From 5000060b04bed23cbbd88ba43ed546220c4b7c69 Mon Sep 17 00:00:00 2001
From: whiteshark0 <whiteshark0@b956fd51-792f-4845-bead-9b4dfca2ff2c>
Date: Tue, 2 Nov 2010 12:51:22 +0000
Subject: create experimental songmanagement branch   - nicer abstraction of
 songs   - split songloading from handling songs   - cleanup singscreen

git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/experimental@2706 b956fd51-792f-4845-bead-9b4dfca2ff2c
---
 songmanagement/.gitignore                          |    22 +
 songmanagement/AUTHORS.txt                         |    27 +
 songmanagement/BuildBot.trigger                    |     1 +
 songmanagement/COPYING.txt                         |   339 +
 songmanagement/COPYRIGHT.txt                       |    30 +
 songmanagement/ChangeLog.GERMAN.txt                |   350 +
 songmanagement/ChangeLog.txt                       |   341 +
 songmanagement/DisplayChanges.patch                |    88 +
 songmanagement/Makefile.in                         |   473 +
 songmanagement/README Mac OS X                     |    47 +
 songmanagement/README.txt                          |   146 +
 songmanagement/RELEASEBLOCKERS.txt                 |    11 +
 songmanagement/autogen.sh                          |     3 +
 songmanagement/build/.gitignore                    |     1 +
 songmanagement/build/delphi-win/.gitignore         |     1 +
 songmanagement/configure                           |  7495 +++++++++++
 songmanagement/configure.ac                        |   298 +
 songmanagement/dists/autogen/config.guess          |  1545 +++
 songmanagement/dists/autogen/config.sub            |  1676 +++
 songmanagement/dists/autogen/install-sh            |   519 +
 songmanagement/dists/autogen/m4/ac_define_dir.m4   |    47 +
 .../dists/autogen/m4/ax_extract_version.m4         |    58 +
 songmanagement/dists/autogen/m4/fpc.m4             |   268 +
 songmanagement/dists/autogen/m4/macosx_version.m4  |    31 +
 .../dists/autogen/m4/pkg_config_utils.m4           |   190 +
 .../dists/bamboo/bamboo-build-lin-laz.bat          |     4 +
 .../dists/bamboo/bamboo-build-lin-laz.sh           |     6 +
 .../dists/bamboo/bamboo-build-win-delphi.bat       |     9 +
 .../dists/bamboo/bamboo-build-win-laz.bat          |     3 +
 songmanagement/dists/code.svnprops                 |   Bin 0 -> 86 bytes
 songmanagement/dists/debian/package_debian.sh      |    32 +
 songmanagement/dists/debian/ultrastardx.control    |    17 +
 songmanagement/dists/delphi2005/readme.txt         |     5 +
 .../dists/delphi2005/ultrastardx.bdsproj           |   175 +
 songmanagement/dists/delphi7/readme.txt            |     5 +
 songmanagement/dists/delphi7/ultrastardx.dof       |   144 +
 songmanagement/dists/gentoo/readme.txt             |    36 +
 .../dists/gentoo/ultrastardx-1.1.0.ebuild          |    68 +
 .../dists/gentoo/ultrastardx-9999.ebuild           |    74 +
 songmanagement/dists/lazarus/clean.bat             |     8 +
 songmanagement/dists/lazarus/readme.txt            |    15 +
 songmanagement/dists/lazarus/ultrastardx-unix.lpi  |   598 +
 songmanagement/dists/lazarus/ultrastardx-win.lpi   |   590 +
 songmanagement/dists/ultrastardx.desktop           |    17 +
 .../dists/xcode/English.lproj/InfoPlist.strings    |   Bin 0 -> 532 bytes
 .../xcode/English.lproj/SDLMain.nib/classes.nib    |    19 +
 .../dists/xcode/English.lproj/SDLMain.nib/info.nib |    21 +
 .../xcode/English.lproj/SDLMain.nib/objects.nib    |   Bin 0 -> 2590 bytes
 .../dists/xcode/UltraStarDX.xcodeproj/eddie.mode1  |  1408 ++
 .../xcode/UltraStarDX.xcodeproj/eddie.mode1v3      |  1740 +++
 .../xcode/UltraStarDX.xcodeproj/eddie.pbxuser      |  1414 ++
 .../xcode/UltraStarDX.xcodeproj/project.pbxproj    |  1613 +++
 songmanagement/doc/Makefile                        |    30 +
 songmanagement/game/.gitignore                     |     8 +
 songmanagement/game/LuaCommands.odt                |   Bin 0 -> 17530 bytes
 songmanagement/game/covers/Artist/Artist#.jpg      |   Bin 0 -> 12206 bytes
 songmanagement/game/covers/Artist/Artist0.jpg      |   Bin 0 -> 10692 bytes
 songmanagement/game/covers/Artist/Artist1.jpg      |   Bin 0 -> 12103 bytes
 songmanagement/game/covers/Artist/Artist2.jpg      |   Bin 0 -> 12597 bytes
 songmanagement/game/covers/Artist/Artist3.jpg      |   Bin 0 -> 13948 bytes
 songmanagement/game/covers/Artist/Artist4.jpg      |   Bin 0 -> 13390 bytes
 songmanagement/game/covers/Artist/Artist5.jpg      |   Bin 0 -> 12891 bytes
 songmanagement/game/covers/Artist/Artist6.jpg      |   Bin 0 -> 12560 bytes
 songmanagement/game/covers/Artist/Artist7.jpg      |   Bin 0 -> 10813 bytes
 songmanagement/game/covers/Artist/Artist8.jpg      |   Bin 0 -> 13626 bytes
 songmanagement/game/covers/Artist/Artist9.jpg      |   Bin 0 -> 11805 bytes
 songmanagement/game/covers/Artist/ArtistA.jpg      |   Bin 0 -> 13311 bytes
 songmanagement/game/covers/Artist/ArtistB.jpg      |   Bin 0 -> 10690 bytes
 songmanagement/game/covers/Artist/ArtistC.jpg      |   Bin 0 -> 13408 bytes
 songmanagement/game/covers/Artist/ArtistD.jpg      |   Bin 0 -> 12829 bytes
 songmanagement/game/covers/Artist/ArtistE.jpg      |   Bin 0 -> 11144 bytes
 songmanagement/game/covers/Artist/ArtistF.jpg      |   Bin 0 -> 14309 bytes
 songmanagement/game/covers/Artist/ArtistG.jpg      |   Bin 0 -> 11586 bytes
 songmanagement/game/covers/Artist/ArtistH.jpg      |   Bin 0 -> 13351 bytes
 songmanagement/game/covers/Artist/ArtistI.jpg      |   Bin 0 -> 10345 bytes
 songmanagement/game/covers/Artist/ArtistJ.jpg      |   Bin 0 -> 11508 bytes
 songmanagement/game/covers/Artist/ArtistK.jpg      |   Bin 0 -> 12374 bytes
 songmanagement/game/covers/Artist/ArtistL.jpg      |   Bin 0 -> 13555 bytes
 songmanagement/game/covers/Artist/ArtistM.jpg      |   Bin 0 -> 12943 bytes
 songmanagement/game/covers/Artist/ArtistN.jpg      |   Bin 0 -> 12466 bytes
 songmanagement/game/covers/Artist/ArtistO.jpg      |   Bin 0 -> 12465 bytes
 songmanagement/game/covers/Artist/ArtistP.jpg      |   Bin 0 -> 11064 bytes
 songmanagement/game/covers/Artist/ArtistQ.jpg      |   Bin 0 -> 13638 bytes
 songmanagement/game/covers/Artist/ArtistR.jpg      |   Bin 0 -> 10801 bytes
 songmanagement/game/covers/Artist/ArtistS.jpg      |   Bin 0 -> 12740 bytes
 songmanagement/game/covers/Artist/ArtistT.jpg      |   Bin 0 -> 12166 bytes
 songmanagement/game/covers/Artist/ArtistU.jpg      |   Bin 0 -> 11014 bytes
 songmanagement/game/covers/Artist/ArtistV.jpg      |   Bin 0 -> 14508 bytes
 songmanagement/game/covers/Artist/ArtistW.jpg      |   Bin 0 -> 10644 bytes
 songmanagement/game/covers/Artist/ArtistX.jpg      |   Bin 0 -> 14438 bytes
 songmanagement/game/covers/Artist/ArtistY.jpg      |   Bin 0 -> 11044 bytes
 songmanagement/game/covers/Artist/ArtistZ.jpg      |   Bin 0 -> 12066 bytes
 .../game/covers/Artist/Artist\303\204.jpg"         |   Bin 0 -> 11733 bytes
 .../game/covers/Artist/Artist\303\226.jpg"         |   Bin 0 -> 14522 bytes
 .../game/covers/Artist/Artist\303\234.jpg"         |   Bin 0 -> 10841 bytes
 songmanagement/game/covers/Covers.ini              |   111 +
 songmanagement/game/covers/Creative Commons.jpg    |   Bin 0 -> 36597 bytes
 songmanagement/game/covers/Language/Austrian.jpg   |   Bin 0 -> 91293 bytes
 songmanagement/game/covers/Language/Bavarian.jpg   |   Bin 0 -> 105054 bytes
 songmanagement/game/covers/Language/Chinese.jpg    |   Bin 0 -> 71812 bytes
 songmanagement/game/covers/Language/Danish.jpg     |   Bin 0 -> 59405 bytes
 songmanagement/game/covers/Language/Dutch.jpg      |   Bin 0 -> 60785 bytes
 songmanagement/game/covers/Language/English.jpg    |   Bin 0 -> 167526 bytes
 songmanagement/game/covers/Language/Finish.jpg     |   Bin 0 -> 57942 bytes
 songmanagement/game/covers/Language/French.jpg     |   Bin 0 -> 87219 bytes
 songmanagement/game/covers/Language/German.jpg     |   Bin 0 -> 87831 bytes
 songmanagement/game/covers/Language/Greek.jpg      |   Bin 0 -> 72164 bytes
 songmanagement/game/covers/Language/Italian.jpg    |   Bin 0 -> 87474 bytes
 songmanagement/game/covers/Language/Japanese.jpg   |   Bin 0 -> 92385 bytes
 .../game/covers/Language/K\303\266lsch.jpg"        |   Bin 0 -> 61604 bytes
 songmanagement/game/covers/Language/Norwegian.jpg  |   Bin 0 -> 70092 bytes
 songmanagement/game/covers/Language/Peruvian.jpg   |   Bin 0 -> 82161 bytes
 songmanagement/game/covers/Language/Polish.jpg     |   Bin 0 -> 85870 bytes
 songmanagement/game/covers/Language/Romanian.jpg   |   Bin 0 -> 95414 bytes
 songmanagement/game/covers/Language/Russian.jpg    |   Bin 0 -> 90154 bytes
 songmanagement/game/covers/Language/Slovenian.jpg  |   Bin 0 -> 90154 bytes
 songmanagement/game/covers/Language/Spanish.jpg    |   Bin 0 -> 158036 bytes
 songmanagement/game/covers/Language/Swedish.jpg    |   Bin 0 -> 63411 bytes
 songmanagement/game/covers/Language/Thumbs.db      |   Bin 0 -> 8704 bytes
 songmanagement/game/covers/Language/Turkish.jpg    |   Bin 0 -> 69735 bytes
 songmanagement/game/covers/NoCover.jpg             |   Bin 0 -> 33592 bytes
 songmanagement/game/covers/Title/Title#.jpg        |   Bin 0 -> 12194 bytes
 songmanagement/game/covers/Title/Title0.jpg        |   Bin 0 -> 10443 bytes
 songmanagement/game/covers/Title/Title1.jpg        |   Bin 0 -> 11755 bytes
 songmanagement/game/covers/Title/Title2.jpg        |   Bin 0 -> 12472 bytes
 songmanagement/game/covers/Title/Title3.jpg        |   Bin 0 -> 13618 bytes
 songmanagement/game/covers/Title/Title4.jpg        |   Bin 0 -> 13278 bytes
 songmanagement/game/covers/Title/Title5.jpg        |   Bin 0 -> 12906 bytes
 songmanagement/game/covers/Title/Title6.jpg        |   Bin 0 -> 12492 bytes
 songmanagement/game/covers/Title/Title7.jpg        |   Bin 0 -> 10578 bytes
 songmanagement/game/covers/Title/Title8.jpg        |   Bin 0 -> 13362 bytes
 songmanagement/game/covers/Title/Title9.jpg        |   Bin 0 -> 11656 bytes
 songmanagement/game/covers/Title/TitleD.jpg        |   Bin 0 -> 12608 bytes
 songmanagement/game/covers/Title/TitleE.jpg        |   Bin 0 -> 10901 bytes
 songmanagement/game/covers/Title/TitleF.jpg        |   Bin 0 -> 14225 bytes
 songmanagement/game/covers/Title/TitleG.jpg        |   Bin 0 -> 11536 bytes
 songmanagement/game/covers/Title/TitleH.jpg        |   Bin 0 -> 13333 bytes
 songmanagement/game/covers/Title/TitleI.jpg        |   Bin 0 -> 10073 bytes
 songmanagement/game/covers/Title/TitleJ.jpg        |   Bin 0 -> 11417 bytes
 songmanagement/game/covers/Title/TitleK.jpg        |   Bin 0 -> 12313 bytes
 songmanagement/game/covers/Title/TitleL.jpg        |   Bin 0 -> 13184 bytes
 songmanagement/game/covers/Title/TitleM.jpg        |   Bin 0 -> 12971 bytes
 songmanagement/game/covers/Title/TitleN.jpg        |   Bin 0 -> 12470 bytes
 songmanagement/game/covers/Title/TitleO.jpg        |   Bin 0 -> 12469 bytes
 songmanagement/game/covers/Title/TitleP.jpg        |   Bin 0 -> 10894 bytes
 songmanagement/game/covers/Title/TitleQ.jpg        |   Bin 0 -> 13522 bytes
 songmanagement/game/covers/Title/TitleR.jpg        |   Bin 0 -> 10564 bytes
 songmanagement/game/covers/Title/TitleS.jpg        |   Bin 0 -> 12424 bytes
 songmanagement/game/covers/Title/TitleT.jpg        |   Bin 0 -> 11842 bytes
 songmanagement/game/covers/Title/TitleU.jpg        |   Bin 0 -> 10812 bytes
 songmanagement/game/covers/Title/TitleV.jpg        |   Bin 0 -> 14451 bytes
 songmanagement/game/covers/Title/TitleW.jpg        |   Bin 0 -> 10624 bytes
 songmanagement/game/covers/Title/TitleX.jpg        |   Bin 0 -> 14480 bytes
 songmanagement/game/covers/Title/TitleY.jpg        |   Bin 0 -> 10884 bytes
 songmanagement/game/covers/Title/TitleZ.jpg        |   Bin 0 -> 12062 bytes
 songmanagement/game/covers/Title/Titlea.jpg        |   Bin 0 -> 13109 bytes
 songmanagement/game/covers/Title/Titleb.jpg        |   Bin 0 -> 10398 bytes
 songmanagement/game/covers/Title/Titlec.jpg        |   Bin 0 -> 13268 bytes
 .../game/covers/Title/Title\303\204.jpg"           |   Bin 0 -> 11653 bytes
 .../game/covers/Title/Title\303\226.jpg"           |   Bin 0 -> 14573 bytes
 .../game/covers/Title/Title\303\234.jpg"           |   Bin 0 -> 10839 bytes
 songmanagement/game/fonts/DejaVu/AUTHORS           |    44 +
 .../game/fonts/DejaVu/DejaVuSans-Bold.ttf          |   Bin 0 -> 561576 bytes
 songmanagement/game/fonts/DejaVu/DejaVuSans.ttf    |   Bin 0 -> 611552 bytes
 songmanagement/game/fonts/DejaVu/LICENSE           |    99 +
 songmanagement/game/fonts/DejaVu/README            |    59 +
 songmanagement/game/fonts/FreeSans/AUTHORS         |   191 +
 songmanagement/game/fonts/FreeSans/COPYING         |   341 +
 songmanagement/game/fonts/FreeSans/CREDITS         |   506 +
 songmanagement/game/fonts/FreeSans/FreeSans.ttf    |   Bin 0 -> 770828 bytes
 .../game/fonts/FreeSans/FreeSansBold.ttf           |   Bin 0 -> 250228 bytes
 songmanagement/game/fonts/FreeSans/README          |   108 +
 songmanagement/game/fonts/fonts.ini                |    56 +
 songmanagement/game/fonts/wqy-microhei/AUTHORS.txt | 12774 +++++++++++++++++++
 .../game/fonts/wqy-microhei/LICENSE_Apache2.txt    |   122 +
 .../game/fonts/wqy-microhei/LICENSE_GPLv3.txt      |   674 +
 songmanagement/game/fonts/wqy-microhei/README.txt  |   378 +
 .../game/fonts/wqy-microhei/wqy-microhei.ttc       |   Bin 0 -> 5177387 bytes
 songmanagement/game/languages/Catalan.ini          |   443 +
 songmanagement/game/languages/Chinese.ini          |   443 +
 songmanagement/game/languages/Croatian.ini         |   446 +
 songmanagement/game/languages/Czech.ini            |   442 +
 songmanagement/game/languages/Danish.ini           |   443 +
 songmanagement/game/languages/Dutch.ini            |   443 +
 songmanagement/game/languages/English.ini          |   442 +
 songmanagement/game/languages/Euskara.ini          |   441 +
 songmanagement/game/languages/Finnish.ini          |   445 +
 songmanagement/game/languages/French.ini           |   441 +
 songmanagement/game/languages/German.ini           |   442 +
 songmanagement/game/languages/Greek.ini            |   443 +
 songmanagement/game/languages/Hungarian.ini        |   441 +
 songmanagement/game/languages/Icelandic.ini        |   443 +
 songmanagement/game/languages/Italian.ini          |   443 +
 songmanagement/game/languages/Japanese.ini         |   443 +
 songmanagement/game/languages/Language.new         |   441 +
 songmanagement/game/languages/Luxembourgish.ini    |   442 +
 songmanagement/game/languages/Norwegian.ini        |   444 +
 songmanagement/game/languages/Polish.ini           |   441 +
 songmanagement/game/languages/Portuguese.ini       |   441 +
 songmanagement/game/languages/Russian.ini          |   442 +
 songmanagement/game/languages/Serbian.ini          |   443 +
 songmanagement/game/languages/Slovak.ini           |   443 +
 songmanagement/game/languages/Slovenian.ini        |   442 +
 songmanagement/game/languages/Spanish.ini          |   443 +
 songmanagement/game/languages/Swedish.ini          |   442 +
 songmanagement/game/languages/convert.sh           |    43 +
 songmanagement/game/languages/readme.txt           |    99 +
 songmanagement/game/languages/update.py            |   154 +
 songmanagement/game/plugins/5000points.usdx        |    74 +
 songmanagement/game/plugins/PluginDescription.odt  |   Bin 0 -> 18417 bytes
 songmanagement/game/plugins/blind.usdx             |    53 +
 songmanagement/game/plugins/duel.usdx              |    41 +
 songmanagement/game/plugins/holdtheline.usdx       |   219 +
 songmanagement/game/plugins/hooks.txt              |     5 +
 songmanagement/game/plugins/teamduel.usdx          |   258 +
 .../game/resources/credits/credits_v5_bg.png       |   Bin 0 -> 264166 bytes
 .../game/resources/credits/credits_v5_overlay.png  |   Bin 0 -> 380739 bytes
 .../game/resources/credits/intro-l-01.png          |   Bin 0 -> 31481 bytes
 .../game/resources/credits/intro-l-02.png          |   Bin 0 -> 27728 bytes
 .../game/resources/credits/intro-l-03.png          |   Bin 0 -> 222080 bytes
 .../game/resources/credits/intro-l-04.png          |   Bin 0 -> 102638 bytes
 .../game/resources/credits/intro-l-05.png          |   Bin 0 -> 26961 bytes
 .../game/resources/credits/intro-l-06.png          |   Bin 0 -> 77860 bytes
 .../game/resources/credits/intro-l-07.png          |   Bin 0 -> 31873 bytes
 .../game/resources/credits/intro-l-08.png          |   Bin 0 -> 13041 bytes
 .../game/resources/credits/intro-l-09.png          |   Bin 0 -> 7553 bytes
 .../game/resources/credits/names_alexanders.png    |   Bin 0 -> 22920 bytes
 .../game/resources/credits/names_blindguard.png    |   Bin 0 -> 23478 bytes
 .../game/resources/credits/names_blindy.png        |   Bin 0 -> 27516 bytes
 .../game/resources/credits/names_brunzel.png       |   Bin 0 -> 28522 bytes
 .../game/resources/credits/names_canni.png         |   Bin 0 -> 27779 bytes
 .../game/resources/credits/names_commandio.png     |   Bin 0 -> 20290 bytes
 .../game/resources/credits/names_hennymcc.png      |   Bin 0 -> 37554 bytes
 .../game/resources/credits/names_jaybinks.png      |   Bin 0 -> 28831 bytes
 .../game/resources/credits/names_krueger.png       |   Bin 0 -> 23282 bytes
 .../game/resources/credits/names_lazyjoker.png     |   Bin 0 -> 22641 bytes
 .../game/resources/credits/names_mezzox.png        |   Bin 0 -> 27091 bytes
 .../game/resources/credits/names_mischi.png        |   Bin 0 -> 21892 bytes
 .../game/resources/credits/names_mog.png           |   Bin 0 -> 22464 bytes
 .../game/resources/credits/names_mota.png          |   Bin 0 -> 22027 bytes
 .../game/resources/credits/names_skillmaster.png   |   Bin 0 -> 21424 bytes
 .../game/resources/credits/names_whiteshark.png    |   Bin 0 -> 35865 bytes
 songmanagement/game/resources/credits/outro-bg.png |   Bin 0 -> 595653 bytes
 .../game/resources/credits/outro-esc.png           |   Bin 0 -> 75369 bytes
 .../game/resources/credits/outro-exit-dark.png     |   Bin 0 -> 68263 bytes
 songmanagement/game/resources/graphics/NoCover.jpg |   Bin 0 -> 33592 bytes
 .../game/resources/icons/ultrastardx-icon.png      |   Bin 0 -> 666 bytes
 songmanagement/game/sounds/Common back.mp3         |   Bin 0 -> 23431 bytes
 songmanagement/game/sounds/Common start.mp3        |   Bin 0 -> 23431 bytes
 .../game/sounds/background track license.txt       |    10 +
 songmanagement/game/sounds/background track.mp3    |   Bin 0 -> 4486887 bytes
 songmanagement/game/sounds/credits-outro-tune.mp3  |   Bin 0 -> 156212 bytes
 songmanagement/game/sounds/dismissed.mp3           |   Bin 0 -> 5433 bytes
 songmanagement/game/sounds/menu swoosh.mp3         |   Bin 0 -> 5246 bytes
 songmanagement/game/sounds/option change col.mp3   |   Bin 0 -> 3734 bytes
 songmanagement/game/sounds/rimshot022b.mp3         |   Bin 0 -> 2090 bytes
 .../game/sounds/select music change music 50.mp3   |   Bin 0 -> 17580 bytes
 .../game/sounds/select music change music.mp3      |   Bin 0 -> 8565 bytes
 songmanagement/game/sounds/wome-credits-tune.mp3   |   Bin 0 -> 1682311 bytes
 songmanagement/game/themes/Candy.ini               |  7139 +++++++++++
 songmanagement/game/themes/Candy/Clouds static.ini |   145 +
 songmanagement/game/themes/Candy/Clouds.ini        |   145 +
 songmanagement/game/themes/Candy/Party1BG.png      |   Bin 0 -> 9136 bytes
 songmanagement/game/themes/Candy/Party1Bar.png     |   Bin 0 -> 2856 bytes
 .../game/themes/Candy/SongMenuButton.png           |   Bin 0 -> 2866 bytes
 songmanagement/game/themes/Candy/StatsBox.png      |   Bin 0 -> 19134 bytes
 songmanagement/game/themes/Candy/Transparent.png   |   Bin 0 -> 2792 bytes
 .../game/themes/Candy/[bg-load]clouds.jpg          |   Bin 0 -> 33891 bytes
 .../game/themes/Candy/[bg-main]clouds.AVI          |   Bin 0 -> 584826 bytes
 .../game/themes/Candy/[bg-main]clouds.jpg          |   Bin 0 -> 111100 bytes
 .../game/themes/Candy/[bg-main]options.AVI         |   Bin 0 -> 154424 bytes
 .../game/themes/Candy/[bg-main]options.jpg         |   Bin 0 -> 103776 bytes
 songmanagement/game/themes/Candy/[button]13.png    |   Bin 0 -> 3248 bytes
 songmanagement/game/themes/Candy/[button]alt.png   |   Bin 0 -> 3200 bytes
 songmanagement/game/themes/Candy/[button]az.png    |   Bin 0 -> 3293 bytes
 songmanagement/game/themes/Candy/[button]enter.png |   Bin 0 -> 3247 bytes
 songmanagement/game/themes/Candy/[button]esc.png   |   Bin 0 -> 3283 bytes
 songmanagement/game/themes/Candy/[button]j.png     |   Bin 0 -> 3036 bytes
 songmanagement/game/themes/Candy/[button]m.png     |   Bin 0 -> 3152 bytes
 songmanagement/game/themes/Candy/[button]main.png  |   Bin 0 -> 7401 bytes
 songmanagement/game/themes/Candy/[button]navi.png  |   Bin 0 -> 3523 bytes
 songmanagement/game/themes/Candy/[button]p.png     |   Bin 0 -> 3119 bytes
 .../game/themes/Candy/[effect]goldenNoteStar.png   |   Bin 0 -> 24444 bytes
 .../game/themes/Candy/[effect]perfectNoteStar.png  |   Bin 0 -> 40783 bytes
 songmanagement/game/themes/Candy/[icon]logo.png    |   Bin 0 -> 9724 bytes
 songmanagement/game/themes/Candy/[icon]options.png |   Bin 0 -> 4836 bytes
 .../game/themes/Candy/[icon]song_duett.png         |   Bin 0 -> 3097 bytes
 .../game/themes/Candy/[icon]song_video.png         |   Bin 0 -> 2811 bytes
 .../game/themes/Candy/[interface]cursor.png        |   Bin 0 -> 5635 bytes
 .../themes/Candy/[interface]cursor_pressed.png     |   Bin 0 -> 4086 bytes
 .../themes/Candy/[interface]select_arrow_left.png  |   Bin 0 -> 485 bytes
 .../themes/Candy/[interface]select_arrow_right.png |   Bin 0 -> 485 bytes
 .../themes/Candy/[interface]selectbg_search.png    |   Bin 0 -> 477 bytes
 songmanagement/game/themes/Candy/[main]button.png  |   Bin 0 -> 293 bytes
 songmanagement/game/themes/Candy/[main]mainBar.png |   Bin 0 -> 3569 bytes
 .../game/themes/Candy/[main]partymenubg.png        |   Bin 0 -> 15143 bytes
 .../game/themes/Candy/[main]searchbg.png           |   Bin 0 -> 15392 bytes
 .../game/themes/Candy/[main]selectbg.png           |   Bin 0 -> 2958 bytes
 .../game/themes/Candy/[main]songCover.jpg          |   Bin 0 -> 26978 bytes
 .../game/themes/Candy/[main]songSelection1.png     |   Bin 0 -> 12671 bytes
 .../game/themes/Candy/[main]songSelection2.png     |   Bin 0 -> 14979 bytes
 songmanagement/game/themes/Candy/[party]Joker.png  |   Bin 0 -> 4920 bytes
 .../game/themes/Candy/[party]playerButton.png      |   Bin 0 -> 3572 bytes
 .../game/themes/Candy/[party]playerTeamButton.png  |   Bin 0 -> 3348 bytes
 .../game/themes/Candy/[party]playerselectbg.png    |   Bin 0 -> 2877 bytes
 .../game/themes/Candy/[party]pointer.png           |   Bin 0 -> 362 bytes
 .../game/themes/Candy/[party]roundBG1.png          |   Bin 0 -> 3040 bytes
 .../game/themes/Candy/[party]roundBG2.png          |   Bin 0 -> 2961 bytes
 .../game/themes/Candy/[party]roundBG3.png          |   Bin 0 -> 3085 bytes
 .../game/themes/Candy/[party]roundBG4.png          |   Bin 0 -> 3045 bytes
 .../game/themes/Candy/[party]roundTeamButton.png   |   Bin 0 -> 3448 bytes
 .../game/themes/Candy/[party]winDecoration.png     |   Bin 0 -> 8147 bytes
 songmanagement/game/themes/Candy/[score]Line.png   |   Bin 0 -> 2825 bytes
 .../game/themes/Candy/[score]bar_box_dark.png      |   Bin 0 -> 496 bytes
 .../game/themes/Candy/[score]bar_box_light.png     |   Bin 0 -> 490 bytes
 .../game/themes/Candy/[score]bar_box_lightest.png  |   Bin 0 -> 484 bytes
 songmanagement/game/themes/Candy/[score]box.png    |   Bin 0 -> 307 bytes
 songmanagement/game/themes/Candy/[score]endcap.png |   Bin 0 -> 4343 bytes
 songmanagement/game/themes/Candy/[score]level.png  |   Bin 0 -> 266 bytes
 .../game/themes/Candy/[score]levelRound.png        |   Bin 0 -> 524 bytes
 .../game/themes/Candy/[score]level_dark.png        |   Bin 0 -> 213 bytes
 .../game/themes/Candy/[score]level_dark_round.png  |   Bin 0 -> 3235 bytes
 .../game/themes/Candy/[score]level_light.png       |   Bin 0 -> 209 bytes
 .../game/themes/Candy/[score]level_light_round.png |   Bin 0 -> 3234 bytes
 .../game/themes/Candy/[score]level_lightest.png    |   Bin 0 -> 209 bytes
 .../themes/Candy/[score]level_lightest_round.png   |   Bin 0 -> 3233 bytes
 songmanagement/game/themes/Candy/[score]pipe.png   |   Bin 0 -> 3504 bytes
 .../game/themes/Candy/[score]rating_0.png          |   Bin 0 -> 9632 bytes
 .../game/themes/Candy/[score]rating_1.png          |   Bin 0 -> 8687 bytes
 .../game/themes/Candy/[score]rating_2.png          |   Bin 0 -> 10860 bytes
 .../game/themes/Candy/[score]rating_3.png          |   Bin 0 -> 11103 bytes
 .../themes/Candy/[sing.player1]lyric_active.png    |   Bin 0 -> 884 bytes
 .../themes/Candy/[sing.player1]lyric_inactive.png  |   Bin 0 -> 862 bytes
 .../themes/Candy/[sing.player2]lyric_active.png    |   Bin 0 -> 1034 bytes
 .../themes/Candy/[sing.player2]lyric_inactive.png  |   Bin 0 -> 948 bytes
 .../themes/Candy/[sing.player3]lyric_active.png    |   Bin 0 -> 988 bytes
 .../themes/Candy/[sing.player3]lyric_inactive.png  |   Bin 0 -> 911 bytes
 .../themes/Candy/[sing.player4]lyric_active.png    |   Bin 0 -> 966 bytes
 .../themes/Candy/[sing.player4]lyric_inactive.png  |   Bin 0 -> 861 bytes
 .../themes/Candy/[sing.player5]lyric_active.png    |   Bin 0 -> 959 bytes
 .../themes/Candy/[sing.player5]lyric_inactive.png  |   Bin 0 -> 877 bytes
 .../themes/Candy/[sing.player6]lyric_active.png    |   Bin 0 -> 960 bytes
 .../themes/Candy/[sing.player6]lyric_inactive.png  |   Bin 0 -> 872 bytes
 .../game/themes/Candy/[sing]lyricsHelpBar.png      |   Bin 0 -> 4609 bytes
 .../game/themes/Candy/[sing]notesBgLeft.png        |   Bin 0 -> 2914 bytes
 .../game/themes/Candy/[sing]notesBgMid.png         |   Bin 0 -> 2837 bytes
 .../game/themes/Candy/[sing]notesBgRight.png       |   Bin 0 -> 2919 bytes
 .../game/themes/Candy/[sing]notesLeft.png          |   Bin 0 -> 3370 bytes
 .../game/themes/Candy/[sing]notesMid.png           |   Bin 0 -> 2883 bytes
 .../game/themes/Candy/[sing]notesPlainLeft.png     |   Bin 0 -> 2976 bytes
 .../game/themes/Candy/[sing]notesPlainMid.png      |   Bin 0 -> 2841 bytes
 .../game/themes/Candy/[sing]notesPlainRight.png    |   Bin 0 -> 2986 bytes
 .../game/themes/Candy/[sing]notesRight.png         |   Bin 0 -> 3316 bytes
 songmanagement/game/themes/Candy/[sing]p.png       |   Bin 0 -> 3796 bytes
 songmanagement/game/themes/Candy/[sing]pause.png   |   Bin 0 -> 164439 bytes
 songmanagement/game/themes/Candy/[sing]scoreBg.png |   Bin 0 -> 6055 bytes
 .../game/themes/Candy/[sing]singBarBack.png        |   Bin 0 -> 203 bytes
 .../game/themes/Candy/[sing]singBarBar.png         |   Bin 0 -> 183 bytes
 .../game/themes/Candy/[sing]singBarFront.png       |   Bin 0 -> 199 bytes
 songmanagement/game/themes/Candy/[sing]textBar.png |   Bin 0 -> 14922 bytes
 songmanagement/game/themes/Candy/[sing]timeBar.jpg |   Bin 0 -> 317 bytes
 .../game/themes/Candy/[special]bg_fade.png         |   Bin 0 -> 32518 bytes
 songmanagement/game/themes/Classic.ini             |  8012 ++++++++++++
 songmanagement/game/themes/Classic/Star.ini        |   246 +
 .../game/themes/Classic/[bg-load]star.jpg          |   Bin 0 -> 8249 bytes
 .../game/themes/Classic/[bg-main]star.jpg          |   Bin 0 -> 5928 bytes
 songmanagement/game/themes/Classic/[button]13.png  |   Bin 0 -> 935 bytes
 songmanagement/game/themes/Classic/[button]alt.png |   Bin 0 -> 929 bytes
 songmanagement/game/themes/Classic/[button]az.png  |   Bin 0 -> 954 bytes
 songmanagement/game/themes/Classic/[button]e.png   |   Bin 0 -> 1103 bytes
 .../game/themes/Classic/[button]enter.png          |   Bin 0 -> 884 bytes
 songmanagement/game/themes/Classic/[button]esc.png |   Bin 0 -> 972 bytes
 songmanagement/game/themes/Classic/[button]j.png   |   Bin 0 -> 1116 bytes
 songmanagement/game/themes/Classic/[button]m.png   |   Bin 0 -> 1148 bytes
 .../game/themes/Classic/[button]navi.png           |   Bin 0 -> 1294 bytes
 songmanagement/game/themes/Classic/[button]p.png   |   Bin 0 -> 1130 bytes
 .../game/themes/Classic/[effect]goldenNoteStar.png |   Bin 0 -> 24444 bytes
 .../themes/Classic/[effect]perfectNoteStar.png     |   Bin 0 -> 40783 bytes
 .../game/themes/Classic/[helper]buttonFade.png     |   Bin 0 -> 337 bytes
 .../game/themes/Classic/[helper]rectangle.jpg      |   Bin 0 -> 353 bytes
 songmanagement/game/themes/Classic/[icon]Star.png  |   Bin 0 -> 463 bytes
 songmanagement/game/themes/Classic/[icon]cd.png    |   Bin 0 -> 777 bytes
 songmanagement/game/themes/Classic/[icon]error.png |   Bin 0 -> 694 bytes
 songmanagement/game/themes/Classic/[icon]main.png  |   Bin 0 -> 803 bytes
 .../game/themes/Classic/[icon]options.png          |   Bin 0 -> 954 bytes
 songmanagement/game/themes/Classic/[icon]party.png |   Bin 0 -> 694 bytes
 .../game/themes/Classic/[icon]question.png         |   Bin 0 -> 747 bytes
 songmanagement/game/themes/Classic/[icon]score.png |   Bin 0 -> 794 bytes
 .../game/themes/Classic/[icon]song_menu.png        |   Bin 0 -> 724 bytes
 .../game/themes/Classic/[icon]song_search.png      |   Bin 0 -> 960 bytes
 .../game/themes/Classic/[icon]song_video.png       |   Bin 0 -> 864 bytes
 songmanagement/game/themes/Classic/[icon]stats.png |   Bin 0 -> 676 bytes
 songmanagement/game/themes/Classic/[icon]video.png |   Bin 0 -> 3002 bytes
 .../game/themes/Classic/[interface]cursor.png      |   Bin 0 -> 5635 bytes
 .../themes/Classic/[interface]cursor_pressed.png   |   Bin 0 -> 4086 bytes
 .../Classic/[interface]dialog_background.png       |   Bin 0 -> 887 bytes
 .../Classic/[interface]select_arrow_left.png       |   Bin 0 -> 485 bytes
 .../Classic/[interface]select_arrow_right.png      |   Bin 0 -> 485 bytes
 .../themes/Classic/[interface]selectbg_search.png  |   Bin 0 -> 477 bytes
 .../game/themes/Classic/[main]button.png           |   Bin 0 -> 929 bytes
 .../game/themes/Classic/[main]buttonf.jpg          |   Bin 0 -> 17717 bytes
 songmanagement/game/themes/Classic/[main]logo.png  |   Bin 0 -> 7327 bytes
 .../game/themes/Classic/[main]mainBar.png          |   Bin 0 -> 304 bytes
 .../game/themes/Classic/[main]playerNumberBox.png  |   Bin 0 -> 2267 bytes
 .../game/themes/Classic/[main]selectbg.png         |   Bin 0 -> 285 bytes
 .../game/themes/Classic/[main]songCover.jpg        |   Bin 0 -> 15045 bytes
 .../game/themes/Classic/[mainbutton]Exit.png       |   Bin 0 -> 1688 bytes
 .../game/themes/Classic/[mainbutton]Multi.png      |   Bin 0 -> 1678 bytes
 .../game/themes/Classic/[mainbutton]Options.png    |   Bin 0 -> 1778 bytes
 .../game/themes/Classic/[mainbutton]Solo.png       |   Bin 0 -> 1684 bytes
 .../game/themes/Classic/[mainbutton]Stats.png      |   Bin 0 -> 1774 bytes
 .../game/themes/Classic/[menu]PopUpFg.png          |   Bin 0 -> 912 bytes
 .../game/themes/Classic/[menu]jumpToBg.png         |   Bin 0 -> 18921 bytes
 .../game/themes/Classic/[menu]songMenuBg.png       |   Bin 0 -> 18529 bytes
 .../game/themes/Classic/[menu]songMenuSelectBg.png |   Bin 0 -> 4707 bytes
 .../game/themes/Classic/[party]Joker.png           |   Bin 0 -> 1343 bytes
 .../game/themes/Classic/[party]playerButton.png    |   Bin 0 -> 1346 bytes
 .../themes/Classic/[party]playerTeamButton.png     |   Bin 0 -> 529 bytes
 .../game/themes/Classic/[party]playerselectbg.png  |   Bin 0 -> 200 bytes
 .../game/themes/Classic/[party]pointer.png         |   Bin 0 -> 362 bytes
 .../game/themes/Classic/[party]roundBG1.png        |   Bin 0 -> 1073 bytes
 .../game/themes/Classic/[party]roundBG2.png        |   Bin 0 -> 1049 bytes
 .../game/themes/Classic/[party]roundBG3.png        |   Bin 0 -> 1135 bytes
 .../game/themes/Classic/[party]roundBG4.png        |   Bin 0 -> 1229 bytes
 .../game/themes/Classic/[party]roundTeamButton.png |   Bin 0 -> 1207 bytes
 .../game/themes/Classic/[party]scoreBG1.png        |   Bin 0 -> 529 bytes
 .../game/themes/Classic/[party]scoreBG2.png        |   Bin 0 -> 300 bytes
 .../game/themes/Classic/[party]scoreDecoration.png |   Bin 0 -> 9140 bytes
 .../game/themes/Classic/[party]teamPoints.png      |   Bin 0 -> 1195 bytes
 .../game/themes/Classic/[party]winDecoration.png   |   Bin 0 -> 4292 bytes
 .../game/themes/Classic/[party]winTeamButton1.png  |   Bin 0 -> 516 bytes
 .../game/themes/Classic/[party]winTeamButton2.png  |   Bin 0 -> 419 bytes
 .../game/themes/Classic/[party]winTeamButton3.png  |   Bin 0 -> 378 bytes
 songmanagement/game/themes/Classic/[score]Line.png |   Bin 0 -> 2825 bytes
 .../game/themes/Classic/[score]bar_box_dark.png    |   Bin 0 -> 496 bytes
 .../game/themes/Classic/[score]bar_box_light.png   |   Bin 0 -> 490 bytes
 .../themes/Classic/[score]bar_box_lightest.png     |   Bin 0 -> 484 bytes
 songmanagement/game/themes/Classic/[score]box.png  |   Bin 0 -> 307 bytes
 .../game/themes/Classic/[score]endcap.png          |   Bin 0 -> 2275 bytes
 .../game/themes/Classic/[score]glass_box.png       |   Bin 0 -> 3581 bytes
 .../game/themes/Classic/[score]level.png           |   Bin 0 -> 266 bytes
 .../game/themes/Classic/[score]levelRound.png      |   Bin 0 -> 524 bytes
 .../game/themes/Classic/[score]level_dark.png      |   Bin 0 -> 213 bytes
 .../themes/Classic/[score]level_dark_round.png     |   Bin 0 -> 410 bytes
 .../game/themes/Classic/[score]level_light.png     |   Bin 0 -> 209 bytes
 .../themes/Classic/[score]level_light_round.png    |   Bin 0 -> 445 bytes
 .../game/themes/Classic/[score]level_lightest.png  |   Bin 0 -> 209 bytes
 .../themes/Classic/[score]level_lightest_round.png |   Bin 0 -> 467 bytes
 .../game/themes/Classic/[score]rating_0.png        |   Bin 0 -> 7412 bytes
 .../game/themes/Classic/[score]rating_1.png        |   Bin 0 -> 8206 bytes
 .../game/themes/Classic/[score]rating_2.png        |   Bin 0 -> 9681 bytes
 .../game/themes/Classic/[score]rating_3.png        |   Bin 0 -> 8363 bytes
 .../game/themes/Classic/[score]rating_4.png        |   Bin 0 -> 8231 bytes
 .../game/themes/Classic/[score]rating_5.png        |   Bin 0 -> 8720 bytes
 .../game/themes/Classic/[score]rating_6.png        |   Bin 0 -> 8162 bytes
 .../game/themes/Classic/[score]rating_7.png        |   Bin 0 -> 9573 bytes
 .../themes/Classic/[sing.player1]lyric_active.png  |   Bin 0 -> 884 bytes
 .../Classic/[sing.player1]lyric_inactive.png       |   Bin 0 -> 862 bytes
 .../themes/Classic/[sing.player2]lyric_active.png  |   Bin 0 -> 1034 bytes
 .../Classic/[sing.player2]lyric_inactive.png       |   Bin 0 -> 948 bytes
 .../themes/Classic/[sing.player3]lyric_active.png  |   Bin 0 -> 988 bytes
 .../Classic/[sing.player3]lyric_inactive.png       |   Bin 0 -> 911 bytes
 .../themes/Classic/[sing.player4]lyric_active.png  |   Bin 0 -> 966 bytes
 .../Classic/[sing.player4]lyric_inactive.png       |   Bin 0 -> 861 bytes
 .../themes/Classic/[sing.player5]lyric_active.png  |   Bin 0 -> 959 bytes
 .../Classic/[sing.player5]lyric_inactive.png       |   Bin 0 -> 877 bytes
 .../themes/Classic/[sing.player6]lyric_active.png  |   Bin 0 -> 960 bytes
 .../Classic/[sing.player6]lyric_inactive.png       |   Bin 0 -> 872 bytes
 .../game/themes/Classic/[sing]LyricsBall.png       |   Bin 0 -> 360 bytes
 .../game/themes/Classic/[sing]lineBonusPopUp.png   |   Bin 0 -> 237 bytes
 .../game/themes/Classic/[sing]lyricsHelpBar.png    |   Bin 0 -> 340 bytes
 .../game/themes/Classic/[sing]notesBgLeft.png      |   Bin 0 -> 292 bytes
 .../game/themes/Classic/[sing]notesBgMid.png       |   Bin 0 -> 144 bytes
 .../game/themes/Classic/[sing]notesBgRight.png     |   Bin 0 -> 280 bytes
 .../game/themes/Classic/[sing]notesLeft.png        |   Bin 0 -> 671 bytes
 .../game/themes/Classic/[sing]notesMid.png         |   Bin 0 -> 236 bytes
 .../game/themes/Classic/[sing]notesPlainLeft.png   |   Bin 0 -> 681 bytes
 .../game/themes/Classic/[sing]notesPlainMid.png    |   Bin 0 -> 151 bytes
 .../game/themes/Classic/[sing]notesPlainRight.png  |   Bin 0 -> 690 bytes
 .../game/themes/Classic/[sing]notesRight.png       |   Bin 0 -> 728 bytes
 songmanagement/game/themes/Classic/[sing]p.png     |   Bin 0 -> 192 bytes
 songmanagement/game/themes/Classic/[sing]pause.png |   Bin 0 -> 13261 bytes
 .../game/themes/Classic/[sing]scoreBg.jpg          |   Bin 0 -> 680 bytes
 .../game/themes/Classic/[sing]scoreBg.png          |   Bin 0 -> 289 bytes
 .../game/themes/Classic/[sing]singBarBack.png      |   Bin 0 -> 203 bytes
 .../game/themes/Classic/[sing]singBarBar.jpg       |   Bin 0 -> 371 bytes
 .../game/themes/Classic/[sing]singBarBar.png       |   Bin 0 -> 183 bytes
 .../game/themes/Classic/[sing]singBarFront.png     |   Bin 0 -> 199 bytes
 .../game/themes/Classic/[sing]textBar.png          |   Bin 0 -> 9671 bytes
 .../game/themes/Classic/[sing]timeBar.jpg          |   Bin 0 -> 317 bytes
 .../game/themes/Classic/[sing]timeBarBG.png        |   Bin 0 -> 4121 bytes
 .../game/themes/Classic/[song]BGFade.jpg           |   Bin 0 -> 2537 bytes
 .../game/themes/Classic/[song]EqualizerBG.jpg      |   Bin 0 -> 1169 bytes
 .../game/themes/Classic/[song]selection.png        |   Bin 0 -> 1482 bytes
 songmanagement/game/themes/Classic/[songs]bg.png   |   Bin 0 -> 610 bytes
 .../game/themes/Classic/[special]bar1.png          |   Bin 0 -> 381 bytes
 .../game/themes/Classic/[special]bar2.png          |   Bin 0 -> 410 bytes
 .../game/themes/Classic/[special]bg_fade.png       |   Bin 0 -> 32518 bytes
 .../game/themes/Classic/[stat]detailBG1.png        |   Bin 0 -> 282 bytes
 .../game/themes/Classic/[stat]mainBG1.png          |   Bin 0 -> 269 bytes
 .../game/themes/Classic/[stat]mainBG2.png          |   Bin 0 -> 1093 bytes
 .../game/themes/Classic/[stat]mainBG3.png          |   Bin 0 -> 251 bytes
 songmanagement/game/themes/Deluxe.ini              |  8681 +++++++++++++
 songmanagement/game/themes/Deluxe/Blue.ini         |   235 +
 songmanagement/game/themes/Deluxe/Fall.ini         |   235 +
 songmanagement/game/themes/Deluxe/Ocean.ini        |   235 +
 songmanagement/game/themes/Deluxe/Ribbon.ini       |   234 +
 songmanagement/game/themes/Deluxe/Summer.ini       |   235 +
 songmanagement/game/themes/Deluxe/Winter.ini       |   235 +
 .../game/themes/Deluxe/[bg-load]blue.jpg           |   Bin 0 -> 106213 bytes
 .../game/themes/Deluxe/[bg-load]fall.jpg           |   Bin 0 -> 471938 bytes
 .../game/themes/Deluxe/[bg-load]summer.jpg         |   Bin 0 -> 381304 bytes
 .../game/themes/Deluxe/[bg-load]winter.jpg         |   Bin 0 -> 243663 bytes
 .../game/themes/Deluxe/[bg-main]blue.jpg           |   Bin 0 -> 64218 bytes
 .../game/themes/Deluxe/[bg-main]fall.jpg           |   Bin 0 -> 392979 bytes
 .../game/themes/Deluxe/[bg-main]summer.jpg         |   Bin 0 -> 447517 bytes
 .../game/themes/Deluxe/[bg-main]winter.jpg         |   Bin 0 -> 268024 bytes
 .../game/themes/Deluxe/[bg-video]_ocean.avi        |   Bin 0 -> 599350 bytes
 .../game/themes/Deluxe/[bg-video]ribbon.mov        |   Bin 0 -> 2118942 bytes
 songmanagement/game/themes/Deluxe/[button]13.png   |   Bin 0 -> 1546 bytes
 songmanagement/game/themes/Deluxe/[button]alt.png  |   Bin 0 -> 1513 bytes
 songmanagement/game/themes/Deluxe/[button]az.png   |   Bin 0 -> 1496 bytes
 .../game/themes/Deluxe/[button]enter.png           |   Bin 0 -> 2176 bytes
 songmanagement/game/themes/Deluxe/[button]esc.png  |   Bin 0 -> 1508 bytes
 songmanagement/game/themes/Deluxe/[button]j.png    |   Bin 0 -> 1225 bytes
 songmanagement/game/themes/Deluxe/[button]m.png    |   Bin 0 -> 1256 bytes
 songmanagement/game/themes/Deluxe/[button]navi.png |   Bin 0 -> 4072 bytes
 songmanagement/game/themes/Deluxe/[button]p.png    |   Bin 0 -> 1231 bytes
 .../game/themes/Deluxe/[effect]goldenNoteStar.png  |   Bin 0 -> 24444 bytes
 .../game/themes/Deluxe/[effect]perfectNoteStar.png |   Bin 0 -> 40783 bytes
 .../game/themes/Deluxe/[helper]buttonFade.png      |   Bin 0 -> 337 bytes
 .../game/themes/Deluxe/[helper]rectangle.jpg       |   Bin 0 -> 7193 bytes
 songmanagement/game/themes/Deluxe/[icon]cd.png     |   Bin 0 -> 777 bytes
 songmanagement/game/themes/Deluxe/[icon]error.png  |   Bin 0 -> 694 bytes
 songmanagement/game/themes/Deluxe/[icon]main.png   |   Bin 0 -> 803 bytes
 .../game/themes/Deluxe/[icon]options.png           |   Bin 0 -> 954 bytes
 songmanagement/game/themes/Deluxe/[icon]party.png  |   Bin 0 -> 694 bytes
 .../game/themes/Deluxe/[icon]question.png          |   Bin 0 -> 747 bytes
 songmanagement/game/themes/Deluxe/[icon]score.png  |   Bin 0 -> 794 bytes
 .../game/themes/Deluxe/[icon]song_menu.png         |   Bin 0 -> 724 bytes
 .../game/themes/Deluxe/[icon]song_search.png       |   Bin 0 -> 960 bytes
 .../game/themes/Deluxe/[icon]song_video.png        |   Bin 0 -> 629 bytes
 songmanagement/game/themes/Deluxe/[icon]stats.png  |   Bin 0 -> 676 bytes
 songmanagement/game/themes/Deluxe/[icon]video.png  |   Bin 0 -> 3002 bytes
 .../game/themes/Deluxe/[interface]cursor.png       |   Bin 0 -> 5635 bytes
 .../themes/Deluxe/[interface]cursor_pressed.png    |   Bin 0 -> 4086 bytes
 .../themes/Deluxe/[interface]dialog_background.png |   Bin 0 -> 4063 bytes
 .../themes/Deluxe/[interface]select_arrow_left.png |   Bin 0 -> 485 bytes
 .../Deluxe/[interface]select_arrow_right.png       |   Bin 0 -> 485 bytes
 .../themes/Deluxe/[interface]selectbg_search.png   |   Bin 0 -> 477 bytes
 songmanagement/game/themes/Deluxe/[main]button.png |   Bin 0 -> 293 bytes
 .../game/themes/Deluxe/[main]buttonf.jpg           |   Bin 0 -> 17717 bytes
 .../game/themes/Deluxe/[main]mainBar.png           |   Bin 0 -> 184 bytes
 .../game/themes/Deluxe/[main]playerNumberBox.png   |   Bin 0 -> 2267 bytes
 .../game/themes/Deluxe/[main]selectbg.png          |   Bin 0 -> 2969 bytes
 .../game/themes/Deluxe/[main]songCover.jpg         |   Bin 0 -> 15045 bytes
 .../game/themes/Deluxe/[main]songSelection1.png    |   Bin 0 -> 1097 bytes
 .../game/themes/Deluxe/[main]songSelection2.png    |   Bin 0 -> 523 bytes
 .../game/themes/Deluxe/[menu]PopUpFg.png           |   Bin 0 -> 912 bytes
 .../game/themes/Deluxe/[menu]jumpToBg.png          |   Bin 0 -> 18921 bytes
 .../game/themes/Deluxe/[menu]songMenuBg.png        |   Bin 0 -> 18529 bytes
 .../game/themes/Deluxe/[menu]songMenuSelectBg.png  |   Bin 0 -> 4707 bytes
 songmanagement/game/themes/Deluxe/[party]Joker.png |   Bin 0 -> 8302 bytes
 .../game/themes/Deluxe/[party]playerButton.png     |   Bin 0 -> 893 bytes
 .../game/themes/Deluxe/[party]playerTeamButton.png |   Bin 0 -> 665 bytes
 .../game/themes/Deluxe/[party]playerselectbg.png   |   Bin 0 -> 2910 bytes
 .../game/themes/Deluxe/[party]pointer.png          |   Bin 0 -> 362 bytes
 .../game/themes/Deluxe/[party]roundBG1.png         |   Bin 0 -> 358 bytes
 .../game/themes/Deluxe/[party]roundBG2.png         |   Bin 0 -> 279 bytes
 .../game/themes/Deluxe/[party]roundBG3.png         |   Bin 0 -> 407 bytes
 .../game/themes/Deluxe/[party]roundBG4.png         |   Bin 0 -> 365 bytes
 .../game/themes/Deluxe/[party]roundTeamButton.png  |   Bin 0 -> 762 bytes
 .../game/themes/Deluxe/[party]scoreBG1.png         |   Bin 0 -> 642 bytes
 .../game/themes/Deluxe/[party]scoreBG2.png         |   Bin 0 -> 314 bytes
 .../game/themes/Deluxe/[party]scoreDecoration.png  |   Bin 0 -> 9140 bytes
 .../game/themes/Deluxe/[party]teamPoints.png       |   Bin 0 -> 1194 bytes
 .../game/themes/Deluxe/[party]winDecoration.png    |   Bin 0 -> 4292 bytes
 .../game/themes/Deluxe/[party]winTeamButton1.png   |   Bin 0 -> 1240 bytes
 .../game/themes/Deluxe/[party]winTeamButton2.png   |   Bin 0 -> 891 bytes
 .../game/themes/Deluxe/[party]winTeamButton3.png   |   Bin 0 -> 838 bytes
 songmanagement/game/themes/Deluxe/[score]Line.png  |   Bin 0 -> 2825 bytes
 .../game/themes/Deluxe/[score]bar_box_dark.png     |   Bin 0 -> 496 bytes
 .../game/themes/Deluxe/[score]bar_box_light.png    |   Bin 0 -> 490 bytes
 .../game/themes/Deluxe/[score]bar_box_lightest.png |   Bin 0 -> 484 bytes
 songmanagement/game/themes/Deluxe/[score]box.png   |   Bin 0 -> 307 bytes
 .../game/themes/Deluxe/[score]endcap.png           |   Bin 0 -> 2275 bytes
 .../game/themes/Deluxe/[score]glass_box.png        |   Bin 0 -> 3581 bytes
 songmanagement/game/themes/Deluxe/[score]level.png |   Bin 0 -> 266 bytes
 .../game/themes/Deluxe/[score]levelRound.png       |   Bin 0 -> 524 bytes
 .../game/themes/Deluxe/[score]level_dark.png       |   Bin 0 -> 213 bytes
 .../game/themes/Deluxe/[score]level_dark_round.png |   Bin 0 -> 410 bytes
 .../game/themes/Deluxe/[score]level_light.png      |   Bin 0 -> 209 bytes
 .../themes/Deluxe/[score]level_light_round.png     |   Bin 0 -> 445 bytes
 .../game/themes/Deluxe/[score]level_lightest.png   |   Bin 0 -> 209 bytes
 .../themes/Deluxe/[score]level_lightest_round.png  |   Bin 0 -> 467 bytes
 .../game/themes/Deluxe/[score]rating_0.png         |   Bin 0 -> 7412 bytes
 .../game/themes/Deluxe/[score]rating_1.png         |   Bin 0 -> 8206 bytes
 .../game/themes/Deluxe/[score]rating_2.png         |   Bin 0 -> 9681 bytes
 .../game/themes/Deluxe/[score]rating_3.png         |   Bin 0 -> 8363 bytes
 .../game/themes/Deluxe/[score]rating_4.png         |   Bin 0 -> 8231 bytes
 .../game/themes/Deluxe/[score]rating_5.png         |   Bin 0 -> 8720 bytes
 .../game/themes/Deluxe/[score]rating_6.png         |   Bin 0 -> 8162 bytes
 .../game/themes/Deluxe/[score]rating_7.png         |   Bin 0 -> 9573 bytes
 .../themes/Deluxe/[sing.player1]lyric_active.png   |   Bin 0 -> 884 bytes
 .../themes/Deluxe/[sing.player1]lyric_inactive.png |   Bin 0 -> 862 bytes
 .../themes/Deluxe/[sing.player2]lyric_active.png   |   Bin 0 -> 1034 bytes
 .../themes/Deluxe/[sing.player2]lyric_inactive.png |   Bin 0 -> 948 bytes
 .../themes/Deluxe/[sing.player3]lyric_active.png   |   Bin 0 -> 988 bytes
 .../themes/Deluxe/[sing.player3]lyric_inactive.png |   Bin 0 -> 911 bytes
 .../themes/Deluxe/[sing.player4]lyric_active.png   |   Bin 0 -> 966 bytes
 .../themes/Deluxe/[sing.player4]lyric_inactive.png |   Bin 0 -> 861 bytes
 .../themes/Deluxe/[sing.player5]lyric_active.png   |   Bin 0 -> 959 bytes
 .../themes/Deluxe/[sing.player5]lyric_inactive.png |   Bin 0 -> 877 bytes
 .../themes/Deluxe/[sing.player6]lyric_active.png   |   Bin 0 -> 960 bytes
 .../themes/Deluxe/[sing.player6]lyric_inactive.png |   Bin 0 -> 872 bytes
 .../game/themes/Deluxe/[sing]LyricsBall.png        |   Bin 0 -> 360 bytes
 .../game/themes/Deluxe/[sing]lineBonusPopUp.png    |   Bin 0 -> 1344 bytes
 .../game/themes/Deluxe/[sing]lyricsHelpBar.png     |   Bin 0 -> 340 bytes
 .../game/themes/Deluxe/[sing]notesBgLeft.png       |   Bin 0 -> 292 bytes
 .../game/themes/Deluxe/[sing]notesBgMid.png        |   Bin 0 -> 144 bytes
 .../game/themes/Deluxe/[sing]notesBgRight.png      |   Bin 0 -> 280 bytes
 .../game/themes/Deluxe/[sing]notesLeft.png         |   Bin 0 -> 671 bytes
 .../game/themes/Deluxe/[sing]notesMid.png          |   Bin 0 -> 236 bytes
 .../game/themes/Deluxe/[sing]notesPlainLeft.png    |   Bin 0 -> 681 bytes
 .../game/themes/Deluxe/[sing]notesPlainMid.png     |   Bin 0 -> 151 bytes
 .../game/themes/Deluxe/[sing]notesPlainRight.png   |   Bin 0 -> 690 bytes
 .../game/themes/Deluxe/[sing]notesRight.png        |   Bin 0 -> 728 bytes
 songmanagement/game/themes/Deluxe/[sing]p.png      |   Bin 0 -> 637 bytes
 songmanagement/game/themes/Deluxe/[sing]pause.png  |   Bin 0 -> 13261 bytes
 .../game/themes/Deluxe/[sing]scoreBg.jpg           |   Bin 0 -> 1799 bytes
 .../game/themes/Deluxe/[sing]scoreBg.png           |   Bin 0 -> 1705 bytes
 .../game/themes/Deluxe/[sing]singBarBack.png       |   Bin 0 -> 203 bytes
 .../game/themes/Deluxe/[sing]singBarBar.jpg        |   Bin 0 -> 371 bytes
 .../game/themes/Deluxe/[sing]singBarBar.png        |   Bin 0 -> 183 bytes
 .../game/themes/Deluxe/[sing]singBarFront.png      |   Bin 0 -> 199 bytes
 .../game/themes/Deluxe/[sing]textBar.png           |   Bin 0 -> 9671 bytes
 .../game/themes/Deluxe/[sing]timeBar.jpg           |   Bin 0 -> 317 bytes
 .../game/themes/Deluxe/[sing]timeBarBG.png         |   Bin 0 -> 4121 bytes
 .../game/themes/Deluxe/[special]bar1.png           |   Bin 0 -> 381 bytes
 .../game/themes/Deluxe/[special]bar2.png           |   Bin 0 -> 410 bytes
 .../game/themes/Deluxe/[special]bg_fade.png        |   Bin 0 -> 32518 bytes
 .../game/themes/Deluxe/[stat]detailBG1.png         |   Bin 0 -> 388 bytes
 .../game/themes/Deluxe/[stat]mainBG1.png           |   Bin 0 -> 378 bytes
 .../game/themes/Deluxe/[stat]mainBG2.png           |   Bin 0 -> 12014 bytes
 .../game/themes/Deluxe/[stat]mainBG3.png           |   Bin 0 -> 300 bytes
 songmanagement/game/themes/Temptation.ini          |  8815 +++++++++++++
 .../game/themes/Temptation/Temptation (16-9).ini   |   264 +
 .../game/themes/Temptation/Temptation (4-3).ini    |   264 +
 .../game/themes/Temptation/[Level]buttoneasy.png   |   Bin 0 -> 11113 bytes
 .../game/themes/Temptation/[Level]buttonhard.png   |   Bin 0 -> 10142 bytes
 .../game/themes/Temptation/[Level]buttonmedium.png |   Bin 0 -> 10590 bytes
 .../game/themes/Temptation/[Name]button.png        |   Bin 0 -> 10317 bytes
 .../themes/Temptation/[Options]buttonadvanced.png  |   Bin 0 -> 10642 bytes
 .../game/themes/Temptation/[Options]buttonback.png |   Bin 0 -> 9657 bytes
 .../themes/Temptation/[Options]buttondesign.png    |   Bin 0 -> 8657 bytes
 .../game/themes/Temptation/[Options]buttongame.png |   Bin 0 -> 11076 bytes
 .../themes/Temptation/[Options]buttongraphics.png  |   Bin 0 -> 9358 bytes
 .../themes/Temptation/[Options]buttonlyrics.png    |   Bin 0 -> 8895 bytes
 .../themes/Temptation/[Options]buttonrecord.png    |   Bin 0 -> 11523 bytes
 .../themes/Temptation/[Options]buttonsound.png     |   Bin 0 -> 10159 bytes
 .../game/themes/Temptation/[bg-load]16-9.png       |   Bin 0 -> 1048150 bytes
 .../game/themes/Temptation/[bg-load]4-3.png        |   Bin 0 -> 693732 bytes
 .../game/themes/Temptation/[bg-main]16-9.png       |   Bin 0 -> 968938 bytes
 .../game/themes/Temptation/[bg-main]4-3.png        |   Bin 0 -> 659449 bytes
 .../game/themes/Temptation/[bg-title]16-9.png      |   Bin 0 -> 1042112 bytes
 .../game/themes/Temptation/[bg-title]4-3.png       |   Bin 0 -> 688008 bytes
 .../game/themes/Temptation/[button]13.png          |   Bin 0 -> 1934 bytes
 .../game/themes/Temptation/[button]alt.png         |   Bin 0 -> 2022 bytes
 .../game/themes/Temptation/[button]az.png          |   Bin 0 -> 1940 bytes
 .../game/themes/Temptation/[button]enter.png       |   Bin 0 -> 1793 bytes
 .../game/themes/Temptation/[button]esc.png         |   Bin 0 -> 2038 bytes
 .../game/themes/Temptation/[button]j.png           |   Bin 0 -> 1752 bytes
 .../game/themes/Temptation/[button]m.png           |   Bin 0 -> 1782 bytes
 .../game/themes/Temptation/[button]navi.png        |   Bin 0 -> 2017 bytes
 .../game/themes/Temptation/[button]p.png           |   Bin 0 -> 1748 bytes
 .../game/themes/Temptation/[edit]buttonconvert.png |   Bin 0 -> 9773 bytes
 .../themes/Temptation/[effect]goldenNoteStar.png   |   Bin 0 -> 24444 bytes
 .../themes/Temptation/[effect]perfectNoteStar.png  |   Bin 0 -> 40783 bytes
 .../game/themes/Temptation/[helper]buttonFade.png  |   Bin 0 -> 540 bytes
 .../game/themes/Temptation/[helper]rectangle.png   |   Bin 0 -> 346 bytes
 songmanagement/game/themes/Temptation/[icon]cd.png |   Bin 0 -> 3098 bytes
 .../game/themes/Temptation/[icon]error.png         |   Bin 0 -> 2941 bytes
 .../game/themes/Temptation/[icon]main.png          |   Bin 0 -> 3400 bytes
 .../game/themes/Temptation/[icon]options.png       |   Bin 0 -> 3695 bytes
 .../game/themes/Temptation/[icon]party.png         |   Bin 0 -> 3591 bytes
 .../game/themes/Temptation/[icon]question.png      |   Bin 0 -> 3271 bytes
 .../game/themes/Temptation/[icon]score.png         |   Bin 0 -> 3464 bytes
 .../game/themes/Temptation/[icon]song_menu.png     |   Bin 0 -> 3355 bytes
 .../game/themes/Temptation/[icon]song_search.png   |   Bin 0 -> 3642 bytes
 .../game/themes/Temptation/[icon]song_video.png    |   Bin 0 -> 1945 bytes
 .../game/themes/Temptation/[icon]stats.png         |   Bin 0 -> 3038 bytes
 .../game/themes/Temptation/[icon]video.png         |   Bin 0 -> 1945 bytes
 .../game/themes/Temptation/[interface]cursor.png   |   Bin 0 -> 5635 bytes
 .../Temptation/[interface]cursor_pressed.png       |   Bin 0 -> 4086 bytes
 .../Temptation/[interface]dialog_background.png    |   Bin 0 -> 4063 bytes
 .../Temptation/[interface]select_arrow_left.png    |   Bin 0 -> 485 bytes
 .../Temptation/[interface]select_arrow_right.png   |   Bin 0 -> 485 bytes
 .../Temptation/[interface]selectbg_search.png      |   Bin 0 -> 477 bytes
 .../game/themes/Temptation/[main]button.png        |   Bin 0 -> 619 bytes
 .../game/themes/Temptation/[main]button2.png       |   Bin 0 -> 8571 bytes
 .../game/themes/Temptation/[main]buttonedit.png    |   Bin 0 -> 5445 bytes
 .../game/themes/Temptation/[main]buttonexit.png    |   Bin 0 -> 5052 bytes
 .../game/themes/Temptation/[main]buttonf.jpg       |   Bin 0 -> 17717 bytes
 .../game/themes/Temptation/[main]buttonoption.png  |   Bin 0 -> 5270 bytes
 .../game/themes/Temptation/[main]buttonparty.png   |   Bin 0 -> 5221 bytes
 .../game/themes/Temptation/[main]buttonsolo.png    |   Bin 0 -> 4873 bytes
 .../game/themes/Temptation/[main]buttonstats.png   |   Bin 0 -> 4288 bytes
 .../game/themes/Temptation/[main]mainBar.png       |   Bin 0 -> 805 bytes
 .../themes/Temptation/[main]playerNumberBox.png    |   Bin 0 -> 2267 bytes
 .../game/themes/Temptation/[main]selectbg.png      |   Bin 0 -> 1756 bytes
 .../game/themes/Temptation/[main]songCover.jpg     |   Bin 0 -> 15045 bytes
 .../themes/Temptation/[main]songSelection1.png     |   Bin 0 -> 6405 bytes
 .../themes/Temptation/[main]songSelection2.png     |   Bin 0 -> 549 bytes
 .../game/themes/Temptation/[menu]PopUpFg.png       |   Bin 0 -> 912 bytes
 .../game/themes/Temptation/[menu]jumpToBg.png      |   Bin 0 -> 18921 bytes
 .../game/themes/Temptation/[menu]songMenuBg.png    |   Bin 0 -> 18529 bytes
 .../themes/Temptation/[menu]songMenuSelectBg.png   |   Bin 0 -> 4707 bytes
 .../game/themes/Temptation/[party]Joker.png        |   Bin 0 -> 279 bytes
 .../game/themes/Temptation/[party]playerButton.png |   Bin 0 -> 933 bytes
 .../themes/Temptation/[party]playerTeamButton.png  |   Bin 0 -> 651 bytes
 .../themes/Temptation/[party]playerselectbg.png    |   Bin 0 -> 326 bytes
 .../game/themes/Temptation/[party]pointer.png      |   Bin 0 -> 362 bytes
 .../game/themes/Temptation/[party]roundBG1.png     |   Bin 0 -> 358 bytes
 .../game/themes/Temptation/[party]roundBG2.png     |   Bin 0 -> 287 bytes
 .../game/themes/Temptation/[party]roundBG3.png     |   Bin 0 -> 429 bytes
 .../game/themes/Temptation/[party]roundBG4.png     |   Bin 0 -> 349 bytes
 .../themes/Temptation/[party]roundTeamButton.png   |   Bin 0 -> 747 bytes
 .../game/themes/Temptation/[party]scoreBG1.png     |   Bin 0 -> 587 bytes
 .../game/themes/Temptation/[party]scoreBG2.png     |   Bin 0 -> 308 bytes
 .../themes/Temptation/[party]scoreDecoration.png   |   Bin 0 -> 9140 bytes
 .../game/themes/Temptation/[party]teamPoints.png   |   Bin 0 -> 1194 bytes
 .../themes/Temptation/[party]winDecoration.png     |   Bin 0 -> 4292 bytes
 .../themes/Temptation/[party]winTeamButton1.png    |   Bin 0 -> 1261 bytes
 .../themes/Temptation/[party]winTeamButton2.png    |   Bin 0 -> 922 bytes
 .../themes/Temptation/[party]winTeamButton3.png    |   Bin 0 -> 688 bytes
 .../game/themes/Temptation/[score]Line.png         |   Bin 0 -> 2825 bytes
 .../game/themes/Temptation/[score]bar_box_dark.png |   Bin 0 -> 496 bytes
 .../themes/Temptation/[score]bar_box_light.png     |   Bin 0 -> 490 bytes
 .../themes/Temptation/[score]bar_box_lightest.png  |   Bin 0 -> 484 bytes
 .../game/themes/Temptation/[score]box.png          |   Bin 0 -> 307 bytes
 .../game/themes/Temptation/[score]endcap.png       |   Bin 0 -> 2275 bytes
 .../game/themes/Temptation/[score]glass_box.png    |   Bin 0 -> 3581 bytes
 .../game/themes/Temptation/[score]level.png        |   Bin 0 -> 266 bytes
 .../game/themes/Temptation/[score]levelRound.png   |   Bin 0 -> 524 bytes
 .../game/themes/Temptation/[score]level_dark.png   |   Bin 0 -> 213 bytes
 .../themes/Temptation/[score]level_dark_round.png  |   Bin 0 -> 410 bytes
 .../game/themes/Temptation/[score]level_light.png  |   Bin 0 -> 209 bytes
 .../themes/Temptation/[score]level_light_round.png |   Bin 0 -> 445 bytes
 .../themes/Temptation/[score]level_lightest.png    |   Bin 0 -> 209 bytes
 .../Temptation/[score]level_lightest_round.png     |   Bin 0 -> 467 bytes
 .../game/themes/Temptation/[score]rating_0.png     |   Bin 0 -> 7412 bytes
 .../game/themes/Temptation/[score]rating_1.png     |   Bin 0 -> 8206 bytes
 .../game/themes/Temptation/[score]rating_2.png     |   Bin 0 -> 9681 bytes
 .../game/themes/Temptation/[score]rating_3.png     |   Bin 0 -> 8363 bytes
 .../game/themes/Temptation/[score]rating_4.png     |   Bin 0 -> 8231 bytes
 .../game/themes/Temptation/[score]rating_5.png     |   Bin 0 -> 8720 bytes
 .../game/themes/Temptation/[score]rating_6.png     |   Bin 0 -> 8162 bytes
 .../game/themes/Temptation/[score]rating_7.png     |   Bin 0 -> 9573 bytes
 .../Temptation/[sing.player1]lyric_active.png      |   Bin 0 -> 884 bytes
 .../Temptation/[sing.player1]lyric_inactive.png    |   Bin 0 -> 862 bytes
 .../Temptation/[sing.player2]lyric_active.png      |   Bin 0 -> 1034 bytes
 .../Temptation/[sing.player2]lyric_inactive.png    |   Bin 0 -> 948 bytes
 .../Temptation/[sing.player3]lyric_active.png      |   Bin 0 -> 988 bytes
 .../Temptation/[sing.player3]lyric_inactive.png    |   Bin 0 -> 911 bytes
 .../Temptation/[sing.player4]lyric_active.png      |   Bin 0 -> 966 bytes
 .../Temptation/[sing.player4]lyric_inactive.png    |   Bin 0 -> 861 bytes
 .../Temptation/[sing.player5]lyric_active.png      |   Bin 0 -> 959 bytes
 .../Temptation/[sing.player5]lyric_inactive.png    |   Bin 0 -> 877 bytes
 .../Temptation/[sing.player6]lyric_active.png      |   Bin 0 -> 960 bytes
 .../Temptation/[sing.player6]lyric_inactive.png    |   Bin 0 -> 872 bytes
 .../game/themes/Temptation/[sing]LyricsBall.png    |   Bin 0 -> 1529 bytes
 .../themes/Temptation/[sing]lineBonusPopUp.png     |   Bin 0 -> 1344 bytes
 .../game/themes/Temptation/[sing]lyricsHelpBar.png |   Bin 0 -> 340 bytes
 .../game/themes/Temptation/[sing]notesBgLeft.png   |   Bin 0 -> 292 bytes
 .../game/themes/Temptation/[sing]notesBgMid.png    |   Bin 0 -> 144 bytes
 .../game/themes/Temptation/[sing]notesBgRight.png  |   Bin 0 -> 280 bytes
 .../game/themes/Temptation/[sing]notesLeft.png     |   Bin 0 -> 1074 bytes
 .../game/themes/Temptation/[sing]notesMid.png      |   Bin 0 -> 824 bytes
 .../themes/Temptation/[sing]notesPlainLeft.png     |   Bin 0 -> 759 bytes
 .../game/themes/Temptation/[sing]notesPlainMid.png |   Bin 0 -> 376 bytes
 .../themes/Temptation/[sing]notesPlainRight.png    |   Bin 0 -> 768 bytes
 .../game/themes/Temptation/[sing]notesRight.png    |   Bin 0 -> 1131 bytes
 songmanagement/game/themes/Temptation/[sing]p.png  |   Bin 0 -> 637 bytes
 .../game/themes/Temptation/[sing]pause.png         |   Bin 0 -> 13261 bytes
 .../game/themes/Temptation/[sing]scoreBg.jpg       |   Bin 0 -> 1799 bytes
 .../game/themes/Temptation/[sing]scoreBg.png       |   Bin 0 -> 1705 bytes
 .../game/themes/Temptation/[sing]singBarBack.png   |   Bin 0 -> 203 bytes
 .../game/themes/Temptation/[sing]singBarBar.jpg    |   Bin 0 -> 371 bytes
 .../game/themes/Temptation/[sing]singBarBar.png    |   Bin 0 -> 183 bytes
 .../game/themes/Temptation/[sing]singBarFront.png  |   Bin 0 -> 199 bytes
 .../game/themes/Temptation/[sing]textBar.png       |   Bin 0 -> 9671 bytes
 .../game/themes/Temptation/[sing]timeBar.jpg       |   Bin 0 -> 317 bytes
 .../game/themes/Temptation/[sing]timeBarBG.png     |   Bin 0 -> 1030 bytes
 .../game/themes/Temptation/[special]bar1.png       |   Bin 0 -> 407 bytes
 .../game/themes/Temptation/[special]bar2.png       |   Bin 0 -> 441 bytes
 .../game/themes/Temptation/[special]bg_fade.png    |   Bin 0 -> 32518 bytes
 .../game/themes/Temptation/[stat]detailBG1.png     |   Bin 0 -> 236 bytes
 .../game/themes/Temptation/[stat]mainBG1.png       |   Bin 0 -> 220 bytes
 .../game/themes/Temptation/[stat]mainBG2.png       |   Bin 0 -> 10697 bytes
 .../game/themes/Temptation/[stat]mainBG3.png       |   Bin 0 -> 341 bytes
 songmanagement/game/themes/Verdure.ini             |  8994 +++++++++++++
 songmanagement/game/themes/Verdure/Drippin.ini     |   241 +
 songmanagement/game/themes/Verdure/Drippin_Low.ini |   241 +
 .../game/themes/Verdure/Drippin_Static.ini         |   241 +
 songmanagement/game/themes/Verdure/Springtime.ini  |   241 +
 .../game/themes/Verdure/Springtime_Low.ini         |   241 +
 .../game/themes/Verdure/Springtime_Static.ini      |   241 +
 .../game/themes/Verdure/[bg-video]drippin.avi      |   Bin 0 -> 1848682 bytes
 .../game/themes/Verdure/[bg-video]drippin_low.avi  |   Bin 0 -> 697310 bytes
 .../game/themes/Verdure/[bg-video]springtime.avi   |   Bin 0 -> 1091544 bytes
 .../themes/Verdure/[bg-video]springtime_low.avi    |   Bin 0 -> 352532 bytes
 songmanagement/game/themes/Verdure/[bg]drippin.jpg |   Bin 0 -> 63145 bytes
 .../game/themes/Verdure/[bg]springtime.jpg         |   Bin 0 -> 30597 bytes
 songmanagement/game/themes/Verdure/[button]13.png  |   Bin 0 -> 1546 bytes
 songmanagement/game/themes/Verdure/[button]alt.png |   Bin 0 -> 1513 bytes
 songmanagement/game/themes/Verdure/[button]az.png  |   Bin 0 -> 1496 bytes
 .../game/themes/Verdure/[button]enter.png          |   Bin 0 -> 2176 bytes
 songmanagement/game/themes/Verdure/[button]esc.png |   Bin 0 -> 1508 bytes
 songmanagement/game/themes/Verdure/[button]j.png   |   Bin 0 -> 1225 bytes
 songmanagement/game/themes/Verdure/[button]m.png   |   Bin 0 -> 1256 bytes
 .../game/themes/Verdure/[button]navi.png           |   Bin 0 -> 4072 bytes
 songmanagement/game/themes/Verdure/[button]p.png   |   Bin 0 -> 1231 bytes
 .../game/themes/Verdure/[effect]goldenNoteStar.png |   Bin 0 -> 24444 bytes
 .../themes/Verdure/[effect]perfectNoteStar.png     |   Bin 0 -> 40783 bytes
 .../game/themes/Verdure/[helper]buttonFade.png     |   Bin 0 -> 337 bytes
 .../game/themes/Verdure/[helper]rectangle.png      |   Bin 0 -> 208 bytes
 songmanagement/game/themes/Verdure/[icon]cd.png    |   Bin 0 -> 777 bytes
 songmanagement/game/themes/Verdure/[icon]error.png |   Bin 0 -> 694 bytes
 songmanagement/game/themes/Verdure/[icon]main.png  |   Bin 0 -> 803 bytes
 .../game/themes/Verdure/[icon]options.png          |   Bin 0 -> 954 bytes
 songmanagement/game/themes/Verdure/[icon]party.png |   Bin 0 -> 694 bytes
 .../game/themes/Verdure/[icon]question.png         |   Bin 0 -> 747 bytes
 songmanagement/game/themes/Verdure/[icon]score.png |   Bin 0 -> 794 bytes
 .../game/themes/Verdure/[icon]song_menu.png        |   Bin 0 -> 724 bytes
 .../game/themes/Verdure/[icon]song_search.png      |   Bin 0 -> 960 bytes
 .../game/themes/Verdure/[icon]song_video.png       |   Bin 0 -> 864 bytes
 songmanagement/game/themes/Verdure/[icon]stats.png |   Bin 0 -> 676 bytes
 songmanagement/game/themes/Verdure/[icon]video.png |   Bin 0 -> 3002 bytes
 .../game/themes/Verdure/[interface]cursor.png      |   Bin 0 -> 5635 bytes
 .../themes/Verdure/[interface]cursor_pressed.png   |   Bin 0 -> 4086 bytes
 .../Verdure/[interface]dialog_background.png       |   Bin 0 -> 1602 bytes
 .../Verdure/[interface]select_arrow_left.png       |   Bin 0 -> 485 bytes
 .../Verdure/[interface]select_arrow_right.png      |   Bin 0 -> 485 bytes
 .../themes/Verdure/[interface]selectbg_search.png  |   Bin 0 -> 477 bytes
 .../game/themes/Verdure/[main]button.png           |   Bin 0 -> 297 bytes
 .../game/themes/Verdure/[main]button_left.png      |   Bin 0 -> 759 bytes
 .../game/themes/Verdure/[main]button_right.png     |   Bin 0 -> 841 bytes
 .../game/themes/Verdure/[main]buttonf.jpg          |   Bin 0 -> 17717 bytes
 songmanagement/game/themes/Verdure/[main]logo.png  |   Bin 0 -> 44436 bytes
 .../game/themes/Verdure/[main]mainBar.png          |   Bin 0 -> 249 bytes
 .../game/themes/Verdure/[main]playerNumberBox.png  |   Bin 0 -> 550 bytes
 .../game/themes/Verdure/[main]selectbg.png         |   Bin 0 -> 377 bytes
 .../game/themes/Verdure/[main]songCover.jpg        |   Bin 0 -> 15045 bytes
 .../game/themes/Verdure/[main]songSelection1.png   |   Bin 0 -> 1033 bytes
 .../game/themes/Verdure/[main]songSelection2.png   |   Bin 0 -> 1049 bytes
 .../game/themes/Verdure/[main]songSelection3.png   |   Bin 0 -> 1887 bytes
 .../game/themes/Verdure/[main]textbg.png           |   Bin 0 -> 1750 bytes
 .../game/themes/Verdure/[menu]PopUpFg.png          |   Bin 0 -> 912 bytes
 .../game/themes/Verdure/[menu]jumpToBg.png         |   Bin 0 -> 18921 bytes
 .../game/themes/Verdure/[menu]songMenuBg.png       |   Bin 0 -> 18529 bytes
 .../game/themes/Verdure/[menu]songMenuSelectBg.png |   Bin 0 -> 4707 bytes
 .../game/themes/Verdure/[party]Joker.png           |   Bin 0 -> 2084 bytes
 .../game/themes/Verdure/[party]playerButton.png    |   Bin 0 -> 755 bytes
 .../themes/Verdure/[party]playerTeamButton.png     |   Bin 0 -> 579 bytes
 .../game/themes/Verdure/[party]playerselectbg.png  |   Bin 0 -> 315 bytes
 .../game/themes/Verdure/[party]pointer.png         |   Bin 0 -> 362 bytes
 .../game/themes/Verdure/[party]roundBG1.png        |   Bin 0 -> 523 bytes
 .../game/themes/Verdure/[party]roundBG2.png        |   Bin 0 -> 375 bytes
 .../game/themes/Verdure/[party]roundBG3.png        |   Bin 0 -> 545 bytes
 .../game/themes/Verdure/[party]roundBG4.png        |   Bin 0 -> 511 bytes
 .../game/themes/Verdure/[party]roundTeamButton.png |   Bin 0 -> 603 bytes
 .../game/themes/Verdure/[party]scoreBG1.png        |   Bin 0 -> 713 bytes
 .../game/themes/Verdure/[party]scoreBG2.png        |   Bin 0 -> 407 bytes
 .../game/themes/Verdure/[party]scoreDecoration.png |   Bin 0 -> 9140 bytes
 .../game/themes/Verdure/[party]teamPoints.png      |   Bin 0 -> 1150 bytes
 .../game/themes/Verdure/[party]winDecoration.png   |   Bin 0 -> 4292 bytes
 .../game/themes/Verdure/[party]winTeamButton1.png  |   Bin 0 -> 712 bytes
 .../game/themes/Verdure/[party]winTeamButton2.png  |   Bin 0 -> 603 bytes
 .../game/themes/Verdure/[party]winTeamButton3.png  |   Bin 0 -> 560 bytes
 songmanagement/game/themes/Verdure/[score]Line.png |   Bin 0 -> 2825 bytes
 .../game/themes/Verdure/[score]bar_box_dark.png    |   Bin 0 -> 496 bytes
 .../game/themes/Verdure/[score]bar_box_light.png   |   Bin 0 -> 490 bytes
 .../themes/Verdure/[score]bar_box_lightest.png     |   Bin 0 -> 484 bytes
 songmanagement/game/themes/Verdure/[score]box.png  |   Bin 0 -> 307 bytes
 .../game/themes/Verdure/[score]endcap.png          |   Bin 0 -> 2275 bytes
 .../game/themes/Verdure/[score]glass_box.png       |   Bin 0 -> 3581 bytes
 .../game/themes/Verdure/[score]glassbackground.png |   Bin 0 -> 1515 bytes
 .../game/themes/Verdure/[score]level.png           |   Bin 0 -> 266 bytes
 .../game/themes/Verdure/[score]levelRound.png      |   Bin 0 -> 524 bytes
 .../game/themes/Verdure/[score]level_dark.png      |   Bin 0 -> 213 bytes
 .../themes/Verdure/[score]level_dark_round.png     |   Bin 0 -> 410 bytes
 .../game/themes/Verdure/[score]level_light.png     |   Bin 0 -> 209 bytes
 .../themes/Verdure/[score]level_light_round.png    |   Bin 0 -> 445 bytes
 .../game/themes/Verdure/[score]level_lightest.png  |   Bin 0 -> 209 bytes
 .../themes/Verdure/[score]level_lightest_round.png |   Bin 0 -> 467 bytes
 .../game/themes/Verdure/[score]rating_0.png        |   Bin 0 -> 7412 bytes
 .../game/themes/Verdure/[score]rating_1.png        |   Bin 0 -> 8206 bytes
 .../game/themes/Verdure/[score]rating_2.png        |   Bin 0 -> 9681 bytes
 .../game/themes/Verdure/[score]rating_3.png        |   Bin 0 -> 8363 bytes
 .../game/themes/Verdure/[score]rating_4.png        |   Bin 0 -> 8231 bytes
 .../game/themes/Verdure/[score]rating_5.png        |   Bin 0 -> 8720 bytes
 .../game/themes/Verdure/[score]rating_6.png        |   Bin 0 -> 8162 bytes
 .../game/themes/Verdure/[score]rating_7.png        |   Bin 0 -> 9573 bytes
 .../themes/Verdure/[sing.player1]lyric_active.png  |   Bin 0 -> 884 bytes
 .../Verdure/[sing.player1]lyric_inactive.png       |   Bin 0 -> 862 bytes
 .../themes/Verdure/[sing.player2]lyric_active.png  |   Bin 0 -> 1034 bytes
 .../Verdure/[sing.player2]lyric_inactive.png       |   Bin 0 -> 948 bytes
 .../themes/Verdure/[sing.player3]lyric_active.png  |   Bin 0 -> 988 bytes
 .../Verdure/[sing.player3]lyric_inactive.png       |   Bin 0 -> 911 bytes
 .../themes/Verdure/[sing.player4]lyric_active.png  |   Bin 0 -> 966 bytes
 .../Verdure/[sing.player4]lyric_inactive.png       |   Bin 0 -> 861 bytes
 .../themes/Verdure/[sing.player5]lyric_active.png  |   Bin 0 -> 959 bytes
 .../Verdure/[sing.player5]lyric_inactive.png       |   Bin 0 -> 877 bytes
 .../themes/Verdure/[sing.player6]lyric_active.png  |   Bin 0 -> 960 bytes
 .../Verdure/[sing.player6]lyric_inactive.png       |   Bin 0 -> 872 bytes
 .../game/themes/Verdure/[sing]LyricsBall.png       |   Bin 0 -> 360 bytes
 .../game/themes/Verdure/[sing]lineBonusPopUp.png   |   Bin 0 -> 1344 bytes
 .../game/themes/Verdure/[sing]lyricsHelpBar.png    |   Bin 0 -> 206 bytes
 .../game/themes/Verdure/[sing]notesBgLeft.png      |   Bin 0 -> 292 bytes
 .../game/themes/Verdure/[sing]notesBgMid.png       |   Bin 0 -> 144 bytes
 .../game/themes/Verdure/[sing]notesBgRight.png     |   Bin 0 -> 280 bytes
 .../game/themes/Verdure/[sing]notesLeft.png        |   Bin 0 -> 671 bytes
 .../game/themes/Verdure/[sing]notesMid.png         |   Bin 0 -> 236 bytes
 .../game/themes/Verdure/[sing]notesPlainLeft.png   |   Bin 0 -> 681 bytes
 .../game/themes/Verdure/[sing]notesPlainMid.png    |   Bin 0 -> 151 bytes
 .../game/themes/Verdure/[sing]notesPlainRight.png  |   Bin 0 -> 690 bytes
 .../game/themes/Verdure/[sing]notesRight.png       |   Bin 0 -> 728 bytes
 songmanagement/game/themes/Verdure/[sing]p.png     |   Bin 0 -> 637 bytes
 songmanagement/game/themes/Verdure/[sing]pause.png |   Bin 0 -> 13261 bytes
 .../game/themes/Verdure/[sing]scoreBg.jpg          |   Bin 0 -> 1799 bytes
 .../game/themes/Verdure/[sing]scoreBg.png          |   Bin 0 -> 1705 bytes
 .../game/themes/Verdure/[sing]singBarBack.png      |   Bin 0 -> 203 bytes
 .../game/themes/Verdure/[sing]singBarBar.jpg       |   Bin 0 -> 371 bytes
 .../game/themes/Verdure/[sing]singBarBar.png       |   Bin 0 -> 183 bytes
 .../game/themes/Verdure/[sing]singBarFront.png     |   Bin 0 -> 199 bytes
 .../game/themes/Verdure/[sing]textBar.png          |   Bin 0 -> 9671 bytes
 .../game/themes/Verdure/[sing]timeBar.jpg          |   Bin 0 -> 317 bytes
 .../game/themes/Verdure/[sing]timeBarBG.png        |   Bin 0 -> 4121 bytes
 .../game/themes/Verdure/[special]bar1.png          |   Bin 0 -> 600 bytes
 .../game/themes/Verdure/[special]bar12.png         |   Bin 0 -> 381 bytes
 .../game/themes/Verdure/[special]bar2.png          |   Bin 0 -> 328 bytes
 .../game/themes/Verdure/[special]bar22.png         |   Bin 0 -> 410 bytes
 .../game/themes/Verdure/[special]bg_fade.png       |   Bin 0 -> 32518 bytes
 .../game/themes/Verdure/[stat]detailBG1.png        |   Bin 0 -> 587 bytes
 .../game/themes/Verdure/[stat]mainBG1.png          |   Bin 0 -> 569 bytes
 .../game/themes/Verdure/[stat]mainBG2.png          |   Bin 0 -> 1427 bytes
 .../game/themes/Verdure/[stat]mainBG3.png          |   Bin 0 -> 435 bytes
 songmanagement/game/visuals/.gitignore             |     2 +
 songmanagement/icons/readme.txt                    |    20 +
 songmanagement/icons/ultrastardx-icon.svg          |  4001 ++++++
 songmanagement/icons/ultrastardx-icon_32.png       |   Bin 0 -> 666 bytes
 songmanagement/icons/ultrastardx-icon_512.png      |   Bin 0 -> 106731 bytes
 songmanagement/icons/ultrastardx.icns              |   Bin 0 -> 235181 bytes
 songmanagement/icons/ultrastardx.ico               |   Bin 0 -> 22486 bytes
 songmanagement/installer/UAC.nsh                   |   191 +
 songmanagement/installer/UltraStar Deluxe.nsi      |   614 +
 songmanagement/installer/Update.nsi                |   215 +
 .../installer/dependencies/dll/put game dlls here  |     0
 .../dependencies/documents/documentation.pdf       |   Bin 0 -> 581246 bytes
 .../installer/dependencies/documents/license.txt   |   125 +
 .../installer/dependencies/images/header.bmp       |   Bin 0 -> 25820 bytes
 .../installer/dependencies/images/side.bmp         |   Bin 0 -> 618008 bytes
 songmanagement/installer/dependencies/loop.wav     |   Bin 0 -> 1228860 bytes
 .../installer/dependencies/plugins/NSISdl.dll      |   Bin 0 -> 14848 bytes
 .../installer/dependencies/plugins/UAC.dll         |   Bin 0 -> 17408 bytes
 .../installer/dependencies/plugins/ZipDLL.dll      |   Bin 0 -> 167424 bytes
 .../installer/dependencies/plugins/nsProcess.dll   |   Bin 0 -> 4096 bytes
 songmanagement/installer/install.ico               |   Bin 0 -> 17542 bytes
 songmanagement/installer/languages/English.nsh     |   131 +
 songmanagement/installer/languages/German.nsh      |   130 +
 songmanagement/installer/languages/Hungarian.nsh   |   133 +
 songmanagement/installer/languages/Polish.nsh      |   131 +
 .../installer/languages/translations.txt           |    16 +
 .../installer/settings/files_main_install.nsh      |    90 +
 .../installer/settings/files_main_uninstall.nsh    |   110 +
 .../installer/settings/files_opt_songs.nsh         |   931 ++
 songmanagement/installer/settings/functions.nsh    |    50 +
 .../installer/settings/settings-1031.ini           |   161 +
 .../installer/settings/settings-1033.ini           |   161 +
 .../installer/settings/settings-1038.ini           |   161 +
 .../installer/settings/settings-1045.ini           |   161 +
 songmanagement/installer/settings/variables.nsh    |    89 +
 songmanagement/installer/uninstall.ico             |   Bin 0 -> 22486 bytes
 songmanagement/res/rccompile-delphi.bat            |     2 +
 songmanagement/res/rccompile-fpc.bat               |     4 +
 songmanagement/res/ultrastardx.exe.manifest        |    12 +
 songmanagement/res/ultrastardx.rc                  |     4 +
 songmanagement/res/ultrastardx.res                 |   Bin 0 -> 23352 bytes
 songmanagement/src/.gitignore                      |     8 +
 songmanagement/src/Makefile.in                     |   252 +
 songmanagement/src/base/TextGL.pas                 |   267 +
 songmanagement/src/base/UBeatTimer.pas             |   299 +
 songmanagement/src/base/UCatCovers.pas             |   211 +
 songmanagement/src/base/UCommandLine.pas           |   345 +
 songmanagement/src/base/UCommon.pas                |   609 +
 songmanagement/src/base/UConfig.pas                |   232 +
 songmanagement/src/base/UCovers.pas                |   459 +
 songmanagement/src/base/UDataBase.pas              |   720 ++
 songmanagement/src/base/UDraw.pas                  |  1163 ++
 songmanagement/src/base/UEditorLyrics.pas          |   260 +
 songmanagement/src/base/UFiles.pas                 |   214 +
 songmanagement/src/base/UFilesystem.pas            |   692 +
 songmanagement/src/base/UFont.pas                  |  3067 +++++
 songmanagement/src/base/UGraphic.pas               |   852 ++
 songmanagement/src/base/UGraphicClasses.pas        |   726 ++
 songmanagement/src/base/UImage.pas                 |  1131 ++
 songmanagement/src/base/UIni.pas                   |  1232 ++
 songmanagement/src/base/UJoystick.pas              |   312 +
 songmanagement/src/base/ULanguage.pas              |   302 +
 songmanagement/src/base/ULog.pas                   |   441 +
 songmanagement/src/base/ULyrics.pas                |   726 ++
 songmanagement/src/base/UMain.pas                  |   598 +
 songmanagement/src/base/UMusic.pas                 |  1235 ++
 songmanagement/src/base/UNote.pas                  |   618 +
 songmanagement/src/base/UParty.pas                 |  1026 ++
 songmanagement/src/base/UPath.pas                  |  1427 +++
 songmanagement/src/base/UPathUtils.pas             |   201 +
 songmanagement/src/base/UPlatform.pas              |   136 +
 songmanagement/src/base/UPlatformLinux.pas         |   149 +
 songmanagement/src/base/UPlatformMacOSX.pas        |   302 +
 songmanagement/src/base/UPlatformWindows.pas       |   209 +
 songmanagement/src/base/UPlaylist.pas              |   520 +
 songmanagement/src/base/URecord.pas                |   904 ++
 songmanagement/src/base/URingBuffer.pas            |   165 +
 songmanagement/src/base/USingNotes.pas             |    42 +
 songmanagement/src/base/USingScores.pas            |  1122 ++
 songmanagement/src/base/USkins.pas                 |   248 +
 songmanagement/src/base/USong.pas                  |  1303 ++
 songmanagement/src/base/USongs.pas                 |   845 ++
 songmanagement/src/base/UTextEncoding.pas          |   248 +
 songmanagement/src/base/UTexture.pas               |   548 +
 songmanagement/src/base/UThemes.pas                |  2501 ++++
 songmanagement/src/base/UTime.pas                  |   246 +
 songmanagement/src/base/UUnicodeUtils.pas          |   670 +
 songmanagement/src/base/UXMLSong.pas               |   623 +
 songmanagement/src/config-darwin.inc               |    58 +
 songmanagement/src/config-win.inc                  |    55 +
 songmanagement/src/config.inc.in                   |    58 +
 songmanagement/src/encoding/Auto.inc               |   137 +
 songmanagement/src/encoding/CP1250.inc             |   236 +
 songmanagement/src/encoding/CP1252.inc             |   122 +
 songmanagement/src/encoding/Locale.inc             |    55 +
 songmanagement/src/encoding/UTF8.inc               |    70 +
 songmanagement/src/lib/FreeImage/FreeBitmap.pas    |  1742 +++
 songmanagement/src/lib/FreeImage/FreeImage.pas     |   771 ++
 .../src/lib/JEDI-SDL/JEDI-SDL-README.txt           |   244 +
 .../src/lib/JEDI-SDL/OpenGL-Set8087CW.patch        |    16 +
 .../src/lib/JEDI-SDL/OpenGL/Pas/geometry.pas       |  1994 +++
 songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas  |  2301 ++++
 .../src/lib/JEDI-SDL/OpenGL/Pas/glext.pas          |  9579 ++++++++++++++
 songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas |   582 +
 .../src/lib/JEDI-SDL/OpenGL/Pas/glut.pas           |   688 +
 songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas |   279 +
 songmanagement/src/lib/JEDI-SDL/SDL/Pas/Readme.txt |    27 +
 .../src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc          |   442 +
 .../src/lib/JEDI-SDL/SDL/Pas/libxmlparser.pas      |  2688 ++++
 songmanagement/src/lib/JEDI-SDL/SDL/Pas/logger.pas |   189 +
 .../src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas      |   320 +
 .../JEDI-SDL/SDL/Pas/registryuserpreferences.pas   |   229 +
 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdl.pas    |  4332 +++++++
 .../src/lib/JEDI-SDL/SDL/Pas/sdl_cpuinfo.pas       |   155 +
 .../src/lib/JEDI-SDL/SDL/Pas/sdlgameinterface.pas  |   202 +
 .../src/lib/JEDI-SDL/SDL/Pas/sdli386utils.pas      |  5236 ++++++++
 .../src/lib/JEDI-SDL/SDL/Pas/sdlinput.pas          |   923 ++
 .../src/lib/JEDI-SDL/SDL/Pas/sdlstreams.pas        |   216 +
 .../src/lib/JEDI-SDL/SDL/Pas/sdlticks.pas          |   197 +
 .../src/lib/JEDI-SDL/SDL/Pas/sdlutils.pas          |  4363 +++++++
 .../src/lib/JEDI-SDL/SDL/Pas/sdlwindow.pas         |   566 +
 .../src/lib/JEDI-SDL/SDL/Pas/userpreferences.pas   |   159 +
 .../src/lib/JEDI-SDL/SDL_Image/Pas/sdl_image.pas   |   350 +
 songmanagement/src/lib/JEDI-SDL/fpc-install.sh     |   252 +
 .../src/lib/JEDI-SDL/jedi-sdl-64bit.patch          |  1280 ++
 .../src/lib/JEDI-SDL/moduleloader-libc.patch       |    25 +
 songmanagement/src/lib/Lua/ULua.pas                |  1086 ++
 songmanagement/src/lib/SQLite/SQLite3.pas          |   253 +
 songmanagement/src/lib/SQLite/SQLiteTable3.pas     |  1500 +++
 songmanagement/src/lib/SQLite/example/Sunset.jpg   |   Bin 0 -> 71189 bytes
 .../src/lib/SQLite/example/TestSqlite.dpr          |    15 +
 .../src/lib/SQLite/example/TestSqlite.res          |   Bin 0 -> 876 bytes
 .../src/lib/SQLite/example/uTestSqlite.dfm         |   110 +
 .../src/lib/SQLite/example/uTestSqlite.pas         |   233 +
 songmanagement/src/lib/SQLite/readme.txt           |    93 +
 .../src/lib/TntUnicodeControls/License.txt         |    11 +
 .../src/lib/TntUnicodeControls/Readme.txt          |    53 +
 .../src/lib/TntUnicodeControls/TntClasses.pas      |  1806 +++
 .../src/lib/TntUnicodeControls/TntCompilers.inc    |   378 +
 .../lib/TntUnicodeControls/TntFormatStrUtils.pas   |   521 +
 .../src/lib/TntUnicodeControls/TntSysUtils.pas     |  1753 +++
 .../src/lib/TntUnicodeControls/TntSystem.pas       |  1427 +++
 .../src/lib/TntUnicodeControls/TntWideStrUtils.pas |   455 +
 .../src/lib/TntUnicodeControls/TntWideStrings.pas  |   846 ++
 .../src/lib/TntUnicodeControls/TntWindows.pas      |  1501 +++
 songmanagement/src/lib/bass/bass.chm               |   Bin 0 -> 217294 bytes
 songmanagement/src/lib/bass/bass.txt               |  1734 +++
 .../src/lib/bass/delphi/bass-macosx.patch          |   368 +
 songmanagement/src/lib/bass/delphi/bass.pas        |   941 ++
 songmanagement/src/lib/collections/CollArray.pas   |   183 +
 songmanagement/src/lib/collections/CollHash.pas    |  1497 +++
 songmanagement/src/lib/collections/CollLibrary.pas |   131 +
 songmanagement/src/lib/collections/CollList.pas    |   270 +
 songmanagement/src/lib/collections/CollPArray.pas  |   689 +
 .../src/lib/collections/CollWrappers.pas           |   876 ++
 songmanagement/src/lib/collections/Collections.pas |  5318 ++++++++
 songmanagement/src/lib/collections/readme.txt      |    14 +
 songmanagement/src/lib/ctypes/ctypes.pas           |    72 +
 songmanagement/src/lib/ffmpeg/avcodec.pas          |  5002 ++++++++
 songmanagement/src/lib/ffmpeg/avformat.pas         |  2100 +++
 songmanagement/src/lib/ffmpeg/avio.pas             |   796 ++
 songmanagement/src/lib/ffmpeg/avutil.pas           |   504 +
 songmanagement/src/lib/ffmpeg/error.pas            |   115 +
 songmanagement/src/lib/ffmpeg/mathematics.pas      |   133 +
 songmanagement/src/lib/ffmpeg/opt.pas              |   261 +
 songmanagement/src/lib/ffmpeg/rational.pas         |   170 +
 songmanagement/src/lib/ffmpeg/swscale.pas          |   434 +
 songmanagement/src/lib/fft/UFFT.pas                |   602 +
 .../src/lib/freetype/demo/engine-test.bdsproj      |   175 +
 .../src/lib/freetype/demo/engine-test.dpr          |   338 +
 .../src/lib/freetype/demo/engine-test.lpi          |   182 +
 .../src/lib/freetype/demo/nehe/UFreeType.pas       |   326 +
 .../src/lib/freetype/demo/nehe/lesson43.bdsproj    |   175 +
 .../src/lib/freetype/demo/nehe/lesson43.dpr        |   289 +
 .../src/lib/freetype/demo/nehe/readme.txt          |     9 +
 songmanagement/src/lib/freetype/demo/switches.inc  |     1 +
 songmanagement/src/lib/freetype/freetype.pas       |  1903 +++
 songmanagement/src/lib/freetype/ftconfig.inc       |    35 +
 songmanagement/src/lib/freetype/ftglyph.inc        |   435 +
 songmanagement/src/lib/freetype/ftimage.inc        |   849 ++
 songmanagement/src/lib/freetype/ftoutln.inc        |   497 +
 songmanagement/src/lib/freetype/ftstroke.inc       |   711 ++
 songmanagement/src/lib/freetype/fttypes.inc        |   311 +
 songmanagement/src/lib/lib-info.txt                |    60 +
 songmanagement/src/lib/libpng/png.pas              |   974 ++
 songmanagement/src/lib/midi/CIRCBUF.PAS            |   183 +
 songmanagement/src/lib/midi/DELPHMCB.PAS           |   140 +
 songmanagement/src/lib/midi/MIDIDEFS.PAS           |    55 +
 songmanagement/src/lib/midi/MIDITYPE.PAS           |    90 +
 songmanagement/src/lib/midi/MidiFile.pas           |   968 ++
 songmanagement/src/lib/midi/MidiScope.pas          |   198 +
 songmanagement/src/lib/midi/Midicons.pas           |    47 +
 songmanagement/src/lib/midi/Midiin.pas             |   720 ++
 songmanagement/src/lib/midi/Midiout.pas            |   612 +
 songmanagement/src/lib/midi/demo/MidiTest.dfm      |   Bin 0 -> 1872 bytes
 songmanagement/src/lib/midi/demo/MidiTest.pas      |   249 +
 songmanagement/src/lib/midi/demo/Project1.dpr      |    13 +
 songmanagement/src/lib/midi/demo/Project1.res      |   Bin 0 -> 876 bytes
 songmanagement/src/lib/midi/midiComp.cfg           |    35 +
 songmanagement/src/lib/midi/midiComp.dpk           |    45 +
 songmanagement/src/lib/midi/midiComp.res           |   Bin 0 -> 876 bytes
 songmanagement/src/lib/midi/readme.txt             |    60 +
 songmanagement/src/lib/other/DirWatch.pas          |   345 +
 songmanagement/src/lib/other/WinAllocation.pas     |   101 +
 songmanagement/src/lib/pcre/pcre.pas               |   867 ++
 songmanagement/src/lib/portaudio/portaudio.pas     |  1160 ++
 songmanagement/src/lib/portmixer/portmixer.pas     |   149 +
 .../src/lib/projectM/cwrapper/Makefile.in          |    41 +
 .../lib/projectM/cwrapper/projectM-cwrapper.cpp    |   104 +
 .../src/lib/projectM/cwrapper/projectM-cwrapper.h  |    68 +
 .../lib/projectM/cwrapper/projectM-cwrapper.sln    |    20 +
 .../lib/projectM/cwrapper/projectM-cwrapper.vcproj |   205 +
 songmanagement/src/lib/projectM/projectM-0_9.inc   |   427 +
 songmanagement/src/lib/projectM/projectM-1_0.inc   |   188 +
 songmanagement/src/lib/projectM/projectM.pas       |   232 +
 songmanagement/src/lib/requirements.txt            |    48 +
 songmanagement/src/lib/samplerate/samplerate.pas   |   199 +
 songmanagement/src/lib/zlib/zlib.pas               |   215 +
 songmanagement/src/lua/UHookableEvent.pas          |   380 +
 songmanagement/src/lua/ULuaCore.pas                |  1021 ++
 songmanagement/src/lua/ULuaGl.pas                  |  1513 +++
 songmanagement/src/lua/ULuaLog.pas                 |   167 +
 songmanagement/src/lua/ULuaParty.pas               |   391 +
 songmanagement/src/lua/ULuaScreenSing.pas          |   489 +
 songmanagement/src/lua/ULuaTextGL.pas              |   148 +
 songmanagement/src/lua/ULuaTexture.pas             |    63 +
 songmanagement/src/lua/ULuaUsdx.pas                |   145 +
 songmanagement/src/lua/ULuaUtils.pas               |   186 +
 songmanagement/src/macosx/Info.plist               |    38 +
 songmanagement/src/macosx/PseudoThread.pas         |    75 +
 songmanagement/src/media/UAudioConverter.pas       |   483 +
 songmanagement/src/media/UAudioCore_Bass.pas       |   177 +
 songmanagement/src/media/UAudioCore_Portaudio.pas  |   337 +
 songmanagement/src/media/UAudioDecoder_Bass.pas    |   278 +
 songmanagement/src/media/UAudioDecoder_FFmpeg.pas  |  1159 ++
 songmanagement/src/media/UAudioInput_Bass.pas      |   519 +
 songmanagement/src/media/UAudioInput_Portaudio.pas |   537 +
 songmanagement/src/media/UAudioPlaybackBase.pas    |   319 +
 songmanagement/src/media/UAudioPlayback_Bass.pas   |   758 ++
 .../src/media/UAudioPlayback_Portaudio.pas         |   385 +
 songmanagement/src/media/UAudioPlayback_SDL.pas    |   182 +
 .../src/media/UAudioPlayback_SoftMixer.pas         |  1204 ++
 songmanagement/src/media/UMediaCore_FFmpeg.pas     |   645 +
 songmanagement/src/media/UMediaCore_SDL.pas        |    63 +
 songmanagement/src/media/UMedia_dummy.pas          |   492 +
 songmanagement/src/media/UVideo.pas                |  1436 +++
 songmanagement/src/media/UVisualizer.pas           |   685 +
 songmanagement/src/menu/UDisplay.pas               |   747 ++
 songmanagement/src/menu/UDrawTexture.pas           |   139 +
 songmanagement/src/menu/UMenu.pas                  |  1804 +++
 songmanagement/src/menu/UMenuBackground.pas        |    83 +
 songmanagement/src/menu/UMenuBackgroundColor.pas   |    73 +
 songmanagement/src/menu/UMenuBackgroundFade.pas    |   176 +
 songmanagement/src/menu/UMenuBackgroundNone.pas    |    70 +
 songmanagement/src/menu/UMenuBackgroundTexture.pas |   126 +
 songmanagement/src/menu/UMenuBackgroundVideo.pas   |   211 +
 songmanagement/src/menu/UMenuButton.pas            |   647 +
 songmanagement/src/menu/UMenuButtonCollection.pas  |   101 +
 songmanagement/src/menu/UMenuEqualizer.pas         |   320 +
 songmanagement/src/menu/UMenuInteract.pas          |    54 +
 songmanagement/src/menu/UMenuSelectSlide.pas       |   541 +
 songmanagement/src/menu/UMenuStatic.pas            |   117 +
 songmanagement/src/menu/UMenuText.pas              |   379 +
 songmanagement/src/screens/UScreenCredits.pas      |  1329 ++
 songmanagement/src/screens/UScreenEdit.pas         |   164 +
 songmanagement/src/screens/UScreenEditConvert.pas  |   826 ++
 songmanagement/src/screens/UScreenEditHeader.pas   |   445 +
 songmanagement/src/screens/UScreenEditSub.pas      |  1809 +++
 songmanagement/src/screens/UScreenLevel.pas        |   139 +
 songmanagement/src/screens/UScreenLoading.pas      |    78 +
 songmanagement/src/screens/UScreenMain.pas         |   296 +
 songmanagement/src/screens/UScreenName.pas         |   284 +
 songmanagement/src/screens/UScreenOpen.pas         |   231 +
 songmanagement/src/screens/UScreenOptions.pas      |   234 +
 .../src/screens/UScreenOptionsAdvanced.pas         |   168 +
 songmanagement/src/screens/UScreenOptionsGame.pas  |   175 +
 .../src/screens/UScreenOptionsGraphics.pas         |   164 +
 .../src/screens/UScreenOptionsLyrics.pas           |   147 +
 .../src/screens/UScreenOptionsRecord.pas           |   836 ++
 songmanagement/src/screens/UScreenOptionsSound.pas |   187 +
 .../src/screens/UScreenOptionsThemes.pas           |   237 +
 .../src/screens/UScreenPartyNewRound.pas           |   334 +
 songmanagement/src/screens/UScreenPartyOptions.pas |   284 +
 songmanagement/src/screens/UScreenPartyPlayer.pas  |   449 +
 songmanagement/src/screens/UScreenPartyRounds.pas  |   233 +
 songmanagement/src/screens/UScreenPartyScore.pas   |   334 +
 songmanagement/src/screens/UScreenPartyWin.pas     |   295 +
 songmanagement/src/screens/UScreenPopup.pas        |   308 +
 songmanagement/src/screens/UScreenScore.pas        |  1187 ++
 songmanagement/src/screens/UScreenSing.pas         |  1071 ++
 songmanagement/src/screens/UScreenSong.pas         |  2156 ++++
 songmanagement/src/screens/UScreenSongJumpto.pas   |   247 +
 songmanagement/src/screens/UScreenSongMenu.pas     |   664 +
 songmanagement/src/screens/UScreenStatDetail.pas   |   303 +
 songmanagement/src/screens/UScreenStatMain.pas     |   323 +
 songmanagement/src/screens/UScreenTop5.pas         |   307 +
 songmanagement/src/switches.inc                    |   129 +
 songmanagement/src/ultrastardx.dpr                 |   345 +
 songmanagement/test/TestPortAudioDevice.pas        |   528 +
 songmanagement/test/TestSignAlgorithm.pas          |    58 +
 songmanagement/test/switches.inc                   |     0
 songmanagement/test/test001.pas                    |    86 +
 songmanagement/test/test_libraries.lpi             |   299 +
 songmanagement/test/test_libraries.lpr             |    31 +
 songmanagement/test/testsqllite.pas                |    84 +
 .../tools/ScoreConverter/ScoreConverter.dpr        |    17 +
 .../tools/ScoreConverter/ScoreConverter.ico        |   Bin 0 -> 766 bytes
 .../tools/ScoreConverter/ScoreConverter.res        |   Bin 0 -> 876 bytes
 songmanagement/tools/ScoreConverter/UScores.pas    |   102 +
 songmanagement/tools/ScoreConverter/USongs.pas     |   160 +
 songmanagement/tools/ScoreConverter/Umainform.dfm  |   123 +
 songmanagement/tools/ScoreConverter/Umainform.pas  |   230 +
 1259 files changed, 262786 insertions(+)
 create mode 100644 songmanagement/.gitignore
 create mode 100644 songmanagement/AUTHORS.txt
 create mode 100644 songmanagement/BuildBot.trigger
 create mode 100644 songmanagement/COPYING.txt
 create mode 100644 songmanagement/COPYRIGHT.txt
 create mode 100644 songmanagement/ChangeLog.GERMAN.txt
 create mode 100644 songmanagement/ChangeLog.txt
 create mode 100644 songmanagement/DisplayChanges.patch
 create mode 100644 songmanagement/Makefile.in
 create mode 100644 songmanagement/README Mac OS X
 create mode 100644 songmanagement/README.txt
 create mode 100644 songmanagement/RELEASEBLOCKERS.txt
 create mode 100755 songmanagement/autogen.sh
 create mode 100644 songmanagement/build/.gitignore
 create mode 100644 songmanagement/build/delphi-win/.gitignore
 create mode 100755 songmanagement/configure
 create mode 100644 songmanagement/configure.ac
 create mode 100755 songmanagement/dists/autogen/config.guess
 create mode 100755 songmanagement/dists/autogen/config.sub
 create mode 100755 songmanagement/dists/autogen/install-sh
 create mode 100644 songmanagement/dists/autogen/m4/ac_define_dir.m4
 create mode 100644 songmanagement/dists/autogen/m4/ax_extract_version.m4
 create mode 100644 songmanagement/dists/autogen/m4/fpc.m4
 create mode 100644 songmanagement/dists/autogen/m4/macosx_version.m4
 create mode 100644 songmanagement/dists/autogen/m4/pkg_config_utils.m4
 create mode 100644 songmanagement/dists/bamboo/bamboo-build-lin-laz.bat
 create mode 100644 songmanagement/dists/bamboo/bamboo-build-lin-laz.sh
 create mode 100644 songmanagement/dists/bamboo/bamboo-build-win-delphi.bat
 create mode 100644 songmanagement/dists/bamboo/bamboo-build-win-laz.bat
 create mode 100644 songmanagement/dists/code.svnprops
 create mode 100644 songmanagement/dists/debian/package_debian.sh
 create mode 100644 songmanagement/dists/debian/ultrastardx.control
 create mode 100644 songmanagement/dists/delphi2005/readme.txt
 create mode 100644 songmanagement/dists/delphi2005/ultrastardx.bdsproj
 create mode 100644 songmanagement/dists/delphi7/readme.txt
 create mode 100644 songmanagement/dists/delphi7/ultrastardx.dof
 create mode 100644 songmanagement/dists/gentoo/readme.txt
 create mode 100644 songmanagement/dists/gentoo/ultrastardx-1.1.0.ebuild
 create mode 100644 songmanagement/dists/gentoo/ultrastardx-9999.ebuild
 create mode 100644 songmanagement/dists/lazarus/clean.bat
 create mode 100755 songmanagement/dists/lazarus/readme.txt
 create mode 100644 songmanagement/dists/lazarus/ultrastardx-unix.lpi
 create mode 100644 songmanagement/dists/lazarus/ultrastardx-win.lpi
 create mode 100644 songmanagement/dists/ultrastardx.desktop
 create mode 100755 songmanagement/dists/xcode/English.lproj/InfoPlist.strings
 create mode 100644 songmanagement/dists/xcode/English.lproj/SDLMain.nib/classes.nib
 create mode 100644 songmanagement/dists/xcode/English.lproj/SDLMain.nib/info.nib
 create mode 100644 songmanagement/dists/xcode/English.lproj/SDLMain.nib/objects.nib
 create mode 100644 songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.mode1
 create mode 100644 songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.mode1v3
 create mode 100644 songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.pbxuser
 create mode 100644 songmanagement/dists/xcode/UltraStarDX.xcodeproj/project.pbxproj
 create mode 100644 songmanagement/doc/Makefile
 create mode 100644 songmanagement/game/.gitignore
 create mode 100644 songmanagement/game/LuaCommands.odt
 create mode 100644 songmanagement/game/covers/Artist/Artist#.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist0.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist1.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist2.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist3.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist4.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist5.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist6.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist7.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist8.jpg
 create mode 100644 songmanagement/game/covers/Artist/Artist9.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistA.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistB.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistC.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistD.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistE.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistF.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistG.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistH.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistI.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistJ.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistK.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistL.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistM.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistN.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistO.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistP.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistQ.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistR.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistS.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistT.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistU.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistV.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistW.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistX.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistY.jpg
 create mode 100644 songmanagement/game/covers/Artist/ArtistZ.jpg
 create mode 100644 "songmanagement/game/covers/Artist/Artist\303\204.jpg"
 create mode 100644 "songmanagement/game/covers/Artist/Artist\303\226.jpg"
 create mode 100644 "songmanagement/game/covers/Artist/Artist\303\234.jpg"
 create mode 100644 songmanagement/game/covers/Covers.ini
 create mode 100644 songmanagement/game/covers/Creative Commons.jpg
 create mode 100644 songmanagement/game/covers/Language/Austrian.jpg
 create mode 100644 songmanagement/game/covers/Language/Bavarian.jpg
 create mode 100644 songmanagement/game/covers/Language/Chinese.jpg
 create mode 100644 songmanagement/game/covers/Language/Danish.jpg
 create mode 100644 songmanagement/game/covers/Language/Dutch.jpg
 create mode 100644 songmanagement/game/covers/Language/English.jpg
 create mode 100644 songmanagement/game/covers/Language/Finish.jpg
 create mode 100644 songmanagement/game/covers/Language/French.jpg
 create mode 100644 songmanagement/game/covers/Language/German.jpg
 create mode 100644 songmanagement/game/covers/Language/Greek.jpg
 create mode 100644 songmanagement/game/covers/Language/Italian.jpg
 create mode 100644 songmanagement/game/covers/Language/Japanese.jpg
 create mode 100644 "songmanagement/game/covers/Language/K\303\266lsch.jpg"
 create mode 100644 songmanagement/game/covers/Language/Norwegian.jpg
 create mode 100644 songmanagement/game/covers/Language/Peruvian.jpg
 create mode 100644 songmanagement/game/covers/Language/Polish.jpg
 create mode 100644 songmanagement/game/covers/Language/Romanian.jpg
 create mode 100644 songmanagement/game/covers/Language/Russian.jpg
 create mode 100644 songmanagement/game/covers/Language/Slovenian.jpg
 create mode 100644 songmanagement/game/covers/Language/Spanish.jpg
 create mode 100644 songmanagement/game/covers/Language/Swedish.jpg
 create mode 100644 songmanagement/game/covers/Language/Thumbs.db
 create mode 100644 songmanagement/game/covers/Language/Turkish.jpg
 create mode 100644 songmanagement/game/covers/NoCover.jpg
 create mode 100644 songmanagement/game/covers/Title/Title#.jpg
 create mode 100644 songmanagement/game/covers/Title/Title0.jpg
 create mode 100644 songmanagement/game/covers/Title/Title1.jpg
 create mode 100644 songmanagement/game/covers/Title/Title2.jpg
 create mode 100644 songmanagement/game/covers/Title/Title3.jpg
 create mode 100644 songmanagement/game/covers/Title/Title4.jpg
 create mode 100644 songmanagement/game/covers/Title/Title5.jpg
 create mode 100644 songmanagement/game/covers/Title/Title6.jpg
 create mode 100644 songmanagement/game/covers/Title/Title7.jpg
 create mode 100644 songmanagement/game/covers/Title/Title8.jpg
 create mode 100644 songmanagement/game/covers/Title/Title9.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleD.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleE.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleF.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleG.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleH.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleI.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleJ.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleK.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleL.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleM.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleN.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleO.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleP.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleQ.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleR.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleS.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleT.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleU.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleV.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleW.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleX.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleY.jpg
 create mode 100644 songmanagement/game/covers/Title/TitleZ.jpg
 create mode 100644 songmanagement/game/covers/Title/Titlea.jpg
 create mode 100644 songmanagement/game/covers/Title/Titleb.jpg
 create mode 100644 songmanagement/game/covers/Title/Titlec.jpg
 create mode 100644 "songmanagement/game/covers/Title/Title\303\204.jpg"
 create mode 100644 "songmanagement/game/covers/Title/Title\303\226.jpg"
 create mode 100644 "songmanagement/game/covers/Title/Title\303\234.jpg"
 create mode 100644 songmanagement/game/fonts/DejaVu/AUTHORS
 create mode 100644 songmanagement/game/fonts/DejaVu/DejaVuSans-Bold.ttf
 create mode 100644 songmanagement/game/fonts/DejaVu/DejaVuSans.ttf
 create mode 100644 songmanagement/game/fonts/DejaVu/LICENSE
 create mode 100644 songmanagement/game/fonts/DejaVu/README
 create mode 100644 songmanagement/game/fonts/FreeSans/AUTHORS
 create mode 100644 songmanagement/game/fonts/FreeSans/COPYING
 create mode 100644 songmanagement/game/fonts/FreeSans/CREDITS
 create mode 100644 songmanagement/game/fonts/FreeSans/FreeSans.ttf
 create mode 100644 songmanagement/game/fonts/FreeSans/FreeSansBold.ttf
 create mode 100644 songmanagement/game/fonts/FreeSans/README
 create mode 100755 songmanagement/game/fonts/fonts.ini
 create mode 100644 songmanagement/game/fonts/wqy-microhei/AUTHORS.txt
 create mode 100644 songmanagement/game/fonts/wqy-microhei/LICENSE_Apache2.txt
 create mode 100644 songmanagement/game/fonts/wqy-microhei/LICENSE_GPLv3.txt
 create mode 100644 songmanagement/game/fonts/wqy-microhei/README.txt
 create mode 100644 songmanagement/game/fonts/wqy-microhei/wqy-microhei.ttc
 create mode 100644 songmanagement/game/languages/Catalan.ini
 create mode 100644 songmanagement/game/languages/Chinese.ini
 create mode 100644 songmanagement/game/languages/Croatian.ini
 create mode 100644 songmanagement/game/languages/Czech.ini
 create mode 100644 songmanagement/game/languages/Danish.ini
 create mode 100644 songmanagement/game/languages/Dutch.ini
 create mode 100644 songmanagement/game/languages/English.ini
 create mode 100644 songmanagement/game/languages/Euskara.ini
 create mode 100644 songmanagement/game/languages/Finnish.ini
 create mode 100644 songmanagement/game/languages/French.ini
 create mode 100644 songmanagement/game/languages/German.ini
 create mode 100644 songmanagement/game/languages/Greek.ini
 create mode 100644 songmanagement/game/languages/Hungarian.ini
 create mode 100644 songmanagement/game/languages/Icelandic.ini
 create mode 100644 songmanagement/game/languages/Italian.ini
 create mode 100644 songmanagement/game/languages/Japanese.ini
 create mode 100644 songmanagement/game/languages/Language.new
 create mode 100644 songmanagement/game/languages/Luxembourgish.ini
 create mode 100644 songmanagement/game/languages/Norwegian.ini
 create mode 100644 songmanagement/game/languages/Polish.ini
 create mode 100644 songmanagement/game/languages/Portuguese.ini
 create mode 100644 songmanagement/game/languages/Russian.ini
 create mode 100644 songmanagement/game/languages/Serbian.ini
 create mode 100644 songmanagement/game/languages/Slovak.ini
 create mode 100644 songmanagement/game/languages/Slovenian.ini
 create mode 100644 songmanagement/game/languages/Spanish.ini
 create mode 100644 songmanagement/game/languages/Swedish.ini
 create mode 100755 songmanagement/game/languages/convert.sh
 create mode 100644 songmanagement/game/languages/readme.txt
 create mode 100755 songmanagement/game/languages/update.py
 create mode 100644 songmanagement/game/plugins/5000points.usdx
 create mode 100644 songmanagement/game/plugins/PluginDescription.odt
 create mode 100644 songmanagement/game/plugins/blind.usdx
 create mode 100644 songmanagement/game/plugins/duel.usdx
 create mode 100644 songmanagement/game/plugins/holdtheline.usdx
 create mode 100644 songmanagement/game/plugins/hooks.txt
 create mode 100644 songmanagement/game/plugins/teamduel.usdx
 create mode 100644 songmanagement/game/resources/credits/credits_v5_bg.png
 create mode 100644 songmanagement/game/resources/credits/credits_v5_overlay.png
 create mode 100644 songmanagement/game/resources/credits/intro-l-01.png
 create mode 100644 songmanagement/game/resources/credits/intro-l-02.png
 create mode 100644 songmanagement/game/resources/credits/intro-l-03.png
 create mode 100644 songmanagement/game/resources/credits/intro-l-04.png
 create mode 100644 songmanagement/game/resources/credits/intro-l-05.png
 create mode 100644 songmanagement/game/resources/credits/intro-l-06.png
 create mode 100644 songmanagement/game/resources/credits/intro-l-07.png
 create mode 100644 songmanagement/game/resources/credits/intro-l-08.png
 create mode 100644 songmanagement/game/resources/credits/intro-l-09.png
 create mode 100644 songmanagement/game/resources/credits/names_alexanders.png
 create mode 100644 songmanagement/game/resources/credits/names_blindguard.png
 create mode 100644 songmanagement/game/resources/credits/names_blindy.png
 create mode 100644 songmanagement/game/resources/credits/names_brunzel.png
 create mode 100644 songmanagement/game/resources/credits/names_canni.png
 create mode 100644 songmanagement/game/resources/credits/names_commandio.png
 create mode 100644 songmanagement/game/resources/credits/names_hennymcc.png
 create mode 100644 songmanagement/game/resources/credits/names_jaybinks.png
 create mode 100644 songmanagement/game/resources/credits/names_krueger.png
 create mode 100644 songmanagement/game/resources/credits/names_lazyjoker.png
 create mode 100644 songmanagement/game/resources/credits/names_mezzox.png
 create mode 100644 songmanagement/game/resources/credits/names_mischi.png
 create mode 100644 songmanagement/game/resources/credits/names_mog.png
 create mode 100644 songmanagement/game/resources/credits/names_mota.png
 create mode 100644 songmanagement/game/resources/credits/names_skillmaster.png
 create mode 100644 songmanagement/game/resources/credits/names_whiteshark.png
 create mode 100644 songmanagement/game/resources/credits/outro-bg.png
 create mode 100644 songmanagement/game/resources/credits/outro-esc.png
 create mode 100644 songmanagement/game/resources/credits/outro-exit-dark.png
 create mode 100644 songmanagement/game/resources/graphics/NoCover.jpg
 create mode 100644 songmanagement/game/resources/icons/ultrastardx-icon.png
 create mode 100644 songmanagement/game/sounds/Common back.mp3
 create mode 100644 songmanagement/game/sounds/Common start.mp3
 create mode 100755 songmanagement/game/sounds/background track license.txt
 create mode 100755 songmanagement/game/sounds/background track.mp3
 create mode 100644 songmanagement/game/sounds/credits-outro-tune.mp3
 create mode 100644 songmanagement/game/sounds/dismissed.mp3
 create mode 100644 songmanagement/game/sounds/menu swoosh.mp3
 create mode 100644 songmanagement/game/sounds/option change col.mp3
 create mode 100644 songmanagement/game/sounds/rimshot022b.mp3
 create mode 100644 songmanagement/game/sounds/select music change music 50.mp3
 create mode 100644 songmanagement/game/sounds/select music change music.mp3
 create mode 100644 songmanagement/game/sounds/wome-credits-tune.mp3
 create mode 100755 songmanagement/game/themes/Candy.ini
 create mode 100755 songmanagement/game/themes/Candy/Clouds static.ini
 create mode 100755 songmanagement/game/themes/Candy/Clouds.ini
 create mode 100755 songmanagement/game/themes/Candy/Party1BG.png
 create mode 100755 songmanagement/game/themes/Candy/Party1Bar.png
 create mode 100755 songmanagement/game/themes/Candy/SongMenuButton.png
 create mode 100755 songmanagement/game/themes/Candy/StatsBox.png
 create mode 100755 songmanagement/game/themes/Candy/Transparent.png
 create mode 100755 songmanagement/game/themes/Candy/[bg-load]clouds.jpg
 create mode 100755 songmanagement/game/themes/Candy/[bg-main]clouds.AVI
 create mode 100755 songmanagement/game/themes/Candy/[bg-main]clouds.jpg
 create mode 100755 songmanagement/game/themes/Candy/[bg-main]options.AVI
 create mode 100755 songmanagement/game/themes/Candy/[bg-main]options.jpg
 create mode 100755 songmanagement/game/themes/Candy/[button]13.png
 create mode 100755 songmanagement/game/themes/Candy/[button]alt.png
 create mode 100755 songmanagement/game/themes/Candy/[button]az.png
 create mode 100755 songmanagement/game/themes/Candy/[button]enter.png
 create mode 100755 songmanagement/game/themes/Candy/[button]esc.png
 create mode 100755 songmanagement/game/themes/Candy/[button]j.png
 create mode 100755 songmanagement/game/themes/Candy/[button]m.png
 create mode 100755 songmanagement/game/themes/Candy/[button]main.png
 create mode 100755 songmanagement/game/themes/Candy/[button]navi.png
 create mode 100755 songmanagement/game/themes/Candy/[button]p.png
 create mode 100755 songmanagement/game/themes/Candy/[effect]goldenNoteStar.png
 create mode 100755 songmanagement/game/themes/Candy/[effect]perfectNoteStar.png
 create mode 100755 songmanagement/game/themes/Candy/[icon]logo.png
 create mode 100755 songmanagement/game/themes/Candy/[icon]options.png
 create mode 100755 songmanagement/game/themes/Candy/[icon]song_duett.png
 create mode 100755 songmanagement/game/themes/Candy/[icon]song_video.png
 create mode 100755 songmanagement/game/themes/Candy/[interface]cursor.png
 create mode 100755 songmanagement/game/themes/Candy/[interface]cursor_pressed.png
 create mode 100755 songmanagement/game/themes/Candy/[interface]select_arrow_left.png
 create mode 100755 songmanagement/game/themes/Candy/[interface]select_arrow_right.png
 create mode 100755 songmanagement/game/themes/Candy/[interface]selectbg_search.png
 create mode 100755 songmanagement/game/themes/Candy/[main]button.png
 create mode 100755 songmanagement/game/themes/Candy/[main]mainBar.png
 create mode 100755 songmanagement/game/themes/Candy/[main]partymenubg.png
 create mode 100755 songmanagement/game/themes/Candy/[main]searchbg.png
 create mode 100755 songmanagement/game/themes/Candy/[main]selectbg.png
 create mode 100755 songmanagement/game/themes/Candy/[main]songCover.jpg
 create mode 100755 songmanagement/game/themes/Candy/[main]songSelection1.png
 create mode 100755 songmanagement/game/themes/Candy/[main]songSelection2.png
 create mode 100755 songmanagement/game/themes/Candy/[party]Joker.png
 create mode 100755 songmanagement/game/themes/Candy/[party]playerButton.png
 create mode 100755 songmanagement/game/themes/Candy/[party]playerTeamButton.png
 create mode 100755 songmanagement/game/themes/Candy/[party]playerselectbg.png
 create mode 100755 songmanagement/game/themes/Candy/[party]pointer.png
 create mode 100755 songmanagement/game/themes/Candy/[party]roundBG1.png
 create mode 100755 songmanagement/game/themes/Candy/[party]roundBG2.png
 create mode 100755 songmanagement/game/themes/Candy/[party]roundBG3.png
 create mode 100755 songmanagement/game/themes/Candy/[party]roundBG4.png
 create mode 100755 songmanagement/game/themes/Candy/[party]roundTeamButton.png
 create mode 100755 songmanagement/game/themes/Candy/[party]winDecoration.png
 create mode 100755 songmanagement/game/themes/Candy/[score]Line.png
 create mode 100755 songmanagement/game/themes/Candy/[score]bar_box_dark.png
 create mode 100755 songmanagement/game/themes/Candy/[score]bar_box_light.png
 create mode 100755 songmanagement/game/themes/Candy/[score]bar_box_lightest.png
 create mode 100755 songmanagement/game/themes/Candy/[score]box.png
 create mode 100755 songmanagement/game/themes/Candy/[score]endcap.png
 create mode 100755 songmanagement/game/themes/Candy/[score]level.png
 create mode 100755 songmanagement/game/themes/Candy/[score]levelRound.png
 create mode 100755 songmanagement/game/themes/Candy/[score]level_dark.png
 create mode 100755 songmanagement/game/themes/Candy/[score]level_dark_round.png
 create mode 100755 songmanagement/game/themes/Candy/[score]level_light.png
 create mode 100755 songmanagement/game/themes/Candy/[score]level_light_round.png
 create mode 100755 songmanagement/game/themes/Candy/[score]level_lightest.png
 create mode 100755 songmanagement/game/themes/Candy/[score]level_lightest_round.png
 create mode 100755 songmanagement/game/themes/Candy/[score]pipe.png
 create mode 100755 songmanagement/game/themes/Candy/[score]rating_0.png
 create mode 100755 songmanagement/game/themes/Candy/[score]rating_1.png
 create mode 100755 songmanagement/game/themes/Candy/[score]rating_2.png
 create mode 100755 songmanagement/game/themes/Candy/[score]rating_3.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player1]lyric_active.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player1]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player2]lyric_active.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player2]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player3]lyric_active.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player3]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player4]lyric_active.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player4]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player5]lyric_active.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player5]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player6]lyric_active.png
 create mode 100755 songmanagement/game/themes/Candy/[sing.player6]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]lyricsHelpBar.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]notesBgLeft.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]notesBgMid.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]notesBgRight.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]notesLeft.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]notesMid.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]notesPlainLeft.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]notesPlainMid.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]notesPlainRight.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]notesRight.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]p.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]pause.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]scoreBg.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]singBarBack.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]singBarBar.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]singBarFront.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]textBar.png
 create mode 100755 songmanagement/game/themes/Candy/[sing]timeBar.jpg
 create mode 100755 songmanagement/game/themes/Candy/[special]bg_fade.png
 create mode 100644 songmanagement/game/themes/Classic.ini
 create mode 100644 songmanagement/game/themes/Classic/Star.ini
 create mode 100644 songmanagement/game/themes/Classic/[bg-load]star.jpg
 create mode 100644 songmanagement/game/themes/Classic/[bg-main]star.jpg
 create mode 100644 songmanagement/game/themes/Classic/[button]13.png
 create mode 100644 songmanagement/game/themes/Classic/[button]alt.png
 create mode 100644 songmanagement/game/themes/Classic/[button]az.png
 create mode 100644 songmanagement/game/themes/Classic/[button]e.png
 create mode 100644 songmanagement/game/themes/Classic/[button]enter.png
 create mode 100644 songmanagement/game/themes/Classic/[button]esc.png
 create mode 100644 songmanagement/game/themes/Classic/[button]j.png
 create mode 100644 songmanagement/game/themes/Classic/[button]m.png
 create mode 100644 songmanagement/game/themes/Classic/[button]navi.png
 create mode 100644 songmanagement/game/themes/Classic/[button]p.png
 create mode 100644 songmanagement/game/themes/Classic/[effect]goldenNoteStar.png
 create mode 100644 songmanagement/game/themes/Classic/[effect]perfectNoteStar.png
 create mode 100644 songmanagement/game/themes/Classic/[helper]buttonFade.png
 create mode 100644 songmanagement/game/themes/Classic/[helper]rectangle.jpg
 create mode 100644 songmanagement/game/themes/Classic/[icon]Star.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]cd.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]error.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]main.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]options.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]party.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]question.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]score.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]song_menu.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]song_search.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]song_video.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]stats.png
 create mode 100644 songmanagement/game/themes/Classic/[icon]video.png
 create mode 100644 songmanagement/game/themes/Classic/[interface]cursor.png
 create mode 100644 songmanagement/game/themes/Classic/[interface]cursor_pressed.png
 create mode 100644 songmanagement/game/themes/Classic/[interface]dialog_background.png
 create mode 100644 songmanagement/game/themes/Classic/[interface]select_arrow_left.png
 create mode 100644 songmanagement/game/themes/Classic/[interface]select_arrow_right.png
 create mode 100644 songmanagement/game/themes/Classic/[interface]selectbg_search.png
 create mode 100644 songmanagement/game/themes/Classic/[main]button.png
 create mode 100644 songmanagement/game/themes/Classic/[main]buttonf.jpg
 create mode 100644 songmanagement/game/themes/Classic/[main]logo.png
 create mode 100644 songmanagement/game/themes/Classic/[main]mainBar.png
 create mode 100644 songmanagement/game/themes/Classic/[main]playerNumberBox.png
 create mode 100644 songmanagement/game/themes/Classic/[main]selectbg.png
 create mode 100644 songmanagement/game/themes/Classic/[main]songCover.jpg
 create mode 100644 songmanagement/game/themes/Classic/[mainbutton]Exit.png
 create mode 100644 songmanagement/game/themes/Classic/[mainbutton]Multi.png
 create mode 100644 songmanagement/game/themes/Classic/[mainbutton]Options.png
 create mode 100644 songmanagement/game/themes/Classic/[mainbutton]Solo.png
 create mode 100644 songmanagement/game/themes/Classic/[mainbutton]Stats.png
 create mode 100644 songmanagement/game/themes/Classic/[menu]PopUpFg.png
 create mode 100644 songmanagement/game/themes/Classic/[menu]jumpToBg.png
 create mode 100644 songmanagement/game/themes/Classic/[menu]songMenuBg.png
 create mode 100644 songmanagement/game/themes/Classic/[menu]songMenuSelectBg.png
 create mode 100644 songmanagement/game/themes/Classic/[party]Joker.png
 create mode 100644 songmanagement/game/themes/Classic/[party]playerButton.png
 create mode 100644 songmanagement/game/themes/Classic/[party]playerTeamButton.png
 create mode 100644 songmanagement/game/themes/Classic/[party]playerselectbg.png
 create mode 100644 songmanagement/game/themes/Classic/[party]pointer.png
 create mode 100644 songmanagement/game/themes/Classic/[party]roundBG1.png
 create mode 100644 songmanagement/game/themes/Classic/[party]roundBG2.png
 create mode 100644 songmanagement/game/themes/Classic/[party]roundBG3.png
 create mode 100644 songmanagement/game/themes/Classic/[party]roundBG4.png
 create mode 100644 songmanagement/game/themes/Classic/[party]roundTeamButton.png
 create mode 100644 songmanagement/game/themes/Classic/[party]scoreBG1.png
 create mode 100644 songmanagement/game/themes/Classic/[party]scoreBG2.png
 create mode 100644 songmanagement/game/themes/Classic/[party]scoreDecoration.png
 create mode 100644 songmanagement/game/themes/Classic/[party]teamPoints.png
 create mode 100644 songmanagement/game/themes/Classic/[party]winDecoration.png
 create mode 100644 songmanagement/game/themes/Classic/[party]winTeamButton1.png
 create mode 100644 songmanagement/game/themes/Classic/[party]winTeamButton2.png
 create mode 100644 songmanagement/game/themes/Classic/[party]winTeamButton3.png
 create mode 100644 songmanagement/game/themes/Classic/[score]Line.png
 create mode 100644 songmanagement/game/themes/Classic/[score]bar_box_dark.png
 create mode 100644 songmanagement/game/themes/Classic/[score]bar_box_light.png
 create mode 100644 songmanagement/game/themes/Classic/[score]bar_box_lightest.png
 create mode 100644 songmanagement/game/themes/Classic/[score]box.png
 create mode 100644 songmanagement/game/themes/Classic/[score]endcap.png
 create mode 100644 songmanagement/game/themes/Classic/[score]glass_box.png
 create mode 100644 songmanagement/game/themes/Classic/[score]level.png
 create mode 100644 songmanagement/game/themes/Classic/[score]levelRound.png
 create mode 100644 songmanagement/game/themes/Classic/[score]level_dark.png
 create mode 100644 songmanagement/game/themes/Classic/[score]level_dark_round.png
 create mode 100644 songmanagement/game/themes/Classic/[score]level_light.png
 create mode 100644 songmanagement/game/themes/Classic/[score]level_light_round.png
 create mode 100644 songmanagement/game/themes/Classic/[score]level_lightest.png
 create mode 100644 songmanagement/game/themes/Classic/[score]level_lightest_round.png
 create mode 100644 songmanagement/game/themes/Classic/[score]rating_0.png
 create mode 100644 songmanagement/game/themes/Classic/[score]rating_1.png
 create mode 100644 songmanagement/game/themes/Classic/[score]rating_2.png
 create mode 100644 songmanagement/game/themes/Classic/[score]rating_3.png
 create mode 100644 songmanagement/game/themes/Classic/[score]rating_4.png
 create mode 100644 songmanagement/game/themes/Classic/[score]rating_5.png
 create mode 100644 songmanagement/game/themes/Classic/[score]rating_6.png
 create mode 100644 songmanagement/game/themes/Classic/[score]rating_7.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player1]lyric_active.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player1]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player2]lyric_active.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player2]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player3]lyric_active.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player3]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player4]lyric_active.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player4]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player5]lyric_active.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player5]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player6]lyric_active.png
 create mode 100644 songmanagement/game/themes/Classic/[sing.player6]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]LyricsBall.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]lineBonusPopUp.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]lyricsHelpBar.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]notesBgLeft.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]notesBgMid.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]notesBgRight.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]notesLeft.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]notesMid.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]notesPlainLeft.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]notesPlainMid.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]notesPlainRight.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]notesRight.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]p.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]pause.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]scoreBg.jpg
 create mode 100644 songmanagement/game/themes/Classic/[sing]scoreBg.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]singBarBack.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]singBarBar.jpg
 create mode 100644 songmanagement/game/themes/Classic/[sing]singBarBar.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]singBarFront.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]textBar.png
 create mode 100644 songmanagement/game/themes/Classic/[sing]timeBar.jpg
 create mode 100644 songmanagement/game/themes/Classic/[sing]timeBarBG.png
 create mode 100644 songmanagement/game/themes/Classic/[song]BGFade.jpg
 create mode 100644 songmanagement/game/themes/Classic/[song]EqualizerBG.jpg
 create mode 100644 songmanagement/game/themes/Classic/[song]selection.png
 create mode 100644 songmanagement/game/themes/Classic/[songs]bg.png
 create mode 100644 songmanagement/game/themes/Classic/[special]bar1.png
 create mode 100644 songmanagement/game/themes/Classic/[special]bar2.png
 create mode 100644 songmanagement/game/themes/Classic/[special]bg_fade.png
 create mode 100644 songmanagement/game/themes/Classic/[stat]detailBG1.png
 create mode 100644 songmanagement/game/themes/Classic/[stat]mainBG1.png
 create mode 100644 songmanagement/game/themes/Classic/[stat]mainBG2.png
 create mode 100644 songmanagement/game/themes/Classic/[stat]mainBG3.png
 create mode 100644 songmanagement/game/themes/Deluxe.ini
 create mode 100644 songmanagement/game/themes/Deluxe/Blue.ini
 create mode 100644 songmanagement/game/themes/Deluxe/Fall.ini
 create mode 100644 songmanagement/game/themes/Deluxe/Ocean.ini
 create mode 100644 songmanagement/game/themes/Deluxe/Ribbon.ini
 create mode 100644 songmanagement/game/themes/Deluxe/Summer.ini
 create mode 100644 songmanagement/game/themes/Deluxe/Winter.ini
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-load]blue.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-load]fall.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-load]summer.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-load]winter.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-main]blue.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-main]fall.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-main]summer.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-main]winter.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-video]_ocean.avi
 create mode 100644 songmanagement/game/themes/Deluxe/[bg-video]ribbon.mov
 create mode 100644 songmanagement/game/themes/Deluxe/[button]13.png
 create mode 100644 songmanagement/game/themes/Deluxe/[button]alt.png
 create mode 100644 songmanagement/game/themes/Deluxe/[button]az.png
 create mode 100644 songmanagement/game/themes/Deluxe/[button]enter.png
 create mode 100644 songmanagement/game/themes/Deluxe/[button]esc.png
 create mode 100644 songmanagement/game/themes/Deluxe/[button]j.png
 create mode 100644 songmanagement/game/themes/Deluxe/[button]m.png
 create mode 100644 songmanagement/game/themes/Deluxe/[button]navi.png
 create mode 100644 songmanagement/game/themes/Deluxe/[button]p.png
 create mode 100644 songmanagement/game/themes/Deluxe/[effect]goldenNoteStar.png
 create mode 100644 songmanagement/game/themes/Deluxe/[effect]perfectNoteStar.png
 create mode 100644 songmanagement/game/themes/Deluxe/[helper]buttonFade.png
 create mode 100644 songmanagement/game/themes/Deluxe/[helper]rectangle.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]cd.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]error.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]main.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]options.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]party.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]question.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]score.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]song_menu.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]song_search.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]song_video.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]stats.png
 create mode 100644 songmanagement/game/themes/Deluxe/[icon]video.png
 create mode 100644 songmanagement/game/themes/Deluxe/[interface]cursor.png
 create mode 100644 songmanagement/game/themes/Deluxe/[interface]cursor_pressed.png
 create mode 100644 songmanagement/game/themes/Deluxe/[interface]dialog_background.png
 create mode 100644 songmanagement/game/themes/Deluxe/[interface]select_arrow_left.png
 create mode 100644 songmanagement/game/themes/Deluxe/[interface]select_arrow_right.png
 create mode 100644 songmanagement/game/themes/Deluxe/[interface]selectbg_search.png
 create mode 100644 songmanagement/game/themes/Deluxe/[main]button.png
 create mode 100644 songmanagement/game/themes/Deluxe/[main]buttonf.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[main]mainBar.png
 create mode 100644 songmanagement/game/themes/Deluxe/[main]playerNumberBox.png
 create mode 100644 songmanagement/game/themes/Deluxe/[main]selectbg.png
 create mode 100644 songmanagement/game/themes/Deluxe/[main]songCover.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[main]songSelection1.png
 create mode 100644 songmanagement/game/themes/Deluxe/[main]songSelection2.png
 create mode 100644 songmanagement/game/themes/Deluxe/[menu]PopUpFg.png
 create mode 100644 songmanagement/game/themes/Deluxe/[menu]jumpToBg.png
 create mode 100644 songmanagement/game/themes/Deluxe/[menu]songMenuBg.png
 create mode 100644 songmanagement/game/themes/Deluxe/[menu]songMenuSelectBg.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]Joker.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]playerButton.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]playerTeamButton.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]playerselectbg.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]pointer.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]roundBG1.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]roundBG2.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]roundBG3.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]roundBG4.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]roundTeamButton.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]scoreBG1.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]scoreBG2.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]scoreDecoration.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]teamPoints.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]winDecoration.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]winTeamButton1.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]winTeamButton2.png
 create mode 100644 songmanagement/game/themes/Deluxe/[party]winTeamButton3.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]Line.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]bar_box_dark.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]bar_box_light.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]bar_box_lightest.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]box.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]endcap.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]glass_box.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]level.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]levelRound.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]level_dark.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]level_dark_round.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]level_light.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]level_light_round.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]level_lightest.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]level_lightest_round.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]rating_0.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]rating_1.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]rating_2.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]rating_3.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]rating_4.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]rating_5.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]rating_6.png
 create mode 100644 songmanagement/game/themes/Deluxe/[score]rating_7.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player1]lyric_active.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player1]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player2]lyric_active.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player2]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player3]lyric_active.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player3]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player4]lyric_active.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player4]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player5]lyric_active.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player5]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player6]lyric_active.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing.player6]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]LyricsBall.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]lineBonusPopUp.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]lyricsHelpBar.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]notesBgLeft.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]notesBgMid.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]notesBgRight.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]notesLeft.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]notesMid.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]notesPlainLeft.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]notesPlainMid.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]notesPlainRight.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]notesRight.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]p.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]pause.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]scoreBg.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]scoreBg.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]singBarBack.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]singBarBar.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]singBarBar.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]singBarFront.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]textBar.png
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]timeBar.jpg
 create mode 100644 songmanagement/game/themes/Deluxe/[sing]timeBarBG.png
 create mode 100644 songmanagement/game/themes/Deluxe/[special]bar1.png
 create mode 100644 songmanagement/game/themes/Deluxe/[special]bar2.png
 create mode 100644 songmanagement/game/themes/Deluxe/[special]bg_fade.png
 create mode 100644 songmanagement/game/themes/Deluxe/[stat]detailBG1.png
 create mode 100644 songmanagement/game/themes/Deluxe/[stat]mainBG1.png
 create mode 100644 songmanagement/game/themes/Deluxe/[stat]mainBG2.png
 create mode 100644 songmanagement/game/themes/Deluxe/[stat]mainBG3.png
 create mode 100755 songmanagement/game/themes/Temptation.ini
 create mode 100755 songmanagement/game/themes/Temptation/Temptation (16-9).ini
 create mode 100755 songmanagement/game/themes/Temptation/Temptation (4-3).ini
 create mode 100755 songmanagement/game/themes/Temptation/[Level]buttoneasy.png
 create mode 100755 songmanagement/game/themes/Temptation/[Level]buttonhard.png
 create mode 100755 songmanagement/game/themes/Temptation/[Level]buttonmedium.png
 create mode 100755 songmanagement/game/themes/Temptation/[Name]button.png
 create mode 100755 songmanagement/game/themes/Temptation/[Options]buttonadvanced.png
 create mode 100755 songmanagement/game/themes/Temptation/[Options]buttonback.png
 create mode 100755 songmanagement/game/themes/Temptation/[Options]buttondesign.png
 create mode 100755 songmanagement/game/themes/Temptation/[Options]buttongame.png
 create mode 100755 songmanagement/game/themes/Temptation/[Options]buttongraphics.png
 create mode 100755 songmanagement/game/themes/Temptation/[Options]buttonlyrics.png
 create mode 100755 songmanagement/game/themes/Temptation/[Options]buttonrecord.png
 create mode 100755 songmanagement/game/themes/Temptation/[Options]buttonsound.png
 create mode 100755 songmanagement/game/themes/Temptation/[bg-load]16-9.png
 create mode 100755 songmanagement/game/themes/Temptation/[bg-load]4-3.png
 create mode 100755 songmanagement/game/themes/Temptation/[bg-main]16-9.png
 create mode 100755 songmanagement/game/themes/Temptation/[bg-main]4-3.png
 create mode 100755 songmanagement/game/themes/Temptation/[bg-title]16-9.png
 create mode 100755 songmanagement/game/themes/Temptation/[bg-title]4-3.png
 create mode 100755 songmanagement/game/themes/Temptation/[button]13.png
 create mode 100755 songmanagement/game/themes/Temptation/[button]alt.png
 create mode 100755 songmanagement/game/themes/Temptation/[button]az.png
 create mode 100755 songmanagement/game/themes/Temptation/[button]enter.png
 create mode 100755 songmanagement/game/themes/Temptation/[button]esc.png
 create mode 100755 songmanagement/game/themes/Temptation/[button]j.png
 create mode 100755 songmanagement/game/themes/Temptation/[button]m.png
 create mode 100755 songmanagement/game/themes/Temptation/[button]navi.png
 create mode 100755 songmanagement/game/themes/Temptation/[button]p.png
 create mode 100755 songmanagement/game/themes/Temptation/[edit]buttonconvert.png
 create mode 100755 songmanagement/game/themes/Temptation/[effect]goldenNoteStar.png
 create mode 100755 songmanagement/game/themes/Temptation/[effect]perfectNoteStar.png
 create mode 100755 songmanagement/game/themes/Temptation/[helper]buttonFade.png
 create mode 100755 songmanagement/game/themes/Temptation/[helper]rectangle.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]cd.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]error.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]main.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]options.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]party.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]question.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]score.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]song_menu.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]song_search.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]song_video.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]stats.png
 create mode 100755 songmanagement/game/themes/Temptation/[icon]video.png
 create mode 100755 songmanagement/game/themes/Temptation/[interface]cursor.png
 create mode 100755 songmanagement/game/themes/Temptation/[interface]cursor_pressed.png
 create mode 100755 songmanagement/game/themes/Temptation/[interface]dialog_background.png
 create mode 100755 songmanagement/game/themes/Temptation/[interface]select_arrow_left.png
 create mode 100755 songmanagement/game/themes/Temptation/[interface]select_arrow_right.png
 create mode 100755 songmanagement/game/themes/Temptation/[interface]selectbg_search.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]button.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]button2.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]buttonedit.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]buttonexit.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]buttonf.jpg
 create mode 100755 songmanagement/game/themes/Temptation/[main]buttonoption.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]buttonparty.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]buttonsolo.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]buttonstats.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]mainBar.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]playerNumberBox.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]selectbg.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]songCover.jpg
 create mode 100755 songmanagement/game/themes/Temptation/[main]songSelection1.png
 create mode 100755 songmanagement/game/themes/Temptation/[main]songSelection2.png
 create mode 100755 songmanagement/game/themes/Temptation/[menu]PopUpFg.png
 create mode 100755 songmanagement/game/themes/Temptation/[menu]jumpToBg.png
 create mode 100755 songmanagement/game/themes/Temptation/[menu]songMenuBg.png
 create mode 100755 songmanagement/game/themes/Temptation/[menu]songMenuSelectBg.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]Joker.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]playerButton.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]playerTeamButton.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]playerselectbg.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]pointer.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]roundBG1.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]roundBG2.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]roundBG3.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]roundBG4.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]roundTeamButton.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]scoreBG1.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]scoreBG2.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]scoreDecoration.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]teamPoints.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]winDecoration.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]winTeamButton1.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]winTeamButton2.png
 create mode 100755 songmanagement/game/themes/Temptation/[party]winTeamButton3.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]Line.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]bar_box_dark.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]bar_box_light.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]bar_box_lightest.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]box.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]endcap.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]glass_box.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]level.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]levelRound.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]level_dark.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]level_dark_round.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]level_light.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]level_light_round.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]level_lightest.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]level_lightest_round.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]rating_0.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]rating_1.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]rating_2.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]rating_3.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]rating_4.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]rating_5.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]rating_6.png
 create mode 100755 songmanagement/game/themes/Temptation/[score]rating_7.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player1]lyric_active.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player1]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player2]lyric_active.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player2]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player3]lyric_active.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player3]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player4]lyric_active.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player4]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player5]lyric_active.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player5]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player6]lyric_active.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing.player6]lyric_inactive.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]LyricsBall.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]lineBonusPopUp.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]lyricsHelpBar.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]notesBgLeft.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]notesBgMid.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]notesBgRight.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]notesLeft.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]notesMid.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]notesPlainLeft.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]notesPlainMid.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]notesPlainRight.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]notesRight.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]p.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]pause.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]scoreBg.jpg
 create mode 100755 songmanagement/game/themes/Temptation/[sing]scoreBg.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]singBarBack.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]singBarBar.jpg
 create mode 100755 songmanagement/game/themes/Temptation/[sing]singBarBar.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]singBarFront.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]textBar.png
 create mode 100755 songmanagement/game/themes/Temptation/[sing]timeBar.jpg
 create mode 100755 songmanagement/game/themes/Temptation/[sing]timeBarBG.png
 create mode 100755 songmanagement/game/themes/Temptation/[special]bar1.png
 create mode 100755 songmanagement/game/themes/Temptation/[special]bar2.png
 create mode 100755 songmanagement/game/themes/Temptation/[special]bg_fade.png
 create mode 100755 songmanagement/game/themes/Temptation/[stat]detailBG1.png
 create mode 100755 songmanagement/game/themes/Temptation/[stat]mainBG1.png
 create mode 100755 songmanagement/game/themes/Temptation/[stat]mainBG2.png
 create mode 100755 songmanagement/game/themes/Temptation/[stat]mainBG3.png
 create mode 100644 songmanagement/game/themes/Verdure.ini
 create mode 100644 songmanagement/game/themes/Verdure/Drippin.ini
 create mode 100644 songmanagement/game/themes/Verdure/Drippin_Low.ini
 create mode 100644 songmanagement/game/themes/Verdure/Drippin_Static.ini
 create mode 100644 songmanagement/game/themes/Verdure/Springtime.ini
 create mode 100644 songmanagement/game/themes/Verdure/Springtime_Low.ini
 create mode 100644 songmanagement/game/themes/Verdure/Springtime_Static.ini
 create mode 100644 songmanagement/game/themes/Verdure/[bg-video]drippin.avi
 create mode 100644 songmanagement/game/themes/Verdure/[bg-video]drippin_low.avi
 create mode 100644 songmanagement/game/themes/Verdure/[bg-video]springtime.avi
 create mode 100644 songmanagement/game/themes/Verdure/[bg-video]springtime_low.avi
 create mode 100644 songmanagement/game/themes/Verdure/[bg]drippin.jpg
 create mode 100644 songmanagement/game/themes/Verdure/[bg]springtime.jpg
 create mode 100644 songmanagement/game/themes/Verdure/[button]13.png
 create mode 100644 songmanagement/game/themes/Verdure/[button]alt.png
 create mode 100644 songmanagement/game/themes/Verdure/[button]az.png
 create mode 100644 songmanagement/game/themes/Verdure/[button]enter.png
 create mode 100644 songmanagement/game/themes/Verdure/[button]esc.png
 create mode 100644 songmanagement/game/themes/Verdure/[button]j.png
 create mode 100644 songmanagement/game/themes/Verdure/[button]m.png
 create mode 100644 songmanagement/game/themes/Verdure/[button]navi.png
 create mode 100644 songmanagement/game/themes/Verdure/[button]p.png
 create mode 100644 songmanagement/game/themes/Verdure/[effect]goldenNoteStar.png
 create mode 100644 songmanagement/game/themes/Verdure/[effect]perfectNoteStar.png
 create mode 100644 songmanagement/game/themes/Verdure/[helper]buttonFade.png
 create mode 100644 songmanagement/game/themes/Verdure/[helper]rectangle.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]cd.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]error.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]main.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]options.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]party.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]question.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]score.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]song_menu.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]song_search.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]song_video.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]stats.png
 create mode 100644 songmanagement/game/themes/Verdure/[icon]video.png
 create mode 100644 songmanagement/game/themes/Verdure/[interface]cursor.png
 create mode 100644 songmanagement/game/themes/Verdure/[interface]cursor_pressed.png
 create mode 100644 songmanagement/game/themes/Verdure/[interface]dialog_background.png
 create mode 100644 songmanagement/game/themes/Verdure/[interface]select_arrow_left.png
 create mode 100644 songmanagement/game/themes/Verdure/[interface]select_arrow_right.png
 create mode 100644 songmanagement/game/themes/Verdure/[interface]selectbg_search.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]button.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]button_left.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]button_right.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]buttonf.jpg
 create mode 100644 songmanagement/game/themes/Verdure/[main]logo.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]mainBar.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]playerNumberBox.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]selectbg.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]songCover.jpg
 create mode 100644 songmanagement/game/themes/Verdure/[main]songSelection1.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]songSelection2.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]songSelection3.png
 create mode 100644 songmanagement/game/themes/Verdure/[main]textbg.png
 create mode 100644 songmanagement/game/themes/Verdure/[menu]PopUpFg.png
 create mode 100644 songmanagement/game/themes/Verdure/[menu]jumpToBg.png
 create mode 100644 songmanagement/game/themes/Verdure/[menu]songMenuBg.png
 create mode 100644 songmanagement/game/themes/Verdure/[menu]songMenuSelectBg.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]Joker.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]playerButton.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]playerTeamButton.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]playerselectbg.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]pointer.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]roundBG1.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]roundBG2.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]roundBG3.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]roundBG4.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]roundTeamButton.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]scoreBG1.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]scoreBG2.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]scoreDecoration.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]teamPoints.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]winDecoration.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]winTeamButton1.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]winTeamButton2.png
 create mode 100644 songmanagement/game/themes/Verdure/[party]winTeamButton3.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]Line.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]bar_box_dark.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]bar_box_light.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]bar_box_lightest.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]box.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]endcap.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]glass_box.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]glassbackground.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]level.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]levelRound.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]level_dark.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]level_dark_round.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]level_light.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]level_light_round.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]level_lightest.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]level_lightest_round.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]rating_0.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]rating_1.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]rating_2.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]rating_3.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]rating_4.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]rating_5.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]rating_6.png
 create mode 100644 songmanagement/game/themes/Verdure/[score]rating_7.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player1]lyric_active.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player1]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player2]lyric_active.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player2]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player3]lyric_active.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player3]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player4]lyric_active.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player4]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player5]lyric_active.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player5]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player6]lyric_active.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing.player6]lyric_inactive.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]LyricsBall.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]lineBonusPopUp.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]lyricsHelpBar.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]notesBgLeft.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]notesBgMid.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]notesBgRight.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]notesLeft.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]notesMid.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]notesPlainLeft.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]notesPlainMid.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]notesPlainRight.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]notesRight.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]p.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]pause.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]scoreBg.jpg
 create mode 100644 songmanagement/game/themes/Verdure/[sing]scoreBg.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]singBarBack.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]singBarBar.jpg
 create mode 100644 songmanagement/game/themes/Verdure/[sing]singBarBar.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]singBarFront.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]textBar.png
 create mode 100644 songmanagement/game/themes/Verdure/[sing]timeBar.jpg
 create mode 100644 songmanagement/game/themes/Verdure/[sing]timeBarBG.png
 create mode 100644 songmanagement/game/themes/Verdure/[special]bar1.png
 create mode 100644 songmanagement/game/themes/Verdure/[special]bar12.png
 create mode 100644 songmanagement/game/themes/Verdure/[special]bar2.png
 create mode 100644 songmanagement/game/themes/Verdure/[special]bar22.png
 create mode 100644 songmanagement/game/themes/Verdure/[special]bg_fade.png
 create mode 100644 songmanagement/game/themes/Verdure/[stat]detailBG1.png
 create mode 100644 songmanagement/game/themes/Verdure/[stat]mainBG1.png
 create mode 100644 songmanagement/game/themes/Verdure/[stat]mainBG2.png
 create mode 100644 songmanagement/game/themes/Verdure/[stat]mainBG3.png
 create mode 100644 songmanagement/game/visuals/.gitignore
 create mode 100644 songmanagement/icons/readme.txt
 create mode 100644 songmanagement/icons/ultrastardx-icon.svg
 create mode 100644 songmanagement/icons/ultrastardx-icon_32.png
 create mode 100644 songmanagement/icons/ultrastardx-icon_512.png
 create mode 100644 songmanagement/icons/ultrastardx.icns
 create mode 100644 songmanagement/icons/ultrastardx.ico
 create mode 100644 songmanagement/installer/UAC.nsh
 create mode 100644 songmanagement/installer/UltraStar Deluxe.nsi
 create mode 100644 songmanagement/installer/Update.nsi
 create mode 100644 songmanagement/installer/dependencies/dll/put game dlls here
 create mode 100644 songmanagement/installer/dependencies/documents/documentation.pdf
 create mode 100644 songmanagement/installer/dependencies/documents/license.txt
 create mode 100644 songmanagement/installer/dependencies/images/header.bmp
 create mode 100644 songmanagement/installer/dependencies/images/side.bmp
 create mode 100644 songmanagement/installer/dependencies/loop.wav
 create mode 100644 songmanagement/installer/dependencies/plugins/NSISdl.dll
 create mode 100644 songmanagement/installer/dependencies/plugins/UAC.dll
 create mode 100644 songmanagement/installer/dependencies/plugins/ZipDLL.dll
 create mode 100644 songmanagement/installer/dependencies/plugins/nsProcess.dll
 create mode 100644 songmanagement/installer/install.ico
 create mode 100644 songmanagement/installer/languages/English.nsh
 create mode 100644 songmanagement/installer/languages/German.nsh
 create mode 100644 songmanagement/installer/languages/Hungarian.nsh
 create mode 100644 songmanagement/installer/languages/Polish.nsh
 create mode 100644 songmanagement/installer/languages/translations.txt
 create mode 100644 songmanagement/installer/settings/files_main_install.nsh
 create mode 100644 songmanagement/installer/settings/files_main_uninstall.nsh
 create mode 100644 songmanagement/installer/settings/files_opt_songs.nsh
 create mode 100644 songmanagement/installer/settings/functions.nsh
 create mode 100644 songmanagement/installer/settings/settings-1031.ini
 create mode 100644 songmanagement/installer/settings/settings-1033.ini
 create mode 100644 songmanagement/installer/settings/settings-1038.ini
 create mode 100644 songmanagement/installer/settings/settings-1045.ini
 create mode 100644 songmanagement/installer/settings/variables.nsh
 create mode 100644 songmanagement/installer/uninstall.ico
 create mode 100644 songmanagement/res/rccompile-delphi.bat
 create mode 100644 songmanagement/res/rccompile-fpc.bat
 create mode 100644 songmanagement/res/ultrastardx.exe.manifest
 create mode 100644 songmanagement/res/ultrastardx.rc
 create mode 100644 songmanagement/res/ultrastardx.res
 create mode 100644 songmanagement/src/.gitignore
 create mode 100644 songmanagement/src/Makefile.in
 create mode 100644 songmanagement/src/base/TextGL.pas
 create mode 100644 songmanagement/src/base/UBeatTimer.pas
 create mode 100644 songmanagement/src/base/UCatCovers.pas
 create mode 100644 songmanagement/src/base/UCommandLine.pas
 create mode 100644 songmanagement/src/base/UCommon.pas
 create mode 100644 songmanagement/src/base/UConfig.pas
 create mode 100644 songmanagement/src/base/UCovers.pas
 create mode 100644 songmanagement/src/base/UDataBase.pas
 create mode 100644 songmanagement/src/base/UDraw.pas
 create mode 100644 songmanagement/src/base/UEditorLyrics.pas
 create mode 100644 songmanagement/src/base/UFiles.pas
 create mode 100644 songmanagement/src/base/UFilesystem.pas
 create mode 100644 songmanagement/src/base/UFont.pas
 create mode 100644 songmanagement/src/base/UGraphic.pas
 create mode 100644 songmanagement/src/base/UGraphicClasses.pas
 create mode 100644 songmanagement/src/base/UImage.pas
 create mode 100644 songmanagement/src/base/UIni.pas
 create mode 100644 songmanagement/src/base/UJoystick.pas
 create mode 100644 songmanagement/src/base/ULanguage.pas
 create mode 100644 songmanagement/src/base/ULog.pas
 create mode 100644 songmanagement/src/base/ULyrics.pas
 create mode 100644 songmanagement/src/base/UMain.pas
 create mode 100644 songmanagement/src/base/UMusic.pas
 create mode 100644 songmanagement/src/base/UNote.pas
 create mode 100644 songmanagement/src/base/UParty.pas
 create mode 100644 songmanagement/src/base/UPath.pas
 create mode 100644 songmanagement/src/base/UPathUtils.pas
 create mode 100644 songmanagement/src/base/UPlatform.pas
 create mode 100644 songmanagement/src/base/UPlatformLinux.pas
 create mode 100644 songmanagement/src/base/UPlatformMacOSX.pas
 create mode 100644 songmanagement/src/base/UPlatformWindows.pas
 create mode 100644 songmanagement/src/base/UPlaylist.pas
 create mode 100644 songmanagement/src/base/URecord.pas
 create mode 100644 songmanagement/src/base/URingBuffer.pas
 create mode 100644 songmanagement/src/base/USingNotes.pas
 create mode 100644 songmanagement/src/base/USingScores.pas
 create mode 100644 songmanagement/src/base/USkins.pas
 create mode 100644 songmanagement/src/base/USong.pas
 create mode 100644 songmanagement/src/base/USongs.pas
 create mode 100644 songmanagement/src/base/UTextEncoding.pas
 create mode 100644 songmanagement/src/base/UTexture.pas
 create mode 100644 songmanagement/src/base/UThemes.pas
 create mode 100644 songmanagement/src/base/UTime.pas
 create mode 100644 songmanagement/src/base/UUnicodeUtils.pas
 create mode 100644 songmanagement/src/base/UXMLSong.pas
 create mode 100644 songmanagement/src/config-darwin.inc
 create mode 100644 songmanagement/src/config-win.inc
 create mode 100644 songmanagement/src/config.inc.in
 create mode 100644 songmanagement/src/encoding/Auto.inc
 create mode 100644 songmanagement/src/encoding/CP1250.inc
 create mode 100644 songmanagement/src/encoding/CP1252.inc
 create mode 100644 songmanagement/src/encoding/Locale.inc
 create mode 100644 songmanagement/src/encoding/UTF8.inc
 create mode 100644 songmanagement/src/lib/FreeImage/FreeBitmap.pas
 create mode 100644 songmanagement/src/lib/FreeImage/FreeImage.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/JEDI-SDL-README.txt
 create mode 100644 songmanagement/src/lib/JEDI-SDL/OpenGL-Set8087CW.patch
 create mode 100644 songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/geometry.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glext.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glut.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/Readme.txt
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/libxmlparser.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/logger.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/registryuserpreferences.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdl.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdl_cpuinfo.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlgameinterface.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdli386utils.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlinput.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlstreams.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlticks.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlutils.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlwindow.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL/Pas/userpreferences.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/SDL_Image/Pas/sdl_image.pas
 create mode 100644 songmanagement/src/lib/JEDI-SDL/fpc-install.sh
 create mode 100644 songmanagement/src/lib/JEDI-SDL/jedi-sdl-64bit.patch
 create mode 100644 songmanagement/src/lib/JEDI-SDL/moduleloader-libc.patch
 create mode 100644 songmanagement/src/lib/Lua/ULua.pas
 create mode 100644 songmanagement/src/lib/SQLite/SQLite3.pas
 create mode 100644 songmanagement/src/lib/SQLite/SQLiteTable3.pas
 create mode 100644 songmanagement/src/lib/SQLite/example/Sunset.jpg
 create mode 100644 songmanagement/src/lib/SQLite/example/TestSqlite.dpr
 create mode 100644 songmanagement/src/lib/SQLite/example/TestSqlite.res
 create mode 100644 songmanagement/src/lib/SQLite/example/uTestSqlite.dfm
 create mode 100644 songmanagement/src/lib/SQLite/example/uTestSqlite.pas
 create mode 100644 songmanagement/src/lib/SQLite/readme.txt
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/License.txt
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/Readme.txt
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/TntClasses.pas
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/TntCompilers.inc
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/TntFormatStrUtils.pas
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/TntSysUtils.pas
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/TntSystem.pas
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/TntWideStrUtils.pas
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/TntWideStrings.pas
 create mode 100644 songmanagement/src/lib/TntUnicodeControls/TntWindows.pas
 create mode 100644 songmanagement/src/lib/bass/bass.chm
 create mode 100644 songmanagement/src/lib/bass/bass.txt
 create mode 100644 songmanagement/src/lib/bass/delphi/bass-macosx.patch
 create mode 100644 songmanagement/src/lib/bass/delphi/bass.pas
 create mode 100644 songmanagement/src/lib/collections/CollArray.pas
 create mode 100644 songmanagement/src/lib/collections/CollHash.pas
 create mode 100644 songmanagement/src/lib/collections/CollLibrary.pas
 create mode 100644 songmanagement/src/lib/collections/CollList.pas
 create mode 100644 songmanagement/src/lib/collections/CollPArray.pas
 create mode 100644 songmanagement/src/lib/collections/CollWrappers.pas
 create mode 100644 songmanagement/src/lib/collections/Collections.pas
 create mode 100644 songmanagement/src/lib/collections/readme.txt
 create mode 100644 songmanagement/src/lib/ctypes/ctypes.pas
 create mode 100644 songmanagement/src/lib/ffmpeg/avcodec.pas
 create mode 100644 songmanagement/src/lib/ffmpeg/avformat.pas
 create mode 100644 songmanagement/src/lib/ffmpeg/avio.pas
 create mode 100644 songmanagement/src/lib/ffmpeg/avutil.pas
 create mode 100644 songmanagement/src/lib/ffmpeg/error.pas
 create mode 100644 songmanagement/src/lib/ffmpeg/mathematics.pas
 create mode 100644 songmanagement/src/lib/ffmpeg/opt.pas
 create mode 100644 songmanagement/src/lib/ffmpeg/rational.pas
 create mode 100644 songmanagement/src/lib/ffmpeg/swscale.pas
 create mode 100644 songmanagement/src/lib/fft/UFFT.pas
 create mode 100644 songmanagement/src/lib/freetype/demo/engine-test.bdsproj
 create mode 100644 songmanagement/src/lib/freetype/demo/engine-test.dpr
 create mode 100644 songmanagement/src/lib/freetype/demo/engine-test.lpi
 create mode 100644 songmanagement/src/lib/freetype/demo/nehe/UFreeType.pas
 create mode 100644 songmanagement/src/lib/freetype/demo/nehe/lesson43.bdsproj
 create mode 100644 songmanagement/src/lib/freetype/demo/nehe/lesson43.dpr
 create mode 100644 songmanagement/src/lib/freetype/demo/nehe/readme.txt
 create mode 100644 songmanagement/src/lib/freetype/demo/switches.inc
 create mode 100644 songmanagement/src/lib/freetype/freetype.pas
 create mode 100644 songmanagement/src/lib/freetype/ftconfig.inc
 create mode 100644 songmanagement/src/lib/freetype/ftglyph.inc
 create mode 100644 songmanagement/src/lib/freetype/ftimage.inc
 create mode 100644 songmanagement/src/lib/freetype/ftoutln.inc
 create mode 100644 songmanagement/src/lib/freetype/ftstroke.inc
 create mode 100644 songmanagement/src/lib/freetype/fttypes.inc
 create mode 100644 songmanagement/src/lib/lib-info.txt
 create mode 100644 songmanagement/src/lib/libpng/png.pas
 create mode 100644 songmanagement/src/lib/midi/CIRCBUF.PAS
 create mode 100644 songmanagement/src/lib/midi/DELPHMCB.PAS
 create mode 100644 songmanagement/src/lib/midi/MIDIDEFS.PAS
 create mode 100644 songmanagement/src/lib/midi/MIDITYPE.PAS
 create mode 100644 songmanagement/src/lib/midi/MidiFile.pas
 create mode 100644 songmanagement/src/lib/midi/MidiScope.pas
 create mode 100644 songmanagement/src/lib/midi/Midicons.pas
 create mode 100644 songmanagement/src/lib/midi/Midiin.pas
 create mode 100644 songmanagement/src/lib/midi/Midiout.pas
 create mode 100644 songmanagement/src/lib/midi/demo/MidiTest.dfm
 create mode 100644 songmanagement/src/lib/midi/demo/MidiTest.pas
 create mode 100644 songmanagement/src/lib/midi/demo/Project1.dpr
 create mode 100644 songmanagement/src/lib/midi/demo/Project1.res
 create mode 100644 songmanagement/src/lib/midi/midiComp.cfg
 create mode 100644 songmanagement/src/lib/midi/midiComp.dpk
 create mode 100644 songmanagement/src/lib/midi/midiComp.res
 create mode 100644 songmanagement/src/lib/midi/readme.txt
 create mode 100644 songmanagement/src/lib/other/DirWatch.pas
 create mode 100644 songmanagement/src/lib/other/WinAllocation.pas
 create mode 100644 songmanagement/src/lib/pcre/pcre.pas
 create mode 100644 songmanagement/src/lib/portaudio/portaudio.pas
 create mode 100644 songmanagement/src/lib/portmixer/portmixer.pas
 create mode 100644 songmanagement/src/lib/projectM/cwrapper/Makefile.in
 create mode 100644 songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.cpp
 create mode 100644 songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.h
 create mode 100644 songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.sln
 create mode 100644 songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.vcproj
 create mode 100644 songmanagement/src/lib/projectM/projectM-0_9.inc
 create mode 100644 songmanagement/src/lib/projectM/projectM-1_0.inc
 create mode 100644 songmanagement/src/lib/projectM/projectM.pas
 create mode 100644 songmanagement/src/lib/requirements.txt
 create mode 100644 songmanagement/src/lib/samplerate/samplerate.pas
 create mode 100644 songmanagement/src/lib/zlib/zlib.pas
 create mode 100644 songmanagement/src/lua/UHookableEvent.pas
 create mode 100644 songmanagement/src/lua/ULuaCore.pas
 create mode 100644 songmanagement/src/lua/ULuaGl.pas
 create mode 100644 songmanagement/src/lua/ULuaLog.pas
 create mode 100644 songmanagement/src/lua/ULuaParty.pas
 create mode 100644 songmanagement/src/lua/ULuaScreenSing.pas
 create mode 100644 songmanagement/src/lua/ULuaTextGL.pas
 create mode 100644 songmanagement/src/lua/ULuaTexture.pas
 create mode 100644 songmanagement/src/lua/ULuaUsdx.pas
 create mode 100644 songmanagement/src/lua/ULuaUtils.pas
 create mode 100644 songmanagement/src/macosx/Info.plist
 create mode 100644 songmanagement/src/macosx/PseudoThread.pas
 create mode 100644 songmanagement/src/media/UAudioConverter.pas
 create mode 100644 songmanagement/src/media/UAudioCore_Bass.pas
 create mode 100644 songmanagement/src/media/UAudioCore_Portaudio.pas
 create mode 100644 songmanagement/src/media/UAudioDecoder_Bass.pas
 create mode 100644 songmanagement/src/media/UAudioDecoder_FFmpeg.pas
 create mode 100644 songmanagement/src/media/UAudioInput_Bass.pas
 create mode 100644 songmanagement/src/media/UAudioInput_Portaudio.pas
 create mode 100644 songmanagement/src/media/UAudioPlaybackBase.pas
 create mode 100644 songmanagement/src/media/UAudioPlayback_Bass.pas
 create mode 100644 songmanagement/src/media/UAudioPlayback_Portaudio.pas
 create mode 100644 songmanagement/src/media/UAudioPlayback_SDL.pas
 create mode 100644 songmanagement/src/media/UAudioPlayback_SoftMixer.pas
 create mode 100644 songmanagement/src/media/UMediaCore_FFmpeg.pas
 create mode 100644 songmanagement/src/media/UMediaCore_SDL.pas
 create mode 100644 songmanagement/src/media/UMedia_dummy.pas
 create mode 100644 songmanagement/src/media/UVideo.pas
 create mode 100644 songmanagement/src/media/UVisualizer.pas
 create mode 100644 songmanagement/src/menu/UDisplay.pas
 create mode 100644 songmanagement/src/menu/UDrawTexture.pas
 create mode 100644 songmanagement/src/menu/UMenu.pas
 create mode 100644 songmanagement/src/menu/UMenuBackground.pas
 create mode 100644 songmanagement/src/menu/UMenuBackgroundColor.pas
 create mode 100644 songmanagement/src/menu/UMenuBackgroundFade.pas
 create mode 100644 songmanagement/src/menu/UMenuBackgroundNone.pas
 create mode 100644 songmanagement/src/menu/UMenuBackgroundTexture.pas
 create mode 100644 songmanagement/src/menu/UMenuBackgroundVideo.pas
 create mode 100644 songmanagement/src/menu/UMenuButton.pas
 create mode 100644 songmanagement/src/menu/UMenuButtonCollection.pas
 create mode 100644 songmanagement/src/menu/UMenuEqualizer.pas
 create mode 100644 songmanagement/src/menu/UMenuInteract.pas
 create mode 100644 songmanagement/src/menu/UMenuSelectSlide.pas
 create mode 100644 songmanagement/src/menu/UMenuStatic.pas
 create mode 100644 songmanagement/src/menu/UMenuText.pas
 create mode 100644 songmanagement/src/screens/UScreenCredits.pas
 create mode 100644 songmanagement/src/screens/UScreenEdit.pas
 create mode 100644 songmanagement/src/screens/UScreenEditConvert.pas
 create mode 100644 songmanagement/src/screens/UScreenEditHeader.pas
 create mode 100644 songmanagement/src/screens/UScreenEditSub.pas
 create mode 100644 songmanagement/src/screens/UScreenLevel.pas
 create mode 100644 songmanagement/src/screens/UScreenLoading.pas
 create mode 100644 songmanagement/src/screens/UScreenMain.pas
 create mode 100644 songmanagement/src/screens/UScreenName.pas
 create mode 100644 songmanagement/src/screens/UScreenOpen.pas
 create mode 100644 songmanagement/src/screens/UScreenOptions.pas
 create mode 100644 songmanagement/src/screens/UScreenOptionsAdvanced.pas
 create mode 100644 songmanagement/src/screens/UScreenOptionsGame.pas
 create mode 100644 songmanagement/src/screens/UScreenOptionsGraphics.pas
 create mode 100644 songmanagement/src/screens/UScreenOptionsLyrics.pas
 create mode 100644 songmanagement/src/screens/UScreenOptionsRecord.pas
 create mode 100644 songmanagement/src/screens/UScreenOptionsSound.pas
 create mode 100644 songmanagement/src/screens/UScreenOptionsThemes.pas
 create mode 100644 songmanagement/src/screens/UScreenPartyNewRound.pas
 create mode 100644 songmanagement/src/screens/UScreenPartyOptions.pas
 create mode 100644 songmanagement/src/screens/UScreenPartyPlayer.pas
 create mode 100644 songmanagement/src/screens/UScreenPartyRounds.pas
 create mode 100644 songmanagement/src/screens/UScreenPartyScore.pas
 create mode 100644 songmanagement/src/screens/UScreenPartyWin.pas
 create mode 100644 songmanagement/src/screens/UScreenPopup.pas
 create mode 100644 songmanagement/src/screens/UScreenScore.pas
 create mode 100644 songmanagement/src/screens/UScreenSing.pas
 create mode 100644 songmanagement/src/screens/UScreenSong.pas
 create mode 100644 songmanagement/src/screens/UScreenSongJumpto.pas
 create mode 100644 songmanagement/src/screens/UScreenSongMenu.pas
 create mode 100644 songmanagement/src/screens/UScreenStatDetail.pas
 create mode 100644 songmanagement/src/screens/UScreenStatMain.pas
 create mode 100644 songmanagement/src/screens/UScreenTop5.pas
 create mode 100644 songmanagement/src/switches.inc
 create mode 100644 songmanagement/src/ultrastardx.dpr
 create mode 100644 songmanagement/test/TestPortAudioDevice.pas
 create mode 100644 songmanagement/test/TestSignAlgorithm.pas
 create mode 100644 songmanagement/test/switches.inc
 create mode 100644 songmanagement/test/test001.pas
 create mode 100644 songmanagement/test/test_libraries.lpi
 create mode 100644 songmanagement/test/test_libraries.lpr
 create mode 100644 songmanagement/test/testsqllite.pas
 create mode 100644 songmanagement/tools/ScoreConverter/ScoreConverter.dpr
 create mode 100644 songmanagement/tools/ScoreConverter/ScoreConverter.ico
 create mode 100644 songmanagement/tools/ScoreConverter/ScoreConverter.res
 create mode 100644 songmanagement/tools/ScoreConverter/UScores.pas
 create mode 100644 songmanagement/tools/ScoreConverter/USongs.pas
 create mode 100644 songmanagement/tools/ScoreConverter/Umainform.dfm
 create mode 100644 songmanagement/tools/ScoreConverter/Umainform.pas

diff --git a/songmanagement/.gitignore b/songmanagement/.gitignore
new file mode 100644
index 00000000..2223ac43
--- /dev/null
+++ b/songmanagement/.gitignore
@@ -0,0 +1,22 @@
+Thumbs.db
+.svn
+*.orig
+*.dcu
+*.ppu
+*.rst
+*.compiled
+*.or
+*.o
+*.a
+*.exe
+*.dll
+*.identcache
+*.bdsproj.local
+*.bak
+*~
+Makefile
+config.log
+config.status
+__history
+aclocal.m4
+autom4te.cache/
diff --git a/songmanagement/AUTHORS.txt b/songmanagement/AUTHORS.txt
new file mode 100644
index 00000000..21f2c27a
--- /dev/null
+++ b/songmanagement/AUTHORS.txt
@@ -0,0 +1,27 @@
+This game was introduced by Corvus5 writing most of the code by himself.
+Based on the official release 0.5.0 Mota and Whiteshark started to add small
+patches and modifications and released a package named ultra-star.dl.am Mod.
+This modification was continued at Sourceforge.net by the Ultrastar Deluxe Team:
+
+~=[ DevTeam 1.1 - Harakirioke ]=~     
+    Tobi
+    Mischi
+    Mog
+    Whiteshark
+	brunzel
+  
+~=[ Retired project developers / admins ]=~
+    Alex
+    Blindy  
+    fifth
+    Jay
+    Mota
+    Sawyer
+
+~=[ Thanks ]=~
+    Corvus5
+    Songmakers
+    CC People <3
+    Translators
+    
+And this piece of software is the result!
diff --git a/songmanagement/BuildBot.trigger b/songmanagement/BuildBot.trigger
new file mode 100644
index 00000000..be162472
--- /dev/null
+++ b/songmanagement/BuildBot.trigger
@@ -0,0 +1 @@
+4
\ No newline at end of file
diff --git a/songmanagement/COPYING.txt b/songmanagement/COPYING.txt
new file mode 100644
index 00000000..d511905c
--- /dev/null
+++ b/songmanagement/COPYING.txt
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/songmanagement/COPYRIGHT.txt b/songmanagement/COPYRIGHT.txt
new file mode 100644
index 00000000..f2a8e249
--- /dev/null
+++ b/songmanagement/COPYRIGHT.txt
@@ -0,0 +1,30 @@
+Ultrastar Deluxe
+Copyright (C) 2007-2008 by the following:
+
+If you have contributed to this project then you deserve to be on this
+list.  Contact us (see: AUTHORS) and we'll add you.
+
+Jay Binks "jaybinks"
+Dirk Dunger "blindy"
+Alexander Eckart "brunzel"
+"eddie-0815"
+Mike Gränz "mog"
+Tobias Gunkel "tobigun"
+"mota"
+Alexander S. "s_alexander"
+Karl-Michael Schindler "mischi"
+Philipp Steinhardt "whiteshark"
+
+Based on UltraStar written by:
+"Corvus5"
+
+Patches contributed by:
+"d0ccrazy"
+"elBandito07"
+"f1fth_freed0m"
+"GogolNr1"
+"jekatt"
+Benedikt Krueger
+Holger Kuhn "hawkear"
+Florian Küpper "flokuep"
+Wesley Stessens "profoX"
\ No newline at end of file
diff --git a/songmanagement/ChangeLog.GERMAN.txt b/songmanagement/ChangeLog.GERMAN.txt
new file mode 100644
index 00000000..0ad57ffd
--- /dev/null
+++ b/songmanagement/ChangeLog.GERMAN.txt
@@ -0,0 +1,350 @@
+Ultrastar Deluxe 1.1
+-----------------------------
+
+--------------
+Plattform
+--------------
+Upd: Plattformunabhängige Codebasis
+Upd: Codebasis unabhängig von der Byte-Reihenfolge
+Add: Unterstützung für Linux und FreeBSD (beide x86/x86_64)
+Add: Unterstützung für Mac OS X (Intel 10.5/10.6)
+
+--------------
+Audio
+--------------
+Upd: Audio Ausgabe und Eingabe komplett neu implementiert
+Upd: Austauschbare Audio/Video Module
+       - Bass Eingabe/Ausgabe/Dekodierung (Nur Windows)
+       - SDL Audio Ausgabe (Alle Plattformen)
+       - Portaudio Eingabe/Ausgabe (Alle Plattformen)
+       - FFmpeg Dekodierung (Alle Plattformen)
+Upd: Es können nun auch Videodateien für das #MP3 Tag verwendet werden (der erste Audiostream des Videos wird verwendet)
+Add: Mikrofon Weiterleitung (sehr experimentell)
+Fix: Ein Start ohne angeschlossenes Mikrofon führt nicht mehr zum Absturz
+Add: Hintergrundmusik
+
+--------------
+Video
+--------------
+Upd: Videodekodierung überarbeitet
+Upd: Windows: FFmpeg Version aktualisiert
+Upd: Einige Performanceverbesserungen
+
+--------------
+Interface
+--------------
+Upd: Videohintergründe für Themes
+Upd: Performance im Songscreen bei vielen Songs verbessert
+Upd: Themewechsel ohne Neustart möglich
+Upd: Neue Punkteanzeige im Singscreen (animiert)
+Upd: Score Screen umgestaltet (Animationen)
+Upd: Deluxe Theme komplett überholt (ty mog)
+Upd: Party Plugins können vor dem Spiel ausgewählt werden
+Upd: Default Skin und Color kann in Themes bzw. Skins gespeichert werden
+Add: Visualisierungen (mit projectM) als Hintergrund beim Singen
+Upd: Truetype Schriften (durch freetype) anstatt der alten Bitmap Font
+     -> Unterstützung internationale Zeichensätze
+     -> glatteres Schriftbild
+Upd: Neuer Lyrics Effekt: Shift
+Upd: Mehr als ein Songpfad kann in der config.ini (SongDirX) angegeben werden
+Upd: Mikrofon Einstellungen vereinfacht
+      - Vu-meter für einkommende Signale auf dem gewählen Eingang
+      - Anzeige für Eingangslautstärke
+      - Eingangslautstärke über '+' und '-' Tasten regelbar
+      - Anzeige für Rauschunterdrückung (grauer Balken)
+      - Rauschunterdrückung (Threshold) änderbar mit Taste 'T'
+Upd: Internationales Keyboard-Layout (einheitliche Shortcuts bei QWERTZ, QWERTY, AZERTY, ...)
+Rem: verwirrende Solmization Option entfernt
+Add: Textreflektionen für Themes
+Add: Notenlinien in den Optionen abschaltbar
+Add: Maus-Unterstützung
+Add: Texturtyp "Colorized": Textur wird über Hue-Wert (siehe HSB-Farbmodell) eingefärbt
+Add: Overlay bei aktiviertem Pause-Modus im SingScreen
+Fix: Einige "Screens=2" Bugs
+Add: Unicode support: Alle "druckbaren" Zeichen sollten nun mit den Eingabefeldern (z.B. Spielernamen) funktionieren
+Add: Fenstergröße veränderbar
+Add: Wechsel von Vollbild und Fenstermodus mit ALT+Eingabe (nur Linux und FreeBSD)
+Fix: Aktion bei Eingabe und Return (Zehnertastatur) ist nun gleich
+Add: VideoPreview in der Songauswahl
+Add: Zeitanzeige mit Taste 'T' wählbar zwischen aktueller Position, Restanzeige und Gesamtzeit
+Add: Unterstützung des Benutzers bei den Konfiguration der Mikrofone durch Fehlermeldungen, wenn Spieler mehrere oder keine Mikrofone zugewiesen wurden
+
+--------------
+Intern
+--------------
+Upd: Synchronisation von Lyrics, Video und Audio
+     (Vorher wurden die verschiedenen Timer nicht synchronisiert)
+     Es kann per config.ini ("SyncTo"-Option) gewählt werden zwischen:
+      - Lyrics und Video gegen Audio synchronisieren (Standard)
+      - Audio und Video gegen Lyrics synchronisieren
+      - keine Synchronisation
+Upd: Lua Plugin Interface anstatt des alten DLL Interfaces
+Upd: Select Objekt entfernt stattdessen wird überall Select Slide verwendet
+Upd: Verbesserte Stabilität und aufgeräumte Codebase
+Fix: Einige Fehler/Crashes im Midi/Kar-Konverter behoben
+Upd: Vista/Win7 Konformität: Konfigurationsdateien werden im Benutzerordner abgelegt. Ein Programmstart von CD/DVD sollte nun möglich sein.
+Upd: Cover-Thumbnails werden in einer SQLite Tabelle gespeichert
+     -> Verlässlicher als die alte Lösung; leichte Performance-Einbußen beim Start
+Fix: hängende Maus nach Alt-Tab durch Austausch der SDL.dll behoben
+Fix: bessere Erkennung des Endes eines Songs/Videos bei Verwendung von FFmpeg
+Upd: Windows: Benutzerdaten werden nun im Installationsordner abgelegt falls Schreibrechte darauf existieren, anderenfalls in APPDATA
+
+--------------
+Song Dateien
+--------------
+Upd: Unterstützung für UTF8
+Upd: #Encoding Tag
+      - CP1250: Mittel-/Osteuropäische Kodierung; wird standardmäßig von Corvus Ultrastar benutzt (sollte für neue Dateien nicht verwendet werden)
+      - CP1252: Westeuropäische Kodierung; wurde standardmäßig von Ultrastar Deluxe vor 1.1 benutzt (sollte für neue Dateien nicht verwendet werden)
+      - Locale: Benutzt die Systemkodierung (sollte für neue Dateien nicht verwendet werden)
+      - UTF8:   Textdatei ist in UTF8 kodiert (empfohlen)
+Upd: Sollte kein #Encoding Tag oder UTF-8 BOM in der Song Datei vorhanden sein, wird der in der config.ini
+  gewählte Standardwert der "Encoding" Option genutzt:
+  - Werte:
+    - "Auto" (Standard), "UTF8",
+    - "CP1252" (USDX<1.1 Standard), "CP1250" (alter US Standard), "Locale" (Systemkodierung)
+  - WICHTIG:
+    - "CP1252", "CP1250" und "Locale" dienen nur zur Kompatibilität mit älteren USDX und US Versionen,
+      neue Song Dateien sollten immer in UTF-8 mit BOM gespeichert werden.
+Upd: Unterstützung für UTF8 BOM (neuer Standard in Ultrastar Deluxe)
+Upd: #Year Tag wird gelesen und gespeichert
+Fix: Kein Absturz mehr, wenn kein Lyrics-Zeilenumbruch in der Datei ist
+Fix: Leere Lyrics Zeilen werden ignoriert
+Fix: Der Editor löscht beim Speichern keine unbekannten Tags mehr aus den TXT-Dateien
+
+UltraStar Deluxe 1.01a
+-----------------------------
+Fix: VideoGap funktioniert wieder mit Mpeg Videos
+Fix: Video Start wird nun richtig berechnet, wenn der Start-Tag benutzt wird
+
+UltraStar Deluxe 1.01
+-----------------------------
+Upd: Neue SDL-Lib
+Upd: Neue Bass.dll
+Upd: Video support neu geschrieben (FFMpeg anstatt SMPeg)
+     ->Fast alle Videoformate werden nun unterstützt. Bessere Synchronisation der meisten Videos.
+Upd: Theme, Skin und Farbe können ohne Neustart geändert werden
+Upd: Einige Geschwindigkeitsverbesserungen
+Upd: Backspace ist nun identisch mit ESC bei den meisten Screens
+Upd: Editor: Singlenote-playback (SHIFT + Leertaste / STRG + SHIFT + Leertaste)
+Upd: Editor: Mehr Buchstaben funktionieren nun im Texteditmodus z.B. '~'
+Upd: Deluxe-Theme verschönert.
+       - Neue Texturen für die Leiste
+       - Neue Hintergründe für die Deluxe Skins
+       - Farbe ist nun im Deluxe-Theme änderbar \o/
+Upd: Executable Name zu USdx.exe geändert
+Upd: Neue Sounds für die Menüs
+Upd: 3 neue Skins von Skar/Alajasam hinzugefügt
+Upd: TeamDuell (ähnlich Gib das Mikro weiter) Modiplugin hinzugefügt
+
+Add: Installer verfügbar
+
+Fix: 4/6 Spieler: Richtige Punktzahlen werden auf dem Scorescreen angezeigt
+Fix: Doppeltes hinzufügen der Scores bei Screens=2
+Fix: Überlappen einiger Artistennamen mit den Songname sollte nun in den meisten Fällen gefixed sein.
+Fix: License- und Readme.txt Dateien tauchen nicht mehr in der error.log auf
+Fix: Einige Sounds, (hauptsächlich der Editor 'klick'-Sound) waren zu leise
+Fix: USdx sollte nun mit Girder funktionieren
+
+UltraStar Deluxe 1.00 (by Ultrastar Deluxe Team)
+-----------------------------
+
+--------------
+Theme System
+--------------
+Upd: Neues Skin/Theme System aus Ultrastar 0.5.1
+Upd: Laden von selbsterstellten Themes ermöglicht
+Upd: Covereigenschaften in Theme.ini ausgelagert (z.B. Position)
+Upd: Optionale Coverspiegelungen hinzugefügt
+Upd: Neue Coveranordnung (Bessereres Aussehen mit vielen Songs). (Kann im Theme an und ausgeschaltet werden)
+Upd: SongScreen Equalizer Objekt hinzugefügt
+Upd: Optionale Spiegelungen zu Buttons und Statics hinzugefügt. (Reflection = 1)
+Upd: Buttons können nun im Theme zu Gruppen zusammengefasst werden.z.B. Deluxe Theme Main Menu Tools Collection.
+Upd: Buttons könen vom Theme ausgeblendet werden. z.B. für den Exit Button, oder falls Hotkeys existieren.
+Upd: Texte können nun eine Länge (w= ..) erhalten. Sie werden dann bei der gegebenen Länge umgebrochen.
+
+--------------
+Aufnahme Optionen
+--------------
+Upd: Ultrastar 0.5.2 Recording Optionen hinzugefügt
+Fix: Soundcard Einträge wurden mehrmals in die Config.Ini eingetragen
+Fix: Mehr als ein Singstaradapter sind jetzt möglich(2 Soundkarten mit dem selben Namen)
+
+--------------
+Song Screen
+--------------
+Upd: Playlist Support hinzugefügt
+
+Upd: Song Suche (mit Interface)
+Upd: Jump to Letter Hotkey
+Upd: Songscreen Menu ähnlich wie bei Singstar
+Upd: Spielernamen können nun vor dem Singen geändert werden
+Upd: Song Vorschau Lautstärke kann nun geändert werden
+Upd: Song Vorschau kann eingefadet werden
+
+--------------
+Party Modus
+--------------
+Upd: Party Modus hinzugefügt:
+       3 Teams mit bis zu 4 Spielern möglich
+       => insgesamt 12 Spieler
+Upd: Modi SDK: Party Modi können mit etwas Programmiererfahrung leicht erstellt werden.
+Upd: 4 Standard Party Modi Plugins: Duell, Hold the Line, Until 5000, Blind Mode
+
+--------------
+Effekte
+--------------
+Upd: Neue Perfect Note Effekte
+Upd: Effekt bei perfekt gesungenem Satz hinzugefügt
+Upd: Goldene Noten haben jetzt einen Singstar ähnlichen Glitzereffekt, und sind nicht mehr gelb.
+Upd: Neuer Effekt bei getroffenen Goldenen Noten
+Upd: Neuer Menü-Übergangs-Effekt: Screen verschwimmt und "fliegt aus dem Bild heraus". Neue Möglichkeiten für Theme-Ersteller
+
+--------------
+Sonstiges
+--------------
+Upd: Deluxe Theme hinzugefügt: Theme mit PS3 ähnlichem Aussehen
+Upd: Neues Score Speicherungssystem (basierend auf SQLite)
+Upd: Statistiken hinzugefügt. Generelle Statistiken und
+     Beste Scores, Beste Sänger, beliebteste Songs, beliebteste Bands
+Upd: Einige On Screen Fehler Benachrichtigungen hinzugefügt, die neuen Spielern helfen sollten.
+Upd: Neuer Erweiterter Options Screen hinzugefügt
+Upd: Abfrage vor dem Beenden hinzugefügt
+Upd: Song Hintergrundbilder können jetzt auch auf voller Bildschrimfläche dargestellt werden.
+Upd: Im Editor werden jetzt zusätzlich die richtigen Notennamen ausgegeben (C, F#, etc.)
+Upd: Neue Schriftarten
+Upd: Bessere Unterstützung für Kommandozeilen Parameter
+Fix: Nahezu keine Abstürze mehr wegen fehlerhaften TXT-Dateien.
+     In Game Popup hinzugefügt und einen Rücksprunk zum Songscreen.
+     Selbst der Partymodus wird nicht unterbrochen.
+Fix: Workaround für Cover und Hintergrund JPEG-Errors
+Fix: Videosize kann wieder geändert werden.
+Fix: Bug in LineBonus Popup behoben das zu Speicherüberläufen führen kann.
+Fix: Bug in SelectSlide behoben der zu Fehlern mit weniger als 3 optionen führen kann.
+     Automatisches Resizing hinzugefügt
+Fix: Backgrounds can be used now in option Screens, too
+Fix: Unnützer Speicherverbauch wenn ein Song mit Video abgespielt wird. Einige Videodaten blieben im Speicher nachdem der Song beendet wurde.
+     Dies könnte zu einem Out Of Memory Error führen wenn viele Songs mit Video gespielt werden.
+Fix: Einige Speichernutzungs und Ladezeit Updates
+Fix: Falsche Satzübergänge wenn T im Editor benutzt wurde und sich 2 Noten von verschiedenen
+     Sätzen überlagerten.
+Fix: Editor stürzte ab wenn die letzte Note eines Satzes gelöscht wurde.
+Fix: [Midi Converter]Noten wurden mehrmals hinzugefügt wenn eine Datei mehrmals geöffnet wurde
+                     oder der Save Button mehrmals gedrückt wurde.
+Fix: [Midi Converter]Satzübergänge werden nun vom Mide Converter automatisch berechnet.
+
+UltraStar 0.5.0 ultra-star.dl.am Mod X-Mas Edition (by Mota und Whiteshark)
+-----------------------------
+Upd: Neue schnellerer und fehlerresistenter Headereinlesefunktion
+Upd: Bewertungs Bar (Singstar Like)
+Upd: PhrasenBonus + Popups
+
+Upd: Skin verschönert
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r10 (by Mota und Whiteshark)
+-----------------------------
+Fix: Ein kleiner Bug bei der Pause Funktion wurde gefixt.
+Fix: Ein Bug im Theme System wurde behoben. (SelectSlide konnte nicht weniger als 3 Einträge enthalten.)
+Fix: Skin, Beschränkung auf 4 Skins aufgehoben
+Fix: Noten Texturen werden anders/besser eingelesen
+
+Upd: Zahlen bei der Songauswahl sind jetzt sinnvoller.
+Upd: Anzahl der Songs die eine Kategorie beinhaltet wird in der Übersicht angezeigt
+Upd: Neuer Notenskin
+
+Upd: LanguageTag + Sortierung
+Upd: Unterstützung der Covers.ini aus 0.5.1 - Für alle Sortier-Funtionen. Die alte Möglichkeit ohne die Covers.ini ist weiterhin möglich, genauso wie eine Kombination beider Methoden.
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r9 (Release by Whiteshark)
+-----------------------------
+
+Upd: BPM und VideoGap Angaben mit Punkt werden jetzt auch eingelesen. Es wird aber in diesem Fall in der Error.log eine meldung mit dem Namen des Fehlerhaften Songs ausgegeben.
+Upd: Sollte beim Einlesen eines Songs(speziell beim Header) ein Fehler auftreten wird in der Error.log der Songname + Zeile ausgegeben.
+
+Upd, Beta: Pause. P drücken und der Song wird pausiert, nocheinmal P und es kann wieder gesungen werden. Noch keine Anzeige ob Pause aktiviert wird, und noch kein Pause Menü.
+
+bekannte Probleme:
+Stellt man die Aufnahme Funktion ein, kommt es zu einem extremen CPU-Zeit verbrauch und es fängt an zu Laggen
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r8b (Release by Whiteshark)
+-----------------------------
+Fix: Random Funktionen funktionieren alle ohne Fehler
+Fix: In der Kategorieauswahl wird jetzt beim Start immer die erste Kategorie angezeigt
+Fix: Musik wird nach Kategoriewechsel korrekt abgespielt
+Fix: Richtiger Text wird jetzt nicht mehr zu falscher Musik abgespielt
+Fix: Nach Beenden eines Songs ist dieser jetzt wieder in der Übersicht angewählt
+Fix: Midi-konvertor Bug behoben (Nur Freestyle Noten anstatt Normalen)
+
+Thx to: dennisthemenace und mota für die super Bug-Reports :P
+
+Upd: doomhammers Cover sind Integriert: thx to doomhammer
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r8a (Release by Whiteshark)
+-----------------------------
+Fix: Theme System konnte nicht ausgewählt werden (workaround: Nur bis zu 4 Themes möglich)
+Fix: Richtige Kategorie wird angezeigt nach Druck von Escape
+
+Upd: Neue Random Funktionen: R + [Strg]: Random in allen Kategorien (Hier wird die Kategorie oben noch falsch angezeigt); R + [Shift]: Zufällige Kategorie
+Upd: Gerade gewählte Kategorie wird oben links in der Ecke gezeigt
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r8 (Release by Whiteshark)
+-----------------------------
+Fix: Creatorbug behoben
+Fix: Wenn Tabs=on kam es manchmal vor das der angewählte Song nicht mit dem Angezeigten übereingestimmt hat
+
+Upd: Theme System komplett
+   -Bei Start nach Themes Suchen
+   -Den ThemeOptions Screen ändern
+Upd: Neue Farben für Themes :)
+Upd: kleine änderungen am Editor
+   -Leerzeichen im Header werden automatisch korrigiert
+   -Header ist nicht mehr Case Sensitive
+
+Upd: Skin Ordner gesäubert, Es gibt jetzt 2 Skins: Motas und der Original Skin
+Upd: Ordner haben ihr eigenes Cover, welches angezeigt wird falls kein spezielles Cover vorhanden ist
+Upd: Der BewertungsText (Ultrastar, Singstar, etc.) kann jetzt übersetzt werden
+
+Upd: Falls eine Sprache nicht komplett ist werden die nicht übersetzten Texte, mit der Englischen Sprachdatei übersetzt. (Falls es zu nicht kompletten Sprachdateien kommt)
+
+Upd: neues Kategorie System:
+   -Wenn eine Kategorie angewählt wird, werden nur die enthaltenden Songs angezeigt.
+   -Mit Escape gehts zurück in die Kategorie Auswahl
+   -Mit Hoch und Runter kann die Kategorie gewechselt werden.
+
+UltraStar 0.5.0 mota patch r7 (Release by Mota)
+-----------------------------
+- Neues Notendesign.
+- versch. Neue Grafiken.
+- Neue Bewertung "Ultrastar" ab 9810 Punkte.
+- Textgröße-Bug im Editor behoben.
+
+UltraStar 0.5.0 mota patch r6 - 17.11.06 (Release by Mota)
+----------------------------------------
+- Editiorfunktionen für Goldene/Freestyle-Noten. (Tasten [G] und [F])
+- Speicherfunktion des Editors angepasst.
+- Verändertes Theme "SingStar".
+
+UltraStar 0.5.0 mota patch r5 - 16.11.06 (Release by Mota)
+----------------------------------------
+- Goldene Noten werden dargestellt
+- Zufallsauswahl verbessert
+
+UltraStar 0.5.0 mota patch r4 (Release by Mota)
+-----------------------------
+- Perfekt-Stern animation
+
+UltraStar 0.5.0 mota patch r3 (Release by Mota)
+-----------------------------
+- Sortierung Title2 und Artist2 -> Zahlen in Ordner "#"
+
+UltraStar 0.5.0 mota patch r2 (Release by Mota)
+-----------------------------
+- Eigene Cover für alle Sortierungen
+
+UltraStar 0.5.0 mota patch (Release by Mota)
+--------------------------
+- Eigene Cover für Sortierung nach Edition.
+
+UltraStar 0.5.0 (by Corvus5)
+--------------------------
+- Original Code
\ No newline at end of file
diff --git a/songmanagement/ChangeLog.txt b/songmanagement/ChangeLog.txt
new file mode 100644
index 00000000..11d6816f
--- /dev/null
+++ b/songmanagement/ChangeLog.txt
@@ -0,0 +1,341 @@
+Ultrastar Deluxe 1.1
+-----------------------------
+
+--------------
+platform
+--------------
+upd: platform independent code base
+upd: endianness independent code base
+add: Linux and FreeBSD support (x86 and x86_64)
+add: Mac OS X support (Intel 10.5/10.6)
+
+--------------
+audio
+--------------
+upd: reimplemented audio playback and input
+upd: pluggable audio/video modules
+       - Bass input/playback/decoder (windows only)
+       - SDL audio playback (all platforms)
+       - Portaudio playback/input (all platforms)
+       - FFmpeg decoder (all platforms)
+upd: video files enabled for the #MP3 tag (using the first audio stream of a video)
+add: Microphone Passthrough (experimental)
+fix: a start without a microphone plugged-in does not result in a crash
+add: background music
+
+--------------
+video
+--------------
+upd: revised video decoder implementation
+upd: windows: updated FFmpeg binary
+upd: performance improvements
+
+--------------
+interface
+--------------
+upd: video backgrounds for themes
+upd: Song Screen: performance improvements with many songs
+upd: theme change w/o restarting Ultrastar Deluxe
+upd: new score display in Sing Screen (animated)
+upd: Score Screen redesigned (animations)
+upd: Deluxe theme enhanced (ty mog)
+upd: ability to select party modes before the game
+upd: default skin and color are read from themes and skins
+add: visualisations (due to projectM) as background while singing
+upd: Truetype fonts (due to freetype6) instead of the old bitmap fonts
+     -> support for international character sets
+     -> smoother type face
+upd: new lyrics effect: Shift
+upd: more than one additional song path can be set in config.ini (SongDirX)
+upd: microphone settings simplified
+      - vu-meter for incoming signals on the selected input
+      - display of input volume
+      - adjust input volume by using '+' and '-' keys
+      - threshold display (gray bar)
+      - adjust threshold with 'T' key
+upd: international keyboard layout (uniform shortcuts on QWERTZ, QWERTY, AZERTY, ...)
+rem: removed confusing solmization option
+add: text reflections in themes
+add: note lines can be switched off in options
+add: mouse support (hardware and software)
+add: texture type "Colorized": Texture is colorized by adjusting the hue value (see HSB color model)
+add: overlay when pause modus is activated in Sing Screen
+fix: some "Screens=2" bugs
+add: Unicode support: All "printable" characters should work with the input fields (e.g. players' names)
+add: resizable window
+add: toggle between fullscreen and windowed mode with ALT+Return (Linux and FreeBSD only)
+fix: mapped same function to Return and Enter (numpad)
+add: video preview during song selection
+add: toggle displayed time with 'T' key between current position, remaining or total playback time
+add: mic configuration assistance: error messages are displayed if multiple or no mics were assigned to a player.
+
+--------------
+internal
+--------------
+upd: synchronization of lyrics, video and audio
+     (timers were not synchronized until now)
+     you can be choose via config.ini ("SyncTo" option) between:
+      - synchronize lyrics and video to audio (default)
+      - synchronize audio and video to lyrics
+      - no synchronization
+upd: DLL interface replaced by Lua plugin interface
+upd: Select Object replaced by Select Slide
+upd: improved stability and major code base cleanup
+fix: solved some bugs/crashes in Midi/Kar converter
+upd: Vista/Win7 conform: configuration files is saved in the user directory. Running USDX from CD/DVD should also be possible from now on.
+upd: cover thumbnails are saved in an SQLite database
+     ->  more reliable than the old solution; small performance loss on start
+fix: cursor freeze after Alt-Tab fixed through change of SDL.dll
+fix: better detection of ending at songs/videos while using FFmpeg
+upd: windows: user data will be placed in installation directory if user has write permissions, else it will be stored in APPDATA
+
+--------------
+song files
+--------------
+upd: UTF8 support
+upd: #Encoding tag
+      - CP1250: Central/Eastern european encoding (should not be used for new files)
+      - CP1252: Western european encoding; was used as default before 1.1 (should not be used for new files)
+      - Locale: uses system encoding (should not be used for new files!)
+      - UTF8: text file is encoded in UTF8 (recommended)
+upd: select default encoding (if #Encoding tag is missing) via the "Encoding" option in config.ini.
+  - Possible values: 
+    - "Auto" (Default), "UTF8", 
+    - "CP1252" (USDX<1.1 default), "CP1250" (old US default), "Locale" (System encoding)
+  - IMPORTANT:
+    - "CP1252", "CP1250" and "Locale" are for backward compatibility only, new files should always be encoded in UTF-8 with BOM
+upd: support for UTF8 BOM (new standard in Ultrastar Deluxe)
+upd: #Year tag is read and saved
+fix: does not crash any longer if there is no linebreak in lyrics file
+fix: blank lyrics lines are ignored
+fix: editor does not delete unknown tags any longer from song txt files
+
+UltraStar Deluxe 1.01a
+-----------------------------
+Fix: VideoGap works with mpeg again
+Fix: video start time is calculated correctly if Start-tag is used
+
+UltraStar Deluxe 1.01
+-----------------------------
+Upd: SDL-Lib update
+Upd: Bass update
+Upd: New video support (FFMpeg instead of SMPeg)
+     ->nearly all video formats are supported. Better synchronisation of most vids.
+Upd: On demand theme, skin and color changing
+Upd: Some speed improvements
+Upd: Backspace works now like ESC on most screens
+Upd: Editor: Singlenote-playback (SHIFT + Space / CTRL + SHIFT + Space)
+Upd: Editor: More characters work in text-edit-mode e.g. '~'
+Upd: Beautified Deluxe theme.
+       - New textures for the bar
+       - New backgrounds for the Deluxe skins
+       - Color is changeable in Deluxe theme now \o/
+Upd: Executable name changed to USdx.exe
+Upd: New menusounds
+Upd: Added 3 new skins by Skar/Alajasam
+Upd: Added TeamDuell modi-plugin
+
+Add: Installer available
+
+Fix: 4/6 Players: Scores are shown correctly on the scorescreen
+Fix: Double adding of Highscores if screens=2
+Fix: Overlapping of some artists names with songs should be fixed in most cases
+Fix: License and Readme files caused error messages in error.log
+Fix: Some sounds, (mainly the editors 'click' sound) were to quiet
+Fix: Should now work with Girder
+
+UltraStar Deluxe 1.00 (by Ultrastar Deluxe Team)
+-----------------------------
+
+--------------
+Theme System
+--------------
+Upd: New Ultrastar 0.5.1 Skin/Theme Sytem
+Upd: Add ability to 0.5.1 System to load third party Themes to add usability
+Upd: Add ability to change Positions and some other things relating to Covers within the Theme
+Upd: Add ability to add reflections to the Covers
+Upd: New Method for displaying Covers in a Circle. Looks better with many Songs. (Turn Off On within the Theme)
+Upd: Add Equalizer Object to SongScreen
+Upd: Add ability to add reflection to Buttons and Statics (Reflection = 1)
+Upd: Add ability to Group Buttons to a Buttonmenu, see Deluxe Theme Main Menu Tools Collection
+Upd: Add ability to Hide Buttons within Theme. Useful for example for Mainscreen Exit Button
+Upd: Add ability to give Texts a Width, so the Text breaks at the given Position.
+
+--------------
+Recording Options
+--------------
+Upd: Ultrastar 0.5.2 Recording Options added
+Fix: Write Soundcards more then one Time to Ini
+Fix: Use of more then one SingStar Mic. adapter now Possible(2 Soundcards with same Name Patch)
+
+--------------
+Song Screen
+--------------
+Upd: Added Playlist Support
+
+Upd: Song Search (with Screen interface)
+Upd: Jump to Letter Hotkey
+Upd: Menu in Songscreen similar to Singstars
+Upd: Ability to change Playernames before singing
+Upd: Ability to change Song Preview Volume
+Upd: Song Preview Fade in
+
+--------------
+Party Mode
+--------------
+Upd: Added Party Mode:
+       3 Teams possible with up to 4 Players
+       => total of 12 Players
+Upd: Modi SDK: Possibility to create nearly any Modi with some Programming Skill
+Upd: 4 Custom Party Modi Plugins: Duell, Hold the Line, Until 5000, Blind Mode
+
+--------------
+Effects
+--------------
+Upd: New Perfect Note Effects
+Upd: Add Perfect Sentence Effect
+Upd: Golden Notes now with Singstar like Star Twinkle Effect, instead of just Yellow coloring
+Upd: Add Effect: Golden notes "Glow" when they are hit
+Upd: New Screen Fading Effect: Screen Blurs and "Flys" out of the Screen
+     looks better with every Background. More possibility for Theme Creators
+
+--------------
+Other
+--------------
+Upd: Added Deluxe Theme: Theme that has a look similiar to PS3 Singstar.
+Upd: New Score Saving System (SQLite Based)
+Upd: Statistic Screen with general Statistics and some Tables:
+     Best Scores, Best Singers, Most Popular Songs, Most Popular Bands
+Upd: Add some on Screen Error Messages helping new Peoples
+Upd: Add Advanced Screen with some new Options.
+Upd: Add a Question PopUp before exiting
+Upd: Add ability to scale Background Images in Singscreen to Fullsize
+Upd: Show real Note in Editor (C, F#, etc.)
+Upd: New fonts added
+Upd: Add better support for Command-Line Parameters
+Fix: No crashes caused by corrupted Textfiles anymore.
+     Added inGame Errormessage Popup and Jump Back to Songscreen. So even the Party Mode,
+     isn't interuppted.
+Fix: Workaround for Cover and BG JPG Errors
+Fix: Videosize can now be changed again
+Fix: Bug in LineBonus Popup that can end up in a Memory Overflow
+Fix: Bug in SelectSlide with less then 3 Options, No Overlapping anymore. Automatic resizing
+Fix: Backgrounds can be used now in option Screens, too
+Fix: useless Memory usement when Song with Video is Played. When a Song with Video is played
+     there was some Memory that was not freeed at the End of the Song. This could have caused
+     too much Memory usement when many Songs with Video are Played.
+Fix: Some Changes in Memory usement and better Loading speed.
+Fix: Wrong Timings pressing T in Editor if 2 Notes from different Sentences overlap
+Fix: Editor crashes when last note of a sentence is deleted
+Fix: [Midi Converter]Notes are added more than once when a File is opened twice or the save                      button is pressed multiple times.
+Fix: [Midi Converter]Sentence Timings are calculated automaticly when Midi File is converted
+
+UltraStar 0.5.0 ultra-star.dl.am Mod X-Mas Edition (by Mota und Whiteshark)
+-----------------------------
+Upd: New faster and Error resistant Header reader
+Upd: Bewertungs Bar (Singstar Like)
+Upd: LineBonus + Popups
+
+Upd: Skin beautified
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r10 (by Mota und Whiteshark)
+-----------------------------
+Fix: Minor Bug in Pause Method fixed.
+Fix: Fixed a Bug in Theme System
+Fix: New Note Texture Reading
+
+Upd: Numbers in SongSelection are now more meaningful
+Upd: Show Count of Songs in Category in Category Overview
+Upd: New Note Texture
+
+Upd: LanguageTag + Sorting
+Upd: Support for the Covers.ini from 0.5.1 - for all sorting options. The old behaviour without Covers.ini is also possible, just as well as a combination of both methods.
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r9 (Release by Whiteshark)
+-----------------------------
+
+Upd: BPM and VideoGap Can now be read, too. But there will be an Errormessage in Error.log
+
+Upd, Beta: Pause. Press P and the Song will be paused, press P again and it will be continued. Pause Display and Menu missing.
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r8b (Release by Whiteshark)
+-----------------------------
+Fix: Random Methods now work without Errors
+Fix: First Category is now shown at Startup.
+Fix: Music is played correctly after categorychange
+Fix: No wrong MP3 playing anymore
+Fix: After exit Singing Mode the Song is chossen in Song Screen
+Fix: Midi-konvertor Bug (Only Freestyle Notes instead of normal)
+
+Thx to: dennisthemenace and mota for Bug-Reports :P
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r8a (Release by Whiteshark)
+-----------------------------
+Fix: Themes could not be Selected (workaround: Only 4 Themes possible)
+Fix: Correct category is displayed after pressing Escape
+
+Upd: new Random functions: R + [Strg]: Random in all Categorys;
+                           R + [Shift]: Random Category
+Upd: Chossen Category is displayed in the top left
+
+UltraStar 0.5.0 ultra-star.dl.am Mod r8 (Release by Whiteshark)
+-----------------------------
+Fix: Creatorbug fixed
+Fix: Tabs=on Preview Bug
+
+Upd: Theme System ready
+   -Look for Themes at Startup
+   -ThemeOptions Screen working
+Upd: New Theme Colors :)
+Upd: Little changes at Editor
+   -Spaces in Header are corrected automaticaly
+   -Header is not Case Sensitive anymore
+
+Upd: Skin Folder Cleaned up, There are 2 Skins now: Motas and the Original Skin
+Upd: Categorys have their own noCover Image
+Upd: Rating Text (Ultrastar, Singstar, etc.) can now be Translated
+
+Upd: Inomplete Languages are corrected with Entrys from the English Language File
+
+Upd: new Category System:
+   -If a category is choosen only the Songs from this category are shown
+   -Press Escape to leave a category
+   -Press up or down to change the category.
+
+UltraStar 0.5.0 mota patch r7 (Release by Mota)
+-----------------------------
+- New Note Texture.
+- other new grafics.
+- New rating "Ultrastar" with more than 9810 Points.
+- Textsize-Bug in editor fixed.
+
+UltraStar 0.5.0 mota patch r6 - 17.11.06 (Release by Mota)
+----------------------------------------
+- Editiorfunctions for Golden/Freestyle-Notes. (Press [G] or [F])
+- Saving Methods of Editor changed
+- Changed Theme "SingStar".
+
+UltraStar 0.5.0 mota patch r5 - 16.11.06 (Release by Mota)
+----------------------------------------
+- Goldene Notes are displayed
+- Randomizing improved
+
+UltraStar 0.5.0 mota patch r4 (Release by Mota)
+-----------------------------
+- Perfect-Star animation
+
+UltraStar 0.5.0 mota patch r3 (Release by Mota)
+-----------------------------
+- Sorting Title2 and Artist2 -> Numbers in Category "#"
+
+UltraStar 0.5.0 mota patch r2 (Release by Mota)
+-----------------------------
+- Cover for all Categorys and Sortings can be choosen
+
+UltraStar 0.5.0 mota patch (Release by Mota)
+--------------------------
+- Cover for Edition sorting can be choosen
+
+UltraStar 0.5.0 (by Corvus5)
+--------------------------
+- Original Code
diff --git a/songmanagement/DisplayChanges.patch b/songmanagement/DisplayChanges.patch
new file mode 100644
index 00000000..9cb00a18
--- /dev/null
+++ b/songmanagement/DisplayChanges.patch
@@ -0,0 +1,88 @@
+Index: src/menu/UDisplay.pas
+===================================================================
+--- src/menu/UDisplay.pas	(revision 1702)
++++ src/menu/UDisplay.pas	(working copy)
+@@ -42,8 +42,65 @@
+   SysUtils;
+ 
+ type
++  { this is a effect for screen fade that in fact does nothing
++    and should be used as parent for new fade effect.
++    It will also be used if fading is disabled }
++  TFadeEffect = class
++    private
++
++    public
++      constructor Create;
++
++      { this procedure is called when a screen change starts }
++      procedure StartFade;
++
++      { this function is called during a screen change, before screen
++        is drawn. screenchange is finished if this function returns
++        true. DoFadePostDraw will be called in every case after this
++        function was called, but fading will be finished regardless
++        what is returned DoFadePostDraw.}
++      function DoFadePreDraw: Boolean;
++
++      { this function is called during a screen change, after screen
++        was drawn. screenchange is finished if this function returns
++        true. }
++      function DoFadePostDraw: Boolean;
++
++
++
++      destructor Destroy;
++  end;
++
++  { class representing a kind of screen that is drawn over
++    one or more other screens. it has focus before the
++    screens that it is overlaying }
++  TOverlay = class(TMenu);
++
+   TDisplay = class
+     private
++      FadeInProgress: Boolean;
++      CurrentMenu: TMenu;
++
++      FadeEffect: TFadeEffect;
++    public
++      constructor Create(Caption: String);
++
++      { changes displayed screen, starts fading }
++      procedure ChangeMenu(NewScreen: TMenu);
++      property Menu: TMenu read CurrentMenu write ChangeMenu;
++
++
++
++
++
++      { calls draw procedures of Screen and overlays, it
++        returns false if application should be closed }
++      function Draw: Boolean;
++
++      destructor Destroy;
++
++  {TDisplay = class
++    private
+       //fade-to-black-hack
+       BlackScreen: boolean;
+ 
+@@ -53,7 +110,7 @@
+       LastFadeTime:  cardinal; // last fade update time
+ 
+       FadeTex:       array[1..2] of GLuint;
+- 
++
+       FPSCounter:    cardinal;
+       LastFPS:       cardinal;
+       NextFPSSwap:   cardinal;
+@@ -78,7 +135,7 @@
+       procedure SaveScreenShot;
+ 
+       function  Draw: boolean;
+-  end;
++  end; }
+ 
+ var
+   Display:          TDisplay;
diff --git a/songmanagement/Makefile.in b/songmanagement/Makefile.in
new file mode 100644
index 00000000..7e9450a6
--- /dev/null
+++ b/songmanagement/Makefile.in
@@ -0,0 +1,473 @@
+#################################################
+# @PACKAGE_STRING@
+# @configure_input@
+#################################################
+
+@SET_MAKE@
+SHELL = /bin/sh
+
+#################################################
+# Standard definitions
+#################################################
+
+prefix      ?= @prefix@
+exec_prefix ?= @exec_prefix@
+bindir      ?= @bindir@
+datarootdir ?= @datarootdir@
+datadir     ?= @datadir@
+libdir      ?= @libdir@
+docdir      ?= @docdir@
+pdfdir      ?= @pdfdir@
+mandir      ?= @mandir@
+# project root-dir (directory of configure script)
+top_srcdir  ?= @top_srcdir@
+# project src-dir (directory of the current Makefile)
+srcdir      ?= @srcdir@
+
+# file-type suffix of executables (e.g. ".exe" in windows)
+EXEEXT ?= @EXEEXT@
+
+#################################################
+# Tools
+#################################################
+
+# recursive dir creation tool (mkdir -p)
+MKDIR        ?= @MKDIR_P@
+RM           ?= rm -f
+RM_REC       ?= $(RM) -r
+
+# install tool
+INSTALL         ?= @INSTALL@
+INSTALL_DATA    ?= @INSTALL_DATA@
+INSTALL_PROGRAM ?= @INSTALL_PROGRAM@
+
+#################################################
+# General package configuration
+#################################################
+
+USDX_PACKAGE_NAME := @PACKAGE_NAME@
+USDX_VERSION := @PACKAGE_VERSION@
+USDX_TARNAME := @PACKAGE_TARNAME@
+
+#################################################
+# USDX Paths
+#################################################
+
+USDX_SRC_DIR   := $(top_srcdir)/src
+USDX_GAME_DIR  := $(top_srcdir)/game
+USDX_TOOLS_DIR := $(top_srcdir)/tools
+USDX_BUILD_DIR := $(top_srcdir)/build
+USDX_LIB_DIR   := $(USDX_SRC_DIR)/lib
+
+INSTALL_DATADIR := $(datadir)/$(USDX_PACKAGE_NAME)
+
+#################################################
+# Binary name
+#################################################
+
+# name of executable
+USDX_BIN_NAME ?= ultrastardx$(EXEEXT)
+USDX_BIN := $(USDX_GAME_DIR)/$(USDX_BIN_NAME)
+
+#################################################
+# ProjectM
+#################################################
+
+PROJECTM_CWRAPPER_DIR := $(USDX_LIB_DIR)/projectM/cwrapper
+USE_PROJECTM_CWRAPPER = @USE_PROJECTM_CWRAPPER@
+
+#################################################
+# Dependencies
+#################################################
+
+DEPS :=
+ifeq ($(USE_PROJECTM_CWRAPPER), yes)
+DEPS += $(PROJECTM_CWRAPPER_DIR)
+endif
+
+#################################################
+# general targets
+#################################################
+
+##
+# IMPORTANT:
+# Always assure that this Makefile still works with the -jN 
+# parameter set. This is important as Gentoo uses parallel 
+# make (-j2) by default.
+# If parallel execution is enabled you cannot rely on a 
+# specific order the prerequisites are build. 
+#
+# Example:
+#   target: dependency dependant
+#
+# will first build "dependency" and "dependant" afterwards with a
+# sequential execution (-j1). With parallel execution "dependant"
+# might be started before "dependency" is finished and make will
+# crash.
+#
+# If it is not possible, add the virtual .NOTPARALLEL target.
+# This will disable parallel execution for ALL targets.
+##
+
+BUILD_TARGETS = all debug release rebuild build
+.PHONY: $(BUILD_TARGETS)
+$(BUILD_TARGETS): all-deps
+	$(MAKE) -C $(USDX_SRC_DIR) $@
+
+.PHONY: all-deps
+all-deps:
+	@for dir in $(DEPS); do \
+	  $(MAKE) -C "$$dir" all; \
+	done
+
+.PHONY: clean
+clean: clean-src clean-deps
+
+.PHONY: clean-src
+clean-src:
+	$(MAKE) -C $(USDX_SRC_DIR) clean
+
+.PHONY: clean-deps
+clean-deps:
+	@for dir in $(DEPS); do \
+	  $(MAKE) -C "$$dir" clean; \
+	done
+
+.PHONY: clean-game
+clean-game:
+	$(RM) $(USDX_GAME_DIR)/*.log
+	$(RM) $(USDX_GAME_DIR)/*.db
+	$(RM) $(USDX_GAME_DIR)/*.ini
+	-rmdir $(USDX_GAME_DIR)/screenshots
+	-rmdir $(USDX_GAME_DIR)/playlists
+	-rmdir $(USDX_GAME_DIR)/songs
+
+# just clean the game build data but no dependencies (libs, tools, ...)
+.PHONY: mostlyclean
+mostlyclean: clean-src
+
+.PHONY: distclean
+distclean: clean clean-game
+	$(RM) config.log config.status aclocal.m4 
+	$(RM_REC) autom4te.cache
+	$(RM) $(USDX_SRC_DIR)/config.inc 
+	$(RM) $(srcdir)/Makefile $(USDX_SRC_DIR)/Makefile $(PROJECTM_CWRAPPER_DIR)/Makefile
+
+.PHONY: maintainer-clean
+maintainer-clean: distclean
+
+# remove temporary and backup files
+.PHONY: tidy
+tidy:
+# FPC stuff
+	find $(srcdir) -name "*.compiled" | xargs $(RM)
+# Delphi stuff
+	find $(srcdir) -name "__history" | xargs $(RM_REC)
+	find $(srcdir) -name "*.identcache" -o -name "*.dcu" | xargs $(RM)
+# Backup files
+	find $(srcdir) -name "*~" -o -name "*.bak" -o -name "*.orig" | xargs $(RM)
+
+
+#################################################
+# auto-update
+#################################################
+
+Makefile: $(srcdir)/Makefile.in $(USDX_SRC_DIR)/Makefile.in $(USDX_SRC_DIR)/config.inc.in $(PROJECTM_CWRAPPER_DIR)/Makefile.in config.status
+	@echo "-----------------------------------"
+	@echo "Performing reconfiguration..."
+	./config.status
+	@echo "-----------------------------------"
+
+config.status: configure
+	./config.status --recheck
+
+.PHONY: reconf
+reconf:
+	./autogen.sh
+
+#################################################
+# install/uninstall
+#################################################
+
+##
+# For information on directory and install conventions see
+#   "info autoconf", Section 4.8.2. Installation Directory Variables
+#                    Section 4.8.1, 4.8.3 and 4.8.4 
+# Notes:
+# - "make install" must not rebuild, so do not depend on all.
+# - use the DESTDIR variable as prefix for installation directories, 
+#   otherwise Gentoo will not be able to install as it uses a sandbox.
+##
+
+.PHONY: install
+install: install-all
+	@echo "--------------------------------"
+	@echo "$(USDX_PACKAGE_NAME) installed."
+	@echo "Start with: $(bindir)/$(USDX_BIN_NAME)"
+	@echo "--------------------------------"
+
+# strip binaries during install
+install-strip:
+	$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
+                install
+
+.PHONY: install-all
+install-all: install-exec install-plugins install-data
+
+.PHONY: install-exec
+install-exec:
+	$(MKDIR) "$(DESTDIR)$(bindir)"
+	$(INSTALL_PROGRAM) "$(USDX_BIN)" "$(DESTDIR)$(bindir)"
+
+# FPC target platform and processor
+PPLATFORM  := @FPC_PLATFORM@
+PPROCESSOR := @FPC_PROCESSOR@
+
+.PHONY: install-plugins
+install-plugins:
+	$(MKDIR) "$(DESTDIR)$(INSTALL_DATADIR)/plugins"
+	$(INSTALL) "$(USDX_GAME_DIR)/plugins"/* "$(DESTDIR)$(INSTALL_DATADIR)/plugins"
+
+.PHONY: install-data
+install-data:
+	$(MAKE) RECURSIVE_SRC_DIR="$(USDX_GAME_DIR)/languages" \
+            RECURSIVE_DST_DIR="$(DESTDIR)$(INSTALL_DATADIR)/languages" \
+            install-data-recursive
+	$(MAKE) RECURSIVE_SRC_DIR="$(USDX_GAME_DIR)/sounds" \
+            RECURSIVE_DST_DIR="$(DESTDIR)$(INSTALL_DATADIR)/sounds" \
+            install-data-recursive
+	$(MAKE) RECURSIVE_SRC_DIR="$(USDX_GAME_DIR)/themes" \
+            RECURSIVE_DST_DIR="$(DESTDIR)$(INSTALL_DATADIR)/themes" \
+            install-data-recursive
+	$(MAKE) RECURSIVE_SRC_DIR="$(USDX_GAME_DIR)/fonts" \
+            RECURSIVE_DST_DIR="$(DESTDIR)$(INSTALL_DATADIR)/fonts" \
+            install-data-recursive
+	$(MAKE) RECURSIVE_SRC_DIR="$(USDX_GAME_DIR)/resources" \
+            RECURSIVE_DST_DIR="$(DESTDIR)$(INSTALL_DATADIR)/resources" \
+            install-data-recursive
+	$(INSTALL_DATA) "COPYING.txt" "$(DESTDIR)$(INSTALL_DATADIR)/COPYING.txt"
+
+.PHONY: install-data-recursive
+install-data-recursive:
+# Note: the project contains filesnames with whitespace 
+	$(MKDIR) "$(RECURSIVE_DST_DIR)"
+	@for file in "$(RECURSIVE_SRC_DIR)"/*; do \
+	  if test -f "$$file"; then \
+	    filename=`basename "$$file"`; \
+	    echo "$(INSTALL_DATA) \"$$file\" \"$(RECURSIVE_DST_DIR)/$$filename\""; \
+	    $(INSTALL_DATA) "$$file" "$(RECURSIVE_DST_DIR)/$$filename" || exit 1; \
+	  fi; \
+	  if test -d "$$file"; then \
+	    subdir="$$file"; \
+	    subdirname=`basename "$$subdir"`; \
+	    $(MAKE) RECURSIVE_SRC_DIR="$$subdir" \
+	            RECURSIVE_DST_DIR="$(RECURSIVE_DST_DIR)/$$subdirname" \
+	            install-data-recursive || exit 1; \
+	  fi; \
+	done
+
+.PHONY: uninstall
+uninstall: uninstall-all
+
+.PHONY: uninstall-all
+uninstall-all: uninstall-data uninstall-exec uninstall-plugins
+
+.PHONY: uninstall-data
+uninstall-data:
+	$(RM_REC) "$(DESTDIR)$(INSTALL_DATADIR)/languages"
+	$(RM_REC) "$(DESTDIR)$(INSTALL_DATADIR)/sounds"
+	$(RM_REC) "$(DESTDIR)$(INSTALL_DATADIR)/themes"
+	$(RM_REC) "$(DESTDIR)$(INSTALL_DATADIR)/fonts"
+	$(RM_REC) "$(DESTDIR)$(INSTALL_DATADIR)/resources"
+	$(RM)     "$(DESTDIR)$(INSTALL_DATADIR)/COPYING.txt"
+	-rmdir "$(DESTDIR)$(INSTALL_DATADIR)"
+
+.PHONY: uninstall-exec
+uninstall-exec:
+	$(RM) "$(DESTDIR)$(bindir)/$(USDX_BIN_NAME)"
+
+.PHONY: uninstall-plugins
+uninstall-plugins:
+	$(RM_REC) "$(DESTDIR)$(INSTALL_DATADIR)/plugins"
+
+#################################################
+# Distributable source-package (TODO)
+#################################################
+
+#disttmpdir := $(USDX_PACKAGE_NAME)-$(USDX_VERSION)-src
+disttmpdir := $(USDX_PACKAGE_NAME)-1.1_alpha-src
+# choose all files in SVN that are not deleted
+svn-files := svn status -v | grep -v "^[?D]" | cut -c8- | tr -s " " | cut -f5- -d" "
+
+.PHONY: dist
+dist:
+	@$(svn-files) | while read FILE; do \
+	  if test -d "$$FILE"; then \
+	    echo "MKDIR: $(disttmpdir)/$$FILE"; \
+	    $(MKDIR) "$(disttmpdir)/$$FILE" || exit 1; \
+	  else \
+	    echo "COPY:  $$FILE"; \
+	    cp "$$FILE" "$(disttmpdir)/$$FILE" || exit 1; \
+	  fi; \
+	done
+	tar cvf $(disttmpdir).tar $(disttmpdir)
+	gzip $(disttmpdir).tar
+	$(RM_REC) $(disttmpdir)
+
+#################################################
+# Debian package
+#################################################
+
+debpkgdir    ?= dists/debian
+debpkgtmpdir := $(debpkgdir)/deb-package
+debpkgprefix := $(USDX_PACKAGE_NAME)
+debpkgname   := $(debpkgprefix)_$(USDX_VERSION)_$(PPROCESSOR).deb
+
+.PHONY: deb
+deb: all
+	$(RM_REC) $(debpkgtmpdir)
+
+	$(MKDIR) $(debpkgdir)
+	$(MKDIR) $(debpkgtmpdir)/DEBIAN
+
+	$(MAKE) DESTDIR=$(debpkgtmpdir)/ install-all
+
+	$(INSTALL_DATA) $(debpkgdir)/$(debpkgprefix).control $(debpkgtmpdir)/DEBIAN/control
+
+	dpkg-deb --build $(debpkgtmpdir)
+	mv $(debpkgtmpdir)/../deb-package.deb $(debpkgdir)/$(debpkgname)
+
+	$(RM_REC) $(debpkgtmpdir)
+
+#################################################
+# RPM (TODO)
+#################################################
+
+.PHONY: rpm
+rpm: all
+	@echo "Coming soon"
+
+
+#################################################
+# Mac OS X defines
+#################################################
+
+# otool: Mac OS X object file displaying tool
+OTOOL := /usr/bin/otool 
+# install_name_tool: Mac OS X tool to change dynamic shared library install names
+INSTALL_NAME_TOOL := /usr/bin/install_name_tool
+# hdiutil: Mac OS X disk image tool
+HDIUTIL := /usr/bin/hdiutil
+# finkLibDir := path for libraries installed using fink
+finkLibDir := /sw/lib
+
+#################################################
+# Mac OS X app-bundle
+#################################################
+
+macosx_bundle_path := UltraStarDeluxe.app/Contents
+.PHONY: macosx-app
+macosx-app: all 
+# Create double clickable Mac OS X application.
+
+	@echo ""
+	@echo "Creating the Mac OS X application"
+	@echo ""
+
+	$(MKDIR) $(macosx_bundle_path)
+
+# Put the icon file into its particular place. 
+# Must be done BEFORE info.plist is created.
+	$(MKDIR) $(macosx_bundle_path)/resources
+	$(INSTALL_DATA) icons/ultrastardx.icns $(macosx_bundle_path)/resources/
+
+# the info.plist file
+	$(INSTALL_DATA) $(USDX_SRC_DIR)/macosx/Info.plist $(macosx_bundle_path)/
+
+# Copy the resources. 
+	$(MAKE) install-all INSTALL_DATADIR=$(macosx_bundle_path) bindir=$(macosx_bundle_path)/MacOS
+
+# Copy the lua plugins. 
+	$(MAKE) install-plugins INSTALL_DATADIR=$(macosx_bundle_path) bindir=$(macosx_bundle_path)/MacOS
+
+# Create the song directory. 
+	$(MKDIR) $(macosx_bundle_path)/songs
+
+# final messages
+	@echo ""
+	@echo "Mac OS X application created."
+	@echo "Please report issues to the developer team, preferably mischi."
+	@echo "Have fun."
+	@echo ""
+
+.PHONY: macosx-standalone-app
+macosx-standalone-app: macosx-app 
+# Create double clickable standalone (does not need fink) Mac OS X 
+# application. Not fully test, but should work on 10.5.
+
+	@echo ""
+	@echo "Creating the standalone Mac OS X application"
+	@echo ""
+
+# copy the dylib and change its install names
+
+define install_osx_libraries
+    $(shell $(INSTALL) -m 755 $(dylib) $(macosx_bundle_path)/MacOS)
+    $(shell $(INSTALL_NAME_TOOL) -change $(dylib) @executable_path/$(notdir $(dylib)) $(macosx_bundle_path)/MacOS/ultrastardx)
+    $(shell $(INSTALL_NAME_TOOL) -id @executable_path/$(notdir $(dylib)) $(macosx_bundle_path)/MacOS/$(notdir $(dylib)))
+    $(foreach linked_dylibs_2,$(shell $(OTOOL) -L $(dylib) | grep version | cut -f 1 -d ' ' | grep -v \/System\/Library | grep -v \usr\/lib | grep -v executable_path),$(rename_secondary_osx_libraries))
+endef
+
+define rename_secondary_osx_libraries
+    $(shell $(INSTALL_NAME_TOOL) -change $(linked_dylibs_2) @executable_path/$(notdir $(linked_dylibs_2)) $(macosx_bundle_path)/MacOS/$(notdir $(dylib)))
+endef
+
+# work on the dylibs in $(macosx_bundle_path)/MacOS/ultrastardx
+	$(foreach dylib,$(shell $(OTOOL) -L $(macosx_bundle_path)/MacOS/ultrastardx | grep version | cut -f 1 -d ' ' | grep -v \/System\/Library | grep -v \/usr\/lib),$(install_osx_libraries))
+
+# work on the secondary dylibs from ffmpeg
+# libavcodec references all tertiary libraries of the ffmpeg libs
+	$(foreach dylib,$(shell $(OTOOL) -L $(finkLibDir)/libavcodec.dylib   | grep version | cut -f 1 -d ' ' | grep -v \/System\/Library | grep -v \/usr\/lib),$(install_osx_libraries))
+# same procedure in libfaac. it gets libgnugetopt
+	$(foreach dylib,$(shell $(OTOOL) -L $(finkLibDir)/libfaac.dylib      | grep version | cut -f 1 -d ' ' | grep -v \/System\/Library | grep -v \/usr\/lib),$(install_osx_libraries))
+
+# same procedure for tertiary libs in SDL_image
+	$(foreach dylib,$(shell $(OTOOL) -L $(finkLibDir)/libSDL_image.dylib | grep version | cut -f 1 -d ' ' | grep -v \/System\/Library | grep -v \/usr\/lib),$(install_osx_libraries))
+
+# X11 libs as well, because users may not have installed it on 10.4
+	$(foreach dylib,$(shell $(OTOOL) -L /usr/X11R6/lib/libX11.dylib  | grep version | cut -f 1 -d ' ' | grep -v \/System\/Library | grep -v \/usr\/lib),$(install_osx_libraries))
+
+# libpcre.dylib must be installed extra, since it is not linked to the executable but opened using dlopen
+	$(shell $(INSTALL) -m 755 $(finkLibDir)/libpcre.dylib $(macosx_bundle_path)/MacOS)
+	$(shell $(INSTALL_NAME_TOOL) -change $(finkLibDir)/libpcre.dylib @executable_path/libpcre.dylib $(macosx_bundle_path)/MacOS/libpcre.dylib)
+	$(shell $(INSTALL_NAME_TOOL) -id @executable_path/libpcre.dylib $(macosx_bundle_path)/MacOS/libpcre.dylib)
+
+# final messages
+	@echo "Standalone Mac OS X application created."
+	@echo ""
+
+.PHONY: macosx-dmg
+macosx-dmg: macosx-standalone-app
+	$(RM) UltraStarDeluxe.dmg
+	$(RM) UltraStarDeluxe.sparseimage
+	$(HDIUTIL) create -type SPARSE -size 100m -fs HFS+ -volname UltraStarDeluxe -ov UltraStarDeluxe.sparseimage
+	$(HDIUTIL) attach UltraStarDeluxe.sparseimage
+	/bin/cp -R UltraStarDeluxe.app /Volumes/UltraStarDeluxe
+#	/bin/cp ultrastardx/icons/UltraStarDeluxeVolumeIcon.icns /Volumes/UltraStarDeluxe/.VolumeIcon.icns
+#	/Developer/Tools/SetFile -a C /Volumes/UltraStarDeluxe/.VolumeIcon.icns /Volumes/UltraStarDeluxe
+	$(HDIUTIL) detach /Volumes/UltraStarDeluxe
+	$(HDIUTIL) convert UltraStarDeluxe.sparseimage -format UDBZ -o UltraStarDeluxe.dmg
+	$(RM) UltraStarDeluxe.sparseimage
+
+# remove Mac OS X apllication bundle and disk image
+.PHONY: clean-macosx
+clean-macosx: clean-macosx-app clean-macosx-dmg
+
+.PHONY: clean-macosx-app
+clean-macosx-app:
+	$(RM_REC) UltraStarDeluxe.app 
+
+.PHONY: clean-macosx-dmg
+clean-macosx-dmg:
+	$(RM) UltraStarDeluxe.dmg 
+	$(RM) UltraStarDeluxe.sparseimage
diff --git a/songmanagement/README Mac OS X b/songmanagement/README Mac OS X
new file mode 100644
index 00000000..2bc83908
--- /dev/null
+++ b/songmanagement/README Mac OS X	
@@ -0,0 +1,47 @@
+UltraStar Deluxe Mac Specific README
+------------------------------------
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8 - -
+                   _______  _________
+            ___   /       \/         \_______
+           /   \  \      _/    /\____/       \__________
+          /   _/  /     / \______             \         \___    _____
+         /   |___/      \     \_/             /          \  \  /     \
+         \              /\                   /   |\       \  \/      /
+          \            /  \_ultrastardeluxe_/    |/       /         /
+           \______www_/                 |____________org_/          \
+                                                      /      /\  ~=~ \
+                                                      \_____/  \ mog /
+                                                                 ~=~
+- - 8<- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ ============================
+= 1. Installation            =
+= 2. Song Folders            =
+ ============================
+
+SF.Net Page: http://sourceforge.net/projects/ultrastardx/
+Wiki:        http://wiki.ultrastardeluxe.org/
+
+ ====================
+ = 1. Installation  =
+ ====================
+
+Drag the application to your hard disk. It should run from any folder.
+
+ ====================
+ = 2. Song Folders  =
+ ====================
+
+- The primary folder for songs is "$HOME/Music/UltraStar Deluxe", which is
+  created when UltraStar Deluxe is run for the first time.
+
+- Further folders can be added through the configuration file "config.ini",
+  which is created in "$HOME/Library/Application Support/UltraStarDeluxe" 
+  when UltraStar Deluxe is run for the first time.
+  
+  example:
+  [Directories]
+  SongDir1=/Users/My/Music/MyUSDXSongs
+  SongDir2=/Volumes/MyExternalUSBDisk
+  SongDir...=... (some more directories)
diff --git a/songmanagement/README.txt b/songmanagement/README.txt
new file mode 100644
index 00000000..f6fc65cb
--- /dev/null
+++ b/songmanagement/README.txt
@@ -0,0 +1,146 @@
+UltraStar Deluxe 1.0 README
+----------------------------
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8 - -
+                   _______  _________
+            ___   /       \/         \_______
+           /   \  \      _/    /\____/       \__________
+          /   _/  /     / \______             \         \___    _____
+         /   |___/      \     \_/             /          \  \  /     \
+         \              /\                   /   |\       \  \/      /
+          \            /  \_ultrastardeluxe_/    |/       /         /
+           \______www_/                 |____________org_/          \
+                                                      /      /\  ~=~ \
+                                                      \_____/  \ mog /
+                                                                 ~=~
+- - 8<- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ ============================
+= 1. About                   =
+= 2. Release Notes           =
+= 3. Command-Line Parameters =
+= 4. Controls                =
+ ============================
+
+SF.Net Page: http://sourceforge.net/projects/ultrastardx/
+Wiki:        http://wiki.ultrastardeluxe.org/
+
+ ====================
+ = 1. About         =
+ ====================
+
+UltraStar Deluxe (USDX) is a free and open source karaoke game.  It allows
+up to six players to sing along with music using microphones in order to
+score points, depending on the pitch of the voice and the rhythm of
+singing.
+
+UltraStar Deluxe is a fork of the original UltraStar (developed by corvus5).
+Many features have been added like party mode, theme support and support
+for more audio and video formats.
+The improved stability and code quality of USDX enabled ports to Linux and
+Mac OS X.
+
+ ====================
+ = 2. Release Notes =
+ ====================
+
+- To set additional song directories change your config.ini like this:
+  [Directories]
+  SongDir1=C:\Users\My\Music\MyUSDXSongs
+  SongDir2=F:\EvenMoreUSDXSongs
+  SongDir...=... (some more directories)
+
+- To take a screenshot press "PrintScreen" key.
+  Screenshots are saved in the directory "Screenshots".
+
+- To enable joypad support change config.ini:
+
+  [Controller]
+  Joypad=Off
+
+  to
+
+  [Controller]
+  Joypad=On
+
+- To Enable 4 to 6 player mode 2 screens are needed.
+  Disable the full screen mode, extend your desktop horizontally and set
+  the resolution to fill one screen.
+  Add to Config.ini:
+  [Graphics]
+  Screens=2
+
+- Press Alt + F[1..12] in NameScreen to save the name of a player
+  Press F[1..12] to load the name of a player
+
+- To enable benchmark run the game with -benchmark parameter
+
+
+ ==============================
+ = 3. Command-Line Parameters =
+ ==============================
+
+Command-line parameters are passed to the game adding it to the path of a
+shortcut or starting the game within the console.
+
+The following parameters are possible. They can be joined in any possible way.
+
+- Benchmark         : Create a benchmark.log file with start timings.
+
+- NoLog    	    : Do not create any .log files
+
+- Joypad            : Start with joypad support
+
+- Language [ID]     : Load language [ID] on startup.
+                      Example: -Language german
+
+- Songpath [Path]   : Same as config Songpath.
+                      Example: -SongPath "C:\Ultrastar Songs"
+
+- ConfigFile [File] : Load configuration file [File] instead of config.ini.
+                      The path to the file has to exist.
+                      Example: -ConfigFile config.SongCreation.ini
+
+- ScoreFile [File]  : Use [File] instead of Ultrastar.db
+                      The path to the file has to exist.
+                      Example: -ScoreFile HouseParty.db
+
+- FullScreen        : Start the game in full screen mode
+
+- Depth [16/32]     : Force depth to 16 or 32. Example: -Depth 16
+
+- Resolution [ID]   : Force resolution. Example: -Resolution 800x600
+
+- Screens [1/2]     : Force 1 or 2 screens. Example: -Screens 2
+
+Some Examples:
+
+Start with a resolution of 1024x768, a depth of 32 bit and in full screen
+mode:
+ultrastar.exe -Resolution 1024x768 -Depth 32 -Fullscreen
+
+Start without logging and with polish language
+ultrastar.exe -NoLog -Language polish
+
+Start with a customs configuration file and score database:
+ultrastar.exe -ConfigFile C:\Ultrastar\Configs\PartyConfig.ini -ScoreFile C:\Ultrastar\Scores\PartyScores.db
+
+
+ ===============
+ = 4. Controls =
+ ===============
+
+[J]      to open the "Search for a Song" interface
+[Cursor] to navigate through the screens.
+[Enter]  to confirm
+[Escape] to go to the previous screen.
+
+Songscreen
+[R],
+  [Shift] + [R],
+  [Strg]  + [R]            select a random song/category
+[Alt] + [Letter]           jump to a artist with the first letter [Letter]
+[Alt] + [Shift] + [Letter] jump to a title with the first letter [Letter]
+
+
+Editor controls are described in documentation.pdf
diff --git a/songmanagement/RELEASEBLOCKERS.txt b/songmanagement/RELEASEBLOCKERS.txt
new file mode 100644
index 00000000..a2006b91
--- /dev/null
+++ b/songmanagement/RELEASEBLOCKERS.txt
@@ -0,0 +1,11 @@
+Blockers for the outstanding 1.1 release
+if you want to help us then start at this tasks
+
+Microfone playback (still experimental, will not be fixed in 1.1)
+- buffers have to be adjusted
+  - this may be done automatically (prefer this!)
+  - or at least the user has to manually adjust this
+- there may be other problems as due to the missing buffer adjustment there were no extensive tests
+
+There are also assembla tickets that need to be fixed
+http://www.assembla.com/spaces/usdx/milestones/26192-UltraStar-Deluxe-1-1-Release
\ No newline at end of file
diff --git a/songmanagement/autogen.sh b/songmanagement/autogen.sh
new file mode 100755
index 00000000..8f551bff
--- /dev/null
+++ b/songmanagement/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+AUTOGEN_DIR=dists/autogen
+aclocal -I ${AUTOGEN_DIR}/m4 && autoconf
diff --git a/songmanagement/build/.gitignore b/songmanagement/build/.gitignore
new file mode 100644
index 00000000..caf367b0
--- /dev/null
+++ b/songmanagement/build/.gitignore
@@ -0,0 +1 @@
+*.res
diff --git a/songmanagement/build/delphi-win/.gitignore b/songmanagement/build/delphi-win/.gitignore
new file mode 100644
index 00000000..59424db9
--- /dev/null
+++ b/songmanagement/build/delphi-win/.gitignore
@@ -0,0 +1 @@
+# don't delete this file as it prevents git from removing this directory
diff --git a/songmanagement/configure b/songmanagement/configure
new file mode 100755
index 00000000..8805524a
--- /dev/null
+++ b/songmanagement/configure
@@ -0,0 +1,7495 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.65 for ultrastardx 1.1.
+#
+# Report bugs to <http://sourceforge.net/tracker/?group_id=191560&atid=937872>.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  # We cannot yet assume a decent shell, so we have to provide a
+	# neutralization value for shells without unset; and this also
+	# works around shells that cannot unset nonexistent variables.
+	BASH_ENV=/dev/null
+	ENV=/dev/null
+	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+	export CONFIG_SHELL
+	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: http://sourceforge.net/tracker/?group_id=191560&atid=937872
+$0: about your system, including any error possibly output
+$0: before this message. Then install a modern shell, or
+$0: manually run the script under such a shell if you do
+$0: have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='ultrastardx'
+PACKAGE_TARNAME='ultrastardx'
+PACKAGE_VERSION='1.1'
+PACKAGE_STRING='ultrastardx 1.1'
+PACKAGE_BUGREPORT='http://sourceforge.net/tracker/?group_id=191560&atid=937872'
+PACKAGE_URL=''
+
+ac_unique_file="src/ultrastardx.dpr"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+DEFINE_HAVE_PORTMIXER
+libpcre_LIBDIR
+DEFINE_HAVE_LIBPCRE
+libpcre_VERSION_INT
+libpcre_VERSION_RELEASE
+libpcre_VERSION_MINOR
+libpcre_VERSION_MAJOR
+libpcre_VERSION
+DEFINE_HAVE_PORTAUDIO
+portaudio_VERSION_INT
+portaudio_VERSION_RELEASE
+portaudio_VERSION_MINOR
+portaudio_VERSION_MAJOR
+portaudio_VERSION
+USE_PROJECTM_CWRAPPER
+libprojectM_DATADIR
+libprojectM_INCLUDEDIR
+DEFINE_HAVE_PROJECTM
+libprojectM_VERSION_INT
+libprojectM_VERSION_RELEASE
+libprojectM_VERSION_MINOR
+libprojectM_VERSION_MAJOR
+libprojectM_VERSION
+DEFINE_HAVE_SWSCALE
+libswscale_VERSION_INT
+libswscale_VERSION_RELEASE
+libswscale_VERSION_MINOR
+libswscale_VERSION_MAJOR
+libswscale_VERSION
+DEFINE_HAVE_FFMPEG
+libavutil_VERSION_INT
+libavutil_VERSION_RELEASE
+libavutil_VERSION_MINOR
+libavutil_VERSION_MAJOR
+libavutil_VERSION
+libavformat_VERSION_INT
+libavformat_VERSION_RELEASE
+libavformat_VERSION_MINOR
+libavformat_VERSION_MAJOR
+libavformat_VERSION
+libavcodec_VERSION_INT
+libavcodec_VERSION_RELEASE
+libavcodec_VERSION_MINOR
+libavcodec_VERSION_MAJOR
+libavcodec_VERSION
+lua_LIB_NAME
+libpng_VERSION_INT
+libpng_VERSION_RELEASE
+libpng_VERSION_MINOR
+libpng_VERSION_MAJOR
+libpng_VERSION
+DARWIN_VERSION
+MACOSX_VERSION
+MACOSX_VERSION_INT
+MACOSX_VERSION_RELEASE
+MACOSX_VERSION_MINOR
+MACOSX_VERSION_MAJOR
+PKG_CONFIG
+RANLIB
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+FPC_UNIT_PATH
+FPC_BASE_PATH
+FPC_PREFIX
+FPC_TARGET
+FPC_CPROCESSOR
+FPC_CPLATFORM
+FPC_PROCESSOR
+FPC_PLATFORM
+FPC_VERSION
+FPC_VERSION_INT
+FPC_VERSION_RELEASE
+FPC_VERSION_MINOR
+FPC_VERSION_MAJOR
+FPCMAKE
+PPC
+PFLAGS_EXTRA
+PFLAGS_RELEASE
+PFLAGS_DEBUG
+PFLAGS_BASE
+PFLAGS
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+ENABLE_DEBUG
+GREP
+SED
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+MKDIR_P
+LN_S
+SET_MAKE
+PACKAGE_IRC
+PACKAGE_WEBSITE
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_cfg_dummy1
+with_portmixer
+with_libprojectM
+with_cfg_dummy2
+enable_global
+enable_local
+enable_debug
+enable_dummy_fpc1
+with_fpc
+enable_verbose
+enable_gprof
+enable_valgrind
+enable_heaptrace
+enable_rangechecks
+enable_noexecstack
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+PFLAGS
+PFLAGS_BASE
+PFLAGS_DEBUG
+PFLAGS_RELEASE
+PFLAGS_EXTRA
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+PKG_CONFIG
+libpng_VERSION
+libavcodec_VERSION
+libavformat_VERSION
+libavutil_VERSION
+libswscale_VERSION
+libprojectM_VERSION
+libprojectM_INCLUDEDIR
+libprojectM_DATADIR
+portaudio_VERSION
+libpcre_VERSION
+libpcre_LIBDIR'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information."
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures ultrastardx 1.1 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/ultrastardx]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of ultrastardx 1.1:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features and Packages:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+
+External Libraries:
+  --with-portmixer        enable portmixer audio-mixer support [default=check]
+  --with-libprojectM      enable projectM visualization support [default=no]
+
+Development options:
+  --enable-global         (DEPRECATED, DO NOT USE)
+  --enable-local          (DEPRECATED, DO NOT USE)
+  --enable-debug          Enable debug build [default=no]
+
+Free Pascal Compiler specific options:
+  --with-fpc=DIR          Directory of the FPC executable [PATH]
+  --disable-verbose       Disable verbose compiler output [default=no]
+  --enable-gprof          Enable profiling with gprof [default=no]
+  --enable-valgrind       Enable debugging with valgrind [default=no]
+  --enable-heaptrace      Enable heaptrace (memory corruption detection)
+                          [default=no]
+  --enable-rangechecks    Enables range-checks [default=no]
+  --disable-noexecstack   Allow executable stacks [default=no]
+
+Some influential environment variables:
+  PFLAGS      Free Pascal Compiler flags (replaces all other flags)
+  PFLAGS_BASE Free Pascal Compiler base flags, e.g. -Si
+  PFLAGS_DEBUG
+              Free Pascal Compiler debug flags, e.g. -gl
+  PFLAGS_RELEASE
+              Free Pascal Compiler release flags, e.g. -O2
+  PFLAGS_EXTRA
+              Free Pascal Compiler additional flags
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  PKG_CONFIG  path to pkg-config utility
+  libpng_VERSION
+              version of libpng, overriding pkg-config
+  libavcodec_VERSION
+              version of libavcodec, overriding pkg-config
+  libavformat_VERSION
+              version of libavformat, overriding pkg-config
+  libavutil_VERSION
+              version of libavutil, overriding pkg-config
+  libswscale_VERSION
+              version of libswscale, overriding pkg-config
+  libprojectM_VERSION
+              version of libprojectM, overriding pkg-config
+  libprojectM_INCLUDEDIR
+              C-Header include-dir (e.g. /usr/include), overriding pkg-config
+  libprojectM_DATADIR
+              projectM data-directory for presets etc. (e.g.
+              /usr/share/projectM), overriding pkg-config
+  portaudio_VERSION
+              version of portaudio, overriding pkg-config
+  libpcre_VERSION
+              version of libpcre, overriding pkg-config
+  libpcre_LIBDIR
+              library dir (e.g. /usr/lib, /sw/lib, ...), overriding pkg-config
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <http://sourceforge.net/tracker/?group_id=191560&atid=937872>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+ultrastardx configure 1.1
+generated by GNU Autoconf 2.65
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by ultrastardx $as_me 1.1, which was
+generated by GNU Autoconf 2.65.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# specify the website here
+PACKAGE_WEBSITE="http://www.ultrastardeluxe.org/"
+
+# specify the IRC-channel here
+PACKAGE_IRC="#ultrastardx at quakenet.org"
+
+
+# Specify a source-file so autoconf can check if the source-dir exists
+
+
+# Set the path to install-sh
+ac_aux_dir=
+for ac_dir in dists/autogen "$srcdir"/dists/autogen; do
+  for ac_t in install-sh install.sh shtool; do
+    if test -f "$ac_dir/$ac_t"; then
+      ac_aux_dir=$ac_dir
+      ac_install_sh="$ac_aux_dir/$ac_t -c"
+      break 2
+    fi
+  done
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error "cannot find install-sh, install.sh, or shtool in dists/autogen \"$srcdir\"/dists/autogen" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+
+# show features and packages in one list
+
+
+
+
+# -----------------------------------------
+# find tools
+# -----------------------------------------
+
+# options for make command
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# find tool for ln -s (e.g. uses cp -p for FAT-filesystems)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find a program for recursive dir creation
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  test -d ./--version && rmdir ./--version
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+# find the best install tool
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# some other useful tools
+#AC_PROG_AWK
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if test "${ac_cv_path_SED+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+#AC_PROG_EGREP
+
+# -----------------------------------------
+# macro declarations
+# -----------------------------------------
+
+# AC_SUBST_DEFINE(DEFINE_SUFFIX, IS_DEFINED)
+# used to enable/disable pascal defines
+
+
+# -----------------------------------------
+# define switches
+# -----------------------------------------
+
+# print library options header
+
+# Check whether --with-cfg-dummy1 was given.
+if test "${with_cfg_dummy1+set}" = set; then :
+  withval=$with_cfg_dummy1;
+fi
+
+
+# add portmixer option
+
+# Check whether --with-portmixer was given.
+if test "${with_portmixer+set}" = set; then :
+  withval=$with_portmixer; with_portmixer=$withval
+else
+  with_portmixer="check"
+fi
+
+
+# add projectM option
+
+# Check whether --with-libprojectM was given.
+if test "${with_libprojectM+set}" = set; then :
+  withval=$with_libprojectM; with_libprojectM=$withval
+else
+  with_libprojectM="no"
+fi
+
+
+# print misc options header
+
+# Check whether --with-cfg-dummy2 was given.
+if test "${with_cfg_dummy2+set}" = set; then :
+  withval=$with_cfg_dummy2;
+fi
+
+
+# add DEPRECATED global and local options
+# Check whether --enable-global was given.
+if test "${enable_global+set}" = set; then :
+  enableval=$enable_global;
+fi
+
+# Check whether --enable-local was given.
+if test "${enable_local+set}" = set; then :
+  enableval=$enable_local;
+fi
+
+
+if [ x$enable_global != x -o x$enable_local != x ]; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}:
+
+!!! NOTE: --enable-global and --enable-local are deprecated:
+!!! - global build: just type \"make\" and \"make install\"
+!!! - local  build: just type \"make\" and start \"game/ultrastardx\"
+" >&5
+$as_echo "$as_me:
+
+!!! NOTE: --enable-global and --enable-local are deprecated:
+!!! - global build: just type \"make\" and \"make install\"
+!!! - local  build: just type \"make\" and start \"game/ultrastardx\"
+" >&6;}
+   sleep 2
+fi
+
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then :
+  enableval=$enable_debug; test $enableval = "yes" && ENABLE_DEBUG="yes"
+fi
+
+
+
+# -----------------------------------------
+# check for compilers
+# -----------------------------------------
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+# find and test the freepascal compiler
+# sets PFLAGS, FPC_VERSION, FPC_DEBUG, etc.
+
+
+##
+# User PFLAGS
+##
+
+
+
+
+
+
+
+##
+# Compiler options
+##
+
+# Check whether --enable-dummy_fpc1 was given.
+if test "${enable_dummy_fpc1+set}" = set; then :
+  enableval=$enable_dummy_fpc1;
+fi
+
+
+# fpc path
+
+# Check whether --with-fpc was given.
+if test "${with_fpc+set}" = set; then :
+  withval=$with_fpc; PPC_PATH=$withval
+fi
+
+
+# verbose
+# Check whether --enable-verbose was given.
+if test "${enable_verbose+set}" = set; then :
+  enableval=$enable_verbose; test x$enableval = xno && PFLAGS_EXTRA="$PFLAGS_EXTRA -v0Bew"
+fi
+
+
+# gprof
+# Check whether --enable-gprof was given.
+if test "${enable_gprof+set}" = set; then :
+  enableval=$enable_gprof; test x$enableval = xyes && PFLAGS_EXTRA="$PFLAGS_EXTRA -pg"
+fi
+
+
+# valgrind
+# Check whether --enable-valgrind was given.
+if test "${enable_valgrind+set}" = set; then :
+  enableval=$enable_valgrind; test x$enableval = xyes && PFLAGS_EXTRA="$PFLAGS_EXTRA -gv"
+fi
+
+
+# heaptrace
+# Check whether --enable-heaptrace was given.
+if test "${enable_heaptrace+set}" = set; then :
+  enableval=$enable_heaptrace; test x$enableval = xyes && PFLAGS_EXTRA="$PFLAGS_EXTRA -gh"
+fi
+
+
+# range-checks
+# Check whether --enable-rangechecks was given.
+if test "${enable_rangechecks+set}" = set; then :
+  enableval=$enable_rangechecks; test x$enableval = xyes && PFLAGS_EXTRA="$PFLAGS_EXTRA -Crtoi"
+fi
+
+
+# allow execstack (see noexecstack compiler check below)
+# Check whether --enable-noexecstack was given.
+if test "${enable_noexecstack+set}" = set; then :
+  enableval=$enable_noexecstack;
+else
+  enable_noexecstack="yes"
+fi
+
+
+###
+# Find compiler executable
+###
+
+PPC_CHECK_PROGS="fpc FPC ppc386 ppc PPC386"
+
+if test -z "$PPC_PATH"; then
+    PPC_PATH=$PATH
+    for ac_prog in $PPC_CHECK_PROGS
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_PPC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$PPC"; then
+  ac_cv_prog_PPC="$PPC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_PPC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+PPC=$ac_cv_prog_PPC
+if test -n "$PPC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PPC" >&5
+$as_echo "$PPC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$PPC" && break
+done
+
+    for ac_prog in fpcmake
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_FPCMAKE+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$FPCMAKE"; then
+  ac_cv_prog_FPCMAKE="$FPCMAKE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_FPCMAKE="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+FPCMAKE=$ac_cv_prog_FPCMAKE
+if test -n "$FPCMAKE"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FPCMAKE" >&5
+$as_echo "$FPCMAKE" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$FPCMAKE" && break
+done
+
+else
+    for ac_prog in $PPC_CHECK_PROGS
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_PPC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PPC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PPC="$PPC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PPC_PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PPC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PPC=$ac_cv_path_PPC
+if test -n "$PPC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PPC" >&5
+$as_echo "$PPC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$PPC" && break
+done
+
+    for ac_prog in fpcmake
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_FPCMAKE+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $FPCMAKE in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_FPCMAKE="$FPCMAKE" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PPC_PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_FPCMAKE="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+FPCMAKE=$ac_cv_path_FPCMAKE
+if test -n "$FPCMAKE"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FPCMAKE" >&5
+$as_echo "$FPCMAKE" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$FPCMAKE" && break
+done
+
+fi
+if test -z "$PPC"; then
+    as_fn_error "no Free Pascal Compiler found in $PPC_PATH" "$LINENO" 5
+fi
+
+###
+# Get the FPC compiler info
+###
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking version of fpc" >&5
+$as_echo_n "checking version of fpc... " >&6; }
+FPC_VERSION=`${PPC} -iV`
+
+    version=$FPC_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    FPC_VERSION_MAJOR=$(($major))
+    FPC_VERSION_MINOR=$(($minor))
+    FPC_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    FPC_VERSION_INT=$(($FPC_VERSION_MAJOR*1000000+$FPC_VERSION_MINOR*1000+$FPC_VERSION_RELEASE))
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: [$FPC_VERSION]" >&5
+$as_echo "[$FPC_VERSION]" >&6; }
+
+FPC_PLATFORM=`${PPC} -iTO`
+FPC_PROCESSOR=`${PPC} -iTP`
+FPC_CPLATFORM=`${PPC} -iSO`
+FPC_CPROCESSOR=`${PPC} -iSP`
+
+FPC_TARGET=${FPC_PROCESSOR}-${FPC_PLATFORM}
+
+
+
+
+
+
+
+
+###
+# Get paths
+###
+
+if test "x$prefix" != xNONE; then
+    FPC_PREFIX=$prefix
+else
+    FPC_PREFIX=$ac_default_prefix
+fi
+
+FPC_BASE_PATH="${FPC_PREFIX}/lib/fpc/${FPC_VERSION}"
+FPC_UNIT_PATH="${FPC_BASE_PATH}/units/${FPC_TARGET}"
+
+
+
+
+
+###
+# Compiler checks
+###
+
+SIMPLE_PROGRAM="program foo; begin writeln; end."
+
+# Check if FPC works and can compile a program
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Free Pascal Compiler works" >&5
+$as_echo_n "checking whether the Free Pascal Compiler works... " >&6; }
+if test "${ac_cv_prog_ppc_works+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+
+    # create test file
+    rm -f conftest*
+    echo "$SIMPLE_PROGRAM" > conftest.pp
+
+    # compile test file
+    ${PPC}  conftest.pp >> config.log 2>&1
+
+    # check if test file was compiled
+    if test -f conftest || test -f conftest.exe; then
+        ac_cv_prog_ppc_works="yes"
+    else
+        ac_cv_prog_ppc_works="no"
+    fi
+
+    # remove test file
+    rm -f conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_ppc_works" >&5
+$as_echo "$ac_cv_prog_ppc_works" >&6; }
+if test x$ac_cv_prog_ppc_works = xno; then
+    as_fn_error "installation or configuration problem: Cannot create executables." "$LINENO" 5
+fi
+
+# Check if FPC can link with standard libraries
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Free Pascal Compiler can link" >&5
+$as_echo_n "checking whether the Free Pascal Compiler can link... " >&6; }
+if test "${ac_cv_prog_ppc_links+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+
+    # create test file
+    rm -f conftest*
+    echo "program foo; uses crt; begin writeln; end.
+    " > conftest.pp
+
+    # compile test file
+    ${PPC}  conftest.pp >> config.log 2>&1
+
+    # check if test file was compiled
+    if test -f conftest || test -f conftest.exe; then
+        ac_cv_prog_ppc_links="yes"
+    else
+        ac_cv_prog_ppc_links="no"
+    fi
+
+    # remove test file
+    rm -f conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_ppc_links" >&5
+$as_echo "$ac_cv_prog_ppc_links" >&6; }
+if test x$ac_cv_prog_ppc_links = xno; then
+    as_fn_error "installation or configuration problem: Cannot link with some standard libraries." "$LINENO" 5
+fi
+
+# Check whether FPC's linker knows "-z noexecstack"
+# FPC does not set the NX-flag on stack memory. Binaries generated with FPC
+# might crash on platforms that require the stack to be non-executable.
+# So we will try to find a workaround here.
+# See http://bugs.freepascal.org/view.php?id=11563
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether FPC supports -k\"-z noexecstack\"" >&5
+$as_echo_n "checking whether FPC supports -k\"-z noexecstack\"... " >&6; }
+if test "${ac_cv_prog_ppc_noexecstack+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+
+    # create test file
+    rm -f conftest*
+    echo "$SIMPLE_PROGRAM" > conftest.pp
+
+    # compile test file
+    ${PPC} -k"-z noexecstack" conftest.pp >> config.log 2>&1
+
+    # check if test file was compiled
+    if test -f conftest || test -f conftest.exe; then
+        ac_cv_prog_ppc_noexecstack="yes"
+    else
+        ac_cv_prog_ppc_noexecstack="no"
+    fi
+
+    # remove test file
+    rm -f conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_ppc_noexecstack" >&5
+$as_echo "$ac_cv_prog_ppc_noexecstack" >&6; }
+if test x$enable_noexecstack = xyes; then
+    if test x$ac_cv_prog_ppc_noexecstack = xyes; then
+        PFLAGS_EXTRA="$PFLAGS_EXTRA -k\"-z noexecstack\""
+    fi
+fi
+
+# Finally substitute PFLAGS
+
+# set unset PFLAGS_XYZ vars to $(PFLAGS_XYZ_DEFAULT)
+# so the Makefile can define default values to it.
+true ${PFLAGS:=\$(PFLAGS_DEFAULT)}
+true ${PFLAGS_BASE:=\$(PFLAGS_BASE_DEFAULT)}
+true ${PFLAGS_EXTRA:=\$(PFLAGS_EXTRA_DEFAULT)}
+true ${PFLAGS_DEBUG:=\$(PFLAGS_DEBUG_DEFAULT)}
+true ${PFLAGS_RELEASE:=\$(PFLAGS_RELEASE_DEFAULT)}
+
+
+
+
+
+
+
+
+
+# find and test the C compiler (for C-libs and wrappers)
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "C compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# find and test the C++ compiler (for C-libs and wrappers)
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+# find pkg-config
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=0.9.0
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		PKG_CONFIG=""
+	fi
+
+fi
+if [ x$PKG_CONFIG = x ]; then
+   as_fn_error "
+!!! pkg-config was not found on your system.
+!!! It is needed to determine the versions of your libraries.
+!!! Install it and try again." "$LINENO" 5
+fi
+
+
+# -----------------------------------------
+# check for OS
+# -----------------------------------------
+
+if test x$FPC_PLATFORM = xdarwin; then
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Mac OS X version" >&5
+$as_echo_n "checking for Mac OS X version... " >&6; }
+    MACOSX_VERSION=`sw_vers -productVersion`
+
+    version=$MACOSX_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    MACOSX_VERSION_MAJOR=$(($major))
+    MACOSX_VERSION_MINOR=$(($minor))
+    MACOSX_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    MACOSX_VERSION_INT=$(($MACOSX_VERSION_MAJOR*1000000+$MACOSX_VERSION_MINOR*1000+$MACOSX_VERSION_RELEASE))
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$MACOSX_VERSION]" >&5
+$as_echo "[$MACOSX_VERSION]" >&6; }
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Darwin version" >&5
+$as_echo_n "checking for Darwin version... " >&6; }
+    DARWIN_VERSION=`uname -r | cut -f1 -d.`
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$DARWIN_VERSION]" >&5
+$as_echo "[$DARWIN_VERSION]" >&6; }
+
+
+fi
+
+# -----------------------------------------
+# check for libraries
+# -----------------------------------------
+
+# find libpng
+# pkgconfig name for 1.2 is "libpng12", for 1.4 "libpng"
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libpng12" >&5
+$as_echo_n "checking for libpng12... " >&6; }
+    if test x"$with_libpng" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_libpng" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng12\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libpng12") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            libpng_LIBS=`$PKG_CONFIG --libs --silence-errors "libpng12"`
+            libpng_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "libpng12"`
+            libpng_LIBDIRS=`
+    echo "$libpng_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$libpng_LIBDIRS"; then
+                LIBS="$LIBS $libpng_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        libpng_HAVE="yes"
+        if test -n "$libpng_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libpng_LIBDIRS)" >&5
+$as_echo "yes ($libpng_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        libpng_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xno = xyes -o x"$with_libpng" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libpng12"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-libpng=nocheck and the environment
+variables libpng_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+if [ x$libpng_HAVE = xyes ]; then
+
+    if test x$libpng_HAVE = xyes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of libpng" >&5
+$as_echo_n "checking version of libpng... " >&6; }
+
+
+    # check if variable was defined by the user
+    if test -z "$libpng_VERSION"; then
+        # if not, get it from pkg-config
+        if test x$libpng_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng12\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libpng12") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libpng_VERSION=`$PKG_CONFIG --modversion --silence-errors "libpng12"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libpng12"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libpng=nocheck is defined the environment variable
+libpng_VERSION
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$libpng_VERSION]" >&5
+$as_echo "[$libpng_VERSION]" >&6; }
+    else
+        libpng_VERSION="0.0.0"
+    fi
+
+    version=$libpng_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    libpng_VERSION_MAJOR=$(($major))
+    libpng_VERSION_MINOR=$(($minor))
+    libpng_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    libpng_VERSION_INT=$(($libpng_VERSION_MAJOR*1000000+$libpng_VERSION_MINOR*1000+$libpng_VERSION_RELEASE))
+
+
+
+
+
+
+
+else
+    # check for the generic .pc file
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libpng >= 1.2" >&5
+$as_echo_n "checking for libpng >= 1.2... " >&6; }
+    if test x"$with_libpng" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_libpng" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng >= 1.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libpng >= 1.2") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            libpng_LIBS=`$PKG_CONFIG --libs --silence-errors "libpng >= 1.2"`
+            libpng_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "libpng >= 1.2"`
+            libpng_LIBDIRS=`
+    echo "$libpng_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$libpng_LIBDIRS"; then
+                LIBS="$LIBS $libpng_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        libpng_HAVE="yes"
+        if test -n "$libpng_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libpng_LIBDIRS)" >&5
+$as_echo "yes ($libpng_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        libpng_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xyes = xyes -o x"$with_libpng" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libpng >= 1.2"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-libpng=nocheck and the environment
+variables libpng_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+    if test x$libpng_HAVE = xyes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of libpng" >&5
+$as_echo_n "checking version of libpng... " >&6; }
+
+
+    # check if variable was defined by the user
+    if test -z "$libpng_VERSION"; then
+        # if not, get it from pkg-config
+        if test x$libpng_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng >= 1.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libpng >= 1.2") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libpng_VERSION=`$PKG_CONFIG --modversion --silence-errors "libpng >= 1.2"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libpng >= 1.2"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libpng=nocheck is defined the environment variable
+libpng_VERSION
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$libpng_VERSION]" >&5
+$as_echo "[$libpng_VERSION]" >&6; }
+    else
+        libpng_VERSION="0.0.0"
+    fi
+
+    version=$libpng_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    libpng_VERSION_MAJOR=$(($major))
+    libpng_VERSION_MINOR=$(($minor))
+    libpng_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    libpng_VERSION_INT=$(($libpng_VERSION_MAJOR*1000000+$libpng_VERSION_MINOR*1000+$libpng_VERSION_RELEASE))
+
+
+
+
+
+
+
+fi
+
+# find sdl
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sdl" >&5
+$as_echo_n "checking for sdl... " >&6; }
+    if test x"$with_sdl" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_sdl" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            sdl_LIBS=`$PKG_CONFIG --libs --silence-errors "sdl"`
+            sdl_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "sdl"`
+            sdl_LIBDIRS=`
+    echo "$sdl_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$sdl_LIBDIRS"; then
+                LIBS="$LIBS $sdl_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        sdl_HAVE="yes"
+        if test -n "$sdl_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($sdl_LIBDIRS)" >&5
+$as_echo "yes ($sdl_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        sdl_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xyes = xyes -o x"$with_sdl" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "sdl"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-sdl=nocheck and the environment
+variables sdl_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+# find freetype
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype2" >&5
+$as_echo_n "checking for freetype2... " >&6; }
+    if test x"$with_freetype" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_freetype" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"freetype2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "freetype2") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            freetype_LIBS=`$PKG_CONFIG --libs --silence-errors "freetype2"`
+            freetype_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "freetype2"`
+            freetype_LIBDIRS=`
+    echo "$freetype_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$freetype_LIBDIRS"; then
+                LIBS="$LIBS $freetype_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        freetype_HAVE="yes"
+        if test -n "$freetype_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($freetype_LIBDIRS)" >&5
+$as_echo "yes ($freetype_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        freetype_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xyes = xyes -o x"$with_freetype" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "freetype2"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-freetype=nocheck and the environment
+variables freetype_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+# find sqlite3
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3" >&5
+$as_echo_n "checking for sqlite3... " >&6; }
+    if test x"$with_sqlite3" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_sqlite3" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sqlite3") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            sqlite3_LIBS=`$PKG_CONFIG --libs --silence-errors "sqlite3"`
+            sqlite3_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "sqlite3"`
+            sqlite3_LIBDIRS=`
+    echo "$sqlite3_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$sqlite3_LIBDIRS"; then
+                LIBS="$LIBS $sqlite3_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        sqlite3_HAVE="yes"
+        if test -n "$sqlite3_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($sqlite3_LIBDIRS)" >&5
+$as_echo "yes ($sqlite3_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        sqlite3_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xyes = xyes -o x"$with_sqlite3" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "sqlite3"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-sqlite3=nocheck and the environment
+variables sqlite3_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+# find lua 5.1
+# (K)Ubuntu uses lua5.1.pc, Mac OS X and other
+# linux distributions use lua.pc
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua5.1" >&5
+$as_echo_n "checking for lua5.1... " >&6; }
+    if test x"$with_lua" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_lua" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.1\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "lua5.1") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            lua_LIBS=`$PKG_CONFIG --libs --silence-errors "lua5.1"`
+            lua_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "lua5.1"`
+            lua_LIBDIRS=`
+    echo "$lua_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$lua_LIBDIRS"; then
+                LIBS="$LIBS $lua_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        lua_HAVE="yes"
+        if test -n "$lua_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($lua_LIBDIRS)" >&5
+$as_echo "yes ($lua_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        lua_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xno = xyes -o x"$with_lua" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "lua5.1"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-lua=nocheck and the environment
+variables lua_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+lua_LIB_NAME="lua5.1"
+if [ x$lua_HAVE = xno ]; then
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua >= 5.1" >&5
+$as_echo_n "checking for lua >= 5.1... " >&6; }
+    if test x"$with_lua" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_lua" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua >= 5.1\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "lua >= 5.1") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            lua_LIBS=`$PKG_CONFIG --libs --silence-errors "lua >= 5.1"`
+            lua_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "lua >= 5.1"`
+            lua_LIBDIRS=`
+    echo "$lua_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$lua_LIBDIRS"; then
+                LIBS="$LIBS $lua_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        lua_HAVE="yes"
+        if test -n "$lua_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($lua_LIBDIRS)" >&5
+$as_echo "yes ($lua_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        lua_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xyes = xyes -o x"$with_lua" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "lua >= 5.1"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-lua=nocheck and the environment
+variables lua_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+    lua_LIB_NAME="lua"
+fi
+
+
+# find FFMpeg
+# Note: do not use the min/max version parameters with ffmpeg
+# otherwise it might fail in ubuntu due to a wrong version number
+# format in ffmpeg's .pc-files.
+# For example: 0d.51.1.2 instead of the correct 51.1.2.
+#   A check for version >=52.0.0 will return version 0d.51.1.2
+#   although it is lower because pkg-config is confused by the 0d.
+# Use [mylib]_VERSION_INT for version-checking instead
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libavcodec" >&5
+$as_echo_n "checking for libavcodec... " >&6; }
+    if test x"$with_libavcodec" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_libavcodec" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavcodec") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            libavcodec_LIBS=`$PKG_CONFIG --libs --silence-errors "libavcodec"`
+            libavcodec_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "libavcodec"`
+            libavcodec_LIBDIRS=`
+    echo "$libavcodec_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$libavcodec_LIBDIRS"; then
+                LIBS="$LIBS $libavcodec_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        libavcodec_HAVE="yes"
+        if test -n "$libavcodec_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libavcodec_LIBDIRS)" >&5
+$as_echo "yes ($libavcodec_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        libavcodec_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xyes = xyes -o x"$with_libavcodec" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libavcodec"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-libavcodec=nocheck and the environment
+variables libavcodec_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+    if test x$libavcodec_HAVE = xyes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of libavcodec" >&5
+$as_echo_n "checking version of libavcodec... " >&6; }
+
+
+    # check if variable was defined by the user
+    if test -z "$libavcodec_VERSION"; then
+        # if not, get it from pkg-config
+        if test x$libavcodec_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavcodec") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libavcodec_VERSION=`$PKG_CONFIG --modversion --silence-errors "libavcodec"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libavcodec"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libavcodec=nocheck is defined the environment variable
+libavcodec_VERSION
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$libavcodec_VERSION]" >&5
+$as_echo "[$libavcodec_VERSION]" >&6; }
+    else
+        libavcodec_VERSION="0.0.0"
+    fi
+
+    version=$libavcodec_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    libavcodec_VERSION_MAJOR=$(($major))
+    libavcodec_VERSION_MINOR=$(($minor))
+    libavcodec_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    libavcodec_VERSION_INT=$(($libavcodec_VERSION_MAJOR*1000000+$libavcodec_VERSION_MINOR*1000+$libavcodec_VERSION_RELEASE))
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for avcodec_decode_audio in -lavcodec" >&5
+$as_echo_n "checking for avcodec_decode_audio in -lavcodec... " >&6; }
+if test "${ac_cv_lib_avcodec_avcodec_decode_audio+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lavcodec  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char avcodec_decode_audio ();
+int
+main ()
+{
+return avcodec_decode_audio ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  ac_cv_lib_avcodec_avcodec_decode_audio=yes
+else
+  ac_cv_lib_avcodec_avcodec_decode_audio=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avcodec_avcodec_decode_audio" >&5
+$as_echo "$ac_cv_lib_avcodec_avcodec_decode_audio" >&6; }
+if test "x$ac_cv_lib_avcodec_avcodec_decode_audio" = x""yes; then :
+  HAVE_AVCODEC_DECODE_AUDIO="yes"
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for avcodec_decode_audio2 in -lavcodec" >&5
+$as_echo_n "checking for avcodec_decode_audio2 in -lavcodec... " >&6; }
+if test "${ac_cv_lib_avcodec_avcodec_decode_audio2+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lavcodec  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char avcodec_decode_audio2 ();
+int
+main ()
+{
+return avcodec_decode_audio2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  ac_cv_lib_avcodec_avcodec_decode_audio2=yes
+else
+  ac_cv_lib_avcodec_avcodec_decode_audio2=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avcodec_avcodec_decode_audio2" >&5
+$as_echo "$ac_cv_lib_avcodec_avcodec_decode_audio2" >&6; }
+if test "x$ac_cv_lib_avcodec_avcodec_decode_audio2" = x""yes; then :
+  HAVE_AVCODEC_DECODE_AUDIO2="yes"
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for img_convert in -lavcodec" >&5
+$as_echo_n "checking for img_convert in -lavcodec... " >&6; }
+if test "${ac_cv_lib_avcodec_img_convert+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lavcodec  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char img_convert ();
+int
+main ()
+{
+return img_convert ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  ac_cv_lib_avcodec_img_convert=yes
+else
+  ac_cv_lib_avcodec_img_convert=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avcodec_img_convert" >&5
+$as_echo "$ac_cv_lib_avcodec_img_convert" >&6; }
+if test "x$ac_cv_lib_avcodec_img_convert" = x""yes; then :
+  HAVE_IMG_CONVERT="yes"
+fi
+
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libavformat" >&5
+$as_echo_n "checking for libavformat... " >&6; }
+    if test x"$with_libavformat" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_libavformat" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavformat\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavformat") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            libavformat_LIBS=`$PKG_CONFIG --libs --silence-errors "libavformat"`
+            libavformat_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "libavformat"`
+            libavformat_LIBDIRS=`
+    echo "$libavformat_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$libavformat_LIBDIRS"; then
+                LIBS="$LIBS $libavformat_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        libavformat_HAVE="yes"
+        if test -n "$libavformat_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libavformat_LIBDIRS)" >&5
+$as_echo "yes ($libavformat_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        libavformat_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xyes = xyes -o x"$with_libavformat" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libavformat"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-libavformat=nocheck and the environment
+variables libavformat_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+    if test x$libavformat_HAVE = xyes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of libavformat" >&5
+$as_echo_n "checking version of libavformat... " >&6; }
+
+
+    # check if variable was defined by the user
+    if test -z "$libavformat_VERSION"; then
+        # if not, get it from pkg-config
+        if test x$libavformat_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavformat\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavformat") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libavformat_VERSION=`$PKG_CONFIG --modversion --silence-errors "libavformat"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libavformat"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libavformat=nocheck is defined the environment variable
+libavformat_VERSION
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$libavformat_VERSION]" >&5
+$as_echo "[$libavformat_VERSION]" >&6; }
+    else
+        libavformat_VERSION="0.0.0"
+    fi
+
+    version=$libavformat_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    libavformat_VERSION_MAJOR=$(($major))
+    libavformat_VERSION_MINOR=$(($minor))
+    libavformat_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    libavformat_VERSION_INT=$(($libavformat_VERSION_MAJOR*1000000+$libavformat_VERSION_MINOR*1000+$libavformat_VERSION_RELEASE))
+
+
+
+
+
+
+
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libavutil" >&5
+$as_echo_n "checking for libavutil... " >&6; }
+    if test x"$with_libavutil" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_libavutil" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavutil\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavutil") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            libavutil_LIBS=`$PKG_CONFIG --libs --silence-errors "libavutil"`
+            libavutil_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "libavutil"`
+            libavutil_LIBDIRS=`
+    echo "$libavutil_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$libavutil_LIBDIRS"; then
+                LIBS="$LIBS $libavutil_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        libavutil_HAVE="yes"
+        if test -n "$libavutil_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libavutil_LIBDIRS)" >&5
+$as_echo "yes ($libavutil_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        libavutil_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xyes = xyes -o x"$with_libavutil" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libavutil"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-libavutil=nocheck and the environment
+variables libavutil_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+    if test x$libavutil_HAVE = xyes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of libavutil" >&5
+$as_echo_n "checking version of libavutil... " >&6; }
+
+
+    # check if variable was defined by the user
+    if test -z "$libavutil_VERSION"; then
+        # if not, get it from pkg-config
+        if test x$libavutil_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavutil\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavutil") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libavutil_VERSION=`$PKG_CONFIG --modversion --silence-errors "libavutil"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libavutil"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libavutil=nocheck is defined the environment variable
+libavutil_VERSION
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$libavutil_VERSION]" >&5
+$as_echo "[$libavutil_VERSION]" >&6; }
+    else
+        libavutil_VERSION="0.0.0"
+    fi
+
+    version=$libavutil_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    libavutil_VERSION_MAJOR=$(($major))
+    libavutil_VERSION_MINOR=$(($minor))
+    libavutil_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    libavutil_VERSION_INT=$(($libavutil_VERSION_MAJOR*1000000+$libavutil_VERSION_MINOR*1000+$libavutil_VERSION_RELEASE))
+
+
+
+
+
+
+
+if [ x$libavcodec_HAVE = xyes -a x$libavformat_HAVE = xyes -a x$libavutil_HAVE = xyes ]; then
+    ffmpeg_HAVE=yes
+else
+    ffmpeg_HAVE=no
+fi
+
+    if [ x$ffmpeg_HAVE = xyes ]; then
+        DEFINE_HAVE_FFMPEG=DEFINE
+    else
+	DEFINE_HAVE_FFMPEG=UNDEF
+    fi
+
+
+
+# find FFMpeg's swscale lib (just if FFMpeg is compiled in GPL mode)
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libswscale" >&5
+$as_echo_n "checking for libswscale... " >&6; }
+    if test x"$with_libswscale" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_libswscale" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libswscale\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libswscale") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            libswscale_LIBS=`$PKG_CONFIG --libs --silence-errors "libswscale"`
+            libswscale_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "libswscale"`
+            libswscale_LIBDIRS=`
+    echo "$libswscale_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$libswscale_LIBDIRS"; then
+                LIBS="$LIBS $libswscale_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        libswscale_HAVE="yes"
+        if test -n "$libswscale_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libswscale_LIBDIRS)" >&5
+$as_echo "yes ($libswscale_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        libswscale_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xno = xyes -o x"$with_libswscale" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libswscale"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-libswscale=nocheck and the environment
+variables libswscale_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+    if test x$libswscale_HAVE = xyes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of libswscale" >&5
+$as_echo_n "checking version of libswscale... " >&6; }
+
+
+    # check if variable was defined by the user
+    if test -z "$libswscale_VERSION"; then
+        # if not, get it from pkg-config
+        if test x$libswscale_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libswscale\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libswscale") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libswscale_VERSION=`$PKG_CONFIG --modversion --silence-errors "libswscale"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "libswscale"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libswscale=nocheck is defined the environment variable
+libswscale_VERSION
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$libswscale_VERSION]" >&5
+$as_echo "[$libswscale_VERSION]" >&6; }
+    else
+        libswscale_VERSION="0.0.0"
+    fi
+
+    version=$libswscale_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    libswscale_VERSION_MAJOR=$(($major))
+    libswscale_VERSION_MINOR=$(($minor))
+    libswscale_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    libswscale_VERSION_INT=$(($libswscale_VERSION_MAJOR*1000000+$libswscale_VERSION_MINOR*1000+$libswscale_VERSION_RELEASE))
+
+
+
+
+
+
+
+
+    if [ x$libswscale_HAVE = xyes ]; then
+        DEFINE_HAVE_SWSCALE=DEFINE
+    else
+	DEFINE_HAVE_SWSCALE=UNDEF
+    fi
+
+
+
+
+# find projectM version
+libprojectM_PKG="libprojectM >= 0.98"
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $libprojectM_PKG" >&5
+$as_echo_n "checking for $libprojectM_PKG... " >&6; }
+    if test x"$with_libprojectM" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_libprojectM" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$libprojectM_PKG\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$libprojectM_PKG") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            libprojectM_LIBS=`$PKG_CONFIG --libs --silence-errors "$libprojectM_PKG"`
+            libprojectM_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "$libprojectM_PKG"`
+            libprojectM_LIBDIRS=`
+    echo "$libprojectM_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$libprojectM_LIBDIRS"; then
+                LIBS="$LIBS $libprojectM_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        libprojectM_HAVE="yes"
+        if test -n "$libprojectM_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libprojectM_LIBDIRS)" >&5
+$as_echo "yes ($libprojectM_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        libprojectM_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xno = xyes -o x"$with_libprojectM" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "$libprojectM_PKG"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-libprojectM=nocheck and the environment
+variables libprojectM_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+    if test x$libprojectM_HAVE = xyes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of libprojectM" >&5
+$as_echo_n "checking version of libprojectM... " >&6; }
+
+
+    # check if variable was defined by the user
+    if test -z "$libprojectM_VERSION"; then
+        # if not, get it from pkg-config
+        if test x$libprojectM_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$libprojectM_PKG\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$libprojectM_PKG") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libprojectM_VERSION=`$PKG_CONFIG --modversion --silence-errors "$libprojectM_PKG"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "$libprojectM_PKG"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libprojectM=nocheck is defined the environment variable
+libprojectM_VERSION
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$libprojectM_VERSION]" >&5
+$as_echo "[$libprojectM_VERSION]" >&6; }
+    else
+        libprojectM_VERSION="0.0.0"
+    fi
+
+    version=$libprojectM_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    libprojectM_VERSION_MAJOR=$(($major))
+    libprojectM_VERSION_MINOR=$(($minor))
+    libprojectM_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    libprojectM_VERSION_INT=$(($libprojectM_VERSION_MAJOR*1000000+$libprojectM_VERSION_MINOR*1000+$libprojectM_VERSION_RELEASE))
+
+
+
+
+
+
+
+
+    if [ x$libprojectM_HAVE = xyes ]; then
+        DEFINE_HAVE_PROJECTM=DEFINE
+    else
+	DEFINE_HAVE_PROJECTM=UNDEF
+    fi
+
+
+# get projectM include-dir
+
+
+    # check if variable was defined by the user
+    if test -z "$libprojectM_INCLUDEDIR"; then
+        # if not, get it from pkg-config
+        if test x$libprojectM_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$libprojectM_PKG\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$libprojectM_PKG") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libprojectM_INCLUDEDIR=`$PKG_CONFIG --variable=includedir --silence-errors "$libprojectM_PKG"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "$libprojectM_PKG"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libprojectM=nocheck is defined the environment variable
+libprojectM_INCLUDEDIR
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+# get projectM data-dir (for preset- and font-dir)
+
+
+    # check if variable was defined by the user
+    if test -z "$libprojectM_DATADIR"; then
+        # if not, get it from pkg-config
+        if test x$libprojectM_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$libprojectM_PKG\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$libprojectM_PKG") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libprojectM_DATADIR=`$PKG_CONFIG --variable=pkgdatadir --silence-errors "$libprojectM_PKG"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "$libprojectM_PKG"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libprojectM=nocheck is defined the environment variable
+libprojectM_DATADIR
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+# check if we need the c-wrapper
+if [ "$libprojectM_VERSION_MAJOR" -ge 1 ]; then
+    libprojectM_USE_CWRAPPER=yes
+else
+    libprojectM_USE_CWRAPPER=no
+fi
+USE_PROJECTM_CWRAPPER=$libprojectM_USE_CWRAPPER
+
+
+# find portaudio
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for portaudio-2.0" >&5
+$as_echo_n "checking for portaudio-2.0... " >&6; }
+    if test x"$with_portaudio" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_portaudio" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"portaudio-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "portaudio-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            portaudio_LIBS=`$PKG_CONFIG --libs --silence-errors "portaudio-2.0"`
+            portaudio_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "portaudio-2.0"`
+            portaudio_LIBDIRS=`
+    echo "$portaudio_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$portaudio_LIBDIRS"; then
+                LIBS="$LIBS $portaudio_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        portaudio_HAVE="yes"
+        if test -n "$portaudio_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($portaudio_LIBDIRS)" >&5
+$as_echo "yes ($portaudio_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        portaudio_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xyes = xyes -o x"$with_portaudio" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "portaudio-2.0"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-portaudio=nocheck and the environment
+variables portaudio_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+    if test x$portaudio_HAVE = xyes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of portaudio" >&5
+$as_echo_n "checking version of portaudio... " >&6; }
+
+
+    # check if variable was defined by the user
+    if test -z "$portaudio_VERSION"; then
+        # if not, get it from pkg-config
+        if test x$portaudio_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"portaudio-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "portaudio-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  portaudio_VERSION=`$PKG_CONFIG --modversion --silence-errors "portaudio-2.0"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "portaudio-2.0"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-portaudio=nocheck is defined the environment variable
+portaudio_VERSION
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$portaudio_VERSION]" >&5
+$as_echo "[$portaudio_VERSION]" >&6; }
+    else
+        portaudio_VERSION="0.0.0"
+    fi
+
+    version=$portaudio_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    portaudio_VERSION_MAJOR=$(($major))
+    portaudio_VERSION_MINOR=$(($minor))
+    portaudio_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    portaudio_VERSION_INT=$(($portaudio_VERSION_MAJOR*1000000+$portaudio_VERSION_MINOR*1000+$portaudio_VERSION_RELEASE))
+
+
+
+
+
+
+
+
+    if [ x$portaudio_HAVE = xyes ]; then
+        DEFINE_HAVE_PORTAUDIO=DEFINE
+    else
+	DEFINE_HAVE_PORTAUDIO=UNDEF
+    fi
+
+
+
+# find pcre
+libpcre_PKG="libpcre"
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $libpcre_PKG" >&5
+$as_echo_n "checking for $libpcre_PKG... " >&6; }
+    if test x"$with_libpcre" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_libpcre" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$libpcre_PKG\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$libpcre_PKG") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            libpcre_LIBS=`$PKG_CONFIG --libs --silence-errors "$libpcre_PKG"`
+            libpcre_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "$libpcre_PKG"`
+            libpcre_LIBDIRS=`
+    echo "$libpcre_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$libpcre_LIBDIRS"; then
+                LIBS="$LIBS $libpcre_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        libpcre_HAVE="yes"
+        if test -n "$libpcre_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libpcre_LIBDIRS)" >&5
+$as_echo "yes ($libpcre_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        libpcre_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xno = xyes -o x"$with_libpcre" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "$libpcre_PKG"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-libpcre=nocheck and the environment
+variables libpcre_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+    if test x$libpcre_HAVE = xyes; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of libpcre" >&5
+$as_echo_n "checking version of libpcre... " >&6; }
+
+
+    # check if variable was defined by the user
+    if test -z "$libpcre_VERSION"; then
+        # if not, get it from pkg-config
+        if test x$libpcre_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$libpcre_PKG\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$libpcre_PKG") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libpcre_VERSION=`$PKG_CONFIG --modversion --silence-errors "$libpcre_PKG"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "$libpcre_PKG"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libpcre=nocheck is defined the environment variable
+libpcre_VERSION
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: [$libpcre_VERSION]" >&5
+$as_echo "[$libpcre_VERSION]" >&6; }
+    else
+        libpcre_VERSION="0.0.0"
+    fi
+
+    version=$libpcre_VERSION
+
+    # strip leading non-numeric tokens
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[^.]*[^0-9.][^.]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[^0-9\ ].*//'`
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    libpcre_VERSION_MAJOR=$(($major))
+    libpcre_VERSION_MINOR=$(($minor))
+    libpcre_VERSION_RELEASE=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    libpcre_VERSION_INT=$(($libpcre_VERSION_MAJOR*1000000+$libpcre_VERSION_MINOR*1000+$libpcre_VERSION_RELEASE))
+
+
+
+
+
+
+
+
+    if [ x$libpcre_HAVE = xyes ]; then
+        DEFINE_HAVE_LIBPCRE=DEFINE
+    else
+	DEFINE_HAVE_LIBPCRE=UNDEF
+    fi
+
+
+# get libpcre library dir
+
+
+    # check if variable was defined by the user
+    if test -z "$libpcre_LIBDIR"; then
+        # if not, get it from pkg-config
+        if test x$libpcre_HAVE = xyes; then
+            if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$libpcre_PKG\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$libpcre_PKG") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  libpcre_LIBDIR=`$PKG_CONFIG --variable=libdir --silence-errors "$libpcre_PKG"`
+else
+  # print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "$libpcre_PKG"`
+                 as_fn_error "
+
+$err_msg
+
+If --with-libpcre=nocheck is defined the environment variable
+libpcre_LIBDIR
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+
+
+fi
+        fi
+    fi
+
+
+
+# find portmixer
+
+    have_lib="no"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for portmixer" >&5
+$as_echo_n "checking for portmixer... " >&6; }
+    if test x"$with_portmixer" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_portmixer" != xno; then
+        # check if package exists
+	if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"portmixer\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "portmixer") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+
+            have_lib="yes"
+            portmixer_LIBS=`$PKG_CONFIG --libs --silence-errors "portmixer"`
+            portmixer_LIBDIRS=`$PKG_CONFIG --libs-only-L --silence-errors "portmixer"`
+            portmixer_LIBDIRS=`
+    echo "$portmixer_LIBDIRS" | $SED 's/^[ \t]*//' | $SED 's/[ \t]*$//'
+`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$portmixer_LIBDIRS"; then
+                LIBS="$LIBS $portmixer_LIBDIRS"
+            fi
+
+fi
+    fi
+    if test x$have_lib = xyes; then
+        portmixer_HAVE="yes"
+        if test -n "$portmixer_LIBDIRS"; then
+            # show additional lib-dirs
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($portmixer_LIBDIRS)" >&5
+$as_echo "yes ($portmixer_LIBDIRS)" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+    else
+        portmixer_HAVE="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+        # check if package is required
+        if test xno = xyes -o x"$with_portmixer" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "portmixer"`
+            as_fn_error "
+
+$err_msg
+
+Alternatively, you may set --with-portmixer=nocheck and the environment
+variables portmixer_[...] (see configure --help)
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+" "$LINENO" 5
+        fi
+    fi
+
+
+    if [ x$portmixer_HAVE = xyes ]; then
+        DEFINE_HAVE_PORTMIXER=DEFINE
+    else
+	DEFINE_HAVE_PORTMIXER=UNDEF
+    fi
+
+
+
+# determine linker-flags
+if test x$FPC_PLATFORM = xdarwin; then
+  LDFLAGS="-macosx_version_min 10.4 -undefined dynamic_lookup -headerpad_max_install_names"
+fi
+#LIBS=
+
+
+
+# -----------------------------------------
+# create output files
+# -----------------------------------------
+
+ac_config_files="$ac_config_files Makefile"
+
+ac_config_files="$ac_config_files src/Makefile"
+
+ac_config_files="$ac_config_files src/config-$FPC_PLATFORM.inc:src/config.inc.in"
+
+if [ x$libprojectM_USE_CWRAPPER = xyes ]; then
+    ac_config_files="$ac_config_files src/lib/projectM/cwrapper/Makefile"
+
+fi
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+	g
+	s/^\n//
+	s/\n/ /g
+	p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$?; test $as_status -eq 0 && as_status=1
+  if test "$3"; then
+    as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+  fi
+  $as_echo "$as_me: error: $1" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by ultrastardx $as_me 1.1, which was
+generated by GNU Autoconf 2.65.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <http://sourceforge.net/tracker/?group_id=191560&atid=937872>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+ultrastardx config.status 1.1
+configured by $0, generated by GNU Autoconf 2.65,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+    "src/config-$FPC_PLATFORM.inc") CONFIG_FILES="$CONFIG_FILES src/config-$FPC_PLATFORM.inc:src/config.inc.in" ;;
+    "src/lib/projectM/cwrapper/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/projectM/cwrapper/Makefile" ;;
+
+  *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || as_fn_error "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X "  :F $CONFIG_FILES      "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit $?
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+# -----------------------------------------
+# show results
+# -----------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}:
+
+!!!
+!!! Configuration of $PACKAGE_NAME $PACKAGE_VERSION done!
+!!!
+!!! Type \"make\" to compile and
+!!!      \"make install\" to install it afterwards.
+!!!
+!!! For further information on $PACKAGE_NAME visit:
+!!!   $PACKAGE_WEBSITE
+!!!
+!!! In case you find a bug send a bugreport to:
+!!!   $PACKAGE_BUGREPORT
+!!! You might as well ask for help at the IRC-Channel
+!!!   $PACKAGE_IRC
+!!!
+" >&5
+$as_echo "$as_me:
+
+!!!
+!!! Configuration of $PACKAGE_NAME $PACKAGE_VERSION done!
+!!!
+!!! Type \"make\" to compile and
+!!!      \"make install\" to install it afterwards.
+!!!
+!!! For further information on $PACKAGE_NAME visit:
+!!!   $PACKAGE_WEBSITE
+!!!
+!!! In case you find a bug send a bugreport to:
+!!!   $PACKAGE_BUGREPORT
+!!! You might as well ask for help at the IRC-Channel
+!!!   $PACKAGE_IRC
+!!!
+" >&6;}
+
+
+
diff --git a/songmanagement/configure.ac b/songmanagement/configure.ac
new file mode 100644
index 00000000..c240aa7d
--- /dev/null
+++ b/songmanagement/configure.ac
@@ -0,0 +1,298 @@
+#
+# ultrastardx configure.ac script
+#
+# by UltraStar Deluxe Team
+#
+# Execute "autogen.sh" or "make reconf"
+# to create the configure script.
+#
+# Helper macros have been separated to
+#   ax_extract_version.m4 (AX_EXTRACT_VERSION)
+#   pkg_config_utils.m4   (PKG_VALUE, PKG_VERSION, PKG_HAVE)
+#
+
+# Require autoconf >= 2.61
+AC_PREREQ(2.61)
+
+# Init autoconf
+AC_INIT([ultrastardx], 
+        [1.1], 
+        [http://sourceforge.net/tracker/?group_id=191560&atid=937872])
+# specify the website here
+PACKAGE_WEBSITE="http://www.ultrastardeluxe.org/"
+AC_SUBST(PACKAGE_WEBSITE)
+# specify the IRC-channel here
+PACKAGE_IRC="#ultrastardx at quakenet.org"
+AC_SUBST(PACKAGE_IRC)
+
+# Specify a source-file so autoconf can check if the source-dir exists
+AC_CONFIG_SRCDIR(src/ultrastardx.dpr)
+
+# Set the path to install-sh
+AC_CONFIG_AUX_DIR(dists/autogen)
+
+# show features and packages in one list
+AC_PRESERVE_HELP_ORDER
+
+# -----------------------------------------
+# find tools
+# -----------------------------------------
+
+# options for make command
+AC_PROG_MAKE_SET
+# find tool for ln -s (e.g. uses cp -p for FAT-filesystems)
+AC_LN_S
+# find a program for recursive dir creation
+AC_PROG_MKDIR_P
+# find the best install tool
+AC_PROG_INSTALL
+# some other useful tools
+#AC_PROG_AWK
+AC_PROG_SED
+AC_PROG_GREP
+#AC_PROG_EGREP
+
+# -----------------------------------------
+# macro declarations
+# -----------------------------------------
+
+# AC_SUBST_DEFINE(DEFINE_SUFFIX, IS_DEFINED)
+# used to enable/disable pascal defines
+AC_DEFUN([AC_SUBST_DEFINE],
+[
+    if [[ x$2 = xyes ]]; then
+        DEFINE_[$1]=DEFINE
+    else
+	DEFINE_[$1]=UNDEF
+    fi
+    AC_SUBST(DEFINE_[$1])
+])
+
+# -----------------------------------------
+# define switches
+# -----------------------------------------
+
+# print library options header
+AC_ARG_WITH([cfg-dummy1], [
+External Libraries:])
+
+# add portmixer option
+AC_ARG_WITH([portmixer],
+    [AS_HELP_STRING([--with-portmixer],
+      [enable portmixer audio-mixer support @<:@default=check@:>@])],
+    [with_portmixer=$withval], [with_portmixer="check"])
+
+# add projectM option
+AC_ARG_WITH([libprojectM], 
+    [AS_HELP_STRING([--with-libprojectM],
+      [enable projectM visualization support @<:@default=no@:>@])],
+    [with_libprojectM=$withval], [with_libprojectM="no"])
+
+# print misc options header
+AC_ARG_WITH([cfg-dummy2], [
+Development options:])
+
+# add DEPRECATED global and local options
+AC_ARG_ENABLE(global, [AS_HELP_STRING([--enable-global], [(DEPRECATED, DO NOT USE]))])
+AC_ARG_ENABLE(local, [AS_HELP_STRING([--enable-local], [(DEPRECATED, DO NOT USE]))])
+
+if [[ x$enable_global != x -o x$enable_local != x ]]; then
+   AC_MSG_NOTICE([
+
+!!! NOTE: --enable-global and --enable-local are deprecated:
+!!! - global build: just type "make" and "make install"
+!!! - local  build: just type "make" and start "game/ultrastardx"
+])
+   sleep 2
+fi
+
+AC_ARG_ENABLE(debug,
+  [AS_HELP_STRING([--enable-debug],
+    [Enable debug build @<:@default=no@:>@])],
+  [test $enableval = "yes" && ENABLE_DEBUG="yes"], [])
+AC_SUBST(ENABLE_DEBUG)
+
+# -----------------------------------------
+# check for compilers
+# -----------------------------------------
+
+AC_CANONICAL_HOST
+
+# find and test the freepascal compiler
+# sets PFLAGS, FPC_VERSION, FPC_DEBUG, etc.
+AC_PROG_FPC
+
+# find and test the C compiler (for C-libs and wrappers)
+AC_PROG_CC
+AC_LANG([C])
+
+# find and test the C++ compiler (for C-libs and wrappers)
+AC_PROG_CXX
+AC_LANG([C++])
+
+AC_PROG_RANLIB
+
+# find pkg-config
+PKG_PROG_PKG_CONFIG()
+if [[ x$PKG_CONFIG = x ]]; then
+   AC_MSG_ERROR([
+!!! pkg-config was not found on your system. 
+!!! It is needed to determine the versions of your libraries.
+!!! Install it and try again.])
+fi
+
+
+# -----------------------------------------
+# check for OS
+# -----------------------------------------
+
+if test x$FPC_PLATFORM = xdarwin; then
+   AC_MACOSX_VERSION
+fi
+
+# -----------------------------------------
+# check for libraries
+# -----------------------------------------
+
+# find libpng
+# pkgconfig name for 1.2 is "libpng12", for 1.4 "libpng"
+PKG_HAVE([libpng], [libpng12], no)
+if [[ x$libpng_HAVE = xyes ]]; then
+    PKG_VERSION([libpng], [libpng12])
+else
+    # check for the generic .pc file
+    PKG_HAVE([libpng], [libpng >= 1.2], yes)
+    PKG_VERSION([libpng], [libpng >= 1.2])
+fi
+
+# find sdl
+PKG_HAVE([sdl], [sdl], yes)
+
+# find freetype
+PKG_HAVE([freetype], [freetype2], yes)
+
+# find sqlite3
+PKG_HAVE([sqlite3], [sqlite3], yes)
+
+# find lua 5.1
+# (K)Ubuntu uses lua5.1.pc, Mac OS X and other 
+# linux distributions use lua.pc
+PKG_HAVE([lua], [lua5.1], no)
+lua_LIB_NAME="lua5.1"
+if [[ x$lua_HAVE = xno ]]; then
+    PKG_HAVE([lua], [lua >= 5.1], yes)
+    lua_LIB_NAME="lua"
+fi
+AC_SUBST(lua_LIB_NAME)
+
+# find FFMpeg
+# Note: do not use the min/max version parameters with ffmpeg
+# otherwise it might fail in ubuntu due to a wrong version number 
+# format in ffmpeg's .pc-files.
+# For example: 0d.51.1.2 instead of the correct 51.1.2.
+#   A check for version >=52.0.0 will return version 0d.51.1.2 
+#   although it is lower because pkg-config is confused by the 0d.
+# Use [mylib]_VERSION_INT for version-checking instead
+PKG_HAVE([libavcodec], [libavcodec], yes)
+PKG_VERSION([libavcodec], [libavcodec])
+AC_CHECK_LIB([avcodec], [avcodec_decode_audio], [HAVE_AVCODEC_DECODE_AUDIO="yes"])
+AC_CHECK_LIB([avcodec], [avcodec_decode_audio2], [HAVE_AVCODEC_DECODE_AUDIO2="yes"])
+AC_CHECK_LIB([avcodec], [img_convert], [HAVE_IMG_CONVERT="yes"])
+PKG_HAVE([libavformat], [libavformat], yes)
+PKG_VERSION([libavformat], [libavformat])
+PKG_HAVE([libavutil], [libavutil], yes)
+PKG_VERSION([libavutil], [libavutil])
+if [[ x$libavcodec_HAVE = xyes -a x$libavformat_HAVE = xyes -a x$libavutil_HAVE = xyes ]]; then
+    ffmpeg_HAVE=yes
+else
+    ffmpeg_HAVE=no
+fi
+AC_SUBST_DEFINE(HAVE_FFMPEG, $ffmpeg_HAVE)
+
+# find FFMpeg's swscale lib (just if FFMpeg is compiled in GPL mode)
+PKG_HAVE([libswscale], [libswscale], no)
+PKG_VERSION([libswscale], [libswscale])
+AC_SUBST_DEFINE(HAVE_SWSCALE, $libswscale_HAVE)
+
+
+# find projectM version
+libprojectM_PKG="libprojectM >= 0.98"
+PKG_HAVE([libprojectM], [$libprojectM_PKG], no)
+PKG_VERSION([libprojectM], [$libprojectM_PKG])
+AC_SUBST_DEFINE(HAVE_PROJECTM, $libprojectM_HAVE)
+# get projectM include-dir
+PKG_VALUE([libprojectM], [INCLUDEDIR], [variable=includedir], [$libprojectM_PKG], 
+          [C-Header include-dir (e.g. /usr/include)])
+# get projectM data-dir (for preset- and font-dir)
+PKG_VALUE([libprojectM], [DATADIR], [variable=pkgdatadir], [$libprojectM_PKG], 
+          [projectM data-directory for presets etc. (e.g. /usr/share/projectM)])
+# check if we need the c-wrapper
+if [[ "$libprojectM_VERSION_MAJOR" -ge 1 ]]; then
+    libprojectM_USE_CWRAPPER=yes
+else
+    libprojectM_USE_CWRAPPER=no
+fi
+AC_SUBST(USE_PROJECTM_CWRAPPER, $libprojectM_USE_CWRAPPER)
+
+# find portaudio
+PKG_HAVE([portaudio], [portaudio-2.0], yes)
+PKG_VERSION([portaudio], [portaudio-2.0])
+AC_SUBST_DEFINE(HAVE_PORTAUDIO, $portaudio_HAVE)
+
+# find pcre
+libpcre_PKG="libpcre"
+PKG_HAVE([libpcre], [$libpcre_PKG], no)
+PKG_VERSION([libpcre], [$libpcre_PKG])
+AC_SUBST_DEFINE(HAVE_LIBPCRE, $libpcre_HAVE)
+# get libpcre library dir
+PKG_VALUE([libpcre], [LIBDIR], [variable=libdir], [$libpcre_PKG], 
+          [library dir (e.g. /usr/lib, /sw/lib, ...)])
+
+# find portmixer
+PKG_HAVE([portmixer], [portmixer], no)
+AC_SUBST_DEFINE(HAVE_PORTMIXER, $portmixer_HAVE)
+
+# determine linker-flags
+if test x$FPC_PLATFORM = xdarwin; then
+  LDFLAGS="-macosx_version_min 10.4 -undefined dynamic_lookup -headerpad_max_install_names"
+fi
+#LIBS=
+AC_SUBST(LDFLAGS)
+AC_SUBST(LIBS)
+
+# -----------------------------------------
+# create output files
+# -----------------------------------------
+
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([src/Makefile])
+AC_CONFIG_FILES([src/config-$FPC_PLATFORM.inc:src/config.inc.in])
+if [[ x$libprojectM_USE_CWRAPPER = xyes ]]; then
+    AC_CONFIG_FILES([src/lib/projectM/cwrapper/Makefile])
+fi
+AC_OUTPUT
+
+# -----------------------------------------
+# show results
+# -----------------------------------------
+
+AC_MSG_NOTICE([
+
+!!!
+!!! Configuration of $PACKAGE_NAME $PACKAGE_VERSION done!
+!!!
+!!! Type "make" to compile and 
+!!!      "make install" to install it afterwards.
+!!!
+!!! For further information on $PACKAGE_NAME visit:
+!!!   $PACKAGE_WEBSITE
+!!!
+!!! In case you find a bug send a bugreport to:
+!!!   $PACKAGE_BUGREPORT
+!!! You might as well ask for help at the IRC-Channel
+!!!   $PACKAGE_IRC
+!!!
+])
+
+
+
diff --git a/songmanagement/dists/autogen/config.guess b/songmanagement/dists/autogen/config.guess
new file mode 100755
index 00000000..2313a174
--- /dev/null
+++ b/songmanagement/dists/autogen/config.guess
@@ -0,0 +1,1545 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-01-23'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+if [ "${UNAME_SYSTEM}" = "Linux" ] ; then
+	eval $set_cc_for_build
+	cat << EOF > $dummy.c
+	#include <features.h>
+	#ifdef __UCLIBC__
+	# ifdef __UCLIBC_CONFIG_VERSION__
+	LIBC=uclibc __UCLIBC_CONFIG_VERSION__
+	# else
+	LIBC=uclibc
+	# endif
+	#else
+	LIBC=gnu
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep LIBC= | sed -e 's: ::g'`
+fi
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[456])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	case ${UNAME_MACHINE} in
+	    pc98)
+		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+    	# uname -m includes "-pc" on this system.
+    	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:[3456]*)
+    	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    EM64T | authenticamd)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	else
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-${LIBC}
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-${LIBC}
+	exit ;;
+    frv:Linux:*:*)
+    	echo frv-unknown-linux-${LIBC}
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-${LIBC}
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-${LIBC}
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
+	esac
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-${LIBC}
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-${LIBC}
+	exit ;;
+    xtensa*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-${LIBC}"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}aout"
+		exit ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}coff"
+		exit ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}oldld"
+		exit ;;
+	esac
+	# This should get integrated into the C code below, but now we hack
+	if [ "$LIBC" != "gnu" ] ; then echo "$TENTATIVE" && exit 0 ; fi
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^LIBC/{
+		s: ::g
+		p
+	    }'`"
+	test x"${LIBC}" != x && {
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+		exit
+	}
+	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/songmanagement/dists/autogen/config.sub b/songmanagement/dists/autogen/config.sub
new file mode 100755
index 00000000..ba16ebf5
--- /dev/null
+++ b/songmanagement/dists/autogen/config.sub
@@ -0,0 +1,1676 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-01-16'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx | dvp \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| mt \
+	| msp430 \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]a*eb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]a*eb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mipsEE* | ee | ps2)
+		basic_machine=mips64r5900el-scei
+		case $os in
+		    -linux*)
+			;;
+		    *)
+			os=-elf
+			;;
+		esac
+		;;
+	iop)
+		basic_machine=mipsel-scei
+		os=-irx
+		;;
+	dvp)
+		basic_machine=dvp-scei
+		os=-elf
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tile*)
+		basic_machine=tile-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -irx*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+        -os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+        -tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+		os=-elf
+		;;
+        spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+        mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+    	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/songmanagement/dists/autogen/install-sh b/songmanagement/dists/autogen/install-sh
new file mode 100755
index 00000000..a5897de6
--- /dev/null
+++ b/songmanagement/dists/autogen/install-sh
@@ -0,0 +1,519 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-12-25.00
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""	$nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+	shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+	case $mode in
+	  *' '* | *'	'* | *'
+'*	  | *'*'* | *'?'* | *'['*)
+	    echo "$0: invalid mode: $mode" >&2
+	    exit 1;;
+	esac
+	shift;;
+
+    -o) chowncmd="$chownprog $2"
+	shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+	shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)	shift
+	break;;
+
+    -*)	echo "$0: invalid option: $1" >&2
+	exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dst_arg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dst_arg: Is a directory" >&2
+	exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+	(dirname "$dst") 2>/dev/null ||
+	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	     X"$dst" : 'X\(//\)[^/]' \| \
+	     X"$dst" : 'X\(//\)$' \| \
+	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+	echo X"$dst" |
+	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)[^/].*/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\).*/{
+		   s//\1/
+		   q
+		 }
+		 s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+	# Create intermediate dirs using mode 755 as modified by the umask.
+	# This is like FreeBSD 'install' as of 1997-10-28.
+	umask=`umask`
+	case $stripcmd.$umask in
+	  # Optimize common cases.
+	  *[2367][2367]) mkdir_umask=$umask;;
+	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+	  *[0-7])
+	    mkdir_umask=`expr $umask + 22 \
+	      - $umask % 100 % 40 + $umask % 20 \
+	      - $umask % 10 % 4 + $umask % 2
+	    `;;
+	  *) mkdir_umask=$umask,go-w;;
+	esac
+
+	# With -d, create the new directory with the user-specified mode.
+	# Otherwise, rely on $mkdir_umask.
+	if test -n "$dir_arg"; then
+	  mkdir_mode=-m$mode
+	else
+	  mkdir_mode=
+	fi
+
+	posix_mkdir=false
+	case $umask in
+	  *[123567][0-7][0-7])
+	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
+	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+	    ;;
+	  *)
+	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+	    if (umask $mkdir_umask &&
+		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+	    then
+	      if test -z "$dir_arg" || {
+		   # Check for POSIX incompatibilities with -m.
+		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+		   # other-writeable bit of parent directory when it shouldn't.
+		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+		   case $ls_ld_tmpdir in
+		     d????-?r-*) different_mode=700;;
+		     d????-?--*) different_mode=755;;
+		     *) false;;
+		   esac &&
+		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+		   }
+		 }
+	      then posix_mkdir=:
+	      fi
+	      rmdir "$tmpdir/d" "$tmpdir"
+	    else
+	      # Remove any dirs left behind by ancient mkdir implementations.
+	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+	    fi
+	    trap '' 0;;
+	esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+	umask $mkdir_umask &&
+	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+	/*) prefix='/';;
+	-*) prefix='./';;
+	*)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+	test -z "$d" && continue
+
+	prefix=$prefix$d
+	if test -d "$prefix"; then
+	  prefixes=
+	else
+	  if $posix_mkdir; then
+	    (umask=$mkdir_umask &&
+	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+	    # Don't fail if two instances are running concurrently.
+	    test -d "$prefix" || exit 1
+	  else
+	    case $prefix in
+	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+	      *) qprefix=$prefix;;
+	    esac
+	    prefixes="$prefixes '$qprefix'"
+	  fi
+	fi
+	prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+	# Don't fail if two instances are running concurrently.
+	(umask $mkdir_umask &&
+	 eval "\$doit_exec \$mkdirprog $prefixes") ||
+	  test -d "$dstdir" || exit 1
+	obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+	# Now remove or move aside any old file at destination location.
+	# We try this two ways since rm can't unlink itself on some
+	# systems and the destination file might be busy for other
+	# reasons.  In this case, the final cleanup might fail but the new
+	# file should still install successfully.
+	{
+	  test ! -f "$dst" ||
+	  $doit $rmcmd -f "$dst" 2>/dev/null ||
+	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+	  } ||
+	  { echo "$0: cannot unlink or rename $dst" >&2
+	    (exit 1); exit 1
+	  }
+	} &&
+
+	# Now rename the file to the real destination.
+	$doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/songmanagement/dists/autogen/m4/ac_define_dir.m4 b/songmanagement/dists/autogen/m4/ac_define_dir.m4
new file mode 100644
index 00000000..f3d8734f
--- /dev/null
+++ b/songmanagement/dists/autogen/m4/ac_define_dir.m4
@@ -0,0 +1,47 @@
+##### http://autoconf-archive.cryp.to/ac_define_dir.html
+#
+# SYNOPSIS
+#
+#   AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION])
+#
+# DESCRIPTION
+#
+#   This macro sets VARNAME to the expansion of the DIR variable,
+#   taking care of fixing up ${prefix} and such.
+#
+#   VARNAME is then offered as both an output variable and a C
+#   preprocessor symbol.
+#
+#   Example:
+#
+#      AC_DEFINE_DIR([DATADIR], [datadir], [Where data are placed to.])
+#
+# LAST MODIFICATION
+#
+#   2006-10-13
+#
+# COPYLEFT
+#
+#   Copyright (c) 2006 Stepan Kasal <kasal@ucw.cz>
+#   Copyright (c) 2006 Andreas Schwab <schwab@suse.de>
+#   Copyright (c) 2006 Guido U. Draheim <guidod@gmx.de>
+#   Copyright (c) 2006 Alexandre Oliva
+#
+#   Copying and distribution of this file, with or without
+#   modification, are permitted in any medium without royalty provided
+#   the copyright notice and this notice are preserved.
+
+AC_DEFUN([AC_DEFINE_DIR], [
+  prefix_NONE=
+  exec_prefix_NONE=
+  test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
+  test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
+dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn
+dnl refers to ${prefix}.  Thus we have to use `eval' twice.
+  eval ac_define_dir="\"[$]$2\""
+  eval ac_define_dir="\"$ac_define_dir\""
+  AC_SUBST($1, "$ac_define_dir")
+  AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
+  test "$prefix_NONE" && prefix=NONE
+  test "$exec_prefix_NONE" && exec_prefix=NONE
+])
diff --git a/songmanagement/dists/autogen/m4/ax_extract_version.m4 b/songmanagement/dists/autogen/m4/ax_extract_version.m4
new file mode 100644
index 00000000..c514e3c3
--- /dev/null
+++ b/songmanagement/dists/autogen/m4/ax_extract_version.m4
@@ -0,0 +1,58 @@
+# This file is part of UltraStar Deluxe
+# Created by the UltraStar Deluxe Team
+
+# SYNOPSIS
+#
+#   AX_EXTRACT_VERSION(VARIABLE_PREFIX, VERSION)
+#
+# DESCRIPTION
+#
+#   Splits a version number ("major.minor.release") into its components.
+#   The resulting components of the version are guaranteed to be
+#   numeric. All non-numeric chars are removed.
+#
+# Sets
+#   [$VARIABLE_PREFIX]_VERSION_MAJOR
+#   [$VARIABLE_PREFIX]_VERSION_MINOR
+#   [$VARIABLE_PREFIX]_VERSION_RELEASE
+#
+# This function calls
+#   AC_SUBST([$VARIABLE_PREFIX]_VERSION_type] for each type
+
+AC_DEFUN([AX_EXTRACT_VERSION],
+[
+    version=[$2]    
+
+    # strip leading non-numeric tokens 
+    # (necessary for some ffmpeg-packages in ubuntu)
+    # example: 0d.51.1.0 -> 51.1.0
+    version=`echo $version | sed 's/^[[^.]]*[[^0-9.]][[^.]]*\.//'`
+
+    # replace "." and "-" with " " and ignore trailing tokens.
+    # 1.23.4-r2 will be splitted to [maj=1, min=23, rel=4].
+    # In addition we delete everything after the first character 
+    # which is not 0-9.
+    # 1.3a4-r32 will be [maj=1, min=3, rel=0].
+    read major minor release ignore <<eof
+        `echo $version | tr '.-' ' ' | sed 's/[[^0-9\ ]].*//'` 
+eof
+    # Note: Do NOT indent the eof-delimiter
+    # We use a here-document (<<< here-strings not POSIX compatible)
+
+    test -z $major && major=0
+    test -z $minor && minor=0
+    test -z $release && release=0
+
+    # strip preceding 0s and set unset version-parts to 0
+    [$1][_VERSION_MAJOR]=$(($major))
+    [$1][_VERSION_MINOR]=$(($minor))
+    [$1][_VERSION_RELEASE]=$(($release))
+    # integer representation: MMMmmmrrr (M:major,m:minor,r:release)
+    # can be used if pkg-config's comparison fails
+    [$1][_VERSION_INT]=$(($[$1][_VERSION_MAJOR]*1000000+$[$1][_VERSION_MINOR]*1000+$[$1][_VERSION_RELEASE]))
+
+    AC_SUBST([$1][_VERSION_MAJOR])
+    AC_SUBST([$1][_VERSION_MINOR])
+    AC_SUBST([$1][_VERSION_RELEASE])
+    AC_SUBST([$1][_VERSION_INT])
+])
diff --git a/songmanagement/dists/autogen/m4/fpc.m4 b/songmanagement/dists/autogen/m4/fpc.m4
new file mode 100644
index 00000000..740071cb
--- /dev/null
+++ b/songmanagement/dists/autogen/m4/fpc.m4
@@ -0,0 +1,268 @@
+# Based on fpc.m4 Version 1.1 provided with
+#   J Sound System (http://jss.sourceforge.net)
+# 
+# Originally written by
+#   Matti "ccr/TNSP" Hamalainen
+#   (C) Copyright 2000-2001 Tecnic Software productions (TNSP)
+# 
+# Mostly rewritten by 
+#   UltraStar Deluxe Team
+
+# SYNOPSIS
+#
+#   AC_PROG_FPC
+#
+# DESCRIPTION
+#
+#   Checks for Free Pascal Compiler
+#
+#   Sets:
+#     PPC            : fpc command          
+#     FPCMAKE        : fpcmake command       
+#
+#     PFLAGS         : flags passed to fpc (overwrite default)
+#     PFLAGS_BASE    : base flags (release + debug)
+#     PFLAGS_EXTRA   : additional flags (appended to default PFLAGS)
+#     PFLAGS_DEBUG   : flags used in debug build
+#     PFLAGS_RELEASE : flags used in release build
+#
+#     Note: 
+#       all PFLAGS/PFLAGS_XYZ vars are set to $(PFLAGS_XYZ_DEFAULT)
+#       if not set by the user, so the Makefile can assign default
+#       values to them.
+#
+#     FPC_VERSION        : fpc version string, e.g. 2.3.1
+#     FPC_VERSION_MAJOR  : major version (here 2) 
+#     FPC_VERSION_MINOR  : minor version (here 3)
+#     FPC_VERSION_RELEASE: release version (here 1)
+#
+#     FPC_PLATFORM   : platform of the target (linux/darwin/win32/...)
+#     FPC_PROCESSOR  : processor of the target, (i386/...)
+#     FPC_CPLATFORM  : platform of the compiler host, (linux/darwin/win32/...)
+#     FPC_CPROCESSOR : processor of the compiler host, (i386/...)
+#     FPC_TARGET     : FPC_PROCESSOR-FPC_PLATFORM (e.g. i386-linux)
+#
+#     FPC_PREFIX     : prefix of fpc install path, (default: /usr)
+#     FPC_BASE_PATH  : $FPC_PREFIX/lib/fpc/$FPC_VERSION
+#     FPC_UNIT_PATH  : $FPC_BASE_PATH/units/$FPC_TARGET
+#
+# See "fpc -i" for a list of supported platforms and processors
+
+AC_DEFUN([AC_PROG_FPC], [
+
+##
+# User PFLAGS
+##
+
+AC_ARG_VAR(PFLAGS, [Free Pascal Compiler flags (replaces all other flags)])
+AC_ARG_VAR(PFLAGS_BASE,    [Free Pascal Compiler base flags, e.g. -Si])
+AC_ARG_VAR(PFLAGS_DEBUG,   [Free Pascal Compiler debug flags, e.g. -gl])
+AC_ARG_VAR(PFLAGS_RELEASE, [Free Pascal Compiler release flags, e.g. -O2])
+AC_ARG_VAR(PFLAGS_EXTRA,   [Free Pascal Compiler additional flags])
+
+##
+# Compiler options
+##
+
+AC_ARG_ENABLE(dummy_fpc1,[
+Free Pascal Compiler specific options:])
+
+# fpc path
+AC_ARG_WITH(fpc,
+  [AS_HELP_STRING([--with-fpc=DIR],
+    [Directory of the FPC executable @<:@PATH@:>@])],
+  [PPC_PATH=$withval], [])
+
+# verbose
+AC_ARG_ENABLE(verbose,
+  [AS_HELP_STRING([--disable-verbose],
+    [Disable verbose compiler output @<:@default=no@:>@])],
+  [test x$enableval = xno && PFLAGS_EXTRA="$PFLAGS_EXTRA -v0Bew"], [])
+
+# gprof
+AC_ARG_ENABLE(gprof,
+  [AS_HELP_STRING([--enable-gprof],
+    [Enable profiling with gprof @<:@default=no@:>@])],
+  [test x$enableval = xyes && PFLAGS_EXTRA="$PFLAGS_EXTRA -pg"], [])
+
+# valgrind
+AC_ARG_ENABLE(valgrind,
+  [AS_HELP_STRING([--enable-valgrind],
+    [Enable debugging with valgrind @<:@default=no@:>@])],
+  [test x$enableval = xyes && PFLAGS_EXTRA="$PFLAGS_EXTRA -gv"], [])
+
+# heaptrace
+AC_ARG_ENABLE(heaptrace,
+  [AS_HELP_STRING([--enable-heaptrace],
+    [Enable heaptrace (memory corruption detection) @<:@default=no@:>@])],
+  [test x$enableval = xyes && PFLAGS_EXTRA="$PFLAGS_EXTRA -gh"], [])
+
+# range-checks
+AC_ARG_ENABLE(rangechecks,
+  [AS_HELP_STRING([--enable-rangechecks],
+    [Enables range-checks @<:@default=no@:>@])],
+  [test x$enableval = xyes && PFLAGS_EXTRA="$PFLAGS_EXTRA -Crtoi"], [])
+
+# allow execstack (see noexecstack compiler check below)
+AC_ARG_ENABLE(noexecstack,
+  [AS_HELP_STRING([--disable-noexecstack],
+    [Allow executable stacks @<:@default=no@:>@])],
+  [], [enable_noexecstack="yes"])
+
+###
+# Find compiler executable
+###
+
+PPC_CHECK_PROGS="fpc FPC ppc386 ppc PPC386"
+
+if test -z "$PPC_PATH"; then
+    PPC_PATH=$PATH
+    AC_CHECK_PROGS(PPC, $PPC_CHECK_PROGS)
+    AC_CHECK_PROGS(FPCMAKE, [fpcmake])
+else
+    AC_PATH_PROGS(PPC, $PPC_CHECK_PROGS, [], $PPC_PATH)
+    AC_PATH_PROGS(FPCMAKE, [fpcmake], [], $PPC_PATH)
+fi
+if test -z "$PPC"; then
+    AC_MSG_ERROR([no Free Pascal Compiler found in $PPC_PATH])
+fi
+
+###
+# Get the FPC compiler info
+###
+
+AC_MSG_CHECKING([version of fpc])
+FPC_VERSION=`${PPC} -iV`
+AX_EXTRACT_VERSION(FPC, $FPC_VERSION)
+AC_SUBST(FPC_VERSION)
+AC_MSG_RESULT([@<:@$FPC_VERSION@:>@])
+
+FPC_PLATFORM=`${PPC} -iTO`
+FPC_PROCESSOR=`${PPC} -iTP`
+FPC_CPLATFORM=`${PPC} -iSO`
+FPC_CPROCESSOR=`${PPC} -iSP`
+
+FPC_TARGET=${FPC_PROCESSOR}-${FPC_PLATFORM}
+
+
+AC_SUBST(FPC_PLATFORM)
+AC_SUBST(FPC_PROCESSOR)
+AC_SUBST(FPC_CPLATFORM)
+AC_SUBST(FPC_CPROCESSOR)
+AC_SUBST(FPC_TARGET)
+
+###
+# Get paths
+###
+
+if test "x$prefix" != xNONE; then
+    FPC_PREFIX=$prefix
+else
+    FPC_PREFIX=$ac_default_prefix
+fi
+
+FPC_BASE_PATH="${FPC_PREFIX}/lib/fpc/${FPC_VERSION}"
+FPC_UNIT_PATH="${FPC_BASE_PATH}/units/${FPC_TARGET}"
+
+AC_SUBST(FPC_PREFIX)
+AC_SUBST(FPC_BASE_PATH)
+AC_SUBST(FPC_UNIT_PATH)
+
+###
+# Compiler checks
+###
+
+SIMPLE_PROGRAM="program foo; begin writeln; end."
+
+# Check if FPC works and can compile a program
+AC_CACHE_CHECK([whether the Free Pascal Compiler works], ac_cv_prog_ppc_works,
+[
+    AC_PROG_FPC_CHECK([ac_cv_prog_ppc_works], [], [$SIMPLE_PROGRAM])
+])
+if test x$ac_cv_prog_ppc_works = xno; then
+    AC_MSG_ERROR([installation or configuration problem: Cannot create executables.])
+fi
+
+# Check if FPC can link with standard libraries
+AC_CACHE_CHECK([whether the Free Pascal Compiler can link], ac_cv_prog_ppc_links,
+[
+    AC_PROG_FPC_CHECK([ac_cv_prog_ppc_links], [],
+        [program foo; uses crt; begin writeln; end.]
+    )
+])
+if test x$ac_cv_prog_ppc_links = xno; then
+    AC_MSG_ERROR([installation or configuration problem: Cannot link with some standard libraries.])
+fi
+
+# Check whether FPC's linker knows "-z noexecstack"
+# FPC does not set the NX-flag on stack memory. Binaries generated with FPC
+# might crash on platforms that require the stack to be non-executable.
+# So we will try to find a workaround here.
+# See http://bugs.freepascal.org/view.php?id=11563
+
+AC_CACHE_CHECK([whether FPC supports -k"-z noexecstack"], ac_cv_prog_ppc_noexecstack,
+[
+    AC_PROG_FPC_CHECK([ac_cv_prog_ppc_noexecstack], [-k"-z noexecstack"], [$SIMPLE_PROGRAM])
+])
+if test x$enable_noexecstack = xyes; then
+    if test x$ac_cv_prog_ppc_noexecstack = xyes; then
+        PFLAGS_EXTRA="$PFLAGS_EXTRA -k\"-z noexecstack\""
+    fi
+fi
+
+# Finally substitute PFLAGS
+
+# set unset PFLAGS_XYZ vars to $(PFLAGS_XYZ_DEFAULT)
+# so the Makefile can define default values to it.
+true ${PFLAGS:=\$(PFLAGS_DEFAULT)}
+true ${PFLAGS_BASE:=\$(PFLAGS_BASE_DEFAULT)}
+true ${PFLAGS_EXTRA:=\$(PFLAGS_EXTRA_DEFAULT)}
+true ${PFLAGS_DEBUG:=\$(PFLAGS_DEBUG_DEFAULT)}
+true ${PFLAGS_RELEASE:=\$(PFLAGS_RELEASE_DEFAULT)}
+
+AC_SUBST(PFLAGS)
+AC_SUBST(PFLAGS_BASE)
+AC_SUBST(PFLAGS_EXTRA)
+AC_SUBST(PFLAGS_DEBUG)
+AC_SUBST(PFLAGS_RELEASE)
+
+])
+
+#######################################
+# Helper functions
+#######################################
+
+# SYNOPSIS
+# 
+#   AC_PROG_FPC_CHECK(RESULT, FPC_FLAGS, CODE)
+#
+# DESCRIPTION
+#
+#   Checks if FPC is able to compile CODE with FPC_FLAGS.
+#   The result ("yes" on success, "no" otherwise) is
+#   stored in [$RESULT]
+#
+#   Parameters:
+#     RESULT:    Name of result variable
+#     FPC_FLAGS: Flags passed to FPC
+#     CODE:      
+
+AC_DEFUN([AC_PROG_FPC_CHECK],
+[
+    # create test file
+    rm -f conftest*
+    echo "[$3]" > conftest.pp
+
+    # compile test file
+    ${PPC} [$2] conftest.pp >> config.log 2>&1
+
+    # check if test file was compiled
+    if test -f conftest || test -f conftest.exe; then
+        [$1]="yes"
+    else
+        [$1]="no"
+    fi
+
+    # remove test file
+    rm -f conftest*
+])
diff --git a/songmanagement/dists/autogen/m4/macosx_version.m4 b/songmanagement/dists/autogen/m4/macosx_version.m4
new file mode 100644
index 00000000..ddedd908
--- /dev/null
+++ b/songmanagement/dists/autogen/m4/macosx_version.m4
@@ -0,0 +1,31 @@
+# This file is part of UltraStar Deluxe
+# Created by the UltraStar Deluxe Team
+
+# SYNOPSIS
+#
+#   AC_MACOSX_VERSION
+#
+# DESCRIPTION
+#
+#   Determines the Mac OS X and Darwin version.
+#
+#   +----------+---------+
+#   | Mac OS X |  Darwin |
+#   +----------+---------+
+#   |     10.4 |       8 |
+#   |     10.5 |       9 |
+#   +----------+---------+
+
+AC_DEFUN([AC_MACOSX_VERSION],
+[
+    AC_MSG_CHECKING([for Mac OS X version])
+    MACOSX_VERSION=`sw_vers -productVersion`
+    AX_EXTRACT_VERSION(MACOSX, $MACOSX_VERSION)
+    AC_MSG_RESULT(@<:@$MACOSX_VERSION@:>@)
+    AC_SUBST(MACOSX_VERSION)
+
+    AC_MSG_CHECKING([for Darwin version])
+    DARWIN_VERSION=`uname -r | cut -f1 -d.`
+    AC_MSG_RESULT(@<:@$DARWIN_VERSION@:>@)
+    AC_SUBST(DARWIN_VERSION)
+])
diff --git a/songmanagement/dists/autogen/m4/pkg_config_utils.m4 b/songmanagement/dists/autogen/m4/pkg_config_utils.m4
new file mode 100644
index 00000000..903e0fc9
--- /dev/null
+++ b/songmanagement/dists/autogen/m4/pkg_config_utils.m4
@@ -0,0 +1,190 @@
+# This file is part of UltraStar Deluxe
+# Created by the UltraStar Deluxe Team
+
+
+# OVERVIEW
+#
+#   PKG_VALUE(VARIABLE_PREFIX, POSTFIX, COMMAND, MODULE, HELP-STRING)
+#   PKG_VERSION(VARIABLE_PREFIX, MODULE)
+#   PKG_HAVE(VARIABLE_PREFIX, MODULE, [REQUIRED])
+#   AX_TRIM(STRING)
+
+# SYNOPSIS
+#
+#   PKG_VALUE(VARIABLE_PREFIX, POSTFIX, COMMAND, MODULE, HELP-STRING)
+#
+# DESCRIPTION
+#
+#   Calls pkg-config with a given command and stores the result.
+#   If the variable was already defined by the user or the package
+#   is not present on the system ([$VARIABLE_PREFIX]_HAVE <> yes) 
+#   pkg-config will not be executed and the old value remains.
+#   In addition the variable will be shown on "./configure --help"
+#   described by a given help-string.
+#
+#   Parameters:
+#     - VARIABLE_PREFIX: the prefix for the variables storing 
+#                        information about the package.
+#     - POSTFIX:         [$VARIABLE_PREFIX]_[$POSTFIX] will contain the value
+#     - COMMAND:         a pkg-config command, e.g. "variable=prefix"
+#     - MODULE:          the package pkg-config will retrieve info from
+#     - HELP-STRING:     description of the variable
+#
+#   Sets:
+#     [$VARIABLE_PREFIX]_[$POSTFIX]   # value (AC_SUBST)
+
+AC_DEFUN([PKG_VALUE],
+[
+    AC_ARG_VAR([$1]_[$2], [$5, overriding pkg-config])   
+    # check if variable was defined by the user
+    if test -z "$[$1]_[$2]"; then
+        # if not, get it from pkg-config
+        if test x$[$1][_HAVE] = xyes; then
+            PKG_CHECK_EXISTS([$4],
+                [[$1]_[$2]=`$PKG_CONFIG --[$3] --silence-errors "$4"`],
+                [# print error message and quit
+                 err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "$4"`
+                 AC_MSG_ERROR(
+[
+
+$err_msg
+
+If --with-[$1]=nocheck is defined the environment variable 
+[$1]_[$2]
+must be set to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+])
+
+                ])
+        fi
+    fi
+    AC_SUBST([$1]_[$2])
+])
+
+# SYNOPSIS
+#
+#   PKG_VERSION(VARIABLE_PREFIX, MODULE)
+#
+# DESCRIPTION
+#
+#   Retrieves the version of a package
+#
+#   Parameters:
+#     - VARIABLE_PREFIX: the prefix for the variables storing 
+#                        information about the package.
+#     - MODULE:          package name according to pkg-config
+#
+#   Sets:
+#     [$VARIABLE_PREFIX]_VERSION         # full version string 
+#                                        #   (format: "major.minor.release")
+#
+#     [$VARIABLE_PREFIX]_VERSION_MAJOR   # major version number
+#     [$VARIABLE_PREFIX]_VERSION_MINOR   # minor version number
+#     [$VARIABLE_PREFIX]_VERSION_RELEASE # release version number
+#
+#     [$VARIABLE_PREFIX]_VERSION_INT     # integer representation: 
+#                                        #   MMMmmmrrr (M:major,m:minor,r:release)
+
+AC_DEFUN([PKG_VERSION],
+[
+    if test x$[$1][_HAVE] = xyes; then
+        AC_MSG_CHECKING([version of $1])
+        PKG_VALUE([$1], [VERSION], [modversion], [$2], [version of $1])   
+        AC_MSG_RESULT(@<:@$[$1][_VERSION]@:>@)
+    else
+        [$1][_VERSION]="0.0.0"
+    fi
+    AX_EXTRACT_VERSION([$1], $[$1][_VERSION])
+])
+
+
+# SYNOPSIS
+#
+#   AX_TRIM(STRING)
+#
+# DESCRIPTION
+#
+#   Removes surrounding whitespace
+
+AC_DEFUN([AX_TRIM],
+[
+    echo "[$1]" | $SED 's/^[[ \t]]*//' | $SED 's/[[ \t]]*$//'
+])
+
+# SYNOPSIS
+#
+#   PKG_HAVE(VARIABLE_PREFIX, MODULE, [REQUIRED])
+#
+# DESCRIPTION
+#
+#   Checks with pkg-config if a package exists and retrieves 
+#   information about it.
+#
+#   Parameters:
+#     - VARIABLE_PREFIX: the prefix for the variables storing information about the package.
+#     - MODULE:   package name according to pkg-config
+#     - REQUIRED: if true, the configure-script is aborted if the package was not found
+# 
+#   Uses:
+#     with_[$VARIABLE_PREFIX]: whether and how the package should be checked for
+#       "check":   check for the package but do not abort if it does not exist (default)
+#       "no":      do not check for the package (sets _HAVE to "no" and _VERSION to "0.0.0")
+#       "yes":     check for the package and abort if it does not exist
+#       "nocheck": do not check for the package (sets _HAVE to "yes")
+# 
+#   Sets:
+#     [$VARIABLE_PREFIX]_HAVE       # package is available (values: "yes"|"no")
+#     [$VARIABLE_PREFIX]_LIBS       # linker flags (e.g. -Lmylibdir -lmylib)
+#     [$VARIABLE_PREFIX]_LIBDIRS    # library dirs (e.g. -Lmylibdir)
+
+AC_DEFUN([PKG_HAVE],
+[
+    have_lib="no"
+    AC_MSG_CHECKING([for $2])
+    if test x"$with_[$1]" = xnocheck; then
+        # do not call pkg-config, use user settings
+        have_lib="yes"
+    elif test x"$with_[$1]" != xno; then
+        # check if package exists
+	PKG_CHECK_EXISTS([$2], [
+            have_lib="yes"
+            [$1][_LIBS]=`$PKG_CONFIG --libs --silence-errors "$2"`
+            [$1][_LIBDIRS]=`$PKG_CONFIG --libs-only-L --silence-errors "$2"`
+            [$1][_LIBDIRS]=`AX_TRIM($[$1][_LIBDIRS])`
+            # add library directories to LIBS (ignore *_LIBS for now)
+	    if test -n "$[$1][_LIBDIRS]"; then
+                LIBS="$LIBS $[$1][_LIBDIRS]"
+            fi
+        ])
+    fi
+    if test x$have_lib = xyes; then
+        [$1][_HAVE]="yes"
+        if test -n "$[$1][_LIBDIRS]"; then
+            # show additional lib-dirs
+            AC_MSG_RESULT(yes [(]$[$1][_LIBDIRS][)])
+        else
+            AC_MSG_RESULT(yes)
+        fi
+    else
+        [$1][_HAVE]="no"
+        AC_MSG_RESULT(no)
+
+        # check if package is required
+        if test x$3 = xyes -o x"$with_[$1]" = xyes ; then
+            # print error message and quit
+            err_msg=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+            AC_MSG_ERROR(
+[
+
+$err_msg
+
+Alternatively, you may set --with-[$1]=nocheck and the environment
+variables [$1]_[[...]] (see configure --help) 
+to appropriate values to avoid the need to call pkg-config.
+
+See the pkg-config man page for more details.
+])
+        fi
+    fi
+])
diff --git a/songmanagement/dists/bamboo/bamboo-build-lin-laz.bat b/songmanagement/dists/bamboo/bamboo-build-lin-laz.bat
new file mode 100644
index 00000000..bcaca539
--- /dev/null
+++ b/songmanagement/dists/bamboo/bamboo-build-lin-laz.bat
@@ -0,0 +1,4 @@
+clear
+fpc  -S2cgi -OG1 -gl -vewnhi -l -Filib/JEDI-SDLv1.0/SDL/Pas/ -Fu/usr/lib/lazarus/components/images/lib/i386-linux/ -Fu/usr/lib/lazarus/lcl/units/i386-linux/ -Fu/usr/lib/lazarus/lcl/units/i386-linux/gtk2/ -Fu/usr/lib/lazarus/packager/units/i386-linux/ -Fu. -oUltraStar -dLCL -dLCLgtk2 UltraStar.lpr
+
+#mv ./UltraStar /home/jay/src/ultrastardx/output/
diff --git a/songmanagement/dists/bamboo/bamboo-build-lin-laz.sh b/songmanagement/dists/bamboo/bamboo-build-lin-laz.sh
new file mode 100644
index 00000000..ad8ef19f
--- /dev/null
+++ b/songmanagement/dists/bamboo/bamboo-build-lin-laz.sh
@@ -0,0 +1,6 @@
+svn update
+
+clear
+fpc  -S2cgi -OG1 -gl -vewnhi -l -Filib/JEDI-SDLv1.0/SDL/Pas/ -Fu/usr/lib/lazarus/components/images/lib/i386-linux/ -Fu/usr/lib/lazarus/lcl/units/i386-linux/ -Fu/usr/lib/lazarus/lcl/units/i386-linux/gtk2/ -Fu/usr/lib/lazarus/packager/units/i386-linux/ -Fu. -oUltraStar -dLCL -dLCLgtk2 UltraStar.lpr
+
+#mv ./UltraStar /home/jay/src/ultrastardx/output/
diff --git a/songmanagement/dists/bamboo/bamboo-build-win-delphi.bat b/songmanagement/dists/bamboo/bamboo-build-win-delphi.bat
new file mode 100644
index 00000000..8a6be942
--- /dev/null
+++ b/songmanagement/dists/bamboo/bamboo-build-win-delphi.bat
@@ -0,0 +1,9 @@
+"C:\Program Files\Borland\BDS\4.0\Bin\brc32.exe" -r ./UltraStar.rc
+
+"C:\Program Files\Borland\BDS\4.0\Bin\dcc32.exe" -U"lib\JEDI-SDL\SDL\Pas" -O"lib\JEDI-SDL\SDL\Pas" -I"lib\JEDI-SDL\SDL\Pas" -R"lib\JEDI-SDL\SDL\Pas" UltraStar.dpr
+cp UltraStar.exe ..\..\
+
+rem cd ..\..\Installer
+rem "C:\Program Files\NSIS\makeNSIS.exe" UltraStarDeluxe.nsi
+
+rem cd ..\Game\Code
\ No newline at end of file
diff --git a/songmanagement/dists/bamboo/bamboo-build-win-laz.bat b/songmanagement/dists/bamboo/bamboo-build-win-laz.bat
new file mode 100644
index 00000000..1d096004
--- /dev/null
+++ b/songmanagement/dists/bamboo/bamboo-build-win-laz.bat
@@ -0,0 +1,3 @@
+USDXResCompiler.exe UltraStar.rc
+
+C:\lazarus\fpc\2.0.4\bin\i386-win32\ppc386.exe  -S2cgi -OG1 -gl -vewnhi -l -Filib\JEDI-SDLv1.0\SDL\Pas\ -Fuc:\lazarus\components\jpeg\lib\i386-win32\ -Fuc:\lazarus\components\images\lib\i386-win32\ -Fuc:\lazarus\lcl\units\i386-win32\ -Fuc:\lazarus\lcl\units\i386-win32\win32\ -Fuc:\lazarus\packager\units\i386-win32\ -Fu. -oUltraStar.exe -dLCL -dLCLwin32 UltraStar.lpr
diff --git a/songmanagement/dists/code.svnprops b/songmanagement/dists/code.svnprops
new file mode 100644
index 00000000..51db6183
Binary files /dev/null and b/songmanagement/dists/code.svnprops differ
diff --git a/songmanagement/dists/debian/package_debian.sh b/songmanagement/dists/debian/package_debian.sh
new file mode 100644
index 00000000..bdb341a2
--- /dev/null
+++ b/songmanagement/dists/debian/package_debian.sh
@@ -0,0 +1,32 @@
+# This script should be run post-compile
+# and i should move files to the correct location for packaging ... ( for DEB package )
+
+rm -fr ../../../deb-package
+rm -fr ../../../packages
+clear
+
+mkdir ../../../packages
+
+mkdir ../../../deb-package
+mkdir ../../../deb-package/DEBIAN
+mkdir ../../../deb-package/usr
+mkdir ../../../deb-package/usr/local
+mkdir ../../../deb-package/usr/local/share
+mkdir ../../../deb-package/usr/local/share/UltraStarDeluxe
+mkdir ../../../deb-package/usr/bin
+
+cp ../../UltraStar ../../../deb-package/usr/bin/UltraStarDeluxe
+
+cp -a ../../Themes/ ../../../deb-package/usr/local/share/UltraStarDeluxe/
+cp -a ../../Sounds/ ../../../deb-package/usr/local/share/UltraStarDeluxe/
+cp -a ../../Skins/ ../../../deb-package/usr/local/share/UltraStarDeluxe/
+cp -a ../../Languages/ ../../../deb-package/usr/local/share/UltraStarDeluxe/
+
+cp UltraStarDeluxe.control ../../../deb-package/DEBIAN/control
+
+cd ../../../
+
+dpkg-deb --build ./deb-package
+mv deb-package.deb ./packages/UltraStarDeluxe_1.1_i386.deb
+
+rm -fr ../../../deb-package
diff --git a/songmanagement/dists/debian/ultrastardx.control b/songmanagement/dists/debian/ultrastardx.control
new file mode 100644
index 00000000..82c2cfb4
--- /dev/null
+++ b/songmanagement/dists/debian/ultrastardx.control
@@ -0,0 +1,17 @@
+Package: ultrastardx
+Priority: optional
+Section: games
+Installed-Size: 18400
+Maintainer: Jay Binks <jaybinks@gmail.com>
+Architecture: i386
+Version: 1.1.1
+Depends: libc6 (>= 2.1), libsdl1.2debian-alsa, libportaudio2, libavcodec1d, libavformat1d, libswscale1d, libsqlite3-0, libfreetype6,  libsdl-image1.2
+Description: 
+ Karaoke Software. 
+ It evaluates your singing by analyzing your voice pitch. 
+ Songs can be created with integrated Editor. 
+ .
+ http://www.ultrastardeluxe.org/
+
+
+
diff --git a/songmanagement/dists/delphi2005/readme.txt b/songmanagement/dists/delphi2005/readme.txt
new file mode 100644
index 00000000..64168d3c
--- /dev/null
+++ b/songmanagement/dists/delphi2005/readme.txt
@@ -0,0 +1,5 @@
+(Turbo-)Delphi 2005/2006 Project file
+--------------------------------------
+1. Copy ultrastardx.bdsproj to <ultrastardx>/src
+2. Double-click <ultrastardx>/src/ultrastardx.bdsproj
+
diff --git a/songmanagement/dists/delphi2005/ultrastardx.bdsproj b/songmanagement/dists/delphi2005/ultrastardx.bdsproj
new file mode 100644
index 00000000..6e05e1b6
--- /dev/null
+++ b/songmanagement/dists/delphi2005/ultrastardx.bdsproj
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="utf-8"?>
+<BorlandProject>
+	<PersonalityInfo>
+		<Option>
+			<Option Name="Personality">Delphi.Personality</Option>
+			<Option Name="ProjectType">VCLApplication</Option>
+			<Option Name="Version">1.0</Option>
+			<Option Name="GUID">{D87E04A0-8C17-4C12-922D-D26A317FCBA7}</Option>
+		</Option>
+	</PersonalityInfo>
+	<Delphi.Personality>
+		<Source>
+			<Source Name="MainSource">ultrastardx.dpr</Source>
+		</Source>
+		<FileVersion>
+			<FileVersion Name="Version">7.0</FileVersion>
+		</FileVersion>
+		<Compiler>
+			<Compiler Name="A">8</Compiler>
+			<Compiler Name="B">0</Compiler>
+			<Compiler Name="C">1</Compiler>
+			<Compiler Name="D">1</Compiler>
+			<Compiler Name="E">0</Compiler>
+			<Compiler Name="F">0</Compiler>
+			<Compiler Name="G">1</Compiler>
+			<Compiler Name="H">1</Compiler>
+			<Compiler Name="I">1</Compiler>
+			<Compiler Name="J">0</Compiler>
+			<Compiler Name="K">0</Compiler>
+			<Compiler Name="L">1</Compiler>
+			<Compiler Name="M">0</Compiler>
+			<Compiler Name="N">1</Compiler>
+			<Compiler Name="O">1</Compiler>
+			<Compiler Name="P">1</Compiler>
+			<Compiler Name="Q">0</Compiler>
+			<Compiler Name="R">0</Compiler>
+			<Compiler Name="S">0</Compiler>
+			<Compiler Name="T">0</Compiler>
+			<Compiler Name="U">0</Compiler>
+			<Compiler Name="V">1</Compiler>
+			<Compiler Name="W">0</Compiler>
+			<Compiler Name="X">1</Compiler>
+			<Compiler Name="Y">1</Compiler>
+			<Compiler Name="Z">1</Compiler>
+			<Compiler Name="ShowHints">True</Compiler>
+			<Compiler Name="ShowWarnings">True</Compiler>
+			<Compiler Name="UnitAliases">WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;</Compiler>
+			<Compiler Name="NamespacePrefix"></Compiler>
+			<Compiler Name="GenerateDocumentation">False</Compiler>
+			<Compiler Name="DefaultNamespace"></Compiler>
+			<Compiler Name="SymbolDeprecated">True</Compiler>
+			<Compiler Name="SymbolLibrary">True</Compiler>
+			<Compiler Name="SymbolPlatform">True</Compiler>
+			<Compiler Name="SymbolExperimental">True</Compiler>
+			<Compiler Name="UnitLibrary">True</Compiler>
+			<Compiler Name="UnitPlatform">True</Compiler>
+			<Compiler Name="UnitDeprecated">True</Compiler>
+			<Compiler Name="UnitExperimental">True</Compiler>
+			<Compiler Name="HResultCompat">True</Compiler>
+			<Compiler Name="HidingMember">True</Compiler>
+			<Compiler Name="HiddenVirtual">True</Compiler>
+			<Compiler Name="Garbage">True</Compiler>
+			<Compiler Name="BoundsError">True</Compiler>
+			<Compiler Name="ZeroNilCompat">True</Compiler>
+			<Compiler Name="StringConstTruncated">True</Compiler>
+			<Compiler Name="ForLoopVarVarPar">True</Compiler>
+			<Compiler Name="TypedConstVarPar">True</Compiler>
+			<Compiler Name="AsgToTypedConst">True</Compiler>
+			<Compiler Name="CaseLabelRange">True</Compiler>
+			<Compiler Name="ForVariable">True</Compiler>
+			<Compiler Name="ConstructingAbstract">True</Compiler>
+			<Compiler Name="ComparisonFalse">True</Compiler>
+			<Compiler Name="ComparisonTrue">True</Compiler>
+			<Compiler Name="ComparingSignedUnsigned">True</Compiler>
+			<Compiler Name="CombiningSignedUnsigned">True</Compiler>
+			<Compiler Name="UnsupportedConstruct">True</Compiler>
+			<Compiler Name="FileOpen">True</Compiler>
+			<Compiler Name="FileOpenUnitSrc">True</Compiler>
+			<Compiler Name="BadGlobalSymbol">True</Compiler>
+			<Compiler Name="DuplicateConstructorDestructor">True</Compiler>
+			<Compiler Name="InvalidDirective">True</Compiler>
+			<Compiler Name="PackageNoLink">True</Compiler>
+			<Compiler Name="PackageThreadVar">True</Compiler>
+			<Compiler Name="ImplicitImport">True</Compiler>
+			<Compiler Name="HPPEMITIgnored">True</Compiler>
+			<Compiler Name="NoRetVal">True</Compiler>
+			<Compiler Name="UseBeforeDef">True</Compiler>
+			<Compiler Name="ForLoopVarUndef">True</Compiler>
+			<Compiler Name="UnitNameMismatch">True</Compiler>
+			<Compiler Name="NoCFGFileFound">True</Compiler>
+			<Compiler Name="ImplicitVariants">True</Compiler>
+			<Compiler Name="UnicodeToLocale">True</Compiler>
+			<Compiler Name="LocaleToUnicode">True</Compiler>
+			<Compiler Name="ImagebaseMultiple">True</Compiler>
+			<Compiler Name="SuspiciousTypecast">True</Compiler>
+			<Compiler Name="PrivatePropAccessor">True</Compiler>
+			<Compiler Name="UnsafeType">False</Compiler>
+			<Compiler Name="UnsafeCode">False</Compiler>
+			<Compiler Name="UnsafeCast">False</Compiler>
+			<Compiler Name="OptionTruncated">True</Compiler>
+			<Compiler Name="WideCharReduced">True</Compiler>
+			<Compiler Name="DuplicatesIgnored">True</Compiler>
+			<Compiler Name="UnitInitSeq">True</Compiler>
+			<Compiler Name="LocalPInvoke">True</Compiler>
+			<Compiler Name="MessageDirective">True</Compiler>
+			<Compiler Name="CodePage"></Compiler>
+		</Compiler>
+		<Linker>
+			<Linker Name="MapFile">0</Linker>
+			<Linker Name="OutputObjs">0</Linker>
+			<Linker Name="GenerateHpps">False</Linker>
+			<Linker Name="ConsoleApp">1</Linker>
+			<Linker Name="DebugInfo">False</Linker>
+			<Linker Name="RemoteSymbols">False</Linker>
+			<Linker Name="GenerateDRC">False</Linker>
+			<Linker Name="MinStackSize">16384</Linker>
+			<Linker Name="MaxStackSize">1048576</Linker>
+			<Linker Name="ImageBase">4194304</Linker>
+			<Linker Name="ExeDescription"></Linker>
+		</Linker>
+		<Directories>
+			<Directories Name="OutputDir">..\game</Directories>
+			<Directories Name="UnitOutputDir">..\build\delphi-win</Directories>
+			<Directories Name="PackageDLLOutputDir"></Directories>
+			<Directories Name="PackageDCPOutputDir"></Directories>
+			<Directories Name="SearchPath">lib\JEDI-SDL\SDL\Pas</Directories>
+			<Directories Name="Packages">vclx;vcl;rtl;vclactnband</Directories>
+			<Directories Name="Conditionals"></Directories>
+			<Directories Name="DebugSourceDirs"></Directories>
+			<Directories Name="UsePackages">False</Directories>
+		</Directories>
+		<Parameters>
+			<Parameters Name="RunParams"></Parameters>
+			<Parameters Name="HostApplication"></Parameters>
+			<Parameters Name="Launcher"></Parameters>
+			<Parameters Name="UseLauncher">False</Parameters>
+			<Parameters Name="DebugCWD"></Parameters>
+			<Parameters Name="Debug Symbols Search Path"></Parameters>
+			<Parameters Name="LoadAllSymbols">True</Parameters>
+			<Parameters Name="LoadUnspecifiedSymbols">False</Parameters>
+		</Parameters>
+		<Language>
+			<Language Name="ActiveLang"></Language>
+			<Language Name="ProjectLang">$00000000</Language>
+			<Language Name="RootDir"></Language>
+		</Language>
+		<VersionInfo>
+			<VersionInfo Name="IncludeVerInfo">False</VersionInfo>
+			<VersionInfo Name="AutoIncBuild">False</VersionInfo>
+			<VersionInfo Name="MajorVer">1</VersionInfo>
+			<VersionInfo Name="MinorVer">0</VersionInfo>
+			<VersionInfo Name="Release">0</VersionInfo>
+			<VersionInfo Name="Build">0</VersionInfo>
+			<VersionInfo Name="Debug">False</VersionInfo>
+			<VersionInfo Name="PreRelease">False</VersionInfo>
+			<VersionInfo Name="Special">False</VersionInfo>
+			<VersionInfo Name="Private">False</VersionInfo>
+			<VersionInfo Name="DLL">False</VersionInfo>
+			<VersionInfo Name="Locale">1031</VersionInfo>
+			<VersionInfo Name="CodePage">1252</VersionInfo>
+		</VersionInfo>
+		<VersionInfoKeys>
+			<VersionInfoKeys Name="CompanyName"></VersionInfoKeys>
+			<VersionInfoKeys Name="FileDescription"></VersionInfoKeys>
+			<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
+			<VersionInfoKeys Name="InternalName"></VersionInfoKeys>
+			<VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys>
+			<VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys>
+			<VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys>
+			<VersionInfoKeys Name="ProductName"></VersionInfoKeys>
+			<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
+			<VersionInfoKeys Name="Comments"></VersionInfoKeys>
+		</VersionInfoKeys>
+	</Delphi.Personality>
+</BorlandProject>
diff --git a/songmanagement/dists/delphi7/readme.txt b/songmanagement/dists/delphi7/readme.txt
new file mode 100644
index 00000000..fa77699b
--- /dev/null
+++ b/songmanagement/dists/delphi7/readme.txt
@@ -0,0 +1,5 @@
+Delphi 7 Project file
+--------------------------------------
+1. Copy ultrastardx.dof to <ultrastardx>/src
+2. Double-click <ultrastardx>/src/ultrastardx.dpr
+
diff --git a/songmanagement/dists/delphi7/ultrastardx.dof b/songmanagement/dists/delphi7/ultrastardx.dof
new file mode 100644
index 00000000..771034b7
--- /dev/null
+++ b/songmanagement/dists/delphi7/ultrastardx.dof
@@ -0,0 +1,144 @@
+[FileVersion]
+Version=7.0
+[Compiler]
+A=8
+B=0
+C=1
+D=1
+E=0
+F=0
+G=1
+H=1
+I=1
+J=0
+K=0
+L=1
+M=0
+N=1
+O=1
+P=1
+Q=0
+R=0
+S=0
+T=0
+U=0
+V=1
+W=0
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+NamespacePrefix=
+SymbolDeprecated=1
+SymbolLibrary=1
+SymbolPlatform=1
+UnitLibrary=1
+UnitPlatform=1
+UnitDeprecated=1
+HResultCompat=1
+HidingMember=1
+HiddenVirtual=1
+Garbage=1
+BoundsError=1
+ZeroNilCompat=1
+StringConstTruncated=1
+ForLoopVarVarPar=1
+TypedConstVarPar=1
+AsgToTypedConst=1
+CaseLabelRange=1
+ForVariable=1
+ConstructingAbstract=1
+ComparisonFalse=1
+ComparisonTrue=1
+ComparingSignedUnsigned=1
+CombiningSignedUnsigned=1
+UnsupportedConstruct=1
+FileOpen=1
+FileOpenUnitSrc=1
+BadGlobalSymbol=1
+DuplicateConstructorDestructor=1
+InvalidDirective=1
+PackageNoLink=1
+PackageThreadVar=1
+ImplicitImport=1
+HPPEMITIgnored=1
+NoRetVal=1
+UseBeforeDef=1
+ForLoopVarUndef=1
+UnitNameMismatch=1
+NoCFGFileFound=1
+MessageDirective=1
+ImplicitVariants=1
+UnicodeToLocale=1
+LocaleToUnicode=1
+ImagebaseMultiple=1
+SuspiciousTypecast=1
+PrivatePropAccessor=1
+UnsafeType=0
+UnsafeCode=0
+UnsafeCast=0
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=1
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=
+[Directories]
+OutputDir=..\game
+UnitOutputDir=..\build\delphi-win
+PackageDLLOutputDir=
+PackageDCPOutputDir=
+SearchPath=lib\JEDI-SDL\SDL\Pas
+Packages=vclx;vcl;rtl;vcldb;dbrtl;dsnap;bdertl;dss;teeui;teedb;tee;vcldbx;vclactnband;adortl;visualclx;visualdbclx;dsnapcon;ibxpress
+Conditionals=
+DebugSourceDirs=
+UsePackages=0
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+[Version Info]
+IncludeVerInfo=0
+AutoIncBuild=0
+MajorVer=1
+MinorVer=0
+Release=0
+Build=0
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=1031
+CodePage=1252
+[Version Info Keys]
+CompanyName=
+FileDescription=
+FileVersion=1.0.0.0
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=1.0.0.0
+Comments=
+[HistoryLists\hlUnitAliases]
+Count=1
+Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[HistoryLists\hlSearchPath]
+Count=1
+Item0=lib\JEDI-SDL\SDL\Pas
+[HistoryLists\hlUnitOutputDirectory]
+Count=1
+Item0=..\build\delphi-win
+[HistoryLists\hlOutputDirectorry]
+Count=1
+Item0=..\game
diff --git a/songmanagement/dists/gentoo/readme.txt b/songmanagement/dists/gentoo/readme.txt
new file mode 100644
index 00000000..99517f84
--- /dev/null
+++ b/songmanagement/dists/gentoo/readme.txt
@@ -0,0 +1,36 @@
+---------------------------------------
+1. Introduction
+---------------------------------------
+This directory contains two ebuilds for UltraStar Deluxe
+- ultrastardx-9999.ebuild: a live ebuild using SVN sources
+- ultrastardx-1.1.ebuild: a snapshot ebuild that might be appended to the official portage someday
+
+---------------------------------------
+2. Create a portage overlay
+---------------------------------------
+If you want to try one of the ebuilds (at the moment only use the live ebuild) you must have a portage overlay.
+In case you do not have one or do not know what it is, see
+  http://gentoo-wiki.com/HOWTO_Create_an_Updated_Ebuild
+
+Normally this can be achieved (as root) with:
+  mkdir -p /usr/local/portage && echo 'PORTDIR_OVERLAY="/usr/local/portage"' >> /etc/make.conf
+
+---------------------------------------
+3. Add the USDX ebuild to your overlay
+---------------------------------------
+First create the directory structure (as root):
+  mkdir -p /usr/local/portage/games-arcade/ultrastardx
+
+Now copy the (live) ebuild to the new directory:
+  cp ultrastardx-9999.ebuild /usr/local/portage/games-arcade/ultrastardx
+
+Go to the overlay directory:
+  cd /usr/local/portage/games-arcade/ultrastardx
+
+Create a manifest:
+  ebuild ultrastardx-9999.ebuild manifest
+
+And you are done!
+
+Now you can emerge USDX with:
+  emerge ultrastardx -av
diff --git a/songmanagement/dists/gentoo/ultrastardx-1.1.0.ebuild b/songmanagement/dists/gentoo/ultrastardx-1.1.0.ebuild
new file mode 100644
index 00000000..7170fcdb
--- /dev/null
+++ b/songmanagement/dists/gentoo/ultrastardx-1.1.0.ebuild
@@ -0,0 +1,68 @@
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header $
+
+inherit eutils games
+
+SONGS_PKG=USDX-SongPackage
+SONGS_VER=01
+
+DESCRIPTION="An open-source karaoke game"
+HOMEPAGE="http://www.ultrastardeluxe.org/"
+SRC_URI="mirror://sourceforge/${PN}/${P}-src.tar.gz
+	songs? ( mirror://sourceforge/${PN}/${SONGS_PKG}-${SONGS_VER}.zip )"
+
+LICENSE="GPL-2
+	songs? (
+		CCPL-Attribution-ShareAlike-NonCommercial-2.5
+		CCPL-Attribution-NonCommercial-NoDerivs-2.5
+	)"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="projectm debug songs"
+
+RDEPEND="virtual/opengl
+	virtual/glu
+	media-libs/libsdl
+	media-libs/sdl-image
+	media-libs/freetype
+	media-libs/libpng
+	=media-libs/portaudio-19*
+	media-video/ffmpeg
+	dev-db/sqlite
+	projectm? ( media-libs/libprojectm )"
+DEPEND="${RDEPEND}
+	dev-util/pkgconfig
+	>=dev-lang/fpc-2.2.0"
+
+S=${WORKDIR}/${P}-src
+
+pkg_setup() {
+    games_pkg_setup
+    built_with_use media-libs/libsdl opengl \
+        || die "You need to compile media-libs/libsdl with USE=opengl."
+}
+
+src_compile() {
+	egamesconf \
+		$(use_with projectm libprojectM) \
+		$(use_enable debug) \
+		|| die
+	emake || die "emake failed"
+}
+
+src_install() {
+	emake DESTDIR="${D}" install || die "emake install failed"
+
+	if use songs; then
+		insinto "${GAMES_DATADIR}"/${PN}/songs
+		doins -r ${WORKDIR}/Songs/* || die "doins songs failed"
+	fi
+
+	dodoc AUTHORS.txt ChangeLog.german.txt ChangeLog.txt README.txt
+
+	doicon icons/${PN}-icon.svg
+	make_desktop_entry ${PN} "UltraStar Deluxe"
+
+	prepgamesdirs
+}
diff --git a/songmanagement/dists/gentoo/ultrastardx-9999.ebuild b/songmanagement/dists/gentoo/ultrastardx-9999.ebuild
new file mode 100644
index 00000000..7b092919
--- /dev/null
+++ b/songmanagement/dists/gentoo/ultrastardx-9999.ebuild
@@ -0,0 +1,74 @@
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header $
+
+inherit subversion eutils games
+
+SONGS_PKG=USDX-SongPackage
+SONGS_VER=01
+
+DESCRIPTION="An open-source karaoke game"
+HOMEPAGE="http://www.ultrastardeluxe.org/"
+ESVN_REPO_URI="https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk"
+ESVN_PROJECT="ultrastardx"
+SRC_URI="songs? ( mirror://sourceforge/${PN}/${SONGS_PKG}-${SONGS_VER}.zip )"
+
+LICENSE="GPL-2
+	songs? (
+		CCPL-Attribution-ShareAlike-NonCommercial-2.5
+		CCPL-Attribution-NonCommercial-NoDerivs-2.5
+	)"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="projectm debug songs"
+
+RDEPEND="virtual/opengl
+	virtual/glu
+	media-libs/libsdl
+	media-libs/sdl-image
+	media-libs/freetype
+	media-libs/libpng
+	=media-libs/portaudio-19*
+	media-video/ffmpeg
+	dev-db/sqlite
+	projectm? ( media-libs/libprojectm )"
+DEPEND="${RDEPEND}
+	dev-util/pkgconfig
+	>=dev-lang/fpc-2.2.0"
+
+S=${WORKDIR}/${P}-src
+
+pkg_setup() {
+    games_pkg_setup
+    built_with_use media-libs/libsdl opengl \
+        || die "You need to compile media-libs/libsdl with USE=opengl."
+}
+
+src_unpack() {
+	unpack ${A}
+	subversion_src_unpack
+}
+
+src_compile() {
+	egamesconf \
+		$(use_with projectm libprojectM) \
+		$(use_enable debug) \
+		|| die
+	emake || die "emake failed"
+}
+
+src_install() {
+	emake DESTDIR="${D}" install || die "emake install failed"
+
+	if use songs; then
+		insinto "${GAMES_DATADIR}"/${PN}/songs
+		doins -r ${WORKDIR}/Songs/* || die "doins songs failed"
+	fi
+
+	dodoc AUTHORS.txt ChangeLog.german.txt ChangeLog.txt README.txt
+
+	doicon icons/${PN}-icon.svg
+	make_desktop_entry ${PN} "UltraStar Deluxe"
+
+	prepgamesdirs
+}
diff --git a/songmanagement/dists/lazarus/clean.bat b/songmanagement/dists/lazarus/clean.bat
new file mode 100644
index 00000000..800aafb2
--- /dev/null
+++ b/songmanagement/dists/lazarus/clean.bat
@@ -0,0 +1,8 @@
+@ECHO OFF
+set OBJ_PATH=%1
+mkdir %OBJ_PATH%
+del %OBJ_PATH%\*.o
+del %OBJ_PATH%\*.ppu
+del %OBJ_PATH%\*.a
+del %OBJ_PATH%\*.rst
+del %OBJ_PATH%\*.compiled
diff --git a/songmanagement/dists/lazarus/readme.txt b/songmanagement/dists/lazarus/readme.txt
new file mode 100755
index 00000000..012ee37a
--- /dev/null
+++ b/songmanagement/dists/lazarus/readme.txt
@@ -0,0 +1,15 @@
+Lazarus Project file
+--------------------------------------
+
+Unix:
+ 1. Copy "ultrastardx-unix.lpi" to <ultrastardx>/src 
+    (you may rename it to ultrastardx.lpi if you want)
+ 2. Start Lazarus, click on "Project -> Open Project ..."  
+    and select "ultrastardx-unix.lpi"
+
+Windows:
+ 1. Copy "ultrastardx-win.lpi" to <ultrastardx>/src 
+    (you may rename it to ultrastardx.lpi if you want)
+ 2. Copy "clean.bat" to <ultrastardx>/src 
+ 3. Start Lazarus, click on "Project -> Open Project ..."  
+    and select "ultrastardx-win.lpi"
diff --git a/songmanagement/dists/lazarus/ultrastardx-unix.lpi b/songmanagement/dists/lazarus/ultrastardx-unix.lpi
new file mode 100644
index 00000000..4160f850
--- /dev/null
+++ b/songmanagement/dists/lazarus/ultrastardx-unix.lpi
@@ -0,0 +1,598 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="/"/>
+    <Version Value="7"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <LRSInOutputDirectory Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <TargetFileExt Value=""/>
+      <Title Value="ultrastardx"/>
+    </General>
+    <VersionInfo>
+      <ProjectVersion Value=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <Units Count="127">
+      <Unit0>
+        <Filename Value="ultrastardx.dpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ultrastardx"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="base/TextGL.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="base/UCatCovers.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="base/UCommandLine.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="base/UCommon.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="base/UConfig.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="base/UCore.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="base/UCoreModule.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="base/UCovers.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="base/UDLLManager.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="base/UDataBase.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit10>
+      <Unit11>
+        <Filename Value="base/UDraw.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit11>
+      <Unit12>
+        <Filename Value="base/UEditorLyrics.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit12>
+      <Unit13>
+        <Filename Value="base/UFiles.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit13>
+      <Unit14>
+        <Filename Value="base/UFont.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit14>
+      <Unit15>
+        <Filename Value="base/UGraphic.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit15>
+      <Unit16>
+        <Filename Value="base/UGraphicClasses.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit16>
+      <Unit17>
+        <Filename Value="base/UHooks.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit17>
+      <Unit18>
+        <Filename Value="base/UImage.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit18>
+      <Unit19>
+        <Filename Value="base/UIni.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit19>
+      <Unit20>
+        <Filename Value="base/UJoystick.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit20>
+      <Unit21>
+        <Filename Value="base/ULanguage.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit21>
+      <Unit22>
+        <Filename Value="base/ULog.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit22>
+      <Unit23>
+        <Filename Value="base/ULyrics.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit23>
+      <Unit24>
+        <Filename Value="base/UMain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="UMain"/>
+      </Unit24>
+      <Unit25>
+        <Filename Value="base/UMusic.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit25>
+      <Unit26>
+        <Filename Value="base/UParty.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit26>
+      <Unit27>
+        <Filename Value="base/UPlatform.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit27>
+      <Unit28>
+        <Filename Value="base/UPlatformLinux.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit28>
+      <Unit29>
+        <Filename Value="base/UPlatformMacOSX.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit29>
+      <Unit30>
+        <Filename Value="base/UPlatformWindows.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit30>
+      <Unit31>
+        <Filename Value="base/UPlaylist.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit31>
+      <Unit32>
+        <Filename Value="base/UPluginInterface.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit32>
+      <Unit33>
+        <Filename Value="base/UPluginLoader.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit33>
+      <Unit34>
+        <Filename Value="base/URecord.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit34>
+      <Unit35>
+        <Filename Value="base/URingBuffer.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit35>
+      <Unit36>
+        <Filename Value="base/UServices.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit36>
+      <Unit37>
+        <Filename Value="base/USingNotes.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit37>
+      <Unit38>
+        <Filename Value="base/USingScores.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit38>
+      <Unit39>
+        <Filename Value="base/USkins.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit39>
+      <Unit40>
+        <Filename Value="base/USong.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit40>
+      <Unit41>
+        <Filename Value="base/USongs.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit41>
+      <Unit42>
+        <Filename Value="base/UTextClasses.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit42>
+      <Unit43>
+        <Filename Value="base/UTexture.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit43>
+      <Unit44>
+        <Filename Value="base/UThemes.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="UThemes"/>
+      </Unit44>
+      <Unit45>
+        <Filename Value="base/UTime.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="UTime"/>
+      </Unit45>
+      <Unit46>
+        <Filename Value="base/UXMLSong.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit46>
+      <Unit47>
+        <Filename Value="menu/UDisplay.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit47>
+      <Unit48>
+        <Filename Value="menu/UDrawTexture.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit48>
+      <Unit49>
+        <Filename Value="menu/UMenu.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit49>
+      <Unit50>
+        <Filename Value="menu/UMenuBackground.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit50>
+      <Unit51>
+        <Filename Value="menu/UMenuBackgroundColor.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit51>
+      <Unit52>
+        <Filename Value="menu/UMenuBackgroundFade.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit52>
+      <Unit53>
+        <Filename Value="menu/UMenuBackgroundNone.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit53>
+      <Unit54>
+        <Filename Value="menu/UMenuBackgroundTexture.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit54>
+      <Unit55>
+        <Filename Value="menu/UMenuBackgroundVideo.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit55>
+      <Unit56>
+        <Filename Value="menu/UMenuButton.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit56>
+      <Unit57>
+        <Filename Value="menu/UMenuButtonCollection.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit57>
+      <Unit58>
+        <Filename Value="menu/UMenuEqualizer.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit58>
+      <Unit59>
+        <Filename Value="menu/UMenuInteract.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit59>
+      <Unit60>
+        <Filename Value="menu/UMenuSelectSlide.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit60>
+      <Unit61>
+        <Filename Value="menu/UMenuStatic.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit61>
+      <Unit62>
+        <Filename Value="menu/UMenuText.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit62>
+      <Unit63>
+        <Filename Value="screens/UScreenCredits.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="UScreenCredits"/>
+      </Unit63>
+      <Unit64>
+        <Filename Value="screens/UScreenEdit.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit64>
+      <Unit65>
+        <Filename Value="screens/UScreenEditConvert.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit65>
+      <Unit66>
+        <Filename Value="screens/UScreenEditHeader.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit66>
+      <Unit67>
+        <Filename Value="screens/UScreenEditSub.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit67>
+      <Unit68>
+        <Filename Value="screens/UScreenLevel.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit68>
+      <Unit69>
+        <Filename Value="screens/UScreenLoading.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit69>
+      <Unit70>
+        <Filename Value="screens/UScreenMain.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit70>
+      <Unit71>
+        <Filename Value="screens/UScreenName.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit71>
+      <Unit72>
+        <Filename Value="screens/UScreenOpen.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit72>
+      <Unit73>
+        <Filename Value="screens/UScreenOptions.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit73>
+      <Unit74>
+        <Filename Value="screens/UScreenOptionsAdvanced.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit74>
+      <Unit75>
+        <Filename Value="screens/UScreenOptionsGame.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit75>
+      <Unit76>
+        <Filename Value="screens/UScreenOptionsGraphics.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit76>
+      <Unit77>
+        <Filename Value="screens/UScreenOptionsLyrics.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit77>
+      <Unit78>
+        <Filename Value="screens/UScreenOptionsRecord.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit78>
+      <Unit79>
+        <Filename Value="screens/UScreenOptionsSound.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit79>
+      <Unit80>
+        <Filename Value="screens/UScreenOptionsThemes.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit80>
+      <Unit81>
+        <Filename Value="screens/UScreenPartyNewRound.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit81>
+      <Unit82>
+        <Filename Value="screens/UScreenPartyOptions.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit82>
+      <Unit83>
+        <Filename Value="screens/UScreenPartyPlayer.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit83>
+      <Unit84>
+        <Filename Value="screens/UScreenPartyScore.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit84>
+      <Unit85>
+        <Filename Value="screens/UScreenPartyWin.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit85>
+      <Unit86>
+        <Filename Value="screens/UScreenPopup.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit86>
+      <Unit87>
+        <Filename Value="screens/UScreenScore.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit87>
+      <Unit88>
+        <Filename Value="screens/UScreenSing.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit88>
+      <Unit89>
+        <Filename Value="screens/UScreenSingModi.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit89>
+      <Unit90>
+        <Filename Value="screens/UScreenSong.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit90>
+      <Unit91>
+        <Filename Value="screens/UScreenSongJumpto.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit91>
+      <Unit92>
+        <Filename Value="screens/UScreenSongMenu.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit92>
+      <Unit93>
+        <Filename Value="screens/UScreenStatDetail.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit93>
+      <Unit94>
+        <Filename Value="screens/UScreenStatMain.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit94>
+      <Unit95>
+        <Filename Value="screens/UScreenTop5.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit95>
+      <Unit96>
+        <Filename Value="screens/UScreenWelcome.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit96>
+      <Unit97>
+        <Filename Value="media/UAudioConverter.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit97>
+      <Unit98>
+        <Filename Value="media/UAudioCore_Bass.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit98>
+      <Unit99>
+        <Filename Value="media/UAudioCore_Portaudio.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit99>
+      <Unit100>
+        <Filename Value="media/UAudioDecoder_Bass.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit100>
+      <Unit101>
+        <Filename Value="media/UAudioDecoder_FFmpeg.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit101>
+      <Unit102>
+        <Filename Value="media/UAudioInput_Bass.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit102>
+      <Unit103>
+        <Filename Value="media/UAudioInput_Portaudio.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit103>
+      <Unit104>
+        <Filename Value="media/UAudioPlaybackBase.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit104>
+      <Unit105>
+        <Filename Value="media/UAudioPlayback_Bass.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit105>
+      <Unit106>
+        <Filename Value="media/UAudioPlayback_Portaudio.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit106>
+      <Unit107>
+        <Filename Value="media/UAudioPlayback_SDL.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit107>
+      <Unit108>
+        <Filename Value="media/UAudioPlayback_SoftMixer.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit108>
+      <Unit109>
+        <Filename Value="media/UMediaCore_FFmpeg.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit109>
+      <Unit110>
+        <Filename Value="media/UMediaCore_SDL.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit110>
+      <Unit111>
+        <Filename Value="media/UMedia_dummy.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit111>
+      <Unit112>
+        <Filename Value="media/UVideo.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="UVideo"/>
+      </Unit112>
+      <Unit113>
+        <Filename Value="media/UVisualizer.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="UVisualizer"/>
+      </Unit113>
+      <Unit114>
+        <Filename Value="config-linux.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit114>
+      <Unit115>
+        <Filename Value="paths.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit115>
+      <Unit116>
+        <Filename Value="switches.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit116>
+      <Unit117>
+        <Filename Value="lua/UHookableEvent.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="UHookableEvent"/>
+      </Unit117>
+      <Unit118>
+        <Filename Value="lua/ULuaCore.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaCore"/>
+      </Unit118>
+      <Unit119>
+        <Filename Value="lua/ULuaGl.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaGl"/>
+      </Unit119>
+      <Unit120>
+        <Filename Value="lua/ULuaLog.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaLog"/>
+      </Unit120>
+      <Unit121>
+        <Filename Value="lua/ULuaParty.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaParty"/>
+      </Unit121>
+      <Unit122>
+        <Filename Value="lua/ULuaScreenSing.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaScreenSing"/>
+      </Unit122>
+      <Unit123>
+        <Filename Value="lua/ULuaTextGL.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaTextGL"/>
+      </Unit123>
+      <Unit124>
+        <Filename Value="lua/ULuaTexture.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaTexture"/>
+      </Unit124>
+      <Unit125>
+        <Filename Value="lua/ULuaUsdx.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaUsdx"/>
+      </Unit125>
+      <Unit126>
+        <Filename Value="lua/ULuaUtils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaUtils"/>
+      </Unit126>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="8"/>
+    <Target>
+      <Filename Value="../game/ultrastardx"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="lib/JEDI-SDL/SDL/Pas/"/>
+      <OtherUnitFiles Value="base/;menu/;screens/;media/;lib/;lua/"/>
+      <UnitOutputDirectory Value="../build/fpc-$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <CStyleOperator Value="False"/>
+        <AllowLabel Value="False"/>
+      </SyntaxOptions>
+    </Parsing>
+    <Linking>
+      <Debugging>
+        <GenerateDebugInfo Value="True"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <Verbosity>
+        <ShowNotes Value="False"/>
+        <ShowHints Value="False"/>
+      </Verbosity>
+      <CompilerPath Value="$(CompPath)"/>
+      <ExecuteBefore>
+        <Command Value="/usr/bin/make"/>
+        <ScanForFPCMsgs Value="True"/>
+        <ScanForMakeMsgs Value="True"/>
+      </ExecuteBefore>
+      <ExecuteAfter>
+        <CompileReasons Compile="False" Build="False" Run="False"/>
+      </ExecuteAfter>
+    </Other>
+    <CompileReasons Compile="False" Build="False" Run="False"/>
+  </CompilerOptions>
+</CONFIG>
diff --git a/songmanagement/dists/lazarus/ultrastardx-win.lpi b/songmanagement/dists/lazarus/ultrastardx-win.lpi
new file mode 100644
index 00000000..acce323b
--- /dev/null
+++ b/songmanagement/dists/lazarus/ultrastardx-win.lpi
@@ -0,0 +1,590 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="\"/>
+    <Version Value="7"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <AlwaysBuild Value="False"/>
+        <LRSInOutputDirectory Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <TargetFileExt Value=".exe"/>
+      <Title Value="ultrastardx"/>
+    </General>
+    <VersionInfo>
+      <ProjectVersion Value=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <Units Count="127">
+      <Unit0>
+        <Filename Value="ultrastardx.dpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ultrastardx"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="base\UXMLSong.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="base\TextGL.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="base\UCatCovers.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="base\UCommandLine.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="base\UCommon.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="base\UConfig.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="base\UCore.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="base\UCoreModule.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="base\UCovers.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="base\UDataBase.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit10>
+      <Unit11>
+        <Filename Value="base\UDLLManager.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit11>
+      <Unit12>
+        <Filename Value="base\UDraw.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit12>
+      <Unit13>
+        <Filename Value="base\UEditorLyrics.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit13>
+      <Unit14>
+        <Filename Value="base\UFiles.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit14>
+      <Unit15>
+        <Filename Value="base\UFont.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit15>
+      <Unit16>
+        <Filename Value="base\UGraphic.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit16>
+      <Unit17>
+        <Filename Value="base\UGraphicClasses.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit17>
+      <Unit18>
+        <Filename Value="base\UHooks.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit18>
+      <Unit19>
+        <Filename Value="base\UImage.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit19>
+      <Unit20>
+        <Filename Value="base\UIni.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit20>
+      <Unit21>
+        <Filename Value="base\UJoystick.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit21>
+      <Unit22>
+        <Filename Value="base\ULanguage.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit22>
+      <Unit23>
+        <Filename Value="base\ULog.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit23>
+      <Unit24>
+        <Filename Value="base\ULyrics.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit24>
+      <Unit25>
+        <Filename Value="base\UMain.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit25>
+      <Unit26>
+        <Filename Value="base\UModules.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit26>
+      <Unit27>
+        <Filename Value="base\UMusic.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit27>
+      <Unit28>
+        <Filename Value="base\UParty.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit28>
+      <Unit29>
+        <Filename Value="base\UPlatform.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit29>
+      <Unit30>
+        <Filename Value="base\UPlatformLinux.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit30>
+      <Unit31>
+        <Filename Value="base\UPlatformMacOSX.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit31>
+      <Unit32>
+        <Filename Value="base\UPlatformWindows.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit32>
+      <Unit33>
+        <Filename Value="base\UPlaylist.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit33>
+      <Unit34>
+        <Filename Value="base\UPluginInterface.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit34>
+      <Unit35>
+        <Filename Value="base\UPluginLoader.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit35>
+      <Unit36>
+        <Filename Value="base\URecord.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit36>
+      <Unit37>
+        <Filename Value="base\URingBuffer.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit37>
+      <Unit38>
+        <Filename Value="base\UServices.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit38>
+      <Unit39>
+        <Filename Value="base\USingNotes.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit39>
+      <Unit40>
+        <Filename Value="base\USingScores.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit40>
+      <Unit41>
+        <Filename Value="base\USkins.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit41>
+      <Unit42>
+        <Filename Value="base\USong.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit42>
+      <Unit43>
+        <Filename Value="base\USongs.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit43>
+      <Unit44>
+        <Filename Value="base\UTextClasses.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit44>
+      <Unit45>
+        <Filename Value="base\UTexture.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit45>
+      <Unit46>
+        <Filename Value="base\UThemes.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit46>
+      <Unit47>
+        <Filename Value="base\UTime.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit47>
+      <Unit48>
+        <Filename Value="menu\UMenuText.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit48>
+      <Unit49>
+        <Filename Value="menu\UDisplay.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit49>
+      <Unit50>
+        <Filename Value="menu\UDrawTexture.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit50>
+      <Unit51>
+        <Filename Value="menu\UMenu.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit51>
+      <Unit52>
+        <Filename Value="menu\UMenuBackground.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit52>
+      <Unit53>
+        <Filename Value="menu\UMenuBackgroundColor.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit53>
+      <Unit54>
+        <Filename Value="menu\UMenuBackgroundFade.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit54>
+      <Unit55>
+        <Filename Value="menu\UMenuBackgroundNone.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit55>
+      <Unit56>
+        <Filename Value="menu\UMenuBackgroundTexture.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit56>
+      <Unit57>
+        <Filename Value="menu\UMenuBackgroundVideo.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit57>
+      <Unit58>
+        <Filename Value="menu\UMenuButton.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit58>
+      <Unit59>
+        <Filename Value="menu\UMenuButtonCollection.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit59>
+      <Unit60>
+        <Filename Value="menu\UMenuEqualizer.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit60>
+      <Unit61>
+        <Filename Value="menu\UMenuInteract.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit61>
+      <Unit62>
+        <Filename Value="menu\UMenuSelectSlide.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit62>
+      <Unit63>
+        <Filename Value="menu\UMenuStatic.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit63>
+      <Unit64>
+        <Filename Value="screens\UScreenWelcome.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit64>
+      <Unit65>
+        <Filename Value="screens\UScreenCredits.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit65>
+      <Unit66>
+        <Filename Value="screens\UScreenEdit.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit66>
+      <Unit67>
+        <Filename Value="screens\UScreenEditConvert.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit67>
+      <Unit68>
+        <Filename Value="screens\UScreenEditHeader.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit68>
+      <Unit69>
+        <Filename Value="screens\UScreenEditSub.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit69>
+      <Unit70>
+        <Filename Value="screens\UScreenLevel.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit70>
+      <Unit71>
+        <Filename Value="screens\UScreenLoading.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit71>
+      <Unit72>
+        <Filename Value="screens\UScreenMain.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit72>
+      <Unit73>
+        <Filename Value="screens\UScreenName.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit73>
+      <Unit74>
+        <Filename Value="screens\UScreenOpen.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit74>
+      <Unit75>
+        <Filename Value="screens\UScreenOptions.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit75>
+      <Unit76>
+        <Filename Value="screens\UScreenOptionsAdvanced.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit76>
+      <Unit77>
+        <Filename Value="screens\UScreenOptionsGame.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit77>
+      <Unit78>
+        <Filename Value="screens\UScreenOptionsGraphics.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit78>
+      <Unit79>
+        <Filename Value="screens\UScreenOptionsLyrics.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit79>
+      <Unit80>
+        <Filename Value="screens\UScreenOptionsRecord.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit80>
+      <Unit81>
+        <Filename Value="screens\UScreenOptionsSound.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit81>
+      <Unit82>
+        <Filename Value="screens\UScreenOptionsThemes.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit82>
+      <Unit83>
+        <Filename Value="screens\UScreenPartyNewRound.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit83>
+      <Unit84>
+        <Filename Value="screens\UScreenPartyOptions.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit84>
+      <Unit85>
+        <Filename Value="screens\UScreenPartyPlayer.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit85>
+      <Unit86>
+        <Filename Value="screens\UScreenPartyScore.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit86>
+      <Unit87>
+        <Filename Value="screens\UScreenPartyWin.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit87>
+      <Unit88>
+        <Filename Value="screens\UScreenPopup.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit88>
+      <Unit89>
+        <Filename Value="screens\UScreenScore.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit89>
+      <Unit90>
+        <Filename Value="screens\UScreenSing.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit90>
+      <Unit91>
+        <Filename Value="screens\UScreenSingModi.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit91>
+      <Unit92>
+        <Filename Value="screens\UScreenSong.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit92>
+      <Unit93>
+        <Filename Value="screens\UScreenSongJumpto.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit93>
+      <Unit94>
+        <Filename Value="screens\UScreenSongMenu.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit94>
+      <Unit95>
+        <Filename Value="screens\UScreenStatDetail.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit95>
+      <Unit96>
+        <Filename Value="screens\UScreenStatMain.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit96>
+      <Unit97>
+        <Filename Value="screens\UScreenTop5.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit97>
+      <Unit98>
+        <Filename Value="media\UVisualizer.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit98>
+      <Unit99>
+        <Filename Value="media\UAudioConverter.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit99>
+      <Unit100>
+        <Filename Value="media\UAudioCore_Bass.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit100>
+      <Unit101>
+        <Filename Value="media\UAudioCore_Portaudio.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit101>
+      <Unit102>
+        <Filename Value="media\UAudioDecoder_Bass.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit102>
+      <Unit103>
+        <Filename Value="media\UAudioDecoder_FFmpeg.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit103>
+      <Unit104>
+        <Filename Value="media\UAudioInput_Bass.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit104>
+      <Unit105>
+        <Filename Value="media\UAudioInput_Portaudio.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit105>
+      <Unit106>
+        <Filename Value="media\UAudioPlayback_Bass.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit106>
+      <Unit107>
+        <Filename Value="media\UAudioPlayback_Portaudio.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit107>
+      <Unit108>
+        <Filename Value="media\UAudioPlayback_SDL.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit108>
+      <Unit109>
+        <Filename Value="media\UAudioPlayback_SoftMixer.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit109>
+      <Unit110>
+        <Filename Value="media\UAudioPlaybackBase.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit110>
+      <Unit111>
+        <Filename Value="media\UMedia_dummy.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit111>
+      <Unit112>
+        <Filename Value="media\UMediaCore_FFmpeg.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit112>
+      <Unit113>
+        <Filename Value="media\UMediaCore_SDL.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit113>
+      <Unit114>
+        <Filename Value="media\UVideo.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit114>
+      <Unit115>
+        <Filename Value="switches.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit115>
+      <Unit116>
+        <Filename Value="config-win.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit116>
+      <Unit117>
+        <Filename Value="lua\ULuaUtils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaUtils"/>
+      </Unit117>
+      <Unit118>
+        <Filename Value="lua\UHookableEvent.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="UHookableEvent"/>
+      </Unit118>
+      <Unit119>
+        <Filename Value="lua\ULuaCore.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaCore"/>
+      </Unit119>
+      <Unit120>
+        <Filename Value="lua\ULuaGl.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaGl"/>
+      </Unit120>
+      <Unit121>
+        <Filename Value="lua\ULuaLog.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaLog"/>
+      </Unit121>
+      <Unit122>
+        <Filename Value="lua\ULuaParty.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaParty"/>
+      </Unit122>
+      <Unit123>
+        <Filename Value="lua\ULuaScreenSing.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaScreenSing"/>
+      </Unit123>
+      <Unit124>
+        <Filename Value="lua\ULuaTextGL.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaTextGL"/>
+      </Unit124>
+      <Unit125>
+        <Filename Value="lua\ULuaTexture.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaTexture"/>
+      </Unit125>
+      <Unit126>
+        <Filename Value="lua\ULuaUsdx.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ULuaUsdx"/>
+      </Unit126>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="8"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="..\game\ultrastardx"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="lib\JEDI-SDL\SDL\Pas\"/>
+      <OtherUnitFiles Value="base\;lua\;media\;menu\;screens\;lib\JEDI-SDL\SDL\Pas\;lib\JEDI-SDL\SDL_Image\Pas\;lib\JEDI-SDL\OpenGL\Pas\;lib\portaudio\;lib\ffmpeg\;lib\SQLite\;lib\other\"/>
+      <UnitOutputDirectory Value="..\build\fpc-$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <CStyleOperator Value="False"/>
+        <AllowLabel Value="False"/>
+      </SyntaxOptions>
+    </Parsing>
+    <Linking>
+      <Debugging>
+        <GenerateDebugInfo Value="True"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <Verbosity>
+        <ShowNotes Value="False"/>
+        <ShowHints Value="False"/>
+      </Verbosity>
+      <CompilerPath Value="$(CompPath)"/>
+      <ExecuteBefore>
+        <Command Value="clean.bat ..\build\fpc-$(TargetCPU)-$(TargetOS)"/>
+        <CompileReasons Run="False"/>
+      </ExecuteBefore>
+    </Other>
+    <CompileReasons Run="False"/>
+  </CompilerOptions>
+</CONFIG>
diff --git a/songmanagement/dists/ultrastardx.desktop b/songmanagement/dists/ultrastardx.desktop
new file mode 100644
index 00000000..d49f05ef
--- /dev/null
+++ b/songmanagement/dists/ultrastardx.desktop
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+
+Name=UltraStar Deluxe
+Comment=Karaoke program that evaluates your performance
+Comment[de]=Singe Karaoke und messe dich mit anderen Spielern
+
+Icon=ultrastardx
+
+TryExec=ultrastardx
+Exec=ultrastardx
+StartupNotify=false
+Terminal=false
+
+Type=Application
+Categories=Application;Game;ArcadeGame;
diff --git a/songmanagement/dists/xcode/English.lproj/InfoPlist.strings b/songmanagement/dists/xcode/English.lproj/InfoPlist.strings
new file mode 100755
index 00000000..ce30d99a
Binary files /dev/null and b/songmanagement/dists/xcode/English.lproj/InfoPlist.strings differ
diff --git a/songmanagement/dists/xcode/English.lproj/SDLMain.nib/classes.nib b/songmanagement/dists/xcode/English.lproj/SDLMain.nib/classes.nib
new file mode 100644
index 00000000..799eaadd
--- /dev/null
+++ b/songmanagement/dists/xcode/English.lproj/SDLMain.nib/classes.nib
@@ -0,0 +1,19 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {
+            ACTIONS = {
+                help = id; 
+                newGame = id; 
+                openGame = id; 
+                prefsMenu = id; 
+                saveGame = id; 
+                saveGameAs = id; 
+            }; 
+            CLASS = SDLMain; 
+            LANGUAGE = ObjC; 
+            SUPERCLASS = NSObject; 
+        }
+    ); 
+    IBVersion = 1; 
+}
\ No newline at end of file
diff --git a/songmanagement/dists/xcode/English.lproj/SDLMain.nib/info.nib b/songmanagement/dists/xcode/English.lproj/SDLMain.nib/info.nib
new file mode 100644
index 00000000..1d6fb7e0
--- /dev/null
+++ b/songmanagement/dists/xcode/English.lproj/SDLMain.nib/info.nib
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBDocumentLocation</key>
+	<string>62 117 356 240 0 0 1152 848 </string>
+	<key>IBEditorPositions</key>
+	<dict>
+		<key>29</key>
+		<string>62 362 195 44 0 0 1152 848 </string>
+	</dict>
+	<key>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>29</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6L60</string>
+</dict>
+</plist>
diff --git a/songmanagement/dists/xcode/English.lproj/SDLMain.nib/objects.nib b/songmanagement/dists/xcode/English.lproj/SDLMain.nib/objects.nib
new file mode 100644
index 00000000..63780152
Binary files /dev/null and b/songmanagement/dists/xcode/English.lproj/SDLMain.nib/objects.nib differ
diff --git a/songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.mode1 b/songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.mode1
new file mode 100644
index 00000000..578575c4
--- /dev/null
+++ b/songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.mode1
@@ -0,0 +1,1408 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ActivePerspectiveName</key>
+	<string>Project</string>
+	<key>AllowedModules</key>
+	<array>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXSmartGroupTreeModule</string>
+			<key>Name</key>
+			<string>Groups and Files Outline View</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXNavigatorGroup</string>
+			<key>Name</key>
+			<string>Editor</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCTaskListModule</string>
+			<key>Name</key>
+			<string>Task List</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCDetailModule</string>
+			<key>Name</key>
+			<string>File and Smart Group Detail Viewer</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXBuildResultsModule</string>
+			<key>Name</key>
+			<string>Detailed Build Results Viewer</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXProjectFindModule</string>
+			<key>Name</key>
+			<string>Project Batch Find Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXRunSessionModule</string>
+			<key>Name</key>
+			<string>Run Log</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXBookmarksModule</string>
+			<key>Name</key>
+			<string>Bookmarks Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXClassBrowserModule</string>
+			<key>Name</key>
+			<string>Class Browser</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXCVSModule</string>
+			<key>Name</key>
+			<string>Source Code Control Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXDebugBreakpointsModule</string>
+			<key>Name</key>
+			<string>Debug Breakpoints Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCDockableInspector</string>
+			<key>Name</key>
+			<string>Inspector</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXOpenQuicklyModule</string>
+			<key>Name</key>
+			<string>Open Quickly Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXDebugSessionModule</string>
+			<key>Name</key>
+			<string>Debugger</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXDebugCLIModule</string>
+			<key>Name</key>
+			<string>Debug Console</string>
+		</dict>
+	</array>
+	<key>Description</key>
+	<string>DefaultDescriptionKey</string>
+	<key>DockingSystemVisible</key>
+	<false/>
+	<key>Extension</key>
+	<string>mode1</string>
+	<key>FavBarConfig</key>
+	<dict>
+		<key>PBXProjectModuleGUID</key>
+		<string>2CDD4B6F0CB935C700549FAC</string>
+		<key>XCBarModuleItemNames</key>
+		<dict/>
+		<key>XCBarModuleItems</key>
+		<array/>
+	</dict>
+	<key>FirstTimeWindowDisplayed</key>
+	<false/>
+	<key>Identifier</key>
+	<string>com.apple.perspectives.project.mode1</string>
+	<key>MajorVersion</key>
+	<integer>31</integer>
+	<key>MinorVersion</key>
+	<integer>1</integer>
+	<key>Name</key>
+	<string>Default</string>
+	<key>Notifications</key>
+	<array/>
+	<key>OpenEditors</key>
+	<array>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2CAE5FE50CE3B914009D9EF2</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>USongs.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2CAE5FE60CE3B914009D9EF2</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>USongs.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CF1EFD70CE77D5600B5167D</string>
+						<key>history</key>
+						<array>
+							<string>2C0B367E0CE3D50000158AB2</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {797, 748}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>15 212 797 789 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2CC28B200CE3C14E00D16793</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>UPlatformWindows.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2CC28B210CE3C14E00D16793</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>UPlatformWindows.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CF1EFD80CE77D5600B5167D</string>
+						<key>history</key>
+						<array>
+							<string>2C0B367F0CE3D50000158AB2</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {776, 859}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>15 123 776 900 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+	</array>
+	<key>PerspectiveWidths</key>
+	<array>
+		<integer>-1</integer>
+		<integer>-1</integer>
+	</array>
+	<key>Perspectives</key>
+	<array>
+		<dict>
+			<key>ChosenToolbarItems</key>
+			<array>
+				<string>active-target-popup</string>
+				<string>active-buildstyle-popup</string>
+				<string>action</string>
+				<string>NSToolbarFlexibleSpaceItem</string>
+				<string>buildOrClean</string>
+				<string>build-and-runOrDebug</string>
+				<string>com.apple.ide.PBXToolbarStopButton</string>
+				<string>get-info</string>
+				<string>toggle-editor</string>
+				<string>NSToolbarFlexibleSpaceItem</string>
+				<string>com.apple.pbx.toolbar.searchfield</string>
+			</array>
+			<key>ControllerClassBaseName</key>
+			<string></string>
+			<key>IconName</key>
+			<string>WindowOfProjectWithEditor</string>
+			<key>Identifier</key>
+			<string>perspective.project</string>
+			<key>IsVertical</key>
+			<false/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>ContentConfiguration</key>
+					<dict>
+						<key>PBXBottomSmartGroupGIDs</key>
+						<array>
+							<string>1C37FBAC04509CD000000102</string>
+							<string>1C37FAAC04509CD000000102</string>
+							<string>1C08E77C0454961000C914BD</string>
+							<string>1C37FABC05509CD000000102</string>
+							<string>1C37FABC05539CD112110102</string>
+							<string>E2644B35053B69B200211256</string>
+							<string>1C37FABC04509CD000100104</string>
+							<string>1CC0EA4004350EF90044410B</string>
+							<string>1CC0EA4004350EF90041110B</string>
+						</array>
+						<key>PBXProjectModuleGUID</key>
+						<string>1CE0B1FE06471DED0097A5F4</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>Files</string>
+						<key>PBXProjectStructureProvided</key>
+						<string>yes</string>
+						<key>PBXSmartGroupTreeModuleColumnData</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+							<array>
+								<real>266</real>
+							</array>
+							<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+							<array>
+								<string>MainColumn</string>
+							</array>
+						</dict>
+						<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+							<array>
+								<string>DDC6850D09F5717A004E4BFF</string>
+								<string>DD7C45450A6E72DE003FA52B</string>
+								<string>1C37FBAC04509CD000000102</string>
+								<string>1C37FAAC04509CD000000102</string>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+							<array>
+								<array>
+									<integer>17</integer>
+									<integer>15</integer>
+									<integer>0</integer>
+								</array>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+							<string>{{0, 0}, {266, 694}}</string>
+						</dict>
+						<key>PBXTopSmartGroupGIDs</key>
+						<array/>
+						<key>XCIncludePerspectivesSwitch</key>
+						<true/>
+						<key>XCSharingToken</key>
+						<string>com.apple.Xcode.GFSharingToken</string>
+					</dict>
+					<key>GeometryConfiguration</key>
+					<dict>
+						<key>Frame</key>
+						<string>{{0, 0}, {283, 712}}</string>
+						<key>GroupTreeTableConfiguration</key>
+						<array>
+							<string>MainColumn</string>
+							<real>266</real>
+						</array>
+						<key>RubberWindowFrame</key>
+						<string>858 143 817 753 0 0 1680 1028 </string>
+					</dict>
+					<key>Module</key>
+					<string>PBXSmartGroupTreeModule</string>
+					<key>Proportion</key>
+					<string>283pt</string>
+				</dict>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CE0B20306471E060097A5F4</string>
+								<key>PBXProjectModuleLabel</key>
+								<string></string>
+								<key>PBXSplitModuleInNavigatorKey</key>
+								<dict>
+									<key>Split0</key>
+									<dict>
+										<key>PBXProjectModuleGUID</key>
+										<string>1CE0B20406471E060097A5F4</string>
+										<key>PBXProjectModuleLabel</key>
+										<string></string>
+									</dict>
+									<key>SplitCount</key>
+									<string>1</string>
+								</dict>
+								<key>StatusBarVisibility</key>
+								<true/>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {529, 0}}</string>
+								<key>RubberWindowFrame</key>
+								<string>858 143 817 753 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>0pt</string>
+						</dict>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CE0B20506471E060097A5F4</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Detail</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 5}, {529, 707}}</string>
+								<key>RubberWindowFrame</key>
+								<string>858 143 817 753 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>XCDetailModule</string>
+							<key>Proportion</key>
+							<string>707pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>529pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Project</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCModuleDock</string>
+				<string>PBXSmartGroupTreeModule</string>
+				<string>XCModuleDock</string>
+				<string>PBXNavigatorGroup</string>
+				<string>XCDetailModule</string>
+			</array>
+			<key>TableOfContents</key>
+			<array>
+				<string>2CF1EFD10CE77D5600B5167D</string>
+				<string>1CE0B1FE06471DED0097A5F4</string>
+				<string>2CF1EFD20CE77D5600B5167D</string>
+				<string>1CE0B20306471E060097A5F4</string>
+				<string>1CE0B20506471E060097A5F4</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.default</string>
+		</dict>
+		<dict>
+			<key>ControllerClassBaseName</key>
+			<string></string>
+			<key>IconName</key>
+			<string>WindowOfProject</string>
+			<key>Identifier</key>
+			<string>perspective.morph</string>
+			<key>IsVertical</key>
+			<integer>0</integer>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>BecomeActive</key>
+					<integer>1</integer>
+					<key>ContentConfiguration</key>
+					<dict>
+						<key>PBXBottomSmartGroupGIDs</key>
+						<array>
+							<string>1C37FBAC04509CD000000102</string>
+							<string>1C37FAAC04509CD000000102</string>
+							<string>1C08E77C0454961000C914BD</string>
+							<string>1C37FABC05509CD000000102</string>
+							<string>1C37FABC05539CD112110102</string>
+							<string>E2644B35053B69B200211256</string>
+							<string>1C37FABC04509CD000100104</string>
+							<string>1CC0EA4004350EF90044410B</string>
+							<string>1CC0EA4004350EF90041110B</string>
+						</array>
+						<key>PBXProjectModuleGUID</key>
+						<string>11E0B1FE06471DED0097A5F4</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>Files</string>
+						<key>PBXProjectStructureProvided</key>
+						<string>yes</string>
+						<key>PBXSmartGroupTreeModuleColumnData</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+							<array>
+								<real>186</real>
+							</array>
+							<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+							<array>
+								<string>MainColumn</string>
+							</array>
+						</dict>
+						<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+							<array>
+								<string>29B97314FDCFA39411CA2CEA</string>
+								<string>1C37FABC05509CD000000102</string>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+							<array>
+								<array>
+									<integer>0</integer>
+								</array>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+							<string>{{0, 0}, {186, 337}}</string>
+						</dict>
+						<key>PBXTopSmartGroupGIDs</key>
+						<array/>
+						<key>XCIncludePerspectivesSwitch</key>
+						<integer>1</integer>
+						<key>XCSharingToken</key>
+						<string>com.apple.Xcode.GFSharingToken</string>
+					</dict>
+					<key>GeometryConfiguration</key>
+					<dict>
+						<key>Frame</key>
+						<string>{{0, 0}, {203, 355}}</string>
+						<key>GroupTreeTableConfiguration</key>
+						<array>
+							<string>MainColumn</string>
+							<real>186</real>
+						</array>
+						<key>RubberWindowFrame</key>
+						<string>373 269 690 397 0 0 1440 878 </string>
+					</dict>
+					<key>Module</key>
+					<string>PBXSmartGroupTreeModule</string>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Morph</string>
+			<key>PreferredWidth</key>
+			<integer>300</integer>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCModuleDock</string>
+				<string>PBXSmartGroupTreeModule</string>
+			</array>
+			<key>TableOfContents</key>
+			<array>
+				<string>11E0B1FE06471DED0097A5F4</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.default.short</string>
+		</dict>
+	</array>
+	<key>PerspectivesBarVisible</key>
+	<false/>
+	<key>ShelfIsVisible</key>
+	<false/>
+	<key>SourceDescription</key>
+	<string>file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string>
+	<key>StatusbarIsVisible</key>
+	<true/>
+	<key>TimeStamp</key>
+	<real>0.0</real>
+	<key>ToolbarDisplayMode</key>
+	<integer>1</integer>
+	<key>ToolbarIsVisible</key>
+	<true/>
+	<key>ToolbarSizeMode</key>
+	<integer>1</integer>
+	<key>Type</key>
+	<string>Perspectives</string>
+	<key>UpdateMessage</key>
+	<string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature).  You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature.  Do you wish to update to the latest Workspace defaults for project '%@'?</string>
+	<key>WindowJustification</key>
+	<integer>5</integer>
+	<key>WindowOrderList</key>
+	<array>
+		<string>2CC28B200CE3C14E00D16793</string>
+		<string>2CAE5FE50CE3B914009D9EF2</string>
+		<string>1C0AD2B3069F1EA900FABCE6</string>
+		<string>/Users/eddie/Projekte/UltraStarDX/trunk/Game/Code/MacOSX/UltraStarDX.xcodeproj</string>
+	</array>
+	<key>WindowString</key>
+	<string>858 143 817 753 0 0 1680 1028 </string>
+	<key>WindowTools</key>
+	<array>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.build</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD0528F0623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string></string>
+								<key>StatusBarVisibility</key>
+								<true/>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {1346, 566}}</string>
+								<key>RubberWindowFrame</key>
+								<string>106 169 1346 848 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>566pt</string>
+						</dict>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>XCMainBuildResultsModuleGUID</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Build</string>
+								<key>XCBuildResultsTrigger_Collapse</key>
+								<integer>1021</integer>
+								<key>XCBuildResultsTrigger_Open</key>
+								<integer>1011</integer>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 571}, {1346, 236}}</string>
+								<key>RubberWindowFrame</key>
+								<string>106 169 1346 848 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXBuildResultsModule</string>
+							<key>Proportion</key>
+							<string>236pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>807pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Build Results</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXBuildResultsModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>2CDD4B730CB935C700549FAC</string>
+				<string>2C0B36810CE3D50000158AB2</string>
+				<string>1CD0528F0623707200166675</string>
+				<string>XCMainBuildResultsModuleGUID</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.build</string>
+			<key>WindowString</key>
+			<string>106 169 1346 848 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>2CDD4B730CB935C700549FAC</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.debugger</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>Debugger</key>
+								<dict>
+									<key>HorizontalSplitView</key>
+									<dict>
+										<key>_collapsingFrameDimension</key>
+										<real>0.0</real>
+										<key>_indexOfCollapsedView</key>
+										<integer>0</integer>
+										<key>_percentageOfCollapsedView</key>
+										<real>0.0</real>
+										<key>isCollapsed</key>
+										<string>yes</string>
+										<key>sizes</key>
+										<array>
+											<string>{{0, 0}, {333, 414}}</string>
+											<string>{{333, 0}, {631, 414}}</string>
+										</array>
+									</dict>
+									<key>VerticalSplitView</key>
+									<dict>
+										<key>_collapsingFrameDimension</key>
+										<real>0.0</real>
+										<key>_indexOfCollapsedView</key>
+										<integer>0</integer>
+										<key>_percentageOfCollapsedView</key>
+										<real>0.0</real>
+										<key>isCollapsed</key>
+										<string>yes</string>
+										<key>sizes</key>
+										<array>
+											<string>{{0, 0}, {964, 414}}</string>
+											<string>{{0, 414}, {964, 374}}</string>
+										</array>
+									</dict>
+								</dict>
+								<key>LauncherConfigVersion</key>
+								<string>8</string>
+								<key>PBXProjectModuleGUID</key>
+								<string>1C162984064C10D400B95A72</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Debug - GLUTExamples (Underwater)</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>DebugConsoleDrawerSize</key>
+								<string>{100, 120}</string>
+								<key>DebugConsoleVisible</key>
+								<string>None</string>
+								<key>DebugConsoleWindowFrame</key>
+								<string>{{200, 200}, {500, 300}}</string>
+								<key>DebugSTDIOWindowFrame</key>
+								<string>{{200, 200}, {500, 300}}</string>
+								<key>Frame</key>
+								<string>{{0, 0}, {964, 788}}</string>
+								<key>RubberWindowFrame</key>
+								<string>227 162 964 829 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXDebugSessionModule</string>
+							<key>Proportion</key>
+							<string>788pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>788pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Debugger</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXDebugSessionModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1CD10A99069EF8BA00B06720</string>
+				<string>2C89371D0CE3926A005D8A87</string>
+				<string>1C162984064C10D400B95A72</string>
+				<string>2C89371E0CE3926A005D8A87</string>
+				<string>2C89371F0CE3926A005D8A87</string>
+				<string>2C8937200CE3926A005D8A87</string>
+				<string>2C8937210CE3926A005D8A87</string>
+				<string>2C8937220CE3926A005D8A87</string>
+				<string>2C8937230CE3926A005D8A87</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.debug</string>
+			<key>WindowString</key>
+			<string>227 162 964 829 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>1CD10A99069EF8BA00B06720</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.find</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Dock</key>
+							<array>
+								<dict>
+									<key>BecomeActive</key>
+									<true/>
+									<key>ContentConfiguration</key>
+									<dict>
+										<key>PBXProjectModuleGUID</key>
+										<string>1CDD528C0622207200134675</string>
+										<key>PBXProjectModuleLabel</key>
+										<string>UCommon.pas</string>
+										<key>StatusBarVisibility</key>
+										<true/>
+									</dict>
+									<key>GeometryConfiguration</key>
+									<dict>
+										<key>Frame</key>
+										<string>{{0, 0}, {790, 502}}</string>
+										<key>RubberWindowFrame</key>
+										<string>821 68 790 888 0 0 1680 1028 </string>
+									</dict>
+									<key>Module</key>
+									<string>PBXNavigatorGroup</string>
+									<key>Proportion</key>
+									<string>790pt</string>
+								</dict>
+							</array>
+							<key>Proportion</key>
+							<string>502pt</string>
+						</dict>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD0528E0623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Project Find</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 507}, {790, 340}}</string>
+								<key>RubberWindowFrame</key>
+								<string>821 68 790 888 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXProjectFindModule</string>
+							<key>Proportion</key>
+							<string>340pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>847pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Project Find</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXProjectFindModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C530D57069F1CE1000CFCEE</string>
+				<string>2C5C69C90CE3B3AF00545A7B</string>
+				<string>2C5C69CA0CE3B3AF00545A7B</string>
+				<string>1CDD528C0622207200134675</string>
+				<string>1CD0528E0623707200166675</string>
+			</array>
+			<key>WindowString</key>
+			<string>821 68 790 888 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>1C530D57069F1CE1000CFCEE</string>
+			<key>WindowToolIsVisible</key>
+			<true/>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>MENUSEPARATOR</string>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.debuggerConsole</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1C78EAAC065D492600B07095</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Debugger Console</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {1245, 708}}</string>
+								<key>RubberWindowFrame</key>
+								<string>410 84 1245 749 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXDebugCLIModule</string>
+							<key>Proportion</key>
+							<string>708pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>708pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Debugger Console</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXDebugCLIModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>2CDD4BFC0CB948FC00549FAC</string>
+				<string>2C8937D00CE3A1FF005D8A87</string>
+				<string>1C78EAAC065D492600B07095</string>
+			</array>
+			<key>WindowString</key>
+			<string>410 84 1245 749 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>2CDD4BFC0CB948FC00549FAC</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.run</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>LauncherConfigVersion</key>
+								<string>3</string>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD0528B0623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Run</string>
+								<key>Runner</key>
+								<dict>
+									<key>HorizontalSplitView</key>
+									<dict>
+										<key>_collapsingFrameDimension</key>
+										<real>0.0</real>
+										<key>_indexOfCollapsedView</key>
+										<integer>0</integer>
+										<key>_percentageOfCollapsedView</key>
+										<real>0.0</real>
+										<key>isCollapsed</key>
+										<string>yes</string>
+										<key>sizes</key>
+										<array>
+											<string>{{0, 0}, {493, 167}}</string>
+											<string>{{0, 176}, {493, 267}}</string>
+										</array>
+									</dict>
+									<key>VerticalSplitView</key>
+									<dict>
+										<key>_collapsingFrameDimension</key>
+										<real>0.0</real>
+										<key>_indexOfCollapsedView</key>
+										<integer>0</integer>
+										<key>_percentageOfCollapsedView</key>
+										<real>0.0</real>
+										<key>isCollapsed</key>
+										<string>yes</string>
+										<key>sizes</key>
+										<array>
+											<string>{{0, 0}, {405, 443}}</string>
+											<string>{{414, 0}, {514, 443}}</string>
+										</array>
+									</dict>
+								</dict>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {1092, 660}}</string>
+								<key>RubberWindowFrame</key>
+								<string>266 221 1092 701 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXRunSessionModule</string>
+							<key>Proportion</key>
+							<string>660pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>660pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Run Log</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXRunSessionModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C0AD2B3069F1EA900FABCE6</string>
+				<string>2CF1EFD50CE77D5600B5167D</string>
+				<string>1CD0528B0623707200166675</string>
+				<string>2CF1EFD60CE77D5600B5167D</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.run</string>
+			<key>WindowString</key>
+			<string>266 221 1092 701 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>1C0AD2B3069F1EA900FABCE6</string>
+			<key>WindowToolIsVisible</key>
+			<true/>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.scm</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1C78EAB2065D492600B07095</string>
+								<key>PBXProjectModuleLabel</key>
+								<string></string>
+								<key>StatusBarVisibility</key>
+								<true/>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {452, 0}}</string>
+								<key>RubberWindowFrame</key>
+								<string>194 589 452 308 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>0pt</string>
+						</dict>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD052920623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>SCM Results</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 5}, {452, 262}}</string>
+								<key>RubberWindowFrame</key>
+								<string>194 589 452 308 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXCVSModule</string>
+							<key>Proportion</key>
+							<string>262pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>267pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>SCM</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXCVSModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>2CBF1CB30CC566690030C462</string>
+				<string>2CBF1CB40CC566690030C462</string>
+				<string>1C78EAB2065D492600B07095</string>
+				<string>1CD052920623707200166675</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.scm</string>
+			<key>WindowString</key>
+			<string>194 589 452 308 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>2CBF1CB30CC566690030C462</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.breakpoints</string>
+			<key>IsVertical</key>
+			<integer>0</integer>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<integer>1</integer>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXBottomSmartGroupGIDs</key>
+								<array>
+									<string>1C77FABC04509CD000000102</string>
+								</array>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CE0B1FE06471DED0097A5F4</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Files</string>
+								<key>PBXProjectStructureProvided</key>
+								<string>no</string>
+								<key>PBXSmartGroupTreeModuleColumnData</key>
+								<dict>
+									<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+									<array>
+										<real>168</real>
+									</array>
+									<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+									<array>
+										<string>MainColumn</string>
+									</array>
+								</dict>
+								<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+								<dict>
+									<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+									<array>
+										<string>1C77FABC04509CD000000102</string>
+									</array>
+									<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+									<array>
+										<array>
+											<integer>0</integer>
+										</array>
+									</array>
+									<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+									<string>{{0, 0}, {168, 350}}</string>
+								</dict>
+								<key>PBXTopSmartGroupGIDs</key>
+								<array/>
+								<key>XCIncludePerspectivesSwitch</key>
+								<integer>0</integer>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {185, 368}}</string>
+								<key>GroupTreeTableConfiguration</key>
+								<array>
+									<string>MainColumn</string>
+									<real>168</real>
+								</array>
+								<key>RubberWindowFrame</key>
+								<string>315 424 744 409 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXSmartGroupTreeModule</string>
+							<key>Proportion</key>
+							<string>185pt</string>
+						</dict>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CA1AED706398EBD00589147</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Detail</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{190, 0}, {554, 368}}</string>
+								<key>RubberWindowFrame</key>
+								<string>315 424 744 409 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>XCDetailModule</string>
+							<key>Proportion</key>
+							<string>554pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>368pt</string>
+				</dict>
+			</array>
+			<key>MajorVersion</key>
+			<integer>2</integer>
+			<key>MinorVersion</key>
+			<integer>0</integer>
+			<key>Name</key>
+			<string>Breakpoints</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXSmartGroupTreeModule</string>
+				<string>XCDetailModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>1</integer>
+			<key>TableOfContents</key>
+			<array>
+				<string>1CDDB66807F98D9800BB5817</string>
+				<string>1CDDB66907F98D9800BB5817</string>
+				<string>1CE0B1FE06471DED0097A5F4</string>
+				<string>1CA1AED706398EBD00589147</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.breakpoints</string>
+			<key>WindowString</key>
+			<string>315 424 744 409 0 0 1440 878 </string>
+			<key>WindowToolGUID</key>
+			<string>1CDDB66807F98D9800BB5817</string>
+			<key>WindowToolIsVisible</key>
+			<integer>1</integer>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.debugAnimator</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Debug Visualizer</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXNavigatorGroup</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>1</integer>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.debugAnimator</string>
+			<key>WindowString</key>
+			<string>100 100 700 500 0 0 1280 1002 </string>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.bookmarks</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>PBXBookmarksModule</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Bookmarks</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXBookmarksModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>0</integer>
+			<key>WindowString</key>
+			<string>538 42 401 187 0 0 1280 1002 </string>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.classBrowser</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<integer>1</integer>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>OptionsSetName</key>
+								<string>Hierarchy, all classes</string>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CA6456E063B45B4001379D8</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Class Browser - NSObject</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>ClassesFrame</key>
+								<string>{{0, 0}, {374, 96}}</string>
+								<key>ClassesTreeTableConfiguration</key>
+								<array>
+									<string>PBXClassNameColumnIdentifier</string>
+									<real>208</real>
+									<string>PBXClassBookColumnIdentifier</string>
+									<real>22</real>
+								</array>
+								<key>Frame</key>
+								<string>{{0, 0}, {630, 331}}</string>
+								<key>MembersFrame</key>
+								<string>{{0, 105}, {374, 395}}</string>
+								<key>MembersTreeTableConfiguration</key>
+								<array>
+									<string>PBXMemberTypeIconColumnIdentifier</string>
+									<real>22</real>
+									<string>PBXMemberNameColumnIdentifier</string>
+									<real>216</real>
+									<string>PBXMemberTypeColumnIdentifier</string>
+									<real>97</real>
+									<string>PBXMemberBookColumnIdentifier</string>
+									<real>22</real>
+								</array>
+								<key>PBXModuleWindowStatusBarHidden2</key>
+								<integer>1</integer>
+								<key>RubberWindowFrame</key>
+								<string>385 179 630 352 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXClassBrowserModule</string>
+							<key>Proportion</key>
+							<string>332pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>332pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Class Browser</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXClassBrowserModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>0</integer>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C0AD2AF069F1E9B00FABCE6</string>
+				<string>1C0AD2B0069F1E9B00FABCE6</string>
+				<string>1CA6456E063B45B4001379D8</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.classbrowser</string>
+			<key>WindowString</key>
+			<string>385 179 630 352 0 0 1440 878 </string>
+			<key>WindowToolGUID</key>
+			<string>1C0AD2AF069F1E9B00FABCE6</string>
+			<key>WindowToolIsVisible</key>
+			<integer>0</integer>
+		</dict>
+	</array>
+</dict>
+</plist>
diff --git a/songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.mode1v3 b/songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.mode1v3
new file mode 100644
index 00000000..3a15da1d
--- /dev/null
+++ b/songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.mode1v3
@@ -0,0 +1,1740 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ActivePerspectiveName</key>
+	<string>Project</string>
+	<key>AllowedModules</key>
+	<array>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXSmartGroupTreeModule</string>
+			<key>Name</key>
+			<string>Groups and Files Outline View</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXNavigatorGroup</string>
+			<key>Name</key>
+			<string>Editor</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCTaskListModule</string>
+			<key>Name</key>
+			<string>Task List</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCDetailModule</string>
+			<key>Name</key>
+			<string>File and Smart Group Detail Viewer</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXBuildResultsModule</string>
+			<key>Name</key>
+			<string>Detailed Build Results Viewer</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXProjectFindModule</string>
+			<key>Name</key>
+			<string>Project Batch Find Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCProjectFormatConflictsModule</string>
+			<key>Name</key>
+			<string>Project Format Conflicts List</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXBookmarksModule</string>
+			<key>Name</key>
+			<string>Bookmarks Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXClassBrowserModule</string>
+			<key>Name</key>
+			<string>Class Browser</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXCVSModule</string>
+			<key>Name</key>
+			<string>Source Code Control Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXDebugBreakpointsModule</string>
+			<key>Name</key>
+			<string>Debug Breakpoints Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCDockableInspector</string>
+			<key>Name</key>
+			<string>Inspector</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXOpenQuicklyModule</string>
+			<key>Name</key>
+			<string>Open Quickly Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXDebugSessionModule</string>
+			<key>Name</key>
+			<string>Debugger</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXDebugCLIModule</string>
+			<key>Name</key>
+			<string>Debug Console</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCSnapshotModule</string>
+			<key>Name</key>
+			<string>Snapshots Tool</string>
+		</dict>
+	</array>
+	<key>Description</key>
+	<string>DefaultDescriptionKey</string>
+	<key>DockingSystemVisible</key>
+	<false/>
+	<key>Extension</key>
+	<string>mode1v3</string>
+	<key>FavBarConfig</key>
+	<dict>
+		<key>PBXProjectModuleGUID</key>
+		<string>2C349F430CF222D900A55A81</string>
+		<key>XCBarModuleItemNames</key>
+		<dict/>
+		<key>XCBarModuleItems</key>
+		<array/>
+	</dict>
+	<key>FirstTimeWindowDisplayed</key>
+	<false/>
+	<key>Identifier</key>
+	<string>com.apple.perspectives.project.mode1v3</string>
+	<key>MajorVersion</key>
+	<integer>33</integer>
+	<key>MinorVersion</key>
+	<integer>0</integer>
+	<key>Name</key>
+	<string>Default</string>
+	<key>Notifications</key>
+	<array/>
+	<key>OpenEditors</key>
+	<array>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2CA608820D9998CC00EBC4A7</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>UAudioPlayback_Bass.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2CA608830D9998CC00EBC4A7</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>UAudioPlayback_Bass.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CA6088F0D99999100EBC4A7</string>
+						<key>history</key>
+						<array>
+							<string>2CA608790D99987900EBC4A7</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {993, 838}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>38 123 993 879 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2CA608850D9998CC00EBC4A7</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>UAudioCore_Bass.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2CA608860D9998CC00EBC4A7</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>UAudioCore_Bass.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CA608900D99999100EBC4A7</string>
+						<key>history</key>
+						<array>
+							<string>2CA608780D99987200EBC4A7</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {993, 838}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>15 144 993 879 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2C019A0B0D998D4A00974970</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>UMain.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2C019A0C0D998D4A00974970</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>UMain.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CA608910D99999100EBC4A7</string>
+						<key>history</key>
+						<array>
+							<string>2CA607DD0D998F0B00EBC4A7</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {1052, 646}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>30 341 1052 687 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2C0199490D9981C000974970</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>UCommon.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2C01994A0D9981C000974970</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>UCommon.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CA608920D99999100EBC4A7</string>
+						<key>history</key>
+						<array>
+							<string>2CA607DF0D998F0B00EBC4A7</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {754, 847}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>38 134 754 888 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2C0199430D9981C000974970</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>UScreenMain.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2C0199440D9981C000974970</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>UScreenMain.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CA608930D99999100EBC4A7</string>
+						<key>history</key>
+						<array>
+							<string>2C019A190D998D4A00974970</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {754, 847}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>38 135 754 888 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2C0199930D9984F900974970</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>UltraStarDX.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2C0199940D9984F900974970</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>UltraStarDX.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CA608940D99999100EBC4A7</string>
+						<key>history</key>
+						<array>
+							<string>2C019A1A0D998D4A00974970</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {987, 762}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>311 168 987 803 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2C01994C0D9981C000974970</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>OpenGL12.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2C01994D0D9981C000974970</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>OpenGL12.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CA608950D99999100EBC4A7</string>
+						<key>history</key>
+						<array>
+							<string>2C019A1B0D998D4A00974970</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {1070, 868}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>1 119 1070 909 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2CE603EA0D71601400DB0D88</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>UTexture.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2CE603EB0D71601400DB0D88</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>UTexture.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CA608960D99999100EBC4A7</string>
+						<key>history</key>
+						<array>
+							<string>2C019A1C0D998D4A00974970</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {776, 858}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>15 124 776 899 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Content</key>
+			<dict>
+				<key>PBXProjectModuleGUID</key>
+				<string>2CE603EE0D71601400DB0D88</string>
+				<key>PBXProjectModuleLabel</key>
+				<string>UPlatformMacOSX.pas</string>
+				<key>PBXSplitModuleInNavigatorKey</key>
+				<dict>
+					<key>Split0</key>
+					<dict>
+						<key>PBXProjectModuleGUID</key>
+						<string>2CE603EF0D71601400DB0D88</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>UPlatformMacOSX.pas</string>
+						<key>_historyCapacity</key>
+						<integer>0</integer>
+						<key>bookmark</key>
+						<string>2CA608970D99999100EBC4A7</string>
+						<key>history</key>
+						<array>
+							<string>2C019A1D0D998D4A00974970</string>
+						</array>
+					</dict>
+					<key>SplitCount</key>
+					<string>1</string>
+				</dict>
+				<key>StatusBarVisibility</key>
+				<true/>
+			</dict>
+			<key>Geometry</key>
+			<dict>
+				<key>Frame</key>
+				<string>{{0, 20}, {776, 859}}</string>
+				<key>PBXModuleWindowStatusBarHidden2</key>
+				<false/>
+				<key>RubberWindowFrame</key>
+				<string>79 126 776 900 0 0 1680 1028 </string>
+			</dict>
+		</dict>
+	</array>
+	<key>PerspectiveWidths</key>
+	<array>
+		<integer>-1</integer>
+		<integer>-1</integer>
+	</array>
+	<key>Perspectives</key>
+	<array>
+		<dict>
+			<key>ChosenToolbarItems</key>
+			<array>
+				<string>active-target-popup</string>
+				<string>active-buildstyle-popup</string>
+				<string>action</string>
+				<string>NSToolbarFlexibleSpaceItem</string>
+				<string>buildOrClean</string>
+				<string>build-and-goOrGo</string>
+				<string>com.apple.ide.PBXToolbarStopButton</string>
+				<string>get-info</string>
+				<string>toggle-editor</string>
+				<string>NSToolbarFlexibleSpaceItem</string>
+				<string>com.apple.pbx.toolbar.searchfield</string>
+			</array>
+			<key>ControllerClassBaseName</key>
+			<string></string>
+			<key>IconName</key>
+			<string>WindowOfProjectWithEditor</string>
+			<key>Identifier</key>
+			<string>perspective.project</string>
+			<key>IsVertical</key>
+			<false/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>ContentConfiguration</key>
+					<dict>
+						<key>PBXBottomSmartGroupGIDs</key>
+						<array>
+							<string>1C37FBAC04509CD000000102</string>
+							<string>1C37FAAC04509CD000000102</string>
+							<string>1C08E77C0454961000C914BD</string>
+							<string>1C37FABC05509CD000000102</string>
+							<string>1C37FABC05539CD112110102</string>
+							<string>E2644B35053B69B200211256</string>
+							<string>1C37FABC04509CD000100104</string>
+							<string>1CC0EA4004350EF90044410B</string>
+							<string>1CC0EA4004350EF90041110B</string>
+						</array>
+						<key>PBXProjectModuleGUID</key>
+						<string>1CE0B1FE06471DED0097A5F4</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>Files</string>
+						<key>PBXProjectStructureProvided</key>
+						<string>yes</string>
+						<key>PBXSmartGroupTreeModuleColumnData</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+							<array>
+								<real>266</real>
+							</array>
+							<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+							<array>
+								<string>MainColumn</string>
+							</array>
+						</dict>
+						<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+							<array>
+								<string>DDC6850D09F5717A004E4BFF</string>
+								<string>2C4D9D980CC9EE0B0031092D</string>
+								<string>DD7C45450A6E72DE003FA52B</string>
+								<string>2CF5510C0CDA28F000627463</string>
+								<string>1C37FBAC04509CD000000102</string>
+								<string>1C37FAAC04509CD000000102</string>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+							<array>
+								<array>
+									<integer>23</integer>
+									<integer>15</integer>
+									<integer>0</integer>
+								</array>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+							<string>{{0, 105}, {266, 694}}</string>
+						</dict>
+						<key>PBXTopSmartGroupGIDs</key>
+						<array/>
+						<key>XCIncludePerspectivesSwitch</key>
+						<true/>
+						<key>XCSharingToken</key>
+						<string>com.apple.Xcode.GFSharingToken</string>
+					</dict>
+					<key>GeometryConfiguration</key>
+					<dict>
+						<key>Frame</key>
+						<string>{{0, 0}, {283, 712}}</string>
+						<key>GroupTreeTableConfiguration</key>
+						<array>
+							<string>MainColumn</string>
+							<real>266</real>
+						</array>
+						<key>RubberWindowFrame</key>
+						<string>799 242 817 753 0 0 1680 1028 </string>
+					</dict>
+					<key>Module</key>
+					<string>PBXSmartGroupTreeModule</string>
+					<key>Proportion</key>
+					<string>283pt</string>
+				</dict>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CE0B20306471E060097A5F4</string>
+								<key>PBXProjectModuleLabel</key>
+								<string></string>
+								<key>PBXSplitModuleInNavigatorKey</key>
+								<dict>
+									<key>Split0</key>
+									<dict>
+										<key>PBXProjectModuleGUID</key>
+										<string>1CE0B20406471E060097A5F4</string>
+										<key>PBXProjectModuleLabel</key>
+										<string></string>
+									</dict>
+									<key>SplitCount</key>
+									<string>1</string>
+								</dict>
+								<key>StatusBarVisibility</key>
+								<true/>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {529, 0}}</string>
+								<key>RubberWindowFrame</key>
+								<string>799 242 817 753 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>0pt</string>
+						</dict>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CE0B20506471E060097A5F4</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Detail</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 5}, {529, 707}}</string>
+								<key>RubberWindowFrame</key>
+								<string>799 242 817 753 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>XCDetailModule</string>
+							<key>Proportion</key>
+							<string>707pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>529pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Project</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCModuleDock</string>
+				<string>PBXSmartGroupTreeModule</string>
+				<string>XCModuleDock</string>
+				<string>PBXNavigatorGroup</string>
+				<string>XCDetailModule</string>
+			</array>
+			<key>TableOfContents</key>
+			<array>
+				<string>2CA607D80D998F0B00EBC4A7</string>
+				<string>1CE0B1FE06471DED0097A5F4</string>
+				<string>2CA607D90D998F0B00EBC4A7</string>
+				<string>1CE0B20306471E060097A5F4</string>
+				<string>1CE0B20506471E060097A5F4</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.defaultV3</string>
+		</dict>
+		<dict>
+			<key>ControllerClassBaseName</key>
+			<string></string>
+			<key>IconName</key>
+			<string>WindowOfProject</string>
+			<key>Identifier</key>
+			<string>perspective.morph</string>
+			<key>IsVertical</key>
+			<false/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>BecomeActive</key>
+					<integer>1</integer>
+					<key>ContentConfiguration</key>
+					<dict>
+						<key>PBXBottomSmartGroupGIDs</key>
+						<array>
+							<string>1C37FBAC04509CD000000102</string>
+							<string>1C37FAAC04509CD000000102</string>
+							<string>1C08E77C0454961000C914BD</string>
+							<string>1C37FABC05509CD000000102</string>
+							<string>1C37FABC05539CD112110102</string>
+							<string>E2644B35053B69B200211256</string>
+							<string>1C37FABC04509CD000100104</string>
+							<string>1CC0EA4004350EF90044410B</string>
+							<string>1CC0EA4004350EF90041110B</string>
+						</array>
+						<key>PBXProjectModuleGUID</key>
+						<string>11E0B1FE06471DED0097A5F4</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>Files</string>
+						<key>PBXProjectStructureProvided</key>
+						<string>yes</string>
+						<key>PBXSmartGroupTreeModuleColumnData</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+							<array>
+								<real>186</real>
+							</array>
+							<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+							<array>
+								<string>MainColumn</string>
+							</array>
+						</dict>
+						<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+							<array>
+								<string>29B97314FDCFA39411CA2CEA</string>
+								<string>1C37FABC05509CD000000102</string>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+							<array>
+								<array>
+									<integer>0</integer>
+								</array>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+							<string>{{0, 0}, {186, 337}}</string>
+						</dict>
+						<key>PBXTopSmartGroupGIDs</key>
+						<array/>
+						<key>XCIncludePerspectivesSwitch</key>
+						<integer>1</integer>
+						<key>XCSharingToken</key>
+						<string>com.apple.Xcode.GFSharingToken</string>
+					</dict>
+					<key>GeometryConfiguration</key>
+					<dict>
+						<key>Frame</key>
+						<string>{{0, 0}, {203, 355}}</string>
+						<key>GroupTreeTableConfiguration</key>
+						<array>
+							<string>MainColumn</string>
+							<real>186</real>
+						</array>
+						<key>RubberWindowFrame</key>
+						<string>373 269 690 397 0 0 1440 878 </string>
+					</dict>
+					<key>Module</key>
+					<string>PBXSmartGroupTreeModule</string>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Morph</string>
+			<key>PreferredWidth</key>
+			<integer>300</integer>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCModuleDock</string>
+				<string>PBXSmartGroupTreeModule</string>
+			</array>
+			<key>TableOfContents</key>
+			<array>
+				<string>11E0B1FE06471DED0097A5F4</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.default.shortV3</string>
+		</dict>
+	</array>
+	<key>PerspectivesBarVisible</key>
+	<false/>
+	<key>ShelfIsVisible</key>
+	<false/>
+	<key>StatusbarIsVisible</key>
+	<true/>
+	<key>TimeStamp</key>
+	<real>0.0</real>
+	<key>ToolbarDisplayMode</key>
+	<integer>1</integer>
+	<key>ToolbarIsVisible</key>
+	<true/>
+	<key>ToolbarSizeMode</key>
+	<integer>1</integer>
+	<key>Type</key>
+	<string>Perspectives</string>
+	<key>UpdateMessage</key>
+	<string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature).  You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature.  Do you wish to update to the latest Workspace defaults for project '%@'?</string>
+	<key>WindowJustification</key>
+	<integer>5</integer>
+	<key>WindowOrderList</key>
+	<array>
+		<string>2CA6081C0D9991E800EBC4A7</string>
+		<string>2CA6081D0D9991E800EBC4A7</string>
+		<string>1C530D57069F1CE1000CFCEE</string>
+		<string>1C78EAAD065D492600B07095</string>
+		<string>1CD10A99069EF8BA00B06720</string>
+		<string>2C65660B0CF2236C0041F7DC</string>
+		<string>2CE603EE0D71601400DB0D88</string>
+		<string>2CE603EA0D71601400DB0D88</string>
+		<string>2C01994C0D9981C000974970</string>
+		<string>2C0199930D9984F900974970</string>
+		<string>2C0199430D9981C000974970</string>
+		<string>2C0199490D9981C000974970</string>
+		<string>2C019A0B0D998D4A00974970</string>
+		<string>2CA608850D9998CC00EBC4A7</string>
+		<string>/Users/eddie/Projekte/UltraStarDX/trunk/Game/Code/MacOSX/UltraStarDX.xcodeproj</string>
+		<string>2CA608820D9998CC00EBC4A7</string>
+	</array>
+	<key>WindowString</key>
+	<string>799 242 817 753 0 0 1680 1028 </string>
+	<key>WindowToolsV3</key>
+	<array>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.build</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD0528F0623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>UAudioInput_Bass.pas</string>
+								<key>StatusBarVisibility</key>
+								<true/>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {942, 546}}</string>
+								<key>RubberWindowFrame</key>
+								<string>105 189 942 828 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>546pt</string>
+						</dict>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>XCMainBuildResultsModuleGUID</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Build</string>
+								<key>XCBuildResultsTrigger_Collapse</key>
+								<integer>1021</integer>
+								<key>XCBuildResultsTrigger_Open</key>
+								<integer>1011</integer>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 551}, {942, 236}}</string>
+								<key>RubberWindowFrame</key>
+								<string>105 189 942 828 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXBuildResultsModule</string>
+							<key>Proportion</key>
+							<string>236pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>787pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Build Results</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXBuildResultsModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>2C65660B0CF2236C0041F7DC</string>
+				<string>2CA607E60D998F0B00EBC4A7</string>
+				<string>1CD0528F0623707200166675</string>
+				<string>XCMainBuildResultsModuleGUID</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.buildV3</string>
+			<key>WindowString</key>
+			<string>105 189 942 828 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>2C65660B0CF2236C0041F7DC</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.debugger</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>Debugger</key>
+								<dict>
+									<key>HorizontalSplitView</key>
+									<dict>
+										<key>_collapsingFrameDimension</key>
+										<real>0.0</real>
+										<key>_indexOfCollapsedView</key>
+										<integer>0</integer>
+										<key>_percentageOfCollapsedView</key>
+										<real>0.0</real>
+										<key>isCollapsed</key>
+										<string>yes</string>
+										<key>sizes</key>
+										<array>
+											<string>{{0, 0}, {312, 440}}</string>
+											<string>{{312, 0}, {591, 440}}</string>
+										</array>
+									</dict>
+									<key>VerticalSplitView</key>
+									<dict>
+										<key>_collapsingFrameDimension</key>
+										<real>0.0</real>
+										<key>_indexOfCollapsedView</key>
+										<integer>0</integer>
+										<key>_percentageOfCollapsedView</key>
+										<real>0.0</real>
+										<key>isCollapsed</key>
+										<string>yes</string>
+										<key>sizes</key>
+										<array>
+											<string>{{0, 0}, {903, 440}}</string>
+											<string>{{0, 440}, {903, 385}}</string>
+										</array>
+									</dict>
+								</dict>
+								<key>LauncherConfigVersion</key>
+								<string>8</string>
+								<key>PBXProjectModuleGUID</key>
+								<string>1C162984064C10D400B95A72</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Debug - GLUTExamples (Underwater)</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>DebugConsoleVisible</key>
+								<string>None</string>
+								<key>DebugConsoleWindowFrame</key>
+								<string>{{200, 200}, {500, 300}}</string>
+								<key>DebugSTDIOWindowFrame</key>
+								<string>{{200, 200}, {500, 300}}</string>
+								<key>Frame</key>
+								<string>{{0, 0}, {903, 825}}</string>
+								<key>PBXDebugSessionStackFrameViewKey</key>
+								<dict>
+									<key>DebugVariablesTableConfiguration</key>
+									<array>
+										<string>Name</string>
+										<real>120</real>
+										<string>Value</string>
+										<real>85</real>
+										<string>Summary</string>
+										<real>361</real>
+									</array>
+									<key>Frame</key>
+									<string>{{312, 0}, {591, 440}}</string>
+									<key>RubberWindowFrame</key>
+									<string>13 162 903 866 0 0 1680 1028 </string>
+								</dict>
+								<key>RubberWindowFrame</key>
+								<string>13 162 903 866 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXDebugSessionModule</string>
+							<key>Proportion</key>
+							<string>825pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>825pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Debugger</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXDebugSessionModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1CD10A99069EF8BA00B06720</string>
+				<string>2CA607E70D998F0B00EBC4A7</string>
+				<string>1C162984064C10D400B95A72</string>
+				<string>2CA607E80D998F0B00EBC4A7</string>
+				<string>2CA607E90D998F0B00EBC4A7</string>
+				<string>2CA607EA0D998F0B00EBC4A7</string>
+				<string>2CA607EB0D998F0B00EBC4A7</string>
+				<string>2CA607EC0D998F0B00EBC4A7</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.debugV3</string>
+			<key>WindowString</key>
+			<string>13 162 903 866 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>1CD10A99069EF8BA00B06720</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.find</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Dock</key>
+							<array>
+								<dict>
+									<key>ContentConfiguration</key>
+									<dict>
+										<key>PBXProjectModuleGUID</key>
+										<string>1CDD528C0622207200134675</string>
+										<key>PBXProjectModuleLabel</key>
+										<string>&lt;No Editor&gt;</string>
+										<key>StatusBarVisibility</key>
+										<true/>
+									</dict>
+									<key>GeometryConfiguration</key>
+									<dict>
+										<key>Frame</key>
+										<string>{{0, 0}, {790, 502}}</string>
+										<key>RubberWindowFrame</key>
+										<string>821 68 790 888 0 0 1680 1028 </string>
+									</dict>
+									<key>Module</key>
+									<string>PBXNavigatorGroup</string>
+									<key>Proportion</key>
+									<string>790pt</string>
+								</dict>
+							</array>
+							<key>Proportion</key>
+							<string>502pt</string>
+						</dict>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD0528E0623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Project Find</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 507}, {790, 340}}</string>
+								<key>RubberWindowFrame</key>
+								<string>821 68 790 888 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXProjectFindModule</string>
+							<key>Proportion</key>
+							<string>340pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>847pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Project Find</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXProjectFindModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C530D57069F1CE1000CFCEE</string>
+				<string>2CA607ED0D998F0B00EBC4A7</string>
+				<string>2CA607EE0D998F0B00EBC4A7</string>
+				<string>1CDD528C0622207200134675</string>
+				<string>1CD0528E0623707200166675</string>
+			</array>
+			<key>WindowString</key>
+			<string>821 68 790 888 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>1C530D57069F1CE1000CFCEE</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>MENUSEPARATOR</string>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.debuggerConsole</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1C78EAAC065D492600B07095</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Debugger Console</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {779, 729}}</string>
+								<key>RubberWindowFrame</key>
+								<string>886 204 779 770 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXDebugCLIModule</string>
+							<key>Proportion</key>
+							<string>729pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>729pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Debugger Console</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXDebugCLIModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C78EAAD065D492600B07095</string>
+				<string>2CA607EF0D998F0B00EBC4A7</string>
+				<string>1C78EAAC065D492600B07095</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.consoleV3</string>
+			<key>WindowString</key>
+			<string>886 204 779 770 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>1C78EAAD065D492600B07095</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.snapshots</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>XCSnapshotModule</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Snapshots</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCSnapshotModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<string>Yes</string>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.snapshots</string>
+			<key>WindowString</key>
+			<string>315 824 300 550 0 0 1440 878 </string>
+			<key>WindowToolIsVisible</key>
+			<string>Yes</string>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.scm</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1C78EAB2065D492600B07095</string>
+								<key>PBXProjectModuleLabel</key>
+								<string></string>
+								<key>StatusBarVisibility</key>
+								<true/>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {452, 0}}</string>
+								<key>RubberWindowFrame</key>
+								<string>194 589 452 308 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>0pt</string>
+						</dict>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD052920623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>SCM Results</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 5}, {452, 262}}</string>
+								<key>RubberWindowFrame</key>
+								<string>194 589 452 308 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXCVSModule</string>
+							<key>Proportion</key>
+							<string>262pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>267pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>SCM</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXCVSModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C78EAB4065D492600B07095</string>
+				<string>1C78EAB5065D492600B07095</string>
+				<string>1C78EAB2065D492600B07095</string>
+				<string>1CD052920623707200166675</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.scm</string>
+			<key>WindowString</key>
+			<string>194 589 452 308 0 0 1680 1028 </string>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.breakpoints</string>
+			<key>IsVertical</key>
+			<false/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXBottomSmartGroupGIDs</key>
+								<array>
+									<string>1C77FABC04509CD000000102</string>
+								</array>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CE0B1FE06471DED0097A5F4</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Files</string>
+								<key>PBXProjectStructureProvided</key>
+								<string>no</string>
+								<key>PBXSmartGroupTreeModuleColumnData</key>
+								<dict>
+									<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+									<array>
+										<real>168</real>
+									</array>
+									<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+									<array>
+										<string>MainColumn</string>
+									</array>
+								</dict>
+								<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+								<dict>
+									<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+									<array>
+										<string>1C77FABC04509CD000000102</string>
+									</array>
+									<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+									<array>
+										<array>
+											<integer>0</integer>
+										</array>
+									</array>
+									<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+									<string>{{0, 0}, {168, 350}}</string>
+								</dict>
+								<key>PBXTopSmartGroupGIDs</key>
+								<array/>
+								<key>XCIncludePerspectivesSwitch</key>
+								<false/>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {185, 368}}</string>
+								<key>GroupTreeTableConfiguration</key>
+								<array>
+									<string>MainColumn</string>
+									<real>168</real>
+								</array>
+								<key>RubberWindowFrame</key>
+								<string>424 558 744 409 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXSmartGroupTreeModule</string>
+							<key>Proportion</key>
+							<string>185pt</string>
+						</dict>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CA1AED706398EBD00589147</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Detail</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{190, 0}, {554, 368}}</string>
+								<key>RubberWindowFrame</key>
+								<string>424 558 744 409 0 0 1680 1028 </string>
+							</dict>
+							<key>Module</key>
+							<string>XCDetailModule</string>
+							<key>Proportion</key>
+							<string>554pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>368pt</string>
+				</dict>
+			</array>
+			<key>MajorVersion</key>
+			<integer>3</integer>
+			<key>MinorVersion</key>
+			<integer>0</integer>
+			<key>Name</key>
+			<string>Breakpoints</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXSmartGroupTreeModule</string>
+				<string>XCDetailModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>2CA2CD2C0CF61AD5008733A1</string>
+				<string>2CA2CD2D0CF61AD5008733A1</string>
+				<string>1CE0B1FE06471DED0097A5F4</string>
+				<string>1CA1AED706398EBD00589147</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.breakpointsV3</string>
+			<key>WindowString</key>
+			<string>424 558 744 409 0 0 1680 1028 </string>
+			<key>WindowToolGUID</key>
+			<string>2CA2CD2C0CF61AD5008733A1</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.debugAnimator</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Debug Visualizer</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXNavigatorGroup</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.debugAnimatorV3</string>
+			<key>WindowString</key>
+			<string>100 100 700 500 0 0 1280 1002 </string>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.bookmarks</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>PBXBookmarksModule</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Bookmarks</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXBookmarksModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<false/>
+			<key>WindowString</key>
+			<string>538 42 401 187 0 0 1280 1002 </string>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.projectFormatConflicts</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>XCProjectFormatConflictsModule</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Project Format Conflicts</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCProjectFormatConflictsModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<false/>
+			<key>WindowContentMinSize</key>
+			<string>450 300</string>
+			<key>WindowString</key>
+			<string>50 850 472 307 0 0 1440 877</string>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.classBrowser</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<integer>1</integer>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>OptionsSetName</key>
+								<string>Hierarchy, all classes</string>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CA6456E063B45B4001379D8</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Class Browser - NSObject</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>ClassesFrame</key>
+								<string>{{0, 0}, {374, 96}}</string>
+								<key>ClassesTreeTableConfiguration</key>
+								<array>
+									<string>PBXClassNameColumnIdentifier</string>
+									<real>208</real>
+									<string>PBXClassBookColumnIdentifier</string>
+									<real>22</real>
+								</array>
+								<key>Frame</key>
+								<string>{{0, 0}, {630, 331}}</string>
+								<key>MembersFrame</key>
+								<string>{{0, 105}, {374, 395}}</string>
+								<key>MembersTreeTableConfiguration</key>
+								<array>
+									<string>PBXMemberTypeIconColumnIdentifier</string>
+									<real>22</real>
+									<string>PBXMemberNameColumnIdentifier</string>
+									<real>216</real>
+									<string>PBXMemberTypeColumnIdentifier</string>
+									<real>97</real>
+									<string>PBXMemberBookColumnIdentifier</string>
+									<real>22</real>
+								</array>
+								<key>PBXModuleWindowStatusBarHidden2</key>
+								<integer>1</integer>
+								<key>RubberWindowFrame</key>
+								<string>385 179 630 352 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXClassBrowserModule</string>
+							<key>Proportion</key>
+							<string>332pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>332pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Class Browser</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXClassBrowserModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<false/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C0AD2AF069F1E9B00FABCE6</string>
+				<string>1C0AD2B0069F1E9B00FABCE6</string>
+				<string>1CA6456E063B45B4001379D8</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.classbrowser</string>
+			<key>WindowString</key>
+			<string>385 179 630 352 0 0 1440 878 </string>
+			<key>WindowToolGUID</key>
+			<string>1C0AD2AF069F1E9B00FABCE6</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.refactoring</string>
+			<key>IncludeInToolsMenu</key>
+			<false/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{0, 0}, {500, 335}</string>
+								<key>RubberWindowFrame</key>
+								<string>{0, 0}, {500, 335}</string>
+							</dict>
+							<key>Module</key>
+							<string>XCRefactoringModule</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Refactoring</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCRefactoringModule</string>
+			</array>
+			<key>WindowString</key>
+			<string>200 200 500 356 0 0 1920 1200 </string>
+		</dict>
+	</array>
+</dict>
+</plist>
diff --git a/songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.pbxuser b/songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.pbxuser
new file mode 100644
index 00000000..e054f93e
--- /dev/null
+++ b/songmanagement/dists/xcode/UltraStarDX.xcodeproj/eddie.pbxuser
@@ -0,0 +1,1414 @@
+// !$*UTF8*$!
+{
+	2C0199800D99840900974970 /* config-macosx.inc */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {934, 994}}";
+			sepNavSelRange = "{540, 0}";
+			sepNavVisRange = "{353, 1694}";
+			sepNavWindowFrame = "{{15, 88}, {993, 935}}";
+		};
+	};
+	2C019A190D998D4A00974970 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */;
+		name = "UScreenMain.pas: 76";
+		rLen = 17;
+		rLoc = 1560;
+		rType = 0;
+		vrLen = 1274;
+		vrLoc = 1037;
+	};
+	2C019A1A0D998D4A00974970 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DDC6851B09F57195004E4BFF /* UltraStarDX.pas */;
+		name = "UltraStarDX.pas: 3";
+		rLen = 0;
+		rLoc = 72;
+		rType = 0;
+		vrLen = 152;
+		vrLoc = 0;
+	};
+	2C019A1B0D998D4A00974970 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C4D9E040CC9EF840031092D /* OpenGL12.pas */;
+		name = "OpenGL12.pas: 4683";
+		rLen = 0;
+		rLoc = 213678;
+		rType = 0;
+		vrLen = 6646;
+		vrLoc = 207819;
+	};
+	2C019A1C0D998D4A00974970 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */;
+		name = "UTexture.pas: 344";
+		rLen = 0;
+		rLoc = 10496;
+		rType = 0;
+		vrLen = 1662;
+		vrLoc = 9347;
+	};
+	2C019A1D0D998D4A00974970 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */;
+		name = "UPlatformMacOSX.pas: 13";
+		rLen = 0;
+		rLoc = 717;
+		rType = 0;
+		vrLen = 1571;
+		vrLoc = 493;
+	};
+	2C4B70220CF757A400B0F0BD /* Until5000.dpr */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {691, 1218}}";
+			sepNavSelRange = "{0, 0}";
+			sepNavVisRange = "{0, 1115}";
+			sepNavWindowFrame = "{{15, 465}, {750, 558}}";
+		};
+	};
+	2C4D9C620CC9EC8C0031092D /* TextGL.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {881, 7532}}";
+			sepNavSelRange = "{10589, 66}";
+			sepNavVisRange = "{10222, 893}";
+			sepNavVisRect = "{{0, 5908}, {758, 716}}";
+			sepNavWindowFrame = "{{38, 157}, {797, 845}}";
+		};
+	};
+	2C4D9C650CC9EC8C0031092D /* UCatCovers.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {923, 2128}}";
+			sepNavSelRange = "{1154, 0}";
+			sepNavVisRect = "{{0, 354}, {923, 342}}";
+			sepNavWindowFrame = "{{61, 136}, {797, 845}}";
+		};
+	};
+	2C4D9C660CC9EC8C0031092D /* UCommandLine.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 4130}}";
+			sepNavSelRange = "{79, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{84, 115}, {797, 845}}";
+		};
+	};
+	2C4D9C670CC9EC8C0031092D /* UCommon.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {695, 4060}}";
+			sepNavSelRange = "{584, 24}";
+			sepNavVisRange = "{249, 1447}";
+			sepNavVisRect = "{{0, 508}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 78}, {754, 944}}";
+		};
+	};
+	2C4D9C680CC9EC8C0031092D /* UCore.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1202, 7294}}";
+			sepNavSelRange = "{12520, 0}";
+			sepNavVisRect = "{{0, 844}, {758, 716}}";
+			sepNavWindowFrame = "{{107, 94}, {797, 845}}";
+		};
+	};
+	2C4D9C690CC9EC8C0031092D /* UCoreModule.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {577, 1708}}";
+			sepNavSelRange = "{262, 0}";
+			sepNavVisRect = "{{0, 0}, {577, 612}}";
+			sepNavWindowFrame = "{{38, 261}, {616, 741}}";
+		};
+	};
+	2C4D9C6A0CC9EC8C0031092D /* UCovers.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 3668}}";
+			sepNavSelRange = "{49, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{130, 73}, {797, 845}}";
+		};
+	};
+	2C4D9C6B0CC9EC8C0031092D /* UDataBase.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {4058, 5082}}";
+			sepNavSelRange = "{1600, 0}";
+			sepNavVisRect = "{{0, 1250}, {923, 342}}";
+			sepNavWindowFrame = "{{153, 52}, {797, 845}}";
+		};
+	};
+	2C4D9C6C0CC9EC8C0031092D /* UDLLManager.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1424, 3542}}";
+			sepNavSelRange = "{4330, 0}";
+			sepNavVisRange = "{3445, 1320}";
+			sepNavVisRect = "{{0, 456}, {758, 716}}";
+			sepNavWindowFrame = "{{15, 178}, {797, 845}}";
+		};
+	};
+	2C4D9C6D0CC9EC8C0031092D /* UDraw.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {836, 19516}}";
+			sepNavSelRange = "{0, 0}";
+			sepNavVisRange = "{6577, 1474}";
+			sepNavVisRect = "{{0, 4065}, {1277, 312}}";
+			sepNavWindowFrame = "{{61, 122}, {794, 859}}";
+		};
+	};
+	2C4D9C6E0CC9EC8C0031092D /* UFiles.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {815, 2086}}";
+			sepNavSelRange = "{0, 0}";
+			sepNavVisRange = "{2303, 2169}";
+			sepNavVisRect = "{{0, 4494}, {923, 342}}";
+			sepNavWindowFrame = "{{84, 77}, {874, 883}}";
+		};
+	};
+	2C4D9C6F0CC9EC8C0031092D /* UGraphic.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {729, 10626}}";
+			sepNavSelRange = "{16099, 0}";
+			sepNavVisRange = "{13982, 870}";
+			sepNavVisRect = "{{0, 3790}, {749, 470}}";
+			sepNavWindowFrame = "{{38, 157}, {797, 845}}";
+		};
+	};
+	2C4D9C700CC9EC8C0031092D /* UGraphicClasses.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1052, 9450}}";
+			sepNavSelRange = "{5863, 11}";
+			sepNavVisRect = "{{0, 2572}, {749, 470}}";
+			sepNavWindowFrame = "{{61, 136}, {797, 845}}";
+		};
+	};
+	2C4D9C710CC9EC8C0031092D /* UHooks.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1277, 5964}}";
+			sepNavSelRange = "{11810, 0}";
+			sepNavVisRect = "{{0, 5652}, {1277, 312}}";
+			sepNavWindowFrame = "{{84, 115}, {797, 845}}";
+		};
+	};
+	2C4D9C720CC9EC8C0031092D /* UIni.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 11214}}";
+			sepNavSelRange = "{5601, 15}";
+			sepNavVisRange = "{5183, 839}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{107, 94}, {797, 845}}";
+		};
+	};
+	2C4D9C730CC9EC8C0031092D /* UJoystick.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {896, 3962}}";
+			sepNavSelRange = "{46, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{130, 73}, {797, 845}}";
+		};
+	};
+	2C4D9C740CC9EC8C0031092D /* ULanguage.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {738, 3388}}";
+			sepNavSelRange = "{28, 58}";
+			sepNavVisRange = "{0, 1050}";
+			sepNavVisRect = "{{0, 914}, {923, 342}}";
+			sepNavWindowFrame = "{{153, 52}, {797, 845}}";
+		};
+	};
+	2C4D9C760CC9EC8C0031092D /* ULCD.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {577, 4270}}";
+			sepNavSelRange = "{25, 0}";
+			sepNavVisRect = "{{0, 0}, {577, 612}}";
+			sepNavWindowFrame = "{{176, 135}, {616, 741}}";
+		};
+	};
+	2C4D9C770CC9EC8C0031092D /* ULight.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 2282}}";
+			sepNavSelRange = "{1017, 0}";
+			sepNavVisRect = "{{0, 425}, {758, 716}}";
+			sepNavWindowFrame = "{{15, 178}, {797, 845}}";
+		};
+	};
+	2C4D9C780CC9EC8C0031092D /* ULog.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {842, 4102}}";
+			sepNavSelRange = "{6569, 0}";
+			sepNavVisRange = "{6421, 474}";
+			sepNavVisRect = "{{0, 147}, {758, 716}}";
+			sepNavWindowFrame = "{{38, 157}, {797, 845}}";
+		};
+	};
+	2C4D9C790CC9EC8C0031092D /* ULyrics_bak.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1070, 5950}}";
+			sepNavSelRange = "{34, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{84, 115}, {797, 845}}";
+		};
+	};
+	2C4D9C7A0CC9EC8C0031092D /* ULyrics.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 10626}}";
+			sepNavSelRange = "{6965, 12}";
+			sepNavVisRange = "{6549, 702}";
+			sepNavVisRect = "{{0, 4395}, {758, 716}}";
+			sepNavWindowFrame = "{{61, 136}, {797, 845}}";
+		};
+	};
+	2C4D9C7B0CC9EC8C0031092D /* UMain.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1026, 16268}}";
+			sepNavSelRange = "{31433, 0}";
+			sepNavVisRange = "{32193, 1839}";
+			sepNavVisRect = "{{0, 0}, {1013, 614}}";
+			sepNavWindowFrame = "{{30, 285}, {1052, 743}}";
+		};
+	};
+	2C4D9C7C0CC9EC8C0031092D /* UMedia_dummy.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {738, 3864}}";
+			sepNavSelRange = "{960, 0}";
+			sepNavVisRange = "{4488, 788}";
+			sepNavVisRect = "{{0, 1071}, {749, 470}}";
+			sepNavWindowFrame = "{{107, 94}, {797, 845}}";
+		};
+	};
+	2C4D9C7D0CC9EC8C0031092D /* UModules.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 716}}";
+			sepNavSelRange = "{31, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{130, 73}, {797, 845}}";
+		};
+	};
+	2C4D9C7E0CC9EC8C0031092D /* UMusic.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {749, 4494}}";
+			sepNavSelRange = "{4994, 0}";
+			sepNavVisRect = "{{0, 4024}, {749, 470}}";
+			sepNavWindowFrame = "{{153, 52}, {797, 845}}";
+		};
+	};
+	2C4D9C7F0CC9EC8C0031092D /* UParty.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {854, 8988}}";
+			sepNavSelRange = "{17977, 0}";
+			sepNavVisRange = "{16881, 1096}";
+			sepNavVisRect = "{{0, 3141}, {1305, 534}}";
+			sepNavWindowFrame = "{{15, 178}, {797, 845}}";
+		};
+	};
+	2C4D9C800CC9EC8C0031092D /* UPlaylist.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {824, 6496}}";
+			sepNavSelRange = "{51, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{38, 157}, {797, 845}}";
+		};
+	};
+	2C4D9C820CC9EC8C0031092D /* UPluginInterface.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 2198}}";
+			sepNavSelRange = "{247, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{84, 115}, {797, 845}}";
+		};
+	};
+	2C4D9C830CC9EC8C0031092D /* uPluginLoader.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1718, 11116}}";
+			sepNavSelRange = "{317, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{107, 94}, {797, 845}}";
+		};
+	};
+	2C4D9C840CC9EC8C0031092D /* URecord.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {738, 8372}}";
+			sepNavSelRange = "{10657, 20}";
+			sepNavVisRange = "{10176, 1198}";
+			sepNavVisRect = "{{0, 4312}, {758, 716}}";
+			sepNavWindowFrame = "{{130, 73}, {797, 845}}";
+		};
+	};
+	2C4D9C850CC9EC8C0031092D /* UServices.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1916, 4494}}";
+			sepNavSelRange = "{9160, 4}";
+			sepNavVisRect = "{{0, 4182}, {1277, 312}}";
+			sepNavWindowFrame = "{{153, 52}, {797, 845}}";
+		};
+	};
+	2C4D9C860CC9EC8C0031092D /* USingNotes.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 716}}";
+			sepNavSelRange = "{52, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{15, 178}, {797, 845}}";
+		};
+	};
+	2C4D9C870CC9EC8C0031092D /* USingScores.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {950, 13818}}";
+			sepNavSelRange = "{15011, 16}";
+			sepNavVisRect = "{{0, 5904}, {749, 470}}";
+			sepNavWindowFrame = "{{38, 157}, {797, 845}}";
+		};
+	};
+	2C4D9C880CC9EC8C0031092D /* USkins.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {842, 2450}}";
+			sepNavSelRange = "{2805, 0}";
+			sepNavVisRange = "{2928, 803}";
+			sepNavVisRect = "{{0, 550}, {923, 342}}";
+			sepNavWindowFrame = "{{61, 136}, {797, 845}}";
+		};
+	};
+	2C4D9C890CC9EC8C0031092D /* USongs.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {920, 13636}}";
+			sepNavSelRange = "{6946, 0}";
+			sepNavVisRange = "{6429, 995}";
+			sepNavVisRect = "{{0, 4157}, {758, 716}}";
+			sepNavWindowFrame = "{{15, 156}, {797, 845}}";
+		};
+	};
+	2C4D9C8A0CC9EC8C0031092D /* UTextClasses.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1010, 854}}";
+			sepNavSelRange = "{54, 0}";
+			sepNavVisRect = "{{0, 138}, {758, 716}}";
+			sepNavWindowFrame = "{{107, 94}, {797, 845}}";
+		};
+	};
+	2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {858, 16688}}";
+			sepNavSelRange = "{10496, 0}";
+			sepNavVisRange = "{9368, 1825}";
+			sepNavVisRect = "{{0, 3420}, {737, 826}}";
+			sepNavWindowFrame = "{{15, 68}, {776, 955}}";
+		};
+	};
+	2C4D9C8C0CC9EC8C0031092D /* UThemes.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {842, 32242}}";
+			sepNavSelRange = "{59317, 12}";
+			sepNavVisRange = "{61073, 1036}";
+			sepNavVisRect = "{{0, 19678}, {923, 342}}";
+			sepNavWindowFrame = "{{28, 161}, {797, 845}}";
+		};
+	};
+	2C4D9C8D0CC9EC8C0031092D /* UTime.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 1400}}";
+			sepNavSelRange = "{42, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{153, 52}, {797, 845}}";
+		};
+	};
+	2C4D9C8E0CC9EC8C0031092D /* UVideo.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {914, 9016}}";
+			sepNavSelRange = "{12966, 0}";
+			sepNavVisRange = "{12857, 955}";
+			sepNavVisRect = "{{0, 5722}, {749, 470}}";
+			sepNavWindowFrame = "{{15, 178}, {797, 845}}";
+		};
+	};
+	2C4D9D900CC9ED4F0031092D /* FreeBitmap.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {974, 24374}}";
+			sepNavSelRange = "{1377, 0}";
+			sepNavVisRect = "{{0, 0}, {577, 612}}";
+			sepNavWindowFrame = "{{245, 72}, {616, 741}}";
+		};
+	};
+	2C4D9D910CC9ED4F0031092D /* FreeImage.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1718, 10416}}";
+			sepNavSelRange = "{1255, 0}";
+			sepNavVisRect = "{{0, 373}, {577, 612}}";
+			sepNavWindowFrame = "{{15, 282}, {616, 741}}";
+		};
+	};
+	2C4D9DCC0CC9EE6F0031092D /* UDisplay.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {881, 6944}}";
+			sepNavSelRange = "{5028, 51}";
+			sepNavVisRange = "{4044, 1359}";
+			sepNavVisRect = "{{0, 4834}, {758, 716}}";
+			sepNavWindowFrame = "{{38, 157}, {797, 845}}";
+		};
+	};
+	2C4D9DCD0CC9EE6F0031092D /* UDrawTexture.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {738, 1470}}";
+			sepNavSelRange = "{2779, 0}";
+			sepNavVisRange = "{937, 1764}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{61, 136}, {797, 845}}";
+		};
+	};
+	2C4D9DCE0CC9EE6F0031092D /* UMenu.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1284, 22162}}";
+			sepNavSelRange = "{51782, 0}";
+			sepNavVisRange = "{51126, 1038}";
+			sepNavVisRect = "{{0, 3972}, {749, 470}}";
+			sepNavWindowFrame = "{{38, 82}, {898, 920}}";
+		};
+	};
+	2C4D9DCF0CC9EE6F0031092D /* UMenuButton.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {934, 7546}}";
+			sepNavSelRange = "{10421, 15}";
+			sepNavVisRange = "{9357, 1695}";
+			sepNavVisRect = "{{0, 1104}, {577, 612}}";
+			sepNavWindowFrame = "{{44, 71}, {993, 935}}";
+		};
+	};
+	2C4D9DD00CC9EE6F0031092D /* UMenuButtonCollection.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 1008}}";
+			sepNavSelRange = "{63, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{61, 136}, {797, 845}}";
+		};
+	};
+	2C4D9DD10CC9EE6F0031092D /* UMenuInteract.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 716}}";
+			sepNavSelRange = "{55, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{84, 115}, {797, 845}}";
+		};
+	};
+	2C4D9DD20CC9EE6F0031092D /* UMenuSelect.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {577, 2828}}";
+			sepNavSelRange = "{53, 0}";
+			sepNavVisRect = "{{0, 0}, {577, 612}}";
+			sepNavWindowFrame = "{{130, 177}, {616, 741}}";
+		};
+	};
+	2C4D9DD30CC9EE6F0031092D /* UMenuSelectSlide.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 4928}}";
+			sepNavSelRange = "{58, 0}";
+			sepNavVisRect = "{{0, 0}, {758, 716}}";
+			sepNavWindowFrame = "{{107, 94}, {797, 845}}";
+		};
+	};
+	2C4D9DD40CC9EE6F0031092D /* UMenuStatic.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {842, 1204}}";
+			sepNavSelRange = "{400, 0}";
+			sepNavVisRange = "{184, 530}";
+			sepNavVisRect = "{{0, 0}, {577, 612}}";
+			sepNavWindowFrame = "{{107, 198}, {616, 741}}";
+		};
+	};
+	2C4D9DD50CC9EE6F0031092D /* UMenuText.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {962, 5222}}";
+			sepNavSelRange = "{2165, 0}";
+			sepNavVisRect = "{{0, 707}, {758, 716}}";
+			sepNavWindowFrame = "{{130, 73}, {797, 845}}";
+		};
+	};
+	2C4D9DEC0CC9EF0A0031092D /* sdl_image.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1268, 4788}}";
+			sepNavSelRange = "{15613, 0}";
+			sepNavVisRect = "{{0, 1736}, {1013, 614}}";
+			sepNavWindowFrame = "{{15, 280}, {1052, 743}}";
+		};
+	};
+	2C4D9DEF0CC9EF210031092D /* sdl_ttf.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1268, 6552}}";
+			sepNavSelRange = "{8844, 12}";
+			sepNavVisRect = "{{0, 2054}, {749, 470}}";
+		};
+	};
+	2C4D9E040CC9EF840031092D /* OpenGL12.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1608, 64064}}";
+			sepNavSelRange = "{213678, 0}";
+			sepNavVisRange = "{207797, 6669}";
+			sepNavVisRect = "{{0, 64932}, {1031, 840}}";
+			sepNavWindowFrame = "{{1, 63}, {1070, 965}}";
+		};
+	};
+	2C4D9E090CC9EF840031092D /* Windows.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {577, 2352}}";
+			sepNavSelRange = "{2345, 0}";
+			sepNavVisRect = "{{0, 1278}, {577, 612}}";
+			sepNavWindowFrame = "{{176, 135}, {616, 741}}";
+		};
+	};
+	2C4D9E440CC9F0ED0031092D /* switches.inc */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {624, 1918}}";
+			sepNavSelRange = "{1326, 0}";
+			sepNavVisRange = "{657, 1095}";
+			sepNavVisRect = "{{0, 7}, {577, 612}}";
+			sepNavWindowFrame = "{{15, 282}, {616, 741}}";
+		};
+	};
+	2C5663EE0D35645700D4FF53 /* portaudio.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {881, 16842}}";
+			sepNavSelRange = "{2289, 0}";
+			sepNavVisRange = "{7295, 1046}";
+		};
+	};
+	2C56642B0D35683200D4FF53 /* SDLMain.m */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {881, 5404}}";
+			sepNavSelRange = "{247, 16}";
+			sepNavVisRange = "{0, 1181}";
+		};
+	};
+	2C8937290CE393FB005D8A87 /* UPlatform.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {717, 1120}}";
+			sepNavSelRange = "{830, 0}";
+			sepNavVisRange = "{241, 1433}";
+			sepNavVisRect = "{{0, 0}, {737, 826}}";
+			sepNavWindowFrame = "{{200, 71}, {776, 955}}";
+		};
+	};
+	2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {744, 1890}}";
+			sepNavSelRange = "{717, 0}";
+			sepNavVisRange = "{410, 1660}";
+			sepNavVisRect = "{{0, 105}, {737, 827}}";
+			sepNavWindowFrame = "{{79, 70}, {776, 956}}";
+		};
+	};
+	2CA607DD0D998F0B00EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C4D9C7B0CC9EC8C0031092D /* UMain.pas */;
+		name = "UMain.pas: 120";
+		rLen = 0;
+		rLoc = 2684;
+		rType = 0;
+		vrLen = 1123;
+		vrLoc = 1767;
+	};
+	2CA607DF0D998F0B00EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C4D9C670CC9EC8C0031092D /* UCommon.pas */;
+		name = "UCommon.pas: 52";
+		rLen = 0;
+		rLoc = 807;
+		rType = 0;
+		vrLen = 1163;
+		vrLoc = 56;
+	};
+	2CA608780D99987200EBC4A7 /* PBXBookmark */ = {
+		isa = PBXBookmark;
+		fRef = 2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */;
+	};
+	2CA608790D99987900EBC4A7 /* PBXBookmark */ = {
+		isa = PBXBookmark;
+		fRef = 2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */;
+	};
+	2CA6088F0D99999100EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */;
+		name = "UAudioPlayback_Bass.pas: 219";
+		rLen = 3;
+		rLoc = 4658;
+		rType = 0;
+		vrLen = 1277;
+		vrLoc = 4001;
+	};
+	2CA608900D99999100EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */;
+		name = "UAudioCore_Bass.pas: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1211;
+		vrLoc = 0;
+	};
+	2CA608910D99999100EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C4D9C7B0CC9EC8C0031092D /* UMain.pas */;
+		name = "UMain.pas: 1096";
+		rLen = 0;
+		rLoc = 31433;
+		rType = 0;
+		vrLen = 1839;
+		vrLoc = 32193;
+	};
+	2CA608920D99999100EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C4D9C670CC9EC8C0031092D /* UCommon.pas */;
+		name = "UCommon.pas: 44";
+		rLen = 24;
+		rLoc = 584;
+		rType = 0;
+		vrLen = 1447;
+		vrLoc = 249;
+	};
+	2CA608930D99999100EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */;
+		name = "UScreenMain.pas: 76";
+		rLen = 17;
+		rLoc = 1560;
+		rType = 0;
+		vrLen = 1336;
+		vrLoc = 1022;
+	};
+	2CA608940D99999100EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DDC6851B09F57195004E4BFF /* UltraStarDX.pas */;
+		name = "UltraStarDX.pas: 3";
+		rLen = 0;
+		rLoc = 72;
+		rType = 0;
+		vrLen = 152;
+		vrLoc = 0;
+	};
+	2CA608950D99999100EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C4D9E040CC9EF840031092D /* OpenGL12.pas */;
+		name = "OpenGL12.pas: 4683";
+		rLen = 0;
+		rLoc = 213678;
+		rType = 0;
+		vrLen = 6669;
+		vrLoc = 207797;
+	};
+	2CA608960D99999100EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */;
+		name = "UTexture.pas: 344";
+		rLen = 0;
+		rLoc = 10496;
+		rType = 0;
+		vrLen = 1825;
+		vrLoc = 9368;
+	};
+	2CA608970D99999100EBC4A7 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */;
+		name = "UPlatformMacOSX.pas: 13";
+		rLen = 0;
+		rLoc = 717;
+		rType = 0;
+		vrLen = 1660;
+		vrLoc = 410;
+	};
+	2CAC2BDD0D3809F500CA518A /* UAudioInput_Bass.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {842, 3766}}";
+			sepNavSelRange = "{5570, 0}";
+			sepNavVisRange = "{5295, 761}";
+			sepNavWindowFrame = "{{15, 140}, {874, 883}}";
+		};
+	};
+	2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {934, 6104}}";
+			sepNavSelRange = "{4658, 3}";
+			sepNavVisRange = "{4001, 1277}";
+			sepNavWindowFrame = "{{38, 67}, {993, 935}}";
+		};
+	};
+	2CB9E87D0D43B78400214DFA /* USong.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1550, 10290}}";
+			sepNavSelRange = "{19153, 0}";
+			sepNavVisRange = "{18134, 1509}";
+			sepNavWindowFrame = "{{15, 88}, {993, 935}}";
+		};
+	};
+	2CDC716B0CDB9CB70018F966 /* StrUtils.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1013, 1022}}";
+			sepNavSelRange = "{0, 0}";
+			sepNavVisRect = "{{0, 0}, {1013, 614}}";
+			sepNavWindowFrame = "{{38, 259}, {1052, 743}}";
+		};
+	};
+	2CDD4B5D0CB9354800549FAC /* UltraStarDX */ = {
+		isa = PBXExecutable;
+		activeArgIndices = (
+		);
+		argumentStrings = (
+		);
+		autoAttachOnCrash = 1;
+		breakpointsEnabled = 0;
+		configStateDict = {
+		};
+		customDataFormattersEnabled = 1;
+		debuggerPlugin = GDBDebugging;
+		disassemblyDisplayState = 0;
+		dylibVariantSuffix = "";
+		enableDebugStr = 1;
+		environmentEntries = (
+		);
+		executableSystemSymbolLevel = 0;
+		executableUserSymbolLevel = 0;
+		libgmallocEnabled = 0;
+		name = UltraStarDX;
+		savedGlobals = {
+		};
+		sourceDirectories = (
+		);
+		variableFormatDictionary = {
+			$cs = 1;
+			$ds = 1;
+			$eax = 1;
+			$ebp = 1;
+			$ebx = 1;
+			$ecx = 1;
+			$edi = 1;
+			$edx = 1;
+			$eflags = 1;
+			$eip = 1;
+			$es = 1;
+			$esi = 1;
+			$esp = 1;
+			$gs = 1;
+			$ss = 1;
+		};
+	};
+	2CDD4B690CB9357000549FAC /* Source Control */ = {
+		isa = PBXSourceControlManager;
+		fallbackIsa = XCSourceControlManager;
+		isSCMEnabled = 0;
+		scmConfiguration = {
+		};
+		scmType = "";
+	};
+	2CDD4B6A0CB9357000549FAC /* Code sense */ = {
+		isa = PBXCodeSenseManager;
+		indexTemplatePath = "";
+	};
+	2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {934, 1764}}";
+			sepNavSelRange = "{0, 0}";
+			sepNavVisRange = "{0, 1211}";
+			sepNavWindowFrame = "{{15, 88}, {993, 935}}";
+		};
+	};
+	2CE603E10D715F8600DB0D88 /* UConfig.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {881, 3080}}";
+			sepNavSelRange = "{7279, 0}";
+			sepNavVisRange = "{6847, 865}";
+		};
+	};
+	2CEA2AF00CE3868E0097A5FF /* PseudoThread.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {842, 686}}";
+			sepNavSelRange = "{598, 0}";
+			sepNavVisRange = "{214, 458}";
+			sepNavVisRect = "{{0, 0}, {737, 826}}";
+			sepNavWindowFrame = "{{15, 68}, {776, 955}}";
+		};
+	};
+	2CF3EF210CDE13A0004F5956 /* Messages.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1013, 614}}";
+			sepNavSelRange = "{0, 0}";
+			sepNavVisRect = "{{0, 0}, {1013, 614}}";
+			sepNavWindowFrame = "{{38, 259}, {1052, 743}}";
+		};
+	};
+	2CF3EF260CDE13BA004F5956 /* MacResources.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {834, 1750}}";
+			sepNavSelRange = "{1218, 0}";
+			sepNavVisRect = "{{0, 1120}, {834, 610}}";
+			sepNavWindowFrame = "{{200, 248}, {873, 739}}";
+		};
+	};
+	2CF54F430CDA1B2B00627463 /* UScreenCredits.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {695, 19544}}";
+			sepNavSelRange = "{26865, 471}";
+			sepNavVisRange = "{25408, 2367}";
+			sepNavVisRect = "{{0, 1770}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F440CDA1B2B00627463 /* UScreenEdit.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 1610}}";
+			sepNavSelRange = "{34, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F450CDA1B2B00627463 /* UScreenEditConvert.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {842, 8484}}";
+			sepNavSelRange = "{13516, 0}";
+			sepNavVisRange = "{13202, 415}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F460CDA1B2B00627463 /* UScreenEditHeader.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 5180}}";
+			sepNavSelRange = "{59, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F470CDA1B2B00627463 /* UScreenEditSub.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1040, 19236}}";
+			sepNavSelRange = "{37, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F480CDA1B2B00627463 /* UScreenLevel.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 1302}}";
+			sepNavSelRange = "{54, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F490CDA1B2B00627463 /* UScreenLoading.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 815}}";
+			sepNavSelRange = "{58, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {695, 4326}}";
+			sepNavSelRange = "{1560, 17}";
+			sepNavVisRange = "{1022, 1336}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 79}, {754, 944}}";
+		};
+	};
+	2CF54F4B0CDA1B2B00627463 /* UScreenName.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {956, 3318}}";
+			sepNavSelRange = "{34, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F4C0CDA1B2B00627463 /* UScreenOpen.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 2366}}";
+			sepNavSelRange = "{55, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F4D0CDA1B2B00627463 /* UScreenOptions.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 2506}}";
+			sepNavSelRange = "{311, 0}";
+			sepNavVisRect = "{{0, 188}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F4E0CDA1B2B00627463 /* UScreenOptionsAdvanced.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 1484}}";
+			sepNavSelRange = "{45, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F4F0CDA1B2B00627463 /* UScreenOptionsGame.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 1582}}";
+			sepNavSelRange = "{60, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F500CDA1B2B00627463 /* UScreenOptionsGraphics.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 1400}}";
+			sepNavSelRange = "{64, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F510CDA1B2B00627463 /* UScreenOptionsLyrics.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 1330}}";
+			sepNavSelRange = "{62, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F520CDA1B2B00627463 /* UScreenOptionsRecord.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 1974}}";
+			sepNavSelRange = "{39, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F530CDA1B2B00627463 /* UScreenOptionsSound.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 1414}}";
+			sepNavSelRange = "{42, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F540CDA1B2B00627463 /* UScreenOptionsThemes.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 1680}}";
+			sepNavSelRange = "{43, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F550CDA1B2B00627463 /* UScreenPartyNewRound.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {758, 5880}}";
+			sepNavSelRange = "{62, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F560CDA1B2B00627463 /* UScreenPartyOptions.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 3640}}";
+			sepNavSelRange = "{61, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F570CDA1B2B00627463 /* UScreenPartyPlayer.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {956, 4648}}";
+			sepNavSelRange = "{62, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F580CDA1B2B00627463 /* UScreenPartyScore.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1046, 4116}}";
+			sepNavSelRange = "{61, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F590CDA1B2B00627463 /* UScreenPartyWin.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {752, 3640}}";
+			sepNavSelRange = "{59, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F5A0CDA1B2B00627463 /* UScreenPopup.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {729, 3472}}";
+			sepNavSelRange = "{1402, 0}";
+			sepNavVisRange = "{987, 787}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F5B0CDA1B2B00627463 /* UScreenScore.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {792, 14714}}";
+			sepNavSelRange = "{4909, 0}";
+			sepNavVisRange = "{4202, 810}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F5C0CDA1B2B00627463 /* UScreenSing.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1250, 18788}}";
+			sepNavSelRange = "{39356, 0}";
+			sepNavVisRange = "{39482, 1725}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 78}, {754, 944}}";
+		};
+	};
+	2CF54F5D0CDA1B2B00627463 /* UScreenSingModi.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {729, 9912}}";
+			sepNavSelRange = "{21169, 11}";
+			sepNavVisRange = "{20602, 649}";
+			sepNavVisRect = "{{0, 187}, {1277, 312}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F5E0CDA1B2B00627463 /* UScreenSong.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {881, 31066}}";
+			sepNavSelRange = "{7241, 96}";
+			sepNavVisRange = "{6687, 1426}";
+			sepNavVisRect = "{{0, 11219}, {1277, 312}}";
+			sepNavWindowFrame = "{{38, 78}, {754, 944}}";
+		};
+	};
+	2CF54F5F0CDA1B2B00627463 /* UScreenSongJumpto.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1160, 2884}}";
+			sepNavSelRange = "{61, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F600CDA1B2B00627463 /* UScreenSongMenu.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {729, 9352}}";
+			sepNavSelRange = "{1910, 0}";
+			sepNavVisRange = "{1505, 734}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F610CDA1B2B00627463 /* UScreenStatDetail.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {729, 3724}}";
+			sepNavSelRange = "{1078, 0}";
+			sepNavVisRange = "{661, 767}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F620CDA1B2B00627463 /* UScreenStatMain.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {729, 4326}}";
+			sepNavSelRange = "{1057, 0}";
+			sepNavVisRange = "{698, 731}";
+			sepNavVisRect = "{{0, 2749}, {1277, 312}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF54F630CDA1B2B00627463 /* UScreenTop5.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {729, 2492}}";
+			sepNavSelRange = "{996, 0}";
+			sepNavVisRange = "{458, 883}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF54F640CDA1B2B00627463 /* UScreenWelcome.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {715, 1694}}";
+			sepNavSelRange = "{58, 0}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{38, 58}, {754, 944}}";
+		};
+	};
+	2CF5508B0CDA22B000627463 /* ModiSDK.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {986, 2128}}";
+			sepNavSelRange = "{0, 0}";
+			sepNavVisRange = "{0, 2269}";
+			sepNavVisRect = "{{0, 0}, {715, 815}}";
+			sepNavWindowFrame = "{{15, 79}, {754, 944}}";
+		};
+	};
+	2CF5510E0CDA293700627463 /* SQLite3.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1364, 2800}}";
+			sepNavSelRange = "{517, 0}";
+			sepNavVisRect = "{{0, 0}, {1031, 840}}";
+			sepNavWindowFrame = "{{15, 54}, {1070, 969}}";
+		};
+	};
+	2CF5510F0CDA293700627463 /* SQLiteTable3.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1031, 10766}}";
+			sepNavSelRange = "{559, 0}";
+			sepNavVisRect = "{{0, 0}, {1031, 840}}";
+			sepNavWindowFrame = "{{15, 54}, {1070, 969}}";
+		};
+	};
+	2CF551A70CDA356800627463 /* UltraStar.dpr */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {914, 2674}}";
+			sepNavSelRange = "{4560, 0}";
+			sepNavVisRect = "{{0, 990}, {737, 827}}";
+			sepNavWindowFrame = "{{15, 67}, {776, 956}}";
+		};
+	};
+	2CF552110CDA3D1400627463 /* UPluginDefs.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1013, 2506}}";
+			sepNavSelRange = "{5, 11}";
+			sepNavVisRect = "{{0, 0}, {1013, 614}}";
+			sepNavWindowFrame = "{{107, 196}, {1052, 743}}";
+		};
+	};
+	2CF5529E0CDA42C900627463 /* avcodec.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {993, 28406}}";
+			sepNavSelRange = "{1536, 0}";
+			sepNavVisRange = "{0, 1591}";
+			sepNavVisRect = "{{0, 375}, {1013, 614}}";
+			sepNavWindowFrame = "{{176, 133}, {1052, 743}}";
+		};
+	};
+	2CF5529F0CDA42C900627463 /* avformat.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {993, 10206}}";
+			sepNavSelRange = "{1559, 189}";
+			sepNavVisRange = "{1159, 858}";
+			sepNavVisRect = "{{0, 298}, {1013, 614}}";
+			sepNavWindowFrame = "{{245, 70}, {1052, 743}}";
+		};
+	};
+	2CF552A00CDA42C900627463 /* avio.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1013, 3598}}";
+			sepNavSelRange = "{347, 0}";
+			sepNavVisRect = "{{0, 190}, {1013, 614}}";
+			sepNavWindowFrame = "{{199, 112}, {1052, 743}}";
+		};
+	};
+	2CF552A10CDA42C900627463 /* avutil.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {993, 2170}}";
+			sepNavSelRange = "{1520, 0}";
+			sepNavVisRange = "{0, 1756}";
+			sepNavVisRect = "{{0, 293}, {1013, 614}}";
+			sepNavWindowFrame = "{{222, 91}, {1052, 743}}";
+		};
+	};
+	2CF553070CDA51B500627463 /* sdlutils.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1013, 61068}}";
+			sepNavSelRange = "{8481, 20}";
+			sepNavVisRect = "{{0, 1054}, {1013, 614}}";
+			sepNavWindowFrame = "{{38, 259}, {1052, 743}}";
+		};
+	};
+	2CF77DB50CF7556C00F3B101 /* Modi_Until5000 */ = {
+		activeExec = 0;
+	};
+	98B8BE5C0B1F974F00162019 /* sdl.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1268, 58492}}";
+			sepNavSelRange = "{157855, 0}";
+			sepNavVisRect = "{{0, 3444}, {948, 730}}";
+			sepNavWindowFrame = "{{211, 143}, {987, 859}}";
+		};
+	};
+	DD37F2420A60255800975B2D /* fpcrtl */ = {
+		activeExec = 0;
+	};
+	DDC6850F09F5717A004E4BFF /* Project object */ = {
+		activeArchitecture = i386;
+		activeBuildConfigurationName = Release;
+		activeExecutable = 2CDD4B5D0CB9354800549FAC /* UltraStarDX */;
+		activeTarget = DDC688C709F574E9004E4BFF /* UltraStarDX */;
+		addToTargets = (
+		);
+		breakpoints = (
+		);
+		codeSenseManager = 2CDD4B6A0CB9357000549FAC /* Code sense */;
+		executables = (
+			2CDD4B5D0CB9354800549FAC /* UltraStarDX */,
+		);
+		perUserDictionary = {
+			"PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					20,
+					20,
+					198,
+					20,
+					99,
+					99,
+					29,
+					20,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXBreakpointsDataSource_ActionID,
+					PBXBreakpointsDataSource_TypeID,
+					PBXBreakpointsDataSource_BreakpointID,
+					PBXBreakpointsDataSource_UseID,
+					PBXBreakpointsDataSource_LocationID,
+					PBXBreakpointsDataSource_ConditionID,
+					PBXBreakpointsDataSource_IgnoreCountID,
+					PBXBreakpointsDataSource_ContinueID,
+				);
+			};
+			PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					22,
+					300,
+					67,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXExecutablesDataSource_ActiveFlagID,
+					PBXExecutablesDataSource_NameID,
+					PBXExecutablesDataSource_CommentsID,
+				);
+			};
+			PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					20,
+					290,
+					20,
+					48,
+					43,
+					43,
+					20,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXFileDataSource_FiletypeID,
+					PBXFileDataSource_Filename_ColumnID,
+					PBXFileDataSource_Built_ColumnID,
+					PBXFileDataSource_ObjectSize_ColumnID,
+					PBXFileDataSource_Errors_ColumnID,
+					PBXFileDataSource_Warnings_ColumnID,
+					PBXFileDataSource_Target_ColumnID,
+				);
+			};
+			PBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolNameID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					16,
+					200,
+					50,
+					119,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXSymbolsDataSource_SymbolTypeIconID,
+					PBXSymbolsDataSource_SymbolNameID,
+					PBXSymbolsDataSource_SymbolTypeID,
+					PBXSymbolsDataSource_ReferenceNameID,
+				);
+			};
+			PBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					20,
+					20,
+					266,
+					20,
+					48,
+					43,
+					43,
+					20,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXFileDataSource_SCM_ColumnID,
+					PBXFileDataSource_FiletypeID,
+					PBXFileDataSource_Filename_ColumnID,
+					PBXFileDataSource_Built_ColumnID,
+					PBXFileDataSource_ObjectSize_ColumnID,
+					PBXFileDataSource_Errors_ColumnID,
+					PBXFileDataSource_Warnings_ColumnID,
+					PBXFileDataSource_Target_ColumnID,
+				);
+			};
+			PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					20,
+					250,
+					60,
+					20,
+					48,
+					43,
+					43,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXFileDataSource_FiletypeID,
+					PBXFileDataSource_Filename_ColumnID,
+					PBXTargetDataSource_PrimaryAttribute,
+					PBXFileDataSource_Built_ColumnID,
+					PBXFileDataSource_ObjectSize_ColumnID,
+					PBXFileDataSource_Errors_ColumnID,
+					PBXFileDataSource_Warnings_ColumnID,
+				);
+			};
+			PBXPerProjectTemplateStateSaveDate = 228166993;
+			PBXWorkspaceStateSaveDate = 228166993;
+		};
+		perUserProjectItems = {
+			2C019A190D998D4A00974970 /* PBXTextBookmark */ = 2C019A190D998D4A00974970 /* PBXTextBookmark */;
+			2C019A1A0D998D4A00974970 /* PBXTextBookmark */ = 2C019A1A0D998D4A00974970 /* PBXTextBookmark */;
+			2C019A1B0D998D4A00974970 /* PBXTextBookmark */ = 2C019A1B0D998D4A00974970 /* PBXTextBookmark */;
+			2C019A1C0D998D4A00974970 /* PBXTextBookmark */ = 2C019A1C0D998D4A00974970 /* PBXTextBookmark */;
+			2C019A1D0D998D4A00974970 /* PBXTextBookmark */ = 2C019A1D0D998D4A00974970 /* PBXTextBookmark */;
+			2CA607DD0D998F0B00EBC4A7 /* PBXTextBookmark */ = 2CA607DD0D998F0B00EBC4A7 /* PBXTextBookmark */;
+			2CA607DF0D998F0B00EBC4A7 /* PBXTextBookmark */ = 2CA607DF0D998F0B00EBC4A7 /* PBXTextBookmark */;
+			2CA608780D99987200EBC4A7 /* PBXBookmark */ = 2CA608780D99987200EBC4A7 /* PBXBookmark */;
+			2CA608790D99987900EBC4A7 /* PBXBookmark */ = 2CA608790D99987900EBC4A7 /* PBXBookmark */;
+			2CA6088F0D99999100EBC4A7 /* PBXTextBookmark */ = 2CA6088F0D99999100EBC4A7 /* PBXTextBookmark */;
+			2CA608900D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608900D99999100EBC4A7 /* PBXTextBookmark */;
+			2CA608910D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608910D99999100EBC4A7 /* PBXTextBookmark */;
+			2CA608920D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608920D99999100EBC4A7 /* PBXTextBookmark */;
+			2CA608930D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608930D99999100EBC4A7 /* PBXTextBookmark */;
+			2CA608940D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608940D99999100EBC4A7 /* PBXTextBookmark */;
+			2CA608950D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608950D99999100EBC4A7 /* PBXTextBookmark */;
+			2CA608960D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608960D99999100EBC4A7 /* PBXTextBookmark */;
+			2CA608970D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608970D99999100EBC4A7 /* PBXTextBookmark */;
+		};
+		sourceControlManager = 2CDD4B690CB9357000549FAC /* Source Control */;
+		userBuildSettings = {
+		};
+	};
+	DDC6851B09F57195004E4BFF /* UltraStarDX.pas */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {928, 731}}";
+			sepNavSelRange = "{72, 0}";
+			sepNavVisRange = "{0, 152}";
+			sepNavVisRect = "{{0, 0}, {948, 730}}";
+			sepNavWindowFrame = "{{311, 112}, {987, 859}}";
+		};
+	};
+	DDC6868B09F571C2004E4BFF /* Info.plist */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1013, 614}}";
+			sepNavSelRange = "{366, 0}";
+			sepNavVisRect = "{{0, 0}, {1013, 614}}";
+			sepNavWindowFrame = "{{15, 280}, {1052, 743}}";
+		};
+	};
+	DDC688C709F574E9004E4BFF /* UltraStarDX */ = {
+		activeExec = 0;
+		executables = (
+			2CDD4B5D0CB9354800549FAC /* UltraStarDX */,
+		);
+	};
+	DDC688D409F57523004E4BFF /* Put all program sources also in this target */ = {
+		activeExec = 0;
+	};
+	DDC689B309F57C69004E4BFF /* InfoPlist.strings */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {1385, 731}}";
+			sepNavSelRange = "{256, 0}";
+			sepNavVisRect = "{{0, 0}, {1385, 731}}";
+			sepNavWindowFrame = "{{38, 142}, {1424, 860}}";
+		};
+	};
+}
diff --git a/songmanagement/dists/xcode/UltraStarDX.xcodeproj/project.pbxproj b/songmanagement/dists/xcode/UltraStarDX.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..d7902145
--- /dev/null
+++ b/songmanagement/dists/xcode/UltraStarDX.xcodeproj/project.pbxproj
@@ -0,0 +1,1613 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 42;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		2C4B70230CF7581000B0F0BD /* Until5000.dpr in Sources */ = {isa = PBXBuildFile; fileRef = 2C4B70220CF757A400B0F0BD /* Until5000.dpr */; };
+		2C4B70240CF7584500B0F0BD /* ModiSDK.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5508B0CDA22B000627463 /* ModiSDK.pas */; };
+		2C4D9C8F0CC9EC8C0031092D /* TextGL.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C620CC9EC8C0031092D /* TextGL.pas */; };
+		2C4D9C920CC9EC8C0031092D /* UCatCovers.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C650CC9EC8C0031092D /* UCatCovers.pas */; };
+		2C4D9C930CC9EC8C0031092D /* UCommandLine.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C660CC9EC8C0031092D /* UCommandLine.pas */; };
+		2C4D9C940CC9EC8C0031092D /* UCommon.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C670CC9EC8C0031092D /* UCommon.pas */; };
+		2C4D9C950CC9EC8C0031092D /* UCore.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C680CC9EC8C0031092D /* UCore.pas */; };
+		2C4D9C960CC9EC8C0031092D /* UCoreModule.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C690CC9EC8C0031092D /* UCoreModule.pas */; };
+		2C4D9C970CC9EC8C0031092D /* UCovers.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6A0CC9EC8C0031092D /* UCovers.pas */; };
+		2C4D9C980CC9EC8C0031092D /* UDataBase.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6B0CC9EC8C0031092D /* UDataBase.pas */; };
+		2C4D9C990CC9EC8C0031092D /* UDLLManager.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6C0CC9EC8C0031092D /* UDLLManager.pas */; };
+		2C4D9C9A0CC9EC8C0031092D /* UDraw.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6D0CC9EC8C0031092D /* UDraw.pas */; };
+		2C4D9C9B0CC9EC8C0031092D /* UFiles.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6E0CC9EC8C0031092D /* UFiles.pas */; };
+		2C4D9C9C0CC9EC8C0031092D /* UGraphic.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6F0CC9EC8C0031092D /* UGraphic.pas */; };
+		2C4D9C9D0CC9EC8C0031092D /* UGraphicClasses.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C700CC9EC8C0031092D /* UGraphicClasses.pas */; };
+		2C4D9C9E0CC9EC8C0031092D /* UHooks.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C710CC9EC8C0031092D /* UHooks.pas */; };
+		2C4D9C9F0CC9EC8C0031092D /* UIni.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C720CC9EC8C0031092D /* UIni.pas */; };
+		2C4D9CA00CC9EC8C0031092D /* UJoystick.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C730CC9EC8C0031092D /* UJoystick.pas */; };
+		2C4D9CA10CC9EC8C0031092D /* ULanguage.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C740CC9EC8C0031092D /* ULanguage.pas */; };
+		2C4D9CA30CC9EC8C0031092D /* ULCD.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C760CC9EC8C0031092D /* ULCD.pas */; };
+		2C4D9CA40CC9EC8C0031092D /* ULight.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C770CC9EC8C0031092D /* ULight.pas */; };
+		2C4D9CA50CC9EC8C0031092D /* ULog.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C780CC9EC8C0031092D /* ULog.pas */; };
+		2C4D9CA60CC9EC8C0031092D /* ULyrics_bak.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C790CC9EC8C0031092D /* ULyrics_bak.pas */; };
+		2C4D9CA70CC9EC8C0031092D /* ULyrics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7A0CC9EC8C0031092D /* ULyrics.pas */; };
+		2C4D9CA80CC9EC8C0031092D /* UMain.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7B0CC9EC8C0031092D /* UMain.pas */; };
+		2C4D9CA90CC9EC8C0031092D /* UMedia_dummy.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7C0CC9EC8C0031092D /* UMedia_dummy.pas */; };
+		2C4D9CAA0CC9EC8C0031092D /* UModules.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7D0CC9EC8C0031092D /* UModules.pas */; };
+		2C4D9CAB0CC9EC8C0031092D /* UMusic.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7E0CC9EC8C0031092D /* UMusic.pas */; };
+		2C4D9CAC0CC9EC8C0031092D /* UParty.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7F0CC9EC8C0031092D /* UParty.pas */; };
+		2C4D9CAD0CC9EC8C0031092D /* UPlaylist.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C800CC9EC8C0031092D /* UPlaylist.pas */; };
+		2C4D9CAF0CC9EC8C0031092D /* UPluginInterface.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C820CC9EC8C0031092D /* UPluginInterface.pas */; };
+		2C4D9CB00CC9EC8C0031092D /* uPluginLoader.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C830CC9EC8C0031092D /* uPluginLoader.pas */; };
+		2C4D9CB10CC9EC8C0031092D /* URecord.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C840CC9EC8C0031092D /* URecord.pas */; };
+		2C4D9CB20CC9EC8C0031092D /* UServices.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C850CC9EC8C0031092D /* UServices.pas */; };
+		2C4D9CB30CC9EC8C0031092D /* USingNotes.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C860CC9EC8C0031092D /* USingNotes.pas */; };
+		2C4D9CB40CC9EC8C0031092D /* USingScores.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C870CC9EC8C0031092D /* USingScores.pas */; };
+		2C4D9CB50CC9EC8C0031092D /* USkins.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C880CC9EC8C0031092D /* USkins.pas */; };
+		2C4D9CB60CC9EC8C0031092D /* USongs.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C890CC9EC8C0031092D /* USongs.pas */; };
+		2C4D9CB70CC9EC8C0031092D /* UTextClasses.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8A0CC9EC8C0031092D /* UTextClasses.pas */; };
+		2C4D9CB80CC9EC8C0031092D /* UTexture.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */; };
+		2C4D9CB90CC9EC8C0031092D /* UThemes.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8C0CC9EC8C0031092D /* UThemes.pas */; };
+		2C4D9CBA0CC9EC8C0031092D /* UTime.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8D0CC9EC8C0031092D /* UTime.pas */; };
+		2C4D9CBB0CC9EC8C0031092D /* UVideo.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8E0CC9EC8C0031092D /* UVideo.pas */; };
+		2C4D9CBC0CC9EC8C0031092D /* TextGL.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C620CC9EC8C0031092D /* TextGL.pas */; };
+		2C4D9CBF0CC9EC8C0031092D /* UCatCovers.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C650CC9EC8C0031092D /* UCatCovers.pas */; };
+		2C4D9CC00CC9EC8C0031092D /* UCommandLine.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C660CC9EC8C0031092D /* UCommandLine.pas */; };
+		2C4D9CC10CC9EC8C0031092D /* UCommon.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C670CC9EC8C0031092D /* UCommon.pas */; };
+		2C4D9CC20CC9EC8C0031092D /* UCore.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C680CC9EC8C0031092D /* UCore.pas */; };
+		2C4D9CC30CC9EC8C0031092D /* UCoreModule.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C690CC9EC8C0031092D /* UCoreModule.pas */; };
+		2C4D9CC40CC9EC8C0031092D /* UCovers.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6A0CC9EC8C0031092D /* UCovers.pas */; };
+		2C4D9CC50CC9EC8C0031092D /* UDataBase.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6B0CC9EC8C0031092D /* UDataBase.pas */; };
+		2C4D9CC60CC9EC8C0031092D /* UDLLManager.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6C0CC9EC8C0031092D /* UDLLManager.pas */; };
+		2C4D9CC70CC9EC8C0031092D /* UDraw.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6D0CC9EC8C0031092D /* UDraw.pas */; };
+		2C4D9CC80CC9EC8C0031092D /* UFiles.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6E0CC9EC8C0031092D /* UFiles.pas */; };
+		2C4D9CC90CC9EC8C0031092D /* UGraphic.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C6F0CC9EC8C0031092D /* UGraphic.pas */; };
+		2C4D9CCA0CC9EC8C0031092D /* UGraphicClasses.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C700CC9EC8C0031092D /* UGraphicClasses.pas */; };
+		2C4D9CCB0CC9EC8C0031092D /* UHooks.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C710CC9EC8C0031092D /* UHooks.pas */; };
+		2C4D9CCC0CC9EC8C0031092D /* UIni.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C720CC9EC8C0031092D /* UIni.pas */; };
+		2C4D9CCD0CC9EC8C0031092D /* UJoystick.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C730CC9EC8C0031092D /* UJoystick.pas */; };
+		2C4D9CCE0CC9EC8C0031092D /* ULanguage.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C740CC9EC8C0031092D /* ULanguage.pas */; };
+		2C4D9CD00CC9EC8C0031092D /* ULCD.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C760CC9EC8C0031092D /* ULCD.pas */; };
+		2C4D9CD10CC9EC8C0031092D /* ULight.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C770CC9EC8C0031092D /* ULight.pas */; };
+		2C4D9CD20CC9EC8C0031092D /* ULog.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C780CC9EC8C0031092D /* ULog.pas */; };
+		2C4D9CD30CC9EC8C0031092D /* ULyrics_bak.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C790CC9EC8C0031092D /* ULyrics_bak.pas */; };
+		2C4D9CD40CC9EC8C0031092D /* ULyrics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7A0CC9EC8C0031092D /* ULyrics.pas */; };
+		2C4D9CD50CC9EC8C0031092D /* UMain.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7B0CC9EC8C0031092D /* UMain.pas */; };
+		2C4D9CD60CC9EC8C0031092D /* UMedia_dummy.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7C0CC9EC8C0031092D /* UMedia_dummy.pas */; };
+		2C4D9CD70CC9EC8C0031092D /* UModules.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7D0CC9EC8C0031092D /* UModules.pas */; };
+		2C4D9CD80CC9EC8C0031092D /* UMusic.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7E0CC9EC8C0031092D /* UMusic.pas */; };
+		2C4D9CD90CC9EC8C0031092D /* UParty.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C7F0CC9EC8C0031092D /* UParty.pas */; };
+		2C4D9CDA0CC9EC8C0031092D /* UPlaylist.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C800CC9EC8C0031092D /* UPlaylist.pas */; };
+		2C4D9CDC0CC9EC8C0031092D /* UPluginInterface.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C820CC9EC8C0031092D /* UPluginInterface.pas */; };
+		2C4D9CDD0CC9EC8C0031092D /* uPluginLoader.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C830CC9EC8C0031092D /* uPluginLoader.pas */; };
+		2C4D9CDE0CC9EC8C0031092D /* URecord.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C840CC9EC8C0031092D /* URecord.pas */; };
+		2C4D9CDF0CC9EC8C0031092D /* UServices.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C850CC9EC8C0031092D /* UServices.pas */; };
+		2C4D9CE00CC9EC8C0031092D /* USingNotes.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C860CC9EC8C0031092D /* USingNotes.pas */; };
+		2C4D9CE10CC9EC8C0031092D /* USingScores.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C870CC9EC8C0031092D /* USingScores.pas */; };
+		2C4D9CE20CC9EC8C0031092D /* USkins.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C880CC9EC8C0031092D /* USkins.pas */; };
+		2C4D9CE30CC9EC8C0031092D /* USongs.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C890CC9EC8C0031092D /* USongs.pas */; };
+		2C4D9CE40CC9EC8C0031092D /* UTextClasses.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8A0CC9EC8C0031092D /* UTextClasses.pas */; };
+		2C4D9CE50CC9EC8C0031092D /* UTexture.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */; };
+		2C4D9CE60CC9EC8C0031092D /* UThemes.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8C0CC9EC8C0031092D /* UThemes.pas */; };
+		2C4D9CE70CC9EC8C0031092D /* UTime.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8D0CC9EC8C0031092D /* UTime.pas */; };
+		2C4D9CE80CC9EC8C0031092D /* UVideo.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9C8E0CC9EC8C0031092D /* UVideo.pas */; };
+		2C4D9D920CC9ED4F0031092D /* FreeBitmap.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9D900CC9ED4F0031092D /* FreeBitmap.pas */; };
+		2C4D9D930CC9ED4F0031092D /* FreeImage.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9D910CC9ED4F0031092D /* FreeImage.pas */; };
+		2C4D9D940CC9ED4F0031092D /* FreeBitmap.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9D900CC9ED4F0031092D /* FreeBitmap.pas */; };
+		2C4D9D950CC9ED4F0031092D /* FreeImage.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9D910CC9ED4F0031092D /* FreeImage.pas */; };
+		2C4D9D970CC9EDEB0031092D /* libfreeimage.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C4D9D960CC9EDEB0031092D /* libfreeimage.dylib */; };
+		2C4D9D9A0CC9EE0B0031092D /* SDL_image.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C4D9D980CC9EE0B0031092D /* SDL_image.framework */; };
+		2C4D9D9B0CC9EE0B0031092D /* SDL_ttf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C4D9D990CC9EE0B0031092D /* SDL_ttf.framework */; };
+		2C4D9DD60CC9EE6F0031092D /* UDisplay.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DCC0CC9EE6F0031092D /* UDisplay.pas */; };
+		2C4D9DD70CC9EE6F0031092D /* UDrawTexture.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DCD0CC9EE6F0031092D /* UDrawTexture.pas */; };
+		2C4D9DD80CC9EE6F0031092D /* UMenu.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DCE0CC9EE6F0031092D /* UMenu.pas */; };
+		2C4D9DD90CC9EE6F0031092D /* UMenuButton.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DCF0CC9EE6F0031092D /* UMenuButton.pas */; };
+		2C4D9DDA0CC9EE6F0031092D /* UMenuButtonCollection.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD00CC9EE6F0031092D /* UMenuButtonCollection.pas */; };
+		2C4D9DDB0CC9EE6F0031092D /* UMenuInteract.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD10CC9EE6F0031092D /* UMenuInteract.pas */; };
+		2C4D9DDC0CC9EE6F0031092D /* UMenuSelect.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD20CC9EE6F0031092D /* UMenuSelect.pas */; };
+		2C4D9DDD0CC9EE6F0031092D /* UMenuSelectSlide.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD30CC9EE6F0031092D /* UMenuSelectSlide.pas */; };
+		2C4D9DDE0CC9EE6F0031092D /* UMenuStatic.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD40CC9EE6F0031092D /* UMenuStatic.pas */; };
+		2C4D9DDF0CC9EE6F0031092D /* UMenuText.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD50CC9EE6F0031092D /* UMenuText.pas */; };
+		2C4D9DE00CC9EE6F0031092D /* UDisplay.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DCC0CC9EE6F0031092D /* UDisplay.pas */; };
+		2C4D9DE10CC9EE6F0031092D /* UDrawTexture.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DCD0CC9EE6F0031092D /* UDrawTexture.pas */; };
+		2C4D9DE20CC9EE6F0031092D /* UMenu.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DCE0CC9EE6F0031092D /* UMenu.pas */; };
+		2C4D9DE30CC9EE6F0031092D /* UMenuButton.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DCF0CC9EE6F0031092D /* UMenuButton.pas */; };
+		2C4D9DE40CC9EE6F0031092D /* UMenuButtonCollection.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD00CC9EE6F0031092D /* UMenuButtonCollection.pas */; };
+		2C4D9DE50CC9EE6F0031092D /* UMenuInteract.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD10CC9EE6F0031092D /* UMenuInteract.pas */; };
+		2C4D9DE60CC9EE6F0031092D /* UMenuSelect.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD20CC9EE6F0031092D /* UMenuSelect.pas */; };
+		2C4D9DE70CC9EE6F0031092D /* UMenuSelectSlide.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD30CC9EE6F0031092D /* UMenuSelectSlide.pas */; };
+		2C4D9DE80CC9EE6F0031092D /* UMenuStatic.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD40CC9EE6F0031092D /* UMenuStatic.pas */; };
+		2C4D9DE90CC9EE6F0031092D /* UMenuText.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DD50CC9EE6F0031092D /* UMenuText.pas */; };
+		2C4D9DED0CC9EF0A0031092D /* sdl_image.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DEC0CC9EF0A0031092D /* sdl_image.pas */; };
+		2C4D9DEE0CC9EF0A0031092D /* sdl_image.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DEC0CC9EF0A0031092D /* sdl_image.pas */; };
+		2C4D9DF10CC9EF210031092D /* sdl_ttf.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DEF0CC9EF210031092D /* sdl_ttf.pas */; };
+		2C4D9DF30CC9EF210031092D /* sdl_ttf.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9DEF0CC9EF210031092D /* sdl_ttf.pas */; };
+		2C4D9E100CC9EF840031092D /* OpenGL12.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9E040CC9EF840031092D /* OpenGL12.pas */; };
+		2C4D9E150CC9EF840031092D /* Windows.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9E090CC9EF840031092D /* Windows.pas */; };
+		2C4D9E1C0CC9EF840031092D /* OpenGL12.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9E040CC9EF840031092D /* OpenGL12.pas */; };
+		2C4D9E210CC9EF840031092D /* Windows.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9E090CC9EF840031092D /* Windows.pas */; };
+		2C4D9E450CC9F0ED0031092D /* switches.inc in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9E440CC9F0ED0031092D /* switches.inc */; };
+		2C4D9E460CC9F0ED0031092D /* switches.inc in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D9E440CC9F0ED0031092D /* switches.inc */; };
+		2C4FA2A80CDBAD1E002CC3B0 /* ustar-icon_v01.icns in Resources */ = {isa = PBXBuildFile; fileRef = 2C4FA2A70CDBAD1E002CC3B0 /* ustar-icon_v01.icns */; };
+		2C5663EF0D35645700D4FF53 /* portaudio.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C5663EE0D35645700D4FF53 /* portaudio.pas */; };
+		2C5663F00D35645700D4FF53 /* portaudio.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C5663EE0D35645700D4FF53 /* portaudio.pas */; };
+		2C56642C0D35683200D4FF53 /* SDLMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C56642B0D35683200D4FF53 /* SDLMain.m */; };
+		2C89372A0CE393FB005D8A87 /* UPlatform.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C8937290CE393FB005D8A87 /* UPlatform.pas */; };
+		2C89372B0CE393FB005D8A87 /* UPlatform.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C8937290CE393FB005D8A87 /* UPlatform.pas */; };
+		2C8937340CE395CE005D8A87 /* UPlatformMacOSX.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */; };
+		2C8937370CE395CE005D8A87 /* UPlatformMacOSX.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */; };
+		2CAC2BE20D3809F500CA518A /* UAudioInput_Bass.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CAC2BDD0D3809F500CA518A /* UAudioInput_Bass.pas */; };
+		2CAC2BE40D3809F500CA518A /* UAudioPlayback_Bass.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */; };
+		2CAC2BE70D3809F500CA518A /* UAudioInput_Bass.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CAC2BDD0D3809F500CA518A /* UAudioInput_Bass.pas */; };
+		2CAC2BE90D3809F500CA518A /* UAudioPlayback_Bass.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */; };
+		2CAC2BF10D380AC200CA518A /* libbass.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CAC2BF00D380AC200CA518A /* libbass.dylib */; };
+		2CAC2BF40D380AE800CA518A /* libbass.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2CAC2BF00D380AC200CA518A /* libbass.dylib */; };
+		2CAC2BF80D380B1B00CA518A /* Bass.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CAC2BF70D380B1B00CA518A /* Bass.pas */; };
+		2CAC2BF90D380B1B00CA518A /* Bass.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CAC2BF70D380B1B00CA518A /* Bass.pas */; };
+		2CB9E87E0D43B78400214DFA /* USong.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CB9E87D0D43B78400214DFA /* USong.pas */; };
+		2CB9E87F0D43B78400214DFA /* USong.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CB9E87D0D43B78400214DFA /* USong.pas */; };
+		2CDC716C0CDB9CB70018F966 /* StrUtils.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CDC716B0CDB9CB70018F966 /* StrUtils.pas */; };
+		2CDC716D0CDB9CB70018F966 /* StrUtils.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CDC716B0CDB9CB70018F966 /* StrUtils.pas */; };
+		2CDD4BDE0CB947A400549FAC /* sdl.pas in Sources */ = {isa = PBXBuildFile; fileRef = 98B8BE5C0B1F974F00162019 /* sdl.pas */; };
+		2CDD4BE00CB947B100549FAC /* sdl.pas in Sources */ = {isa = PBXBuildFile; fileRef = 98B8BE5C0B1F974F00162019 /* sdl.pas */; };
+		2CDD4BE20CB947BE00549FAC /* UltraStarDX.pas in Sources */ = {isa = PBXBuildFile; fileRef = DDC6851B09F57195004E4BFF /* UltraStarDX.pas */; };
+		2CDEA4F70CBD725B0096994C /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CDEA4F60CBD725B0096994C /* OpenGL.framework */; };
+		2CDEC4960CC5264600FFA244 /* SDL.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 98B8BE570B1F972400162019 /* SDL.framework */; };
+		2CE603DA0D715F2100DB0D88 /* mathematics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CE603D90D715F2100DB0D88 /* mathematics.pas */; };
+		2CE603DB0D715F2100DB0D88 /* mathematics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CE603D90D715F2100DB0D88 /* mathematics.pas */; };
+		2CE603DE0D715F6700DB0D88 /* UAudioCore_Bass.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */; };
+		2CE603DF0D715F6700DB0D88 /* UAudioCore_Bass.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */; };
+		2CE603E20D715F8600DB0D88 /* UConfig.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CE603E10D715F8600DB0D88 /* UConfig.pas */; };
+		2CE603E30D715F8600DB0D88 /* UConfig.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CE603E10D715F8600DB0D88 /* UConfig.pas */; };
+		2CE907930D1BC8A800A1FDFF /* libavcodec.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CE907900D1BC8A800A1FDFF /* libavcodec.dylib */; };
+		2CE907940D1BC8A800A1FDFF /* libavformat.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CE907910D1BC8A800A1FDFF /* libavformat.dylib */; };
+		2CE907950D1BC8A800A1FDFF /* libavutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CE907920D1BC8A800A1FDFF /* libavutil.dylib */; };
+		2CE907980D1BC90A00A1FDFF /* libavcodec.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2CE907900D1BC8A800A1FDFF /* libavcodec.dylib */; };
+		2CE907990D1BC91D00A1FDFF /* libavformat.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2CE907910D1BC8A800A1FDFF /* libavformat.dylib */; };
+		2CE9079A0D1BC91D00A1FDFF /* libavutil.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2CE907920D1BC8A800A1FDFF /* libavutil.dylib */; };
+		2CEA2AE00CE385190097A5FF /* Graphics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CEA2ADE0CE385190097A5FF /* Graphics.pas */; };
+		2CEA2AE10CE385190097A5FF /* JPEG.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CEA2ADF0CE385190097A5FF /* JPEG.pas */; };
+		2CEA2AE20CE385190097A5FF /* Graphics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CEA2ADE0CE385190097A5FF /* Graphics.pas */; };
+		2CEA2AE30CE385190097A5FF /* JPEG.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CEA2ADF0CE385190097A5FF /* JPEG.pas */; };
+		2CEA2AF10CE3868E0097A5FF /* PseudoThread.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CEA2AF00CE3868E0097A5FF /* PseudoThread.pas */; };
+		2CEA2AF20CE3868E0097A5FF /* PseudoThread.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CEA2AF00CE3868E0097A5FF /* PseudoThread.pas */; };
+		2CF3EF220CDE13A0004F5956 /* Messages.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF3EF210CDE13A0004F5956 /* Messages.pas */; };
+		2CF3EF230CDE13A0004F5956 /* Messages.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF3EF210CDE13A0004F5956 /* Messages.pas */; };
+		2CF3EF270CDE13BA004F5956 /* MacResources.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF3EF260CDE13BA004F5956 /* MacResources.pas */; };
+		2CF3EF280CDE13BA004F5956 /* MacResources.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF3EF260CDE13BA004F5956 /* MacResources.pas */; };
+		2CF54F650CDA1B2B00627463 /* UScreenCredits.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F430CDA1B2B00627463 /* UScreenCredits.pas */; };
+		2CF54F660CDA1B2B00627463 /* UScreenEdit.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F440CDA1B2B00627463 /* UScreenEdit.pas */; };
+		2CF54F670CDA1B2B00627463 /* UScreenEditConvert.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F450CDA1B2B00627463 /* UScreenEditConvert.pas */; };
+		2CF54F680CDA1B2B00627463 /* UScreenEditHeader.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F460CDA1B2B00627463 /* UScreenEditHeader.pas */; };
+		2CF54F690CDA1B2B00627463 /* UScreenEditSub.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F470CDA1B2B00627463 /* UScreenEditSub.pas */; };
+		2CF54F6A0CDA1B2B00627463 /* UScreenLevel.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F480CDA1B2B00627463 /* UScreenLevel.pas */; };
+		2CF54F6B0CDA1B2B00627463 /* UScreenLoading.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F490CDA1B2B00627463 /* UScreenLoading.pas */; };
+		2CF54F6C0CDA1B2B00627463 /* UScreenMain.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */; };
+		2CF54F6D0CDA1B2B00627463 /* UScreenName.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4B0CDA1B2B00627463 /* UScreenName.pas */; };
+		2CF54F6E0CDA1B2B00627463 /* UScreenOpen.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4C0CDA1B2B00627463 /* UScreenOpen.pas */; };
+		2CF54F6F0CDA1B2B00627463 /* UScreenOptions.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4D0CDA1B2B00627463 /* UScreenOptions.pas */; };
+		2CF54F700CDA1B2B00627463 /* UScreenOptionsAdvanced.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4E0CDA1B2B00627463 /* UScreenOptionsAdvanced.pas */; };
+		2CF54F710CDA1B2B00627463 /* UScreenOptionsGame.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4F0CDA1B2B00627463 /* UScreenOptionsGame.pas */; };
+		2CF54F720CDA1B2B00627463 /* UScreenOptionsGraphics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F500CDA1B2B00627463 /* UScreenOptionsGraphics.pas */; };
+		2CF54F730CDA1B2B00627463 /* UScreenOptionsLyrics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F510CDA1B2B00627463 /* UScreenOptionsLyrics.pas */; };
+		2CF54F740CDA1B2B00627463 /* UScreenOptionsRecord.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F520CDA1B2B00627463 /* UScreenOptionsRecord.pas */; };
+		2CF54F750CDA1B2B00627463 /* UScreenOptionsSound.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F530CDA1B2B00627463 /* UScreenOptionsSound.pas */; };
+		2CF54F760CDA1B2B00627463 /* UScreenOptionsThemes.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F540CDA1B2B00627463 /* UScreenOptionsThemes.pas */; };
+		2CF54F770CDA1B2B00627463 /* UScreenPartyNewRound.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F550CDA1B2B00627463 /* UScreenPartyNewRound.pas */; };
+		2CF54F780CDA1B2B00627463 /* UScreenPartyOptions.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F560CDA1B2B00627463 /* UScreenPartyOptions.pas */; };
+		2CF54F790CDA1B2B00627463 /* UScreenPartyPlayer.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F570CDA1B2B00627463 /* UScreenPartyPlayer.pas */; };
+		2CF54F7A0CDA1B2B00627463 /* UScreenPartyScore.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F580CDA1B2B00627463 /* UScreenPartyScore.pas */; };
+		2CF54F7B0CDA1B2B00627463 /* UScreenPartyWin.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F590CDA1B2B00627463 /* UScreenPartyWin.pas */; };
+		2CF54F7C0CDA1B2B00627463 /* UScreenPopup.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5A0CDA1B2B00627463 /* UScreenPopup.pas */; };
+		2CF54F7D0CDA1B2B00627463 /* UScreenScore.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5B0CDA1B2B00627463 /* UScreenScore.pas */; };
+		2CF54F7E0CDA1B2B00627463 /* UScreenSing.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5C0CDA1B2B00627463 /* UScreenSing.pas */; };
+		2CF54F7F0CDA1B2B00627463 /* UScreenSingModi.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5D0CDA1B2B00627463 /* UScreenSingModi.pas */; };
+		2CF54F800CDA1B2B00627463 /* UScreenSong.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5E0CDA1B2B00627463 /* UScreenSong.pas */; };
+		2CF54F810CDA1B2B00627463 /* UScreenSongJumpto.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5F0CDA1B2B00627463 /* UScreenSongJumpto.pas */; };
+		2CF54F820CDA1B2B00627463 /* UScreenSongMenu.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F600CDA1B2B00627463 /* UScreenSongMenu.pas */; };
+		2CF54F830CDA1B2B00627463 /* UScreenStatDetail.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F610CDA1B2B00627463 /* UScreenStatDetail.pas */; };
+		2CF54F840CDA1B2B00627463 /* UScreenStatMain.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F620CDA1B2B00627463 /* UScreenStatMain.pas */; };
+		2CF54F850CDA1B2B00627463 /* UScreenTop5.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F630CDA1B2B00627463 /* UScreenTop5.pas */; };
+		2CF54F860CDA1B2B00627463 /* UScreenWelcome.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F640CDA1B2B00627463 /* UScreenWelcome.pas */; };
+		2CF54F870CDA1B2B00627463 /* UScreenCredits.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F430CDA1B2B00627463 /* UScreenCredits.pas */; };
+		2CF54F880CDA1B2B00627463 /* UScreenEdit.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F440CDA1B2B00627463 /* UScreenEdit.pas */; };
+		2CF54F890CDA1B2B00627463 /* UScreenEditConvert.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F450CDA1B2B00627463 /* UScreenEditConvert.pas */; };
+		2CF54F8A0CDA1B2B00627463 /* UScreenEditHeader.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F460CDA1B2B00627463 /* UScreenEditHeader.pas */; };
+		2CF54F8B0CDA1B2B00627463 /* UScreenEditSub.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F470CDA1B2B00627463 /* UScreenEditSub.pas */; };
+		2CF54F8C0CDA1B2B00627463 /* UScreenLevel.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F480CDA1B2B00627463 /* UScreenLevel.pas */; };
+		2CF54F8D0CDA1B2B00627463 /* UScreenLoading.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F490CDA1B2B00627463 /* UScreenLoading.pas */; };
+		2CF54F8E0CDA1B2B00627463 /* UScreenMain.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */; };
+		2CF54F8F0CDA1B2B00627463 /* UScreenName.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4B0CDA1B2B00627463 /* UScreenName.pas */; };
+		2CF54F900CDA1B2B00627463 /* UScreenOpen.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4C0CDA1B2B00627463 /* UScreenOpen.pas */; };
+		2CF54F910CDA1B2B00627463 /* UScreenOptions.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4D0CDA1B2B00627463 /* UScreenOptions.pas */; };
+		2CF54F920CDA1B2B00627463 /* UScreenOptionsAdvanced.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4E0CDA1B2B00627463 /* UScreenOptionsAdvanced.pas */; };
+		2CF54F930CDA1B2B00627463 /* UScreenOptionsGame.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F4F0CDA1B2B00627463 /* UScreenOptionsGame.pas */; };
+		2CF54F940CDA1B2B00627463 /* UScreenOptionsGraphics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F500CDA1B2B00627463 /* UScreenOptionsGraphics.pas */; };
+		2CF54F950CDA1B2B00627463 /* UScreenOptionsLyrics.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F510CDA1B2B00627463 /* UScreenOptionsLyrics.pas */; };
+		2CF54F960CDA1B2B00627463 /* UScreenOptionsRecord.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F520CDA1B2B00627463 /* UScreenOptionsRecord.pas */; };
+		2CF54F970CDA1B2B00627463 /* UScreenOptionsSound.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F530CDA1B2B00627463 /* UScreenOptionsSound.pas */; };
+		2CF54F980CDA1B2B00627463 /* UScreenOptionsThemes.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F540CDA1B2B00627463 /* UScreenOptionsThemes.pas */; };
+		2CF54F990CDA1B2B00627463 /* UScreenPartyNewRound.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F550CDA1B2B00627463 /* UScreenPartyNewRound.pas */; };
+		2CF54F9A0CDA1B2B00627463 /* UScreenPartyOptions.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F560CDA1B2B00627463 /* UScreenPartyOptions.pas */; };
+		2CF54F9B0CDA1B2B00627463 /* UScreenPartyPlayer.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F570CDA1B2B00627463 /* UScreenPartyPlayer.pas */; };
+		2CF54F9C0CDA1B2B00627463 /* UScreenPartyScore.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F580CDA1B2B00627463 /* UScreenPartyScore.pas */; };
+		2CF54F9D0CDA1B2B00627463 /* UScreenPartyWin.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F590CDA1B2B00627463 /* UScreenPartyWin.pas */; };
+		2CF54F9E0CDA1B2B00627463 /* UScreenPopup.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5A0CDA1B2B00627463 /* UScreenPopup.pas */; };
+		2CF54F9F0CDA1B2B00627463 /* UScreenScore.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5B0CDA1B2B00627463 /* UScreenScore.pas */; };
+		2CF54FA00CDA1B2B00627463 /* UScreenSing.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5C0CDA1B2B00627463 /* UScreenSing.pas */; };
+		2CF54FA10CDA1B2B00627463 /* UScreenSingModi.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5D0CDA1B2B00627463 /* UScreenSingModi.pas */; };
+		2CF54FA20CDA1B2B00627463 /* UScreenSong.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5E0CDA1B2B00627463 /* UScreenSong.pas */; };
+		2CF54FA30CDA1B2B00627463 /* UScreenSongJumpto.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F5F0CDA1B2B00627463 /* UScreenSongJumpto.pas */; };
+		2CF54FA40CDA1B2B00627463 /* UScreenSongMenu.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F600CDA1B2B00627463 /* UScreenSongMenu.pas */; };
+		2CF54FA50CDA1B2B00627463 /* UScreenStatDetail.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F610CDA1B2B00627463 /* UScreenStatDetail.pas */; };
+		2CF54FA60CDA1B2B00627463 /* UScreenStatMain.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F620CDA1B2B00627463 /* UScreenStatMain.pas */; };
+		2CF54FA70CDA1B2B00627463 /* UScreenTop5.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F630CDA1B2B00627463 /* UScreenTop5.pas */; };
+		2CF54FA80CDA1B2B00627463 /* UScreenWelcome.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF54F640CDA1B2B00627463 /* UScreenWelcome.pas */; };
+		2CF5508C0CDA22B000627463 /* ModiSDK.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5508B0CDA22B000627463 /* ModiSDK.pas */; };
+		2CF5508D0CDA22B000627463 /* ModiSDK.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5508B0CDA22B000627463 /* ModiSDK.pas */; };
+		2CF551100CDA293700627463 /* SQLite3.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5510E0CDA293700627463 /* SQLite3.pas */; };
+		2CF551110CDA293700627463 /* SQLiteTable3.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5510F0CDA293700627463 /* SQLiteTable3.pas */; };
+		2CF551120CDA293700627463 /* SQLite3.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5510E0CDA293700627463 /* SQLite3.pas */; };
+		2CF551130CDA293700627463 /* SQLiteTable3.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5510F0CDA293700627463 /* SQLiteTable3.pas */; };
+		2CF5512D0CDA29C600627463 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CF5512C0CDA29C600627463 /* libsqlite3.dylib */; };
+		2CF552140CDA3D1400627463 /* UPluginDefs.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552110CDA3D1400627463 /* UPluginDefs.pas */; };
+		2CF552170CDA3D1400627463 /* UPluginDefs.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552110CDA3D1400627463 /* UPluginDefs.pas */; };
+		2CF552A70CDA42C900627463 /* avcodec.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5529E0CDA42C900627463 /* avcodec.pas */; };
+		2CF552A80CDA42C900627463 /* avformat.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5529F0CDA42C900627463 /* avformat.pas */; };
+		2CF552A90CDA42C900627463 /* avio.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552A00CDA42C900627463 /* avio.pas */; };
+		2CF552AA0CDA42C900627463 /* avutil.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552A10CDA42C900627463 /* avutil.pas */; };
+		2CF552AD0CDA42C900627463 /* opt.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552A40CDA42C900627463 /* opt.pas */; };
+		2CF552AE0CDA42C900627463 /* rational.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552A50CDA42C900627463 /* rational.pas */; };
+		2CF552B00CDA42C900627463 /* avcodec.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5529E0CDA42C900627463 /* avcodec.pas */; };
+		2CF552B10CDA42C900627463 /* avformat.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF5529F0CDA42C900627463 /* avformat.pas */; };
+		2CF552B20CDA42C900627463 /* avio.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552A00CDA42C900627463 /* avio.pas */; };
+		2CF552B30CDA42C900627463 /* avutil.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552A10CDA42C900627463 /* avutil.pas */; };
+		2CF552B60CDA42C900627463 /* opt.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552A40CDA42C900627463 /* opt.pas */; };
+		2CF552B70CDA42C900627463 /* rational.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF552A50CDA42C900627463 /* rational.pas */; };
+		2CF553080CDA51B500627463 /* sdlutils.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF553070CDA51B500627463 /* sdlutils.pas */; };
+		2CF553090CDA51B500627463 /* sdlutils.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF553070CDA51B500627463 /* sdlutils.pas */; };
+		2CF553100CDA52D100627463 /* SDL_image.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2C4D9D980CC9EE0B0031092D /* SDL_image.framework */; };
+		2CF5533B0CDA52E200627463 /* SDL_ttf.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2C4D9D990CC9EE0B0031092D /* SDL_ttf.framework */; };
+		2CF5533F0CDA531100627463 /* libfreeimage.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2C4D9D960CC9EDEB0031092D /* libfreeimage.dylib */; };
+		2CF553400CDA531100627463 /* libsqlite3.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2CF5512C0CDA29C600627463 /* libsqlite3.dylib */; };
+		2CF8E6BE0CDFA8E80053A996 /* UPartyDefs.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF8E6BD0CDFA8E80053A996 /* UPartyDefs.pas */; };
+		2CF8E6BF0CDFA8E80053A996 /* UPartyDefs.pas in Sources */ = {isa = PBXBuildFile; fileRef = 2CF8E6BD0CDFA8E80053A996 /* UPartyDefs.pas */; };
+		98B8BE340B1F947800162019 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 98B8BE330B1F947800162019 /* AppKit.framework */; };
+		98B8BE390B1F949C00162019 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 98B8BE370B1F949C00162019 /* Cocoa.framework */; };
+		98B8BE3A0B1F949C00162019 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 98B8BE380B1F949C00162019 /* Foundation.framework */; };
+		98B8BE580B1F972400162019 /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 98B8BE570B1F972400162019 /* SDL.framework */; };
+		DD37F23D0A60252800975B2D /* UltraStarDX.pas in Sources */ = {isa = PBXBuildFile; fileRef = DDC6851B09F57195004E4BFF /* UltraStarDX.pas */; };
+		DD37F2C70A6037EA00975B2D /* libfpcrtl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DD37F2430A60255800975B2D /* libfpcrtl.a */; };
+		DDC689B509F57C69004E4BFF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DDC689B309F57C69004E4BFF /* InfoPlist.strings */; };
+		DDC689B609F57C69004E4BFF /* SDLMain.nib in Resources */ = {isa = PBXBuildFile; fileRef = DDC689B409F57C69004E4BFF /* SDLMain.nib */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXBuildRule section */
+		DD7C44CD0A6E5050003FA52B /* PBXBuildRule */ = {
+			isa = PBXBuildRule;
+			compilerSpec = com.apple.compilers.proxy.script;
+			filePatterns = "*.inc";
+			fileType = pattern.proxy;
+			isEditable = 1;
+			outputFiles = (
+				"$(TARGET_TEMP_DIR)/$(INPUT_FILE_NAME).compiled",
+			);
+			script = "echo \\\"-Fi$INPUT_FILE_DIR\\\" >> \"$PROJECT_TEMP_DIR\"/unitpaths\ntouch \"$TARGET_TEMP_DIR\"/\"$INPUT_FILE_NAME\".compiled\n";
+		};
+		DD7C45710A6E7E36003FA52B /* PBXBuildRule */ = {
+			isa = PBXBuildRule;
+			compilerSpec = com.apple.compilers.proxy.script;
+			filePatterns = "*.inc";
+			fileType = pattern.proxy;
+			isEditable = 1;
+			outputFiles = (
+			);
+			script = "";
+		};
+		DDC688F309F57599004E4BFF /* PBXBuildRule */ = {
+			isa = PBXBuildRule;
+			compilerSpec = com.apple.compilers.proxy.script;
+			fileType = sourcecode.pascal;
+			isEditable = 1;
+			outputFiles = (
+				"$(TARGET_TEMP_DIR)/$(INPUT_FILE_NAME).compiled",
+			);
+			script = "# set -vx\n\n# if FPC_MAIN_FILE is specified, only use that one\nif test \"x$FPC_MAIN_FILE\" = x ; then\n  echo \"$INPUT_FILE_SUFFIX\" \"$INPUT_FILE_PATH\" >> \"$PROJECT_TEMP_DIR\"/files_to_compile\nelif test \"x$INPUT_FILE_NAME\" = \"x$FPC_MAIN_FILE\" || test \"x$INPUT_FILE_PATH\" = \"x$FPC_MAIN_FILE\" ; then\n  echo \"$INPUT_FILE_SUFFIX\" \"$INPUT_FILE_PATH\" > \"$PROJECT_TEMP_DIR\"/files_to_compile\n  echo \"$INPUT_FILE_SUFFIX\" \"$INPUT_FILE_PATH\" > \"$PROJECT_TEMP_DIR\"/mainfile\nfi\n\necho \\\"-Fu$INPUT_FILE_DIR\\\" >> \"$PROJECT_TEMP_DIR\"/unitpaths\necho \\\"-Fi$INPUT_FILE_DIR\\\" >> \"$PROJECT_TEMP_DIR\"/unitpaths\n\n# if this file was not yet before compiled, it may be a new file -> delete\n# source cache (there might be a new mainfile now, unless FPC_MAIN_FILE is specified)\nif test ! -f \"$TARGET_TEMP_DIR\"/\"$INPUT_FILE_NAME\".compiled && test \"x$FPC_MAIN_FILE\" = x ; then\n  cd \"$PROJECT_TEMP_DIR\"\n  rm -f mainfile scriptrun > /dev/null 2>&1\nfi\n\ntouch \"$TARGET_TEMP_DIR\"/\"$INPUT_FILE_NAME\".compiled\n";
+		};
+		DDC6891509F57648004E4BFF /* PBXBuildRule */ = {
+			isa = PBXBuildRule;
+			compilerSpec = com.apple.compilers.proxy.script;
+			fileType = sourcecode.pascal;
+			isEditable = 1;
+			outputFiles = (
+				"$(PROJECT_DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).s",
+			);
+			script = "";
+		};
+/* End PBXBuildRule section */
+
+/* Begin PBXContainerItemProxy section */
+		DD37F25D0A60268D00975B2D /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = DDC6850F09F5717A004E4BFF /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = DD37F2420A60255800975B2D;
+			remoteInfo = fpcrtl;
+		};
+		DDC688ED09F57578004E4BFF /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = DDC6850F09F5717A004E4BFF /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = DDC688D409F57523004E4BFF;
+			remoteInfo = "Put unit sources in the 'Compile Sources' phase of this target";
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		2CDEC44F0CC5255600FFA244 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 6;
+			files = (
+				2CAC2BF40D380AE800CA518A /* libbass.dylib in CopyFiles */,
+				2CE907990D1BC91D00A1FDFF /* libavformat.dylib in CopyFiles */,
+				2CE9079A0D1BC91D00A1FDFF /* libavutil.dylib in CopyFiles */,
+				2CE907980D1BC90A00A1FDFF /* libavcodec.dylib in CopyFiles */,
+				2CF5533F0CDA531100627463 /* libfreeimage.dylib in CopyFiles */,
+				2CF553400CDA531100627463 /* libsqlite3.dylib in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2CDEC4940CC5262700FFA244 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 10;
+			files = (
+				2CDEC4960CC5264600FFA244 /* SDL.framework in CopyFiles */,
+				2CF553100CDA52D100627463 /* SDL_image.framework in CopyFiles */,
+				2CF5533B0CDA52E200627463 /* SDL_ttf.framework in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		2C0199800D99840900974970 /* config-macosx.inc */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = "config-macosx.inc"; path = "../config-macosx.inc"; sourceTree = SOURCE_ROOT; };
+		2C4B70220CF757A400B0F0BD /* Until5000.dpr */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = Until5000.dpr; path = ../../../Modis/5000Points/Until5000.dpr; sourceTree = SOURCE_ROOT; };
+		2C4D9C620CC9EC8C0031092D /* TextGL.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = TextGL.pas; path = ../Classes/TextGL.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C650CC9EC8C0031092D /* UCatCovers.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UCatCovers.pas; path = ../Classes/UCatCovers.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C660CC9EC8C0031092D /* UCommandLine.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UCommandLine.pas; path = ../Classes/UCommandLine.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C670CC9EC8C0031092D /* UCommon.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UCommon.pas; path = ../Classes/UCommon.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C680CC9EC8C0031092D /* UCore.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UCore.pas; path = ../Classes/UCore.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C690CC9EC8C0031092D /* UCoreModule.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UCoreModule.pas; path = ../Classes/UCoreModule.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C6A0CC9EC8C0031092D /* UCovers.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UCovers.pas; path = ../Classes/UCovers.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C6B0CC9EC8C0031092D /* UDataBase.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UDataBase.pas; path = ../Classes/UDataBase.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C6C0CC9EC8C0031092D /* UDLLManager.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UDLLManager.pas; path = ../Classes/UDLLManager.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C6D0CC9EC8C0031092D /* UDraw.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UDraw.pas; path = ../Classes/UDraw.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C6E0CC9EC8C0031092D /* UFiles.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UFiles.pas; path = ../Classes/UFiles.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C6F0CC9EC8C0031092D /* UGraphic.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UGraphic.pas; path = ../Classes/UGraphic.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C700CC9EC8C0031092D /* UGraphicClasses.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UGraphicClasses.pas; path = ../Classes/UGraphicClasses.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C710CC9EC8C0031092D /* UHooks.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UHooks.pas; path = ../Classes/UHooks.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C720CC9EC8C0031092D /* UIni.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UIni.pas; path = ../Classes/UIni.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C730CC9EC8C0031092D /* UJoystick.pas */ = {isa = PBXFileReference; explicitFileType = sourcecode.pascal; fileEncoding = 5; indentWidth = 2; name = UJoystick.pas; path = ../Classes/UJoystick.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C740CC9EC8C0031092D /* ULanguage.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = ULanguage.pas; path = ../Classes/ULanguage.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C760CC9EC8C0031092D /* ULCD.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = ULCD.pas; path = ../Classes/ULCD.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C770CC9EC8C0031092D /* ULight.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = ULight.pas; path = ../Classes/ULight.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C780CC9EC8C0031092D /* ULog.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = ULog.pas; path = ../Classes/ULog.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C790CC9EC8C0031092D /* ULyrics_bak.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = ULyrics_bak.pas; path = ../Classes/ULyrics_bak.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C7A0CC9EC8C0031092D /* ULyrics.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = ULyrics.pas; path = ../Classes/ULyrics.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C7B0CC9EC8C0031092D /* UMain.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMain.pas; path = ../Classes/UMain.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C7C0CC9EC8C0031092D /* UMedia_dummy.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMedia_dummy.pas; path = ../Classes/UMedia_dummy.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C7D0CC9EC8C0031092D /* UModules.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UModules.pas; path = ../Classes/UModules.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C7E0CC9EC8C0031092D /* UMusic.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMusic.pas; path = ../Classes/UMusic.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C7F0CC9EC8C0031092D /* UParty.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UParty.pas; path = ../Classes/UParty.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C800CC9EC8C0031092D /* UPlaylist.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UPlaylist.pas; path = ../Classes/UPlaylist.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C820CC9EC8C0031092D /* UPluginInterface.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UPluginInterface.pas; path = ../Classes/UPluginInterface.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C830CC9EC8C0031092D /* uPluginLoader.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = uPluginLoader.pas; path = ../Classes/uPluginLoader.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C840CC9EC8C0031092D /* URecord.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = URecord.pas; path = ../Classes/URecord.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C850CC9EC8C0031092D /* UServices.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UServices.pas; path = ../Classes/UServices.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C860CC9EC8C0031092D /* USingNotes.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = USingNotes.pas; path = ../Classes/USingNotes.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C870CC9EC8C0031092D /* USingScores.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = USingScores.pas; path = ../Classes/USingScores.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C880CC9EC8C0031092D /* USkins.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = USkins.pas; path = ../Classes/USkins.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C890CC9EC8C0031092D /* USongs.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = USongs.pas; path = ../Classes/USongs.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C8A0CC9EC8C0031092D /* UTextClasses.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UTextClasses.pas; path = ../Classes/UTextClasses.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UTexture.pas; path = ../Classes/UTexture.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C8C0CC9EC8C0031092D /* UThemes.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UThemes.pas; path = ../Classes/UThemes.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C8D0CC9EC8C0031092D /* UTime.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UTime.pas; path = ../Classes/UTime.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9C8E0CC9EC8C0031092D /* UVideo.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UVideo.pas; path = ../Classes/UVideo.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9D900CC9ED4F0031092D /* FreeBitmap.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = FreeBitmap.pas; path = ../lib/FreeImage/FreeBitmap.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9D910CC9ED4F0031092D /* FreeImage.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = FreeImage.pas; path = ../lib/FreeImage/FreeImage.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9D960CC9EDEB0031092D /* libfreeimage.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfreeimage.dylib; path = ../lib/FreeImage/libfreeimage.dylib; sourceTree = SOURCE_ROOT; };
+		2C4D9D980CC9EE0B0031092D /* SDL_image.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL_image.framework; path = /Library/Frameworks/SDL_image.framework; sourceTree = "<absolute>"; };
+		2C4D9D990CC9EE0B0031092D /* SDL_ttf.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL_ttf.framework; path = /Library/Frameworks/SDL_ttf.framework; sourceTree = "<absolute>"; };
+		2C4D9DCC0CC9EE6F0031092D /* UDisplay.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UDisplay.pas; path = ../Menu/UDisplay.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DCD0CC9EE6F0031092D /* UDrawTexture.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UDrawTexture.pas; path = ../Menu/UDrawTexture.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DCE0CC9EE6F0031092D /* UMenu.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMenu.pas; path = ../Menu/UMenu.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DCF0CC9EE6F0031092D /* UMenuButton.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMenuButton.pas; path = ../Menu/UMenuButton.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DD00CC9EE6F0031092D /* UMenuButtonCollection.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMenuButtonCollection.pas; path = ../Menu/UMenuButtonCollection.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DD10CC9EE6F0031092D /* UMenuInteract.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMenuInteract.pas; path = ../Menu/UMenuInteract.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DD20CC9EE6F0031092D /* UMenuSelect.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMenuSelect.pas; path = ../Menu/UMenuSelect.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DD30CC9EE6F0031092D /* UMenuSelectSlide.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMenuSelectSlide.pas; path = ../Menu/UMenuSelectSlide.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DD40CC9EE6F0031092D /* UMenuStatic.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMenuStatic.pas; path = ../Menu/UMenuStatic.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DD50CC9EE6F0031092D /* UMenuText.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UMenuText.pas; path = ../Menu/UMenuText.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4D9DEC0CC9EF0A0031092D /* sdl_image.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = sdl_image.pas; path = "/Library/Frameworks/JEDI-SDL.framework/SDL_image/sdl_image.pas"; sourceTree = "<absolute>"; tabWidth = 2; };
+		2C4D9DEF0CC9EF210031092D /* sdl_ttf.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = sdl_ttf.pas; path = "/Library/Frameworks/JEDI-SDL.framework/SDL_ttf/sdl_ttf.pas"; sourceTree = "<absolute>"; tabWidth = 2; };
+		2C4D9E040CC9EF840031092D /* OpenGL12.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = OpenGL12.pas; path = Wrapper/OpenGL12.pas; sourceTree = "<group>"; tabWidth = 2; };
+		2C4D9E090CC9EF840031092D /* Windows.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = Windows.pas; path = Wrapper/Windows.pas; sourceTree = "<group>"; tabWidth = 2; };
+		2C4D9E440CC9F0ED0031092D /* switches.inc */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = switches.inc; path = ../switches.inc; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2C4FA2A70CDBAD1E002CC3B0 /* ustar-icon_v01.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = "ustar-icon_v01.icns"; path = "../../Graphics/ustar-icon_v01.icns"; sourceTree = SOURCE_ROOT; };
+		2C5663EE0D35645700D4FF53 /* portaudio.pas */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = portaudio.pas; path = ../lib/portaudio/delphi/portaudio.pas; sourceTree = SOURCE_ROOT; };
+		2C56642B0D35683200D4FF53 /* SDLMain.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; name = SDLMain.m; path = "/Library/Frameworks/JEDI-SDL.framework/SDL/SDLMain.m"; sourceTree = "<absolute>"; };
+		2C56642F0D35688200D4FF53 /* SDL.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = SDL.h; path = /Library/Frameworks/SDL.framework/Versions/A/Headers/SDL.h; sourceTree = "<absolute>"; };
+		2C8937290CE393FB005D8A87 /* UPlatform.pas */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = UPlatform.pas; path = ../Classes/UPlatform.pas; sourceTree = SOURCE_ROOT; };
+		2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; lineEnding = 0; name = UPlatformMacOSX.pas; path = ../Classes/UPlatformMacOSX.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CAC2BDD0D3809F500CA518A /* UAudioInput_Bass.pas */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = UAudioInput_Bass.pas; path = ../Classes/UAudioInput_Bass.pas; sourceTree = SOURCE_ROOT; };
+		2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = UAudioPlayback_Bass.pas; path = ../Classes/UAudioPlayback_Bass.pas; sourceTree = SOURCE_ROOT; };
+		2CAC2BF00D380AC200CA518A /* libbass.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbass.dylib; path = ../lib/bass/libbass.dylib; sourceTree = SOURCE_ROOT; };
+		2CAC2BF70D380B1B00CA518A /* Bass.pas */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = Bass.pas; path = ../lib/bass/MacOSX/Bass.pas; sourceTree = SOURCE_ROOT; };
+		2CB9E87D0D43B78400214DFA /* USong.pas */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = USong.pas; path = ../Classes/USong.pas; sourceTree = SOURCE_ROOT; };
+		2CDC716B0CDB9CB70018F966 /* StrUtils.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = StrUtils.pas; path = ../../../Modis/SDK/StrUtils.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CDEA4F60CBD725B0096994C /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = "<absolute>"; };
+		2CE603D90D715F2100DB0D88 /* mathematics.pas */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.pascal; name = mathematics.pas; path = ../lib/ffmpeg/mathematics.pas; sourceTree = SOURCE_ROOT; };
+		2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.pascal; name = UAudioCore_Bass.pas; path = ../Classes/UAudioCore_Bass.pas; sourceTree = SOURCE_ROOT; };
+		2CE603E10D715F8600DB0D88 /* UConfig.pas */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.pascal; name = UConfig.pas; path = ../Classes/UConfig.pas; sourceTree = SOURCE_ROOT; };
+		2CE907900D1BC8A800A1FDFF /* libavcodec.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libavcodec.dylib; path = ../lib/ffmpeg/libavcodec.dylib; sourceTree = SOURCE_ROOT; };
+		2CE907910D1BC8A800A1FDFF /* libavformat.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libavformat.dylib; path = ../lib/ffmpeg/libavformat.dylib; sourceTree = SOURCE_ROOT; };
+		2CE907920D1BC8A800A1FDFF /* libavutil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libavutil.dylib; path = ../lib/ffmpeg/libavutil.dylib; sourceTree = SOURCE_ROOT; };
+		2CEA2ADE0CE385190097A5FF /* Graphics.pas */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = Graphics.pas; path = Wrapper/Graphics.pas; sourceTree = "<group>"; };
+		2CEA2ADF0CE385190097A5FF /* JPEG.pas */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = JPEG.pas; path = Wrapper/JPEG.pas; sourceTree = "<group>"; };
+		2CEA2AF00CE3868E0097A5FF /* PseudoThread.pas */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = PseudoThread.pas; path = Wrapper/PseudoThread.pas; sourceTree = "<group>"; };
+		2CF3EF210CDE13A0004F5956 /* Messages.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = Messages.pas; path = Wrapper/Messages.pas; sourceTree = "<group>"; tabWidth = 2; };
+		2CF3EF260CDE13BA004F5956 /* MacResources.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = MacResources.pas; path = Wrapper/MacResources.pas; sourceTree = "<group>"; tabWidth = 2; };
+		2CF54F430CDA1B2B00627463 /* UScreenCredits.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenCredits.pas; path = ../Screens/UScreenCredits.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F440CDA1B2B00627463 /* UScreenEdit.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenEdit.pas; path = ../Screens/UScreenEdit.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F450CDA1B2B00627463 /* UScreenEditConvert.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenEditConvert.pas; path = ../Screens/UScreenEditConvert.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F460CDA1B2B00627463 /* UScreenEditHeader.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenEditHeader.pas; path = ../Screens/UScreenEditHeader.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F470CDA1B2B00627463 /* UScreenEditSub.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenEditSub.pas; path = ../Screens/UScreenEditSub.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F480CDA1B2B00627463 /* UScreenLevel.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenLevel.pas; path = ../Screens/UScreenLevel.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F490CDA1B2B00627463 /* UScreenLoading.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenLoading.pas; path = ../Screens/UScreenLoading.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenMain.pas; path = ../Screens/UScreenMain.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F4B0CDA1B2B00627463 /* UScreenName.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenName.pas; path = ../Screens/UScreenName.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F4C0CDA1B2B00627463 /* UScreenOpen.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenOpen.pas; path = ../Screens/UScreenOpen.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F4D0CDA1B2B00627463 /* UScreenOptions.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenOptions.pas; path = ../Screens/UScreenOptions.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F4E0CDA1B2B00627463 /* UScreenOptionsAdvanced.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenOptionsAdvanced.pas; path = ../Screens/UScreenOptionsAdvanced.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F4F0CDA1B2B00627463 /* UScreenOptionsGame.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenOptionsGame.pas; path = ../Screens/UScreenOptionsGame.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F500CDA1B2B00627463 /* UScreenOptionsGraphics.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenOptionsGraphics.pas; path = ../Screens/UScreenOptionsGraphics.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F510CDA1B2B00627463 /* UScreenOptionsLyrics.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenOptionsLyrics.pas; path = ../Screens/UScreenOptionsLyrics.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F520CDA1B2B00627463 /* UScreenOptionsRecord.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenOptionsRecord.pas; path = ../Screens/UScreenOptionsRecord.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F530CDA1B2B00627463 /* UScreenOptionsSound.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenOptionsSound.pas; path = ../Screens/UScreenOptionsSound.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F540CDA1B2B00627463 /* UScreenOptionsThemes.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenOptionsThemes.pas; path = ../Screens/UScreenOptionsThemes.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F550CDA1B2B00627463 /* UScreenPartyNewRound.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenPartyNewRound.pas; path = ../Screens/UScreenPartyNewRound.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F560CDA1B2B00627463 /* UScreenPartyOptions.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenPartyOptions.pas; path = ../Screens/UScreenPartyOptions.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F570CDA1B2B00627463 /* UScreenPartyPlayer.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenPartyPlayer.pas; path = ../Screens/UScreenPartyPlayer.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F580CDA1B2B00627463 /* UScreenPartyScore.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenPartyScore.pas; path = ../Screens/UScreenPartyScore.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F590CDA1B2B00627463 /* UScreenPartyWin.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenPartyWin.pas; path = ../Screens/UScreenPartyWin.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F5A0CDA1B2B00627463 /* UScreenPopup.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenPopup.pas; path = ../Screens/UScreenPopup.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F5B0CDA1B2B00627463 /* UScreenScore.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenScore.pas; path = ../Screens/UScreenScore.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F5C0CDA1B2B00627463 /* UScreenSing.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenSing.pas; path = ../Screens/UScreenSing.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F5D0CDA1B2B00627463 /* UScreenSingModi.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenSingModi.pas; path = ../Screens/UScreenSingModi.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F5E0CDA1B2B00627463 /* UScreenSong.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenSong.pas; path = ../Screens/UScreenSong.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F5F0CDA1B2B00627463 /* UScreenSongJumpto.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenSongJumpto.pas; path = ../Screens/UScreenSongJumpto.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F600CDA1B2B00627463 /* UScreenSongMenu.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenSongMenu.pas; path = ../Screens/UScreenSongMenu.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F610CDA1B2B00627463 /* UScreenStatDetail.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenStatDetail.pas; path = ../Screens/UScreenStatDetail.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F620CDA1B2B00627463 /* UScreenStatMain.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenStatMain.pas; path = ../Screens/UScreenStatMain.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F630CDA1B2B00627463 /* UScreenTop5.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenTop5.pas; path = ../Screens/UScreenTop5.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF54F640CDA1B2B00627463 /* UScreenWelcome.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UScreenWelcome.pas; path = ../Screens/UScreenWelcome.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF5508B0CDA22B000627463 /* ModiSDK.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = ModiSDK.pas; path = ../../../Modis/SDK/ModiSDK.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF5510E0CDA293700627463 /* SQLite3.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = SQLite3.pas; path = ../lib/SQLite/SQLite3.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF5510F0CDA293700627463 /* SQLiteTable3.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = SQLiteTable3.pas; path = ../lib/SQLite/SQLiteTable3.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF5512C0CDA29C600627463 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = ../lib/SQLite/libsqlite3.dylib; sourceTree = SOURCE_ROOT; };
+		2CF551A70CDA356800627463 /* UltraStar.dpr */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = text; name = UltraStar.dpr; path = ../UltraStar.dpr; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF552110CDA3D1400627463 /* UPluginDefs.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UPluginDefs.pas; path = ../../../Modis/SDK/UPluginDefs.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF5529E0CDA42C900627463 /* avcodec.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = avcodec.pas; path = ../lib/ffmpeg/avcodec.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF5529F0CDA42C900627463 /* avformat.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = avformat.pas; path = ../lib/ffmpeg/avformat.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF552A00CDA42C900627463 /* avio.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = avio.pas; path = ../lib/ffmpeg/avio.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF552A10CDA42C900627463 /* avutil.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = avutil.pas; path = ../lib/ffmpeg/avutil.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF552A40CDA42C900627463 /* opt.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = opt.pas; path = ../lib/ffmpeg/opt.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF552A50CDA42C900627463 /* rational.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = rational.pas; path = ../lib/ffmpeg/rational.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		2CF553070CDA51B500627463 /* sdlutils.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = sdlutils.pas; path = "/Library/Frameworks/JEDI-SDL.framework/SDL/sdlutils.pas"; sourceTree = "<absolute>"; tabWidth = 2; };
+		2CF77DB60CF7556C00F3B101 /* libLib_UltraPong.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libLib_UltraPong.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		2CF8E6BD0CDFA8E80053A996 /* UPartyDefs.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UPartyDefs.pas; path = ../../../Modis/SDK/UPartyDefs.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; };
+		98B8BE330B1F947800162019 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+		98B8BE370B1F949C00162019 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+		98B8BE380B1F949C00162019 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+		98B8BE570B1F972400162019 /* SDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL.framework; path = /Library/Frameworks/SDL.framework; sourceTree = "<absolute>"; };
+		98B8BE5C0B1F974F00162019 /* sdl.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = sdl.pas; path = "/Library/Frameworks/JEDI-SDL.framework/SDL/sdl.pas"; sourceTree = "<absolute>"; tabWidth = 2; };
+		DD37F2430A60255800975B2D /* libfpcrtl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libfpcrtl.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		DDC6851B09F57195004E4BFF /* UltraStarDX.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; path = UltraStarDX.pas; sourceTree = "<group>"; tabWidth = 2; };
+		DDC6868B09F571C2004E4BFF /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
+		DDC688C809F574E9004E4BFF /* UltraStar Deluxe.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "UltraStar Deluxe.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		DDC688CA09F574E9004E4BFF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
+		DDC689B309F57C69004E4BFF /* InfoPlist.strings */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		DDC689B409F57C69004E4BFF /* SDLMain.nib */ = {isa = PBXFileReference; explicitFileType = wrapper.nib; name = SDLMain.nib; path = English.lproj/SDLMain.nib; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		2CF77DB40CF7556C00F3B101 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		DDC688C609F574E9004E4BFF /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DD37F2C70A6037EA00975B2D /* libfpcrtl.a in Frameworks */,
+				98B8BE340B1F947800162019 /* AppKit.framework in Frameworks */,
+				98B8BE390B1F949C00162019 /* Cocoa.framework in Frameworks */,
+				98B8BE3A0B1F949C00162019 /* Foundation.framework in Frameworks */,
+				98B8BE580B1F972400162019 /* SDL.framework in Frameworks */,
+				2CDEA4F70CBD725B0096994C /* OpenGL.framework in Frameworks */,
+				2C4D9D970CC9EDEB0031092D /* libfreeimage.dylib in Frameworks */,
+				2C4D9D9A0CC9EE0B0031092D /* SDL_image.framework in Frameworks */,
+				2C4D9D9B0CC9EE0B0031092D /* SDL_ttf.framework in Frameworks */,
+				2CF5512D0CDA29C600627463 /* libsqlite3.dylib in Frameworks */,
+				2CE907930D1BC8A800A1FDFF /* libavcodec.dylib in Frameworks */,
+				2CE907940D1BC8A800A1FDFF /* libavformat.dylib in Frameworks */,
+				2CE907950D1BC8A800A1FDFF /* libavutil.dylib in Frameworks */,
+				2CAC2BF10D380AC200CA518A /* libbass.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		2C4D9DEB0CC9EECC0031092D /* SDL */ = {
+			isa = PBXGroup;
+			children = (
+				2C56642F0D35688200D4FF53 /* SDL.h */,
+				2C56642B0D35683200D4FF53 /* SDLMain.m */,
+				2CF553070CDA51B500627463 /* sdlutils.pas */,
+				2C4D9DEF0CC9EF210031092D /* sdl_ttf.pas */,
+				2C4D9DEC0CC9EF0A0031092D /* sdl_image.pas */,
+				98B8BE5C0B1F974F00162019 /* sdl.pas */,
+			);
+			name = SDL;
+			sourceTree = "<group>";
+		};
+		2C4D9DF50CC9EF3A0031092D /* Wrapper */ = {
+			isa = PBXGroup;
+			children = (
+				2CEA2AF00CE3868E0097A5FF /* PseudoThread.pas */,
+				2CEA2ADE0CE385190097A5FF /* Graphics.pas */,
+				2CEA2ADF0CE385190097A5FF /* JPEG.pas */,
+				2CF3EF260CDE13BA004F5956 /* MacResources.pas */,
+				2CF3EF210CDE13A0004F5956 /* Messages.pas */,
+				2C4D9E040CC9EF840031092D /* OpenGL12.pas */,
+				2C4D9E090CC9EF840031092D /* Windows.pas */,
+			);
+			name = Wrapper;
+			sourceTree = "<group>";
+		};
+		2C5663EC0D35642E00D4FF53 /* portaudio */ = {
+			isa = PBXGroup;
+			children = (
+				2C5663EE0D35645700D4FF53 /* portaudio.pas */,
+			);
+			name = portaudio;
+			sourceTree = "<group>";
+		};
+		2CAC2BF60D380B0800CA518A /* BASS */ = {
+			isa = PBXGroup;
+			children = (
+				2CAC2BF70D380B1B00CA518A /* Bass.pas */,
+			);
+			name = BASS;
+			sourceTree = "<group>";
+		};
+		2CDD43820CBBE8D400F364DE /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				2CE603E10D715F8600DB0D88 /* UConfig.pas */,
+				2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */,
+				2CB9E87D0D43B78400214DFA /* USong.pas */,
+				2CAC2BDD0D3809F500CA518A /* UAudioInput_Bass.pas */,
+				2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */,
+				2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */,
+				2C8937290CE393FB005D8A87 /* UPlatform.pas */,
+				2C4D9C620CC9EC8C0031092D /* TextGL.pas */,
+				2C4D9C650CC9EC8C0031092D /* UCatCovers.pas */,
+				2C4D9C660CC9EC8C0031092D /* UCommandLine.pas */,
+				2C4D9C670CC9EC8C0031092D /* UCommon.pas */,
+				2C4D9C680CC9EC8C0031092D /* UCore.pas */,
+				2C4D9C690CC9EC8C0031092D /* UCoreModule.pas */,
+				2C4D9C6A0CC9EC8C0031092D /* UCovers.pas */,
+				2C4D9C6B0CC9EC8C0031092D /* UDataBase.pas */,
+				2C4D9C6C0CC9EC8C0031092D /* UDLLManager.pas */,
+				2C4D9C6D0CC9EC8C0031092D /* UDraw.pas */,
+				2C4D9C6E0CC9EC8C0031092D /* UFiles.pas */,
+				2C4D9C6F0CC9EC8C0031092D /* UGraphic.pas */,
+				2C4D9C700CC9EC8C0031092D /* UGraphicClasses.pas */,
+				2C4D9C710CC9EC8C0031092D /* UHooks.pas */,
+				2C4D9C720CC9EC8C0031092D /* UIni.pas */,
+				2C4D9C730CC9EC8C0031092D /* UJoystick.pas */,
+				2C4D9C740CC9EC8C0031092D /* ULanguage.pas */,
+				2C4D9C760CC9EC8C0031092D /* ULCD.pas */,
+				2C4D9C770CC9EC8C0031092D /* ULight.pas */,
+				2C4D9C780CC9EC8C0031092D /* ULog.pas */,
+				2C4D9C790CC9EC8C0031092D /* ULyrics_bak.pas */,
+				2C4D9C7A0CC9EC8C0031092D /* ULyrics.pas */,
+				2C4D9C7B0CC9EC8C0031092D /* UMain.pas */,
+				2C4D9C7C0CC9EC8C0031092D /* UMedia_dummy.pas */,
+				2C4D9C7D0CC9EC8C0031092D /* UModules.pas */,
+				2C4D9C7E0CC9EC8C0031092D /* UMusic.pas */,
+				2C4D9C7F0CC9EC8C0031092D /* UParty.pas */,
+				2C4D9C800CC9EC8C0031092D /* UPlaylist.pas */,
+				2C4D9C820CC9EC8C0031092D /* UPluginInterface.pas */,
+				2C4D9C830CC9EC8C0031092D /* uPluginLoader.pas */,
+				2C4D9C840CC9EC8C0031092D /* URecord.pas */,
+				2C4D9C850CC9EC8C0031092D /* UServices.pas */,
+				2C4D9C860CC9EC8C0031092D /* USingNotes.pas */,
+				2C4D9C870CC9EC8C0031092D /* USingScores.pas */,
+				2C4D9C880CC9EC8C0031092D /* USkins.pas */,
+				2C4D9C890CC9EC8C0031092D /* USongs.pas */,
+				2C4D9C8A0CC9EC8C0031092D /* UTextClasses.pas */,
+				2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */,
+				2C4D9C8C0CC9EC8C0031092D /* UThemes.pas */,
+				2C4D9C8D0CC9EC8C0031092D /* UTime.pas */,
+				2C4D9C8E0CC9EC8C0031092D /* UVideo.pas */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		2CDD438D0CBBE8F700F364DE /* Menu */ = {
+			isa = PBXGroup;
+			children = (
+				2C4D9DCC0CC9EE6F0031092D /* UDisplay.pas */,
+				2C4D9DCD0CC9EE6F0031092D /* UDrawTexture.pas */,
+				2C4D9DCE0CC9EE6F0031092D /* UMenu.pas */,
+				2C4D9DCF0CC9EE6F0031092D /* UMenuButton.pas */,
+				2C4D9DD00CC9EE6F0031092D /* UMenuButtonCollection.pas */,
+				2C4D9DD10CC9EE6F0031092D /* UMenuInteract.pas */,
+				2C4D9DD20CC9EE6F0031092D /* UMenuSelect.pas */,
+				2C4D9DD30CC9EE6F0031092D /* UMenuSelectSlide.pas */,
+				2C4D9DD40CC9EE6F0031092D /* UMenuStatic.pas */,
+				2C4D9DD50CC9EE6F0031092D /* UMenuText.pas */,
+			);
+			name = Menu;
+			sourceTree = "<group>";
+		};
+		2CDD8D0B0CC5539900E4169D /* UltraStarDX Resources */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			name = "UltraStarDX Resources";
+			sourceTree = "<group>";
+		};
+		2CE1F4080CC3EEA400CD02E5 /* FreeImage */ = {
+			isa = PBXGroup;
+			children = (
+				2C4D9D900CC9ED4F0031092D /* FreeBitmap.pas */,
+				2C4D9D910CC9ED4F0031092D /* FreeImage.pas */,
+			);
+			name = FreeImage;
+			sourceTree = "<group>";
+		};
+		2CF54F420CDA1B0C00627463 /* Screens */ = {
+			isa = PBXGroup;
+			children = (
+				2CF54F430CDA1B2B00627463 /* UScreenCredits.pas */,
+				2CF54F440CDA1B2B00627463 /* UScreenEdit.pas */,
+				2CF54F450CDA1B2B00627463 /* UScreenEditConvert.pas */,
+				2CF54F460CDA1B2B00627463 /* UScreenEditHeader.pas */,
+				2CF54F470CDA1B2B00627463 /* UScreenEditSub.pas */,
+				2CF54F480CDA1B2B00627463 /* UScreenLevel.pas */,
+				2CF54F490CDA1B2B00627463 /* UScreenLoading.pas */,
+				2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */,
+				2CF54F4B0CDA1B2B00627463 /* UScreenName.pas */,
+				2CF54F4C0CDA1B2B00627463 /* UScreenOpen.pas */,
+				2CF54F4D0CDA1B2B00627463 /* UScreenOptions.pas */,
+				2CF54F4E0CDA1B2B00627463 /* UScreenOptionsAdvanced.pas */,
+				2CF54F4F0CDA1B2B00627463 /* UScreenOptionsGame.pas */,
+				2CF54F500CDA1B2B00627463 /* UScreenOptionsGraphics.pas */,
+				2CF54F510CDA1B2B00627463 /* UScreenOptionsLyrics.pas */,
+				2CF54F520CDA1B2B00627463 /* UScreenOptionsRecord.pas */,
+				2CF54F530CDA1B2B00627463 /* UScreenOptionsSound.pas */,
+				2CF54F540CDA1B2B00627463 /* UScreenOptionsThemes.pas */,
+				2CF54F550CDA1B2B00627463 /* UScreenPartyNewRound.pas */,
+				2CF54F560CDA1B2B00627463 /* UScreenPartyOptions.pas */,
+				2CF54F570CDA1B2B00627463 /* UScreenPartyPlayer.pas */,
+				2CF54F580CDA1B2B00627463 /* UScreenPartyScore.pas */,
+				2CF54F590CDA1B2B00627463 /* UScreenPartyWin.pas */,
+				2CF54F5A0CDA1B2B00627463 /* UScreenPopup.pas */,
+				2CF54F5B0CDA1B2B00627463 /* UScreenScore.pas */,
+				2CF54F5C0CDA1B2B00627463 /* UScreenSing.pas */,
+				2CF54F5D0CDA1B2B00627463 /* UScreenSingModi.pas */,
+				2CF54F5E0CDA1B2B00627463 /* UScreenSong.pas */,
+				2CF54F5F0CDA1B2B00627463 /* UScreenSongJumpto.pas */,
+				2CF54F600CDA1B2B00627463 /* UScreenSongMenu.pas */,
+				2CF54F610CDA1B2B00627463 /* UScreenStatDetail.pas */,
+				2CF54F620CDA1B2B00627463 /* UScreenStatMain.pas */,
+				2CF54F630CDA1B2B00627463 /* UScreenTop5.pas */,
+				2CF54F640CDA1B2B00627463 /* UScreenWelcome.pas */,
+			);
+			name = Screens;
+			sourceTree = "<group>";
+		};
+		2CF5508A0CDA228800627463 /* SDK */ = {
+			isa = PBXGroup;
+			children = (
+				2CF8E6BD0CDFA8E80053A996 /* UPartyDefs.pas */,
+				2CDC716B0CDB9CB70018F966 /* StrUtils.pas */,
+				2CF552110CDA3D1400627463 /* UPluginDefs.pas */,
+				2CF5508B0CDA22B000627463 /* ModiSDK.pas */,
+			);
+			name = SDK;
+			sourceTree = "<group>";
+		};
+		2CF5510C0CDA28F000627463 /* Lib */ = {
+			isa = PBXGroup;
+			children = (
+				2CAC2BF60D380B0800CA518A /* BASS */,
+				2C5663EC0D35642E00D4FF53 /* portaudio */,
+				2CF5529C0CDA428000627463 /* ffmpeg */,
+				2CE1F4080CC3EEA400CD02E5 /* FreeImage */,
+				2C4D9DEB0CC9EECC0031092D /* SDL */,
+				2CF5510D0CDA291200627463 /* SQLite */,
+			);
+			name = Lib;
+			sourceTree = "<group>";
+		};
+		2CF5510D0CDA291200627463 /* SQLite */ = {
+			isa = PBXGroup;
+			children = (
+				2CF5510E0CDA293700627463 /* SQLite3.pas */,
+				2CF5510F0CDA293700627463 /* SQLiteTable3.pas */,
+			);
+			name = SQLite;
+			sourceTree = "<group>";
+		};
+		2CF5529C0CDA428000627463 /* ffmpeg */ = {
+			isa = PBXGroup;
+			children = (
+				2CE603D90D715F2100DB0D88 /* mathematics.pas */,
+				2CF5529E0CDA42C900627463 /* avcodec.pas */,
+				2CF5529F0CDA42C900627463 /* avformat.pas */,
+				2CF552A00CDA42C900627463 /* avio.pas */,
+				2CF552A10CDA42C900627463 /* avutil.pas */,
+				2CF552A40CDA42C900627463 /* opt.pas */,
+				2CF552A50CDA42C900627463 /* rational.pas */,
+			);
+			name = ffmpeg;
+			sourceTree = "<group>";
+		};
+		2CF77DBA0CF755CA00F3B101 /* Modis */ = {
+			isa = PBXGroup;
+			children = (
+				2C4B70220CF757A400B0F0BD /* Until5000.dpr */,
+			);
+			name = Modis;
+			sourceTree = "<group>";
+		};
+		DD7C45450A6E72DE003FA52B /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				2CF5510C0CDA28F000627463 /* Lib */,
+				2CDD43820CBBE8D400F364DE /* Classes */,
+				2CF54F420CDA1B0C00627463 /* Screens */,
+				2CDD438D0CBBE8F700F364DE /* Menu */,
+				2CF5508A0CDA228800627463 /* SDK */,
+				2C4D9DF50CC9EF3A0031092D /* Wrapper */,
+				2CF77DBA0CF755CA00F3B101 /* Modis */,
+				DDC6851B09F57195004E4BFF /* UltraStarDX.pas */,
+				2CF551A70CDA356800627463 /* UltraStar.dpr */,
+				2C4D9E440CC9F0ED0031092D /* switches.inc */,
+				2C0199800D99840900974970 /* config-macosx.inc */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		DDC6850D09F5717A004E4BFF = {
+			isa = PBXGroup;
+			children = (
+				2CAC2BF00D380AC200CA518A /* libbass.dylib */,
+				2CE907900D1BC8A800A1FDFF /* libavcodec.dylib */,
+				2CE907910D1BC8A800A1FDFF /* libavformat.dylib */,
+				2CE907920D1BC8A800A1FDFF /* libavutil.dylib */,
+				98B8BE570B1F972400162019 /* SDL.framework */,
+				2C4D9D980CC9EE0B0031092D /* SDL_image.framework */,
+				2C4D9D990CC9EE0B0031092D /* SDL_ttf.framework */,
+				2CDEA4F60CBD725B0096994C /* OpenGL.framework */,
+				98B8BE370B1F949C00162019 /* Cocoa.framework */,
+				98B8BE380B1F949C00162019 /* Foundation.framework */,
+				98B8BE330B1F947800162019 /* AppKit.framework */,
+				2C4D9D960CC9EDEB0031092D /* libfreeimage.dylib */,
+				2CF5512C0CDA29C600627463 /* libsqlite3.dylib */,
+				DD7C45450A6E72DE003FA52B /* Source */,
+				DDC6868A09F571C2004E4BFF /* Resources */,
+				2CDD8D0B0CC5539900E4169D /* UltraStarDX Resources */,
+				DDC6888C09F57243004E4BFF /* Products */,
+				DDC688CA09F574E9004E4BFF /* Info.plist */,
+			);
+			comments = "(note: \"Main target\" is used below to indicate the target with the same name as your project)\n\nSee the comments for the \"Main target\" under \"Targets\" for detailed information on how this project operates.\n\nIn short:\n\na) add your sources to the  target called 'Put all program sources also in this target'\nb) add your sources *EXCEPT FOR INCLUDE FILES* to the Main Target\nd) add all frameworks, resources, libraries etc to the Main target\n\nIf there are errors, the \"Errors and Warnings\" smart group will probably not work properly (e.g. errors may disappear after you double click on them). To work around this Xcode bug, go to the Build Transcript by double clicking on the icon of the \"Errors and Warnings\" smart group. There you can (double) click on the errors to go to the right position in the right source file.\n\nNote that the assembly view of Xcode does not work before Xcode 2.3. And in Xcode 2.3, you will not be able to step over PowerPC Pascal function calls (this should be fixed in the next Xcode release though).";
+			sourceTree = "<group>";
+		};
+		DDC6868A09F571C2004E4BFF /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				2C4FA2A70CDBAD1E002CC3B0 /* ustar-icon_v01.icns */,
+				DDC689B309F57C69004E4BFF /* InfoPlist.strings */,
+				DDC689B409F57C69004E4BFF /* SDLMain.nib */,
+				DDC6868B09F571C2004E4BFF /* Info.plist */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		DDC6888C09F57243004E4BFF /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				DDC688C809F574E9004E4BFF /* UltraStar Deluxe.app */,
+				DD37F2430A60255800975B2D /* libfpcrtl.a */,
+				2CF77DB60CF7556C00F3B101 /* libLib_UltraPong.dylib */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		2CF77DB20CF7556C00F3B101 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		2CF77DB50CF7556C00F3B101 /* Modi_Until5000 */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2CF77DB90CF7558B00F3B101 /* Build configuration list for PBXNativeTarget "Modi_Until5000" */;
+			buildPhases = (
+				2CF77DB20CF7556C00F3B101 /* Headers */,
+				2CF77DB30CF7556C00F3B101 /* Sources */,
+				2CF77DB40CF7556C00F3B101 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = Modi_Until5000;
+			productName = Lib_UltraPong;
+			productReference = 2CF77DB60CF7556C00F3B101 /* libLib_UltraPong.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		DD37F2420A60255800975B2D /* fpcrtl */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DD37F2560A60258300975B2D /* Build configuration list for PBXNativeTarget "fpcrtl" */;
+			buildPhases = (
+				DD37F2460A60257100975B2D /* ShellScript */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = fpcrtl;
+			productName = fpcrtl;
+			productReference = DD37F2430A60255800975B2D /* libfpcrtl.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		DDC688C709F574E9004E4BFF /* UltraStarDX */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DDC688CB09F574E9004E4BFF /* Build configuration list for PBXNativeTarget "UltraStarDX" */;
+			buildPhases = (
+				DDC688C409F574E9004E4BFF /* Resources */,
+				2CDEC44F0CC5255600FFA244 /* CopyFiles */,
+				2CDEC4940CC5262700FFA244 /* CopyFiles */,
+				DDC6891B09F576D9004E4BFF /* ShellScript */,
+				DDC688C509F574E9004E4BFF /* Sources */,
+				DDC688C609F574E9004E4BFF /* Frameworks */,
+				DDC6890909F5761D004E4BFF /* Rez */,
+				2CDD8E450CC554A000E4169D /* ShellScript */,
+			);
+			buildRules = (
+				DD7C45710A6E7E36003FA52B /* PBXBuildRule */,
+				DDC6891509F57648004E4BFF /* PBXBuildRule */,
+			);
+			comments = "This is the main target that does the actual compilation work. Because of several Xcode bugs and holes in its support for third party compilers, the structure is quite convoluted. There are three targets, but you only have to care about the first two:\n\na) This target (make sure this target is set as the \"Active Target\"!)\n\nThis target does the assembling and linking. It is dependent on the three other targets, so the scripts for those targets are run first. Next, it runs a script which compiles the main program and units (using the previously gathered information) and generate the assembler code. Then its \"Compile Sources\" phase will assemble the code, because if we directly generate the object files then Xcode will not perform any linking.\n\nb) The target called 'Put all program sources also in this target'\n\nAs the name says, you should add your sources to that target. The \"compilation rule\" for the Pascal files in that target will add those source files to a list of files to be compiled.\n\nc) The target called 'fpcrtl'\n\nThis target creates a static library of the FPC run time library. You should not have to change this target (you cannot add sources to it either)\n\n\nThe standard Xcode process is used to link in any necessary frameworks, libraries and resources. Therefore these frameworks, libraries and resources can be added to the project and this (the main) target like in any other Xcode project.\n";
+			dependencies = (
+				DDC688EE09F57578004E4BFF /* PBXTargetDependency */,
+				DD37F25E0A60268D00975B2D /* PBXTargetDependency */,
+			);
+			name = UltraStarDX;
+			productName = "JEDI-SDLCocoa";
+			productReference = DDC688C809F574E9004E4BFF /* UltraStar Deluxe.app */;
+			productType = "com.apple.product-type.application";
+		};
+		DDC688D409F57523004E4BFF /* Put all program sources also in this target */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DDC688DC09F57542004E4BFF /* Build configuration list for PBXNativeTarget "Put all program sources also in this target" */;
+			buildPhases = (
+				DD37F2350A60250900975B2D /* ShellScript */,
+				DDC688D209F57523004E4BFF /* Sources */,
+			);
+			buildRules = (
+				DD7C44CD0A6E5050003FA52B /* PBXBuildRule */,
+				DDC688F309F57599004E4BFF /* PBXBuildRule */,
+			);
+			comments = "See the comments for the target called the same as your project for details.";
+			dependencies = (
+			);
+			name = "Put all program sources also in this target";
+			productName = "Put unit sources in the 'Compile Sources' phase of this target";
+			productType = "com.apple.product-type.objfile";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		DDC6850F09F5717A004E4BFF /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = DDC6851009F5717A004E4BFF /* Build configuration list for PBXProject "UltraStarDX" */;
+			compatibilityVersion = "Xcode 2.4";
+			hasScannedForEncodings = 0;
+			mainGroup = DDC6850D09F5717A004E4BFF;
+			productRefGroup = DDC6888C09F57243004E4BFF /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				DDC688C709F574E9004E4BFF /* UltraStarDX */,
+				DDC688D409F57523004E4BFF /* Put all program sources also in this target */,
+				DD37F2420A60255800975B2D /* fpcrtl */,
+				2CF77DB50CF7556C00F3B101 /* Modi_Until5000 */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		DDC688C409F574E9004E4BFF /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DDC689B509F57C69004E4BFF /* InfoPlist.strings in Resources */,
+				DDC689B609F57C69004E4BFF /* SDLMain.nib in Resources */,
+				2C4FA2A80CDBAD1E002CC3B0 /* ustar-icon_v01.icns in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXRezBuildPhase section */
+		DDC6890909F5761D004E4BFF /* Rez */ = {
+			isa = PBXRezBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		2CDD8E450CC554A000E4169D /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\nUS_RESOURCES_SOURCE_DIR=UltraStarResources\nUS_RESOURCES_DEST_DIR=\"$CONFIGURATION_BUILD_DIR\"/\"$PRODUCT_NAME\".app/Contents\n\n#cp -Rf $US_RESOURCES_SOURCE_DIR $US_RESOURCES_DEST_DIR";
+		};
+		DD37F2350A60250900975B2D /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+				"$(PROJECT_TEMP_DIR)/cleanscriptrun",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "# hack to workaround Xcode bug that $PROJECT_TEMP_DIR isn't cleaned when you clean,\n# and that scripts aren't run when you clean a project\n\nmkdir -p \"$PROJECT_TEMP_DIR\"\n\n# when the \"scripts not run when cleaning\" bug is fixed, this doesn't have be run\n# when cleaning\n\nif [ x\"$ACTION\" = \"xbuild\" ]; then\n  # remove unit path and source file cache\n  cd \"$PROJECT_TEMP_DIR\"\n  rm -f mainfile scriptrun unitpaths files_to_compile  > /dev/null 2>&1\nfi\n\n# simple so that the script isn't run every time you compile\ntouch \"$PROJECT_TEMP_DIR\"/cleanscriptrun";
+		};
+		DD37F2460A60257100975B2D /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+				"$(TARGET_BUILD_DIR)/libfpcrtl.a",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "# if you activate this to see what the script does, Xcode will take a *VERY LONG* time to process the output of the \"ar\" command line\n# set -vx\n\n\n# put the entire RTL in one static library so we can link it easily (without automatically linking all object files)\n\nif [ x\"$ACTION\" = \"xbuild\" ]; then\n  \n  rm -f \"$PROJECT_TEMP_DIR\"/rtllibs\n  for arch in $ARCHS\n  do\n    # get the correct compiler name\n    case $arch in\n      i386)\n        FPC_ARCH=386\n        RTL_ARCH=i386\n     ;;\n      ppc)\n        FPC_ARCH=ppc\n        RTL_ARCH=powerpc\n     ;;\n      * )\n       echo warning: Unsupported target architecture ${arch}, skipping...\n       continue\n     ;;\n    esac\n\n    FPC_VERSION=`/usr/local/bin/ppc${FPC_ARCH} -iV`\n    if [ $? != 0 ]; then\n      echo \"error: Cannot find the FPC binary for $RTL_ARCH (/usr/local/bin/ppc${FPC_ARCH}). Check if you have installed FPC for this architecture.\"\n      exit 1\n    fi\n    MY_OUTPUT_FILE=\"$PROJECT_TEMP_DIR\"/libfpcrtl-${FPC_ARCH}.a\n    ar -ru \"$MY_OUTPUT_FILE\" `ls \"$FPC_RTL_UNITS_BASE\"/\"$FPC_VERSION\"/units/${RTL_ARCH}-darwin/*/*.o | grep -v 'darwin/fv/'`\n    if [ $? != 0 ]; then\n      echo \"error: Problem creating static library for FPC Run Time Library. Check the FPC_RTL_UNITS_BASE setting in the global project configuration.\"\n      exit 1\n    fi\n    echo -n  \" \"\\\"\"$MY_OUTPUT_FILE\"\\\" >> \"$PROJECT_TEMP_DIR\"/rtllibs\n  done\n  /bin/sh -c \"lipo -create `cat \\\"$PROJECT_TEMP_DIR\\\"/rtllibs` -output \\\"$TARGET_BUILD_DIR\\\"/libfpcrtl.a\"\n  ranlib \"$TARGET_BUILD_DIR\"/libfpcrtl.a > /dev/null 2>&1\n  # delete working files\n  rm -f `cat \"$PROJECT_TEMP_DIR\"/rtllibs`\n  rm -f \"$PROJECT_TEMP_DIR\"/rtllibs\nfi\n";
+		};
+		DDC6891B09F576D9004E4BFF /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(PROJECT_TEMP_DIR)/files_to_compile",
+			);
+			outputPaths = (
+				"$(PROJECT_TEMP_DIR)/scriptrun",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "# set -vx\n\nif [ x\"$ACTION\" = \"xclean\" ]; then\n  exit 0\nfi\n\nfunction make_conditional() {\n  for arch in $ARCHS\n  do\n    for file in \"$PROJECT_DERIVED_FILE_DIR\"/\"$arch\"/*.s\n    do\n      DEST_FILE=\"$PROJECT_DERIVED_FILE_DIR\"/`basename \"$file\"`\n      echo \"#ifdef __${arch}__\" >> /\"$DEST_FILE\"\n      cat \"$file\" >> \"$DEST_FILE\"\n      echo \"#endif\" >> \"$DEST_FILE\"\n    done\n  done\n}\n\n\nUNIT_PATHS_FILE=\"$PROJECT_TEMP_DIR\"/unitpaths\n\n# remove duplicate unit search paths\nif test -f \"$UNIT_PATHS_FILE\"; then\n  sort -u < \"$UNIT_PATHS_FILE\" > \"$UNIT_PATHS_FILE\".tmp\n  mv \"$UNIT_PATHS_FILE\".tmp \"$UNIT_PATHS_FILE\"\nelse\n  touch \"$UNIT_PATHS_FILE\"\nfi\n\n# Make sure there are some files to compile\nif test !  -f \"$PROJECT_TEMP_DIR\"/files_to_compile; then\n  echo error: Add your main program and its units to the \\\"Put all program sources also in this target\\\" target\n  exit 1\nfi\n\n\n# support for previous Xcode naming scheme\nif [ \"$BUILD_STYLE\" = Development ]\nthen\n  BUILD_STYLE=Debug\nfi\n\nif [ \"$BUILD_STYLE\" = Deployment ]\nthen\n  BUILD_STYLE=Release\nfi\n\n# keep track of whether we compiled the main program so that once we did, we can stop\nMAIN_PROGRAM_COMPILED=0\n\n# don't skip the first file, since it may be the main program.\nFIRST_FILE=1\n\nFILES_TO_SKIP=\n\nrm \"$PROJECT_DERIVED_FILE_DIR\"/*.s >/dev/null 2>&1\n\n\nwhile read INPUT_FILE_SUFFIX INPUT_FILE_PATH\ndo\n  # skip include files (crude, may miss some)\n  if ! egrep -qi 'end\\.' \"$INPUT_FILE_PATH\" >/dev/null 2>&1; then\n    FIRST_FILE=0\n    echo warning: Skipping compilation of \\\"$INPUT_FILE_PATH\\\", seems to be an include file or not a Pascal file\n    FILES_TO_SKIP=`echo -e \"$INPUT_FILE_PATH\"'\\n'\"$FILES_TO_SKIP\"`\n    continue\n  fi\n\n  for variant in $BUILD_VARIANTS\n  do\n    for arch in $ARCHS\n    do\n      # get the name of the objects file dir\n####\n      #FULL_OBJECT_FILES_DIR=\"$OBJECT_FILE_DIR\"-\"$variant\"/\"$arch\"\n      FULL_OBJECT_FILES_DIR=\"$PROJECT_DERIVED_FILE_DIR\"/\"$arch\"\n####\n\n      # create the necessary directories (not done by Xcode because we only specify a fake output file)\n      mkdir -p \"$PROJECT_TEMP_DIR\" \"$FULL_OBJECT_FILES_DIR\"\n  \n      # if the file was already compiled (because an earlier compiled unit depended on it), skip it\n      if test \"$FULL_OBJECT_FILES_DIR\"/`basename \"$INPUT_FILE_PATH\" $INPUT_FILE_SUFFIX`.o -nt \"$INPUT_FILE_PATH\" -a $FIRST_FILE -ne 1 ; then\n        continue 3\n      fi\n      \n      # get the correct compiler name\n      if [ \"$arch\" = \"i386\" ]\n      then\n        FPCARCH=386\n        RTLARCH=i386\n      else\n        FPCARCH=ppc\n        RTLARCH=powerpc\n      fi\n\n      # check if the compiler exists\n      if ! test -f /usr/local/bin/ppc${FPCARCH}\n      then\n        echo \"error: FPC for $arch is not installed on this machine. You can probably solve this problem by setting the architectures to build for to your native target only and rebuilding.\"\n        exit 2\n      fi\n  \n      # go into the object files dir so we can use short paths\n      cd \"$FULL_OBJECT_FILES_DIR\"\n  \n      # actually compile (but do not assemble nor link)\n      echo -n /usr/local/bin/ppc${FPCARCH} \\\"$INPUT_FILE_PATH\\\" $FPC_SPECIFIC_OPTIONS $FPC_COMMON_OPTIONS -Tdarwin -a -s -FE. -vbr $FPC_OVERRIDE_OPTIONS > docompile.sh\n\n      # add unit paths\n      while read unitsearchpath\n      do\n        echo -n \" \" $unitsearchpath >> docompile.sh\n      done < \"$UNIT_PATHS_FILE\"\n      \n      echo ' > \"$PROJECT_TEMP_DIR\"/compiler_output 2>&1' >> docompile.sh\n      echo 'compres=$?' >> docompile.sh\n      echo 'sed -e \"s/\\([^:]*\\):\\([^:]*\\):\\([^:]*\\):\\([^:]*\\):\\(.*\\)/\\1:\\2:\\3:column \\4 -\\5/\" < \"$PROJECT_TEMP_DIR\"/compiler_output' >> docompile.sh\n      echo 'exit $compres' >> docompile.sh\n      /bin/sh ./docompile.sh\n  \n      # Compilation successful?\n      if [ $? == 0 ]; then\n  \n        # if it was a unit, continue with the next file (no need to compile all its variants and archs, that\n        # will be done when compiling the main program)\n        if test ! -f ./link.res; then\n          continue 3\n        fi\n        \n        echo Main file found!\n\n        # this is the main program -> next time only compile this file\n        # (if units are modified, they will be added after this file, but that doesn't matter\n        echo \"$INPUT_FILE_SUFFIX\" \"$INPUT_FILE_PATH\" > \"$PROJECT_TEMP_DIR\"/files_to_compile\n        \n        # record that the main program was compiled, so we don't have to compile any more units\n        MAIN_PROGRAM_COMPILED=1\n        \n        # delete leftovers\n        rm -f ppas.sh link.res\n  \n        # log the name of the input file so it can be touched if necessary for recompilation\n        echo -n \"$INPUT_FILE_PATH\" > \"$PROJECT_TEMP_DIR\"/mainfile\n  \n      else\n        exit 2\n      fi\n    done\n  done\n\n  # if the main program was compiled, we can stop\n  if test $MAIN_PROGRAM_COMPILED -ne 0; then\n    make_conditional\n    touch \"$PROJECT_TEMP_DIR\"/scriptrun\n    exit 0\n  fi\n  FIRST_FILE=0\n\ndone < \"$PROJECT_TEMP_DIR\"/files_to_compile\n\necho \"warning: It seems your project only contains units and no main program\"\ngrep  -Fv \"$FILES_TO_SKIP\" < \"$PROJECT_TEMP_DIR\"/files_to_compile > \"$PROJECT_TEMP_DIR\"/files_to_compile.tmp\nsort -u < \"$PROJECT_TEMP_DIR\"/files_to_compile.tmp > \"$PROJECT_TEMP_DIR\"/files_to_compile\n";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		2CF77DB30CF7556C00F3B101 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2C4B70240CF7584500B0F0BD /* ModiSDK.pas in Sources */,
+				2C4B70230CF7581000B0F0BD /* Until5000.dpr in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		DDC688C509F574E9004E4BFF /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2CDD4BE20CB947BE00549FAC /* UltraStarDX.pas in Sources */,
+				2CDD4BE00CB947B100549FAC /* sdl.pas in Sources */,
+				2C4D9C8F0CC9EC8C0031092D /* TextGL.pas in Sources */,
+				2C4D9C920CC9EC8C0031092D /* UCatCovers.pas in Sources */,
+				2C4D9C930CC9EC8C0031092D /* UCommandLine.pas in Sources */,
+				2C4D9C940CC9EC8C0031092D /* UCommon.pas in Sources */,
+				2C4D9C950CC9EC8C0031092D /* UCore.pas in Sources */,
+				2C4D9C960CC9EC8C0031092D /* UCoreModule.pas in Sources */,
+				2C4D9C970CC9EC8C0031092D /* UCovers.pas in Sources */,
+				2C4D9C980CC9EC8C0031092D /* UDataBase.pas in Sources */,
+				2C4D9C990CC9EC8C0031092D /* UDLLManager.pas in Sources */,
+				2C4D9C9A0CC9EC8C0031092D /* UDraw.pas in Sources */,
+				2C4D9C9B0CC9EC8C0031092D /* UFiles.pas in Sources */,
+				2C4D9C9C0CC9EC8C0031092D /* UGraphic.pas in Sources */,
+				2C4D9C9D0CC9EC8C0031092D /* UGraphicClasses.pas in Sources */,
+				2C4D9C9E0CC9EC8C0031092D /* UHooks.pas in Sources */,
+				2C4D9C9F0CC9EC8C0031092D /* UIni.pas in Sources */,
+				2C4D9CA00CC9EC8C0031092D /* UJoystick.pas in Sources */,
+				2C4D9CA10CC9EC8C0031092D /* ULanguage.pas in Sources */,
+				2C4D9CA30CC9EC8C0031092D /* ULCD.pas in Sources */,
+				2C4D9CA40CC9EC8C0031092D /* ULight.pas in Sources */,
+				2C4D9CA50CC9EC8C0031092D /* ULog.pas in Sources */,
+				2C4D9CA60CC9EC8C0031092D /* ULyrics_bak.pas in Sources */,
+				2C4D9CA70CC9EC8C0031092D /* ULyrics.pas in Sources */,
+				2C4D9CA80CC9EC8C0031092D /* UMain.pas in Sources */,
+				2C4D9CA90CC9EC8C0031092D /* UMedia_dummy.pas in Sources */,
+				2C4D9CAA0CC9EC8C0031092D /* UModules.pas in Sources */,
+				2C4D9CAB0CC9EC8C0031092D /* UMusic.pas in Sources */,
+				2C4D9CAC0CC9EC8C0031092D /* UParty.pas in Sources */,
+				2C4D9CAD0CC9EC8C0031092D /* UPlaylist.pas in Sources */,
+				2C4D9CAF0CC9EC8C0031092D /* UPluginInterface.pas in Sources */,
+				2C4D9CB00CC9EC8C0031092D /* uPluginLoader.pas in Sources */,
+				2C4D9CB10CC9EC8C0031092D /* URecord.pas in Sources */,
+				2C4D9CB20CC9EC8C0031092D /* UServices.pas in Sources */,
+				2C4D9CB30CC9EC8C0031092D /* USingNotes.pas in Sources */,
+				2C4D9CB40CC9EC8C0031092D /* USingScores.pas in Sources */,
+				2C4D9CB50CC9EC8C0031092D /* USkins.pas in Sources */,
+				2C4D9CB60CC9EC8C0031092D /* USongs.pas in Sources */,
+				2C4D9CB70CC9EC8C0031092D /* UTextClasses.pas in Sources */,
+				2C4D9CB80CC9EC8C0031092D /* UTexture.pas in Sources */,
+				2C4D9CB90CC9EC8C0031092D /* UThemes.pas in Sources */,
+				2C4D9CBA0CC9EC8C0031092D /* UTime.pas in Sources */,
+				2C4D9CBB0CC9EC8C0031092D /* UVideo.pas in Sources */,
+				2C4D9D920CC9ED4F0031092D /* FreeBitmap.pas in Sources */,
+				2C4D9D930CC9ED4F0031092D /* FreeImage.pas in Sources */,
+				2C4D9DD60CC9EE6F0031092D /* UDisplay.pas in Sources */,
+				2C4D9DD70CC9EE6F0031092D /* UDrawTexture.pas in Sources */,
+				2C4D9DD80CC9EE6F0031092D /* UMenu.pas in Sources */,
+				2C4D9DD90CC9EE6F0031092D /* UMenuButton.pas in Sources */,
+				2C4D9DDA0CC9EE6F0031092D /* UMenuButtonCollection.pas in Sources */,
+				2C4D9DDB0CC9EE6F0031092D /* UMenuInteract.pas in Sources */,
+				2C4D9DDC0CC9EE6F0031092D /* UMenuSelect.pas in Sources */,
+				2C4D9DDD0CC9EE6F0031092D /* UMenuSelectSlide.pas in Sources */,
+				2C4D9DDE0CC9EE6F0031092D /* UMenuStatic.pas in Sources */,
+				2C4D9DDF0CC9EE6F0031092D /* UMenuText.pas in Sources */,
+				2C4D9DED0CC9EF0A0031092D /* sdl_image.pas in Sources */,
+				2C4D9DF10CC9EF210031092D /* sdl_ttf.pas in Sources */,
+				2C4D9E100CC9EF840031092D /* OpenGL12.pas in Sources */,
+				2C4D9E150CC9EF840031092D /* Windows.pas in Sources */,
+				2C4D9E450CC9F0ED0031092D /* switches.inc in Sources */,
+				2CF54F650CDA1B2B00627463 /* UScreenCredits.pas in Sources */,
+				2CF54F660CDA1B2B00627463 /* UScreenEdit.pas in Sources */,
+				2CF54F670CDA1B2B00627463 /* UScreenEditConvert.pas in Sources */,
+				2CF54F680CDA1B2B00627463 /* UScreenEditHeader.pas in Sources */,
+				2CF54F690CDA1B2B00627463 /* UScreenEditSub.pas in Sources */,
+				2CF54F6A0CDA1B2B00627463 /* UScreenLevel.pas in Sources */,
+				2CF54F6B0CDA1B2B00627463 /* UScreenLoading.pas in Sources */,
+				2CF54F6C0CDA1B2B00627463 /* UScreenMain.pas in Sources */,
+				2CF54F6D0CDA1B2B00627463 /* UScreenName.pas in Sources */,
+				2CF54F6E0CDA1B2B00627463 /* UScreenOpen.pas in Sources */,
+				2CF54F6F0CDA1B2B00627463 /* UScreenOptions.pas in Sources */,
+				2CF54F700CDA1B2B00627463 /* UScreenOptionsAdvanced.pas in Sources */,
+				2CF54F710CDA1B2B00627463 /* UScreenOptionsGame.pas in Sources */,
+				2CF54F720CDA1B2B00627463 /* UScreenOptionsGraphics.pas in Sources */,
+				2CF54F730CDA1B2B00627463 /* UScreenOptionsLyrics.pas in Sources */,
+				2CF54F740CDA1B2B00627463 /* UScreenOptionsRecord.pas in Sources */,
+				2CF54F750CDA1B2B00627463 /* UScreenOptionsSound.pas in Sources */,
+				2CF54F760CDA1B2B00627463 /* UScreenOptionsThemes.pas in Sources */,
+				2CF54F770CDA1B2B00627463 /* UScreenPartyNewRound.pas in Sources */,
+				2CF54F780CDA1B2B00627463 /* UScreenPartyOptions.pas in Sources */,
+				2CF54F790CDA1B2B00627463 /* UScreenPartyPlayer.pas in Sources */,
+				2CF54F7A0CDA1B2B00627463 /* UScreenPartyScore.pas in Sources */,
+				2CF54F7B0CDA1B2B00627463 /* UScreenPartyWin.pas in Sources */,
+				2CF54F7C0CDA1B2B00627463 /* UScreenPopup.pas in Sources */,
+				2CF54F7D0CDA1B2B00627463 /* UScreenScore.pas in Sources */,
+				2CF54F7E0CDA1B2B00627463 /* UScreenSing.pas in Sources */,
+				2CF54F7F0CDA1B2B00627463 /* UScreenSingModi.pas in Sources */,
+				2CF54F800CDA1B2B00627463 /* UScreenSong.pas in Sources */,
+				2CF54F810CDA1B2B00627463 /* UScreenSongJumpto.pas in Sources */,
+				2CF54F820CDA1B2B00627463 /* UScreenSongMenu.pas in Sources */,
+				2CF54F830CDA1B2B00627463 /* UScreenStatDetail.pas in Sources */,
+				2CF54F840CDA1B2B00627463 /* UScreenStatMain.pas in Sources */,
+				2CF54F850CDA1B2B00627463 /* UScreenTop5.pas in Sources */,
+				2CF54F860CDA1B2B00627463 /* UScreenWelcome.pas in Sources */,
+				2CF5508C0CDA22B000627463 /* ModiSDK.pas in Sources */,
+				2CF551100CDA293700627463 /* SQLite3.pas in Sources */,
+				2CF551110CDA293700627463 /* SQLiteTable3.pas in Sources */,
+				2CF552140CDA3D1400627463 /* UPluginDefs.pas in Sources */,
+				2CF552B00CDA42C900627463 /* avcodec.pas in Sources */,
+				2CF552B10CDA42C900627463 /* avformat.pas in Sources */,
+				2CF552B20CDA42C900627463 /* avio.pas in Sources */,
+				2CF552B30CDA42C900627463 /* avutil.pas in Sources */,
+				2CF552B60CDA42C900627463 /* opt.pas in Sources */,
+				2CF552B70CDA42C900627463 /* rational.pas in Sources */,
+				2CF553080CDA51B500627463 /* sdlutils.pas in Sources */,
+				2CDC716C0CDB9CB70018F966 /* StrUtils.pas in Sources */,
+				2CF3EF220CDE13A0004F5956 /* Messages.pas in Sources */,
+				2CF3EF270CDE13BA004F5956 /* MacResources.pas in Sources */,
+				2CF8E6BE0CDFA8E80053A996 /* UPartyDefs.pas in Sources */,
+				2CEA2AE00CE385190097A5FF /* Graphics.pas in Sources */,
+				2CEA2AE10CE385190097A5FF /* JPEG.pas in Sources */,
+				2CEA2AF10CE3868E0097A5FF /* PseudoThread.pas in Sources */,
+				2C89372A0CE393FB005D8A87 /* UPlatform.pas in Sources */,
+				2C8937340CE395CE005D8A87 /* UPlatformMacOSX.pas in Sources */,
+				2C5663EF0D35645700D4FF53 /* portaudio.pas in Sources */,
+				2C56642C0D35683200D4FF53 /* SDLMain.m in Sources */,
+				2CAC2BE20D3809F500CA518A /* UAudioInput_Bass.pas in Sources */,
+				2CAC2BE40D3809F500CA518A /* UAudioPlayback_Bass.pas in Sources */,
+				2CAC2BF80D380B1B00CA518A /* Bass.pas in Sources */,
+				2CB9E87E0D43B78400214DFA /* USong.pas in Sources */,
+				2CE603DA0D715F2100DB0D88 /* mathematics.pas in Sources */,
+				2CE603DE0D715F6700DB0D88 /* UAudioCore_Bass.pas in Sources */,
+				2CE603E20D715F8600DB0D88 /* UConfig.pas in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		DDC688D209F57523004E4BFF /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2CDD4BDE0CB947A400549FAC /* sdl.pas in Sources */,
+				DD37F23D0A60252800975B2D /* UltraStarDX.pas in Sources */,
+				2C4D9CBC0CC9EC8C0031092D /* TextGL.pas in Sources */,
+				2C4D9CBF0CC9EC8C0031092D /* UCatCovers.pas in Sources */,
+				2C4D9CC00CC9EC8C0031092D /* UCommandLine.pas in Sources */,
+				2C4D9CC10CC9EC8C0031092D /* UCommon.pas in Sources */,
+				2C4D9CC20CC9EC8C0031092D /* UCore.pas in Sources */,
+				2C4D9CC30CC9EC8C0031092D /* UCoreModule.pas in Sources */,
+				2C4D9CC40CC9EC8C0031092D /* UCovers.pas in Sources */,
+				2C4D9CC50CC9EC8C0031092D /* UDataBase.pas in Sources */,
+				2C4D9CC60CC9EC8C0031092D /* UDLLManager.pas in Sources */,
+				2C4D9CC70CC9EC8C0031092D /* UDraw.pas in Sources */,
+				2C4D9CC80CC9EC8C0031092D /* UFiles.pas in Sources */,
+				2C4D9CC90CC9EC8C0031092D /* UGraphic.pas in Sources */,
+				2C4D9CCA0CC9EC8C0031092D /* UGraphicClasses.pas in Sources */,
+				2C4D9CCB0CC9EC8C0031092D /* UHooks.pas in Sources */,
+				2C4D9CCC0CC9EC8C0031092D /* UIni.pas in Sources */,
+				2C4D9CCD0CC9EC8C0031092D /* UJoystick.pas in Sources */,
+				2C4D9CCE0CC9EC8C0031092D /* ULanguage.pas in Sources */,
+				2C4D9CD00CC9EC8C0031092D /* ULCD.pas in Sources */,
+				2C4D9CD10CC9EC8C0031092D /* ULight.pas in Sources */,
+				2C4D9CD20CC9EC8C0031092D /* ULog.pas in Sources */,
+				2C4D9CD30CC9EC8C0031092D /* ULyrics_bak.pas in Sources */,
+				2C4D9CD40CC9EC8C0031092D /* ULyrics.pas in Sources */,
+				2C4D9CD50CC9EC8C0031092D /* UMain.pas in Sources */,
+				2C4D9CD60CC9EC8C0031092D /* UMedia_dummy.pas in Sources */,
+				2C4D9CD70CC9EC8C0031092D /* UModules.pas in Sources */,
+				2C4D9CD80CC9EC8C0031092D /* UMusic.pas in Sources */,
+				2C4D9CD90CC9EC8C0031092D /* UParty.pas in Sources */,
+				2C4D9CDA0CC9EC8C0031092D /* UPlaylist.pas in Sources */,
+				2C4D9CDC0CC9EC8C0031092D /* UPluginInterface.pas in Sources */,
+				2C4D9CDD0CC9EC8C0031092D /* uPluginLoader.pas in Sources */,
+				2C4D9CDE0CC9EC8C0031092D /* URecord.pas in Sources */,
+				2C4D9CDF0CC9EC8C0031092D /* UServices.pas in Sources */,
+				2C4D9CE00CC9EC8C0031092D /* USingNotes.pas in Sources */,
+				2C4D9CE10CC9EC8C0031092D /* USingScores.pas in Sources */,
+				2C4D9CE20CC9EC8C0031092D /* USkins.pas in Sources */,
+				2C4D9CE30CC9EC8C0031092D /* USongs.pas in Sources */,
+				2C4D9CE40CC9EC8C0031092D /* UTextClasses.pas in Sources */,
+				2C4D9CE50CC9EC8C0031092D /* UTexture.pas in Sources */,
+				2C4D9CE60CC9EC8C0031092D /* UThemes.pas in Sources */,
+				2C4D9CE70CC9EC8C0031092D /* UTime.pas in Sources */,
+				2C4D9CE80CC9EC8C0031092D /* UVideo.pas in Sources */,
+				2C4D9D940CC9ED4F0031092D /* FreeBitmap.pas in Sources */,
+				2C4D9D950CC9ED4F0031092D /* FreeImage.pas in Sources */,
+				2C4D9DE00CC9EE6F0031092D /* UDisplay.pas in Sources */,
+				2C4D9DE10CC9EE6F0031092D /* UDrawTexture.pas in Sources */,
+				2C4D9DE20CC9EE6F0031092D /* UMenu.pas in Sources */,
+				2C4D9DE30CC9EE6F0031092D /* UMenuButton.pas in Sources */,
+				2C4D9DE40CC9EE6F0031092D /* UMenuButtonCollection.pas in Sources */,
+				2C4D9DE50CC9EE6F0031092D /* UMenuInteract.pas in Sources */,
+				2C4D9DE60CC9EE6F0031092D /* UMenuSelect.pas in Sources */,
+				2C4D9DE70CC9EE6F0031092D /* UMenuSelectSlide.pas in Sources */,
+				2C4D9DE80CC9EE6F0031092D /* UMenuStatic.pas in Sources */,
+				2C4D9DE90CC9EE6F0031092D /* UMenuText.pas in Sources */,
+				2C4D9DEE0CC9EF0A0031092D /* sdl_image.pas in Sources */,
+				2C4D9DF30CC9EF210031092D /* sdl_ttf.pas in Sources */,
+				2C4D9E1C0CC9EF840031092D /* OpenGL12.pas in Sources */,
+				2C4D9E210CC9EF840031092D /* Windows.pas in Sources */,
+				2C4D9E460CC9F0ED0031092D /* switches.inc in Sources */,
+				2CF54F870CDA1B2B00627463 /* UScreenCredits.pas in Sources */,
+				2CF54F880CDA1B2B00627463 /* UScreenEdit.pas in Sources */,
+				2CF54F890CDA1B2B00627463 /* UScreenEditConvert.pas in Sources */,
+				2CF54F8A0CDA1B2B00627463 /* UScreenEditHeader.pas in Sources */,
+				2CF54F8B0CDA1B2B00627463 /* UScreenEditSub.pas in Sources */,
+				2CF54F8C0CDA1B2B00627463 /* UScreenLevel.pas in Sources */,
+				2CF54F8D0CDA1B2B00627463 /* UScreenLoading.pas in Sources */,
+				2CF54F8E0CDA1B2B00627463 /* UScreenMain.pas in Sources */,
+				2CF54F8F0CDA1B2B00627463 /* UScreenName.pas in Sources */,
+				2CF54F900CDA1B2B00627463 /* UScreenOpen.pas in Sources */,
+				2CF54F910CDA1B2B00627463 /* UScreenOptions.pas in Sources */,
+				2CF54F920CDA1B2B00627463 /* UScreenOptionsAdvanced.pas in Sources */,
+				2CF54F930CDA1B2B00627463 /* UScreenOptionsGame.pas in Sources */,
+				2CF54F940CDA1B2B00627463 /* UScreenOptionsGraphics.pas in Sources */,
+				2CF54F950CDA1B2B00627463 /* UScreenOptionsLyrics.pas in Sources */,
+				2CF54F960CDA1B2B00627463 /* UScreenOptionsRecord.pas in Sources */,
+				2CF54F970CDA1B2B00627463 /* UScreenOptionsSound.pas in Sources */,
+				2CF54F980CDA1B2B00627463 /* UScreenOptionsThemes.pas in Sources */,
+				2CF54F990CDA1B2B00627463 /* UScreenPartyNewRound.pas in Sources */,
+				2CF54F9A0CDA1B2B00627463 /* UScreenPartyOptions.pas in Sources */,
+				2CF54F9B0CDA1B2B00627463 /* UScreenPartyPlayer.pas in Sources */,
+				2CF54F9C0CDA1B2B00627463 /* UScreenPartyScore.pas in Sources */,
+				2CF54F9D0CDA1B2B00627463 /* UScreenPartyWin.pas in Sources */,
+				2CF54F9E0CDA1B2B00627463 /* UScreenPopup.pas in Sources */,
+				2CF54F9F0CDA1B2B00627463 /* UScreenScore.pas in Sources */,
+				2CF54FA00CDA1B2B00627463 /* UScreenSing.pas in Sources */,
+				2CF54FA10CDA1B2B00627463 /* UScreenSingModi.pas in Sources */,
+				2CF54FA20CDA1B2B00627463 /* UScreenSong.pas in Sources */,
+				2CF54FA30CDA1B2B00627463 /* UScreenSongJumpto.pas in Sources */,
+				2CF54FA40CDA1B2B00627463 /* UScreenSongMenu.pas in Sources */,
+				2CF54FA50CDA1B2B00627463 /* UScreenStatDetail.pas in Sources */,
+				2CF54FA60CDA1B2B00627463 /* UScreenStatMain.pas in Sources */,
+				2CF54FA70CDA1B2B00627463 /* UScreenTop5.pas in Sources */,
+				2CF54FA80CDA1B2B00627463 /* UScreenWelcome.pas in Sources */,
+				2CF5508D0CDA22B000627463 /* ModiSDK.pas in Sources */,
+				2CF551120CDA293700627463 /* SQLite3.pas in Sources */,
+				2CF551130CDA293700627463 /* SQLiteTable3.pas in Sources */,
+				2CF552170CDA3D1400627463 /* UPluginDefs.pas in Sources */,
+				2CF552A70CDA42C900627463 /* avcodec.pas in Sources */,
+				2CF552A80CDA42C900627463 /* avformat.pas in Sources */,
+				2CF552A90CDA42C900627463 /* avio.pas in Sources */,
+				2CF552AA0CDA42C900627463 /* avutil.pas in Sources */,
+				2CF552AD0CDA42C900627463 /* opt.pas in Sources */,
+				2CF552AE0CDA42C900627463 /* rational.pas in Sources */,
+				2CF553090CDA51B500627463 /* sdlutils.pas in Sources */,
+				2CDC716D0CDB9CB70018F966 /* StrUtils.pas in Sources */,
+				2CF3EF230CDE13A0004F5956 /* Messages.pas in Sources */,
+				2CF3EF280CDE13BA004F5956 /* MacResources.pas in Sources */,
+				2CF8E6BF0CDFA8E80053A996 /* UPartyDefs.pas in Sources */,
+				2CEA2AE20CE385190097A5FF /* Graphics.pas in Sources */,
+				2CEA2AE30CE385190097A5FF /* JPEG.pas in Sources */,
+				2CEA2AF20CE3868E0097A5FF /* PseudoThread.pas in Sources */,
+				2C89372B0CE393FB005D8A87 /* UPlatform.pas in Sources */,
+				2C8937370CE395CE005D8A87 /* UPlatformMacOSX.pas in Sources */,
+				2C5663F00D35645700D4FF53 /* portaudio.pas in Sources */,
+				2CAC2BE70D3809F500CA518A /* UAudioInput_Bass.pas in Sources */,
+				2CAC2BE90D3809F500CA518A /* UAudioPlayback_Bass.pas in Sources */,
+				2CAC2BF90D380B1B00CA518A /* Bass.pas in Sources */,
+				2CB9E87F0D43B78400214DFA /* USong.pas in Sources */,
+				2CE603DB0D715F2100DB0D88 /* mathematics.pas in Sources */,
+				2CE603DF0D715F6700DB0D88 /* UAudioCore_Bass.pas in Sources */,
+				2CE603E30D715F8600DB0D88 /* UConfig.pas in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		DD37F25E0A60268D00975B2D /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = DD37F2420A60255800975B2D /* fpcrtl */;
+			targetProxy = DD37F25D0A60268D00975B2D /* PBXContainerItemProxy */;
+		};
+		DDC688EE09F57578004E4BFF /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = DDC688D409F57523004E4BFF /* Put all program sources also in this target */;
+			targetProxy = DDC688ED09F57578004E4BFF /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		2CF77DB70CF7556D00F3B101 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				INSTALL_PATH = /usr/local/lib;
+				LD_DYLIB_INSTALL_NAME = "@executable_path/libUntil5000.dylib";
+				PREBINDING = NO;
+				PRODUCT_NAME = Until5000;
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		2CF77DB80CF7556D00F3B101 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				EXECUTABLE_PREFIX = lib;
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = /usr/local/lib;
+				PREBINDING = NO;
+				PRODUCT_NAME = Lib_UltraPong;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		DD37F2570A60258300975B2D /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				INSTALL_PATH = /usr/local/lib;
+				PREBINDING = NO;
+				PRODUCT_NAME = fpcrtl;
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		DD37F2580A60258300975B2D /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				INSTALL_PATH = /usr/local/lib;
+				PREBINDING = NO;
+				PRODUCT_NAME = fpcrtl;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		DDC6851109F5717A004E4BFF /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				FPC_COMMON_OPTIONS = "-Sd -XMSDL_main";
+				FPC_MAIN_FILE = "";
+				FPC_OVERRIDE_OPTIONS = "";
+				FPC_RTL_UNITS_BASE = /usr/local/lib/fpc/;
+				FPC_SPECIFIC_OPTIONS = "-Ci -Cr -Co -gl -O-";
+				FRAMEWORK_SEARCH_PATHS = "";
+				HEADER_SEARCH_PATHS = "";
+				LIBRARY_SEARCH_PATHS = "";
+				REZ_SEARCH_PATHS = "";
+				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+				USER_HEADER_SEARCH_PATHS = "";
+			};
+			name = Debug;
+		};
+		DDC6851209F5717A004E4BFF /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				FPC_COMMON_OPTIONS = "-Sd -XMSDL_main";
+				FPC_MAIN_FILE = "";
+				FPC_OVERRIDE_OPTIONS = "";
+				FPC_RTL_UNITS_BASE = /usr/local/lib/fpc/;
+				FPC_SPECIFIC_OPTIONS = "-Ci- -Cr- -Co- -O3 -Xs ";
+				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+			};
+			name = Release;
+		};
+		DDC688CC09F574E9004E4BFF /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Applications";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_3)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_4)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_5)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_6)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_3)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Debug\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../lib/SQLite\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/../lib/ffmpeg\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_5 = "\"$(SRCROOT)/../lib/bass\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_6 = "\"$(SRCROOT)/../lib/FreeImage\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../lib/ffmpeg\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../lib/bass\"";
+				LINK_WITH_STANDARD_LIBRARIES = YES;
+				OTHER_LDFLAGS = (
+					"-framework",
+					Carbon,
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = "UltraStar Deluxe";
+				WRAPPER_EXTENSION = app;
+				ZERO_LINK = NO;
+			};
+			name = Debug;
+		};
+		DDC688CD09F574E9004E4BFF /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks\"";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Applications";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_2)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_3)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_4)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_5)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_6)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_7)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_8)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_9)",
+					"$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Debug\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/Bass\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/FreeImage\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_4 = "\"$(SRCROOT)/FreeImage\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_5 = "\"$(SRCROOT)/../lib/bass\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_6 = "\"$(SRCROOT)/../lib/FreeImage\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_7 = "\"$(SRCROOT)/../lib/SQLite\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_8 = "\"$(SRCROOT)/../lib/ffmpeg\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_9 = "\"$(SRCROOT)/../lib/ffmpeg\"";
+				LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../lib/bass\"";
+				LINK_WITH_STANDARD_LIBRARIES = YES;
+				OTHER_LDFLAGS = (
+					"-framework",
+					Carbon,
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = "UltraStar Deluxe";
+				WRAPPER_EXTENSION = app;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		DDC688DD09F57542004E4BFF /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
+				INSTALL_PATH = /usr/local/lib;
+				OTHER_LDFLAGS = (
+					"-framework",
+					Carbon,
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = "Put unit sources in the 'Compile Sources' phase of this target";
+			};
+			name = Debug;
+		};
+		DDC688DE09F57542004E4BFF /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
+				INSTALL_PATH = /usr/local/lib;
+				OTHER_LDFLAGS = (
+					"-framework",
+					Carbon,
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = "Put unit sources in the 'Compile Sources' phase of this target";
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		2CF77DB90CF7558B00F3B101 /* Build configuration list for PBXNativeTarget "Modi_Until5000" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2CF77DB70CF7556D00F3B101 /* Debug */,
+				2CF77DB80CF7556D00F3B101 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Debug;
+		};
+		DD37F2560A60258300975B2D /* Build configuration list for PBXNativeTarget "fpcrtl" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				DD37F2570A60258300975B2D /* Debug */,
+				DD37F2580A60258300975B2D /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Debug;
+		};
+		DDC6851009F5717A004E4BFF /* Build configuration list for PBXProject "UltraStarDX" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				DDC6851109F5717A004E4BFF /* Debug */,
+				DDC6851209F5717A004E4BFF /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Debug;
+		};
+		DDC688CB09F574E9004E4BFF /* Build configuration list for PBXNativeTarget "UltraStarDX" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				DDC688CC09F574E9004E4BFF /* Debug */,
+				DDC688CD09F574E9004E4BFF /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Debug;
+		};
+		DDC688DC09F57542004E4BFF /* Build configuration list for PBXNativeTarget "Put all program sources also in this target" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				DDC688DD09F57542004E4BFF /* Debug */,
+				DDC688DE09F57542004E4BFF /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Debug;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = DDC6850F09F5717A004E4BFF /* Project object */;
+}
diff --git a/songmanagement/doc/Makefile b/songmanagement/doc/Makefile
new file mode 100644
index 00000000..bfb4596c
--- /dev/null
+++ b/songmanagement/doc/Makefile
@@ -0,0 +1,30 @@
+MKDIR  ?= mkdir -p
+RM     ?= rm -f
+RM_REC ?= $(RM) -r
+
+PASDOC ?= pasdoc$(EXEEXT)
+
+DOCDIR   ?= ./pasdoc
+SRCDIR   := ../src
+INCLUDE  := -I$(SRCDIR)
+DEFINES  := -DPASDOC
+SRCFILES := $(SRCDIR)/base/*.pas \
+            $(SRCDIR)/screens/*.pas \
+            $(SRCDIR)/menu/*.pas \
+			$(SRCDIR)/media/*.pas 
+
+.PHONY: all
+all: doc
+
+.PHONY: doc
+doc: clean
+	$(MKDIR) $(DOCDIR)
+# pasdoc does not return a meaningful exit code (e.g. an error code on success) so always return true
+	$(PASDOC) --staronly --ignore-leading=* $(INCLUDE) $(DEFINES) --output=$(DOCDIR) $(SRCFILES); true
+# check if doc was created
+	@test -f $(DOCDIR)/index.html
+
+.PHONY: clean
+clean:
+	$(RM) $(DOCDIR)/*.html $(DOCDIR)/*.css $(DOCDIR)/*.gif
+	-rmdir $(DOCDIR) 
\ No newline at end of file
diff --git a/songmanagement/game/.gitignore b/songmanagement/game/.gitignore
new file mode 100644
index 00000000..487210c1
--- /dev/null
+++ b/songmanagement/game/.gitignore
@@ -0,0 +1,8 @@
+playlists
+screenshots
+songs
+config.ini
+cover.db
+ultrastardx
+Ultrastar.db
+Error.log
diff --git a/songmanagement/game/LuaCommands.odt b/songmanagement/game/LuaCommands.odt
new file mode 100644
index 00000000..223df235
Binary files /dev/null and b/songmanagement/game/LuaCommands.odt differ
diff --git a/songmanagement/game/covers/Artist/Artist#.jpg b/songmanagement/game/covers/Artist/Artist#.jpg
new file mode 100644
index 00000000..53f117d1
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist#.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist0.jpg b/songmanagement/game/covers/Artist/Artist0.jpg
new file mode 100644
index 00000000..da8ff47d
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist0.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist1.jpg b/songmanagement/game/covers/Artist/Artist1.jpg
new file mode 100644
index 00000000..386506c7
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist1.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist2.jpg b/songmanagement/game/covers/Artist/Artist2.jpg
new file mode 100644
index 00000000..5de928ce
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist2.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist3.jpg b/songmanagement/game/covers/Artist/Artist3.jpg
new file mode 100644
index 00000000..abdbae53
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist3.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist4.jpg b/songmanagement/game/covers/Artist/Artist4.jpg
new file mode 100644
index 00000000..a4ac2c41
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist4.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist5.jpg b/songmanagement/game/covers/Artist/Artist5.jpg
new file mode 100644
index 00000000..af7de9a2
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist5.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist6.jpg b/songmanagement/game/covers/Artist/Artist6.jpg
new file mode 100644
index 00000000..08fed6ca
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist6.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist7.jpg b/songmanagement/game/covers/Artist/Artist7.jpg
new file mode 100644
index 00000000..2eee160f
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist7.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist8.jpg b/songmanagement/game/covers/Artist/Artist8.jpg
new file mode 100644
index 00000000..86e92067
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist8.jpg differ
diff --git a/songmanagement/game/covers/Artist/Artist9.jpg b/songmanagement/game/covers/Artist/Artist9.jpg
new file mode 100644
index 00000000..61757ff1
Binary files /dev/null and b/songmanagement/game/covers/Artist/Artist9.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistA.jpg b/songmanagement/game/covers/Artist/ArtistA.jpg
new file mode 100644
index 00000000..983a20ea
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistA.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistB.jpg b/songmanagement/game/covers/Artist/ArtistB.jpg
new file mode 100644
index 00000000..ed483f97
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistB.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistC.jpg b/songmanagement/game/covers/Artist/ArtistC.jpg
new file mode 100644
index 00000000..40193397
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistC.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistD.jpg b/songmanagement/game/covers/Artist/ArtistD.jpg
new file mode 100644
index 00000000..90dae418
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistD.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistE.jpg b/songmanagement/game/covers/Artist/ArtistE.jpg
new file mode 100644
index 00000000..fd36bc5b
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistE.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistF.jpg b/songmanagement/game/covers/Artist/ArtistF.jpg
new file mode 100644
index 00000000..63dfe254
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistF.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistG.jpg b/songmanagement/game/covers/Artist/ArtistG.jpg
new file mode 100644
index 00000000..1706b1c9
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistG.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistH.jpg b/songmanagement/game/covers/Artist/ArtistH.jpg
new file mode 100644
index 00000000..ac808f04
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistH.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistI.jpg b/songmanagement/game/covers/Artist/ArtistI.jpg
new file mode 100644
index 00000000..67740ad5
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistI.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistJ.jpg b/songmanagement/game/covers/Artist/ArtistJ.jpg
new file mode 100644
index 00000000..ef4aff91
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistJ.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistK.jpg b/songmanagement/game/covers/Artist/ArtistK.jpg
new file mode 100644
index 00000000..91ac29a9
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistK.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistL.jpg b/songmanagement/game/covers/Artist/ArtistL.jpg
new file mode 100644
index 00000000..d355565f
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistL.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistM.jpg b/songmanagement/game/covers/Artist/ArtistM.jpg
new file mode 100644
index 00000000..4501c21a
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistM.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistN.jpg b/songmanagement/game/covers/Artist/ArtistN.jpg
new file mode 100644
index 00000000..f0ed7adf
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistN.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistO.jpg b/songmanagement/game/covers/Artist/ArtistO.jpg
new file mode 100644
index 00000000..a10c1d8b
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistO.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistP.jpg b/songmanagement/game/covers/Artist/ArtistP.jpg
new file mode 100644
index 00000000..d44bc54c
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistP.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistQ.jpg b/songmanagement/game/covers/Artist/ArtistQ.jpg
new file mode 100644
index 00000000..89c4b24d
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistQ.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistR.jpg b/songmanagement/game/covers/Artist/ArtistR.jpg
new file mode 100644
index 00000000..bd10622a
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistR.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistS.jpg b/songmanagement/game/covers/Artist/ArtistS.jpg
new file mode 100644
index 00000000..8a747c3a
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistS.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistT.jpg b/songmanagement/game/covers/Artist/ArtistT.jpg
new file mode 100644
index 00000000..4945e852
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistT.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistU.jpg b/songmanagement/game/covers/Artist/ArtistU.jpg
new file mode 100644
index 00000000..b1ef4d8e
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistU.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistV.jpg b/songmanagement/game/covers/Artist/ArtistV.jpg
new file mode 100644
index 00000000..5941113e
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistV.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistW.jpg b/songmanagement/game/covers/Artist/ArtistW.jpg
new file mode 100644
index 00000000..40d7cd5f
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistW.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistX.jpg b/songmanagement/game/covers/Artist/ArtistX.jpg
new file mode 100644
index 00000000..5b126e5e
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistX.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistY.jpg b/songmanagement/game/covers/Artist/ArtistY.jpg
new file mode 100644
index 00000000..a0d62836
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistY.jpg differ
diff --git a/songmanagement/game/covers/Artist/ArtistZ.jpg b/songmanagement/game/covers/Artist/ArtistZ.jpg
new file mode 100644
index 00000000..9fc33095
Binary files /dev/null and b/songmanagement/game/covers/Artist/ArtistZ.jpg differ
diff --git "a/songmanagement/game/covers/Artist/Artist\303\204.jpg" "b/songmanagement/game/covers/Artist/Artist\303\204.jpg"
new file mode 100644
index 00000000..2f9ed469
Binary files /dev/null and "b/songmanagement/game/covers/Artist/Artist\303\204.jpg" differ
diff --git "a/songmanagement/game/covers/Artist/Artist\303\226.jpg" "b/songmanagement/game/covers/Artist/Artist\303\226.jpg"
new file mode 100644
index 00000000..056a10d2
Binary files /dev/null and "b/songmanagement/game/covers/Artist/Artist\303\226.jpg" differ
diff --git "a/songmanagement/game/covers/Artist/Artist\303\234.jpg" "b/songmanagement/game/covers/Artist/Artist\303\234.jpg"
new file mode 100644
index 00000000..c23a902a
Binary files /dev/null and "b/songmanagement/game/covers/Artist/Artist\303\234.jpg" differ
diff --git a/songmanagement/game/covers/Covers.ini b/songmanagement/game/covers/Covers.ini
new file mode 100644
index 00000000..80920358
--- /dev/null
+++ b/songmanagement/game/covers/Covers.ini
@@ -0,0 +1,111 @@
+[Edition]
+[Genre]
+[Folder]
+
+[Language]
+Austrian=.\.\Language\Austrian.jpg
+Bavarian=.\.\Language\Bavarian.jpg
+Chinese=.\Language\Chinese.jpg
+Danish=.\Language\Danish.jpg
+Dutch=.\Language\Dutch.jpg
+English=.\Language\English.jpg
+Finish=.\Language\Finish.jpg
+French=.\Language\French.jpg
+German=.\Language\German.jpg
+Greek=.\Language\Greek.jpg
+Italian=.\Language\Italian.jpg
+Japanese=.\Language\Japanese.jpg
+K�lsch=.\Language\K�lsch.jpg
+Norwegian=.\Language\Norwegian.jpg
+Peruvian=.\Language\Peruvian.jpg
+Polish=.\Language\Polish.jpg
+Romanian=.\Language\Romanian.jpg
+Russian=.\Language\Russian.jpg
+Slovenian=.\Language\Slovenian.jpg
+Spanish=.\Language\Spanish.jpg
+Swedish=.\Language\Swedish.jpg
+Turkish=.\Language\Turkish.jpg
+
+[Artist]
+#=.\Artist\Artist#.jpg
+1=.\Artist\Artist1.jpg
+2=.\Artist\Artist2.jpg
+3=.\Artist\Artist3.jpg
+4=.\Artist\Artist4.jpg
+5=.\Artist\Artist5.jpg
+6=.\Artist\Artist6.jpg
+7=.\Artist\Artist7.jpg
+8=.\Artist\Artist8.jpg
+9=.\Artist\Artist9.jpg
+0=.\Artist\Artist0.jpg
+A=.\Artist\ArtistA.jpg
+B=.\Artist\ArtistB.jpg
+C=.\Artist\ArtistC.jpg
+D=.\Artist\ArtistD.jpg
+E=.\Artist\ArtistE.jpg
+F=.\Artist\ArtistF.jpg
+G=.\Artist\ArtistG.jpg
+H=.\Artist\ArtistH.jpg
+I=.\Artist\ArtistI.jpg
+J=.\Artist\ArtistJ.jpg
+K=.\Artist\ArtistK.jpg
+L=.\Artist\ArtistL.jpg
+M=.\Artist\ArtistM.jpg
+N=.\Artist\ArtistN.jpg
+O=.\Artist\ArtistO.jpg
+P=.\Artist\ArtistP.jpg
+Q=.\Artist\ArtistQ.jpg
+R=.\Artist\ArtistR.jpg
+S=.\Artist\ArtistS.jpg
+T=.\Artist\ArtistT.jpg
+U=.\Artist\ArtistU.jpg
+V=.\Artist\ArtistV.jpg
+W=.\Artist\ArtistW.jpg
+X=.\Artist\ArtistX.jpg
+Y=.\Artist\ArtistY.jpg
+Z=.\Artist\ArtistZ.jpg
+�=.\Artist\Artist�.jpg
+�=.\Artist\Artist�.jpg
+�=.\Artist\Artist�.jpg
+
+[Title]
+#=.\Title\Title#.jpg
+1=.\Title\Title1.jpg
+2=.\Title\Title2.jpg
+3=.\Title\Title3.jpg
+4=.\Title\Title4.jpg
+5=.\Title\Title5.jpg
+6=.\Title\Title6.jpg
+7=.\Title\Title7.jpg
+8=.\Title\Title8.jpg
+9=.\Title\Title9.jpg
+0=.\Title\Title0.jpg
+A=.\Title\TitleA.jpg
+B=.\Title\TitleB.jpg
+C=.\Title\TitleC.jpg
+D=.\Title\TitleD.jpg
+E=.\Title\TitleE.jpg
+F=.\Title\TitleF.jpg
+G=.\Title\TitleG.jpg
+H=.\Title\TitleH.jpg
+I=.\Title\TitleI.jpg
+J=.\Title\TitleJ.jpg
+K=.\Title\TitleK.jpg
+L=.\Title\TitleL.jpg
+M=.\Title\TitleM.jpg
+N=.\Title\TitleN.jpg
+O=.\Title\TitleO.jpg
+P=.\Title\TitleP.jpg
+Q=.\Title\TitleQ.jpg
+R=.\Title\TitleR.jpg
+S=.\Title\TitleS.jpg
+T=.\Title\TitleT.jpg
+U=.\Title\TitleU.jpg
+V=.\Title\TitleV.jpg
+W=.\Title\TitleW.jpg
+X=.\Title\TitleX.jpg
+Y=.\Title\TitleY.jpg
+Z=.\Title\TitleZ.jpg
+�=.\Title\Title�.jpg
+�=.\Title\Title�.jpg
+�=.\Title\Title�.jpg
\ No newline at end of file
diff --git a/songmanagement/game/covers/Creative Commons.jpg b/songmanagement/game/covers/Creative Commons.jpg
new file mode 100644
index 00000000..55c66584
Binary files /dev/null and b/songmanagement/game/covers/Creative Commons.jpg differ
diff --git a/songmanagement/game/covers/Language/Austrian.jpg b/songmanagement/game/covers/Language/Austrian.jpg
new file mode 100644
index 00000000..04308ef2
Binary files /dev/null and b/songmanagement/game/covers/Language/Austrian.jpg differ
diff --git a/songmanagement/game/covers/Language/Bavarian.jpg b/songmanagement/game/covers/Language/Bavarian.jpg
new file mode 100644
index 00000000..1d3b82b8
Binary files /dev/null and b/songmanagement/game/covers/Language/Bavarian.jpg differ
diff --git a/songmanagement/game/covers/Language/Chinese.jpg b/songmanagement/game/covers/Language/Chinese.jpg
new file mode 100644
index 00000000..c53df6cc
Binary files /dev/null and b/songmanagement/game/covers/Language/Chinese.jpg differ
diff --git a/songmanagement/game/covers/Language/Danish.jpg b/songmanagement/game/covers/Language/Danish.jpg
new file mode 100644
index 00000000..c79a6083
Binary files /dev/null and b/songmanagement/game/covers/Language/Danish.jpg differ
diff --git a/songmanagement/game/covers/Language/Dutch.jpg b/songmanagement/game/covers/Language/Dutch.jpg
new file mode 100644
index 00000000..b2366ea3
Binary files /dev/null and b/songmanagement/game/covers/Language/Dutch.jpg differ
diff --git a/songmanagement/game/covers/Language/English.jpg b/songmanagement/game/covers/Language/English.jpg
new file mode 100644
index 00000000..97c2ccfa
Binary files /dev/null and b/songmanagement/game/covers/Language/English.jpg differ
diff --git a/songmanagement/game/covers/Language/Finish.jpg b/songmanagement/game/covers/Language/Finish.jpg
new file mode 100644
index 00000000..c2cbeb22
Binary files /dev/null and b/songmanagement/game/covers/Language/Finish.jpg differ
diff --git a/songmanagement/game/covers/Language/French.jpg b/songmanagement/game/covers/Language/French.jpg
new file mode 100644
index 00000000..a891df54
Binary files /dev/null and b/songmanagement/game/covers/Language/French.jpg differ
diff --git a/songmanagement/game/covers/Language/German.jpg b/songmanagement/game/covers/Language/German.jpg
new file mode 100644
index 00000000..c95b5641
Binary files /dev/null and b/songmanagement/game/covers/Language/German.jpg differ
diff --git a/songmanagement/game/covers/Language/Greek.jpg b/songmanagement/game/covers/Language/Greek.jpg
new file mode 100644
index 00000000..f394df30
Binary files /dev/null and b/songmanagement/game/covers/Language/Greek.jpg differ
diff --git a/songmanagement/game/covers/Language/Italian.jpg b/songmanagement/game/covers/Language/Italian.jpg
new file mode 100644
index 00000000..cb1f98aa
Binary files /dev/null and b/songmanagement/game/covers/Language/Italian.jpg differ
diff --git a/songmanagement/game/covers/Language/Japanese.jpg b/songmanagement/game/covers/Language/Japanese.jpg
new file mode 100644
index 00000000..6823f412
Binary files /dev/null and b/songmanagement/game/covers/Language/Japanese.jpg differ
diff --git "a/songmanagement/game/covers/Language/K\303\266lsch.jpg" "b/songmanagement/game/covers/Language/K\303\266lsch.jpg"
new file mode 100644
index 00000000..e0dfa98a
Binary files /dev/null and "b/songmanagement/game/covers/Language/K\303\266lsch.jpg" differ
diff --git a/songmanagement/game/covers/Language/Norwegian.jpg b/songmanagement/game/covers/Language/Norwegian.jpg
new file mode 100644
index 00000000..d0fe1838
Binary files /dev/null and b/songmanagement/game/covers/Language/Norwegian.jpg differ
diff --git a/songmanagement/game/covers/Language/Peruvian.jpg b/songmanagement/game/covers/Language/Peruvian.jpg
new file mode 100644
index 00000000..841fdf53
Binary files /dev/null and b/songmanagement/game/covers/Language/Peruvian.jpg differ
diff --git a/songmanagement/game/covers/Language/Polish.jpg b/songmanagement/game/covers/Language/Polish.jpg
new file mode 100644
index 00000000..53f9413f
Binary files /dev/null and b/songmanagement/game/covers/Language/Polish.jpg differ
diff --git a/songmanagement/game/covers/Language/Romanian.jpg b/songmanagement/game/covers/Language/Romanian.jpg
new file mode 100644
index 00000000..32854824
Binary files /dev/null and b/songmanagement/game/covers/Language/Romanian.jpg differ
diff --git a/songmanagement/game/covers/Language/Russian.jpg b/songmanagement/game/covers/Language/Russian.jpg
new file mode 100644
index 00000000..758dcaf3
Binary files /dev/null and b/songmanagement/game/covers/Language/Russian.jpg differ
diff --git a/songmanagement/game/covers/Language/Slovenian.jpg b/songmanagement/game/covers/Language/Slovenian.jpg
new file mode 100644
index 00000000..758dcaf3
Binary files /dev/null and b/songmanagement/game/covers/Language/Slovenian.jpg differ
diff --git a/songmanagement/game/covers/Language/Spanish.jpg b/songmanagement/game/covers/Language/Spanish.jpg
new file mode 100644
index 00000000..ac366293
Binary files /dev/null and b/songmanagement/game/covers/Language/Spanish.jpg differ
diff --git a/songmanagement/game/covers/Language/Swedish.jpg b/songmanagement/game/covers/Language/Swedish.jpg
new file mode 100644
index 00000000..c51620ea
Binary files /dev/null and b/songmanagement/game/covers/Language/Swedish.jpg differ
diff --git a/songmanagement/game/covers/Language/Thumbs.db b/songmanagement/game/covers/Language/Thumbs.db
new file mode 100644
index 00000000..352a0b63
Binary files /dev/null and b/songmanagement/game/covers/Language/Thumbs.db differ
diff --git a/songmanagement/game/covers/Language/Turkish.jpg b/songmanagement/game/covers/Language/Turkish.jpg
new file mode 100644
index 00000000..9ee803a0
Binary files /dev/null and b/songmanagement/game/covers/Language/Turkish.jpg differ
diff --git a/songmanagement/game/covers/NoCover.jpg b/songmanagement/game/covers/NoCover.jpg
new file mode 100644
index 00000000..0a424708
Binary files /dev/null and b/songmanagement/game/covers/NoCover.jpg differ
diff --git a/songmanagement/game/covers/Title/Title#.jpg b/songmanagement/game/covers/Title/Title#.jpg
new file mode 100644
index 00000000..af577517
Binary files /dev/null and b/songmanagement/game/covers/Title/Title#.jpg differ
diff --git a/songmanagement/game/covers/Title/Title0.jpg b/songmanagement/game/covers/Title/Title0.jpg
new file mode 100644
index 00000000..71370df4
Binary files /dev/null and b/songmanagement/game/covers/Title/Title0.jpg differ
diff --git a/songmanagement/game/covers/Title/Title1.jpg b/songmanagement/game/covers/Title/Title1.jpg
new file mode 100644
index 00000000..094e4f58
Binary files /dev/null and b/songmanagement/game/covers/Title/Title1.jpg differ
diff --git a/songmanagement/game/covers/Title/Title2.jpg b/songmanagement/game/covers/Title/Title2.jpg
new file mode 100644
index 00000000..26c20537
Binary files /dev/null and b/songmanagement/game/covers/Title/Title2.jpg differ
diff --git a/songmanagement/game/covers/Title/Title3.jpg b/songmanagement/game/covers/Title/Title3.jpg
new file mode 100644
index 00000000..5f75f29d
Binary files /dev/null and b/songmanagement/game/covers/Title/Title3.jpg differ
diff --git a/songmanagement/game/covers/Title/Title4.jpg b/songmanagement/game/covers/Title/Title4.jpg
new file mode 100644
index 00000000..f159d05b
Binary files /dev/null and b/songmanagement/game/covers/Title/Title4.jpg differ
diff --git a/songmanagement/game/covers/Title/Title5.jpg b/songmanagement/game/covers/Title/Title5.jpg
new file mode 100644
index 00000000..32cc513e
Binary files /dev/null and b/songmanagement/game/covers/Title/Title5.jpg differ
diff --git a/songmanagement/game/covers/Title/Title6.jpg b/songmanagement/game/covers/Title/Title6.jpg
new file mode 100644
index 00000000..77275577
Binary files /dev/null and b/songmanagement/game/covers/Title/Title6.jpg differ
diff --git a/songmanagement/game/covers/Title/Title7.jpg b/songmanagement/game/covers/Title/Title7.jpg
new file mode 100644
index 00000000..b1edbdae
Binary files /dev/null and b/songmanagement/game/covers/Title/Title7.jpg differ
diff --git a/songmanagement/game/covers/Title/Title8.jpg b/songmanagement/game/covers/Title/Title8.jpg
new file mode 100644
index 00000000..c9bde8d6
Binary files /dev/null and b/songmanagement/game/covers/Title/Title8.jpg differ
diff --git a/songmanagement/game/covers/Title/Title9.jpg b/songmanagement/game/covers/Title/Title9.jpg
new file mode 100644
index 00000000..cdf17287
Binary files /dev/null and b/songmanagement/game/covers/Title/Title9.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleD.jpg b/songmanagement/game/covers/Title/TitleD.jpg
new file mode 100644
index 00000000..9b6f53bb
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleD.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleE.jpg b/songmanagement/game/covers/Title/TitleE.jpg
new file mode 100644
index 00000000..c71d02ef
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleE.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleF.jpg b/songmanagement/game/covers/Title/TitleF.jpg
new file mode 100644
index 00000000..04f6179a
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleF.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleG.jpg b/songmanagement/game/covers/Title/TitleG.jpg
new file mode 100644
index 00000000..5067c462
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleG.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleH.jpg b/songmanagement/game/covers/Title/TitleH.jpg
new file mode 100644
index 00000000..4ce5e02a
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleH.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleI.jpg b/songmanagement/game/covers/Title/TitleI.jpg
new file mode 100644
index 00000000..01e80797
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleI.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleJ.jpg b/songmanagement/game/covers/Title/TitleJ.jpg
new file mode 100644
index 00000000..7b8947e0
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleJ.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleK.jpg b/songmanagement/game/covers/Title/TitleK.jpg
new file mode 100644
index 00000000..da11e2de
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleK.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleL.jpg b/songmanagement/game/covers/Title/TitleL.jpg
new file mode 100644
index 00000000..371d76e2
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleL.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleM.jpg b/songmanagement/game/covers/Title/TitleM.jpg
new file mode 100644
index 00000000..bc8c2ed2
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleM.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleN.jpg b/songmanagement/game/covers/Title/TitleN.jpg
new file mode 100644
index 00000000..dae3a2e4
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleN.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleO.jpg b/songmanagement/game/covers/Title/TitleO.jpg
new file mode 100644
index 00000000..a1fe1268
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleO.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleP.jpg b/songmanagement/game/covers/Title/TitleP.jpg
new file mode 100644
index 00000000..afcf8d55
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleP.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleQ.jpg b/songmanagement/game/covers/Title/TitleQ.jpg
new file mode 100644
index 00000000..99ab7278
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleQ.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleR.jpg b/songmanagement/game/covers/Title/TitleR.jpg
new file mode 100644
index 00000000..22e9c257
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleR.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleS.jpg b/songmanagement/game/covers/Title/TitleS.jpg
new file mode 100644
index 00000000..c1b81249
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleS.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleT.jpg b/songmanagement/game/covers/Title/TitleT.jpg
new file mode 100644
index 00000000..f2b3ef9c
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleT.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleU.jpg b/songmanagement/game/covers/Title/TitleU.jpg
new file mode 100644
index 00000000..05c2a4ca
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleU.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleV.jpg b/songmanagement/game/covers/Title/TitleV.jpg
new file mode 100644
index 00000000..28044811
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleV.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleW.jpg b/songmanagement/game/covers/Title/TitleW.jpg
new file mode 100644
index 00000000..143e5499
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleW.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleX.jpg b/songmanagement/game/covers/Title/TitleX.jpg
new file mode 100644
index 00000000..967b7e8e
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleX.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleY.jpg b/songmanagement/game/covers/Title/TitleY.jpg
new file mode 100644
index 00000000..a59ffd84
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleY.jpg differ
diff --git a/songmanagement/game/covers/Title/TitleZ.jpg b/songmanagement/game/covers/Title/TitleZ.jpg
new file mode 100644
index 00000000..3d3734f0
Binary files /dev/null and b/songmanagement/game/covers/Title/TitleZ.jpg differ
diff --git a/songmanagement/game/covers/Title/Titlea.jpg b/songmanagement/game/covers/Title/Titlea.jpg
new file mode 100644
index 00000000..60538668
Binary files /dev/null and b/songmanagement/game/covers/Title/Titlea.jpg differ
diff --git a/songmanagement/game/covers/Title/Titleb.jpg b/songmanagement/game/covers/Title/Titleb.jpg
new file mode 100644
index 00000000..109e76e0
Binary files /dev/null and b/songmanagement/game/covers/Title/Titleb.jpg differ
diff --git a/songmanagement/game/covers/Title/Titlec.jpg b/songmanagement/game/covers/Title/Titlec.jpg
new file mode 100644
index 00000000..013c12df
Binary files /dev/null and b/songmanagement/game/covers/Title/Titlec.jpg differ
diff --git "a/songmanagement/game/covers/Title/Title\303\204.jpg" "b/songmanagement/game/covers/Title/Title\303\204.jpg"
new file mode 100644
index 00000000..f5eece25
Binary files /dev/null and "b/songmanagement/game/covers/Title/Title\303\204.jpg" differ
diff --git "a/songmanagement/game/covers/Title/Title\303\226.jpg" "b/songmanagement/game/covers/Title/Title\303\226.jpg"
new file mode 100644
index 00000000..c0b11f23
Binary files /dev/null and "b/songmanagement/game/covers/Title/Title\303\226.jpg" differ
diff --git "a/songmanagement/game/covers/Title/Title\303\234.jpg" "b/songmanagement/game/covers/Title/Title\303\234.jpg"
new file mode 100644
index 00000000..c60913e1
Binary files /dev/null and "b/songmanagement/game/covers/Title/Title\303\234.jpg" differ
diff --git a/songmanagement/game/fonts/DejaVu/AUTHORS b/songmanagement/game/fonts/DejaVu/AUTHORS
new file mode 100644
index 00000000..66b7e445
--- /dev/null
+++ b/songmanagement/game/fonts/DejaVu/AUTHORS
@@ -0,0 +1,44 @@
+Adrian Schroeter
+Andrey Valentinovich Panov
+Ben Laenen
+Besarion Gugushvili
+Bhikkhu Pesala
+Clayborne Arevalo
+Dafydd Harries
+Danilo Segan
+Davide Viti
+David Jez
+David Lawrence Ramsey
+Denis Jacquerye
+Dwayne Bailey
+Eugeniy Meshcheryakov
+Gee Fung Sit
+Heikki Lindroos
+James Cloos
+James Crippen
+John Karp
+Keenan Pepper
+Lars Naesbye Christensen
+Mashrab Kuvatov
+Max Berger
+Mederic Boquien
+Michael Everson
+Misu Moldovan
+Nguyen Thai Ngoc Duy
+Nicolas Mailhot
+Ognyan Kulev
+Ondrej Koala Vacha
+Peter Cernak
+Remy Oudompheng
+Roozbeh Pournader
+Sahak Petrosyan
+Sander Vesik
+Stepan Roh
+Stephen Hartke
+Tavmjong Bah
+Tim May
+Valentin Stoykov
+Vasek Stodulka
+Wesley Transue
+
+$Id: AUTHORS 2162 2007-12-27 12:39:07Z ben_laenen $
diff --git a/songmanagement/game/fonts/DejaVu/DejaVuSans-Bold.ttf b/songmanagement/game/fonts/DejaVu/DejaVuSans-Bold.ttf
new file mode 100644
index 00000000..29da1369
Binary files /dev/null and b/songmanagement/game/fonts/DejaVu/DejaVuSans-Bold.ttf differ
diff --git a/songmanagement/game/fonts/DejaVu/DejaVuSans.ttf b/songmanagement/game/fonts/DejaVu/DejaVuSans.ttf
new file mode 100644
index 00000000..e0699fec
Binary files /dev/null and b/songmanagement/game/fonts/DejaVu/DejaVuSans.ttf differ
diff --git a/songmanagement/game/fonts/DejaVu/LICENSE b/songmanagement/game/fonts/DejaVu/LICENSE
new file mode 100644
index 00000000..254e2cc4
--- /dev/null
+++ b/songmanagement/game/fonts/DejaVu/LICENSE
@@ -0,0 +1,99 @@
+Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
+
+Bitstream Vera Fonts Copyright
+------------------------------
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license ("Fonts") and associated
+documentation files (the "Font Software"), to reproduce and distribute the
+Font Software, including without limitation the rights to use, copy, merge,
+publish, distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright and trademark notices and this permission notice shall
+be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and
+additional glyphs or characters may be added to the Fonts, only if the fonts
+are renamed to names not containing either the words "Bitstream" or the word
+"Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font
+Software that has been modified and is distributed under the "Bitstream
+Vera" names.
+
+The Font Software may be sold as part of a larger software package but no
+copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
+ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
+FONT SOFTWARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome
+Foundation, and Bitstream Inc., shall not be used in advertising or
+otherwise to promote the sale, use or other dealings in this Font Software
+without prior written authorization from the Gnome Foundation or Bitstream
+Inc., respectively. For further information, contact: fonts at gnome dot
+org. 
+
+Arev Fonts Copyright
+------------------------------
+
+Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the fonts accompanying this license ("Fonts") and
+associated documentation files (the "Font Software"), to reproduce
+and distribute the modifications to the Bitstream Vera Font Software,
+including without limitation the rights to use, copy, merge, publish,
+distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright and trademark notices and this permission notice
+shall be included in all copies of one or more of the Font Software
+typefaces.
+
+The Font Software may be modified, altered, or added to, and in
+particular the designs of glyphs or characters in the Fonts may be
+modified and additional glyphs or characters may be added to the
+Fonts, only if the fonts are renamed to names not containing either
+the words "Tavmjong Bah" or the word "Arev".
+
+This License becomes null and void to the extent applicable to Fonts
+or Font Software that has been modified and is distributed under the 
+"Tavmjong Bah Arev" names.
+
+The Font Software may be sold as part of a larger software package but
+no copy of one or more of the Font Software typefaces may be sold by
+itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
+TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
+
+Except as contained in this notice, the name of Tavmjong Bah shall not
+be used in advertising or otherwise to promote the sale, use or other
+dealings in this Font Software without prior written authorization
+from Tavmjong Bah. For further information, contact: tavmjong @ free
+. fr.
+
+$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $
diff --git a/songmanagement/game/fonts/DejaVu/README b/songmanagement/game/fonts/DejaVu/README
new file mode 100644
index 00000000..6882268b
--- /dev/null
+++ b/songmanagement/game/fonts/DejaVu/README
@@ -0,0 +1,59 @@
+DejaVu fonts 2.26 (c)2004-2008 DejaVu fonts team
+------------------------------------------------
+
+The DejaVu fonts are a font family based on the Bitstream Vera Fonts
+(http://gnome.org/fonts/). Its purpose is to provide a wider range of
+characters (see status.txt for more information) while maintaining the
+original look and feel.
+
+DejaVu fonts are based on Bitstream Vera fonts version 1.10.
+
+Available fonts (Sans = sans serif, Mono = monospaced):
+
+DejaVu Sans Mono
+DejaVu Sans Mono Bold
+DejaVu Sans Mono Bold Oblique
+DejaVu Sans Mono Oblique
+DejaVu Sans
+DejaVu Sans Bold
+DejaVu Sans Bold Oblique
+DejaVu Sans Oblique
+DejaVu Sans ExtraLight (experimental)
+DejaVu Serif
+DejaVu Serif Bold
+DejaVu Serif Bold Italic (experimental)
+DejaVu Serif Italic (experimental)
+DejaVu Sans Condensed (experimental)
+DejaVu Sans Condensed Bold (experimental)
+DejaVu Sans Condensed Bold Oblique (experimental)
+DejaVu Sans Condensed Oblique (experimental)
+DejaVu Serif Condensed (experimental)
+DejaVu Serif Condensed Bold (experimental)
+DejaVu Serif Condensed Bold Italic (experimental)
+DejaVu Serif Condensed Italic (experimental)
+
+All fonts are also available as derivative called DejaVu LGC with support
+only for Latin, Greek and Cyrillic scripts.
+
+For license information see LICENSE. What's new is described in NEWS. Known
+bugs are in BUGS. All authors are mentioned in AUTHORS.
+
+Fonts are published in source form as SFD files (Spline Font Database from
+FontForge - http://fontforge.sf.net/) and in compiled form as TTF files
+(TrueType fonts).
+
+For more information go to http://dejavu.sourceforge.net/.
+
+Characters from Arev fonts, Copyright (c) 2006 by Tavmjong Bah:
+---------------------------
+U+01BA, U+01BF, U+01F7, U+021C-U+021D, U+0220, U+0222-U+0223,
+U+02B9, U+02BA, U+02BD, U+02C2-U+02C5, U+02d4-U+02D5,
+U+02D7, U+02EC-U+02EE, U+0346-U+034E, U+0360, U+0362,
+U+03E2-03EF, U+0460-0463, U+0466-U+0486, U+0488-U+0489, U+04A8-U+04A9,
+U+0500-U+050F, U+2055-205E, U+20B0, U+20B2-U+20B3, U+2102, U+210D, U+210F,
+U+2111, U+2113, U+2115, U+2118-U+211A, U+211C-U+211D, U+2124, U+2135,
+U+213C-U+2140, U+2295-U+2298, U+2308-U+230B, U+26A2-U+26B1, U+2701-U+2704,
+U+2706-U+2709, U+270C-U+274B, U+2758-U+275A, U+2761-U+2775, U+2780-U+2794,
+U+2798-U+27AF, U+27B1-U+27BE, U+FB05-U+FB06
+
+$Id: README 2263 2008-07-26 19:48:13Z ben_laenen $
diff --git a/songmanagement/game/fonts/FreeSans/AUTHORS b/songmanagement/game/fonts/FreeSans/AUTHORS
new file mode 100644
index 00000000..fbb0e990
--- /dev/null
+++ b/songmanagement/game/fonts/FreeSans/AUTHORS
@@ -0,0 +1,191 @@
+-*- mode:text; coding:utf-8; -*-
+                        GNU FreeFont Authors
+                        ====================
+
+The FreeFont collection is being maintained by
+	Steve White <stevan.white AT googlemail.com>
+The folowing list cites the other contributors that contributed to
+particular ISO 10646 blocks.
+
+* URW++ Design & Development GmbH <http://www.urwpp.de/>
+
+	Basic Latin				(U+0041-U+007A)
+	Latin-1 Supplement                      (U+00C0-U+00FF) (most)
+	Latin Extended-A                        (U+0100-U+017F)
+	Spacing Modifier Letters		(U+02B0-U+02FF)
+	Mathematical Operators			(U+2200-U+22FF) (parts)
+	Block Elements				(U+2580-U+259F)
+	Dingbats				(U+2700-U+27BF)
+
+* Yannis Haralambous <yannis.haralambous AT enst-bretagne.fr> and John
+  Plaice <plaice AT omega.cse.unsw.edu.au>
+
+	Latin Extended-B                        (U+0180-U+024F)
+	IPA Extensions				(U+0250-U+02AF)
+	Greek					(U+0370-U+03FF)
+	Armenian				(U+0530-U+058F)
+	Hebrew					(U+0590-U+05FF)
+	Arabic					(U+0600-U+06FF)
+	Currency Symbols			(U+20A0-U+20CF)
+	Arabic Presentation Forms-A		(U+FB50-U+FDFF)
+	Arabic Presentation Forms-B		(U+FE70-U+FEFF)
+
+* Young U. Ryu <ryoung AT utdallas.edu>
+
+	Arrows					(U+2190-U+21FF)
+	Mathematical Symbols			(U+2200-U+22FF)
+
+* Valek Filippov <frob AT df.ru>
+
+	Cyrillic				(U+0400-U+04FF)
+
+* Wadalab Kanji Comittee
+
+	Hiragana				(U+3040-U+309F)
+	Katakana				(U+30A0-U+30FF)
+
+* Angelo Haritsis <ah AT computer.org>
+
+	Greek					(U+0370-U+03FF)
+
+* Yannis Haralambous and Virach Sornlertlamvanich
+
+	Thai					(U+0E00-U+0E7F)
+
+* Shaheed R. Haque <srhaque AT iee.org>
+
+	Bengali					(U+0980-U+09FF)
+
+* Sam Stepanyan <sam AT arminco.com>
+
+	Armenian				(U+0530-U+058F)
+
+* Mohamed Ishan <ishan AT mitf.f2s.com>
+
+	Thaana					(U+0780-U+07BF)
+
+* Sushant Kumar Dash <sushant AT writeme.com>
+
+	Oriya					(U+0B00-U+0B7F)
+
+* Harsh Kumar <harshkumar AT vsnl.com>
+
+	Devanagari				(U+0900-U+097F)
+	Bengali					(U+0980-U+09FF)
+	Gurmukhi				(U+0A00-U+0A7F)
+	Gujarati				(U+0A80-U+0AFF)
+
+* Prasad A. Chodavarapu <chprasad AT hotmail.com>
+
+	Telugu					(U+0C00-U+0C7F)
+
+* Frans Velthuis <velthuis AT rc.rug.nl> and Anshuman Pandey
+  <apandey AT u.washington.edu> 
+
+	Devanagari				(U+0900-U+097F)
+
+* Hardip Singh Pannu <HSPannu AT aol.com>
+
+	Gurmukhi				(U+0A00-U+0A7F)
+
+* Jeroen Hellingman <jehe AT kabelfoon.nl>
+
+	Oriya					(U+0B00-U+0B7F)
+	Malayalam				(U+0D00-U+0D7F)
+
+* Thomas Ridgeway <email needed>
+
+	Tamil					(U+0B80-U+0BFF)
+
+* Berhanu Beyene <1beyene AT informatik.uni-hamburg.de>,
+  Prof. Dr. Manfred Kudlek <kudlek AT informatik.uni-hamburg.de>, Olaf
+  Kummer <kummer AT informatik.uni-hamburg.de>, and Jochen Metzinger <?>
+
+	Ethiopic				(U+1200-U+137F)
+
+* Maxim Iorsh <iorsh AT users.sourceforge.net>
+
+	Hebrew					(U+0590-U+05FF)
+
+* Vyacheslav Dikonov <sdiconov AT mail.ru>
+
+	Syriac					(U+0700-U+074A)
+	Braille					(U+2800-U+28FF)
+
+* Panayotis Katsaloulis <panayotis AT panayotis.com>
+
+	Greek Extended				(U+1F00-U+1FFF)
+
+* M.S. Sridhar <mssridhar AT vsnl.com>
+
+	Devanagari				(U+0900-U+097F)
+	Bengali					(U+0980-U+09FF)
+	Gurmukhi				(U+0A00-U+0A7F)
+	Gujarati				(U+0A80-U+0AFF)
+	Oriya					(U+0B00-U+0B7F)
+	Tamil					(U+0B80-U+0BFF)
+	Telugu					(U+0C00-U+0C7F)
+	Kannada					(U+0C80-U+0CFF)	
+	Malayalam				(U+0D00-U+0D7F)
+
+* DMS Electronics, The Sri Lanka Tipitaka Project, and Noah Levitt
+  <nlevitt AT columbia.edu>
+
+	Sinhala					(U+0D80-U+0DFF)
+        
+* Dan Shurovich Chirkov <dansh AT chirkov.com>
+
+	Cyrillic				(U+0400-U+04FF)
+
+* Abbas Izad <abbasizad AT hotmail.com>
+
+	Arabic					(U+0600-U+06FF)
+	Arabic Presentation Forms-A		(U+FB50-U+FDFF)
+	Arabic Presentation Forms-B		(U+FE70-U+FEFF)
+
+* Denis Jacquerye <moyogo AT gmail.com>
+
+	Latin Extended-B                        (U+0180-U+024F)
+	IPA Extensions				(U+0250-U+02AF)
+
+* K.H. Hussain <hussain AT kfri.org> and R. Chitrajan
+
+	Malayalam				(U+0D00-U+0D7F)
+
+* Solaiman Karim <solaiman AT ekushey.org> and Omi Azad <omi AT ekushey.org>
+
+	Bengali					(U+0980-U+09FF)
+
+* Sonali Sonania <sonalisonania AT gmail.com> and Monika Shah
+  <monikapatira AT gmail.com>
+
+	Devanagari				(U+0900-U+097F)
+	Gujarati				(U+0A80-U+0AFF)
+
+* Pravin Satpute <pravin_ind21 AT hotmail.com>, Bageshri Salvi
+  <sbagrshri AT yahoo.co.in>, Rahul Bhalerao <rahul_pb_india AT
+  yahoo.com> and Sandeep Shedmake <surgs2k47 AT yahoo.co.in>
+
+	Devanagari				(U+0900-U+097F)
+	Gujarati				(U+0A80-U+0AFF)
+	Oriya					(U+0B00-U+0B7F)
+	Malayalam				(U+0D00-U+0D7F)
+	Tamil					(U+0B80-U+0BFF)
+
+
+* Kulbir Singh Thind
+
+	Gurmukhi				(U+0A00-U+0A7F)
+
+* Gia Shervashidze <giasher AT telenet.ge>
+
+        Georgian				(U+10A0-U+10FF)
+
+* Primož Peterlin <primoz.peterlin AT biofiz.mf.uni-lj.si>
+  maintained FreeFont for several years, and is thanked for all his work.
+
+Please see the CREDITS file for details on who contributed particular
+subsets of the glyphs in font files.
+
+--------------------------------------------------------------------------
+$Id: AUTHORS,v 1.15 2008/08/30 09:31:54 Stevan_White Exp $
diff --git a/songmanagement/game/fonts/FreeSans/COPYING b/songmanagement/game/fonts/FreeSans/COPYING
new file mode 100644
index 00000000..7f1c9b60
--- /dev/null
+++ b/songmanagement/game/fonts/FreeSans/COPYING
@@ -0,0 +1,341 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          51 Franklin Street, Fifth Floor,
+                          Boston, MA 02110-13017, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/songmanagement/game/fonts/FreeSans/CREDITS b/songmanagement/game/fonts/FreeSans/CREDITS
new file mode 100644
index 00000000..0cc30949
--- /dev/null
+++ b/songmanagement/game/fonts/FreeSans/CREDITS
@@ -0,0 +1,506 @@
+-*- mode:text; coding:utf-8; -*-
+                         GNU FreeFont Credits
+                         ====================
+
+This file lists contributors and contributions to the GNU FreeFont project.
+
+
+* URW++ Design & Development GmbH <http://www.urwpp.de/>
+
+URW++ donated a set of 35 core PostScript Type 1 fonts to the
+Ghostscript project <http://www.cs.wisc.edu/~ghost/>, to be available
+under the terms of GNU General Public License (GPL).
+
+	Basic Latin				(U+0041-U+007A)
+	Latin-1 Supplement                      (U+00C0-U+00FF)
+	Latin Extended-A                        (U+0100-U+017F)
+	Spacing Modifier Letters		(U+02B0-U+02FF)
+	Mathematical Operators			(U+2200-U+22FF)
+	Block Elements				(U+2580-U+259F)
+	Dingbats				(U+2700-U+27BF)
+
+
+* Yannis Haralambous <yannis.haralambous AT enst-bretagne.fr> and John
+  Plaice <plaice AT omega.cse.unsw.edu.au>
+
+Yannis Haralambous and John Plaice are the authors of Omega
+typesetting system, <http://omega.cse.unsw.edu.au/>. Omega is an
+extension of TeX. Its first release, aims primarily at improving TeX's
+multilingual abilities. In Omega all characters and pointers into
+data-structures are 16-bit wide, instead of 8-bit, thereby eliminating
+many of the trivial limitations of TeX. Omega also allows multiple
+input and output character sets, and uses programmable filters to
+translate from one encoding to another, to perform contextual
+analysis, etc. Internally, Omega uses the universal 16-bit Unicode
+standard character set, based on ISO-10646. These improvements not
+only make it a lot easier for TeX users to cope with multiple or
+complex languages, like Arabic, Indic, Khmer, Chinese, Japanese or
+Korean, in one document, but will also form the basis for future
+developments in other areas, such as native color support and
+hypertext features. ... Fonts for UT1 (omlgc family) and UT2 (omah
+family) are under development: these fonts are in PostScript format
+and visually close to Times and Helvetica font families. (from the
+Omega WWW site). Omega fonts are available subject to GPL
+<http://www.ctan.org/tex-archive/help/Catalogue/entries/omegafonts.html>.
+
+	Latin Extended-B                        (U+0180-U+024F)
+	IPA Extensions				(U+0250-U+02AF)
+	Greek					(U+0370-U+03FF)
+	Armenian				(U+0530-U+058F)
+	Hebrew					(U+0590-U+05FF)
+	Arabic					(U+0600-U+06FF)
+	Currency Symbols			(U+20A0-U+20CF)
+	Arabic Presentation Forms-A		(U+FB50-U+FDFF)
+	Arabic Presentation Forms-B		(U+FE70-U+FEFF)
+
+
+* Valek Filippov <frob AT df.ru>
+
+Valek Filippov added Cyrillic glyphs and composite Latin Extended A to
+the whole set of the abovementioned URW set of 35 PostScript core
+fonts, <ftp://ftp.gnome.ru/fonts/urw/>. The fonts are available under
+GPL.
+
+	Latin Extended-A                        (U+0100-U+017F)
+	Cyrillic				(U+0400-U+04FF)
+
+
+* Wadalab Kanji Comittee
+
+Between April 1990 and March 1992, Wadalab Kanji Comittee put together
+a series of scalable font files with Japanese scripts, in four forms:
+Sai Micho, Chu Mincho, Cho Kaku and Saimaru. The font files are
+written in custom file format, while tools for conversion into
+Metafont and PostScript Type 1 are also supplied. The Wadalab Kanji
+Comittee has later been dismissed, and the resulting files can be now
+found on the FTP server of the Depertment of Mathematical Engineering
+and Information Physics, Faculty of Engineering, University of Tokyo
+<ftp://ftp.ipl.t.u-tokyo.ac.jp/Font/>.
+
+	Hiragana				(U+3040-U+309F)
+	Katakana				(U+30A0-U+30FF)
+
+
+* Young U. Ryu <ryoung AT utdallas.edu>
+
+Young Ryu is the author of Txfonts, a set of mathematical symbols
+designed to accompany text typeset in Times or its variants. In the
+documentation, Young adresses the design of mathematical symbols: "The
+Adobe Times fonts are thicker than the CM fonts. Designing math fonts
+for Times based on the rule thickness of Times = , , + , / , < ,
+etc. would result in too thick math symbols, in my opinion. In the TX
+fonts, these glyphs are thinner than those of original Times
+fonts. That is, the rule thickness of these glyphs is around 85% of
+that of the Times fonts, but still thicker than that of the CM fonts."
+TX fonts are are distributed under the GNU public license (GPL). 
+<http://www.ctan.org/tex-archive/fonts/txfonts/>.
+
+	Arrows					(U+2190-U+21FF)
+	Mathematical Symbols			(U+2200-U+22FF)
+
+
+* Angelo Haritsis <ah AT computer.org>
+
+Angelo Haritsis has compiled a set of Greek Type 1 fonts, available on
+<ftp://ftp.hellug.gr/pub/unix/linux/GREEK/fonts/greekXfonts-Type1-1.1.tgz>.
+The glyphs from this source has been used to compose Greek glyphs in
+FreeSans and FreeMono.
+
+Angelo's licence says: "You can enjoy free use of these fonts for
+educational or commercial purposes.  All derived works should include
+this paragraph.  If you want to change something please let me have
+your changes (via email) so that they can go into the next
+version. You can also send comments etc to the above address."
+
+	Greek					(U+0370-U+03FF)
+
+
+* Yannis Haralambous and Virach Sornlertlamvanich
+
+In 1999, Yannis Haralambous and Virach Sornlertlamvanich made a set of
+glyphs covering the Thai national standard NF3, in both upright and
+slanted shape. The collection of glyphs have been made part of GNU
+intlfonts 1.2 package and is available on
+<ftp://ftp.gnu.org/pub/gnu/intlfonts/> under GPL.
+
+	Thai					(U+0E00-U+0E7F)
+
+
+* Shaheed R. Haque <srhaque AT iee.org>
+
+Shaheed Haque has developed a basic set of basic Bengali glyphs
+(without ligatures), using ISO10646 encoding. They are available under
+the XFree86 license at <http://www.btinternet.com/~shaheedhaque/>.
+
+Copyright (C) 2001 S.R.Haque <srhaque AT iee.org>.  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, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL S.R.HAQUE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of S.R.Haque shall not be
+used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from
+S.R.Haque.
+
+	Bengali					(U+0980-U+09FF)
+
+
+* Sam Stepanyan <sam AT arminco.com>
+
+Sam Stepanyan created a set of Armenian sans serif glyphs visually
+compatible with Helvetica or Arial. Available on
+<http://www.editum.com.ar/mashtots/html/fonts/ara.tar.gz>. On
+2002-01-24, Sam writes: "Arial Armenian font is free for
+non-commercial use, so it is OK to use under GPL license."
+
+	Armenian				(U+0530-U+058F)
+
+
+* Mohamed Ishan <ishan AT mitf.f2s.com>
+
+Mohamed Ishan has started a Thaana Unicode Project
+<http://thaana.sourceforge.net/> and among other things created a
+couple of Thaana fonts, available under FDL or BDF license.
+
+	Thaana					(U+0780-U+07BF)
+
+
+* Sushant Kumar Dash <sushant AT writeme.com> (*)
+
+Sushant Dash has created a font in his mother tongue, Oriya. As he
+states on his web page <http://members.tripod.com/~sushantdash/>:
+"Please feel free to foreword this mail to your Oriya friends. No
+copyright law is applied for this font. It is totally free!!! Feel
+free to modify this using any font editing tools. This is designed for
+people like me, who are away from Orissa and want to write letters
+home using Computers, but suffer due to unavailability of Oriya
+fonts.(Or the cost of the available packages are too much)."
+
+	Oriya					(U+0B00-U+0B7F)
+
+
+* Harsh Kumar <harshkumar AT vsnl.com>
+
+Harsh Kumar has started BharatBhasha <http://www.bharatbhasha.net/> -
+an effort to provide "FREE software, Tutorial, Source Codes
+etc. available for working in Hindi, Marathi, Gujarati, Gurmukhi and
+Bangla. You can type text, write Web pages or develop Indian Languages
+Applications on Windows and on Linux. We also offer FREE help to
+users, enthusiasts and software developers for their work in Indian
+languages."
+
+	Devanagari				(U+0900-U+097F)
+	Bengali					(U+0980-U+09FF)
+	Gurmukhi				(U+0A00-U+0A7F)
+	Gujarati				(U+0A80-U+0AFF)
+
+
+* Prasad A. Chodavarapu <chprasad AT hotmail.com>
+
+Prasad A. Chodavarapu created Tikkana, a Telugu font available in Type
+1 and TrueType format on <http://chaitanya.bhaavana.net/fonts/>. 
+Tikkana exceeds the Unicode Telugu range with some composite glyphs.
+Available under the GNU General Public License.
+
+	Telugu					(U+0C00-U+0C7F)
+
+
+* Frans Velthuis <velthuis AT rc.rug.nl> and Anshuman Pandey
+  <apandey AT u.washington.edu>
+
+In 1991, Frans Velthuis from the Groningen University, The
+Netherlands, released a Devanagari font as Metafont source, available
+under the terms of GNU GPL. Later, Anshuman Pandey from the Washington
+University, Seattle, USA, took over the maintenance of font. Fonts can
+be found on CTAN, <ftp://ftp.dante.de/tex-archive/language/devanagari/>. I
+converted the font to Type 1 format using Péter Szabó's TeXtrace
+program <http://www.inf.bme.hu/~pts/textrace/> and removed some
+redundant control points with PfaEdit.
+
+	Devanagari				(U+0900-U+097F)
+
+
+* Hardip Singh Pannu <HSPannu AT aol.com>
+
+In 1991, Hardip Singh Pannu has created a free Gurmukhi TrueType font,
+available as regular, bold, oblique and bold oblique form. Its license
+says "Please remember that these fonts are copyrighted (by me) and are
+for non-profit use only." 
+
+	Gurmukhi				(U+0A00-U+0A7F)
+
+
+* Jeroen Hellingman <jehe AT kabelfoon.nl>
+
+Jeroen Hellingman created a set of Malayalam metafonts in 1994, and a
+set of Oriya metafonts in 1996. Malayalam fonts were created as
+uniform stroke only, while Oriya metafonts exist in both uniform and
+modulated stroke. From private communication: "It is my intention to
+release the fonts under GPL, but not all copies around have this
+notice on them." Metafonts can be found on CTAN,
+<ftp://ftp.dante.de/tex-archive/language/oriya/> and
+<ftp://ftp.dante.de/tex-archive/language/malayalam/>.
+
+	Oriya					(U+0B00-U+0B7F)
+	Malayalam				(U+0D00-U+0D7F)
+
+
+* Thomas Ridgeway <> (*)
+
+Thomas Ridgeway, then at the Humanities And Arts Computing Center,
+Washington University, Seattle, USA, (now defunct), created a Tamil
+metafont in 1990. Anshuman Pandey from the same university took over
+the maintenance of font. Fonts can be found at CTAN,
+<ftp://ftp.dante.de/tex-archive/language/tamil/wntamil/>.
+
+	Tamil					(U+0B80-U+0BFF)
+
+
+* Berhanu Beyene <1beyene AT informatik.uni-hamburg.de>,
+  Prof. Dr. Manfred Kudlek <kudlek AT informatik.uni-hamburg.de>, Olaf
+  Kummer <kummer AT informatik.uni-hamburg.de>, and Jochen Metzinger <?>
+
+Beyene, Kudlek, Kummer and Metzinger from the Theoretical Foundations
+of Computer Science, University of Hamburg, prepared a set of Ethiopic
+metafonts, found on
+<ftp://ftp.dante.de/tex-archive/language/ethiopia/ethiop/>. They also
+maintain home page on the Ethiopic font project,
+<http://www.informatik.uni-hamburg.de/TGI/mitarbeiter/wimis/kummer/ethiop_eng.html>,
+and can be reached at <ethiop AT informatik.uni-hamburg.de>. The current
+version of fonts is 0.7 (1998), and they are released under GNU GPL. I
+converted the fonts to Type 1 format using Péter Szabó's TeXtrace-A
+program <http://www.inf.bme.hu/~pts/textrace/> and removed some
+redundant control points with PfaEdit.
+
+	Ethiopic				(U+1200-U+137F)
+
+
+* Maxim Iorsh <iorsh AT users.sourceforge.net>
+
+In 2002, Maxim Iorsh started the Culmus project, aiming at providing
+Hebrew-speaking Linux and Unix community with a basic collection of
+Hebrew fonts for X Windows. The fonts are visually compatible with
+URW++ Century Schoolbook L, URW++ Nimbus Sans L and URW++ Nimbus Mono
+L families, respectively, and are released under GNU GPL license. See
+also <http://culmus.sourceforge.net/>.
+
+	Hebrew					(U+0590-U+05FF)
+
+
+* Panayotis Katsaloulis <panayotis AT panayotis.com>
+
+Panayotis Katsaloulis helped fixing Greek accents in the Greek
+Extended area.
+
+	Greek Extended				(U+1F00-U+1FFF)
+
+
+* Vyacheslav Dikonov <sdiconov AT mail.ru>
+
+Vyacheslav Dikonov made a Braille unicode font that could be merged
+with the UCS fonts to fill the 2800-28FF range completely. (uniform
+scaling is possible to adapt it to any cell size). He also contributed
+a free syriac font, whose glyphs (about half of them) are borrowed
+from the "Carlo Ator" font freely downloadable from
+<http://www.aacf.asso.fr/>. Vyacheslav also filled in a few missing
+spots in the U+2000-U+27FF area, e.g. the box drawing section, sets of
+subscript and superscript digits and capital Roman numbers.
+
+	Syriac					(U+0700-U+074A)
+	Box Drawing				(U+2500-U+257F)
+	Braille					(U+2800-U+28FF)
+
+
+* M.S. Sridhar <mssridhar AT vsnl.com>
+
+M/S Cyberscape Multimedia Limited, Mumbai, developers of Akruti
+Software for Indian Languages (http://www.akruti.com/), have released
+a set of TTF fonts for nine Indian scripts (Devanagari, Gujarati,
+Telugu, Tamil, Malayalam, Kannada, Bengali, Oriya, and Gurumukhi)
+under the GNU General Public License (GPL). You can download the fonts
+from the Free Software Foundation of India WWW site
+(http://www.gnu.org.in/akruti-fonts/) or from the Akruti website.
+
+For any further information or assistance regarding these fonts,
+please contact mssridhar AT vsnl.com.
+
+	Devanagari				(U+0900-U+097F)
+	Bengali					(U+0980-U+09FF)
+	Gurmukhi				(U+0A00-U+0A7F)
+	Gujarati				(U+0A80-U+0AFF)
+	Oriya					(U+0B00-U+0B7F)
+	Tamil					(U+0B80-U+0BFF)
+	Telugu					(U+0C00-U+0C7F)
+	Kannada					(U+0C80-U+0CFF)	
+	Malayalam				(U+0D00-U+0D7F)
+
+
+* DMS Electronics, The Sri Lanka Tipitaka Project, and Noah Levitt
+  <nlevitt AT columbia.edu>
+
+Noah Levitt found out that the Sinhalese fonts available on the site
+<http://www.metta.lk/fonts/> are released under GNU GPL, or,
+precisely, "Public Domain under GNU Licence
 Produced by DMS
+Electronics for The Sri Lanka Tipitaka Project" (taken from the font
+comment), and took the effort of recoding the font to Unicode.
+
+	Sinhala					(U+0D80-U+0DFF)
+       
+
+* Daniel Shurovich Chirkov <dansh AT chirkov.com>
+
+Dan Chirkov updated the FreeSerif font with the missing Cyrillic
+glyphs needed for conformance to Unicode 3.2. The effort is part of
+the Slavjanskij package for Mac OS X,
+<http://www.versiontracker.com/dyn/moreinfo/macosx/18680>.
+
+	Cyrillic				(U+0400-U+04FF)
+
+
+* Denis Jacquerye <moyogo AT gmail.com>
+
+Denis Jacquerye added new glyphs and corrected existing ones in the
+Latin Extended-B and IPA Extensions ranges.
+
+	Latin Extended-B                        (U+0180-U+024F)
+	IPA Extensions				(U+0250-U+02AF)
+
+
+* K.H. Hussain <hussain AT kfri.org> and R. Chitrajan
+
+`Rachana' in Malayalam means `to write', `to create'. Rachana Akshara
+Vedi, a team of socially committed information technology
+professionals and philologists, has applied developments in computer
+technology and desktop publishing to resurrect the Malayalam language
+from the disorder, fragmentation and degeneration it had suffered
+since the attempt to adapt the Malayalam script for using with a
+regular mechanical typewriter, which took place in
+1967-69. K.H. Hussein at the Kerala Forest Research Institute has
+released "Rachana Normal" fonts with approximately 900 glyphs required
+to typeset traditional Malayalam. R. Chitrajan apparently encoded the
+glyphs in the OpenType table.
+
+	Malayalam				(U+0D00-U+0D7F)
+
+
+* Solaiman Karim <solaiman AT ekushey.org>
+
+	Bengali					(U+0980-U+09FF)
+
+Solaiman Karim has developed several OpenType Bangla fonts and
+released them under GNU GPL on www.ekushey.org.
+
+
+* Sonali Sonania <sonalisonania AT gmail.com> and Monika Shah
+  <monikapatira AT gmail.com>
+
+	Devanagari				(U+0900-U+097F)
+	Gujarati				(U+0A80-U+0AFF)
+
+Glyphs were drawn by Cyberscape Multimedia Ltd., #101,Mahalakshmi
+Mansion 21st Main 22nd "A" Cross Banashankari 2nd stage Banglore
+560070, India. Converted to OTF by IndicTrans Team, Powai, Mumbai,
+lead by Prof. Jitendra Shah. Maintained by Monika Shah and Sonali
+Sonania of janabhaaratii Team, C-DAC, Mumbai. This font is released
+under GPL by Dr. Alka Irani and Prof Jitendra Shah, janabhaaratii
+Team, C-DAC, Mumabi. janabhaaratii is localisation project at C-DAC
+Mumbai (formerly National Centre for Software Technology); funded by
+TDIL, Govt. of India. Contact:monika_shah AT lycos.com,
+sonalisonania AT yahoo.com, jitendras AT vsnl.com, alka AT ncst.ernet.in.
+website: www.janabhaaratii.org.in.
+
+
+* Pravin Satpute <pravin_ind21 AT hotmail.com>, Bageshri Salvi
+  <sbagrshri AT yahoo.co.in>, Rahul Bhalerao <rahul_pb_india AT
+  yahoo.com> and Sandeep Shedmake <surgs2k47 AT yahoo.co.in>
+
+	Devanagari				(U+0900-U+097F)
+	Gujarati				(U+0A80-U+0AFF)
+	Oriya					(U+0B00-U+0B7F)
+	Malayalam				(U+0D00-U+0D7F)
+	Tamil					(U+0B80-U+0BFF)
+
+In December 2005 the team at www.gnowledge.org released a set of two
+Unicode pan-Indic fonts: "Samyak" and "Samyak Sans". "Samyak" font
+belongs to serif style and is an original work of the team; "Samyak
+Sans" font belongs to sans serif style and is actually a compilation
+of already released Indic fonts (Gargi, Padma, Mukti, Utkal, Akruti
+and ThendralUni). Both fonts are based on Unicode standard. You can
+download the font files (released under GNU/GPL License) from
+http://www.gnowledge.org/Gnoware/localization/font.htm
+
+
+* Kulbir Singh Thind
+
+	Gurmukhi				(U+0A00-U+0A7F)
+
+Dr. Kulbir Singh Thind designed a set of Gurmukhi Unicode fonts,
+AnmolUni and AnmolUni-Bold, which are available under the terms of GNU
+Generel Public Licens from the Punjabu Computing Resource Center,
+http://guca.sourceforge.net/typography/fonts/anmoluni/.
+
+
+* Gia Shervashidze <giasher AT telenet.ge>
+
+        Georgian				(U+10A0-U+10FF)
+
+Starting in mid-1990s, Gia Shervashidze designed many
+Unicode-compliant Georgian fonts: Times New Roman Georgian, Arial
+Georgian, Courier New Georgian. His work on Georgian localization can
+be reached at http://www.gia.ge/.
+
+
+* Primož Peterlin <primoz.peterlin AT biofiz.mf.uni-lj.si>
+
+Primož Peterlin filled in missing glyphs here and there (e.g. Latin
+Extended-B and IPA Extensions ranges in the FreeMono familiy), and
+created the following UCS blocks:
+
+	Latin Extended-B                        (U+0180-U+024F)
+	IPA Extensions				(U+0250-U+02AF)
+	Arrows					(U+2190-U+21FF)
+	Box Drawing				(U+2500-U+257F)
+	Block Elements				(U+2580-U+259F)
+	Geometrical Shapes			(U+25A0-U+25FF)
+
+* Mark Williamson
+
+Made the MPH 2 Damase font, from which 
+	Hanunóo
+	Buginese
+	Tai Le
+	Ugaritic
+	Old Persian
+
+* Jacob Poon
+
+Submitted a very thorough survey of glyph problems and other suggestions.
+
+* Alexey Kryukov made the TemporaLCGUni fonts, based on the URW++ fonts,
+  from which most of the FreeSerif Cyrillic, and some of the Greek, is drawn.
+  He also provided valuable direction about Cyrillic and Greed typesetting.
+
+Notes:
+
+*: The glyph collection looks license-compatible, but its author has
+   not yet replied and agreed on his/her work being used in part of
+   this glyph collection.
+
+--------------------------------------------------------------------------
+$Id: CREDITS,v 1.17 2008/08/30 09:31:54 Stevan_White Exp $
diff --git a/songmanagement/game/fonts/FreeSans/FreeSans.ttf b/songmanagement/game/fonts/FreeSans/FreeSans.ttf
new file mode 100644
index 00000000..a4c41697
Binary files /dev/null and b/songmanagement/game/fonts/FreeSans/FreeSans.ttf differ
diff --git a/songmanagement/game/fonts/FreeSans/FreeSansBold.ttf b/songmanagement/game/fonts/FreeSans/FreeSansBold.ttf
new file mode 100644
index 00000000..15511674
Binary files /dev/null and b/songmanagement/game/fonts/FreeSans/FreeSansBold.ttf differ
diff --git a/songmanagement/game/fonts/FreeSans/README b/songmanagement/game/fonts/FreeSans/README
new file mode 100644
index 00000000..96e4a4db
--- /dev/null
+++ b/songmanagement/game/fonts/FreeSans/README
@@ -0,0 +1,108 @@
+-*-text-*-
+                          GNU FreeFont
+
+The GNU FreeFont project aims to provide a useful set of free scalable
+(i.e., OpenType) fonts covering as much as possible of the ISO 10646/Unicode
+UCS (Universal Character Set).
+
+Statement of Purpose
+--------------------
+
+The practical reason for putting glyphs together in a single font face is
+to conveniently mix symbols and characters from different writing systems,
+without having to switch fonts.
+
+Coverage
+--------
+
+FreeFont covers the following character sets
+
+* ISO 8859 parts 1-15
+* CEN MES-3 European Unicode Subset
+  http://www.evertype.com/standards/iso10646/pdf/cwa13873.pdf
+* IBM/Microsoft code pages 437, 850, 852, 1250, 1252 and more
+* Microsoft/Adobe Windows Glyph List 4 (WGL4)
+  http://www.microsoft.com/typography/otspec/WGL4.htm
+* KOI8-R and KOI8-RU
+* DEC VT100 graphics symbols
+* International Phonetic Alphabet
+* Arabic, Hebrew, Armenian, Georgian, Ethiopian and Thai alphabets,
+  including Arabic presentation forms A/B
+* mathematical symbols, including the whole TeX repertoire of symbols
+* APL symbols
+  etc.
+
+Editing
+-------
+
+The free outline font editor, George Williams's FontForge
+<http://fontforge.sourceforge.net/> is used for editing the fonts.
+
+Design Issues
+-------------
+
+Which font shapes should be made?  Historical style terms like Renaissance
+or Baroque letterforms cannot be applied beyond Latin/Cyrillic/Greek
+scripts to any greater extent than Kufi or Nashki can be applied beyond
+Arabic script; "italic" is really only meaningful for Latin letters. 
+
+However, most modern writing systems have typographic formulations for
+contrasting uniform and modulated character stroke widths, and have some
+history with "oblique", faces.  Since the advent of the typewriter, most
+have developed a typographic style with uniform-width characters.
+
+Accordingly, the FreeFont family has one monospaced - FreeMono - and two
+proportional faces (one with uniform stroke - FreeSans - and one with
+modulated stroke - FreeSerif).
+
+To make text from different writing systems look good side-by-side, each
+FreeFont face is meant to contain characters of similar style and weight.
+
+Licensing
+---------
+
+Free UCS scalable fonts is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published
+by the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+The fonts are distributed in the hope that they will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+As a special exception, if you create a document which uses this font, and
+embed this font or unaltered portions of this font into the document, this
+font does not by itself cause the resulting document to be covered by the
+GNU General Public License. This exception does not however invalidate any
+other reasons why the document might be covered by the GNU General Public
+License. If you modify this font, you may extend this exception to your
+version of the font, but you are not obligated to do so.  If you do not
+wish to do so, delete this exception statement from your version.
+
+
+Files and their suffixes
+------------------------
+
+The files with .sfd (Spline Font Database) are in FontForge's native format. 
+Please use these if you plan to modify the font files.
+
+TrueType fonts for immediate consumption are the files with the .ttf
+(TrueType Font) suffix.  These are ready to use in Xwindows based
+systems using FreeType, on Mac OS, and on older Windows systems.
+
+OpenType fonts (with suffix .otf) are for use in Windows Vista. 
+Note that although they can be installed on Linux, but many applications
+in Linux still don't support them.
+
+
+--------------------------------------------------------------------------
+Primoz Peterlin, <primoz.peterlin@biofiz.mf.uni-lj.si>
+Steve White <stevan.white@googlemail.com>
+
+Free UCS scalable fonts: http://savannah.gnu.org/projects/freefont/
+$Id: README,v 1.5 2008/08/30 09:30:09 Stevan_White Exp $
diff --git a/songmanagement/game/fonts/fonts.ini b/songmanagement/game/fonts/fonts.ini
new file mode 100755
index 00000000..f152852d
--- /dev/null
+++ b/songmanagement/game/fonts/fonts.ini
@@ -0,0 +1,56 @@
+;+++++++++++++++++++++++++++++++++++++++++++++++++
+; UltraStar Deluxe font configuration file
+;-------------------------------------------------
+; Format:
+;-------------------------------------------------
+;[Font_XYZ]
+;# the font file
+;File=Filename 
+;# space between glyphs (default: 0.0)
+;GlyphSpacing=float
+;# width stretch factor (default: 1.0)
+;Stretch=float
+;# makes the font more bold (default: 0.0). Not used if Outline > 0.0.
+;Embolden=float(>=0.0)
+;# draws an outline around the glyph
+;Outline=float(>=0.0)
+;# outline color components (default: 0.0/0.0/0.0/-1.0)
+;OutlineColorR/G/B=float([0..1])
+;# outline alpha, -1.0 for alpha of interior (default: -1.0)
+;OutlineColorA=float([0..1] or -1)
+;
+;[Font_...]
+;...
+;
+; Fonts that are used in case a character can't be found in the regular font.
+; This is used to display Japanese characters.
+;[Fallbacks]
+;File1=xy.ttf
+;File2=...
+;...
+;+++++++++++++++++++++++++++++++++++++++++++++++++
+
+[Font_Normal]
+File=FreeSans/FreeSans.ttf
+;GlyphSpacing=1.4
+;Stretch=1.2
+
+[Font_Bold]
+File=FreeSans/FreeSansBold.ttf
+;Embolden=0.06
+
+[Font_Outline1]
+File=DejaVu/DejaVuSans-Bold.ttf
+Outline=0.06
+;OutlineColorR=0.3
+;OutlineColorG=0.3
+;OutlineColorB=0.3
+;OutlineColorA=0.3
+
+[Font_Outline2]
+File=FreeSans/FreeSansBold.ttf
+Outline=0.06
+
+[Fallbacks]
+File1=wqy-microhei/wqy-microhei.ttc
+;File2=C:/Windows/Fonts/simsun.ttc
diff --git a/songmanagement/game/fonts/wqy-microhei/AUTHORS.txt b/songmanagement/game/fonts/wqy-microhei/AUTHORS.txt
new file mode 100644
index 00000000..d19d4cad
--- /dev/null
+++ b/songmanagement/game/fonts/wqy-microhei/AUTHORS.txt
@@ -0,0 +1,12774 @@
+==========================================================
+
+                 Wen Quan Yi Micro Hei
+
+               Contributors and Credits
+
+----------------------------------------------------------
+Email obfuscators:
+   replace " #" to "@" , replace " _" to "."
+----------------------------------------------------------
+
+Summary:
+
+ This font package is copyrighted by the WenQuanYi Board of Trustees 2008-2009
+               ( http://wenq.org/index.cgi?WQYBOT );
+           Digitized data copyright � 2007, Google Corporation.
+
+----------------------------------------------------------
+
+Table of Content
+
+ I.   Previous Work
+ II.  WenQuanYi MicroHei Developers
+ III. Revision History for On-line Applications Related to MicroHei
+ V.   Detailed Contributor List and Update Log
+
+----------------------------------------------------------
+
+ I.  Previous Work
+
+    1. WenQuanYi Micro Hei is derived from Google Droid font family
+       shipped in Android SDK (1.0); the source of the font files includes
+       Droid Sans Fallback, Droid Sans and Droid Sans Mono.
+
+    2. some Chinese punctuations were imported from Ume-Font
+       Copyright (c) 1990-2003 Wada Laboratory, the University of Tokyo.
+                     All rights reserved.
+       Copyright (c) 2003-2004 Electronic Font Open Laboratory (/efont/).
+                     All rights reserved.
+
+----------------------------------------------------------
+
+ II. WenQuanYi Vector Font Key Developers
+
+
+   Qianqian Fang[FangQ] (fangq #nmr _mgh _harvard _edu), project maintainer
+   mozbug (mozbugbox #yahoo _com _au), MicroHei project co-maintainer
+
+   Review panel:
+     lsz  (chinatslsz #hotmail _com)
+     pem  (archx #l63 _com)
+     wh
+     kmc
+     Xhacker
+     philacorns
+
+----------------------------------------------------------
+
+ III. Revision History for On-line Applications Related to MicroHei
+
+;Bezier_lib.js:   http://wenq.org/index.cgi?action=history&id=Bezier_lib.js
+;BezierGlyph:     http://wenq.org/index.cgi?action=history&id=BezierGlyph
+;Fontopia(cn):    http://wenq.org/index.cgi?action=history&id=Fontopia(cn)
+;Bezier_lib_FangQ.js:http://wenq.org/index.cgi?action=history&id=Bezier_lib_Fang
+Q.js
+
+----------------------------------------------------------
+
+ V.   Detailed Contributor List and Update Log
+
+The following list records in chronicle order all the received submissions
+with their corresponding author name and time.
+
+ Unicode      Author         Date         Revision
+----------------------------------------------------------
+
+
+U6DC1	FangQ	2008-11-23 (1)
+U4F72	FangQ	2008-11-23 (1)
+U8ACE	FangQ	2008-11-23 (1)
+U6036	FangQ	2008-11-23 (1)
+U92FD	FangQ	2008-11-23 (1)
+U986D	FangQ	2008-11-23 (1)
+U8688	FangQ	2008-11-23 (1)
+U6640	FangQ	2008-11-23 (1)
+U58E6	FangQ	2008-11-23 (1)
+U8BAC	FangQ	2008-11-23 (1)
+U816A	FangQ	2008-11-23 (1)
+U5FDB	FangQ	2008-11-23 (1)
+U82FC	FangQ	2008-11-23 (1)
+U85AD	FangQ	2008-11-23 (1)
+U79C7	FangQ	2008-11-23 (1)
+U5AE7	FangQ	2008-11-23 (1)
+U7717	FangQ	2008-11-23 (1)
+U8B38	FangQ	2008-11-23 (1)
+U9575	FangQ	2008-11-23 (1)
+U5A79	FangQ	2008-11-23 (1)
+U5A79	FangQ	2008-11-23 (2)
+U9D0D	FangQ	2008-11-23 (1)
+U79A3	FangQ	2008-11-23 (1)
+U7858	lsz	2008-11-23 (1)
+U6D71	lsz	2008-11-23 (1)
+U8A65	lsz	2008-11-23 (1)
+U78C0	pem	2008-11-24 (1)
+U6E04	FangQ	2008-11-25 (1)
+U6E04	FangQ	2008-11-25 (2)
+U6C91	FangQ	2008-11-25 (1)
+U56E6	FangQ	2008-11-25 (1)
+U7BB2	FangQ	2008-11-25 (1)
+U8E46	FangQ	2008-11-25 (1)
+U9AC9	lsz	2008-11-25 (1)
+U5803	lsz	2008-11-25 (1)
+U6082	lsz	2008-11-25 (1)
+U4FB8	lsz	2008-11-25 (1)
+U7484	lsz	2008-11-25 (1)
+U9DC0	anonymous	2008-11-25 (1)
+U55D8	pem	2008-11-26 (1)
+U8C38	pem	2008-11-26 (1)
+U994A	pem	2008-11-26 (1)
+U7BFA	pem	2008-11-26 (1)
+U713D	pem	2008-11-27 (1)
+U7882	lsz	2008-11-27 (1)
+U6711	lsz	2008-11-27 (1)
+U54E3	pem	2008-11-28 (1)
+U5D56	pem	2008-11-28 (1)
+U7374	pem	2008-11-28 (1)
+U7374	pem	2008-11-28 (2)
+U7BD7	pem	2008-11-28 (1)
+U5081	mozbug	2008-11-29 (1)
+U93C1	pem	2008-11-29 (1)
+U72DD	pem	2008-11-29 (1)
+U80A7	pem	2008-11-29 (1)
+U78C0	mozbug	2008-11-29 (2)
+U7863	pem	2008-11-29 (1)
+U53DC	pem	2008-11-29 (1)
+U5CC3	pem	2008-11-29 (1)
+U78C0	FangQ	2008-11-29 (3)
+U8419	pem	2008-11-29 (1)
+U53DC	FangQ	2008-11-29 (2)
+U7694	FangQ	2008-11-29 (1)
+U7694	FangQ	2008-11-29 (2)
+U7694	FangQ	2008-11-29 (3)
+U70AA	FangQ	2008-11-29 (1)
+U7453	FangQ	2008-11-29 (1)
+U8EBB	FangQ	2008-11-29 (1)
+U9C53	FangQ	2008-11-29 (1)
+U7013	FangQ	2008-11-29 (1)
+U513E	FangQ	2008-11-29 (1)
+U513E	FangQ	2008-11-29 (2)
+U513E	FangQ	2008-11-29 (3)
+U5CE3	lsz	2008-11-29 (1)
+U9C69	lsz	2008-11-29 (1)
+U8AA2	mozbug	2008-11-30 (1)
+U6646	pem	2008-11-30 (1)
+U9C6B	pem	2008-11-30 (1)
+U5FE9	pem	2008-12-1 (1)
+U7B07	pem	2008-12-1 (1)
+U7FDA	pem	2008-12-2 (1)
+U6228	pem	2008-12-2 (1)
+U680D	pem	2008-12-2 (1)
+U79E5	pem	2008-12-2 (1)
+U9228	pem	2008-12-2 (1)
+U57B7	pem	2008-12-2 (1)
+U9B50	pem	2008-12-2 (1)
+U9B50	pem	2008-12-2 (2)
+U7819	pem	2008-12-2 (1)
+U5405	pem	2008-12-2 (1)
+U9B50	FangQ	2008-12-2 (3)
+U9B50	FangQ	2008-12-2 (4)
+U6202	pem	2008-12-2 (1)
+U4FF0	pem	2008-12-2 (1)
+U9BEE	pem	2008-12-2 (1)
+U6A63	pem	2008-12-2 (1)
+U6A63	pem	2008-12-2 (2)
+U6A63	pem	2008-12-2 (3)
+U6A63	pem	2008-12-2 (4)
+U6A63	pem	2008-12-2 (5)
+U6A63	pem	2008-12-2 (6)
+U6A63	pem	2008-12-2 (7)
+U8267	pem	2008-12-2 (1)
+U7E19	pem	2008-12-3 (1)
+U52D1	FangQ	2008-12-3 (1)
+U869B	FangQ	2008-12-3 (1)
+U76B3	pem	2008-12-3 (1)
+U8C09	pem	2008-12-3 (1)
+U7B89	pem	2008-12-3 (1)
+U7B89	pem	2008-12-3 (2)
+U50B9	anonymous	2008-12-4 (1)
+U50B9	anonymous	2008-12-4 (2)
+U65D1	anonymous	2008-12-4 (1)
+U8A7D	anonymous	2008-12-4 (1)
+U6A63	pem	2008-12-4 (8)
+U7B89	pem	2008-12-4 (3)
+U5D09	pem	2008-12-4 (1)
+U50A4	pem	2008-12-4 (1)
+U5010	pem	2008-12-5 (1)
+U65D1	pem	2008-12-5 (2)
+U5010	mozbug	2008-12-5 (2)
+U8185	pem	2008-12-5 (1)
+U50A0	pem	2008-12-5 (1)
+U50A0	pem	2008-12-5 (2)
+U50A0	pem	2008-12-5 (3)
+U50A0	pem	2008-12-5 (4)
+U5558	pem	2008-12-5 (1)
+U77C8	pem	2008-12-5 (1)
+U8321	FangQ	2008-12-6 (1)
+U6CFF	FangQ	2008-12-6 (1)
+U8A2B	FangQ	2008-12-6 (1)
+U6637	FangQ	2008-12-6 (1)
+U6337	FangQ	2008-12-6 (1)
+U75AD	FangQ	2008-12-6 (1)
+U75AD	FangQ	2008-12-6 (2)
+U75AD	FangQ	2008-12-6 (3)
+U75AD	FangQ	2008-12-6 (4)
+U5846	FangQ	2008-12-7 (1)
+U5846	FangQ	2008-12-7 (2)
+U556B	pem	2008-12-8 (1)
+U64B4	pem	2008-12-8 (1)
+U7764	pem	2008-12-8 (1)
+U7764	FangQ	2008-12-8 (2)
+U98FF	pem	2008-12-9 (1)
+U88AF	pem	2008-12-9 (1)
+U628B	wanghong	2008-12-10 (1)
+U79F1	FangQ	2008-12-10 (1)
+U9F14	FangQ	2008-12-10 (1)
+U8866	FangQ	2008-12-10 (1)
+U7804	FangQ	2008-12-10 (1)
+U79D9	FangQ	2008-12-10 (1)
+U8C9B	FangQ	2008-12-10 (1)
+U5FD3	FangQ	2008-12-10 (1)
+U5FD3	FangQ	2008-12-10 (2)
+U7CE4	FangQ	2008-12-10 (1)
+U9292	FangQ	2008-12-10 (1)
+U65C8	FangQ	2008-12-10 (1)
+U4F44	FangQ	2008-12-10 (1)
+U5E46	FangQ	2008-12-10 (1)
+U605C	pem	2008-12-11 (1)
+U9AA6	pem	2008-12-11 (1)
+U545E	wanghong	2008-12-11 (1)
+U5BC8	pem	2008-12-11 (1)
+U9CE1	pem	2008-12-12 (1)
+U9CE1	pem	2008-12-12 (2)
+U7105	pem	2008-12-12 (1)
+U9A26	pem	2008-12-12 (1)
+U71F6	pem	2008-12-12 (1)
+U5E49	pem	2008-12-12 (1)
+U5E48	pem	2008-12-12 (1)
+U917B	lsz	2008-12-13 (1)
+U9ABD	lsz	2008-12-13 (1)
+U5C1B	lsz	2008-12-13 (1)
+U8F92	lsz	2008-12-13 (1)
+U6FF8	lsz	2008-12-13 (1)
+U6FF8	lsz	2008-12-13 (2)
+U6FF8	lsz	2008-12-13 (3)
+U5C21	FangQ	2008-12-13 (1)
+U9BB0	FangQ	2008-12-13 (1)
+U9BB0	FangQ	2008-12-13 (2)
+U9BED	FangQ	2008-12-13 (1)
+U5BC8	FangQ	2008-12-13 (2)
+U942D	FangQ	2008-12-13 (1)
+U68C1	FangQ	2008-12-13 (1)
+U509F	FangQ	2008-12-13 (1)
+U6BE5	FangQ	2008-12-13 (1)
+U55DE	FangQ	2008-12-13 (1)
+U8A20	FangQ	2008-12-13 (1)
+U6EB8	FangQ	2008-12-13 (1)
+U6E87	FangQ	2008-12-13 (1)
+U8A5A	FangQ	2008-12-13 (1)
+U51B8	FangQ	2008-12-13 (1)
+U63E2	pem	2008-12-14 (1)
+U8149	pem	2008-12-14 (1)
+U758D	anonymous	2008-12-14 (1)
+U6E8B	anonymous	2008-12-14 (1)
+U5234	anonymous	2008-12-14 (1)
+U6030	anonymous	2008-12-14 (1)
+U9789	anonymous	2008-12-14 (1)
+U7E02	anonymous	2008-12-14 (1)
+U635D	anonymous	2008-12-14 (1)
+U937D	anonymous	2008-12-14 (1)
+U9789	FangQ	2008-12-14 (2)
+U9904	pem	2008-12-14 (1)
+U567D	pem	2008-12-14 (1)
+U7EE4	pem	2008-12-14 (1)
+U5C36	pem	2008-12-14 (1)
+U5FA4	FangQ	2008-12-15 (1)
+U5CE7	FangQ	2008-12-15 (1)
+U7245	FangQ	2008-12-15 (1)
+U8A29	FangQ	2008-12-15 (1)
+U5661	FangQ	2008-12-15 (1)
+U8A5C	FangQ	2008-12-15 (1)
+U9937	FangQ	2008-12-15 (1)
+U8B7C	FangQ	2008-12-15 (1)
+U5E35	FangQ	2008-12-15 (1)
+U5573	FangQ	2008-12-15 (1)
+U824C	FangQ	2008-12-15 (1)
+U66C2	FangQ	2008-12-16 (1)
+U51BF	FangQ	2008-12-16 (1)
+U835D	FangQ	2008-12-16 (1)
+U835D	FangQ	2008-12-16 (2)
+U6C45	FangQ	2008-12-16 (1)
+U9B63	FangQ	2008-12-16 (1)
+U60C2	FangQ	2008-12-16 (1)
+U5D08	FangQ	2008-12-16 (1)
+U58C0	FangQ	2008-12-16 (1)
+U630A	FangQ	2008-12-16 (1)
+U62E4	FangQ	2008-12-16 (1)
+U4F99	FangQ	2008-12-16 (1)
+U9289	FangQ	2008-12-16 (1)
+U9D35	FangQ	2008-12-16 (1)
+U9D35	FangQ	2008-12-16 (2)
+U58D0	FangQ	2008-12-17 (1)
+U6946	FangQ	2008-12-17 (1)
+U8EB3	FangQ	2008-12-17 (1)
+U8900	FangQ	2008-12-17 (1)
+U7F0A	FangQ	2008-12-17 (1)
+U7543	FangQ	2008-12-17 (1)
+U94D4	pem	2008-12-17 (1)
+U99DE	FangQ	2008-12-17 (1)
+U9964	FangQ	2008-12-17 (1)
+U7A21	FangQ	2008-12-17 (1)
+U60D7	FangQ	2008-12-17 (1)
+U5B79	anonymous	2008-12-17 (1)
+U71DD	anonymous	2008-12-17 (1)
+U71DD	FangQ	2008-12-17 (2)
+U9040	wanghong	2008-12-17 (1)
+U9040	wanghong	2008-12-17 (2)
+U50FC	FangQ	2008-12-17 (1)
+U91B6	FangQ	2008-12-17 (1)
+U959A	FangQ	2008-12-17 (1)
+U79AF	FangQ	2008-12-17 (1)
+U8D97	FangQ	2008-12-17 (1)
+U9B6E	FangQ	2008-12-17 (1)
+U6235	FangQ	2008-12-17 (1)
+U8A9C	FangQ	2008-12-17 (1)
+U607E	FangQ	2008-12-17 (1)
+U9C80	FangQ	2008-12-17 (1)
+U997B	FangQ	2008-12-17 (1)
+U9CC0	FangQ	2008-12-17 (1)
+U9EAF	FangQ	2008-12-17 (1)
+U6D9A	FangQ	2008-12-17 (1)
+U9CD2	FangQ	2008-12-17 (1)
+U58C3	FangQ	2008-12-17 (1)
+U9906	FangQ	2008-12-17 (1)
+U71F7	FangQ	2008-12-18 (1)
+U6188	FangQ	2008-12-18 (1)
+U5EF5	FangQ	2008-12-18 (1)
+U6091	FangQ	2008-12-18 (1)
+U990F	FangQ	2008-12-18 (1)
+U50FA	FangQ	2008-12-18 (1)
+U6D5B	FangQ	2008-12-18 (1)
+U7774	FangQ	2008-12-18 (1)
+U9A5C	FangQ	2008-12-18 (1)
+U66D7	FangQ	2008-12-18 (1)
+U5E92	pem	2008-12-18 (1)
+U5EA1	FangQ	2008-12-18 (1)
+U7ACC	FangQ	2008-12-18 (1)
+U66CD	FangQ	2008-12-18 (1)
+U76A2	FangQ	2008-12-18 (1)
+U8EED	FangQ	2008-12-18 (1)
+U93DB	FangQ	2008-12-18 (1)
+U93CB	FangQ	2008-12-18 (1)
+U6AFF	FangQ	2008-12-18 (1)
+U87D6	FangQ	2008-12-18 (1)
+U87A6	FangQ	2008-12-18 (1)
+U9235	FangQ	2008-12-18 (1)
+U78EB	FangQ	2008-12-18 (1)
+U7DB3	FangQ	2008-12-18 (1)
+U9BEF	FangQ	2008-12-18 (1)
+U58C4	FangQ	2008-12-18 (1)
+U631C	FangQ	2008-12-18 (1)
+U631C	FangQ	2008-12-18 (2)
+U5667	FangQ	2008-12-18 (1)
+U73C1	FangQ	2008-12-18 (1)
+U9C70	FangQ	2008-12-18 (1)
+U8684	FangQ	2008-12-18 (1)
+U58E0	FangQ	2008-12-18 (1)
+U7390	FangQ	2008-12-18 (1)
+U636C	FangQ	2008-12-18 (1)
+U7E00	FangQ	2008-12-18 (1)
+U8142	FangQ	2008-12-18 (1)
+U8137	FangQ	2008-12-18 (1)
+U9A4B	FangQ	2008-12-18 (1)
+U8955	FangQ	2008-12-18 (1)
+U67D5	FangQ	2008-12-18 (1)
+U6CDF	FangQ	2008-12-18 (1)
+U9BFA	FangQ	2008-12-18 (1)
+U77D6	FangQ	2008-12-18 (1)
+U77D6	FangQ	2008-12-18 (2)
+U55FB	FangQ	2008-12-18 (1)
+U4F6D	FangQ	2008-12-18 (1)
+U57B1	FangQ	2008-12-18 (1)
+U7A72	FangQ	2008-12-18 (1)
+U9C83	FangQ	2008-12-18 (1)
+U92B8	FangQ	2008-12-18 (1)
+U78E6	FangQ	2008-12-18 (1)
+U9427	FangQ	2008-12-18 (1)
+U9C42	FangQ	2008-12-18 (1)
+U5D13	FangQ	2008-12-18 (1)
+U9222	FangQ	2008-12-18 (1)
+U9222	FangQ	2008-12-18 (2)
+U7E06	FangQ	2008-12-18 (1)
+U6F3D	FangQ	2008-12-18 (1)
+U670C	FangQ	2008-12-18 (1)
+U5D1C	FangQ	2008-12-18 (1)
+U8D52	FangQ	2008-12-18 (1)
+U74BC	FangQ	2008-12-18 (1)
+U7E2C	FangQ	2008-12-18 (1)
+U9CC1	FangQ	2008-12-18 (1)
+U70CC	FangQ	2008-12-18 (1)
+U6DCE	FangQ	2008-12-19 (1)
+U7CB0	FangQ	2008-12-19 (1)
+U6471	FangQ	2008-12-19 (1)
+U67F9	FangQ	2008-12-19 (1)
+U5245	FangQ	2008-12-19 (1)
+U57BB	FangQ	2008-12-19 (1)
+U4FBC	FangQ	2008-12-19 (1)
+U7B21	FangQ	2008-12-19 (1)
+U9A3B	FangQ	2008-12-19 (1)
+U9BCB	FangQ	2008-12-19 (1)
+U9A21	FangQ	2008-12-19 (1)
+U7088	anonymous	2008-12-19 (1)
+U664D	anonymous	2008-12-19 (1)
+U71DE	pem	2008-12-19 (1)
+U5570	pem	2008-12-19 (1)
+U71B7	FangQ	2008-12-19 (1)
+U6E70	FangQ	2008-12-19 (1)
+U8055	FangQ	2008-12-19 (1)
+U5A21	FangQ	2008-12-19 (1)
+U88EA	FangQ	2008-12-19 (1)
+U81AF	FangQ	2008-12-19 (1)
+U9BCC	FangQ	2008-12-19 (1)
+U5D0A	FangQ	2008-12-19 (1)
+U7265	FangQ	2008-12-19 (1)
+U7107	FangQ	2008-12-19 (1)
+U5034	FangQ	2008-12-19 (1)
+U77A4	FangQ	2008-12-19 (1)
+U6819	FangQ	2008-12-19 (1)
+U9198	FangQ	2008-12-19 (1)
+U9E1C	FangQ	2008-12-19 (1)
+U5B6D	FangQ	2008-12-19 (1)
+U5647	FangQ	2008-12-19 (1)
+U874A	FangQ	2008-12-19 (1)
+U7328	FangQ	2008-12-19 (1)
+U57D7	FangQ	2008-12-19 (1)
+U54EF	FangQ	2008-12-19 (1)
+U92AF	pem	2008-12-20 (1)
+U9626	pem	2008-12-20 (1)
+U7E4E	wanghong	2008-12-20 (1)
+U511D	wanghong	2008-12-20 (1)
+U6A6C	wanghong	2008-12-20 (1)
+U8B34	wanghong	2008-12-20 (1)
+U50A6	wanghong	2008-12-20 (1)
+U6008	wanghong	2008-12-20 (1)
+U962B	wanghong	2008-12-20 (1)
+U9C84	adsl123456	2008-12-20 (1)
+U97B5	adsl123456	2008-12-20 (1)
+U7844	adsl123456	2008-12-20 (1)
+U572B	adsl123456	2008-12-20 (1)
+U7593	adsl123456	2008-12-20 (1)
+U65BE	adsl123456	2008-12-20 (1)
+U9BCD	adsl123456	2008-12-20 (1)
+U4F35	adsl123456	2008-12-20 (1)
+U6648	adsl123456	2008-12-20 (1)
+U5A82	adsl123456	2008-12-20 (1)
+U5A6E	adsl123456	2008-12-20 (1)
+U5F75	adsl123456	2008-12-20 (1)
+U7C99	adsl123456	2008-12-20 (1)
+U9BCD	FangQ	2008-12-20 (2)
+U7D64	FangQ	2008-12-20 (1)
+U573F	FangQ	2008-12-20 (1)
+U79F3	FangQ	2008-12-20 (1)
+U73EF	FangQ	2008-12-20 (1)
+U58F8	FangQ	2008-12-20 (1)
+U67C7	FangQ	2008-12-20 (1)
+U6767	FangQ	2008-12-20 (1)
+U7CA0	FangQ	2008-12-20 (1)
+U9BCE	FangQ	2008-12-20 (1)
+U5B2B	FangQ	2008-12-20 (1)
+U6F8F	FangQ	2008-12-20 (1)
+U7412	FangQ	2008-12-20 (1)
+U6B30	FangQ	2008-12-20 (1)
+U80DF	FangQ	2008-12-20 (1)
+U71AB	FangQ	2008-12-20 (1)
+U68E2	FangQ	2008-12-20 (1)
+U5A28	FangQ	2008-12-20 (1)
+U6330	FangQ	2008-12-20 (1)
+U8F65	FangQ	2008-12-20 (1)
+U6E57	FangQ	2008-12-20 (1)
+U5E50	FangQ	2008-12-20 (1)
+U5C7D	FangQ	2008-12-20 (1)
+U99BE	FangQ	2008-12-20 (1)
+U88A3	FangQ	2008-12-20 (1)
+U9D1A	FangQ	2008-12-20 (1)
+U8196	FangQ	2008-12-20 (1)
+U8287	FangQ	2008-12-20 (1)
+U9C5B	FangQ	2008-12-20 (1)
+U808D	FangQ	2008-12-20 (1)
+U57BE	FangQ	2008-12-20 (1)
+U7271	FangQ	2008-12-20 (1)
+U593D	FangQ	2008-12-20 (1)
+U5B4F	FangQ	2008-12-20 (1)
+U7EBC	FangQ	2008-12-20 (1)
+U8C8B	FangQ	2008-12-20 (1)
+U9D24	FangQ	2008-12-20 (1)
+U715B	FangQ	2008-12-20 (1)
+U5A63	FangQ	2008-12-20 (1)
+U7F41	FangQ	2008-12-20 (1)
+U9317	FangQ	2008-12-20 (1)
+U756E	wanghong	2008-12-20 (1)
+U9BFF	wanghong	2008-12-20 (1)
+U581F	wanghong	2008-12-20 (1)
+U83ED	wanghong	2008-12-20 (1)
+U930A	wanghong	2008-12-20 (1)
+U97A7	wanghong	2008-12-20 (1)
+U7D87	wanghong	2008-12-20 (1)
+U770E	wanghong	2008-12-20 (1)
+U62A7	wanghong	2008-12-20 (1)
+U5CB4	wanghong	2008-12-20 (1)
+U7AF4	mozbug	2008-12-20 (1)
+U87A0	pem	2008-12-20 (1)
+U5E39	pem	2008-12-20 (1)
+U5E3A	mozbug	2008-12-20 (1)
+U6E6A	anonymous	2008-12-21 (1)
+U6E6A	anonymous	2008-12-21 (2)
+U7348	anonymous	2008-12-21 (1)
+U771C	anonymous	2008-12-21 (1)
+U61A3	anonymous	2008-12-21 (1)
+U5FDA	anonymous	2008-12-21 (1)
+U5579	anonymous	2008-12-21 (1)
+U726B	anonymous	2008-12-21 (1)
+U52BA	anonymous	2008-12-21 (1)
+U71E3	mozbug	2008-12-21 (1)
+U7135	mozbug	2008-12-21 (1)
+U921D	mozbug	2008-12-21 (1)
+U7AFC	mozbug	2008-12-21 (1)
+U5D10	mozbug	2008-12-21 (1)
+U93E9	mozbug	2008-12-21 (1)
+U6A2D	anonymous	2008-12-21 (1)
+U7BC8	anonymous	2008-12-21 (1)
+U92BE	mozbug	2008-12-21 (1)
+U6438	mozbug	2008-12-21 (1)
+U6706	mozbug	2008-12-21 (1)
+U6A2D	FangQ	2008-12-21 (2)
+U743D	mozbug	2008-12-21 (1)
+U58B5	FangQ	2008-12-21 (1)
+U9F3C	FangQ	2008-12-21 (1)
+U9901	FangQ	2008-12-21 (1)
+U9458	mozbug	2008-12-21 (1)
+U9E60	mozbug	2008-12-21 (1)
+U9AAA	mozbug	2008-12-21 (1)
+U8AC1	mozbug	2008-12-21 (1)
+U9960	mozbug	2008-12-21 (1)
+U8041	mozbug	2008-12-21 (1)
+U872F	mozbug	2008-12-21 (1)
+U926E	mozbug	2008-12-21 (1)
+U9795	mozbug	2008-12-21 (1)
+U7706	FangQ	2008-12-21 (1)
+U7D4D	FangQ	2008-12-21 (1)
+U5B41	lsz	2008-12-21 (1)
+U8A94	lsz	2008-12-21 (1)
+U71FA	lsz	2008-12-21 (1)
+U9BBE	lsz	2008-12-21 (1)
+U7FE7	lsz	2008-12-21 (1)
+U8158	lsz	2008-12-21 (1)
+U9025	anonymous	2008-12-22 (1)
+U7E9E	anonymous	2008-12-22 (1)
+U5B7E	anonymous	2008-12-22 (1)
+U6A86	anonymous	2008-12-22 (1)
+U8D1C	anonymous	2008-12-22 (1)
+U8D1C	FangQ	2008-12-22 (2)
+U7E9E	FangQ	2008-12-22 (2)
+U5B7E	FangQ	2008-12-22 (2)
+U6A86	FangQ	2008-12-22 (2)
+U7BF5	anonymous	2008-12-22 (1)
+U66A4	mozbug	2008-12-22 (1)
+U98FB	mozbug	2008-12-22 (1)
+U9D93	mozbug	2008-12-22 (1)
+U5778	lsz	2008-12-22 (1)
+U93BE	lsz	2008-12-22 (1)
+U9E90	mozbug	2008-12-22 (1)
+U6EDB	lsz	2008-12-22 (1)
+U9CD1	mozbug	2008-12-22 (1)
+U724E	lsz	2008-12-22 (1)
+U9378	mozbug	2008-12-22 (1)
+U7DB6	lsz	2008-12-22 (1)
+U9442	mozbug	2008-12-22 (1)
+U6195	lsz	2008-12-22 (1)
+U9C20	mozbug	2008-12-22 (1)
+U8A2E	lsz	2008-12-22 (1)
+U72CF	mozbug	2008-12-22 (1)
+U76A8	lsz	2008-12-22 (1)
+U5936	pem	2008-12-22 (1)
+U52E8	mozbug	2008-12-22 (1)
+U9DB0	mozbug	2008-12-22 (1)
+U5790	mozbug	2008-12-22 (1)
+U8B6E	mozbug	2008-12-22 (1)
+U578A	mozbug	2008-12-22 (1)
+U93BF	mozbug	2008-12-22 (1)
+U917C	mozbug	2008-12-22 (1)
+U97B8	mozbug	2008-12-22 (1)
+U9814	lsz	2008-12-22 (1)
+U8C67	lsz	2008-12-22 (1)
+U7CB6	anonymous	2008-12-22 (1)
+U9A72	anonymous	2008-12-22 (1)
+U64F9	anonymous	2008-12-22 (1)
+U5521	anonymous	2008-12-22 (1)
+U7D98	lsz	2008-12-22 (1)
+U8928	lsz	2008-12-22 (1)
+U865D	lsz	2008-12-22 (1)
+U746C	lsz	2008-12-22 (1)
+U68DB	lsz	2008-12-22 (1)
+U8A28	lsz	2008-12-22 (1)
+U650B	lsz	2008-12-22 (1)
+U77C5	lsz	2008-12-22 (1)
+U553D	lsz	2008-12-22 (1)
+U5877	lsz	2008-12-22 (1)
+U6A37	lsz	2008-12-22 (1)
+U98CD	lsz	2008-12-22 (1)
+U6F9D	lsz	2008-12-22 (1)
+U563C	lsz	2008-12-22 (1)
+U69A2	mozbug	2008-12-23 (1)
+U5A80	mozbug	2008-12-23 (1)
+U51DA	mozbug	2008-12-23 (1)
+U8AB4	mozbug	2008-12-23 (1)
+U8F22	mozbug	2008-12-23 (1)
+U6827	mozbug	2008-12-23 (1)
+U929E	mozbug	2008-12-23 (1)
+U749B	mozbug	2008-12-23 (1)
+U528F	mozbug	2008-12-23 (1)
+U5414	mozbug	2008-12-23 (1)
+U8C7F	mozbug	2008-12-23 (1)
+U67B1	mozbug	2008-12-23 (1)
+U6EEA	mozbug	2008-12-23 (1)
+U6AFE	mozbug	2008-12-23 (1)
+U5489	mozbug	2008-12-23 (1)
+U5489	mozbug	2008-12-23 (2)
+U5878	mozbug	2008-12-23 (1)
+U8BB1	mozbug	2008-12-23 (1)
+U8EC4	mozbug	2008-12-23 (1)
+U4E67	mozbug	2008-12-23 (1)
+U6F1D	mozbug	2008-12-23 (1)
+U89F5	mozbug	2008-12-23 (1)
+U5952	mozbug	2008-12-23 (1)
+U7137	mozbug	2008-12-23 (1)
+U73AA	anonymous	2008-12-23 (1)
+U6618	anonymous	2008-12-23 (1)
+U69C8	anonymous	2008-12-23 (1)
+U70A8	anonymous	2008-12-23 (1)
+U74CE	mozbug	2008-12-23 (1)
+U6B01	mozbug	2008-12-23 (1)
+U92B1	mozbug	2008-12-23 (1)
+U7224	pem	2008-12-23 (1)
+U942F	pem	2008-12-23 (1)
+U8D98	mozbug	2008-12-23 (1)
+U8E0E	mozbug	2008-12-23 (1)
+U5A88	mozbug	2008-12-23 (1)
+U98B9	mozbug	2008-12-23 (1)
+U5A72	mozbug	2008-12-23 (1)
+U5779	mozbug	2008-12-23 (1)
+U58A2	mozbug	2008-12-23 (1)
+U9B79	mozbug	2008-12-23 (1)
+U997E	mozbug	2008-12-23 (1)
+U5F32	mozbug	2008-12-23 (1)
+U52BD	mozbug	2008-12-23 (1)
+U98D0	mozbug	2008-12-23 (1)
+U7E64	mozbug	2008-12-23 (1)
+U9461	lsz	2008-12-23 (1)
+U8CF6	lsz	2008-12-23 (1)
+U8EF3	mozbug	2008-12-23 (1)
+U7F3B	lsz	2008-12-23 (1)
+U9D34	mozbug	2008-12-23 (1)
+U4EF9	lsz	2008-12-23 (1)
+U5908	mozbug	2008-12-23 (1)
+U81DC	mozbug	2008-12-23 (1)
+U8310	lsz	2008-12-23 (1)
+U9311	mozbug	2008-12-23 (1)
+U80CB	mozbug	2008-12-23 (1)
+U7437	mozbug	2008-12-23 (1)
+U6744	mozbug	2008-12-23 (1)
+U5A81	mozbug	2008-12-23 (1)
+U9C8F	mozbug	2008-12-23 (1)
+U569B	mozbug	2008-12-23 (1)
+U51F7	lsz	2008-12-23 (1)
+U6810	mozbug	2008-12-23 (1)
+U9EE3	mozbug	2008-12-23 (1)
+U993B	lsz	2008-12-23 (1)
+U9E52	mozbug	2008-12-23 (1)
+U60D0	lsz	2008-12-23 (1)
+U74D0	mozbug	2008-12-23 (1)
+U74D0	mozbug	2008-12-23 (2)
+U9B65	mozbug	2008-12-23 (1)
+U66EF	mozbug	2008-12-23 (1)
+U70EA	mozbug	2008-12-23 (1)
+U9892	lsz	2008-12-23 (1)
+U7D26	mozbug	2008-12-23 (1)
+U7888	mozbug	2008-12-23 (1)
+U6A33	mozbug	2008-12-23 (1)
+U61E2	mozbug	2008-12-23 (1)
+U748C	mozbug	2008-12-23 (1)
+U9BDD	mozbug	2008-12-23 (1)
+U8EA2	lsz	2008-12-23 (1)
+U9E24	mozbug	2008-12-23 (1)
+U7D6C	mozbug	2008-12-23 (1)
+U77C6	mozbug	2008-12-23 (1)
+U7A55	mozbug	2008-12-23 (1)
+U99E0	mozbug	2008-12-23 (1)
+U5D66	mozbug	2008-12-23 (1)
+U6A42	lsz	2008-12-23 (1)
+U7302	mozbug	2008-12-23 (1)
+U80D3	mozbug	2008-12-23 (1)
+U99E8	mozbug	2008-12-23 (1)
+U6DA5	mozbug	2008-12-23 (1)
+U88A5	mozbug	2008-12-23 (1)
+U58CB	mozbug	2008-12-23 (1)
+U8A6A	mozbug	2008-12-23 (1)
+U78B7	mozbug	2008-12-23 (1)
+U711D	mozbug	2008-12-23 (1)
+U7A09	mozbug	2008-12-23 (1)
+U7A09	mozbug	2008-12-23 (2)
+U8EB8	mozbug	2008-12-23 (1)
+U669E	mozbug	2008-12-23 (1)
+U88B3	mozbug	2008-12-23 (1)
+U68C3	mozbug	2008-12-23 (1)
+U4FFD	mozbug	2008-12-23 (1)
+U921F	mozbug	2008-12-23 (1)
+U8BC7	mozbug	2008-12-23 (1)
+U57E8	mozbug	2008-12-23 (1)
+U77D2	mozbug	2008-12-23 (1)
+U4F21	mozbug	2008-12-23 (1)
+U9A83	mozbug	2008-12-23 (1)
+U4EF8	mozbug	2008-12-23 (1)
+U983E	mozbug	2008-12-23 (1)
+U8C5E	mozbug	2008-12-23 (1)
+U947A	mozbug	2008-12-23 (1)
+U89A0	mozbug	2008-12-23 (1)
+U7E18	mozbug	2008-12-23 (1)
+U89B1	mozbug	2008-12-23 (1)
+U8A90	mozbug	2008-12-23 (1)
+U8DBD	mozbug	2008-12-23 (1)
+U63BF	mozbug	2008-12-23 (1)
+U5D21	mozbug	2008-12-23 (1)
+U5D21	mozbug	2008-12-23 (2)
+U922F	mozbug	2008-12-23 (1)
+U7411	mozbug	2008-12-23 (1)
+U6F83	mozbug	2008-12-23 (1)
+U8DBB	mozbug	2008-12-23 (1)
+U5D91	mozbug	2008-12-23 (1)
+U98D4	mozbug	2008-12-23 (1)
+U5991	mozbug	2008-12-23 (1)
+U9C72	mozbug	2008-12-23 (1)
+U721C	mozbug	2008-12-23 (1)
+U90AB	mozbug	2008-12-23 (1)
+U8C60	mozbug	2008-12-23 (1)
+U7129	mozbug	2008-12-23 (1)
+U8CFF	mozbug	2008-12-23 (1)
+U6A24	mozbug	2008-12-23 (1)
+U5C9E	mozbug	2008-12-23 (1)
+U9423	mozbug	2008-12-23 (1)
+U9255	mozbug	2008-12-23 (1)
+U9E56	mozbug	2008-12-23 (1)
+U8C6E	mozbug	2008-12-23 (1)
+U70A6	mozbug	2008-12-23 (1)
+U98D6	mozbug	2008-12-23 (1)
+U9D7E	mozbug	2008-12-23 (1)
+U9B69	mozbug	2008-12-23 (1)
+U733D	mozbug	2008-12-23 (1)
+U9BC5	mozbug	2008-12-23 (1)
+U6D5D	mozbug	2008-12-23 (1)
+U98F3	mozbug	2008-12-23 (1)
+U9D0C	mozbug	2008-12-23 (1)
+U5C84	mozbug	2008-12-23 (1)
+U93E0	mozbug	2008-12-23 (1)
+U770F	anonymous	2008-12-23 (1)
+U6CA8	anonymous	2008-12-23 (1)
+U7697	anonymous	2008-12-23 (1)
+U5119	anonymous	2008-12-23 (1)
+U74B4	anonymous	2008-12-23 (1)
+U79F9	lsz	2008-12-23 (1)
+U9D11	lsz	2008-12-23 (1)
+U941F	lsz	2008-12-23 (1)
+U8384	lsz	2008-12-23 (1)
+U68B8	lsz	2008-12-23 (1)
+U790D	lsz	2008-12-23 (1)
+U84E2	lsz	2008-12-23 (1)
+U81D4	lsz	2008-12-23 (1)
+U831F	lsz	2008-12-23 (1)
+U5391	lsz	2008-12-23 (1)
+U87A1	lsz	2008-12-23 (1)
+U93A0	mozbug	2008-12-23 (1)
+U739A	mozbug	2008-12-23 (1)
+U87CE	mozbug	2008-12-23 (1)
+U9454	mozbug	2008-12-23 (1)
+U9815	FangQ	2008-12-23 (1)
+U6CE4	mozbug	2008-12-23 (1)
+U5500	FangQ	2008-12-23 (1)
+U7179	mozbug	2008-12-23 (1)
+U8710	FangQ	2008-12-23 (1)
+U8710	FangQ	2008-12-23 (2)
+U9465	FangQ	2008-12-23 (1)
+U9F03	mozbug	2008-12-23 (1)
+U7E07	mozbug	2008-12-23 (1)
+U7552	FangQ	2008-12-23 (1)
+U92DC	FangQ	2008-12-23 (1)
+U97E0	FangQ	2008-12-23 (1)
+U801A	FangQ	2008-12-23 (1)
+U7903	mozbug	2008-12-23 (1)
+U9C89	anonymous	2008-12-24 (1)
+U713B	anonymous	2008-12-24 (1)
+U8F30	anonymous	2008-12-24 (1)
+U9DA5	anonymous	2008-12-24 (1)
+U80A8	anonymous	2008-12-24 (1)
+U8A2F	anonymous	2008-12-24 (1)
+U50E2	anonymous	2008-12-24 (1)
+U8AE3	anonymous	2008-12-24 (1)
+U5F3D	anonymous	2008-12-24 (1)
+U5F8F	anonymous	2008-12-24 (1)
+U64B6	anonymous	2008-12-24 (1)
+U9A10	anonymous	2008-12-24 (1)
+U6E9A	anonymous	2008-12-24 (1)
+U6CF4	anonymous	2008-12-24 (1)
+U7DC3	anonymous	2008-12-24 (1)
+U780B	anonymous	2008-12-24 (1)
+U982A	anonymous	2008-12-24 (1)
+U5089	anonymous	2008-12-24 (1)
+U564B	anonymous	2008-12-24 (1)
+U7447	anonymous	2008-12-24 (1)
+U66A3	anonymous	2008-12-24 (1)
+U9533	anonymous	2008-12-24 (1)
+U79F2	anonymous	2008-12-24 (1)
+U5D60	anonymous	2008-12-24 (1)
+U7A24	anonymous	2008-12-24 (1)
+U6143	anonymous	2008-12-24 (1)
+U7419	anonymous	2008-12-24 (1)
+U7314	anonymous	2008-12-24 (1)
+U5B49	anonymous	2008-12-24 (1)
+U9C8A	anonymous	2008-12-24 (1)
+U7341	anonymous	2008-12-24 (1)
+U6EF0	anonymous	2008-12-24 (1)
+U7C8E	anonymous	2008-12-24 (1)
+U5A0B	anonymous	2008-12-24 (1)
+U5755	anonymous	2008-12-24 (1)
+U91A9	anonymous	2008-12-24 (1)
+U9982	anonymous	2008-12-24 (1)
+U6D14	anonymous	2008-12-24 (1)
+U57AF	anonymous	2008-12-24 (1)
+U6C6E	anonymous	2008-12-24 (1)
+U5F9D	anonymous	2008-12-24 (1)
+U6DFF	anonymous	2008-12-24 (1)
+U6623	anonymous	2008-12-24 (1)
+U9337	pem	2008-12-24 (1)
+U4F45	pem	2008-12-24 (1)
+U4F45	pem	2008-12-24 (2)
+U59C4	pem	2008-12-24 (1)
+U74AE	pem	2008-12-24 (1)
+U8AB3	pem	2008-12-24 (1)
+U6304	pem	2008-12-24 (1)
+U8AA9	lsz	2008-12-24 (1)
+U9029	lsz	2008-12-24 (1)
+U9D8E	lsz	2008-12-24 (1)
+U8400	lsz	2008-12-24 (1)
+U9033	anonymous	2008-12-24 (1)
+U909A	anonymous	2008-12-24 (1)
+U91A6	anonymous	2008-12-24 (1)
+U7775	lsz	2008-12-24 (1)
+U8D7E	anonymous	2008-12-24 (1)
+U5CB9	lsz	2008-12-24 (1)
+U51F2	anonymous	2008-12-24 (1)
+U76C1	lsz	2008-12-24 (1)
+U8065	lsz	2008-12-24 (1)
+U79D7	pem	2008-12-24 (1)
+U8E6B	lsz	2008-12-24 (1)
+U6E91	lsz	2008-12-24 (1)
+U5E56	lsz	2008-12-24 (1)
+U8A88	lsz	2008-12-24 (1)
+U759B	lsz	2008-12-24 (1)
+U5A0D	lsz	2008-12-24 (1)
+U5A0D	lsz	2008-12-24 (2)
+U73A3	anonymous	2008-12-24 (1)
+U5EBC	lsz	2008-12-24 (1)
+U4FC6	anonymous	2008-12-24 (1)
+U8CD4	anonymous	2008-12-24 (1)
+U9F45	lsz	2008-12-24 (1)
+U8890	anonymous	2008-12-24 (1)
+U6335	lsz	2008-12-24 (1)
+U9EB2	lsz	2008-12-24 (1)
+U6408	lsz	2008-12-24 (1)
+U97BE	anonymous	2008-12-24 (1)
+U98B0	lsz	2008-12-24 (1)
+U5F9A	anonymous	2008-12-24 (1)
+U7A35	lsz	2008-12-24 (1)
+U9247	anonymous	2008-12-24 (1)
+U5260	anonymous	2008-12-24 (1)
+U7748	anonymous	2008-12-24 (1)
+U7807	anonymous	2008-12-24 (1)
+U74CD	anonymous	2008-12-24 (1)
+U52DC	anonymous	2008-12-24 (1)
+U931C	anonymous	2008-12-24 (1)
+U799F	anonymous	2008-12-24 (1)
+U8608	lsz	2008-12-24 (1)
+U8EB9	anonymous	2008-12-24 (1)
+U500A	FangQ	2008-12-24 (1)
+U870F	pem	2008-12-24 (1)
+U9B94	FangQ	2008-12-24 (1)
+U6931	FangQ	2008-12-24 (1)
+U5B74	lsz	2008-12-24 (1)
+U93EA	FangQ	2008-12-24 (1)
+U9C45	FangQ	2008-12-24 (1)
+U5B76	lsz	2008-12-24 (1)
+U63C1	lsz	2008-12-24 (1)
+U629D	lsz	2008-12-24 (1)
+U7F52	lsz	2008-12-24 (1)
+U4F29	lsz	2008-12-24 (1)
+U799F	lsz	2008-12-24 (2)
+U947B	lsz	2008-12-24 (1)
+U6DB0	anonymous	2008-12-24 (1)
+U8A32	anonymous	2008-12-24 (1)
+U8858	anonymous	2008-12-24 (1)
+U8AB1	anonymous	2008-12-24 (1)
+U510E	anonymous	2008-12-24 (1)
+U8EB5	anonymous	2008-12-24 (1)
+U52C6	anonymous	2008-12-24 (1)
+U878A	anonymous	2008-12-24 (1)
+U60A1	anonymous	2008-12-24 (1)
+U8B3F	anonymous	2008-12-24 (1)
+U7D65	anonymous	2008-12-24 (1)
+U759C	anonymous	2008-12-24 (1)
+U7346	anonymous	2008-12-24 (1)
+U8D7C	anonymous	2008-12-24 (1)
+U8903	anonymous	2008-12-24 (1)
+U9028	anonymous	2008-12-24 (1)
+U6BED	anonymous	2008-12-24 (1)
+U8D20	anonymous	2008-12-24 (1)
+U7555	anonymous	2008-12-24 (1)
+U827B	anonymous	2008-12-24 (1)
+U7127	yugushen	2008-12-24 (1)
+U941C	yugushen	2008-12-24 (1)
+U5CEB	yugushen	2008-12-24 (1)
+U6D49	yugushen	2008-12-24 (1)
+U59F0	yugushen	2008-12-24 (1)
+U85BC	yugushen	2008-12-24 (1)
+U59F0	lsz	2008-12-24 (2)
+U941C	lsz	2008-12-24 (2)
+U827B	lsz	2008-12-24 (2)
+U5F9A	lsz	2008-12-24 (2)
+U8B3F	lsz	2008-12-24 (2)
+U7D65	lsz	2008-12-24 (2)
+U7BBA	lsz	2008-12-24 (1)
+U6992	lsz	2008-12-24 (1)
+U6E8A	lsz	2008-12-24 (1)
+U7C51	lsz	2008-12-24 (1)
+U7A38	lsz	2008-12-24 (1)
+U5758	lsz	2008-12-24 (1)
+U92E2	lsz	2008-12-24 (1)
+U9EC1	lsz	2008-12-24 (1)
+U717E	wanghong	2008-12-24 (1)
+U51AE	wanghong	2008-12-24 (1)
+U75B7	wanghong	2008-12-24 (1)
+U65BA	wanghong	2008-12-24 (1)
+U51DF	wanghong	2008-12-24 (1)
+U599C	wanghong	2008-12-24 (1)
+U9EB1	wanghong	2008-12-24 (1)
+U6F1B	wanghong	2008-12-24 (1)
+U7AF1	wanghong	2008-12-24 (1)
+U9BDF	wanghong	2008-12-24 (1)
+U96A5	wanghong	2008-12-24 (1)
+U4EB8	wanghong	2008-12-24 (1)
+U65BA	wanghong	2008-12-24 (2)
+U6F1B	wanghong	2008-12-24 (2)
+U8483	anonymous	2008-12-25 (1)
+U56EF	anonymous	2008-12-25 (1)
+U73E2	anonymous	2008-12-25 (1)
+U6DAD	anonymous	2008-12-25 (1)
+U80FF	anonymous	2008-12-25 (1)
+U65F8	anonymous	2008-12-25 (1)
+U62B2	anonymous	2008-12-25 (1)
+U5066	anonymous	2008-12-25 (1)
+U91C4	anonymous	2008-12-25 (1)
+U91C4	lsz	2008-12-25 (2)
+U5994	anonymous	2008-12-25 (1)
+U9E53	pem	2008-12-25 (1)
+U7E28	pem	2008-12-25 (1)
+U9CAA	pem	2008-12-25 (1)
+U56FB	lsz	2008-12-25 (1)
+U5935	lsz	2008-12-25 (1)
+U8094	sqrt2x	2008-12-25 (1)
+U813B	lsz	2008-12-25 (1)
+U6ACA	lsz	2008-12-25 (1)
+U67BC	FangQ	2008-12-25 (1)
+U5059	FangQ	2008-12-25 (1)
+U67D6	FangQ	2008-12-25 (1)
+U9393	FangQ	2008-12-25 (1)
+U7A66	FangQ	2008-12-25 (1)
+U6943	FangQ	2008-12-25 (1)
+U8692	FangQ	2008-12-25 (1)
+U99BF	FangQ	2008-12-25 (1)
+U7866	FangQ	2008-12-25 (1)
+U70B2	FangQ	2008-12-25 (1)
+U7E27	FangQ	2008-12-25 (1)
+U8BBB	FangQ	2008-12-25 (1)
+U5A02	FangQ	2008-12-25 (1)
+U9C01	anonymous	2008-12-25 (1)
+U869F	FangQ	2008-12-25 (1)
+U6119	anonymous	2008-12-25 (1)
+U92BF	anonymous	2008-12-25 (1)
+U5B82	anonymous	2008-12-25 (1)
+U89A5	anonymous	2008-12-25 (1)
+U5D2A	anonymous	2008-12-25 (1)
+U5989	anonymous	2008-12-25 (1)
+U87CF	anonymous	2008-12-25 (1)
+U564F	anonymous	2008-12-25 (1)
+U7867	lsz	2008-12-25 (1)
+U91BB	lsz	2008-12-25 (1)
+U8AB7	lsz	2008-12-25 (1)
+U6B7D	lsz	2008-12-25 (1)
+U9A8D	lsz	2008-12-25 (1)
+U8359	lsz	2008-12-25 (1)
+U7A59	lsz	2008-12-25 (1)
+U71AE	anonymous	2008-12-25 (1)
+U562B	anonymous	2008-12-25 (1)
+U686C	anonymous	2008-12-25 (1)
+U6139	anonymous	2008-12-25 (1)
+U801D	anonymous	2008-12-25 (1)
+U6903	anonymous	2008-12-25 (1)
+U7CDB	anonymous	2008-12-25 (1)
+U5585	anonymous	2008-12-25 (1)
+U979F	anonymous	2008-12-25 (1)
+U8675	anonymous	2008-12-25 (1)
+U7353	anonymous	2008-12-25 (1)
+U7581	anonymous	2008-12-25 (1)
+U712C	anonymous	2008-12-25 (1)
+U8145	anonymous	2008-12-25 (1)
+U9188	anonymous	2008-12-25 (1)
+U8ED0	wanghong	2008-12-25 (1)
+U93D3	wanghong	2008-12-25 (1)
+U9E76	wanghong	2008-12-25 (1)
+U76A0	wanghong	2008-12-25 (1)
+U7C93	wanghong	2008-12-25 (1)
+U6395	wanghong	2008-12-25 (1)
+U9842	wanghong	2008-12-25 (1)
+U7796	wanghong	2008-12-25 (1)
+U74D1	wanghong	2008-12-25 (1)
+U5359	wanghong	2008-12-25 (1)
+U7D5A	wanghong	2008-12-25 (1)
+U66E5	wanghong	2008-12-25 (1)
+U6511	wanghong	2008-12-25 (1)
+U7D74	wanghong	2008-12-25 (1)
+U8181	FangQ	2008-12-25 (1)
+U8181	FangQ	2008-12-25 (2)
+U7B3D	FangQ	2008-12-25 (1)
+U951C	FangQ	2008-12-25 (1)
+U812A	FangQ	2008-12-25 (1)
+U9A58	FangQ	2008-12-25 (1)
+U5CDD	FangQ	2008-12-25 (1)
+U7971	FangQ	2008-12-25 (1)
+U6898	FangQ	2008-12-25 (1)
+U7CEB	wanghong	2008-12-26 (1)
+U611E	wanghong	2008-12-26 (1)
+U9966	wanghong	2008-12-26 (1)
+U73F0	wanghong	2008-12-26 (1)
+U6857	wanghong	2008-12-26 (1)
+U9434	wanghong	2008-12-26 (1)
+U58A7	wanghong	2008-12-26 (1)
+U62D5	wanghong	2008-12-26 (1)
+U9066	wanghong	2008-12-26 (1)
+U79DA	wanghong	2008-12-26 (1)
+U9B5C	wanghong	2008-12-26 (1)
+U86A0	wanghong	2008-12-26 (1)
+U7749	anonymous	2008-12-26 (1)
+U7399	anonymous	2008-12-26 (1)
+U5995	anonymous	2008-12-26 (1)
+U781B	anonymous	2008-12-26 (1)
+U8878	lsz	2008-12-26 (1)
+U89D7	lsz	2008-12-26 (1)
+U8E3B	lsz	2008-12-26 (1)
+U9243	lsz	2008-12-26 (1)
+U8D57	lsz	2008-12-26 (1)
+U693A	lsz	2008-12-26 (1)
+U52C4	lsz	2008-12-26 (1)
+U5444	lsz	2008-12-26 (1)
+U5542	lsz	2008-12-26 (1)
+U54B5	pem	2008-12-26 (1)
+U731A	pem	2008-12-26 (1)
+U6D50	pem	2008-12-26 (1)
+U7F6F	pem	2008-12-26 (1)
+U4F06	pem	2008-12-26 (1)
+U7A01	lsz	2008-12-26 (1)
+U99E1	pem	2008-12-26 (1)
+U76C7	lsz	2008-12-26 (1)
+U7A2A	pem	2008-12-26 (1)
+U6638	pem	2008-12-26 (1)
+U8E83	anonymous	2008-12-26 (1)
+U5568	pem	2008-12-26 (1)
+U555B	pem	2008-12-26 (1)
+U58B4	lsz	2008-12-26 (1)
+U9BC2	lsz	2008-12-26 (1)
+U97DB	lsz	2008-12-26 (1)
+U8243	lsz	2008-12-26 (1)
+U71F3	lsz	2008-12-26 (1)
+U71F3	lsz	2008-12-26 (2)
+U7283	lsz	2008-12-26 (1)
+U904C	lsz	2008-12-26 (1)
+U9F26	lsz	2008-12-26 (1)
+U7CE1	anonymous	2008-12-26 (1)
+U739C	anonymous	2008-12-26 (1)
+U9D39	FangQ	2008-12-26 (1)
+U813C	FangQ	2008-12-26 (1)
+U9E30	FangQ	2008-12-26 (1)
+U6074	anonymous	2008-12-26 (1)
+U820F	FangQ	2008-12-26 (1)
+U667D	FangQ	2008-12-26 (1)
+U79F4	FangQ	2008-12-26 (1)
+U8908	FangQ	2008-12-26 (1)
+U7A45	FangQ	2008-12-26 (1)
+U7208	FangQ	2008-12-26 (1)
+U59EF	FangQ	2008-12-26 (1)
+U59EF	FangQ	2008-12-26 (2)
+U8023	FangQ	2008-12-26 (1)
+U7A3A	FangQ	2008-12-26 (1)
+U7138	FangQ	2008-12-26 (1)
+U6BD1	FangQ	2008-12-26 (1)
+U6048	FangQ	2008-12-26 (1)
+U6D15	FangQ	2008-12-26 (1)
+U9208	FangQ	2008-12-26 (1)
+U8A8E	FangQ	2008-12-26 (1)
+U50AB	FangQ	2008-12-26 (1)
+U59C2	FangQ	2008-12-26 (1)
+U7773	FangQ	2008-12-26 (1)
+U739E	FangQ	2008-12-26 (1)
+U707B	FangQ	2008-12-26 (1)
+U5A6F	FangQ	2008-12-26 (1)
+U78B6	FangQ	2008-12-26 (1)
+U833E	FangQ	2008-12-26 (1)
+U95AA	FangQ	2008-12-26 (1)
+U9B6A	FangQ	2008-12-26 (1)
+U7B0C	FangQ	2008-12-26 (1)
+U7209	FangQ	2008-12-26 (1)
+U90C2	FangQ	2008-12-26 (1)
+U61DD	FangQ	2008-12-26 (1)
+U9978	FangQ	2008-12-26 (1)
+U99A2	FangQ	2008-12-26 (1)
+U5136	FangQ	2008-12-26 (1)
+U9456	FangQ	2008-12-26 (1)
+U9DBD	FangQ	2008-12-26 (1)
+U7D57	FangQ	2008-12-26 (1)
+U5A4E	FangQ	2008-12-26 (1)
+U9B8D	FangQ	2008-12-26 (1)
+U8522	FangQ	2008-12-26 (1)
+U99A0	FangQ	2008-12-26 (1)
+U7216	FangQ	2008-12-26 (1)
+U5AC5	FangQ	2008-12-26 (1)
+U9BB2	wanghong	2008-12-26 (1)
+U9C5C	FangQ	2008-12-26 (1)
+U510D	wanghong	2008-12-26 (1)
+U8887	wanghong	2008-12-26 (1)
+U708B	wanghong	2008-12-26 (1)
+U5067	wanghong	2008-12-26 (1)
+U788A	wanghong	2008-12-26 (1)
+U4F2E	wanghong	2008-12-26 (1)
+U7E4F	wanghong	2008-12-26 (1)
+U9B53	wanghong	2008-12-26 (1)
+U70A7	wanghong	2008-12-26 (1)
+U9AC3	wanghong	2008-12-26 (1)
+U9B6B	wanghong	2008-12-26 (1)
+U9EE1	wanghong	2008-12-26 (1)
+U691E	wanghong	2008-12-26 (1)
+U8503	wanghong	2008-12-26 (1)
+U9EE1	FangQ	2008-12-26 (2)
+U954B	wanghong	2008-12-26 (1)
+U7204	wanghong	2008-12-26 (1)
+U62EA	wanghong	2008-12-26 (1)
+U7320	wanghong	2008-12-26 (1)
+U54F9	wanghong	2008-12-26 (1)
+U8A35	wanghong	2008-12-26 (1)
+U59B7	wanghong	2008-12-26 (1)
+U9607	wanghong	2008-12-26 (1)
+U9C6C	wanghong	2008-12-26 (1)
+U816C	wanghong	2008-12-26 (1)
+U63A6	pem	2008-12-26 (1)
+U78DC	pem	2008-12-26 (1)
+U91FB	pem	2008-12-26 (1)
+U9C1A	pem	2008-12-26 (1)
+U7873	pem	2008-12-26 (1)
+U5A89	lsz	2008-12-26 (1)
+U90CD	lsz	2008-12-26 (1)
+U95C2	lsz	2008-12-26 (1)
+U7254	lsz	2008-12-26 (1)
+U9EF8	lsz	2008-12-26 (1)
+U91D2	FangQ	2008-12-26 (1)
+U9983	FangQ	2008-12-26 (1)
+U9520	FangQ	2008-12-26 (1)
+U68BD	FangQ	2008-12-26 (1)
+U9CC8	FangQ	2008-12-26 (1)
+U68BF	FangQ	2008-12-26 (1)
+U62DE	FangQ	2008-12-26 (1)
+U62C1	FangQ	2008-12-26 (1)
+U5603	FangQ	2008-12-26 (1)
+U748D	FangQ	2008-12-26 (1)
+U52EE	lsz	2008-12-26 (1)
+U8B1F	FangQ	2008-12-26 (1)
+U79FC	FangQ	2008-12-26 (1)
+U6967	FangQ	2008-12-26 (1)
+U7CF9	FangQ	2008-12-26 (1)
+U8EF2	FangQ	2008-12-26 (1)
+U86A6	lsz	2008-12-27 (1)
+U9973	lsz	2008-12-27 (1)
+U6D55	lsz	2008-12-27 (1)
+U5867	lsz	2008-12-27 (1)
+U86AD	lsz	2008-12-27 (1)
+U986E	lsz	2008-12-27 (1)
+U5032	lsz	2008-12-27 (1)
+U9627	lsz	2008-12-27 (1)
+U5F8E	lsz	2008-12-27 (1)
+U6352	lsz	2008-12-27 (1)
+U7414	FangQ	2008-12-27 (1)
+U8D51	FangQ	2008-12-27 (1)
+U708C	FangQ	2008-12-27 (1)
+U8103	FangQ	2008-12-27 (1)
+U519F	FangQ	2008-12-27 (1)
+U7CA6	FangQ	2008-12-27 (1)
+U5596	FangQ	2008-12-27 (1)
+U926A	FangQ	2008-12-27 (1)
+U926A	FangQ	2008-12-27 (2)
+U84DE	FangQ	2008-12-27 (1)
+U6B90	FangQ	2008-12-27 (1)
+U8066	FangQ	2008-12-27 (1)
+U5469	FangQ	2008-12-27 (1)
+U73C4	FangQ	2008-12-27 (1)
+U8886	FangQ	2008-12-27 (1)
+U578E	FangQ	2008-12-27 (1)
+U9A3C	FangQ	2008-12-27 (1)
+U9F53	FangQ	2008-12-27 (1)
+U73B1	FangQ	2008-12-27 (1)
+U7D78	FangQ	2008-12-27 (1)
+U922A	FangQ	2008-12-27 (1)
+U597A	FangQ	2008-12-27 (1)
+U789D	FangQ	2008-12-27 (1)
+U52EA	FangQ	2008-12-27 (1)
+U4F68	FangQ	2008-12-27 (1)
+U8B61	FangQ	2008-12-27 (1)
+U5038	FangQ	2008-12-27 (1)
+U5605	FangQ	2008-12-27 (1)
+U6D72	FangQ	2008-12-27 (1)
+U8A6F	FangQ	2008-12-27 (1)
+U7EAE	FangQ	2008-12-27 (1)
+U573D	FangQ	2008-12-27 (1)
+U7251	FangQ	2008-12-27 (1)
+U7698	FangQ	2008-12-27 (1)
+U7456	FangQ	2008-12-27 (1)
+U603D	FangQ	2008-12-27 (1)
+U8B44	lsz	2008-12-27 (1)
+U893F	lsz	2008-12-27 (1)
+U945C	lsz	2008-12-27 (1)
+U6494	lsz	2008-12-27 (1)
+U77C0	lsz	2008-12-27 (1)
+U9007	lsz	2008-12-27 (1)
+U6D24	wanghong	2008-12-27 (1)
+U97C0	lsz	2008-12-27 (1)
+U6E42	wanghong	2008-12-27 (1)
+U97C0	lsz	2008-12-27 (2)
+U5767	wanghong	2008-12-27 (1)
+U8736	wanghong	2008-12-27 (1)
+U70F2	wanghong	2008-12-27 (1)
+U7072	wanghong	2008-12-27 (1)
+U501D	wanghong	2008-12-27 (1)
+U9B99	wanghong	2008-12-27 (1)
+U96D0	wanghong	2008-12-27 (1)
+U8873	wanghong	2008-12-27 (1)
+U81CB	wanghong	2008-12-27 (1)
+U7C04	wanghong	2008-12-27 (1)
+U8873	FangQ	2008-12-27 (2)
+U9B99	wanghong	2008-12-27 (2)
+U92E3	FangQ	2008-12-27 (1)
+U6331	FangQ	2008-12-27 (1)
+U87A5	FangQ	2008-12-27 (1)
+U7072	wanghong	2008-12-27 (2)
+U70F2	wanghong	2008-12-27 (2)
+U7A2C	FangQ	2008-12-27 (1)
+U8999	FangQ	2008-12-27 (1)
+U8246	FangQ	2008-12-27 (1)
+U639A	FangQ	2008-12-27 (1)
+U8BD0	FangQ	2008-12-27 (1)
+U5325	FangQ	2008-12-27 (1)
+U593B	FangQ	2008-12-27 (1)
+U5502	FangQ	2008-12-27 (1)
+U6F9B	FangQ	2008-12-27 (1)
+U6F9B	FangQ	2008-12-27 (2)
+U8104	FangQ	2008-12-27 (1)
+U7111	FangQ	2008-12-27 (1)
+U888F	wanghong	2008-12-27 (1)
+U708D	wanghong	2008-12-27 (1)
+U6E48	wanghong	2008-12-27 (1)
+U79D0	wanghong	2008-12-28 (1)
+U6BF4	wanghong	2008-12-28 (1)
+U5842	wanghong	2008-12-28 (1)
+U8EAD	wanghong	2008-12-28 (1)
+U6D02	wanghong	2008-12-28 (1)
+U7976	wanghong	2008-12-28 (1)
+U557A	wanghong	2008-12-28 (1)
+U7305	anonymous	2008-12-28 (1)
+U97F4	mozbug	2008-12-28 (1)
+U5B86	mozbug	2008-12-28 (1)
+U6C75	anonymous	2008-12-28 (1)
+U97BD	mozbug	2008-12-28 (1)
+U8EF0	mozbug	2008-12-28 (1)
+U68A5	mozbug	2008-12-28 (1)
+U4F8E	mozbug	2008-12-28 (1)
+U7836	mozbug	2008-12-28 (1)
+U9353	mozbug	2008-12-28 (1)
+U9CB9	mozbug	2008-12-28 (1)
+U7753	mozbug	2008-12-28 (1)
+U53AA	mozbug	2008-12-28 (1)
+U55B4	mozbug	2008-12-28 (1)
+U725C	mozbug	2008-12-28 (1)
+U722B	mozbug	2008-12-28 (1)
+U7989	mozbug	2008-12-28 (1)
+U7F98	mozbug	2008-12-28 (1)
+U6899	mozbug	2008-12-28 (1)
+U790F	mozbug	2008-12-28 (1)
+U6326	mozbug	2008-12-28 (1)
+U91EF	mozbug	2008-12-28 (1)
+U9422	mozbug	2008-12-28 (1)
+U8CD0	mozbug	2008-12-28 (1)
+U87E9	mozbug	2008-12-28 (1)
+U9B39	mozbug	2008-12-28 (1)
+U8DC0	mozbug	2008-12-28 (1)
+U7002	mozbug	2008-12-28 (1)
+U6836		2008-12-28 (1)
+U70EE		2008-12-28 (1)
+U97FC	mozbug	2008-12-28 (1)
+U8660	mozbug	2008-12-28 (1)
+U67AC	vvFeng	2008-12-28 (1)
+U6E0F	vvFeng	2008-12-28 (1)
+U6E0F	vvFeng	2008-12-28 (2)
+U6888	vvFeng	2008-12-28 (1)
+U9775	mozbug	2008-12-28 (1)
+U674A	vvFeng	2008-12-28 (1)
+U70A3	vvFeng	2008-12-28 (1)
+U8A97	mozbug	2008-12-28 (1)
+U941E	mozbug	2008-12-28 (1)
+U9362	mozbug	2008-12-28 (1)
+U738C	mozbug	2008-12-28 (1)
+U998C	mozbug	2008-12-28 (1)
+U717F	mozbug	2008-12-28 (1)
+U8163	mozbug	2008-12-28 (1)
+U722F	mozbug	2008-12-28 (1)
+U9E85	mozbug	2008-12-28 (1)
+U77D1	mozbug	2008-12-28 (1)
+U9FA1	mozbug	2008-12-28 (1)
+U77EA	mozbug	2008-12-28 (1)
+U741C	anonymous	2008-12-28 (1)
+U59D5	mozbug	2008-12-28 (1)
+U8A5D	mozbug	2008-12-28 (1)
+U7776	mozbug	2008-12-28 (1)
+U7776	mozbug	2008-12-28 (2)
+U9637	vvFeng	2008-12-28 (1)
+U8E32	vvFeng	2008-12-28 (1)
+U586A	vvFeng	2008-12-28 (1)
+U89EA	vvFeng	2008-12-28 (1)
+U5826	vvFeng	2008-12-28 (1)
+U9C93	vvFeng	2008-12-28 (1)
+U5826	FangQ	2008-12-28 (2)
+U713E	FangQ	2008-12-28 (1)
+U6F4A	FangQ	2008-12-28 (1)
+U6531	FangQ	2008-12-28 (1)
+U9D0A	FangQ	2008-12-28 (1)
+U5743	FangQ	2008-12-28 (1)
+U6239	FangQ	2008-12-28 (1)
+U89BB	FangQ	2008-12-28 (1)
+U7915	FangQ	2008-12-28 (1)
+U536D	FangQ	2008-12-28 (1)
+U4F9F	FangQ	2008-12-28 (1)
+U97BA		2008-12-28 (1)
+U8B4D	FangQ	2008-12-28 (1)
+U5485	FangQ	2008-12-28 (1)
+U6135	FangQ	2008-12-28 (1)
+U9A33		2008-12-28 (1)
+U62BA	FangQ	2008-12-28 (1)
+U9D6D		2008-12-28 (1)
+U5DC1		2008-12-28 (1)
+U594C	FangQ	2008-12-28 (1)
+U591D	FangQ	2008-12-28 (1)
+U9340	FangQ	2008-12-28 (1)
+U9923	FangQ	2008-12-28 (1)
+U60AE	FangQ	2008-12-28 (1)
+U50EB	FangQ	2008-12-28 (1)
+U6A6E	FangQ	2008-12-28 (1)
+U6305	FangQ	2008-12-28 (1)
+U9A89	FangQ	2008-12-28 (1)
+U546D	FangQ	2008-12-28 (1)
+U6353	FangQ	2008-12-28 (1)
+U9EC5	lsz	2008-12-28 (1)
+U84BE	lsz	2008-12-28 (1)
+U7DE5	lsz	2008-12-28 (1)
+U8EE4	anonymous	2008-12-29 (1)
+U9408	anonymous	2008-12-29 (1)
+U79C4	anonymous	2008-12-29 (1)
+U79C4	anonymous	2008-12-29 (2)
+U66D5	mozbug	2008-12-29 (1)
+U5643	mozbug	2008-12-29 (1)
+U5652	mozbug	2008-12-29 (1)
+U586E	anonymous	2008-12-29 (1)
+U69C5	anonymous	2008-12-29 (1)
+U6692	anonymous	2008-12-29 (1)
+U9C8C	anonymous	2008-12-29 (1)
+U6F9F	mozbug	2008-12-29 (1)
+U8C83	anonymous	2008-12-29 (1)
+U799E	anonymous	2008-12-29 (1)
+U74F9	mozbug	2008-12-29 (1)
+U74ED	mozbug	2008-12-29 (1)
+U9C96	anonymous	2008-12-29 (1)
+U74FA	mozbug	2008-12-29 (1)
+U8E43	anonymous	2008-12-29 (1)
+U74FC	mozbug	2008-12-29 (1)
+U796C	anonymous	2008-12-29 (1)
+U6856	anonymous	2008-12-29 (1)
+U88A6	anonymous	2008-12-29 (1)
+U87B1	mozbug	2008-12-29 (1)
+U5975	anonymous	2008-12-29 (1)
+U87C1	mozbug	2008-12-29 (1)
+U8453	anonymous	2008-12-29 (1)
+U87D5	mozbug	2008-12-29 (1)
+U87DA	mozbug	2008-12-29 (1)
+U51D3	mozbug	2008-12-29 (1)
+U6B06	anonymous	2008-12-29 (1)
+U51D5	mozbug	2008-12-29 (1)
+U9638	anonymous	2008-12-29 (1)
+U51D9	mozbug	2008-12-29 (1)
+U6125	anonymous	2008-12-29 (1)
+U999A	anonymous	2008-12-29 (1)
+U599A	anonymous	2008-12-29 (1)
+U99C0	anonymous	2008-12-29 (1)
+U94D3	anonymous	2008-12-29 (1)
+U5AFC	anonymous	2008-12-29 (1)
+U512B	anonymous	2008-12-29 (1)
+U9BE9	anonymous	2008-12-29 (1)
+U8A09	anonymous	2008-12-29 (1)
+U6455	anonymous	2008-12-29 (1)
+U9BA9	anonymous	2008-12-29 (1)
+U50DC	anonymous	2008-12-29 (1)
+U7139	anonymous	2008-12-29 (1)
+U9E74	anonymous	2008-12-29 (1)
+U74D3	anonymous	2008-12-29 (1)
+U5D78	anonymous	2008-12-29 (1)
+U7F93	anonymous	2008-12-29 (1)
+U7876	anonymous	2008-12-29 (1)
+U9220	anonymous	2008-12-29 (1)
+U9305	anonymous	2008-12-29 (1)
+U9FA6	mozbug	2008-12-29 (1)
+U50AA	anonymous	2008-12-29 (1)
+U510F	anonymous	2008-12-29 (1)
+U8DC9	anonymous	2008-12-29 (1)
+U5B33	anonymous	2008-12-29 (1)
+U9FA8	mozbug	2008-12-29 (1)
+U8F4A	anonymous	2008-12-29 (1)
+U9FA9	mozbug	2008-12-29 (1)
+U4EE6	anonymous	2008-12-29 (1)
+U79FF	anonymous	2008-12-29 (1)
+U9FAA	mozbug	2008-12-29 (1)
+U7CB7	anonymous	2008-12-29 (1)
+U9FAB	mozbug	2008-12-29 (1)
+U9FAB	mozbug	2008-12-29 (2)
+U72D3	anonymous	2008-12-29 (1)
+U9FAC	mozbug	2008-12-29 (1)
+U9384	anonymous	2008-12-29 (1)
+U59B8	anonymous	2008-12-29 (1)
+U8EA7	anonymous	2008-12-29 (1)
+U9FAE	mozbug	2008-12-29 (1)
+U9167	anonymous	2008-12-29 (1)
+U9FAD	mozbug	2008-12-29 (1)
+U7506	anonymous	2008-12-29 (1)
+U9FAF	mozbug	2008-12-29 (1)
+U956E	anonymous	2008-12-29 (1)
+U780A	anonymous	2008-12-29 (1)
+U738F	anonymous	2008-12-29 (1)
+U79FE	anonymous	2008-12-29 (1)
+U9FB1	mozbug	2008-12-29 (1)
+U9FB2	mozbug	2008-12-29 (1)
+U5791	anonymous	2008-12-29 (1)
+U69D1	lsz	2008-12-29 (1)
+U9FBA	mozbug	2008-12-29 (1)
+U9FB3	mozbug	2008-12-29 (1)
+U9FB7	mozbug	2008-12-29 (1)
+U9FBB	mozbug	2008-12-29 (1)
+U9FBC	mozbug	2008-12-29 (1)
+U9FBD	mozbug	2008-12-29 (1)
+U9FBD	mozbug	2008-12-29 (2)
+U5A98	lsz	2008-12-29 (1)
+U9FBE	mozbug	2008-12-29 (1)
+U5AA0	lsz	2008-12-29 (1)
+U5AA1	lsz	2008-12-29 (1)
+U9374	lsz	2008-12-29 (1)
+U9FBF	mozbug	2008-12-29 (1)
+U937F	lsz	2008-12-29 (1)
+U9FC0	mozbug	2008-12-29 (1)
+U9FC1	mozbug	2008-12-29 (1)
+U9FC2	mozbug	2008-12-29 (1)
+U9FC3	mozbug	2008-12-29 (1)
+U9FB6	mozbug	2008-12-29 (1)
+U9FBB	FangQ	2008-12-29 (2)
+U9FB3	FangQ	2008-12-29 (2)
+U8D0C	anonymous	2008-12-29 (1)
+U9AE4	anonymous	2008-12-29 (1)
+U9AF5	anonymous	2008-12-29 (1)
+U5812	anonymous	2008-12-29 (1)
+U7AF3	anonymous	2008-12-29 (1)
+U7AF2	anonymous	2008-12-29 (1)
+U878C	anonymous	2008-12-29 (1)
+U7808	anonymous	2008-12-29 (1)
+U783D	anonymous	2008-12-29 (1)
+U5FA3	anonymous	2008-12-29 (1)
+U5FA7	anonymous	2008-12-29 (1)
+U5FB1	anonymous	2008-12-29 (1)
+U5FB8	anonymous	2008-12-29 (1)
+U6E18	anonymous	2008-12-29 (1)
+U8A06	anonymous	2008-12-29 (1)
+U9A1F	anonymous	2008-12-29 (1)
+U8A7E	anonymous	2008-12-29 (1)
+U9A17	anonymous	2008-12-29 (1)
+U9A2F	anonymous	2008-12-29 (1)
+U8044	anonymous	2008-12-29 (1)
+U8049	anonymous	2008-12-29 (1)
+U804E	anonymous	2008-12-29 (1)
+U7A2D	anonymous	2008-12-29 (1)
+U7A34	anonymous	2008-12-29 (1)
+U73D5	anonymous	2008-12-29 (1)
+U7445	anonymous	2008-12-29 (1)
+U62B7	anonymous	2008-12-29 (1)
+U62B7	anonymous	2008-12-29 (2)
+U6312	anonymous	2008-12-29 (1)
+U78C2	anonymous	2008-12-29 (1)
+U7A1D	anonymous	2008-12-29 (1)
+U7A27	anonymous	2008-12-29 (1)
+U7A29	anonymous	2008-12-29 (1)
+U7A41	anonymous	2008-12-29 (1)
+U6A43	anonymous	2008-12-29 (1)
+U6A43	anonymous	2008-12-29 (2)
+U6A45	anonymous	2008-12-29 (1)
+U6A4C	anonymous	2008-12-29 (1)
+U8040	anonymous	2008-12-29 (1)
+U63B9	anonymous	2008-12-29 (1)
+U63E6	anonymous	2008-12-29 (1)
+U63E6	anonymous	2008-12-29 (2)
+U541A	anonymous	2008-12-29 (1)
+U56D2	anonymous	2008-12-29 (1)
+U56D5	anonymous	2008-12-29 (1)
+U8AE9	anonymous	2008-12-29 (1)
+U8AE9	anonymous	2008-12-29 (2)
+U8AE9	anonymous	2008-12-29 (3)
+U8AE9	anonymous	2008-12-29 (4)
+U8AF9	anonymous	2008-12-29 (1)
+U5A2C	anonymous	2008-12-29 (1)
+U5A2C	anonymous	2008-12-29 (2)
+U5A3A	anonymous	2008-12-29 (1)
+U5A3D	anonymous	2008-12-29 (1)
+U5A3D	anonymous	2008-12-29 (2)
+U5FEC	anonymous	2008-12-29 (1)
+U9241	anonymous	2008-12-29 (1)
+U922B	anonymous	2008-12-29 (1)
+U9242	anonymous	2008-12-29 (1)
+U91E0	anonymous	2008-12-29 (1)
+U6FBB	anonymous	2008-12-29 (1)
+U7402	anonymous	2008-12-29 (1)
+U8A1C	anonymous	2008-12-29 (1)
+U8A21	anonymous	2008-12-29 (1)
+U8A26	anonymous	2008-12-29 (1)
+U7250	anonymous	2008-12-29 (1)
+U8F3C	anonymous	2008-12-29 (1)
+U8F41	anonymous	2008-12-29 (1)
+U8F41	anonymous	2008-12-29 (2)
+U8F41	anonymous	2008-12-29 (3)
+U79F5	anonymous	2008-12-29 (1)
+U7A16	anonymous	2008-12-29 (1)
+U7A07	anonymous	2008-12-29 (1)
+U7A0F	anonymous	2008-12-29 (1)
+U5086	anonymous	2008-12-29 (1)
+U9C38	anonymous	2008-12-29 (1)
+U7CE3	anonymous	2008-12-29 (1)
+U667F	anonymous	2008-12-29 (1)
+U7639	FangQ	2008-12-29 (1)
+U7644	FangQ	2008-12-29 (1)
+U7220	FangQ	2008-12-29 (1)
+U692C	FangQ	2008-12-29 (1)
+U692E	FangQ	2008-12-29 (1)
+U692B	FangQ	2008-12-29 (1)
+U691D	FangQ	2008-12-29 (1)
+U9BD0	anonymous	2008-12-29 (1)
+U94DA	anonymous	2008-12-29 (1)
+U9BD8	anonymous	2008-12-29 (1)
+U9C7D	anonymous	2008-12-29 (1)
+U9BF6	anonymous	2008-12-29 (1)
+U890D	anonymous	2008-12-29 (1)
+U51C2	anonymous	2008-12-29 (1)
+U51C1	anonymous	2008-12-29 (1)
+U69EF	fcicq	2008-12-29 (1)
+U51BA	anonymous	2008-12-29 (1)
+U69FA	fcicq	2008-12-29 (1)
+U8224	fcicq	2008-12-29 (1)
+U9258	anonymous	2008-12-29 (1)
+U925C	anonymous	2008-12-29 (1)
+U9C97	fcicq	2008-12-29 (1)
+U925D	anonymous	2008-12-29 (1)
+U7C8F	fcicq	2008-12-29 (1)
+U9579	anonymous	2008-12-29 (1)
+U4F37	fcicq	2008-12-29 (1)
+U4F42	fcicq	2008-12-29 (1)
+U4F4B	fcicq	2008-12-29 (1)
+U86E5	fcicq	2008-12-29 (1)
+U9BF9	anonymous	2008-12-29 (1)
+U86FF	fcicq	2008-12-29 (1)
+U77DD	fcicq	2008-12-29 (1)
+U9C1F	anonymous	2008-12-29 (1)
+U77DF	fcicq	2008-12-29 (1)
+U520F	anonymous	2008-12-29 (1)
+U663D	fcicq	2008-12-29 (1)
+U664E	fcicq	2008-12-29 (1)
+U9C22	anonymous	2008-12-29 (1)
+U6660	fcicq	2008-12-29 (1)
+U682C	fcicq	2008-12-29 (1)
+U9C2A	anonymous	2008-12-29 (1)
+U7EB4	fcicq	2008-12-29 (1)
+U4F93	fcicq	2008-12-29 (1)
+U4FA4	fcicq	2008-12-29 (1)
+U9C98	fcicq	2008-12-29 (1)
+U8254	anonymous	2008-12-29 (1)
+U7418	anonymous	2008-12-29 (1)
+U7561	anonymous	2008-12-29 (1)
+U9B8C	anonymous	2008-12-29 (1)
+U7922	anonymous	2008-12-29 (1)
+U55A0	anonymous	2008-12-29 (1)
+U9345	anonymous	2008-12-29 (1)
+U918E	anonymous	2008-12-29 (1)
+U4FB0	anonymous	2008-12-29 (1)
+U7177	anonymous	2008-12-29 (1)
+U9AD7	anonymous	2008-12-29 (1)
+U7721	anonymous	2008-12-29 (1)
+U4F66	anonymous	2008-12-29 (1)
+U988E	anonymous	2008-12-29 (1)
+U9C27	anonymous	2008-12-29 (1)
+U7355		2008-12-29 (1)
+U8744		2008-12-29 (1)
+U8772		2008-12-29 (1)
+U7861		2008-12-29 (1)
+U787D		2008-12-29 (1)
+U7878		2008-12-29 (1)
+U9C27	FangQ	2008-12-29 (2)
+U604F	mozbug	2008-12-29 (1)
+U7E6C	mozbug	2008-12-29 (1)
+U7E6E	mozbug	2008-12-29 (1)
+U7E85	mozbug	2008-12-29 (1)
+U7E84	mozbug	2008-12-29 (1)
+U87F0	FangQ	2008-12-29 (1)
+U87F1	FangQ	2008-12-29 (1)
+U67E8	anonymous	2008-12-29 (1)
+U7CA9	anonymous	2008-12-29 (1)
+U96E4	anonymous	2008-12-29 (1)
+U8B9B	anonymous	2008-12-29 (1)
+U8B91	anonymous	2008-12-29 (1)
+U9E3C	anonymous	2008-12-29 (1)
+U53FF	anonymous	2008-12-30 (1)
+U9BC2	anonymous	2008-12-30 (2)
+U692B	anonymous	2008-12-30 (2)
+U82EE	anonymous	2008-12-30 (1)
+U573C	anonymous	2008-12-30 (1)
+U692C	anonymous	2008-12-30 (2)
+U9656	anonymous	2008-12-30 (1)
+U73B1	anonymous	2008-12-30 (2)
+U801A	anonymous	2008-12-30 (2)
+U7677	anonymous	2008-12-30 (1)
+U801D	anonymous	2008-12-30 (2)
+U65EB	anonymous	2008-12-30 (1)
+U9BC5	anonymous	2008-12-30 (2)
+U65F8	anonymous	2008-12-30 (2)
+U692E	anonymous	2008-12-30 (2)
+U5CCD	anonymous	2008-12-30 (1)
+U6601	anonymous	2008-12-30 (1)
+U6931	anonymous	2008-12-30 (2)
+U693A	anonymous	2008-12-30 (2)
+U55F1	FangQ	2008-12-30 (1)
+U9BCB	anonymous	2008-12-30 (2)
+U8B5E	anonymous	2008-12-30 (1)
+U6931	anonymous	2008-12-30 (3)
+U6D23	anonymous	2008-12-30 (1)
+U90C6	anonymous	2008-12-30 (1)
+U559B	anonymous	2008-12-30 (1)
+U8804	anonymous	2008-12-30 (1)
+U6CB5	anonymous	2008-12-30 (1)
+U6CC8	anonymous	2008-12-30 (1)
+U830A	anonymous	2008-12-30 (1)
+U581A	anonymous	2008-12-30 (1)
+U93B8	anonymous	2008-12-30 (1)
+U97C2	anonymous	2008-12-30 (1)
+U6985	anonymous	2008-12-30 (1)
+U97B1	anonymous	2008-12-30 (1)
+U794E	anonymous	2008-12-30 (1)
+U802B	anonymous	2008-12-30 (1)
+U7DE2	anonymous	2008-12-30 (1)
+U7DFC	anonymous	2008-12-30 (1)
+U5CC2	anonymous	2008-12-30 (1)
+U599F	anonymous	2008-12-30 (1)
+U80B0	anonymous	2008-12-30 (1)
+U88E9	anonymous	2008-12-30 (1)
+U8920	anonymous	2008-12-30 (1)
+U7DED	anonymous	2008-12-30 (1)
+U65C7	FangQ	2008-12-30 (1)
+U97B0	anonymous	2008-12-30 (1)
+U4E63	anonymous	2008-12-30 (1)
+U80B3	anonymous	2008-12-30 (1)
+U80B6	anonymous	2008-12-30 (1)
+U503D	anonymous	2008-12-30 (1)
+U7DD4	anonymous	2008-12-30 (1)
+U988B	anonymous	2008-12-30 (1)
+U97BC	anonymous	2008-12-30 (1)
+U7841	anonymous	2008-12-30 (1)
+U6CCE	anonymous	2008-12-30 (1)
+U7DEB	anonymous	2008-12-30 (1)
+U784B	anonymous	2008-12-30 (1)
+U747A	anonymous	2008-12-30 (1)
+U70E3	anonymous	2008-12-30 (1)
+U747B	anonymous	2008-12-30 (1)
+U8924	anonymous	2008-12-30 (1)
+U7304	anonymous	2008-12-30 (1)
+U9B3D	anonymous	2008-12-30 (1)
+U7491	anonymous	2008-12-30 (1)
+U78A6	anonymous	2008-12-30 (1)
+U95AF	anonymous	2008-12-30 (1)
+U69DA	anonymous	2008-12-30 (1)
+U4E68	anonymous	2008-12-30 (1)
+U7DFC	anonymous	2008-12-30 (2)
+U96A6	anonymous	2008-12-30 (1)
+U7458	anonymous	2008-12-30 (1)
+U64A8	anonymous	2008-12-30 (1)
+U55BA	anonymous	2008-12-30 (1)
+U7890	anonymous	2008-12-30 (1)
+U7461	anonymous	2008-12-30 (1)
+U926B	anonymous	2008-12-30 (1)
+U7770	anonymous	2008-12-30 (1)
+U76FF	anonymous	2008-12-30 (1)
+U98F5	anonymous	2008-12-30 (1)
+U772A	anonymous	2008-12-30 (1)
+U64A7	anonymous	2008-12-30 (1)
+U8D83	anonymous	2008-12-30 (1)
+U76F6	anonymous	2008-12-30 (1)
+U8DD2	anonymous	2008-12-30 (1)
+U9DAE	anonymous	2008-12-30 (1)
+U9DAE	anonymous	2008-12-30 (2)
+U6663	anonymous	2008-12-30 (1)
+U5569	anonymous	2008-12-30 (1)
+U5744	anonymous	2008-12-30 (1)
+U9E65	anonymous	2008-12-30 (1)
+U5B8A	anonymous	2008-12-30 (1)
+U5E65	anonymous	2008-12-30 (1)
+U871D	anonymous	2008-12-30 (1)
+U6DB6	anonymous	2008-12-30 (1)
+U6B85	anonymous	2008-12-30 (1)
+U5574	anonymous	2008-12-30 (1)
+U8B09	anonymous	2008-12-30 (1)
+U871D	anonymous	2008-12-30 (2)
+U52FD	anonymous	2008-12-30 (1)
+U8B73	anonymous	2008-12-30 (1)
+U6542	anonymous	2008-12-30 (1)
+U9F5A	anonymous	2008-12-30 (1)
+U5AA3	anonymous	2008-12-30 (1)
+U635B	anonymous	2008-12-30 (1)
+U871D	anonymous	2008-12-30 (3)
+U59B0	anonymous	2008-12-30 (1)
+U871D	anonymous	2008-12-30 (4)
+U966E	anonymous	2008-12-30 (1)
+U5AC3	anonymous	2008-12-30 (1)
+U59AD	anonymous	2008-12-30 (1)
+U7CB8	anonymous	2008-12-30 (1)
+U5226	anonymous	2008-12-30 (1)
+U59DF	anonymous	2008-12-30 (1)
+U545A	anonymous	2008-12-30 (1)
+U5B12	anonymous	2008-12-30 (1)
+U6306	anonymous	2008-12-30 (1)
+U545A	anonymous	2008-12-30 (2)
+U6823	anonymous	2008-12-30 (1)
+U6317	anonymous	2008-12-30 (1)
+U545A	anonymous	2008-12-30 (3)
+U632E	anonymous	2008-12-30 (1)
+U54F4	anonymous	2008-12-30 (1)
+U632E	anonymous	2008-12-30 (2)
+U7588	anonymous	2008-12-30 (1)
+U7975	anonymous	2008-12-30 (1)
+U9979	anonymous	2008-12-30 (1)
+U9C99	anonymous	2008-12-30 (1)
+U718B	anonymous	2008-12-30 (1)
+U57C4	anonymous	2008-12-30 (1)
+U92D6	anonymous	2008-12-30 (1)
+U9C99	anonymous	2008-12-30 (2)
+U57C9	anonymous	2008-12-30 (1)
+U57CD	anonymous	2008-12-30 (1)
+U79DB	anonymous	2008-12-30 (1)
+U5A8D	anonymous	2008-12-30 (1)
+U9218	anonymous	2008-12-30 (1)
+U4EE0	anonymous	2008-12-30 (1)
+U718C	anonymous	2008-12-30 (1)
+U8E71	anonymous	2008-12-30 (1)
+U5388	anonymous	2008-12-30 (1)
+U6257	anonymous	2008-12-30 (1)
+U4EE2	anonymous	2008-12-30 (1)
+U625D	anonymous	2008-12-30 (1)
+U4EEF	anonymous	2008-12-30 (1)
+U788B	anonymous	2008-12-30 (1)
+U5644	anonymous	2008-12-30 (1)
+U805B	anonymous	2008-12-30 (1)
+U72C7	anonymous	2008-12-30 (1)
+U625F	anonymous	2008-12-30 (1)
+U7ED6	anonymous	2008-12-30 (1)
+U718D	anonymous	2008-12-30 (1)
+U6360	anonymous	2008-12-30 (1)
+U689A	anonymous	2008-12-30 (1)
+U718E	anonymous	2008-12-30 (1)
+U5735	anonymous	2008-12-30 (1)
+U79E8	anonymous	2008-12-30 (1)
+U6364	anonymous	2008-12-30 (1)
+U7ED6	anonymous	2008-12-30 (2)
+U4EFA	anonymous	2008-12-30 (1)
+U9A8E	anonymous	2008-12-30 (1)
+U7191	anonymous	2008-12-30 (1)
+U68BE	anonymous	2008-12-30 (1)
+U4F07	anonymous	2008-12-30 (1)
+U551E	anonymous	2008-12-30 (1)
+U57A8	anonymous	2008-12-30 (1)
+U7112	anonymous	2008-12-30 (1)
+U5A3B	anonymous	2008-12-30 (1)
+U6830	anonymous	2008-12-30 (1)
+U9194	anonymous	2008-12-30 (1)
+U9BBC	anonymous	2008-12-30 (1)
+U79E8	anonymous	2008-12-30 (2)
+U5A45	anonymous	2008-12-30 (1)
+U57C5	anonymous	2008-12-30 (1)
+U61D3	anonymous	2008-12-30 (1)
+U81F5	anonymous	2008-12-30 (1)
+U9196	anonymous	2008-12-30 (1)
+U64DC	anonymous	2008-12-30 (1)
+U56BA	anonymous	2008-12-30 (1)
+U65EA	anonymous	2008-12-30 (1)
+U57CA	anonymous	2008-12-30 (1)
+U7859	anonymous	2008-12-30 (1)
+U5DCA	anonymous	2008-12-30 (1)
+U5A91	anonymous	2008-12-30 (1)
+U5B5E	anonymous	2008-12-30 (1)
+U5F2B	anonymous	2008-12-30 (1)
+U512F	anonymous	2008-12-30 (1)
+U50BC	anonymous	2008-12-30 (1)
+U8060	anonymous	2008-12-30 (1)
+U9657	anonymous	2008-12-30 (1)
+U953D	anonymous	2008-12-30 (1)
+U72E5	anonymous	2008-12-30 (1)
+U676B	anonymous	2008-12-30 (1)
+U686A	anonymous	2008-12-30 (1)
+U9EA8	anonymous	2008-12-30 (1)
+U8213	anonymous	2008-12-30 (1)
+U7846	anonymous	2008-12-30 (1)
+U7A52	anonymous	2008-12-30 (1)
+U7C76	anonymous	2008-12-30 (1)
+U7853	anonymous	2008-12-30 (1)
+U9BFB	anonymous	2008-12-30 (1)
+U55AF	anonymous	2008-12-30 (1)
+U821A	anonymous	2008-12-30 (1)
+U72D5	anonymous	2008-12-30 (1)
+U9EAB	anonymous	2008-12-30 (1)
+U6429	anonymous	2008-12-30 (1)
+U8175	anonymous	2008-12-30 (1)
+U72E7	anonymous	2008-12-30 (1)
+U8226	anonymous	2008-12-30 (1)
+U872B	anonymous	2008-12-30 (1)
+U5746	anonymous	2008-12-30 (1)
+U9BFC	anonymous	2008-12-30 (1)
+U9EB3	anonymous	2008-12-30 (1)
+U5AA8	anonymous	2008-12-30 (1)
+U59BF	anonymous	2008-12-30 (1)
+U9EC6	anonymous	2008-12-30 (1)
+U99B7	anonymous	2008-12-30 (1)
+U7306	anonymous	2008-12-30 (1)
+U9E2E	anonymous	2008-12-30 (1)
+U53DE	anonymous	2008-12-30 (1)
+U6824	anonymous	2008-12-30 (1)
+U4F4A	anonymous	2008-12-30 (1)
+U8063	anonymous	2008-12-30 (1)
+U97F7	anonymous	2008-12-30 (1)
+U71D3	anonymous	2008-12-30 (1)
+U813F	anonymous	2008-12-30 (1)
+U6847	anonymous	2008-12-30 (1)
+U7ACE	anonymous	2008-12-30 (1)
+U4F8C	anonymous	2008-12-30 (1)
+U9A94	anonymous	2008-12-30 (1)
+U8417	anonymous	2008-12-30 (1)
+U73FB	anonymous	2008-12-30 (1)
+U6A1C	anonymous	2008-12-30 (1)
+U576C	anonymous	2008-12-30 (1)
+U5519	anonymous	2008-12-30 (1)
+U50C0	anonymous	2008-12-30 (1)
+U79D3	anonymous	2008-12-30 (1)
+U8E68	anonymous	2008-12-30 (1)
+U969F	anonymous	2008-12-30 (1)
+U698F	anonymous	2008-12-30 (1)
+U88A9	anonymous	2008-12-30 (1)
+U5CB2	anonymous	2008-12-30 (1)
+U9BA7	anonymous	2008-12-30 (1)
+U6616	anonymous	2008-12-30 (1)
+U5FDF	anonymous	2008-12-30 (1)
+U5A0E	anonymous	2008-12-30 (1)
+U57EA	anonymous	2008-12-30 (1)
+U57EB	anonymous	2008-12-30 (1)
+U52E1	anonymous	2008-12-30 (1)
+U7786	anonymous	2008-12-30 (1)
+U6B6B	anonymous	2008-12-30 (1)
+U7FB4	anonymous	2008-12-30 (1)
+U8480	anonymous	2008-12-30 (1)
+U8260	anonymous	2008-12-30 (1)
+U796E	anonymous	2008-12-30 (1)
+U54FE	anonymous	2008-12-30 (1)
+U5C78	anonymous	2008-12-30 (1)
+U63FE	anonymous	2008-12-30 (1)
+U7CAC	anonymous	2008-12-30 (1)
+U9AAE	anonymous	2008-12-30 (1)
+U6E06	anonymous	2008-12-30 (1)
+U52ED	anonymous	2008-12-30 (1)
+U56E9	anonymous	2008-12-30 (1)
+U9096	anonymous	2008-12-30 (1)
+U7FC4	anonymous	2008-12-30 (1)
+U6B35	anonymous	2008-12-30 (1)
+U6366	anonymous	2008-12-30 (1)
+U683F	anonymous	2008-12-30 (1)
+U6E6D	anonymous	2008-12-30 (1)
+U9CDB	anonymous	2008-12-30 (1)
+U9CC2	anonymous	2008-12-30 (1)
+U5D2F	anonymous	2008-12-30 (1)
+U78F0	anonymous	2008-12-30 (1)
+U6782	anonymous	2008-12-30 (1)
+U6782	anonymous	2008-12-30 (2)
+U8248	anonymous	2008-12-30 (1)
+U5497	anonymous	2008-12-30 (1)
+U5A59	anonymous	2008-12-30 (1)
+U9CC9	anonymous	2008-12-30 (1)
+U4F23	anonymous	2008-12-30 (1)
+U5493	anonymous	2008-12-30 (1)
+U9DE0	anonymous	2008-12-30 (1)
+U5D3B	anonymous	2008-12-30 (1)
+U7C9A	anonymous	2008-12-30 (1)
+U619E	anonymous	2008-12-30 (1)
+U549E	anonymous	2008-12-30 (1)
+U928F	anonymous	2008-12-30 (1)
+U8DD4	anonymous	2008-12-30 (1)
+U54B9	anonymous	2008-12-30 (1)
+U69DC	anonymous	2008-12-30 (1)
+U7854	anonymous	2008-12-30 (1)
+U4F28	anonymous	2008-12-30 (1)
+U9CDA	anonymous	2008-12-30 (1)
+U8A80	anonymous	2008-12-30 (1)
+U8ED6	anonymous	2008-12-30 (1)
+U69E1	anonymous	2008-12-30 (1)
+U709E	anonymous	2008-12-30 (1)
+U5F06	anonymous	2008-12-30 (1)
+U7790	anonymous	2008-12-30 (1)
+U916B	anonymous	2008-12-30 (1)
+U8A78	anonymous	2008-12-30 (1)
+U8EB7	anonymous	2008-12-30 (1)
+U5F8D	anonymous	2008-12-30 (1)
+U889D	anonymous	2008-12-30 (1)
+U5223	anonymous	2008-12-30 (1)
+U5003	anonymous	2008-12-30 (1)
+U8A5F	anonymous	2008-12-30 (1)
+U5FF2	anonymous	2008-12-30 (1)
+U7757	anonymous	2008-12-30 (1)
+U604E	anonymous	2008-12-30 (1)
+U9555	anonymous	2008-12-30 (1)
+U6285	anonymous	2008-12-30 (1)
+U6C53	anonymous	2008-12-30 (1)
+U9159	anonymous	2008-12-30 (1)
+U6C1C	anonymous	2008-12-30 (1)
+U8CCB	anonymous	2008-12-30 (1)
+U9A5D	anonymous	2008-12-30 (1)
+U71AD	anonymous	2008-12-30 (1)
+U69B8	anonymous	2008-12-30 (1)
+U5DB6	anonymous	2008-12-30 (1)
+U88C8	anonymous	2008-12-30 (1)
+U4F0C	anonymous	2008-12-30 (1)
+U546E	anonymous	2008-12-30 (1)
+U8CA6	anonymous	2008-12-30 (1)
+U91FA	anonymous	2008-12-30 (1)
+U7309	anonymous	2008-12-30 (1)
+U8F6A	anonymous	2008-12-30 (1)
+U5AD1	anonymous	2008-12-30 (1)
+U91F0	anonymous	2008-12-30 (1)
+U5AD1	anonymous	2008-12-30 (2)
+U80E2	anonymous	2008-12-30 (1)
+U7FAA	anonymous	2008-12-30 (1)
+U712A	anonymous	2008-12-30 (1)
+U67A4	anonymous	2008-12-30 (1)
+U585F	anonymous	2008-12-30 (1)
+U6275	anonymous	2008-12-30 (1)
+U80D2	anonymous	2008-12-30 (1)
+U67A4	anonymous	2008-12-30 (2)
+U99A9	anonymous	2008-12-30 (1)
+U98E4	anonymous	2008-12-30 (1)
+U5E52	anonymous	2008-12-30 (1)
+U844F		2008-12-30 (1)
+U5D2B	anonymous	2008-12-30 (1)
+U6A7D	anonymous	2008-12-30 (1)
+U84D5	anonymous	2008-12-30 (1)
+U6752	anonymous	2008-12-30 (1)
+U577A	anonymous	2008-12-30 (1)
+U549F	anonymous	2008-12-30 (1)
+U8168	anonymous	2008-12-30 (1)
+U74EB	anonymous	2008-12-30 (1)
+U71CD	anonymous	2008-12-30 (1)
+U5A4F	anonymous	2008-12-30 (1)
+U5479	anonymous	2008-12-30 (1)
+U8184	anonymous	2008-12-30 (1)
+U6B9D	anonymous	2008-12-30 (1)
+U6E4C	anonymous	2008-12-30 (1)
+U5FCA	anonymous	2008-12-30 (1)
+U5483	anonymous	2008-12-30 (1)
+U5FCB	anonymous	2008-12-30 (1)
+U925F	anonymous	2008-12-30 (1)
+U54F5	anonymous	2008-12-30 (1)
+U54CA	anonymous	2008-12-30 (1)
+U5FE2	anonymous	2008-12-30 (1)
+U65C9	anonymous	2008-12-30 (1)
+U8281	anonymous	2008-12-30 (1)
+U5A54	anonymous	2008-12-30 (1)
+U6E4F	anonymous	2008-12-30 (1)
+U6E4F	anonymous	2008-12-30 (1)
+U6093	anonymous	2008-12-30 (1)
+U5F7A	anonymous	2008-12-30 (1)
+U636A	anonymous	2008-12-30 (1)
+U5F8D	anonymous	2008-12-30 (2)
+U6099		2008-12-30 (1)
+U5FA2	anonymous	2008-12-30 (1)
+U7A5D	anonymous	2008-12-30 (1)
+U8AAF	anonymous	2008-12-30 (1)
+U5F68	anonymous	2008-12-30 (1)
+U8E6E	anonymous	2008-12-30 (1)
+U6093		2008-12-30 (2)
+U88ED	anonymous	2008-12-30 (1)
+U7933	anonymous	2008-12-30 (1)
+U7772	anonymous	2008-12-30 (1)
+U88FF	anonymous	2008-12-30 (1)
+U7D7E	anonymous	2008-12-30 (1)
+U7771	anonymous	2008-12-30 (1)
+U9221	anonymous	2008-12-30 (1)
+U7685	anonymous	2008-12-30 (1)
+U6788	anonymous	2008-12-30 (1)
+U7777	anonymous	2008-12-30 (1)
+U6318	anonymous	2008-12-30 (1)
+U7824	anonymous	2008-12-30 (1)
+U7778	anonymous	2008-12-30 (1)
+U9268	anonymous	2008-12-30 (1)
+U637E	anonymous	2008-12-30 (1)
+U57DE	anonymous	2008-12-30 (1)
+U5748	anonymous	2008-12-30 (1)
+U777A	anonymous	2008-12-30 (1)
+U768C	anonymous	2008-12-30 (1)
+U5FC7	anonymous	2008-12-30 (1)
+U57D1	anonymous	2008-12-30 (1)
+U6BF1	anonymous	2008-12-30 (1)
+U57E6	anonymous	2008-12-30 (1)
+U9787	anonymous	2008-12-30 (1)
+U537E	anonymous	2008-12-30 (1)
+U8B2D	anonymous	2008-12-30 (1)
+U5FFC	anonymous	2008-12-30 (1)
+U99CA	anonymous	2008-12-30 (1)
+U5FF9	anonymous	2008-12-30 (1)
+U9064	anonymous	2008-12-30 (1)
+U78AE	anonymous	2008-12-30 (1)
+U797B	anonymous	2008-12-30 (1)
+U5FE6	anonymous	2008-12-30 (1)
+U676E	anonymous	2008-12-30 (1)
+U769F	anonymous	2008-12-30 (1)
+U7842	anonymous	2008-12-30 (1)
+U5A10	anonymous	2008-12-30 (1)
+U5376	anonymous	2008-12-30 (1)
+U6796	anonymous	2008-12-30 (1)
+U8B43	anonymous	2008-12-30 (1)
+U6796	anonymous	2008-12-30 (2)
+U9B5D	anonymous	2008-12-30 (1)
+U7C77	anonymous	2008-12-30 (1)
+U8B64	anonymous	2008-12-30 (1)
+U6947	anonymous	2008-12-30 (1)
+U8059	anonymous	2008-12-30 (1)
+U6373	anonymous	2008-12-30 (1)
+U7C86	anonymous	2008-12-30 (1)
+U8DCA	anonymous	2008-12-30 (1)
+U6A98	anonymous	2008-12-30 (1)
+U669B	anonymous	2008-12-30 (1)
+U7C87	anonymous	2008-12-30 (1)
+U86B2	anonymous	2008-12-30 (1)
+U5845	anonymous	2008-12-30 (1)
+U7CC3	anonymous	2008-12-30 (1)
+U9681	anonymous	2008-12-30 (1)
+U6E81	anonymous	2008-12-30 (1)
+U7892	anonymous	2008-12-30 (1)
+U6379	anonymous	2008-12-30 (1)
+U699F	anonymous	2008-12-30 (1)
+U8A42	anonymous	2008-12-30 (1)
+U878E	anonymous	2008-12-30 (1)
+U6BE9		2008-12-30 (1)
+U785F	anonymous	2008-12-30 (1)
+U5C85	anonymous	2008-12-30 (1)
+U52B7	anonymous	2008-12-30 (1)
+U9C4F	anonymous	2008-12-30 (1)
+U8A43	anonymous	2008-12-30 (1)
+U8A47	anonymous	2008-12-30 (1)
+U699F	anonymous	2008-12-30 (2)
+U5A12	anonymous	2008-12-30 (1)
+U52C8	anonymous	2008-12-30 (1)
+U7936	anonymous	2008-12-30 (1)
+U78E4	anonymous	2008-12-30 (1)
+U6BFA		2008-12-30 (1)
+U86D2	anonymous	2008-12-30 (1)
+U97E8	anonymous	2008-12-30 (1)
+U7937	anonymous	2008-12-30 (1)
+U5248		2008-12-30 (1)
+U58AA	anonymous	2008-12-30 (1)
+U7936	anonymous	2008-12-30 (2)
+U910C	anonymous	2008-12-30 (1)
+U70A0	anonymous	2008-12-30 (1)
+U80A6	anonymous	2008-12-30 (1)
+U523E		2008-12-30 (1)
+U6E75	anonymous	2008-12-30 (1)
+U96AD	anonymous	2008-12-30 (1)
+U8097	anonymous	2008-12-30 (1)
+U86D5	anonymous	2008-12-30 (1)
+U9543	anonymous	2008-12-30 (1)
+U7943	anonymous	2008-12-30 (1)
+U6754	anonymous	2008-12-30 (1)
+U9E27	anonymous	2008-12-30 (1)
+U7157	anonymous	2008-12-30 (1)
+U6732	anonymous	2008-12-30 (1)
+U998E	anonymous	2008-12-30 (1)
+U52CF	anonymous	2008-12-30 (1)
+U5FF6	anonymous	2008-12-30 (1)
+U8BEA	anonymous	2008-12-30 (1)
+U51C3	anonymous	2008-12-30 (1)
+U5257		2008-12-30 (1)
+U5C83		2008-12-30 (1)
+U9290	anonymous	2008-12-30 (1)
+U523C		2008-12-30 (1)
+U7932	anonymous	2008-12-30 (1)
+U9E3B	anonymous	2008-12-30 (1)
+U523C		2008-12-30 (2)
+U86E1	anonymous	2008-12-30 (1)
+U98F0	anonymous	2008-12-30 (1)
+U5D48	anonymous	2008-12-30 (1)
+U7AD0	anonymous	2008-12-30 (1)
+U4FE2	anonymous	2008-12-30 (1)
+U77A6	anonymous	2008-12-30 (1)
+U4FE7	anonymous	2008-12-30 (1)
+U77AE	anonymous	2008-12-30 (1)
+U8A9B	anonymous	2008-12-30 (1)
+U7CC4	anonymous	2008-12-30 (1)
+U7558	anonymous	2008-12-30 (1)
+U77AF	anonymous	2008-12-30 (1)
+U4FBE	anonymous	2008-12-30 (1)
+U4FEB	anonymous	2008-12-30 (1)
+U86FC	anonymous	2008-12-30 (1)
+U4FC8	anonymous	2008-12-30 (1)
+U4FCC	anonymous	2008-12-30 (1)
+U4FF9	anonymous	2008-12-30 (1)
+U6DB9	anonymous	2008-12-30 (1)
+U4FD2	anonymous	2008-12-30 (1)
+U8C1E	anonymous	2008-12-30 (1)
+U77B8	anonymous	2008-12-30 (1)
+U8F80	anonymous	2008-12-30 (1)
+U8980	anonymous	2008-12-30 (1)
+U8C40	anonymous	2008-12-30 (1)
+U8F8C	anonymous	2008-12-30 (1)
+U7364	anonymous	2008-12-30 (1)
+U8156	anonymous	2008-12-30 (1)
+U77BE	anonymous	2008-12-30 (1)
+U577E	anonymous	2008-12-30 (1)
+U5A85	anonymous	2008-12-30 (1)
+U6F28	anonymous	2008-12-30 (1)
+U81E4	anonymous	2008-12-30 (1)
+U71EF	anonymous	2008-12-30 (1)
+U6007	anonymous	2008-12-30 (1)
+U86FD	anonymous	2008-12-30 (1)
+U8795	anonymous	2008-12-30 (1)
+U8F04	anonymous	2008-12-30 (1)
+U598B	anonymous	2008-12-30 (1)
+U5754	anonymous	2008-12-30 (1)
+U785A	anonymous	2008-12-30 (1)
+U86AE	anonymous	2008-12-30 (1)
+U963E	anonymous	2008-12-30 (1)
+U74C4	anonymous	2008-12-30 (1)
+U5422	anonymous	2008-12-30 (1)
+U9641	anonymous	2008-12-30 (1)
+U61DC	anonymous	2008-12-30 (1)
+U550D	anonymous	2008-12-30 (1)
+U9652	anonymous	2008-12-30 (1)
+U7EEC	anonymous	2008-12-30 (1)
+U9659	anonymous	2008-12-30 (1)
+U86D5	anonymous	2008-12-30 (2)
+U7520	anonymous	2008-12-30 (1)
+U965A	anonymous	2008-12-30 (1)
+U8A24	anonymous	2008-12-30 (1)
+U5FB0	anonymous	2008-12-30 (1)
+U5D04	anonymous	2008-12-30 (1)
+U70C4	anonymous	2008-12-30 (1)
+U8B69	anonymous	2008-12-30 (1)
+U8E2D	anonymous	2008-12-30 (1)
+U7053	anonymous	2008-12-30 (1)
+U8E37	anonymous	2008-12-30 (1)
+U5D44	anonymous	2008-12-30 (1)
+U818E	anonymous	2008-12-30 (1)
+U7417	anonymous	2008-12-30 (1)
+U7417	anonymous	2008-12-30 (2)
+U66B6	anonymous	2008-12-30 (1)
+U618F	anonymous	2008-12-30 (1)
+U9EC7	anonymous	2008-12-30 (1)
+U5651	wanghong	2008-12-30 (1)
+U92B0	anonymous	2008-12-30 (1)
+U5071	anonymous	2008-12-30 (1)
+U61D9	anonymous	2008-12-30 (1)
+U8053	anonymous	2008-12-30 (1)
+U5621	anonymous	2008-12-30 (1)
+U77F4	fcicq	2008-12-30 (1)
+U5620	anonymous	2008-12-30 (1)
+U781E	fcicq	2008-12-30 (1)
+U806D	anonymous	2008-12-30 (1)
+U77F5	fcicq	2008-12-30 (1)
+U7851	fcicq	2008-12-30 (1)
+U7415	anonymous	2008-12-30 (1)
+U9A61	anonymous	2008-12-30 (1)
+U9E62	anonymous	2008-12-30 (1)
+U9F27	anonymous	2008-12-30 (1)
+U7415	anonymous	2008-12-30 (2)
+U5279	fcicq	2008-12-30 (1)
+U8CC6	anonymous	2008-12-30 (1)
+U70B6	anonymous	2008-12-30 (1)
+U7415	fcicq	2008-12-30 (3)
+U92E5	anonymous	2008-12-30 (1)
+U70A5	anonymous	2008-12-30 (1)
+U9390	anonymous	2008-12-30 (1)
+U99A4	anonymous	2008-12-30 (1)
+U9386	anonymous	2008-12-30 (1)
+U8EAE	anonymous	2008-12-30 (1)
+U9381	anonymous	2008-12-30 (1)
+U78B8	anonymous	2008-12-30 (1)
+U9387	anonymous	2008-12-30 (1)
+U7C71	anonymous	2008-12-30 (1)
+U6DB1	anonymous	2008-12-30 (1)
+U7D8B	anonymous	2008-12-30 (1)
+U9284	anonymous	2008-12-30 (1)
+U78BD	anonymous	2008-12-30 (1)
+U5847	anonymous	2008-12-30 (1)
+U5850	anonymous	2008-12-30 (1)
+U78D3	anonymous	2008-12-30 (1)
+U5860	anonymous	2008-12-30 (1)
+U5EF9	anonymous	2008-12-30 (1)
+U78BF	anonymous	2008-12-30 (1)
+U9660	anonymous	2008-12-30 (1)
+U920B	anonymous	2008-12-30 (1)
+U78D2	anonymous	2008-12-30 (1)
+U645A	anonymous	2008-12-30 (1)
+U5004	anonymous	2008-12-30 (1)
+U8A38	anonymous	2008-12-30 (1)
+U7FAB	anonymous	2008-12-30 (1)
+U8194	anonymous	2008-12-30 (1)
+U7CC6	anonymous	2008-12-30 (1)
+U6E12	anonymous	2008-12-30 (1)
+U9A95	anonymous	2008-12-30 (1)
+U882D	anonymous	2008-12-30 (1)
+U6502	anonymous	2008-12-30 (1)
+U56CF	anonymous	2008-12-30 (1)
+U6E1E	anonymous	2008-12-30 (1)
+U5E0D	anonymous	2008-12-30 (1)
+U5FBA	anonymous	2008-12-30 (1)
+U6A2C	anonymous	2008-12-30 (1)
+U7FC8	anonymous	2008-12-30 (1)
+U57DB	anonymous	2008-12-30 (1)
+U6B26	anonymous	2008-12-30 (1)
+U5A86	anonymous	2008-12-30 (1)
+U9C1E	anonymous	2008-12-30 (1)
+U79E2	anonymous	2008-12-30 (1)
+U7DC8	anonymous	2008-12-30 (1)
+U888A	anonymous	2008-12-30 (1)
+U565F	anonymous	2008-12-30 (1)
+U8894	anonymous	2008-12-30 (1)
+U7FD3	anonymous	2008-12-30 (1)
+U9C26	anonymous	2008-12-30 (1)
+U5B00	anonymous	2008-12-30 (1)
+U88BB	anonymous	2008-12-30 (1)
+U88C7	anonymous	2008-12-30 (1)
+U9C35	anonymous	2008-12-30 (1)
+U9C7E	anonymous	2008-12-30 (1)
+U9CAC	anonymous	2008-12-30 (1)
+U71E9	anonymous	2008-12-30 (1)
+U9CAF	anonymous	2008-12-30 (1)
+U78D7	anonymous	2008-12-30 (1)
+U9C51	anonymous	2008-12-30 (1)
+U8241	anonymous	2008-12-30 (1)
+U9424	anonymous	2008-12-30 (1)
+U9424	anonymous	2008-12-30 (2)
+U76A3	anonymous	2008-12-30 (1)
+U65C0	anonymous	2008-12-30 (1)
+U9ED7	anonymous	2008-12-30 (1)
+U6B2B	anonymous	2008-12-30 (1)
+U6BA9	lsz	2008-12-30 (1)
+U6BAC	lsz	2008-12-30 (1)
+U52E5	anonymous	2008-12-30 (1)
+U8A9F	anonymous	2008-12-30 (1)
+U5D2C	anonymous	2008-12-30 (1)
+U9EEC	anonymous	2008-12-30 (1)
+U8AAE	anonymous	2008-12-30 (1)
+U8570	anonymous	2008-12-30 (1)
+U6EF3	anonymous	2008-12-30 (1)
+U9CBE	anonymous	2008-12-30 (1)
+U90CC	anonymous	2008-12-30 (1)
+U772B	anonymous	2008-12-30 (1)
+U772C	anonymous	2008-12-30 (1)
+U772E	anonymous	2008-12-30 (1)
+U9CBF	anonymous	2008-12-30 (1)
+U7730	anonymous	2008-12-30 (1)
+U773F	anonymous	2008-12-30 (1)
+U773F	anonymous	2008-12-30 (2)
+U6018	anonymous	2008-12-30 (1)
+U921B	anonymous	2008-12-30 (1)
+U9CE0	anonymous	2008-12-30 (1)
+U578D	anonymous	2008-12-30 (1)
+U7906	anonymous	2008-12-30 (1)
+U9369	anonymous	2008-12-30 (1)
+U9368	anonymous	2008-12-30 (1)
+U7DA4	aquarius	2008-12-30 (1)
+U7BBD	anonymous	2008-12-30 (1)
+U8B62	anonymous	2008-12-30 (1)
+U7BB6	anonymous	2008-12-30 (1)
+U679B	anonymous	2008-12-30 (1)
+U93C9	anonymous	2008-12-30 (1)
+U5F94	anonymous	2008-12-30 (1)
+U8C87	anonymous	2008-12-30 (1)
+U93F0	anonymous	2008-12-30 (1)
+U986C	aquarius	2008-12-30 (1)
+U90AD	anonymous	2008-12-30 (1)
+U5ACE	aquarius	2008-12-30 (1)
+U5A61	anonymous	2008-12-30 (1)
+U938B	anonymous	2008-12-30 (1)
+U5ACF	aquarius	2008-12-30 (1)
+U8D03	anonymous	2008-12-30 (1)
+U938B	anonymous	2008-12-30 (2)
+U7D49	anonymous	2008-12-30 (1)
+U595F	anonymous	2008-12-30 (1)
+U72B3	anonymous	2008-12-30 (1)
+U79D4	anonymous	2008-12-30 (1)
+U7D37	anonymous	2008-12-30 (1)
+U9307	anonymous	2008-12-30 (1)
+U745D	anonymous	2008-12-30 (1)
+U7FD6	anonymous	2008-12-30 (1)
+U785B	anonymous	2008-12-30 (1)
+U749D	anonymous	2008-12-30 (1)
+U7134	anonymous	2008-12-30 (1)
+U7BBC	anonymous	2008-12-30 (1)
+U777B	anonymous	2008-12-30 (1)
+U91FE	anonymous	2008-12-30 (1)
+U73EC	aquarius	2008-12-30 (1)
+U7134	anonymous	2008-12-30 (2)
+U778A	anonymous	2008-12-30 (1)
+U5390	wanghong	2008-12-30 (1)
+U52CA	anonymous	2008-12-30 (1)
+U91FE	anonymous	2008-12-30 (2)
+U72BB	anonymous	2008-12-30 (1)
+U8A0B	anonymous	2008-12-30 (1)
+U7478	anonymous	2008-12-30 (1)
+U8A0D	anonymous	2008-12-30 (1)
+U7CC9	anonymous	2008-12-30 (1)
+U8A19	anonymous	2008-12-30 (1)
+U740E	aquarius	2008-12-30 (1)
+U601F	anonymous	2008-12-30 (1)
+U78D8	aquarius	2008-12-30 (1)
+U6F0C	anonymous	2008-12-30 (1)
+U5B35	anonymous	2008-12-30 (1)
+U7CCF	anonymous	2008-12-30 (1)
+U7CE6	anonymous	2008-12-30 (1)
+U5724	aquarius	2008-12-30 (1)
+U8E4F	anonymous	2008-12-30 (1)
+U6407	anonymous	2008-12-30 (1)
+U5856	anonymous	2008-12-30 (1)
+U5724	aquarius	2008-12-30 (2)
+U7C24	anonymous	2008-12-30 (1)
+U902B	anonymous	2008-12-30 (1)
+U8E58	anonymous	2008-12-30 (1)
+U8E75	anonymous	2008-12-30 (1)
+U9275	anonymous	2008-12-30 (1)
+U6C58	anonymous	2008-12-30 (1)
+U6C63	anonymous	2008-12-30 (1)
+U6374	anonymous	2008-12-30 (1)
+U9750	anonymous	2008-12-30 (1)
+U5513	anonymous	2008-12-30 (1)
+U9C03	anonymous	2008-12-30 (1)
+U7439	anonymous	2008-12-30 (1)
+U508F	aquarius	2008-12-30 (1)
+U741F	anonymous	2008-12-30 (1)
+U610C	anonymous	2008-12-30 (1)
+U612A	anonymous	2008-12-30 (1)
+U991C	anonymous	2008-12-30 (1)
+U990E	anonymous	2008-12-30 (1)
+U8F28	anonymous	2008-12-30 (1)
+U9922	anonymous	2008-12-30 (1)
+U902A	anonymous	2008-12-30 (1)
+U9E8F	anonymous	2008-12-30 (1)
+U9B62	anonymous	2008-12-30 (1)
+U98E0	anonymous	2008-12-30 (1)
+U9281	anonymous	2008-12-30 (1)
+U7356	anonymous	2008-12-30 (1)
+U9936	anonymous	2008-12-30 (1)
+U80EE	anonymous	2008-12-30 (1)
+U9989	anonymous	2008-12-30 (1)
+U5675	anonymous	2008-12-30 (1)
+U56FC	anonymous	2008-12-30 (1)
+U7959	anonymous	2008-12-30 (1)
+U757C	anonymous	2008-12-30 (1)
+U7ADB	anonymous	2008-12-30 (1)
+U7AE8	anonymous	2008-12-30 (1)
+U7983	anonymous	2008-12-30 (1)
+U7AE9	anonymous	2008-12-30 (1)
+U55D7	anonymous	2008-12-30 (1)
+U6051	anonymous	2008-12-30 (1)
+U608F	anonymous	2008-12-30 (1)
+U666D	anonymous	2008-12-30 (1)
+U668F	anonymous	2008-12-30 (1)
+U60E5	anonymous	2008-12-30 (1)
+U76FD	anonymous	2008-12-30 (1)
+U78C7	anonymous	2008-12-30 (1)
+U7700	anonymous	2008-12-30 (1)
+U9ECA	anonymous	2008-12-30 (1)
+U6299	anonymous	2008-12-30 (1)
+U7702	anonymous	2008-12-30 (1)
+U58B0	anonymous	2008-12-30 (1)
+U5A96	anonymous	2008-12-30 (1)
+U5090	anonymous	2008-12-30 (1)
+U741E	anonymous	2008-12-30 (1)
+U9BB7	anonymous	2008-12-30 (1)
+U79A5	blueiris	2008-12-30 (1)
+U9548	anonymous	2008-12-30 (1)
+U9560	anonymous	2008-12-30 (1)
+U6650	anonymous	2008-12-30 (1)
+U72BC	anonymous	2008-12-30 (1)
+U88D1	anonymous	2008-12-30 (1)
+U9574	anonymous	2008-12-30 (1)
+U9560	anonymous	2008-12-30 (2)
+U9548	anonymous	2008-12-30 (2)
+U88D1	anonymous	2008-12-30 (2)
+U7CFF	anonymous	2008-12-30 (1)
+U6C77	anonymous	2008-12-30 (1)
+U54CB	anonymous	2008-12-30 (1)
+U7D24	anonymous	2008-12-30 (1)
+U553A	anonymous	2008-12-30 (1)
+U8939	blueiris	2008-12-30 (1)
+U4FB1	anonymous	2008-12-30 (1)
+U9C0F	anonymous	2008-12-30 (1)
+U6186	blueiris	2008-12-30 (1)
+U5CE2	anonymous	2008-12-30 (1)
+U714F	anonymous	2008-12-30 (1)
+U7133	anonymous	2008-12-30 (1)
+U7EF9	anonymous	2008-12-30 (1)
+U88E0	anonymous	2008-12-30 (1)
+U7F10	anonymous	2008-12-30 (1)
+U8CD6	anonymous	2008-12-30 (1)
+U5CF2	anonymous	2008-12-30 (1)
+U8CE9	anonymous	2008-12-30 (1)
+U6393	anonymous	2008-12-30 (1)
+U980B	anonymous	2008-12-30 (1)
+U9823	anonymous	2008-12-30 (1)
+U5CF3	anonymous	2008-12-30 (1)
+U66E1	anonymous	2008-12-30 (1)
+U5CFC	anonymous	2008-12-30 (1)
+U9269	anonymous	2008-12-30 (1)
+U78D6	anonymous	2008-12-30 (1)
+U6D8F	anonymous	2008-12-30 (1)
+U936B	anonymous	2008-12-30 (1)
+U7966	anonymous	2008-12-30 (1)
+U54EC	anonymous	2008-12-30 (1)
+U9C02	anonymous	2008-12-30 (1)
+U797E	anonymous	2008-12-30 (1)
+U939C	anonymous	2008-12-30 (1)
+U54F0	anonymous	2008-12-30 (1)
+U7A65	anonymous	2008-12-30 (1)
+U6D1C	anonymous	2008-12-30 (1)
+U7A5E	anonymous	2008-12-30 (1)
+U6AF4	anonymous	2008-12-30 (1)
+U9819	anonymous	2008-12-30 (1)
+U93F1	anonymous	2008-12-30 (1)
+U7A6A	anonymous	2008-12-30 (1)
+U6815	anonymous	2008-12-30 (1)
+U7A64	anonymous	2008-12-30 (1)
+U61EC	anonymous	2008-12-30 (1)
+U93ED	anonymous	2008-12-30 (1)
+U7A65	anonymous	2008-12-30 (2)
+U71CC	anonymous	2008-12-30 (1)
+U543A	anonymous	2008-12-30 (1)
+U794D	anonymous	2008-12-30 (1)
+U5E09	anonymous	2008-12-30 (1)
+U6806	anonymous	2008-12-30 (1)
+U7D5D	qingshi163	2008-12-30 (1)
+U544C	anonymous	2008-12-30 (1)
+U85BB	anonymous	2008-12-30 (1)
+U5E1E	anonymous	2008-12-30 (1)
+U6B9C	anonymous	2008-12-30 (1)
+U544D	anonymous	2008-12-30 (1)
+U8970	anonymous	2008-12-30 (1)
+U803A	qingshi163	2008-12-30 (1)
+U50DF	anonymous	2008-12-30 (1)
+U9825	anonymous	2008-12-30 (1)
+U9CE3	anonymous	2008-12-30 (1)
+U9831	anonymous	2008-12-30 (1)
+U9822	anonymous	2008-12-30 (1)
+U5400	anonymous	2008-12-30 (1)
+U7875	anonymous	2008-12-30 (1)
+U657D	anonymous	2008-12-30 (1)
+U9E5F	anonymous	2008-12-30 (1)
+U842E	anonymous	2008-12-30 (1)
+U6150	anonymous	2008-12-30 (1)
+U658D	anonymous	2008-12-30 (1)
+U7F8F	anonymous	2008-12-30 (1)
+U6658	anonymous	2008-12-30 (1)
+U967B	anonymous	2008-12-30 (1)
+U9E72	anonymous	2008-12-30 (1)
+U9E5D	anonymous	2008-12-30 (1)
+U6902	anonymous	2008-12-30 (1)
+U9E6F	anonymous	2008-12-30 (1)
+U9E6E	anonymous	2008-12-30 (1)
+U92EB	anonymous	2008-12-30 (1)
+U915B	anonymous	2008-12-30 (1)
+U5822	anonymous	2008-12-30 (1)
+U90EE	anonymous	2008-12-30 (1)
+U5884	anonymous	2008-12-30 (1)
+U4FFB	anonymous	2008-12-30 (1)
+U98D7	anonymous	2008-12-30 (1)
+U81B6	anonymous	2008-12-30 (1)
+U5816	anonymous	2008-12-30 (1)
+U503F	anonymous	2008-12-30 (1)
+U9AC8	anonymous	2008-12-30 (1)
+U583C	anonymous	2008-12-30 (1)
+U5CD1	anonymous	2008-12-30 (1)
+U70E5	anonymous	2008-12-30 (1)
+U583E	anonymous	2008-12-30 (1)
+U9ACE	anonymous	2008-12-30 (1)
+U7310	anonymous	2008-12-30 (1)
+U910A	anonymous	2008-12-30 (1)
+U5258	fcicq	2008-12-30 (1)
+U7986	anonymous	2008-12-30 (1)
+U92BA	anonymous	2008-12-30 (1)
+U5A4B	fcicq	2008-12-30 (1)
+U92DA	anonymous	2008-12-30 (1)
+U6A03	anonymous	2008-12-30 (1)
+U5A6B	fcicq	2008-12-30 (1)
+U8A4B	anonymous	2008-12-30 (1)
+U7999	anonymous	2008-12-30 (1)
+U5F19	fcicq	2008-12-30 (1)
+U7798	anonymous	2008-12-30 (1)
+U708F	anonymous	2008-12-30 (1)
+U603E	anonymous	2008-12-30 (1)
+U87F5	anonymous	2008-12-30 (1)
+U5F1E	fcicq	2008-12-30 (1)
+U4FBD	anonymous	2008-12-30 (1)
+U5A68	anonymous	2008-12-30 (1)
+U6386	anonymous	2008-12-30 (1)
+U8F9D		2008-12-30 (1)
+U6386	anonymous	2008-12-30 (2)
+U5222	anonymous	2008-12-30 (1)
+U7987	anonymous	2008-12-30 (1)
+U7DCD	anonymous	2008-12-30 (1)
+U6131	anonymous	2008-12-30 (1)
+U4FD5	anonymous	2008-12-30 (1)
+U7E9D	anonymous	2008-12-30 (1)
+U8A9D	anonymous	2008-12-30 (1)
+U7F3C	anonymous	2008-12-30 (1)
+U7987	anonymous	2008-12-30 (2)
+U8AE5	anonymous	2008-12-30 (1)
+U6E2A	anonymous	2008-12-30 (1)
+U7BEC	anonymous	2008-12-30 (1)
+U8455	anonymous	2008-12-30 (1)
+U5052	anonymous	2008-12-30 (1)
+U7987		2008-12-30 (3)
+U6D26	anonymous	2008-12-30 (1)
+U6E02	anonymous	2008-12-30 (1)
+U5054	anonymous	2008-12-30 (1)
+U6480	anonymous	2008-12-30 (1)
+U798C		2008-12-30 (1)
+U62C3	anonymous	2008-12-30 (1)
+U91F2	anonymous	2008-12-30 (1)
+U916D	anonymous	2008-12-30 (1)
+U7A7C	anonymous	2008-12-30 (1)
+U7B0D	anonymous	2008-12-30 (1)
+U9213	anonymous	2008-12-30 (1)
+U999F	anonymous	2008-12-30 (1)
+U9E0C	anonymous	2008-12-30 (1)
+U99AA	anonymous	2008-12-30 (1)
+U8355	anonymous	2008-12-30 (1)
+U77C3	anonymous	2008-12-30 (1)
+U5B3B	anonymous	2008-12-30 (1)
+U5F47	anonymous	2008-12-30 (1)
+U99B8	anonymous	2008-12-30 (1)
+U9625	anonymous	2008-12-30 (1)
+U9754	anonymous	2008-12-30 (1)
+U7255	anonymous	2008-12-30 (1)
+U4E79	anonymous	2008-12-30 (1)
+U88D3	anonymous	2008-12-30 (1)
+U7BAE	anonymous	2008-12-30 (1)
+U55E0	anonymous	2008-12-30 (1)
+U9BAC	anonymous	2008-12-30 (1)
+U7BBF	anonymous	2008-12-30 (1)
+U9BAC	anonymous	2008-12-30 (2)
+U7CFC	anonymous	2008-12-30 (1)
+U6160	anonymous	2008-12-30 (1)
+U8AB5	anonymous	2008-12-30 (1)
+U9BFE	anonymous	2008-12-30 (1)
+U8C51	anonymous	2008-12-30 (1)
+U98E6	anonymous	2008-12-30 (1)
+U7140	anonymous	2008-12-30 (1)
+U64CC	anonymous	2008-12-30 (1)
+U7148	anonymous	2008-12-30 (1)
+U8ACA	anonymous	2008-12-30 (1)
+U8135	fcicq	2008-12-30 (1)
+U74AC	anonymous	2008-12-30 (1)
+U5001	anonymous	2008-12-30 (1)
+U71EB	anonymous	2008-12-30 (1)
+U7255	anonymous	2008-12-30 (2)
+U7140	fcicq	2008-12-30 (2)
+U644C	anonymous	2008-12-30 (1)
+U8C44	anonymous	2008-12-30 (1)
+U7716	anonymous	2008-12-30 (1)
+U9341	anonymous	2008-12-30 (1)
+U716B	anonymous	2008-12-30 (1)
+U68ED	anonymous	2008-12-30 (1)
+U71EB	anonymous	2008-12-30 (2)
+U678A	fcicq	2008-12-30 (1)
+U71EB	anonymous	2008-12-30 (3)
+U824D	anonymous	2008-12-30 (1)
+U5597	anonymous	2008-12-30 (1)
+U6719	anonymous	2008-12-30 (1)
+U976F	fcicq	2008-12-30 (1)
+U824A	anonymous	2008-12-30 (1)
+U979B	fcicq	2008-12-30 (1)
+U55C1	anonymous	2008-12-30 (1)
+U7F40	qingshi163	2008-12-30 (1)
+U598C	anonymous	2008-12-30 (1)
+U8849	anonymous	2008-12-30 (1)
+U68FE	anonymous	2008-12-30 (1)
+U7F37	qingshi163	2008-12-30 (1)
+U8B8D	anonymous	2008-12-30 (1)
+U68FF	anonymous	2008-12-30 (1)
+U8847	anonymous	2008-12-30 (1)
+U62A3	anonymous	2008-12-30 (1)
+U93B6	anonymous	2008-12-30 (1)
+U6909	anonymous	2008-12-30 (1)
+U79CC	anonymous	2008-12-30 (1)
+U7BD0	anonymous	2008-12-30 (1)
+U7556	anonymous	2008-12-30 (1)
+U935F	anonymous	2008-12-30 (1)
+U66EA	anonymous	2008-12-30 (1)
+U7264	anonymous	2008-12-30 (1)
+U5C8E	anonymous	2008-12-30 (1)
+U7268	anonymous	2008-12-30 (1)
+U5C8E	anonymous	2008-12-30 (2)
+U69D2	anonymous	2008-12-30 (1)
+U5D70	anonymous	2008-12-30 (1)
+U6547	anonymous	2008-12-30 (1)
+U5A14	mozbug	2008-12-30 (1)
+U915C	anonymous	2008-12-30 (1)
+U6CE6	anonymous	2008-12-30 (1)
+U5A22	anonymous	2008-12-30 (1)
+U6CD8	anonymous	2008-12-30 (1)
+U8057	anonymous	2008-12-30 (1)
+U81AD	anonymous	2008-12-30 (1)
+U9AAC	anonymous	2008-12-30 (1)
+U654B	anonymous	2008-12-30 (1)
+U669A	anonymous	2008-12-30 (1)
+U5AFE	anonymous	2008-12-30 (1)
+U62C0	anonymous	2008-12-30 (1)
+U8421	anonymous	2008-12-30 (1)
+U9C5D	anonymous	2008-12-30 (1)
+U78F1	anonymous	2008-12-30 (1)
+U89EE	anonymous	2008-12-30 (1)
+U6BB8	lsz	2008-12-30 (1)
+U655A	anonymous	2008-12-30 (1)
+U7448	anonymous	2008-12-30 (1)
+U84C8	anonymous	2008-12-30 (1)
+U726D	anonymous	2008-12-30 (1)
+U5A2A	anonymous	2008-12-30 (1)
+U909C	anonymous	2008-12-30 (1)
+U9B34	anonymous	2008-12-30 (1)
+U8A53		2008-12-30 (1)
+U79A9	anonymous	2008-12-30 (1)
+U9B73	anonymous	2008-12-30 (1)
+U79A9	anonymous	2008-12-30 (2)
+U9151	anonymous	2008-12-30 (1)
+U9B78	anonymous	2008-12-30 (1)
+U8DED	anonymous	2008-12-30 (1)
+U6D81	anonymous	2008-12-30 (1)
+U655F	anonymous	2008-12-30 (1)
+U5BAF	anonymous	2008-12-30 (1)
+U9166	anonymous	2008-12-30 (1)
+U6023	anonymous	2008-12-30 (1)
+U6DA2	anonymous	2008-12-30 (1)
+U8E7D	anonymous	2008-12-30 (1)
+U9B7F	anonymous	2008-12-30 (1)
+U8FA1	anonymous	2008-12-30 (1)
+U8AFD	anonymous	2008-12-30 (1)
+U8289	anonymous	2008-12-30 (1)
+U9C16	lsz	2008-12-30 (1)
+U693E	anonymous	2008-12-30 (1)
+U55EE	anonymous	2008-12-30 (1)
+U8EDA	anonymous	2008-12-30 (1)
+U8F0F	anonymous	2008-12-30 (1)
+U5B61	anonymous	2008-12-30 (1)
+U8D5F	anonymous	2008-12-30 (1)
+U9C18	lsz	2008-12-30 (1)
+U8EEA	anonymous	2008-12-30 (1)
+U8F2B	anonymous	2008-12-30 (1)
+U6F04	anonymous	2008-12-30 (1)
+U6598	anonymous	2008-12-30 (1)
+U871F	anonymous	2008-12-30 (1)
+U8EBC	anonymous	2008-12-30 (1)
+U9C11	lsz	2008-12-30 (1)
+U809E	anonymous	2008-12-30 (1)
+U8E79	mozbug	2008-12-30 (1)
+U8F21	anonymous	2008-12-30 (1)
+U6057	anonymous	2008-12-30 (1)
+U8EBF	anonymous	2008-12-30 (1)
+U8EC1	anonymous	2008-12-30 (1)
+U716F	anonymous	2008-12-30 (1)
+U9ADA	anonymous	2008-12-30 (1)
+U9B9C	anonymous	2008-12-30 (1)
+U6C7C	anonymous	2008-12-30 (1)
+U5B46	anonymous	2008-12-30 (1)
+U716F	anonymous	2008-12-30 (2)
+U651E	anonymous	2008-12-30 (1)
+U9E59	anonymous	2008-12-30 (1)
+U6278	anonymous	2008-12-30 (1)
+U5B4A	anonymous	2008-12-30 (1)
+U8E77	mozbug	2008-12-30 (1)
+U51D2	anonymous	2008-12-30 (1)
+U6A74	anonymous	2008-12-30 (1)
+U8E7D	mozbug	2008-12-30 (2)
+U628D	anonymous	2008-12-30 (1)
+U59E2	anonymous	2008-12-30 (1)
+U5AE4	anonymous	2008-12-30 (1)
+U6A75	anonymous	2008-12-30 (1)
+U6290	anonymous	2008-12-30 (1)
+U86E0	anonymous	2008-12-30 (1)
+U9B9D	anonymous	2008-12-30 (1)
+U5A1D	anonymous	2008-12-30 (1)
+U4EFE	mozbug	2008-12-30 (1)
+U535B	anonymous	2008-12-30 (1)
+U981F	anonymous	2008-12-30 (1)
+U9C19	anonymous	2008-12-30 (1)
+U6DFE	anonymous	2008-12-30 (1)
+U5AF0	anonymous	2008-12-30 (1)
+U8EB6	anonymous	2008-12-30 (1)
+U5A26	anonymous	2008-12-30 (1)
+U5E9D	anonymous	2008-12-30 (1)
+U624F	anonymous	2008-12-30 (1)
+U78EE	anonymous	2008-12-30 (1)
+U78EE	anonymous	2008-12-30 (2)
+U8EC3	anonymous	2008-12-30 (1)
+U7196	anonymous	2008-12-30 (1)
+U5AEF	anonymous	2008-12-30 (1)
+U52B0	anonymous	2008-12-30 (1)
+U743B	anonymous	2008-12-30 (1)
+U78EE	anonymous	2008-12-30 (3)
+U9629	sqybi	2008-12-30 (1)
+U8678	anonymous	2008-12-30 (1)
+U7794	anonymous	2008-12-30 (1)
+U9C43	anonymous	2008-12-30 (1)
+U967F	anonymous	2008-12-30 (1)
+U744C	lsz	2008-12-30 (1)
+U6C7F	anonymous	2008-12-30 (1)
+U5A26	anonymous	2008-12-30 (2)
+U9833	anonymous	2008-12-30 (1)
+U6C9E	anonymous	2008-12-30 (1)
+U8C96	anonymous	2008-12-30 (1)
+U7466	lsz	2008-12-30 (1)
+U78F6	anonymous	2008-12-30 (1)
+U8C9F	anonymous	2008-12-30 (1)
+U873D	anonymous	2008-12-30 (1)
+U71A3	sqybi	2008-12-30 (1)
+U98F1	anonymous	2008-12-30 (1)
+U9D21	anonymous	2008-12-30 (1)
+U7466	anonymous	2008-12-30 (2)
+U746B	anonymous	2008-12-30 (1)
+U5895	anonymous	2008-12-30 (1)
+U743E	anonymous	2008-12-30 (1)
+U59E7	lsz	2008-12-30 (1)
+U7449	anonymous	2008-12-30 (1)
+U9B6D	anonymous	2008-12-30 (1)
+U5D05	anonymous	2008-12-30 (1)
+U9C64	anonymous	2008-12-30 (1)
+U9B6D	anonymous	2008-12-30 (2)
+U9D32	anonymous	2008-12-30 (1)
+U9B6D	anonymous	2008-12-30 (3)
+U8CB1	anonymous	2008-12-30 (1)
+U9B81	anonymous	2008-12-30 (1)
+U6F8A	anonymous	2008-12-30 (1)
+U746B	anonymous	2008-12-30 (2)
+U8B03	anonymous	2008-12-30 (1)
+U9861	anonymous	2008-12-30 (1)
+U759E	anonymous	2008-12-30 (1)
+U5A24	anonymous	2008-12-30 (1)
+U7908	anonymous	2008-12-30 (1)
+U51E5	anonymous	2008-12-30 (1)
+U5A27	anonymous	2008-12-30 (1)
+U7BA5	anonymous	2008-12-30 (1)
+U7B41	anonymous	2008-12-30 (1)
+U77E4	anonymous	2008-12-30 (1)
+U5A27	lsz	2008-12-30 (2)
+U5A87	anonymous	2008-12-30 (1)
+U5A2B	anonymous	2008-12-30 (1)
+U5AF2	anonymous	2008-12-30 (1)
+U7D60	anonymous	2008-12-30 (1)
+U941D	anonymous	2008-12-30 (1)
+U5B04	anonymous	2008-12-30 (1)
+U658F	anonymous	2008-12-30 (1)
+U8E7E	anonymous	2008-12-30 (1)
+U5A30	lsz	2008-12-30 (1)
+U551D	anonymous	2008-12-30 (1)
+U933F	anonymous	2008-12-30 (1)
+U5A2B	anonymous	2008-12-30 (2)
+U551D	anonymous	2008-12-30 (2)
+U5E5A	anonymous	2008-12-30 (1)
+U8CC9	anonymous	2008-12-30 (1)
+U5A2B	lsz	2008-12-30 (3)
+U7900	anonymous	2008-12-30 (1)
+U96AB	anonymous	2008-12-30 (1)
+U6730	anonymous	2008-12-30 (1)
+U933F	anonymous	2008-12-30 (2)
+U6122	anonymous	2008-12-30 (1)
+U971B	anonymous	2008-12-30 (1)
+U6758	anonymous	2008-12-30 (1)
+U7F49	anonymous	2008-12-30 (1)
+U5A24	lsz	2008-12-30 (2)
+U855C	anonymous	2008-12-30 (1)
+U9417	anonymous	2008-12-30 (1)
+U968C	anonymous	2008-12-30 (1)
+U968C	anonymous	2008-12-30 (2)
+U735C	anonymous	2008-12-30 (1)
+U5736	anonymous	2008-12-30 (1)
+U69F0	anonymous	2008-12-30 (1)
+U5736	anonymous	2008-12-30 (2)
+U6B1C	anonymous	2008-12-30 (1)
+U6A0E	anonymous	2008-12-30 (1)
+U5B1F	anonymous	2008-12-30 (1)
+U5EBF	anonymous	2008-12-30 (1)
+U7D34	anonymous	2008-12-30 (1)
+U6B07	anonymous	2008-12-30 (1)
+U6964	anonymous	2008-12-30 (1)
+U6B4F	anonymous	2008-12-30 (1)
+U9F81	anonymous	2008-12-30 (1)
+U8091	anonymous	2008-12-30 (1)
+U7D2D	anonymous	2008-12-30 (1)
+U6B52	anonymous	2008-12-30 (1)
+U955A	fcicq	2008-12-30 (1)
+U6B44	anonymous	2008-12-30 (1)
+U8992	anonymous	2008-12-30 (1)
+U568B	anonymous	2008-12-30 (1)
+U6BBE	anonymous	2008-12-30 (1)
+U97D2	anonymous	2008-12-30 (1)
+U638B	anonymous	2008-12-30 (1)
+U6A88	fcicq	2008-12-30 (1)
+U6133	anonymous	2008-12-30 (1)
+U74A4	anonymous	2008-12-30 (1)
+U9B84	anonymous	2008-12-30 (1)
+U7D64	anonymous	2008-12-30 (2)
+U76AC	fcicq	2008-12-30 (1)
+U7F1E	anonymous	2008-12-30 (1)
+U9940	anonymous	2008-12-30 (1)
+U56E8	anonymous	2008-12-30 (1)
+U89A8	anonymous	2008-12-30 (1)
+U6DE7	anonymous	2008-12-30 (1)
+U974E	anonymous	2008-12-30 (1)
+U52B8	anonymous	2008-12-30 (1)
+U90BC	anonymous	2008-12-30 (1)
+U58A4	anonymous	2008-12-30 (1)
+U74F3	fcicq	2008-12-30 (1)
+U6ACE	anonymous	2008-12-30 (1)
+U90C0	anonymous	2008-12-30 (1)
+U9939	anonymous	2008-12-30 (1)
+U7CE5	anonymous	2008-12-30 (1)
+U58B6	anonymous	2008-12-30 (1)
+U4EB1	anonymous	2008-12-30 (1)
+U94FB	anonymous	2008-12-30 (1)
+U66DF	anonymous	2008-12-30 (1)
+U4FF2	anonymous	2008-12-30 (1)
+U7918	anonymous	2008-12-30 (1)
+U4FFC	anonymous	2008-12-30 (1)
+U8FA2	anonymous	2008-12-30 (1)
+U807A	anonymous	2008-12-30 (1)
+U7918	anonymous	2008-12-30 (2)
+U75A6	anonymous	2008-12-30 (1)
+U6411	anonymous	2008-12-30 (1)
+U7AEC	anonymous	2008-12-30 (1)
+U975D	anonymous	2008-12-30 (1)
+U75A8	anonymous	2008-12-30 (1)
+U7E5B	anonymous	2008-12-30 (1)
+U57FE	anonymous	2008-12-30 (1)
+U6419	anonymous	2008-12-30 (1)
+U641D	anonymous	2008-12-30 (1)
+U7585	anonymous	2008-12-30 (1)
+U8EB4	anonymous	2008-12-30 (1)
+U791A	anonymous	2008-12-30 (1)
+U93EB	lsz	2008-12-30 (1)
+U7920	anonymous	2008-12-30 (1)
+U8A05	anonymous	2008-12-30 (1)
+U5A3F	anonymous	2008-12-30 (1)
+U7EBB	anonymous	2008-12-30 (1)
+U82FF	anonymous	2008-12-30 (1)
+U93EF	lsz	2008-12-30 (1)
+U612D	anonymous	2008-12-30 (1)
+U730D	anonymous	2008-12-30 (1)
+U93F4	lsz	2008-12-30 (1)
+U7F46	anonymous	2008-12-30 (1)
+U7CE9	anonymous	2008-12-30 (1)
+U93F3	lsz	2008-12-30 (1)
+U7EBB	anonymous	2008-12-30 (2)
+U92D4	anonymous	2008-12-30 (1)
+U975F	anonymous	2008-12-30 (1)
+U7087	anonymous	2008-12-30 (1)
+U5D4D	lsz	2008-12-30 (1)
+U8C52	anonymous	2008-12-30 (1)
+U7090	anonymous	2008-12-30 (1)
+U7151	anonymous	2008-12-30 (1)
+U8D88	anonymous	2008-12-30 (1)
+U5D54	lsz	2008-12-30 (1)
+U7171	anonymous	2008-12-30 (1)
+U9757	anonymous	2008-12-30 (1)
+U61F3	anonymous	2008-12-30 (1)
+U5D5A	lsz	2008-12-30 (1)
+U94C7	anonymous	2008-12-30 (1)
+U9CEE	anonymous	2008-12-30 (1)
+U8D9D	anonymous	2008-12-30 (1)
+U94E6	anonymous	2008-12-30 (1)
+U8C58	anonymous	2008-12-30 (1)
+U70D0	lsz	2008-12-30 (1)
+U5781	anonymous	2008-12-30 (1)
+U6A7A	anonymous	2008-12-30 (1)
+U5DA5	anonymous	2008-12-30 (1)
+U8DF6	anonymous	2008-12-30 (1)
+U5843	anonymous	2008-12-30 (1)
+U6A7A	anonymous	2008-12-30 (2)
+U6A1A	anonymous	2008-12-30 (1)
+U96FC	anonymous	2008-12-30 (1)
+U868F	anonymous	2008-12-30 (1)
+U9A63	anonymous	2008-12-30 (1)
+U9B8A	pem	2008-12-30 (1)
+U7090	FangQ	2008-12-30 (2)
+U8E0B	anonymous	2008-12-30 (1)
+U7DFD	anonymous	2008-12-30 (1)
+U9696	anonymous	2008-12-30 (1)
+U7176	anonymous	2008-12-30 (1)
+U5FC2	anonymous	2008-12-30 (1)
+U9B8B	pem	2008-12-30 (1)
+U7FD9	lsz	2008-12-30 (1)
+U9B98	pem	2008-12-30 (1)
+U90A4	anonymous	2008-12-30 (1)
+U6B14	anonymous	2008-12-30 (1)
+U7DFE	anonymous	2008-12-30 (1)
+U9F69	anonymous	2008-12-30 (1)
+U9B89	anonymous	2008-12-30 (1)
+U90A9	anonymous	2008-12-30 (1)
+U9926	anonymous	2008-12-30 (1)
+U71D1	anonymous	2008-12-30 (1)
+U8C7E	anonymous	2008-12-30 (1)
+U92DB	anonymous	2008-12-30 (1)
+U9B8B	anonymous	2008-12-30 (2)
+U8991	anonymous	2008-12-30 (1)
+U5B0D	anonymous	2008-12-30 (1)
+U552B	anonymous	2008-12-30 (1)
+U89D8	anonymous	2008-12-30 (1)
+U6F71	anonymous	2008-12-30 (1)
+U8ED5	FangQ	2008-12-30 (1)
+U7174	anonymous	2008-12-30 (1)
+U92F4	anonymous	2008-12-30 (1)
+U9836	anonymous	2008-12-30 (1)
+U6F75	anonymous	2008-12-30 (1)
+U8ED5	FangQ	2008-12-30 (2)
+U6685	anonymous	2008-12-30 (1)
+U90C9	pem	2008-12-30 (1)
+U8192	anonymous	2008-12-30 (1)
+U969A	anonymous	2008-12-30 (1)
+U8940	anonymous	2008-12-30 (1)
+U8E80	anonymous	2008-12-30 (1)
+U6E50	anonymous	2008-12-30 (1)
+U7B43	anonymous	2008-12-30 (1)
+U76A1	anonymous	2008-12-30 (1)
+U7B93	anonymous	2008-12-30 (1)
+U790B	anonymous	2008-12-30 (1)
+U8D65	anonymous	2008-12-30 (1)
+U8013	anonymous	2008-12-30 (1)
+U4FA2	lsz	2008-12-30 (1)
+U8C88	anonymous	2008-12-30 (1)
+U7F99	pem	2008-12-30 (1)
+U7A82	anonymous	2008-12-30 (1)
+U8947	anonymous	2008-12-30 (1)
+U65CA	anonymous	2008-12-30 (1)
+U8948	anonymous	2008-12-30 (1)
+U7A53	anonymous	2008-12-30 (1)
+U5A7E	FangQ	2008-12-30 (1)
+U7FDD	pem	2008-12-30 (1)
+U8945	anonymous	2008-12-30 (1)
+U65D4	anonymous	2008-12-30 (1)
+U4F71	lsz	2008-12-30 (1)
+U9E61	anonymous	2008-12-30 (1)
+U5F1C	anonymous	2008-12-30 (1)
+U5ECD	anonymous	2008-12-30 (1)
+U8032	anonymous	2008-12-30 (1)
+U6780	anonymous	2008-12-30 (1)
+U9342	anonymous	2008-12-30 (1)
+U7B1C	anonymous	2008-12-30 (1)
+U9343	anonymous	2008-12-30 (1)
+U63B6	anonymous	2008-12-30 (1)
+U935D	anonymous	2008-12-30 (1)
+U878C	lsz	2008-12-30 (2)
+U8120	anonymous	2008-12-30 (1)
+U9C97	lsz	2008-12-30 (2)
+U9E7B	anonymous	2008-12-30 (1)
+U556F	anonymous	2008-12-30 (1)
+U9E77	anonymous	2008-12-30 (1)
+U99B6	anonymous	2008-12-30 (1)
+U8045	anonymous	2008-12-30 (1)
+U5732	anonymous	2008-12-30 (1)
+U5B94	anonymous	2008-12-30 (1)
+U6C97	anonymous	2008-12-30 (1)
+U6CA0	anonymous	2008-12-30 (1)
+U615C	anonymous	2008-12-30 (1)
+U53AB	anonymous	2008-12-30 (1)
+U69D5	anonymous	2008-12-30 (1)
+U6CAF	anonymous	2008-12-30 (1)
+U9ADB	anonymous	2008-12-30 (1)
+U807C	anonymous	2008-12-30 (1)
+U722E	anonymous	2008-12-30 (1)
+U93BB	anonymous	2008-12-30 (1)
+U74EA	anonymous	2008-12-30 (1)
+U93BA	anonymous	2008-12-30 (1)
+U63D4	anonymous	2008-12-30 (1)
+U7CDA	anonymous	2008-12-30 (1)
+U9E34	anonymous	2008-12-30 (1)
+U63EC	anonymous	2008-12-30 (1)
+U58E1	anonymous	2008-12-30 (1)
+U5691	anonymous	2008-12-30 (1)
+U55BC	anonymous	2008-12-30 (1)
+U5F6E	anonymous	2008-12-30 (1)
+U5F6E	anonymous	2008-12-30 (2)
+U6B1B	anonymous	2008-12-30 (1)
+U6E01	anonymous	2008-12-30 (1)
+U58EA	anonymous	2008-12-30 (1)
+U5D46	anonymous	2008-12-30 (1)
+U671A	anonymous	2008-12-30 (1)
+U685B	anonymous	2008-12-30 (1)
+U55BC	anonymous	2008-12-30 (2)
+U9793	anonymous	2008-12-30 (1)
+U6B2E	anonymous	2008-12-30 (1)
+U5590	anonymous	2008-12-30 (1)
+U5C2E	anonymous	2008-12-30 (1)
+U9BB3	anonymous	2008-12-30 (1)
+U8A1A	anonymous	2008-12-30 (1)
+U76D9	anonymous	2008-12-30 (1)
+U7175	anonymous	2008-12-30 (1)
+U7175	tchaikov	2008-12-30 (2)
+U6A7B	anonymous	2008-12-30 (1)
+U78F8	anonymous	2008-12-30 (1)
+U9796	tchaikov	2008-12-30 (1)
+U8786	anonymous	2008-12-30 (1)
+U7AD4	anonymous	2008-12-30 (1)
+U9B40	anonymous	2008-12-30 (1)
+U7FE4	tchaikov	2008-12-30 (1)
+U6D56	anonymous	2008-12-30 (1)
+U7AFE	anonymous	2008-12-30 (1)
+U6D57	anonymous	2008-12-30 (1)
+U95CE	anonymous	2008-12-30 (1)
+U81F6	anonymous	2008-12-30 (1)
+U8D7F	anonymous	2008-12-30 (1)
+U8A3D	anonymous	2008-12-30 (1)
+U87F8	anonymous	2008-12-30 (1)
+U6E6C	anonymous	2008-12-30 (1)
+U95CF	anonymous	2008-12-30 (1)
+U9366	anonymous	2008-12-30 (1)
+U5B11	anonymous	2008-12-30 (1)
+U92F6	anonymous	2008-12-30 (1)
+U5B06	anonymous	2008-12-30 (1)
+U9D63	anonymous	2008-12-30 (1)
+U8A49	anonymous	2008-12-30 (1)
+U7DA8	anonymous	2008-12-30 (1)
+U85E0	anonymous	2008-12-30 (1)
+U671C	anonymous	2008-12-30 (1)
+U9D62	anonymous	2008-12-30 (1)
+U8D6A	anonymous	2008-12-30 (1)
+U8DB0	anonymous	2008-12-30 (1)
+U717C	anonymous	2008-12-30 (1)
+U7637	anonymous	2008-12-30 (1)
+U8676	anonymous	2008-12-30 (1)
+U7641	anonymous	2008-12-30 (1)
+U5266	anonymous	2008-12-30 (1)
+U675B	anonymous	2008-12-30 (1)
+U7D59	anonymous	2008-12-30 (1)
+U893A	anonymous	2008-12-30 (1)
+U55F0	anonymous	2008-12-30 (1)
+U76CC	anonymous	2008-12-30 (1)
+U6724	anonymous	2008-12-30 (1)
+U7D8A	anonymous	2008-12-30 (1)
+U4EDB	anonymous	2008-12-30 (1)
+U6BA8	anonymous	2008-12-30 (1)
+U6BA8	anonymous	2008-12-30 (2)
+U7E65	anonymous	2008-12-30 (1)
+U6AF5	anonymous	2008-12-30 (1)
+U5058	anonymous	2008-12-30 (1)
+U5044	anonymous	2008-12-30 (1)
+U560A	anonymous	2008-12-30 (1)
+U9944	anonymous	2008-12-30 (1)
+U5079	anonymous	2008-12-30 (1)
+U9946	anonymous	2008-12-30 (1)
+U5079	anonymous	2008-12-30 (2)
+U89CD	anonymous	2008-12-30 (1)
+U8B76	anonymous	2008-12-30 (1)
+U5692	anonymous	2008-12-30 (1)
+U9CE8	anonymous	2008-12-30 (1)
+U8E01	anonymous	2008-12-30 (1)
+U5FC8	anonymous	2008-12-30 (1)
+U6C51	anonymous	2008-12-30 (1)
+U5689	anonymous	2008-12-30 (1)
+U5692	anonymous	2008-12-30 (2)
+U7DD0	anonymous	2008-12-30 (1)
+U8E28	anonymous	2008-12-30 (1)
+U6916	anonymous	2008-12-30 (1)
+U5AAD	anonymous	2008-12-30 (1)
+U9D6E	anonymous	2008-12-30 (1)
+U5DF6	anonymous	2008-12-30 (1)
+U7D97	anonymous	2008-12-30 (1)
+U7D95	anonymous	2008-12-30 (1)
+U8FC0	anonymous	2008-12-30 (1)
+U7DA5	anonymous	2008-12-30 (1)
+U8FB8	anonymous	2008-12-30 (1)
+U5DF8	anonymous	2008-12-30 (1)
+U6486	anonymous	2008-12-30 (1)
+U7BD6	anonymous	2008-12-30 (1)
+U5CFE	anonymous	2008-12-30 (1)
+U6858	anonymous	2008-12-30 (1)
+U9E98	anonymous	2008-12-30 (1)
+U791F	anonymous	2008-12-30 (1)
+U8D82	anonymous	2008-12-30 (1)
+U7D90	anonymous	2008-12-30 (1)
+U7D82	anonymous	2008-12-30 (1)
+U6B57	anonymous	2008-12-30 (1)
+U6B5A	anonymous	2008-12-30 (1)
+U6B57	anonymous	2008-12-30 (2)
+U7DF8	anonymous	2008-12-30 (1)
+U5696	anonymous	2008-12-30 (1)
+U7AA4	anonymous	2008-12-30 (1)
+U82D0	anonymous	2008-12-30 (1)
+U6BDD	anonymous	2008-12-30 (1)
+U5D6E	anonymous	2008-12-30 (1)
+U6BDC	anonymous	2008-12-30 (1)
+U6E59	anonymous	2008-12-30 (1)
+U56B0	anonymous	2008-12-30 (1)
+U5B0A	anonymous	2008-12-30 (1)
+U7568	anonymous	2008-12-30 (1)
+U7958	anonymous	2008-12-30 (1)
+U71EA	anonymous	2008-12-30 (1)
+U5B0A	anonymous	2008-12-30 (2)
+U8357	anonymous	2008-12-30 (1)
+U58B7	anonymous	2008-12-30 (1)
+U521F	anonymous	2008-12-30 (1)
+U58ED		2008-12-30 (1)
+U5813		2008-12-30 (1)
+U6A82	anonymous	2008-12-30 (1)
+U9AB2	anonymous	2008-12-30 (1)
+U685A	anonymous	2008-12-30 (1)
+U9AB5	anonymous	2008-12-30 (1)
+U5B18	anonymous	2008-12-30 (1)
+U7C2F	anonymous	2008-12-30 (1)
+U93BD	anonymous	2008-12-30 (1)
+U7A73		2008-12-30 (1)
+U5CD5	anonymous	2008-12-30 (1)
+U720B	anonymous	2008-12-30 (1)
+U720E	anonymous	2008-12-30 (1)
+U720F	anonymous	2008-12-30 (1)
+U5E8E	anonymous	2008-12-30 (1)
+U5E8E	anonymous	2008-12-30 (2)
+U8D1A		2008-12-30 (1)
+U7A25	anonymous	2008-12-30 (1)
+U790A	anonymous	2008-12-30 (1)
+U5EAF	anonymous	2008-12-30 (1)
+U7427		2008-12-30 (1)
+U5EAF	anonymous	2008-12-30 (2)
+U7193	anonymous	2008-12-30 (1)
+U80B9	anonymous	2008-12-30 (1)
+U7A73	anonymous	2008-12-30 (2)
+U957E	anonymous	2008-12-30 (1)
+U9D13	anonymous	2008-12-30 (1)
+U9125	anonymous	2008-12-30 (1)
+U6245		2008-12-30 (1)
+U8A01	anonymous	2008-12-30 (1)
+U9D16	anonymous	2008-12-30 (1)
+U5276	anonymous	2008-12-30 (1)
+U9F3A	anonymous	2008-12-30 (1)
+U76A7	anonymous	2008-12-30 (1)
+U7C15	anonymous	2008-12-30 (1)
+U76A9	anonymous	2008-12-30 (1)
+U71B6	anonymous	2008-12-30 (1)
+U5D6A	anonymous	2008-12-30 (1)
+U57FF	anonymous	2008-12-30 (1)
+U5D7B	anonymous	2008-12-30 (1)
+U85F3	anonymous	2008-12-30 (1)
+U79C2	anonymous	2008-12-30 (1)
+U6F59	anonymous	2008-12-30 (1)
+U619C	anonymous	2008-12-30 (1)
+U5E12	anonymous	2008-12-30 (1)
+U5E13	anonymous	2008-12-30 (1)
+U5E2A	anonymous	2008-12-30 (1)
+U9E96	anonymous	2008-12-30 (1)
+U8B32	anonymous	2008-12-30 (1)
+U9E84	anonymous	2008-12-30 (1)
+U8126	anonymous	2008-12-30 (1)
+U7B6F	anonymous	2008-12-30 (1)
+U9BA3	anonymous	2008-12-30 (1)
+U9C61	anonymous	2008-12-30 (1)
+U8B75	anonymous	2008-12-30 (1)
+U99DA	anonymous	2008-12-30 (1)
+U98CA	anonymous	2008-12-30 (1)
+U9E9E	anonymous	2008-12-30 (1)
+U681B	anonymous	2008-12-30 (1)
+U9C65	anonymous	2008-12-30 (1)
+U681B	anonymous	2008-12-30 (2)
+U9C6F	anonymous	2008-12-30 (1)
+U98C8	anonymous	2008-12-30 (1)
+U9EA3	anonymous	2008-12-30 (1)
+U98C5	anonymous	2008-12-30 (1)
+U9EAC	anonymous	2008-12-30 (1)
+U99E6	anonymous	2008-12-30 (1)
+U5607	anonymous	2008-12-30 (1)
+U560B	anonymous	2008-12-30 (1)
+U894A	anonymous	2008-12-30 (1)
+U8954	anonymous	2008-12-30 (1)
+U894E	anonymous	2008-12-30 (1)
+U5B15	anonymous	2008-12-30 (1)
+U511B	anonymous	2008-12-30 (1)
+U50F7	anonymous	2008-12-30 (1)
+U66CE	anonymous	2008-12-30 (1)
+U76B6		2008-12-30 (1)
+U5342		2008-12-30 (1)
+U685E		2008-12-30 (1)
+U7F59		2008-12-30 (1)
+U5259	anonymous	2008-12-30 (1)
+U6540	anonymous	2008-12-30 (1)
+U6544	anonymous	2008-12-30 (1)
+U8CD8	anonymous	2008-12-30 (1)
+U99EB	anonymous	2008-12-30 (1)
+U99EF	anonymous	2008-12-30 (1)
+U99F3	anonymous	2008-12-30 (1)
+U7294	anonymous	2008-12-30 (1)
+U8D7A		2008-12-30 (1)
+U7299	anonymous	2008-12-30 (1)
+U8D86		2008-12-30 (1)
+U729C	anonymous	2008-12-30 (1)
+U7DD3	anonymous	2008-12-30 (1)
+U8D87		2008-12-30 (1)
+U9CF8	anonymous	2008-12-30 (1)
+U9CEF	anonymous	2008-12-30 (1)
+U9D0B	anonymous	2008-12-30 (1)
+U944D	anonymous	2008-12-30 (1)
+U5BA9	anonymous	2008-12-30 (1)
+U9895	anonymous	2008-12-30 (1)
+U9899	anonymous	2008-12-30 (1)
+U649B	anonymous	2008-12-30 (1)
+U5D8E	anonymous	2008-12-30 (1)
+U76BC	anonymous	2008-12-30 (1)
+U96ED	anonymous	2008-12-30 (1)
+U8141	anonymous	2008-12-30 (1)
+U6918	anonymous	2008-12-30 (1)
+U9D0F	anonymous	2008-12-30 (1)
+U9D3C	anonymous	2008-12-30 (1)
+U75D3	anonymous	2008-12-30 (1)
+U8532	anonymous	2008-12-30 (1)
+U76C0	anonymous	2008-12-30 (1)
+U593F	anonymous	2008-12-30 (1)
+U65E4	anonymous	2008-12-30 (1)
+U7509	anonymous	2008-12-30 (1)
+U8A14	anonymous	2008-12-30 (1)
+U792E	anonymous	2008-12-30 (1)
+U528E	anonymous	2008-12-30 (1)
+U613A	anonymous	2008-12-30 (1)
+U5295	anonymous	2008-12-30 (1)
+U75EC	anonymous	2008-12-30 (1)
+U810C	anonymous	2008-12-30 (1)
+U66E7	anonymous	2008-12-30 (1)
+U6038	anonymous	2008-12-30 (1)
+U9D66	anonymous	2008-12-30 (1)
+U7371	anonymous	2008-12-30 (1)
+U6B29	anonymous	2008-12-30 (1)
+U6B29	anonymous	2008-12-30 (2)
+U7793	anonymous	2008-12-30 (1)
+U6675		2008-12-30 (1)
+U7A9A	anonymous	2008-12-30 (1)
+U6D6B		2008-12-30 (1)
+U6560	anonymous	2008-12-30 (1)
+U5285	anonymous	2008-12-30 (1)
+U961B	anonymous	2008-12-30 (1)
+U50D9	FangQ	2008-12-30 (1)
+U9043	FangQ	2008-12-30 (1)
+U9043	FangQ	2008-12-30 (2)
+U9048	FangQ	2008-12-30 (1)
+U6D06	anonymous	2008-12-30 (1)
+U518B	anonymous	2008-12-30 (1)
+U9F82	anonymous	2008-12-30 (1)
+U6C44	anonymous	2008-12-30 (1)
+U8C5B	anonymous	2008-12-30 (1)
+U6950	anonymous	2008-12-30 (1)
+U8C59	anonymous	2008-12-30 (1)
+U7C4E	anonymous	2008-12-30 (1)
+U8391	anonymous	2008-12-30 (1)
+U70A2	anonymous	2008-12-30 (1)
+U5C87	anonymous	2008-12-30 (1)
+U5D85	anonymous	2008-12-30 (1)
+U6B2A	anonymous	2008-12-30 (1)
+U97CA	anonymous	2008-12-30 (1)
+U9A0C	anonymous	2008-12-30 (1)
+U65F9	anonymous	2008-12-30 (1)
+U8965	anonymous	2008-12-30 (1)
+U8965	anonymous	2008-12-30 (2)
+U507C	anonymous	2008-12-30 (1)
+U51A7	anonymous	2008-12-30 (1)
+U8965	anonymous	2008-12-30 (3)
+U97DA	anonymous	2008-12-30 (1)
+U999B	anonymous	2008-12-30 (1)
+U7257	anonymous	2008-12-30 (1)
+U63FB	anonymous	2008-12-30 (1)
+U860E	anonymous	2008-12-30 (1)
+U7A8E	anonymous	2008-12-30 (1)
+U7079	anonymous	2008-12-30 (1)
+U8128	anonymous	2008-12-30 (1)
+U8799	anonymous	2008-12-30 (1)
+U5756	anonymous	2008-12-30 (1)
+U9AF0	anonymous	2008-12-30 (1)
+U5FCE	mosoplyr	2008-12-30 (1)
+U941B	anonymous	2008-12-30 (1)
+U66D0	mosoplyr	2008-12-30 (1)
+U9443	anonymous	2008-12-30 (1)
+U5529	mosoplyr	2008-12-30 (1)
+U98CF	mosoplyr	2008-12-30 (1)
+U9D3A	anonymous	2008-12-30 (1)
+U87A7	anonymous	2008-12-30 (1)
+U750A	anonymous	2008-12-30 (1)
+U5C17	anonymous	2008-12-30 (1)
+U8B81	anonymous	2008-12-30 (1)
+U8DE5	anonymous	2008-12-30 (1)
+U9273	anonymous	2008-12-30 (1)
+U7B17	anonymous	2008-12-30 (1)
+U7B1F	anonymous	2008-12-30 (1)
+U52D4	anonymous	2008-12-30 (1)
+U5817	anonymous	2008-12-30 (1)
+U6F17	anonymous	2008-12-30 (1)
+U73E1	anonymous	2008-12-30 (1)
+U543F	anonymous	2008-12-30 (1)
+U8F31	anonymous	2008-12-30 (1)
+U994F	anonymous	2008-12-30 (1)
+U79B5	anonymous	2008-12-30 (1)
+U7D2A	anonymous	2008-12-30 (1)
+U8295	anonymous	2008-12-30 (1)
+U815D	anonymous	2008-12-30 (1)
+U5571	anonymous	2008-12-30 (1)
+U9496	anonymous	2008-12-30 (1)
+U9E40	anonymous	2008-12-30 (1)
+U9491	anonymous	2008-12-30 (1)
+U9919	anonymous	2008-12-30 (1)
+U98F7	anonymous	2008-12-30 (1)
+U6403	anonymous	2008-12-30 (1)
+U96EC	anonymous	2008-12-30 (1)
+U699D	anonymous	2008-12-30 (1)
+U8F2D	anonymous	2008-12-30 (1)
+U8967	anonymous	2008-12-30 (1)
+U945F	anonymous	2008-12-30 (1)
+U6629	anonymous	2008-12-30 (1)
+U522C	anonymous	2008-12-30 (1)
+U96EC	anonymous	2008-12-30 (2)
+U6617	anonymous	2008-12-30 (1)
+U8968	anonymous	2008-12-30 (1)
+U802E	anonymous	2008-12-30 (1)
+U8975	anonymous	2008-12-30 (1)
+U8975	anonymous	2008-12-30 (2)
+U9498	anonymous	2008-12-30 (1)
+U661B	anonymous	2008-12-30 (1)
+U83CD	anonymous	2008-12-30 (1)
+U90B7	anonymous	2008-12-30 (1)
+U9A99	anonymous	2008-12-30 (1)
+U7BCD	anonymous	2008-12-30 (1)
+U662C	anonymous	2008-12-30 (1)
+U97E2	anonymous	2008-12-30 (1)
+U775D	anonymous	2008-12-30 (1)
+U77CB	anonymous	2008-12-30 (1)
+U7047	anonymous	2008-12-30 (1)
+U9303	anonymous	2008-12-30 (1)
+U5097	anonymous	2008-12-30 (1)
+U77E1	anonymous	2008-12-30 (1)
+U65A6	anonymous	2008-12-30 (1)
+U9405	anonymous	2008-12-30 (1)
+U5A71	anonymous	2008-12-30 (1)
+U8ED9	anonymous	2008-12-30 (1)
+U7B81	anonymous	2008-12-30 (1)
+U8EC7	anonymous	2008-12-30 (1)
+U9142	anonymous	2008-12-30 (1)
+U7B7F	something	2008-12-30 (1)
+U944E	anonymous	2008-12-30 (1)
+U580F	something	2008-12-30 (1)
+U53DA	anonymous	2008-12-30 (1)
+U511E	anonymous	2008-12-30 (1)
+U9426	anonymous	2008-12-30 (1)
+U75E5	anonymous	2008-12-30 (1)
+U6169	anonymous	2008-12-30 (1)
+U8372	something	2008-12-30 (1)
+U8380	something	2008-12-30 (1)
+U5818	anonymous	2008-12-30 (1)
+U6E37	anonymous	2008-12-30 (1)
+U8978	anonymous	2008-12-30 (1)
+U5926	anonymous	2008-12-30 (1)
+U98F8	anonymous	2008-12-30 (1)
+U9401	anonymous	2008-12-30 (1)
+U7183	anonymous	2008-12-30 (1)
+U6A8A	anonymous	2008-12-30 (1)
+U6C31	anonymous	2008-12-30 (1)
+U7379	anonymous	2008-12-30 (1)
+U89B4	anonymous	2008-12-30 (1)
+U6F99	anonymous	2008-12-30 (1)
+U7379	anonymous	2008-12-30 (2)
+U61B9	anonymous	2008-12-30 (1)
+U89AB	anonymous	2008-12-30 (1)
+U8FAC	anonymous	2008-12-30 (1)
+U6C12	anonymous	2008-12-30 (1)
+U61BB	anonymous	2008-12-30 (1)
+U61B9	anonymous	2008-12-30 (2)
+U61BB	anonymous	2008-12-30 (2)
+U6117	anonymous	2008-12-30 (1)
+U61D7	anonymous	2008-12-30 (1)
+U531E	anonymous	2008-12-30 (1)
+U8C74	anonymous	2008-12-30 (1)
+U81EB	anonymous	2008-12-30 (1)
+U8C63	anonymous	2008-12-30 (1)
+U5387	anonymous	2008-12-30 (1)
+U5328	anonymous	2008-12-30 (1)
+U734B	anonymous	2008-12-30 (1)
+U906C	anonymous	2008-12-30 (1)
+U83AD	anonymous	2008-12-30 (1)
+U6BF6	anonymous	2008-12-30 (1)
+U5327	anonymous	2008-12-30 (1)
+U51E8	anonymous	2008-12-30 (1)
+U8081	anonymous	2008-12-30 (1)
+U897D	anonymous	2008-12-30 (1)
+U51EE	anonymous	2008-12-30 (1)
+U9A00	anonymous	2008-12-30 (1)
+U9527	anonymous	2008-12-30 (1)
+U5E71	anonymous	2008-12-30 (1)
+U9467	anonymous	2008-12-30 (1)
+U9E50	anonymous	2008-12-30 (1)
+U65FE	anonymous	2008-12-30 (1)
+U5BB1	anonymous	2008-12-30 (1)
+U9467	anonymous	2008-12-30 (2)
+U51F4	anonymous	2008-12-30 (1)
+U9AF8	anonymous	2008-12-30 (1)
+U9466	anonymous	2008-12-30 (1)
+U72F5	anonymous	2008-12-30 (1)
+U81F0	anonymous	2008-12-30 (1)
+U9AFF	anonymous	2008-12-30 (1)
+U9D83	anonymous	2008-12-30 (1)
+U9B00	anonymous	2008-12-30 (1)
+U995A	lsz	2008-12-30 (1)
+U7215	mozbug	2008-12-30 (1)
+U7215	mozbug	2008-12-30 (2)
+U5123	anonymous	2008-12-30 (1)
+U8FA0	anonymous	2008-12-30 (1)
+U5BFD	anonymous	2008-12-30 (1)
+U9D8D	anonymous	2008-12-30 (1)
+U8FA0	anonymous	2008-12-30 (2)
+U58AD	anonymous	2008-12-30 (1)
+U5DA6	anonymous	2008-12-30 (1)
+U6725	anonymous	2008-12-30 (1)
+U7215	mozbug	2008-12-30 (3)
+U8134	anonymous	2008-12-30 (1)
+U9D95	anonymous	2008-12-30 (1)
+U812E	anonymous	2008-12-30 (1)
+U58CD	anonymous	2008-12-30 (1)
+U6707	anonymous	2008-12-30 (1)
+U898C	anonymous	2008-12-30 (1)
+U6AD4	anonymous	2008-12-30 (1)
+U7B5F	anonymous	2008-12-30 (1)
+U990B	anonymous	2008-12-30 (1)
+U7215	mozbug	2008-12-30 (4)
+U53A1	anonymous	2008-12-30 (1)
+U8D11	anonymous	2008-12-30 (1)
+U5F4D	anonymous	2008-12-30 (1)
+U6972	anonymous	2008-12-30 (1)
+U7AA1	lsz	2008-12-30 (1)
+U7215	mozbug	2008-12-30 (5)
+U8FA4	anonymous	2008-12-30 (1)
+U96F4	anonymous	2008-12-30 (1)
+U6E7C	anonymous	2008-12-30 (1)
+U7645	anonymous	2008-12-30 (1)
+U8B87	anonymous	2008-12-30 (1)
+U96EE	anonymous	2008-12-30 (1)
+U7215	mozbug	2008-12-30 (6)
+U7215	mozbug	2008-12-30 (7)
+U5093	anonymous	2008-12-30 (1)
+U7215	mozbug	2008-12-30 (8)
+U7215	mozbug	2008-12-30 (9)
+U508A	anonymous	2008-12-30 (1)
+U7A9B	lsz	2008-12-30 (1)
+U7AA7	anonymous	2008-12-30 (1)
+U8B89	anonymous	2008-12-30 (1)
+U9F73	anonymous	2008-12-30 (1)
+U689E	anonymous	2008-12-30 (1)
+U5B29	anonymous	2008-12-30 (1)
+U9F7C	anonymous	2008-12-30 (1)
+U9F68	anonymous	2008-12-30 (1)
+U8D9E	anonymous	2008-12-30 (1)
+U8D0E	anonymous	2008-12-30 (1)
+U647C	lsz	2008-12-30 (1)
+U7B55	anonymous	2008-12-30 (1)
+U6481	lsz	2008-12-30 (1)
+U647E	lsz	2008-12-30 (1)
+U8FB3	anonymous	2008-12-30 (1)
+U983A	lsz	2008-12-30 (1)
+U56F8	anonymous	2008-12-30 (1)
+U8649	anonymous	2008-12-30 (1)
+U7103	anonymous	2008-12-30 (1)
+U7F64	anonymous	2008-12-30 (1)
+U5E85	anonymous	2008-12-30 (1)
+U9B38	anonymous	2008-12-30 (1)
+U9B38	anonymous	2008-12-30 (2)
+U5DB3	anonymous	2008-12-30 (1)
+U765B	anonymous	2008-12-30 (1)
+U8771	anonymous	2008-12-30 (1)
+U6A5C	anonymous	2008-12-30 (1)
+U7AB9	anonymous	2008-12-30 (1)
+U8D18	anonymous	2008-12-30 (1)
+U5DBB	anonymous	2008-12-30 (1)
+U9D49	anonymous	2008-12-30 (1)
+U5946	anonymous	2008-12-30 (1)
+U650A	anonymous	2008-12-30 (1)
+U4E97	mosoplyr	2008-12-30 (1)
+U8689	anonymous	2008-12-30 (1)
+U8592	anonymous	2008-12-30 (1)
+U697F	anonymous	2008-12-30 (1)
+U5921	anonymous	2008-12-30 (1)
+U5DBE	anonymous	2008-12-30 (1)
+U857F	anonymous	2008-12-30 (1)
+U9840	anonymous	2008-12-30 (1)
+U5F3F	anonymous	2008-12-30 (1)
+U8716	anonymous	2008-12-30 (1)
+U52F6	anonymous	2008-12-30 (1)
+U8103	anonymous	2008-12-30 (2)
+U658A	anonymous	2008-12-30 (1)
+U7527	anonymous	2008-12-30 (1)
+U82E9	anonymous	2008-12-30 (1)
+U6457	anonymous	2008-12-30 (1)
+U810C	anonymous	2008-12-30 (2)
+U5731	anonymous	2008-12-30 (1)
+U9330	anonymous	2008-12-30 (1)
+U9D01	anonymous	2008-12-30 (1)
+U527E	anonymous	2008-12-30 (1)
+U9AA9	anonymous	2008-12-30 (1)
+U6F44	anonymous	2008-12-30 (1)
+U856F	anonymous	2008-12-30 (1)
+U9E54	anonymous	2008-12-30 (1)
+U68D9	anonymous	2008-12-30 (1)
+U6A8F	anonymous	2008-12-30 (1)
+U6A99	anonymous	2008-12-30 (1)
+U5DA3	anonymous	2008-12-30 (1)
+U6056	anonymous	2008-12-30 (1)
+U7059	anonymous	2008-12-30 (1)
+U5402	anonymous	2008-12-30 (1)
+U53FE	anonymous	2008-12-30 (1)
+U5253	anonymous	2008-12-30 (1)
+U7C1B	anonymous	2008-12-30 (1)
+U5BB7	anonymous	2008-12-30 (1)
+U8AD0	anonymous	2008-12-30 (1)
+U694D	anonymous	2008-12-30 (1)
+U66D1	anonymous	2008-12-30 (1)
+U9679	anonymous	2008-12-30 (1)
+U6D13	anonymous	2008-12-30 (1)
+U5D57	anonymous	2008-12-30 (1)
+U9037	anonymous	2008-12-30 (1)
+U5622	anonymous	2008-12-30 (1)
+U71B4	anonymous	2008-12-30 (1)
+U5622	anonymous	2008-12-30 (2)
+U5D5F	anonymous	2008-12-30 (1)
+U5619		2008-12-30 (1)
+U5625	anonymous	2008-12-30 (1)
+U9721	pem	2008-12-30 (1)
+U64C6	anonymous	2008-12-30 (1)
+U905A	anonymous	2008-12-30 (1)
+U609E	anonymous	2008-12-30 (1)
+U71B4	anonymous	2008-12-30 (2)
+U55F8	anonymous	2008-12-30 (1)
+U5688	anonymous	2008-12-30 (1)
+U9AE0	anonymous	2008-12-30 (1)
+U7218	anonymous	2008-12-30 (1)
+U7ABC	anonymous	2008-12-30 (1)
+U5D83	anonymous	2008-12-31 (1)
+U9703	anonymous	2008-12-31 (1)
+U92F5	anonymous	2008-12-31 (1)
+U8265	anonymous	2008-12-31 (1)
+U644F	anonymous	2008-12-31 (1)
+U7DFF	anonymous	2008-12-31 (1)
+U6456	anonymous	2008-12-31 (1)
+U76CB	anonymous	2008-12-31 (1)
+U6071	anonymous	2008-12-31 (1)
+U7E71	anonymous	2008-12-31 (1)
+U7ABB	anonymous	2008-12-31 (1)
+U828C	anonymous	2008-12-31 (1)
+U5525	anonymous	2008-12-31 (1)
+U7AC2	anonymous	2008-12-31 (1)
+U9484	anonymous	2008-12-31 (1)
+U7354	anonymous	2008-12-31 (1)
+U50D0	anonymous	2008-12-31 (1)
+U9372	anonymous	2008-12-31 (1)
+U9484	anonymous	2008-12-31 (2)
+U7ABD	anonymous	2008-12-31 (1)
+U95FF	anonymous	2008-12-31 (1)
+U94CF	anonymous	2008-12-31 (1)
+U6157	anonymous	2008-12-31 (1)
+U94CF	anonymous	2008-12-31 (2)
+U5D61	anonymous	2008-12-31 (1)
+U643B	anonymous	2008-12-31 (1)
+U8FC3	anonymous	2008-12-31 (1)
+U50A1	anonymous	2008-12-31 (1)
+U82B2	anonymous	2008-12-31 (1)
+U855F	anonymous	2008-12-31 (1)
+U9938	anonymous	2008-12-31 (1)
+U995D	anonymous	2008-12-31 (1)
+U9962	anonymous	2008-12-31 (1)
+U530C	anonymous	2008-12-31 (1)
+U530C	anonymous	2008-12-31 (2)
+U92EC	anonymous	2008-12-31 (1)
+U9ADD	anonymous	2008-12-31 (1)
+U8552	anonymous	2008-12-31 (1)
+U7B68	anonymous	2008-12-31 (1)
+U9847	anonymous	2008-12-31 (1)
+U7DF5	anonymous	2008-12-31 (1)
+U7AC9	anonymous	2008-12-31 (1)
+U69C0	anonymous	2008-12-31 (1)
+U69D6	anonymous	2008-12-31 (1)
+U5DE4	anonymous	2008-12-31 (1)
+U9331	anonymous	2008-12-31 (1)
+U8296	anonymous	2008-12-31 (1)
+U82C6	anonymous	2008-12-31 (1)
+U5F72	anonymous	2008-12-31 (1)
+U9373	anonymous	2008-12-31 (1)
+U6693	anonymous	2008-12-31 (1)
+U5C43	anonymous	2008-12-31 (1)
+U6E95	anonymous	2008-12-31 (1)
+U8989	anonymous	2008-12-31 (1)
+U7B5E	anonymous	2008-12-31 (1)
+U8FCC	anonymous	2008-12-31 (1)
+U7B6B	anonymous	2008-12-31 (1)
+U898D	anonymous	2008-12-31 (1)
+U63FC	anonymous	2008-12-31 (1)
+U5128	anonymous	2008-12-31 (1)
+U6C56	anonymous	2008-12-31 (1)
+U9DE7	anonymous	2008-12-31 (1)
+U7B16	anonymous	2008-12-31 (1)
+U96B5	anonymous	2008-12-31 (1)
+U5C77	anonymous	2008-12-31 (1)
+U9584	anonymous	2008-12-31 (1)
+U561A	anonymous	2008-12-31 (1)
+U60EA	anonymous	2008-12-31 (1)
+U6C1E	anonymous	2008-12-31 (1)
+U7BBB	anonymous	2008-12-31 (1)
+U588C	anonymous	2008-12-31 (1)
+U9581	anonymous	2008-12-31 (1)
+U6884	anonymous	2008-12-31 (1)
+U7499	anonymous	2008-12-31 (1)
+U5B0E	anonymous	2008-12-31 (1)
+U8994	anonymous	2008-12-31 (1)
+U52F6	lsz	2008-12-31 (2)
+U8DA2	anonymous	2008-12-31 (1)
+U6404	anonymous	2008-12-31 (1)
+U4F40	anonymous	2008-12-31 (1)
+U6431	anonymous	2008-12-31 (1)
+U7B29	anonymous	2008-12-31 (1)
+U5DBF	anonymous	2008-12-31 (1)
+U55B8	anonymous	2008-12-31 (1)
+U5DC4	anonymous	2008-12-31 (1)
+U5711	anonymous	2008-12-31 (1)
+U970C	anonymous	2008-12-31 (1)
+U5655	anonymous	2008-12-31 (1)
+U6D73	anonymous	2008-12-31 (1)
+U5C2F	anonymous	2008-12-31 (1)
+U69E3	lsz	2008-12-31 (1)
+U6EA9	anonymous	2008-12-31 (1)
+U5C35	anonymous	2008-12-31 (1)
+U9585	anonymous	2008-12-31 (1)
+U67E1	lsz	2008-12-31 (1)
+U7B37	anonymous	2008-12-31 (1)
+U70FE	anonymous	2008-12-31 (1)
+U6B0D	lsz	2008-12-31 (1)
+U6870	anonymous	2008-12-31 (1)
+U5286	anonymous	2008-12-31 (1)
+U6B15	lsz	2008-12-31 (1)
+U8851	anonymous	2008-12-31 (1)
+U9BBA	anonymous	2008-12-31 (1)
+U885C	anonymous	2008-12-31 (1)
+U7B3F	anonymous	2008-12-31 (1)
+U55ED	anonymous	2008-12-31 (1)
+U885C	anonymous	2008-12-31 (2)
+U9734	anonymous	2008-12-31 (1)
+U6D21	anonymous	2008-12-31 (1)
+U82DD	anonymous	2008-12-31 (1)
+U51A3	anonymous	2008-12-31 (1)
+U863D	anonymous	2008-12-31 (1)
+U971A	anonymous	2008-12-31 (1)
+U66D3	lsz	2008-12-31 (1)
+U8FCF	anonymous	2008-12-31 (1)
+U8FCA	anonymous	2008-12-31 (1)
+U7BB3	anonymous	2008-12-31 (1)
+U7211	anonymous	2008-12-31 (1)
+U8672	anonymous	2008-12-31 (1)
+U95B4	anonymous	2008-12-31 (1)
+U7BC2	anonymous	2008-12-31 (1)
+U7BC3	anonymous	2008-12-31 (1)
+U7003	李健	2008-12-31 (1)
+U6056	lsz	2008-12-31 (2)
+U7B42	anonymous	2008-12-31 (1)
+U9714	anonymous	2008-12-31 (1)
+U748F	anonymous	2008-12-31 (1)
+U95EC	anonymous	2008-12-31 (1)
+U95EC	anonymous	2008-12-31 (2)
+U7604	anonymous	2008-12-31 (1)
+U52A5	anonymous	2008-12-31 (1)
+U87A9	anonymous	2008-12-31 (1)
+U9A18	anonymous	2008-12-31 (1)
+U6A10	anonymous	2008-12-31 (1)
+U5D75	anonymous	2008-12-31 (1)
+U9A47	anonymous	2008-12-31 (1)
+U6A5C	lsz	2008-12-31 (2)
+U857D	anonymous	2008-12-31 (1)
+U87FD	anonymous	2008-12-31 (1)
+U8313	anonymous	2008-12-31 (1)
+U5D64	anonymous	2008-12-31 (1)
+U90F6	anonymous	2008-12-31 (1)
+U60D6	anonymous	2008-12-31 (1)
+U531B	anonymous	2008-12-31 (1)
+U802F	anonymous	2008-12-31 (1)
+U5560	anonymous	2008-12-31 (1)
+U5D96	anonymous	2008-12-31 (1)
+U5E98	anonymous	2008-12-31 (1)
+U7607		2008-12-31 (1)
+U61DA	anonymous	2008-12-31 (1)
+U61DB	anonymous	2008-12-31 (1)
+U7612		2008-12-31 (1)
+U60FD	anonymous	2008-12-31 (1)
+U8666	anonymous	2008-12-31 (1)
+U765D	anonymous	2008-12-31 (1)
+U765D	anonymous	2008-12-31 (2)
+U8CEF	anonymous	2008-12-31 (1)
+U9D1C	anonymous	2008-12-31 (1)
+U9597	anonymous	2008-12-31 (1)
+U9595	anonymous	2008-12-31 (1)
+U5B1C	anonymous	2008-12-31 (1)
+U6C0A	anonymous	2008-12-31 (1)
+U6BB9	anonymous	2008-12-31 (1)
+U81CE	anonymous	2008-12-31 (1)
+U579C	anonymous	2008-12-31 (1)
+U6AC4	anonymous	2008-12-31 (1)
+U6AC0	anonymous	2008-12-31 (1)
+U50CC	anonymous	2008-12-31 (1)
+U5F2C	anonymous	2008-12-31 (1)
+U96E6	anonymous	2008-12-31 (1)
+U97A9	anonymous	2008-12-31 (1)
+U97EF	anonymous	2008-12-31 (1)
+U9613	anonymous	2008-12-31 (1)
+U9618	anonymous	2008-12-31 (1)
+U6107	anonymous	2008-12-31 (1)
+U7B27	anonymous	2008-12-31 (1)
+U66AD	wanghong	2008-12-31 (1)
+U95E7	anonymous	2008-12-31 (1)
+U4E64	anonymous	2008-12-31 (1)
+U71BB	anonymous	2008-12-31 (1)
+U6F98	anonymous	2008-12-31 (1)
+U881A	anonymous	2008-12-31 (1)
+U9D47	anonymous	2008-12-31 (1)
+U7BC5	anonymous	2008-12-31 (1)
+U6F98	anonymous	2008-12-31 (2)
+U69E9	lsz	2008-12-31 (1)
+U9B02	anonymous	2008-12-31 (1)
+U551F	anonymous	2008-12-31 (1)
+U95B8	anonymous	2008-12-31 (1)
+U4E9D	lsz	2008-12-31 (1)
+U582B	anonymous	2008-12-31 (1)
+U8984	anonymous	2008-12-31 (1)
+U6178	lsz	2008-12-31 (1)
+U83A1	anonymous	2008-12-31 (1)
+U8370	anonymous	2008-12-31 (1)
+U6D4C	lsz	2008-12-31 (1)
+U76FF	anonymous	2008-12-31 (2)
+U9E4D	anonymous	2008-12-31 (1)
+U6B40	anonymous	2008-12-31 (1)
+U5AD3	anonymous	2008-12-31 (1)
+U7B57	anonymous	2008-12-31 (1)
+U6E7D	anonymous	2008-12-31 (1)
+U50E1	anonymous	2008-12-31 (1)
+U7542	anonymous	2008-12-31 (1)
+U5EA9	anonymous	2008-12-31 (1)
+U6C3C	anonymous	2008-12-31 (1)
+U82DA	anonymous	2008-12-31 (1)
+U52A7	anonymous	2008-12-31 (1)
+U6E84	lsz	2008-12-31 (1)
+U93C5	anonymous	2008-12-31 (1)
+U6E7D	lsz	2008-12-31 (2)
+U5304	anonymous	2008-12-31 (1)
+U5905		2008-12-31 (1)
+U66D4	anonymous	2008-12-31 (1)
+U662A		2008-12-31 (1)
+U7B59		2008-12-31 (1)
+U98B5	anonymous	2008-12-31 (1)
+U6A9D	李健	2008-12-31 (1)
+U7B5C		2008-12-31 (1)
+U68E5		2008-12-31 (1)
+U6895	anonymous	2008-12-31 (1)
+U7067		2008-12-31 (1)
+U6EAD	anonymous	2008-12-31 (1)
+U89B0	anonymous	2008-12-31 (1)
+U9E08	anonymous	2008-12-31 (1)
+U50D2	anonymous	2008-12-31 (1)
+U5B31		2008-12-31 (1)
+U66E2	sui z	2008-12-31 (1)
+U89B5	anonymous	2008-12-31 (1)
+U50F2	anonymous	2008-12-31 (1)
+U93F2	anonymous	2008-12-31 (1)
+U50F2	anonymous	2008-12-31 (2)
+U70D5	anonymous	2008-12-31 (1)
+U5127	anonymous	2008-12-31 (1)
+U5EBD	anonymous	2008-12-31 (1)
+U5BED	anonymous	2008-12-31 (1)
+U8FE7	anonymous	2008-12-31 (1)
+U8FEC	anonymous	2008-12-31 (1)
+U7F84	lsz	2008-12-31 (1)
+U9866	anonymous	2008-12-31 (1)
+U56C7	anonymous	2008-12-31 (1)
+U7F90	lsz	2008-12-31 (1)
+U96E7	lsz	2008-12-31 (1)
+U56D6	anonymous	2008-12-31 (1)
+U512C	anonymous	2008-12-31 (1)
+U5611	anonymous	2008-12-31 (1)
+U53F4	anonymous	2008-12-31 (1)
+U53BC	anonymous	2008-12-31 (1)
+U8B9D	anonymous	2008-12-31 (1)
+U8FF1	anonymous	2008-12-31 (1)
+U89F9	anonymous	2008-12-31 (1)
+U5656	anonymous	2008-12-31 (1)
+U6530	anonymous	2008-12-31 (1)
+U653C	anonymous	2008-12-31 (1)
+U98A3	anonymous	2008-12-31 (1)
+U978C	anonymous	2008-12-31 (1)
+U529A	anonymous	2008-12-31 (1)
+U688E	anonymous	2008-12-31 (1)
+U9B07	anonymous	2008-12-31 (1)
+U688E	anonymous	2008-12-31 (2)
+U7550	anonymous	2008-12-31 (1)
+U5873	anonymous	2008-12-31 (1)
+U52CE	anonymous	2008-12-31 (1)
+U9D91	anonymous	2008-12-31 (1)
+U7C2E	anonymous	2008-12-31 (1)
+U830B	anonymous	2008-12-31 (1)
+U847B	anonymous	2008-12-31 (1)
+U64C8	anonymous	2008-12-31 (1)
+U9ECB	anonymous	2008-12-31 (1)
+U9934	anonymous	2008-12-31 (1)
+U9CE4	anonymous	2008-12-31 (1)
+U8B97	FangQ	2008-12-31 (1)
+U75C6	anonymous	2008-12-31 (1)
+U8B97	anonymous	2008-12-31 (2)
+U82E2	anonymous	2008-12-31 (1)
+U6EB5	anonymous	2008-12-31 (1)
+U6ABC	anonymous	2008-12-31 (1)
+U9EA2	anonymous	2008-12-31 (1)
+U6098	anonymous	2008-12-31 (1)
+U6C2D	anonymous	2008-12-31 (1)
+U9AE8	anonymous	2008-12-31 (1)
+U6ED9	anonymous	2008-12-31 (1)
+U6244	anonymous	2008-12-31 (1)
+U6244	anonymous	2008-12-31 (2)
+U959D	anonymous	2008-12-31 (1)
+U89B8	anonymous	2008-12-31 (1)
+U69F5	anonymous	2008-12-31 (1)
+U7496	anonymous	2008-12-31 (1)
+U4C36	FangQ	2008-12-31 (1)
+U85F4	anonymous	2008-12-31 (1)
+U648E	anonymous	2008-12-31 (1)
+U4C37	FangQ	2008-12-31 (1)
+U4C38	FangQ	2008-12-31 (1)
+U66A5	anonymous	2008-12-31 (1)
+U4C5B	FangQ	2008-12-31 (1)
+U4C5C	FangQ	2008-12-31 (1)
+U85EE	anonymous	2008-12-31 (1)
+U56A1	anonymous	2008-12-31 (1)
+U52B6	anonymous	2008-12-31 (1)
+U85F5	anonymous	2008-12-31 (1)
+U5866	anonymous	2008-12-31 (1)
+U565D	anonymous	2008-12-31 (1)
+U569F	anonymous	2008-12-31 (1)
+U8190	anonymous	2008-12-31 (1)
+U7CF5	anonymous	2008-12-31 (1)
+U5DD7	anonymous	2008-12-31 (1)
+U5DD9	anonymous	2008-12-31 (1)
+U5DDA	anonymous	2008-12-31 (1)
+U5753	anonymous	2008-12-31 (1)
+U65A3	anonymous	2008-12-31 (1)
+U5B44	anonymous	2008-12-31 (1)
+U65D8	anonymous	2008-12-31 (1)
+U35CA	FangQ	2008-12-31 (1)
+U3930	FangQ	2008-12-31 (1)
+U3F52	FangQ	2008-12-31 (1)
+U6432	anonymous	2008-12-31 (1)
+U6462	anonymous	2008-12-31 (1)
+U6432	anonymous	2008-12-31 (2)
+U6462	anonymous	2008-12-31 (2)
+U933D	anonymous	2008-12-31 (1)
+U9B14	anonymous	2008-12-31 (1)
+U5796	anonymous	2008-12-31 (1)
+U61A5	anonymous	2008-12-31 (1)
+U4B33	anonymous	2008-12-31 (1)
+U5D8F	anonymous	2008-12-31 (1)
+U390C	anonymous	2008-12-31 (1)
+U5D98	anonymous	2008-12-31 (1)
+U390E	anonymous	2008-12-31 (1)
+U406B	anonymous	2008-12-31 (1)
+U406C	anonymous	2008-12-31 (1)
+U9F6D	anonymous	2008-12-31 (1)
+U406D	anonymous	2008-12-31 (1)
+U6F16	anonymous	2008-12-31 (1)
+U3473	anonymous	2008-12-31 (1)
+U9F3F	anonymous	2008-12-31 (1)
+U3475	anonymous	2008-12-31 (1)
+U56F6	anonymous	2008-12-31 (1)
+U6F0B	anonymous	2008-12-31 (1)
+U6EE7	anonymous	2008-12-31 (1)
+U42E5	anonymous	2008-12-31 (1)
+U6256	anonymous	2008-12-31 (1)
+U5966	anonymous	2008-12-31 (1)
+U36C7	anonymous	2008-12-31 (1)
+U36C9	anonymous	2008-12-31 (1)
+U9137	anonymous	2008-12-31 (1)
+U7493	anonymous	2008-12-31 (1)
+U74C7	anonymous	2008-12-31 (1)
+U66AC	anonymous	2008-12-31 (1)
+U9717	anonymous	2008-12-31 (1)
+U5F0E	anonymous	2008-12-31 (1)
+U46B1	FangQ	2008-12-31 (1)
+U46B1	FangQ	2008-12-31 (2)
+U3841	anonymous	2008-12-31 (1)
+U98B4	anonymous	2008-12-31 (1)
+U8739	anonymous	2008-12-31 (1)
+U98AB	anonymous	2008-12-31 (1)
+U66C3	anonymous	2008-12-31 (1)
+U95C1	anonymous	2008-12-31 (1)
+U4819	anonymous	2008-12-31 (1)
+U95A6	anonymous	2008-12-31 (1)
+U37AF	anonymous	2008-12-31 (1)
+U37B0	anonymous	2008-12-31 (1)
+U3FE0	anonymous	2008-12-31 (1)
+U95C4	anonymous	2008-12-31 (1)
+U9092	anonymous	2008-12-31 (1)
+U3FDF	anonymous	2008-12-31 (1)
+U5D9B	anonymous	2008-12-31 (1)
+U3803	anonymous	2008-12-31 (1)
+U5572	anonymous	2008-12-31 (1)
+U95D9	anonymous	2008-12-31 (1)
+U8DA4	anonymous	2008-12-31 (1)
+U4817	anonymous	2008-12-31 (1)
+U3837	anonymous	2008-12-31 (1)
+U8DA4	anonymous	2008-12-31 (2)
+U5DAB	anonymous	2008-12-31 (1)
+U95D7	anonymous	2008-12-31 (1)
+U648D	anonymous	2008-12-31 (1)
+U46A4	anonymous	2008-12-31 (1)
+U48BB	anonymous	2008-12-31 (1)
+U364B	anonymous	2008-12-31 (1)
+U5B60	anonymous	2008-12-31 (1)
+U74CC	anonymous	2008-12-31 (1)
+U48BC	anonymous	2008-12-31 (1)
+U4B66	anonymous	2008-12-31 (1)
+U5911	anonymous	2008-12-31 (1)
+U3953	anonymous	2008-12-31 (1)
+U4D5E	anonymous	2008-12-31 (1)
+U3E1D	anonymous	2008-12-31 (1)
+U4D5F	anonymous	2008-12-31 (1)
+U4D60	anonymous	2008-12-31 (1)
+U8008	anonymous	2008-12-31 (1)
+U43FD	anonymous	2008-12-31 (1)
+U3D58	anonymous	2008-12-31 (1)
+U3D59	anonymous	2008-12-31 (1)
+U43FE	anonymous	2008-12-31 (1)
+U5964	anonymous	2008-12-31 (1)
+U4A50	anonymous	2008-12-31 (1)
+U4268	anonymous	2008-12-31 (1)
+U5F5E	anonymous	2008-12-31 (1)
+U4C91	anonymous	2008-12-31 (1)
+U596F	anonymous	2008-12-31 (1)
+U3CCC	anonymous	2008-12-31 (1)
+U4C92	anonymous	2008-12-31 (1)
+U435A	anonymous	2008-12-31 (1)
+U435B	anonymous	2008-12-31 (1)
+U7D23	anonymous	2008-12-31 (1)
+U8DA6	anonymous	2008-12-31 (1)
+U913D	anonymous	2008-12-31 (1)
+U8DA6	anonymous	2008-12-31 (2)
+U3907	anonymous	2008-12-31 (1)
+U435C	anonymous	2008-12-31 (1)
+U4A80	anonymous	2008-12-31 (1)
+U3908	anonymous	2008-12-31 (1)
+U3C29	anonymous	2008-12-31 (1)
+U4A51	anonymous	2008-12-31 (1)
+U3909	anonymous	2008-12-31 (1)
+U7CED	anonymous	2008-12-31 (1)
+U3C2A	anonymous	2008-12-31 (1)
+U42A0	anonymous	2008-12-31 (1)
+U42A1	anonymous	2008-12-31 (1)
+U47B5	anonymous	2008-12-31 (1)
+U5528	anonymous	2008-12-31 (1)
+U42A2	anonymous	2008-12-31 (1)
+U47B5	anonymous	2008-12-31 (2)
+U36E3	anonymous	2008-12-31 (1)
+U854C	anonymous	2008-12-31 (1)
+U4AD6	anonymous	2008-12-31 (1)
+U3928	anonymous	2008-12-31 (1)
+U9D4E	anonymous	2008-12-31 (1)
+U3462	anonymous	2008-12-31 (1)
+U3461	anonymous	2008-12-31 (1)
+U3460	anonymous	2008-12-31 (1)
+U4294	anonymous	2008-12-31 (1)
+U4295	anonymous	2008-12-31 (1)
+U4296	anonymous	2008-12-31 (1)
+U3CA2	anonymous	2008-12-31 (1)
+U4BA3	anonymous	2008-12-31 (1)
+U8683	anonymous	2008-12-31 (1)
+U49CB	anonymous	2008-12-31 (1)
+U4BA4	anonymous	2008-12-31 (1)
+U3D43	anonymous	2008-12-31 (1)
+U49CC	anonymous	2008-12-31 (1)
+U7B83	anonymous	2008-12-31 (1)
+U3CE2	anonymous	2008-12-31 (1)
+U4345	anonymous	2008-12-31 (1)
+U6EFA	anonymous	2008-12-31 (1)
+U35C5	anonymous	2008-12-31 (1)
+U38AE	anonymous	2008-12-31 (1)
+U49CD	anonymous	2008-12-31 (1)
+U35C5	anonymous	2008-12-31 (2)
+U35C7	anonymous	2008-12-31 (1)
+U35E7	anonymous	2008-12-31 (1)
+U6463	anonymous	2008-12-31 (1)
+U702E	anonymous	2008-12-31 (1)
+U656E	anonymous	2008-12-31 (1)
+U6571	anonymous	2008-12-31 (1)
+U49D8	anonymous	2008-12-31 (1)
+U85CA	anonymous	2008-12-31 (1)
+U357C	anonymous	2008-12-31 (1)
+U6586	anonymous	2008-12-31 (1)
+U3CFC	anonymous	2008-12-31 (1)
+U35E8	anonymous	2008-12-31 (1)
+U4422	anonymous	2008-12-31 (1)
+U39C9	anonymous	2008-12-31 (1)
+U4423	anonymous	2008-12-31 (1)
+U4423	anonymous	2008-12-31 (2)
+U7CF3	anonymous	2008-12-31 (1)
+U39CA	anonymous	2008-12-31 (1)
+U39CB	anonymous	2008-12-31 (1)
+U45CA	lsz	2008-12-31 (1)
+U45CC	lsz	2008-12-31 (1)
+U851B	anonymous	2008-12-31 (1)
+U8DA9	anonymous	2008-12-31 (1)
+U97E4	anonymous	2008-12-31 (1)
+U6B70	anonymous	2008-12-31 (1)
+U9715	anonymous	2008-12-31 (1)
+U6B71	anonymous	2008-12-31 (1)
+U8DA9	anonymous	2008-12-31 (2)
+U5DA4	anonymous	2008-12-31 (1)
+U3C4B	anonymous	2008-12-31 (1)
+U6B75	anonymous	2008-12-31 (1)
+U5DC8	anonymous	2008-12-31 (1)
+U9479	anonymous	2008-12-31 (1)
+U3C9B	anonymous	2008-12-31 (1)
+U45CB	lsz	2008-12-31 (1)
+U436A	lsz	2008-12-31 (1)
+U6A57	anonymous	2008-12-31 (1)
+U3C9C	anonymous	2008-12-31 (1)
+U436C	lsz	2008-12-31 (1)
+U436B	lsz	2008-12-31 (1)
+U6464	anonymous	2008-12-31 (1)
+U3C68	anonymous	2008-12-31 (1)
+U3C69	anonymous	2008-12-31 (1)
+U6AF7	anonymous	2008-12-31 (1)
+U56A4	anonymous	2008-12-31 (1)
+U4054	anonymous	2008-12-31 (1)
+U646A	anonymous	2008-12-31 (1)
+U498F	lsz	2008-12-31 (1)
+U4990	lsz	2008-12-31 (1)
+U6AD2	anonymous	2008-12-31 (1)
+U6A4A	anonymous	2008-12-31 (1)
+U4A9B	anonymous	2008-12-31 (1)
+U9071	anonymous	2008-12-31 (1)
+U83DA	anonymous	2008-12-31 (1)
+U4859	anonymous	2008-12-31 (1)
+U9D55	anonymous	2008-12-31 (1)
+U43E1	anonymous	2008-12-31 (1)
+U43E2	anonymous	2008-12-31 (1)
+U43E3	anonymous	2008-12-31 (1)
+U3B13	anonymous	2008-12-31 (1)
+U9D4D	anonymous	2008-12-31 (1)
+U4A19	anonymous	2008-12-31 (1)
+U3B14	anonymous	2008-12-31 (1)
+U4991	lsz	2008-12-31 (1)
+U3B15	anonymous	2008-12-31 (1)
+U485B	anonymous	2008-12-31 (1)
+U9D65	anonymous	2008-12-31 (1)
+U48C1	anonymous	2008-12-31 (1)
+U394D	anonymous	2008-12-31 (1)
+U394F	anonymous	2008-12-31 (1)
+U8D01	anonymous	2008-12-31 (1)
+U3995	anonymous	2008-12-31 (1)
+U3996	anonymous	2008-12-31 (1)
+U5574	anonymous	2008-12-31 (2)
+U4506	anonymous	2008-12-31 (1)
+U5F5A	anonymous	2008-12-31 (1)
+U5573	anonymous	2008-12-31 (2)
+U36AA	anonymous	2008-12-31 (1)
+U4507	anonymous	2008-12-31 (1)
+U5579	anonymous	2008-12-31 (2)
+U7B6A	phoebezh	2008-12-31 (1)
+U48D3	lsz	2008-12-31 (1)
+U5F5F	anonymous	2008-12-31 (1)
+U48D4	lsz	2008-12-31 (1)
+U906A	anonymous	2008-12-31 (1)
+U48D5	lsz	2008-12-31 (1)
+U860D	anonymous	2008-12-31 (1)
+U6B5D	anonymous	2008-12-31 (1)
+U440F	anonymous	2008-12-31 (1)
+U6B68	anonymous	2008-12-31 (1)
+U477D	bloodelf	2008-12-31 (1)
+U3911	anonymous	2008-12-31 (1)
+U832E	anonymous	2008-12-31 (1)
+U4354	anonymous	2008-12-31 (1)
+U831D	anonymous	2008-12-31 (1)
+U4356	anonymous	2008-12-31 (1)
+U9D7C	anonymous	2008-12-31 (1)
+U3B22	bloodelf	2008-12-31 (1)
+U3539	bloodelf	2008-12-31 (1)
+U47D8	bloodelf	2008-12-31 (1)
+U4D3E	lsz	2008-12-31 (1)
+U764F	anonymous	2008-12-31 (1)
+U864A	anonymous	2008-12-31 (1)
+U4D40	lsz	2008-12-31 (1)
+U545D	anonymous	2008-12-31 (1)
+U39FA	lsz	2008-12-31 (1)
+U39FB	lsz	2008-12-31 (1)
+U340B	anonymous	2008-12-31 (1)
+U39FB	lsz	2008-12-31 (2)
+U713F	anonymous	2008-12-31 (1)
+U7243	anonymous	2008-12-31 (1)
+U340A	anonymous	2008-12-31 (1)
+U4605	lsz	2008-12-31 (1)
+U4606	lsz	2008-12-31 (1)
+U757B	anonymous	2008-12-31 (1)
+U712D	anonymous	2008-12-31 (1)
+U3DCE	phoebezh	2008-12-31 (1)
+U4607	lsz	2008-12-31 (1)
+U4607	lsz	2008-12-31 (2)
+U6AB0	anonymous	2008-12-31 (1)
+U833D	anonymous	2008-12-31 (1)
+U4D9E	phoebezh	2008-12-31 (1)
+U37AD	phoebezh	2008-12-31 (1)
+U9DC9	anonymous	2008-12-31 (1)
+U3A5D	anonymous	2008-12-31 (1)
+U9D76	anonymous	2008-12-31 (1)
+U3EDE	FangQ	2008-12-31 (1)
+U3A5C	anonymous	2008-12-31 (1)
+U35ED	FangQ	2008-12-31 (1)
+U9DD4	anonymous	2008-12-31 (1)
+U35EF	FangQ	2008-12-31 (1)
+U447A	phoebezh	2008-12-31 (1)
+U35A5	FangQ	2008-12-31 (1)
+U35A6	FangQ	2008-12-31 (1)
+U4214	phoebezh	2008-12-31 (1)
+U35A7	FangQ	2008-12-31 (1)
+U9D27	anonymous	2008-12-31 (1)
+U3A5B	anonymous	2008-12-31 (1)
+U4ACD	FangQ	2008-12-31 (1)
+U4ACF	FangQ	2008-12-31 (1)
+U4ACE	FangQ	2008-12-31 (1)
+U4634	anonymous	2008-12-31 (1)
+U7C4B	anonymous	2008-12-31 (1)
+U3C2F	FangQ	2008-12-31 (1)
+U46E9	anonymous	2008-12-31 (1)
+U4635	anonymous	2008-12-31 (1)
+U9DFC	anonymous	2008-12-31 (1)
+U4636	anonymous	2008-12-31 (1)
+U3C30	FangQ	2008-12-31 (1)
+U3C31	FangQ	2008-12-31 (1)
+U46EB	anonymous	2008-12-31 (1)
+U9E0A	anonymous	2008-12-31 (1)
+U4853	FangQ	2008-12-31 (1)
+U4130	anonymous	2008-12-31 (1)
+U4214	phoebezh	2008-12-31 (2)
+U4131	anonymous	2008-12-31 (1)
+U3E4A	anonymous	2008-12-31 (1)
+U4132	anonymous	2008-12-31 (1)
+U861D	anonymous	2008-12-31 (1)
+U4D30	anonymous	2008-12-31 (1)
+U9F7D	anonymous	2008-12-31 (1)
+U4854	FangQ	2008-12-31 (1)
+U3E4B	anonymous	2008-12-31 (1)
+U4855	FangQ	2008-12-31 (1)
+U85A5	anonymous	2008-12-31 (1)
+U3575	anonymous	2008-12-31 (1)
+U4C0F	anonymous	2008-12-31 (1)
+U3E4C	anonymous	2008-12-31 (1)
+U9F8F	anonymous	2008-12-31 (1)
+U5943	anonymous	2008-12-31 (1)
+U3CED	anonymous	2008-12-31 (1)
+U3AA6	anonymous	2008-12-31 (1)
+U3BE9	anonymous	2008-12-31 (1)
+U4997	phoebezh	2008-12-31 (1)
+U4834	phoebezh	2008-12-31 (1)
+U480A	anonymous	2008-12-31 (1)
+U35A3	anonymous	2008-12-31 (1)
+U3BEA	anonymous	2008-12-31 (1)
+U4374	phoebezh	2008-12-31 (1)
+U3BEB	anonymous	2008-12-31 (1)
+U480B	anonymous	2008-12-31 (1)
+U8780	anonymous	2008-12-31 (1)
+U38C4	phoebezh	2008-12-31 (1)
+U4BC6	anonymous	2008-12-31 (1)
+U3B10	anonymous	2008-12-31 (1)
+U40A6	anonymous	2008-12-31 (1)
+U3B11	anonymous	2008-12-31 (1)
+U4AE5	phoebezh	2008-12-31 (1)
+U3B12	anonymous	2008-12-31 (1)
+U3DFB	anonymous	2008-12-31 (1)
+U3DFD	anonymous	2008-12-31 (1)
+U3637	Shiqi Yu	2008-12-31 (1)
+U4832	anonymous	2008-12-31 (1)
+U4833	anonymous	2008-12-31 (1)
+U34B6		2008-12-31 (1)
+U437B	anonymous	2008-12-31 (1)
+U34B6		2008-12-31 (2)
+U491E	pem	2008-12-31 (1)
+U359F		2008-12-31 (1)
+U35A0		2008-12-31 (1)
+U4680	pem	2008-12-31 (1)
+U35A1		2008-12-31 (1)
+U3A2A	pem	2008-12-31 (1)
+U46D3	Shiqi Yu	2008-12-31 (1)
+U40A0		2008-12-31 (1)
+U46D4	Shiqi Yu	2008-12-31 (1)
+U475B	phoebezh	2008-12-31 (1)
+U3756	Shiqi Yu	2008-12-31 (1)
+U475B	phoebezh	2008-12-31 (2)
+U449C	phoebezh	2008-12-31 (1)
+U49EB	phoebezh	2008-12-31 (1)
+U3758	Shiqi Yu	2008-12-31 (1)
+U3AC9	phoebezh	2008-12-31 (1)
+U37E8	Shiqi Yu	2008-12-31 (1)
+U47DB	phoebezh	2008-12-31 (1)
+U37EA	Shiqi Yu	2008-12-31 (1)
+U43E0	phoebezh	2008-12-31 (1)
+U3BF5	phoebezh	2008-12-31 (1)
+U4850	Shiqi Yu	2008-12-31 (1)
+U4466	anonymous	2008-12-31 (1)
+U343D	anonymous	2008-12-31 (1)
+U4D6A	anonymous	2008-12-31 (1)
+U74C8	anonymous	2008-12-31 (1)
+U409B	anonymous	2008-12-31 (1)
+U405B	anonymous	2008-12-31 (1)
+U709B	anonymous	2008-12-31 (1)
+U36A7	anonymous	2008-12-31 (1)
+U4C71	anonymous	2008-12-31 (1)
+U42F2	anonymous	2008-12-31 (1)
+U36A8	anonymous	2008-12-31 (1)
+U4404	anonymous	2008-12-31 (1)
+U42F1	anonymous	2008-12-31 (1)
+U4C1C	anonymous	2008-12-31 (1)
+U42F3	anonymous	2008-12-31 (1)
+U3E07	yanqian	2008-12-31 (1)
+U3878	anonymous	2008-12-31 (1)
+U36B3	anonymous	2008-12-31 (1)
+U3879	anonymous	2008-12-31 (1)
+U370F	anonymous	2008-12-31 (1)
+U3F57	anonymous	2008-12-31 (1)
+U387A	anonymous	2008-12-31 (1)
+U3C5A	anonymous	2008-12-31 (1)
+U3ECD	anonymous	2008-12-31 (1)
+U4800	anonymous	2008-12-31 (1)
+U3C5B	anonymous	2008-12-31 (1)
+U446E	anonymous	2008-12-31 (1)
+U446F	anonymous	2008-12-31 (1)
+U466E	anonymous	2008-12-31 (1)
+U391D	anonymous	2008-12-31 (1)
+U70F5	anonymous	2008-12-31 (1)
+U43FA	anonymous	2008-12-31 (1)
+U3C60	anonymous	2008-12-31 (1)
+U3C5F	anonymous	2008-12-31 (1)
+U3C61	anonymous	2008-12-31 (1)
+U409E	anonymous	2008-12-31 (1)
+U4B4A	anonymous	2008-12-31 (1)
+U9DEA	FangQ	2008-12-31 (1)
+U9E0E	FangQ	2008-12-31 (1)
+U417A	anonymous	2008-12-31 (1)
+U417B	anonymous	2008-12-31 (1)
+U417C	anonymous	2008-12-31 (1)
+U39CD	anonymous	2008-12-31 (1)
+U39CE	anonymous	2008-12-31 (1)
+U3E67	anonymous	2008-12-31 (1)
+U3E68	anonymous	2008-12-31 (1)
+U3E69	anonymous	2008-12-31 (1)
+U4839	anonymous	2008-12-31 (1)
+U3F57	FangQ	2008-12-31 (2)
+U4838	anonymous	2008-12-31 (1)
+U4861	FangQ	2008-12-31 (1)
+U4862	FangQ	2008-12-31 (1)
+U4863	FangQ	2008-12-31 (1)
+U3691	anonymous	2008-12-31 (1)
+U3691	anonymous	2008-12-31 (2)
+U40E5	anonymous	2008-12-31 (1)
+U36F4	anonymous	2008-12-31 (1)
+U4390	anonymous	2008-12-31 (1)
+U4164	anonymous	2008-12-31 (1)
+U4166	anonymous	2008-12-31 (1)
+U4165	anonymous	2008-12-31 (1)
+U36EB	anonymous	2008-12-31 (1)
+U45CE	anonymous	2008-12-31 (1)
+U4120	anonymous	2008-12-31 (1)
+U38E9	anonymous	2008-12-31 (1)
+U4463	anonymous	2008-12-31 (1)
+U4462	anonymous	2008-12-31 (1)
+U3B74	anonymous	2008-12-31 (1)
+U3B74	anonymous	2008-12-31 (2)
+U4342	anonymous	2008-12-31 (1)
+U428A	anonymous	2008-12-31 (1)
+U3430	anonymous	2008-12-31 (1)
+U3A0B	anonymous	2008-12-31 (1)
+U3446	anonymous	2008-12-31 (1)
+U3447	anonymous	2008-12-31 (1)
+U37AB	anonymous	2008-12-31 (1)
+U4AAD	anonymous	2008-12-31 (1)
+U3F84	anonymous	2008-12-31 (1)
+U363F	anonymous	2008-12-31 (1)
+U4349	anonymous	2008-12-31 (1)
+U434A	anonymous	2008-12-31 (1)
+U3DB7	anonymous	2008-12-31 (1)
+U36F0	anonymous	2008-12-31 (1)
+U43A5	anonymous	2008-12-31 (1)
+U43A7	anonymous	2008-12-31 (1)
+U43A6	anonymous	2008-12-31 (1)
+U4837	anonymous	2008-12-31 (1)
+U4795	anonymous	2008-12-31 (1)
+U4CB1	anonymous	2008-12-31 (1)
+U3572	anonymous	2008-12-31 (1)
+U47DF	anonymous	2008-12-31 (1)
+U47DF	anonymous	2008-12-31 (2)
+U3B88	anonymous	2008-12-31 (1)
+U4A47	anonymous	2008-12-31 (1)
+U467A	anonymous	2008-12-31 (1)
+U34CE	anonymous	2008-12-31 (1)
+U3595	anonymous	2008-12-31 (1)
+U3E57	anonymous	2008-12-31 (1)
+U98B7	anonymous	2008-12-31 (1)
+U3BDC	anonymous	2008-12-31 (1)
+U3BDD	anonymous	2008-12-31 (1)
+U40BA	anonymous	2008-12-31 (1)
+U40BB	anonymous	2008-12-31 (1)
+U52DA	loach	2008-12-31 (1)
+U40BC	anonymous	2008-12-31 (1)
+U95DD	anonymous	2008-12-31 (1)
+U7BA3	loach	2008-12-31 (1)
+U4981	anonymous	2008-12-31 (1)
+U4982	anonymous	2008-12-31 (1)
+U4983	anonymous	2008-12-31 (1)
+U808E	FangQ	2008-12-31 (1)
+U9E16	loach	2008-12-31 (1)
+U8088	FangQ	2008-12-31 (1)
+U807B	FangQ	2008-12-31 (1)
+U913C	FangQ	2008-12-31 (1)
+U908E	FangQ	2008-12-31 (1)
+U4BAB	anonymous	2008-12-31 (1)
+U3940	anonymous	2008-12-31 (1)
+U3942	anonymous	2008-12-31 (1)
+U43ED	anonymous	2008-12-31 (1)
+U43EF	anonymous	2008-12-31 (1)
+U3EB4	anonymous	2008-12-31 (1)
+U474D	anonymous	2008-12-31 (1)
+U45A8	anonymous	2008-12-31 (1)
+U4B80	anonymous	2008-12-31 (1)
+U3437	anonymous	2008-12-31 (1)
+U462D	anonymous	2008-12-31 (1)
+U443A	anonymous	2008-12-31 (1)
+U3749	anonymous	2008-12-31 (1)
+U38CD	anonymous	2008-12-31 (1)
+U38CC	anonymous	2008-12-31 (1)
+U34C7	anonymous	2008-12-31 (1)
+U34C8	anonymous	2008-12-31 (1)
+U34C9	anonymous	2008-12-31 (1)
+U410D	anonymous	2008-12-31 (1)
+U38C2	anonymous	2008-12-31 (1)
+U40A9	anonymous	2008-12-31 (1)
+U345A	anonymous	2008-12-31 (1)
+U40AA	anonymous	2008-12-31 (1)
+U40AB	anonymous	2008-12-31 (1)
+U36B9	anonymous	2008-12-31 (1)
+U36B8	anonymous	2008-12-31 (1)
+U3635	anonymous	2008-12-31 (1)
+U4133	anonymous	2008-12-31 (1)
+U4134	anonymous	2008-12-31 (1)
+U4337	anonymous	2008-12-31 (1)
+U45A4	anonymous	2008-12-31 (1)
+U4134	anonymous	2008-12-31 (2)
+U4BC8	anonymous	2008-12-31 (1)
+U45A7	anonymous	2008-12-31 (1)
+U4BC9	anonymous	2008-12-31 (1)
+U4BCA	anonymous	2008-12-31 (1)
+U712B	anonymous	2008-12-31 (1)
+U45A6	anonymous	2008-12-31 (1)
+U3EC7	anonymous	2008-12-31 (1)
+U3EC8	anonymous	2008-12-31 (1)
+U4167	anonymous	2008-12-31 (1)
+U43F8	anonymous	2008-12-31 (1)
+U43F7	anonymous	2008-12-31 (1)
+U43F6	anonymous	2008-12-31 (1)
+U3EC9	anonymous	2008-12-31 (1)
+U3C20	anonymous	2008-12-31 (1)
+U4810	anonymous	2008-12-31 (1)
+U35BA	anonymous	2008-12-31 (1)
+U3716	anonymous	2008-12-31 (1)
+U3657	anonymous	2008-12-31 (1)
+U3717	anonymous	2008-12-31 (1)
+U37F1	anonymous	2008-12-31 (1)
+U3715	anonymous	2008-12-31 (1)
+U3A36	anonymous	2008-12-31 (1)
+U3A37	anonymous	2008-12-31 (1)
+U4041	anonymous	2008-12-31 (1)
+U46E6	anonymous	2008-12-31 (1)
+U4B23	anonymous	2008-12-31 (1)
+U46E7	anonymous	2008-12-31 (1)
+U46E8	anonymous	2008-12-31 (1)
+U470D	anonymous	2008-12-31 (1)
+U470E	anonymous	2008-12-31 (1)
+U38C0	anonymous	2008-12-31 (1)
+U45F2	anonymous	2008-12-31 (1)
+U38C1	anonymous	2008-12-31 (1)
+U45F2	anonymous	2008-12-31 (2)
+U402B	anonymous	2008-12-31 (1)
+U402C	anonymous	2008-12-31 (1)
+U45F1	anonymous	2008-12-31 (1)
+U3597	anonymous	2008-12-31 (1)
+U46BE	anonymous	2008-12-31 (1)
+U3DD2	anonymous	2008-12-31 (1)
+U428F	anonymous	2008-12-31 (1)
+U4290	anonymous	2008-12-31 (1)
+U4D91	anonymous	2008-12-31 (1)
+U4317	anonymous	2008-12-31 (1)
+U4291	anonymous	2008-12-31 (1)
+U4319	anonymous	2008-12-31 (1)
+U4D93	anonymous	2008-12-31 (1)
+U4648	anonymous	2008-12-31 (1)
+U4649	anonymous	2008-12-31 (1)
+U4A3F	anonymous	2008-12-31 (1)
+U390B	anonymous	2008-12-31 (1)
+U3815	anonymous	2008-12-31 (1)
+U464A	anonymous	2008-12-31 (1)
+U4722	anonymous	2008-12-31 (1)
+U40D6	anonymous	2008-12-31 (1)
+U3654	anonymous	2008-12-31 (1)
+U3499	anonymous	2008-12-31 (1)
+U3655	anonymous	2008-12-31 (1)
+U4372	anonymous	2008-12-31 (1)
+U495E	anonymous	2008-12-31 (1)
+U40A2	anonymous	2008-12-31 (1)
+U3D0B	anonymous	2008-12-31 (1)
+U4B7A	anonymous	2008-12-31 (1)
+U4D9A	anonymous	2008-12-31 (1)
+U343B	anonymous	2008-12-31 (1)
+U6102	anonymous	2008-12-31 (1)
+U475C	anonymous	2008-12-31 (1)
+U475D	anonymous	2008-12-31 (1)
+U3A0D	anonymous	2008-12-31 (1)
+U38E2	anonymous	2008-12-31 (1)
+U343C	anonymous	2008-12-31 (1)
+U475E	anonymous	2008-12-31 (1)
+U38A9	anonymous	2008-12-31 (1)
+U38AB	anonymous	2008-12-31 (1)
+U3AF8	anonymous	2008-12-31 (1)
+U3F28	anonymous	2008-12-31 (1)
+U5710	anonymous	2008-12-31 (1)
+U3F29	anonymous	2008-12-31 (1)
+U34ED	anonymous	2008-12-31 (1)
+U3B92	anonymous	2008-12-31 (1)
+U36EC	anonymous	2008-12-31 (1)
+U3B94	anonymous	2008-12-31 (1)
+U36ED	anonymous	2008-12-31 (1)
+U3658	anonymous	2008-12-31 (1)
+U4A52	anonymous	2008-12-31 (1)
+U8818	anonymous	2008-12-31 (1)
+U3A42	anonymous	2008-12-31 (1)
+U3943	anonymous	2008-12-31 (1)
+U3944	anonymous	2008-12-31 (1)
+U3945	anonymous	2008-12-31 (1)
+U3844	anonymous	2008-12-31 (1)
+U42BD	anonymous	2008-12-31 (1)
+U3F64	anonymous	2008-12-31 (1)
+U3845	anonymous	2008-12-31 (1)
+U3846	anonymous	2008-12-31 (1)
+U9731	anonymous	2008-12-31 (1)
+U42BE	anonymous	2008-12-31 (1)
+U42BF	anonymous	2008-12-31 (1)
+U413D	anonymous	2008-12-31 (1)
+U413E	anonymous	2008-12-31 (1)
+U3F65	anonymous	2008-12-31 (1)
+U3701	anonymous	2008-12-31 (1)
+U413F	anonymous	2008-12-31 (1)
+U589B	anonymous	2008-12-31 (1)
+U3E43	anonymous	2008-12-31 (1)
+U448A	anonymous	2008-12-31 (1)
+U3E29	anonymous	2008-12-31 (1)
+U3C27	anonymous	2008-12-31 (1)
+U3E7C	anonymous	2008-12-31 (1)
+U3E7D	anonymous	2008-12-31 (1)
+U448B	anonymous	2008-12-31 (1)
+U41E4	anonymous	2008-12-31 (1)
+U3C28	anonymous	2008-12-31 (1)
+U9736	anonymous	2008-12-31 (1)
+U4667	anonymous	2008-12-31 (1)
+U4669	anonymous	2008-12-31 (1)
+U448C	anonymous	2008-12-31 (1)
+U46DB	anonymous	2008-12-31 (1)
+U465C	anonymous	2008-12-31 (1)
+U4092	anonymous	2008-12-31 (1)
+U643C	anonymous	2008-12-31 (1)
+U465E	anonymous	2008-12-31 (1)
+U476D	anonymous	2008-12-31 (1)
+U9FA3	emittime	2008-12-31 (1)
+U476E	anonymous	2008-12-31 (1)
+U34D3	anonymous	2008-12-31 (1)
+U476F	anonymous	2008-12-31 (1)
+U40EA	anonymous	2008-12-31 (1)
+U34D4	anonymous	2008-12-31 (1)
+U9E18	anonymous	2008-12-31 (1)
+U36CE	anonymous	2008-12-31 (1)
+U34D5	anonymous	2008-12-31 (1)
+U43DC	anonymous	2008-12-31 (1)
+U4C32	anonymous	2008-12-31 (1)
+U43DE	anonymous	2008-12-31 (1)
+U49A4	anonymous	2008-12-31 (1)
+U3650	anonymous	2008-12-31 (1)
+U364F	anonymous	2008-12-31 (1)
+U3AB4	anonymous	2008-12-31 (1)
+U53C6	anonymous	2008-12-31 (1)
+U9E18	emittime	2008-12-31 (2)
+U43A8	anonymous	2008-12-31 (1)
+U3AB5	anonymous	2008-12-31 (1)
+U4816	anonymous	2008-12-31 (1)
+U49A5	anonymous	2008-12-31 (1)
+U53C7	anonymous	2008-12-31 (1)
+U43A9	anonymous	2008-12-31 (1)
+U365E	anonymous	2008-12-31 (1)
+U365F	anonymous	2008-12-31 (1)
+U43AA	anonymous	2008-12-31 (1)
+U49A6	anonymous	2008-12-31 (1)
+U4034	anonymous	2008-12-31 (1)
+U4023	anonymous	2008-12-31 (1)
+U4035	anonymous	2008-12-31 (1)
+U4103	anonymous	2008-12-31 (1)
+U56B1	emittime	2008-12-31 (1)
+U42B9	anonymous	2008-12-31 (1)
+U4104	anonymous	2008-12-31 (1)
+U358F	anonymous	2008-12-31 (1)
+U42BB	anonymous	2008-12-31 (1)
+U4025	anonymous	2008-12-31 (1)
+U3925	anonymous	2008-12-31 (1)
+U702D	anonymous	2008-12-31 (1)
+U4642	anonymous	2008-12-31 (1)
+U46B5	anonymous	2008-12-31 (1)
+U3831	anonymous	2008-12-31 (1)
+U37D8	anonymous	2008-12-31 (1)
+U4644	anonymous	2008-12-31 (1)
+U3660	anonymous	2008-12-31 (1)
+U4643	anonymous	2008-12-31 (1)
+U3F61	anonymous	2008-12-31 (1)
+U87CD	anonymous	2008-12-31 (1)
+U3E88	anonymous	2008-12-31 (1)
+U3F62	anonymous	2008-12-31 (1)
+U3832	anonymous	2008-12-31 (1)
+U6561	emittime	2008-12-31 (1)
+U3F63	anonymous	2008-12-31 (1)
+U474A	anonymous	2008-12-31 (1)
+U34AF	anonymous	2008-12-31 (1)
+U474B	anonymous	2008-12-31 (1)
+U4AB0	anonymous	2009-1-1 (1)
+U474C	anonymous	2009-1-1 (1)
+U3833	anonymous	2009-1-1 (1)
+U3571	anonymous	2009-1-1 (1)
+U4AB1	anonymous	2009-1-1 (1)
+U491A	anonymous	2009-1-1 (1)
+U3573	anonymous	2009-1-1 (1)
+U4AAF	anonymous	2009-1-1 (1)
+U35F6	anonymous	2009-1-1 (1)
+U38B0	anonymous	2009-1-1 (1)
+U3B08	anonymous	2009-1-1 (1)
+U3BA0	anonymous	2009-1-1 (1)
+U3B07	anonymous	2009-1-1 (1)
+U3B06	anonymous	2009-1-1 (1)
+U34B0	anonymous	2009-1-1 (1)
+U43CE	anonymous	2009-1-1 (1)
+U3BA2	anonymous	2009-1-1 (1)
+U43CF	anonymous	2009-1-1 (1)
+U4145	anonymous	2009-1-1 (1)
+U374D	anonymous	2009-1-1 (1)
+U374F	anonymous	2009-1-1 (1)
+U4144	anonymous	2009-1-1 (1)
+U973C	emittime	2009-1-1 (1)
+U4146	anonymous	2009-1-1 (1)
+U3C3C	anonymous	2009-1-1 (1)
+U453F	anonymous	2009-1-1 (1)
+U4938	anonymous	2009-1-1 (1)
+U9741	emittime	2009-1-1 (1)
+U4540	anonymous	2009-1-1 (1)
+U8860	anonymous	2009-1-1 (1)
+U3C3D	anonymous	2009-1-1 (1)
+U4937	anonymous	2009-1-1 (1)
+U38A3	anonymous	2009-1-1 (1)
+U373F	anonymous	2009-1-1 (1)
+U3699	anonymous	2009-1-1 (1)
+U4541	anonymous	2009-1-1 (1)
+U3C3E	anonymous	2009-1-1 (1)
+U4790	anonymous	2009-1-1 (1)
+U4B7E	anonymous	2009-1-1 (1)
+U3743	anonymous	2009-1-1 (1)
+U403B	anonymous	2009-1-1 (1)
+U3744	anonymous	2009-1-1 (1)
+U4830	anonymous	2009-1-1 (1)
+U3740	anonymous	2009-1-1 (1)
+U45AA	anonymous	2009-1-1 (1)
+U482E	anonymous	2009-1-1 (1)
+U441D	anonymous	2009-1-1 (1)
+U3E8B	anonymous	2009-1-1 (1)
+U441E	anonymous	2009-1-1 (1)
+U3C67	anonymous	2009-1-1 (1)
+U441F	anonymous	2009-1-1 (1)
+U3C2D	anonymous	2009-1-1 (1)
+U4604	anonymous	2009-1-1 (1)
+U3C2C	anonymous	2009-1-1 (1)
+U41A5	anonymous	2009-1-1 (1)
+U3C2B	anonymous	2009-1-1 (1)
+U4246	anonymous	2009-1-1 (1)
+U3BFF	anonymous	2009-1-1 (1)
+U91BF	anonymous	2009-1-1 (1)
+U3CCF	anonymous	2009-1-1 (1)
+U37CF	anonymous	2009-1-1 (1)
+U4D98	anonymous	2009-1-1 (1)
+U37D0	anonymous	2009-1-1 (1)
+U37D1	anonymous	2009-1-1 (1)
+U41F6	anonymous	2009-1-1 (1)
+U3C32	anonymous	2009-1-1 (1)
+U9113	anonymous	2009-1-1 (1)
+U46CF	anonymous	2009-1-1 (1)
+U46D1	anonymous	2009-1-1 (1)
+U3F27	anonymous	2009-1-1 (1)
+U4B26	anonymous	2009-1-1 (1)
+U3F26	anonymous	2009-1-1 (1)
+U36B2	anonymous	2009-1-1 (1)
+U3EBD	anonymous	2009-1-1 (1)
+U36B4	anonymous	2009-1-1 (1)
+U3855	anonymous	2009-1-1 (1)
+U3EBB	anonymous	2009-1-1 (1)
+U3856	anonymous	2009-1-1 (1)
+U37EB	anonymous	2009-1-1 (1)
+U3D4F	anonymous	2009-1-1 (1)
+U3D50	anonymous	2009-1-1 (1)
+U358A	anonymous	2009-1-1 (1)
+U444F	anonymous	2009-1-1 (1)
+U48F6	anonymous	2009-1-1 (1)
+U48F5	anonymous	2009-1-1 (1)
+U34A4	anonymous	2009-1-1 (1)
+U4C8E	anonymous	2009-1-1 (1)
+U4079	anonymous	2009-1-1 (1)
+U407A	anonymous	2009-1-1 (1)
+U45D6	anonymous	2009-1-1 (1)
+U3D54	anonymous	2009-1-1 (1)
+U4623	anonymous	2009-1-1 (1)
+U38EC	anonymous	2009-1-1 (1)
+U698C	anonymous	2009-1-1 (1)
+U45F3	anonymous	2009-1-1 (1)
+U3DA0	anonymous	2009-1-1 (1)
+U4900	anonymous	2009-1-1 (1)
+U4297	anonymous	2009-1-1 (1)
+U3DA2	anonymous	2009-1-1 (1)
+U4626	anonymous	2009-1-1 (1)
+U5268	anonymous	2009-1-1 (1)
+U373A	anonymous	2009-1-1 (1)
+U415C	anonymous	2009-1-1 (1)
+U415E	anonymous	2009-1-1 (1)
+U3962	anonymous	2009-1-1 (1)
+U3432	anonymous	2009-1-1 (1)
+U393F	anonymous	2009-1-1 (1)
+U7D25	anonymous	2009-1-1 (1)
+U37DD	anonymous	2009-1-1 (1)
+U4682	anonymous	2009-1-1 (1)
+U4494	extc	2009-1-1 (1)
+U4684	anonymous	2009-1-1 (1)
+U9745	anonymous	2009-1-1 (1)
+U4124	anonymous	2009-1-1 (1)
+U46DE	anonymous	2009-1-1 (1)
+U48DA	anonymous	2009-1-1 (1)
+U44A7	anonymous	2009-1-1 (1)
+U48DB	anonymous	2009-1-1 (1)
+U6552	anonymous	2009-1-1 (1)
+U46E0	anonymous	2009-1-1 (1)
+U47DD	anonymous	2009-1-1 (1)
+U47DC	anonymous	2009-1-1 (1)
+U44A6	anonymous	2009-1-1 (1)
+U36E9	anonymous	2009-1-1 (1)
+U36E8	anonymous	2009-1-1 (1)
+U4913	anonymous	2009-1-1 (1)
+U6B6E	anonymous	2009-1-1 (1)
+U36E7	anonymous	2009-1-1 (1)
+U4918	anonymous	2009-1-1 (1)
+U3ECB	anonymous	2009-1-1 (1)
+U3ECC	anonymous	2009-1-1 (1)
+U4919	anonymous	2009-1-1 (1)
+U4174	anonymous	2009-1-1 (1)
+U4172	anonymous	2009-1-1 (1)
+U44B0	anonymous	2009-1-1 (1)
+U48CB	anonymous	2009-1-1 (1)
+U48CC	anonymous	2009-1-1 (1)
+U42D6	anonymous	2009-1-1 (1)
+U344D	anonymous	2009-1-1 (1)
+U42D5	anonymous	2009-1-1 (1)
+U48C6	anonymous	2009-1-1 (1)
+U3913	anonymous	2009-1-1 (1)
+U48C7	anonymous	2009-1-1 (1)
+U3914	anonymous	2009-1-1 (1)
+U4A64	anonymous	2009-1-1 (1)
+U467C	anonymous	2009-1-1 (1)
+U3E58	anonymous	2009-1-1 (1)
+U467B	anonymous	2009-1-1 (1)
+U3A31	anonymous	2009-1-1 (1)
+U39EF	anonymous	2009-1-1 (1)
+U39F0	anonymous	2009-1-1 (1)
+U3F96	anonymous	2009-1-1 (1)
+U3A33	anonymous	2009-1-1 (1)
+U35EB	anonymous	2009-1-1 (1)
+U4158	anonymous	2009-1-1 (1)
+U4C04	anonymous	2009-1-1 (1)
+U4159	anonymous	2009-1-1 (1)
+U43D9	anonymous	2009-1-1 (1)
+U415A	anonymous	2009-1-1 (1)
+U40B8	anonymous	2009-1-1 (1)
+U4C06	anonymous	2009-1-1 (1)
+U3AB1	anonymous	2009-1-1 (1)
+U43DA	anonymous	2009-1-1 (1)
+U41CE	anonymous	2009-1-1 (1)
+U44E1	anonymous	2009-1-1 (1)
+U40CC	anonymous	2009-1-1 (1)
+U40CD	anonymous	2009-1-1 (1)
+U43DB	anonymous	2009-1-1 (1)
+U3B00	anonymous	2009-1-1 (1)
+U3555	anonymous	2009-1-1 (1)
+U4CDC	anonymous	2009-1-1 (1)
+U3CE7	anonymous	2009-1-1 (1)
+U3554	anonymous	2009-1-1 (1)
+U4CDD	anonymous	2009-1-1 (1)
+U3918	anonymous	2009-1-1 (1)
+U345F	anonymous	2009-1-1 (1)
+U34CA	anonymous	2009-1-1 (1)
+U4A54	anonymous	2009-1-1 (1)
+U37CE	anonymous	2009-1-1 (1)
+U3556	anonymous	2009-1-1 (1)
+U363C	anonymous	2009-1-1 (1)
+U4A55	anonymous	2009-1-1 (1)
+U3ADF	anonymous	2009-1-1 (1)
+U4A56	anonymous	2009-1-1 (1)
+U3ADD	anonymous	2009-1-1 (1)
+U4BAF	anonymous	2009-1-1 (1)
+U3B28	anonymous	2009-1-1 (1)
+U45F7	anonymous	2009-1-1 (1)
+U4BB0	anonymous	2009-1-1 (1)
+U4056	anonymous	2009-1-1 (1)
+U4058	anonymous	2009-1-1 (1)
+U4697	anonymous	2009-1-1 (1)
+U415B	anonymous	2009-1-1 (1)
+U35FB	anonymous	2009-1-1 (1)
+U4CEF	anonymous	2009-1-1 (1)
+U4116	anonymous	2009-1-1 (1)
+U4117	anonymous	2009-1-1 (1)
+U4118	anonymous	2009-1-1 (1)
+U45D8	anonymous	2009-1-1 (1)
+U35FC	anonymous	2009-1-1 (1)
+U40DF	anonymous	2009-1-1 (1)
+U40E0	anonymous	2009-1-1 (1)
+U4762	anonymous	2009-1-1 (1)
+U4071	anonymous	2009-1-1 (1)
+U484C	anonymous	2009-1-1 (1)
+U484E	anonymous	2009-1-1 (1)
+U484D	anonymous	2009-1-1 (1)
+U4764	anonymous	2009-1-1 (1)
+U4751	anonymous	2009-1-1 (1)
+U4150	anonymous	2009-1-1 (1)
+U3D36	anonymous	2009-1-1 (1)
+U39D1	anonymous	2009-1-1 (1)
+U3E32	anonymous	2009-1-1 (1)
+U3EA9	anonymous	2009-1-1 (1)
+U3EA8	anonymous	2009-1-1 (1)
+U3A04	anonymous	2009-1-1 (1)
+U39D3	anonymous	2009-1-1 (1)
+U4163	anonymous	2009-1-1 (1)
+U3E98	anonymous	2009-1-1 (1)
+U4791	anonymous	2009-1-1 (1)
+U4A60	anonymous	2009-1-1 (1)
+U3E3C	anonymous	2009-1-1 (1)
+U4A61	anonymous	2009-1-1 (1)
+U461B	anonymous	2009-1-1 (1)
+U4A62	anonymous	2009-1-1 (1)
+U356A	anonymous	2009-1-1 (1)
+U3EAD	anonymous	2009-1-1 (1)
+U4371	anonymous	2009-1-1 (1)
+U4373	anonymous	2009-1-1 (1)
+U34D6	anonymous	2009-1-1 (1)
+U37C4	anonymous	2009-1-1 (1)
+U45AC	anonymous	2009-1-1 (1)
+U37C6	anonymous	2009-1-1 (1)
+U3A9B	anonymous	2009-1-1 (1)
+U3A9C	anonymous	2009-1-1 (1)
+U476B	anonymous	2009-1-1 (1)
+U3A9D	anonymous	2009-1-1 (1)
+U476C	anonymous	2009-1-1 (1)
+U3B0F	anonymous	2009-1-1 (1)
+U49FD	anonymous	2009-1-1 (1)
+U9EF1	anonymous	2009-1-1 (1)
+U5959	anonymous	2009-1-1 (1)
+U49FB	anonymous	2009-1-1 (1)
+U383D	anonymous	2009-1-1 (1)
+U34CC	anonymous	2009-1-1 (1)
+U49FC	anonymous	2009-1-1 (1)
+U383E	anonymous	2009-1-1 (1)
+U383F	anonymous	2009-1-1 (1)
+U4126	anonymous	2009-1-1 (1)
+U34CD	anonymous	2009-1-1 (1)
+U4127	anonymous	2009-1-1 (1)
+U45C5	anonymous	2009-1-1 (1)
+U3E02	anonymous	2009-1-1 (1)
+U45C6	anonymous	2009-1-1 (1)
+U394C	anonymous	2009-1-1 (1)
+U4136	anonymous	2009-1-1 (1)
+U4137	anonymous	2009-1-1 (1)
+U3FF8	anonymous	2009-1-1 (1)
+U4138	anonymous	2009-1-1 (1)
+U4D37	anonymous	2009-1-1 (1)
+U4C70	anonymous	2009-1-1 (1)
+U404B	anonymous	2009-1-1 (1)
+U404D	anonymous	2009-1-1 (1)
+U49CA	anonymous	2009-1-1 (1)
+U404C	anonymous	2009-1-1 (1)
+U46F0	anonymous	2009-1-1 (1)
+U4712	anonymous	2009-1-1 (1)
+U390D	anonymous	2009-1-1 (1)
+U46F2	anonymous	2009-1-1 (1)
+U3BD1	anonymous	2009-1-1 (1)
+U46F1	anonymous	2009-1-1 (1)
+U41E5	anonymous	2009-1-1 (1)
+U3BD2	anonymous	2009-1-1 (1)
+U46B2	anonymous	2009-1-1 (1)
+U4123	anonymous	2009-1-1 (1)
+U46B3	anonymous	2009-1-1 (1)
+U4125	anonymous	2009-1-1 (1)
+U4333	anonymous	2009-1-1 (1)
+U46B4	anonymous	2009-1-1 (1)
+U3CC5	anonymous	2009-1-1 (1)
+U3CC6	anonymous	2009-1-1 (1)
+U3949	anonymous	2009-1-1 (1)
+U394A	anonymous	2009-1-1 (1)
+U413B	anonymous	2009-1-1 (1)
+U4633	anonymous	2009-1-1 (1)
+U4716	anonymous	2009-1-1 (1)
+U413A	anonymous	2009-1-1 (1)
+U3A89	anonymous	2009-1-1 (1)
+U4717	anonymous	2009-1-1 (1)
+U4184	anonymous	2009-1-1 (1)
+U4C6C	anonymous	2009-1-1 (1)
+U4186	anonymous	2009-1-1 (1)
+U3A8A	anonymous	2009-1-1 (1)
+U45D4	anonymous	2009-1-1 (1)
+U373E	anonymous	2009-1-1 (1)
+U3A8B	anonymous	2009-1-1 (1)
+U443C	anonymous	2009-1-1 (1)
+U392C	anonymous	2009-1-1 (1)
+U3F93	anonymous	2009-1-1 (1)
+U3DE7	anonymous	2009-1-1 (1)
+U392D	anonymous	2009-1-1 (1)
+U3F94	anonymous	2009-1-1 (1)
+U35C4	anonymous	2009-1-1 (1)
+U3839	anonymous	2009-1-1 (1)
+U376B	anonymous	2009-1-1 (1)
+U45B0	anonymous	2009-1-1 (1)
+U383A	anonymous	2009-1-1 (1)
+U45B1	anonymous	2009-1-1 (1)
+U3F95	anonymous	2009-1-1 (1)
+U45B2	anonymous	2009-1-1 (1)
+U470F	anonymous	2009-1-1 (1)
+U3CEF	anonymous	2009-1-1 (1)
+U422C	anonymous	2009-1-1 (1)
+U3724	anonymous	2009-1-1 (1)
+U344C	anonymous	2009-1-1 (1)
+U3725	anonymous	2009-1-1 (1)
+U38D6	anonymous	2009-1-1 (1)
+U38D7	anonymous	2009-1-1 (1)
+U404F	anonymous	2009-1-1 (1)
+U4051	anonymous	2009-1-1 (1)
+U422D	anonymous	2009-1-1 (1)
+U38D8	anonymous	2009-1-1 (1)
+U45DB	anonymous	2009-1-1 (1)
+U45DA	anonymous	2009-1-1 (1)
+U37F7	anonymous	2009-1-1 (1)
+U37BE	anonymous	2009-1-1 (1)
+U397A	anonymous	2009-1-1 (1)
+U4B8F	anonymous	2009-1-1 (1)
+U43B6	anonymous	2009-1-1 (1)
+U43B7	anonymous	2009-1-1 (1)
+U43B8	anonymous	2009-1-1 (1)
+U4400	anonymous	2009-1-1 (1)
+U4401	anonymous	2009-1-1 (1)
+U4472	anonymous	2009-1-1 (1)
+U46F7	anonymous	2009-1-1 (1)
+U4402	anonymous	2009-1-1 (1)
+U4B91	anonymous	2009-1-1 (1)
+U4473	anonymous	2009-1-1 (1)
+U4473	anonymous	2009-1-1 (2)
+U4495	anonymous	2009-1-1 (1)
+U4474	anonymous	2009-1-1 (1)
+U4474	anonymous	2009-1-1 (2)
+U3E74	anonymous	2009-1-1 (1)
+U4A5F	anonymous	2009-1-1 (1)
+U3E73	anonymous	2009-1-1 (1)
+U3E72	anonymous	2009-1-1 (1)
+U46F5	anonymous	2009-1-1 (1)
+U3FD2	anonymous	2009-1-1 (1)
+U3E72	anonymous	2009-1-1 (2)
+U4745	anonymous	2009-1-1 (1)
+U42EE	anonymous	2009-1-1 (1)
+U3B34	anonymous	2009-1-1 (1)
+U4880	anonymous	2009-1-1 (1)
+U3B35	anonymous	2009-1-1 (1)
+U4881	anonymous	2009-1-1 (1)
+U484F	anonymous	2009-1-1 (1)
+U3B36	anonymous	2009-1-1 (1)
+U46F8	anonymous	2009-1-1 (1)
+U4027	anonymous	2009-1-1 (1)
+U46F9	anonymous	2009-1-1 (1)
+U42D9	anonymous	2009-1-1 (1)
+U3DC6	anonymous	2009-1-1 (1)
+U34E4	anonymous	2009-1-1 (1)
+U34E2	anonymous	2009-1-1 (1)
+U4213	anonymous	2009-1-1 (1)
+U34E3	anonymous	2009-1-1 (1)
+U3906	anonymous	2009-1-1 (1)
+U3613	anonymous	2009-1-1 (1)
+U61A6	anonymous	2009-1-1 (1)
+U3965	anonymous	2009-1-1 (1)
+U61C0	anonymous	2009-1-1 (1)
+U345B	anonymous	2009-1-1 (1)
+U40E9	anonymous	2009-1-1 (1)
+U4A22	anonymous	2009-1-1 (1)
+U345C	anonymous	2009-1-1 (1)
+U6AB5	anonymous	2009-1-1 (1)
+U3B91	anonymous	2009-1-1 (1)
+U39E2	anonymous	2009-1-1 (1)
+U4014	anonymous	2009-1-1 (1)
+U39E1	anonymous	2009-1-1 (1)
+U4015	anonymous	2009-1-1 (1)
+U4D05	anonymous	2009-1-1 (1)
+U9737	anonymous	2009-1-1 (1)
+U4D06	anonymous	2009-1-1 (1)
+U39BB	anonymous	2009-1-1 (1)
+U38C3	anonymous	2009-1-1 (1)
+U7225	anonymous	2009-1-1 (1)
+U3726	anonymous	2009-1-1 (1)
+U4641	anonymous	2009-1-1 (1)
+U3564	anonymous	2009-1-1 (1)
+U408B	anonymous	2009-1-1 (1)
+U5E32	anonymous	2009-1-1 (1)
+U3E6E	anonymous	2009-1-1 (1)
+U3BB3	anonymous	2009-1-1 (1)
+U3E6F	anonymous	2009-1-1 (1)
+U3E70	anonymous	2009-1-1 (1)
+U486F	anonymous	2009-1-1 (1)
+U4307	anonymous	2009-1-1 (1)
+U4067	anonymous	2009-1-1 (1)
+U380C	anonymous	2009-1-1 (1)
+U4308	anonymous	2009-1-1 (1)
+U380A	anonymous	2009-1-1 (1)
+U47DE	anonymous	2009-1-1 (1)
+U4879	anonymous	2009-1-1 (1)
+U35AB	anonymous	2009-1-1 (1)
+U35A9	anonymous	2009-1-1 (1)
+U3838	anonymous	2009-1-1 (1)
+U4305	anonymous	2009-1-1 (1)
+U3E6A	anonymous	2009-1-1 (1)
+U4760	anonymous	2009-1-1 (1)
+U4306	anonymous	2009-1-1 (1)
+U3617	anonymous	2009-1-1 (1)
+U4775	anonymous	2009-1-1 (1)
+U4C4F	anonymous	2009-1-1 (1)
+U4154	anonymous	2009-1-1 (1)
+U4155	anonymous	2009-1-1 (1)
+U4156	anonymous	2009-1-1 (1)
+U3DDA	anonymous	2009-1-1 (1)
+U4C4E	anonymous	2009-1-1 (1)
+U3ECA	anonymous	2009-1-1 (1)
+U3DDC	anonymous	2009-1-1 (1)
+U4107	anonymous	2009-1-1 (1)
+U3B5B	anonymous	2009-1-1 (1)
+U45E1	anonymous	2009-1-1 (1)
+U4108	anonymous	2009-1-1 (1)
+U461E	anonymous	2009-1-1 (1)
+U3B5C	anonymous	2009-1-1 (1)
+U414C	anonymous	2009-1-1 (1)
+U3592	anonymous	2009-1-1 (1)
+U37B4	anonymous	2009-1-1 (1)
+U39E7	anonymous	2009-1-1 (1)
+U3B9E	anonymous	2009-1-1 (1)
+U37B6	anonymous	2009-1-1 (1)
+U39E8	anonymous	2009-1-1 (1)
+U4344	anonymous	2009-1-1 (1)
+U39E9	anonymous	2009-1-1 (1)
+U34D7	anonymous	2009-1-1 (1)
+U3970	anonymous	2009-1-1 (1)
+U4A63	anonymous	2009-1-1 (1)
+U3852	anonymous	2009-1-1 (1)
+U39FF	anonymous	2009-1-1 (1)
+U3A01	anonymous	2009-1-1 (1)
+U3971	anonymous	2009-1-1 (1)
+U346E	anonymous	2009-1-1 (1)
+U3ED5	anonymous	2009-1-1 (1)
+U3470	anonymous	2009-1-1 (1)
+U3A20	anonymous	2009-1-1 (1)
+U3EE9	anonymous	2009-1-1 (1)
+U3969	anonymous	2009-1-1 (1)
+U39A8	anonymous	2009-1-1 (1)
+U3DEE	anonymous	2009-1-1 (1)
+U4CCF	anonymous	2009-1-1 (1)
+U3B44	anonymous	2009-1-1 (1)
+U3B6A	anonymous	2009-1-1 (1)
+U3B6B	anonymous	2009-1-1 (1)
+U4CD0	anonymous	2009-1-1 (1)
+U4CD1	anonymous	2009-1-1 (1)
+U4CD1	anonymous	2009-1-1 (2)
+U36CC	anonymous	2009-1-1 (1)
+U36CD	anonymous	2009-1-1 (1)
+U406A	anonymous	2009-1-1 (1)
+U3AF0	anonymous	2009-1-1 (1)
+U42B6	anonymous	2009-1-1 (1)
+U42B7	anonymous	2009-1-1 (1)
+U4BD7	anonymous	2009-1-1 (1)
+U4BD8	anonymous	2009-1-1 (1)
+U42B8	anonymous	2009-1-1 (1)
+U4BD9	anonymous	2009-1-1 (1)
+U4B9A	anonymous	2009-1-1 (1)
+U471D	anonymous	2009-1-1 (1)
+U3F42	anonymous	2009-1-1 (1)
+U3F1C	anonymous	2009-1-1 (1)
+U444B	anonymous	2009-1-1 (1)
+U444C	anonymous	2009-1-1 (1)
+U4852	anonymous	2009-1-1 (1)
+U3853	anonymous	2009-1-1 (1)
+U478C	anonymous	2009-1-1 (1)
+U478D	anonymous	2009-1-1 (1)
+U5172	anonymous	2009-1-1 (1)
+U478E	anonymous	2009-1-1 (1)
+U3EF0	anonymous	2009-1-1 (1)
+U3EF0	anonymous	2009-1-1 (2)
+U3E41	anonymous	2009-1-1 (1)
+U3E40	anonymous	2009-1-1 (1)
+U3B83	anonymous	2009-1-1 (1)
+U3EF1	anonymous	2009-1-1 (1)
+U3B81	anonymous	2009-1-1 (1)
+U4C76	anonymous	2009-1-1 (1)
+U47A6	anonymous	2009-1-1 (1)
+U409F	anonymous	2009-1-1 (1)
+U363B	anonymous	2009-1-1 (1)
+U3AD1	anonymous	2009-1-1 (1)
+U37A0	anonymous	2009-1-1 (1)
+U3E34	anonymous	2009-1-1 (1)
+U37A0	anonymous	2009-1-1 (2)
+U3E33	anonymous	2009-1-1 (1)
+U3E35	anonymous	2009-1-1 (1)
+U3DAC	anonymous	2009-1-1 (1)
+U35BC	anonymous	2009-1-1 (1)
+U35BB	anonymous	2009-1-1 (1)
+U3A73	anonymous	2009-1-1 (1)
+U3BD6	anonymous	2009-1-1 (1)
+U3729	anonymous	2009-1-1 (1)
+U43F1	anonymous	2009-1-1 (1)
+U43F2	anonymous	2009-1-1 (1)
+U3A74	anonymous	2009-1-1 (1)
+U676B	anonymous	2009-1-1 (2)
+U676E	anonymous	2009-1-1 (2)
+U3CDB	anonymous	2009-1-1 (1)
+U3416	anonymous	2009-1-1 (1)
+U41C7	anonymous	2009-1-1 (1)
+U3E9C	anonymous	2009-1-1 (1)
+U3E9D	anonymous	2009-1-1 (1)
+U35AA	anonymous	2009-1-1 (1)
+U4CAD	anonymous	2009-1-1 (1)
+U372E	anonymous	2009-1-1 (1)
+U4709	anonymous	2009-1-1 (1)
+U4707	anonymous	2009-1-1 (1)
+U3417	anonymous	2009-1-1 (1)
+U4A70	anonymous	2009-1-1 (1)
+U43D0	anonymous	2009-1-1 (1)
+U4692	anonymous	2009-1-1 (1)
+U4693	anonymous	2009-1-1 (1)
+U3DB1	anonymous	2009-1-1 (1)
+U3DB2	anonymous	2009-1-1 (1)
+U458B	anonymous	2009-1-1 (1)
+U37B3	anonymous	2009-1-1 (1)
+U3A1F	anonymous	2009-1-1 (1)
+U416A	anonymous	2009-1-1 (1)
+U4B39	anonymous	2009-1-1 (1)
+U4B3A	anonymous	2009-1-1 (1)
+U41D1	anonymous	2009-1-1 (1)
+U4B3A	anonymous	2009-1-1 (2)
+U4181	anonymous	2009-1-1 (1)
+U4182	anonymous	2009-1-1 (1)
+U4182	anonymous	2009-1-1 (2)
+U3886	anonymous	2009-1-1 (1)
+U4180	anonymous	2009-1-1 (1)
+U3D39	anonymous	2009-1-1 (1)
+U4CEC	anonymous	2009-1-1 (1)
+U4B50	anonymous	2009-1-1 (1)
+U3C71	anonymous	2009-1-1 (1)
+U4AA7	anonymous	2009-1-1 (1)
+U3C72	anonymous	2009-1-1 (1)
+U490C	anonymous	2009-1-1 (1)
+U3A97	anonymous	2009-1-1 (1)
+U37E0	anonymous	2009-1-1 (1)
+U4CCB	anonymous	2009-1-1 (1)
+U3704	anonymous	2009-1-1 (1)
+U4CCD	anonymous	2009-1-1 (1)
+U4013	anonymous	2009-1-1 (1)
+U3922	anonymous	2009-1-1 (1)
+U40A5	anonymous	2009-1-1 (1)
+U41CB	anonymous	2009-1-1 (1)
+U41C9	anonymous	2009-1-1 (1)
+U405A	anonymous	2009-1-1 (1)
+U3923	anonymous	2009-1-1 (1)
+U4533	anonymous	2009-1-1 (1)
+U4376	anonymous	2009-1-1 (1)
+U4377	anonymous	2009-1-1 (1)
+U4378	anonymous	2009-1-1 (1)
+U3674	anonymous	2009-1-1 (1)
+U4535	anonymous	2009-1-1 (1)
+U3CD4	anonymous	2009-1-1 (1)
+U3CD5	anonymous	2009-1-1 (1)
+U3CD6	anonymous	2009-1-1 (1)
+U37DE	anonymous	2009-1-1 (1)
+U43EC	anonymous	2009-1-1 (1)
+U35AE	anonymous	2009-1-1 (1)
+U42E7	anonymous	2009-1-1 (1)
+U42E8	anonymous	2009-1-1 (1)
+U42E9	anonymous	2009-1-1 (1)
+U48B9	anonymous	2009-1-1 (1)
+U47FB	anonymous	2009-1-1 (1)
+U4CFC	anonymous	2009-1-1 (1)
+U3EDD	anonymous	2009-1-1 (1)
+U402D	anonymous	2009-1-1 (1)
+U37FD	anonymous	2009-1-1 (1)
+U40C1	anonymous	2009-1-1 (1)
+U4467	anonymous	2009-1-1 (1)
+U482B	anonymous	2009-1-1 (1)
+U4464	anonymous	2009-1-1 (1)
+U4465	anonymous	2009-1-1 (1)
+U45BB	anonymous	2009-1-1 (1)
+U45BC	anonymous	2009-1-1 (1)
+U45BD	anonymous	2009-1-1 (1)
+U46C0	anonymous	2009-1-1 (1)
+U46BF	anonymous	2009-1-1 (1)
+U391A	anonymous	2009-1-1 (1)
+U3507	anonymous	2009-1-1 (1)
+U36FC	anonymous	2009-1-1 (1)
+U45A2	anonymous	2009-1-1 (1)
+U45A3	anonymous	2009-1-1 (1)
+U4BE4	anonymous	2009-1-1 (1)
+U4BE3	anonymous	2009-1-1 (1)
+U4140	anonymous	2009-1-1 (1)
+U974A		2009-1-1 (1)
+U372D	anonymous	2009-1-1 (1)
+U3CFB	anonymous	2009-1-1 (1)
+U4099	anonymous	2009-1-1 (1)
+U3CFE	anonymous	2009-1-1 (1)
+U3B6F	anonymous	2009-1-1 (1)
+U4346	anonymous	2009-1-1 (1)
+U3524	anonymous	2009-1-1 (1)
+U3B2C	anonymous	2009-1-1 (1)
+U3523	anonymous	2009-1-1 (1)
+U4C79	anonymous	2009-1-1 (1)
+U4033	anonymous	2009-1-1 (1)
+U390F	anonymous	2009-1-1 (1)
+U4113	anonymous	2009-1-1 (1)
+U4113	anonymous	2009-1-1 (2)
+U4036	anonymous	2009-1-1 (1)
+U4111	anonymous	2009-1-1 (1)
+U5D4F		2009-1-1 (1)
+U3C94	anonymous	2009-1-1 (1)
+U46E5	anonymous	2009-1-1 (1)
+U346B	anonymous	2009-1-1 (1)
+U46EC	anonymous	2009-1-1 (1)
+U47E7	anonymous	2009-1-1 (1)
+U38C9	anonymous	2009-1-1 (1)
+U3915	anonymous	2009-1-1 (1)
+U3916	anonymous	2009-1-1 (1)
+U35BF	anonymous	2009-1-1 (1)
+U4661	anonymous	2009-1-1 (1)
+U3CAC	anonymous	2009-1-1 (1)
+U4662	anonymous	2009-1-1 (1)
+U3952	anonymous	2009-1-1 (1)
+U349B	anonymous	2009-1-1 (1)
+U362C	anonymous	2009-1-1 (1)
+U362B	anonymous	2009-1-1 (1)
+U34E0	anonymous	2009-1-1 (1)
+U48D7	anonymous	2009-1-1 (1)
+U48D7	anonymous	2009-1-1 (2)
+U34E1	anonymous	2009-1-1 (1)
+U47D2	anonymous	2009-1-1 (1)
+U4658	anonymous	2009-1-1 (1)
+U34E5	anonymous	2009-1-1 (1)
+U47D3	anonymous	2009-1-1 (1)
+U47D4	anonymous	2009-1-1 (1)
+U5EBA		2009-1-1 (1)
+U3B76	anonymous	2009-1-1 (1)
+U4B88	anonymous	2009-1-1 (1)
+U4B87	anonymous	2009-1-1 (1)
+U4B89	anonymous	2009-1-1 (1)
+U3A62	anonymous	2009-1-1 (1)
+U4724	anonymous	2009-1-1 (1)
+U3F85	anonymous	2009-1-1 (1)
+U3806	anonymous	2009-1-1 (1)
+U3808	anonymous	2009-1-1 (1)
+U3842	anonymous	2009-1-1 (1)
+U585C		2009-1-1 (1)
+U458E	anonymous	2009-1-1 (1)
+U4C82	anonymous	2009-1-1 (1)
+U56A9	anonymous	2009-1-1 (1)
+U4814	anonymous	2009-1-1 (1)
+U4815	anonymous	2009-1-1 (1)
+U4CAE	anonymous	2009-1-1 (1)
+U4590	anonymous	2009-1-1 (1)
+U4CAC	anonymous	2009-1-1 (1)
+U4427	anonymous	2009-1-1 (1)
+U3B39	anonymous	2009-1-1 (1)
+U4429	anonymous	2009-1-1 (1)
+U7C31		2009-1-1 (1)
+U3587	anonymous	2009-1-1 (1)
+U3AC2	anonymous	2009-1-1 (1)
+U3586	anonymous	2009-1-1 (1)
+U3DF5	anonymous	2009-1-1 (1)
+U7C32		2009-1-1 (1)
+U4469	anonymous	2009-1-1 (1)
+U3EC2	anonymous	2009-1-1 (1)
+U35B7	anonymous	2009-1-1 (1)
+U3AC3	anonymous	2009-1-1 (1)
+U35B8	anonymous	2009-1-1 (1)
+U46F3	anonymous	2009-1-1 (1)
+U3835	anonymous	2009-1-1 (1)
+U46F4	anonymous	2009-1-1 (1)
+U39E3	anonymous	2009-1-1 (1)
+U39E4	anonymous	2009-1-1 (1)
+U4CB9	anonymous	2009-1-1 (1)
+U39E5	anonymous	2009-1-1 (1)
+U4CBA	anonymous	2009-1-1 (1)
+U343E	anonymous	2009-1-1 (1)
+U4CBB	anonymous	2009-1-1 (1)
+U9F05		2009-1-1 (1)
+U3DB8	anonymous	2009-1-1 (1)
+U3DB9	anonymous	2009-1-1 (1)
+U3DC5	anonymous	2009-1-1 (1)
+U4BB7	anonymous	2009-1-1 (1)
+U4B48	anonymous	2009-1-1 (1)
+U9F04		2009-1-1 (1)
+U53B1	anonymous	2009-1-1 (1)
+U3F67	anonymous	2009-1-1 (1)
+U3F68	anonymous	2009-1-1 (1)
+U9F02		2009-1-1 (1)
+U3F0B	emittime	2009-1-1 (1)
+U4A40	anonymous	2009-1-1 (1)
+U434B	emittime	2009-1-1 (1)
+U4488	anonymous	2009-1-1 (1)
+U4489	anonymous	2009-1-1 (1)
+U4A41	anonymous	2009-1-1 (1)
+U6873	anonymous	2009-1-1 (1)
+U434C	emittime	2009-1-1 (1)
+U4A42	anonymous	2009-1-1 (1)
+U4292	emittime	2009-1-1 (1)
+U448D	anonymous	2009-1-1 (1)
+U38BE	anonymous	2009-1-1 (1)
+U3B4B	anonymous	2009-1-1 (1)
+U4293	emittime	2009-1-1 (1)
+U3B4C	anonymous	2009-1-1 (1)
+U42AB	emittime	2009-1-1 (1)
+U371E	anonymous	2009-1-1 (1)
+U68BB	anonymous	2009-1-1 (1)
+U5B3A	anonymous	2009-1-1 (1)
+U38BF	anonymous	2009-1-1 (1)
+U4B82	anonymous	2009-1-1 (1)
+U4B83	anonymous	2009-1-1 (1)
+U42AD	emittime	2009-1-1 (1)
+U371F	anonymous	2009-1-1 (1)
+U4B84	anonymous	2009-1-1 (1)
+U4443	anonymous	2009-1-1 (1)
+U3720	anonymous	2009-1-1 (1)
+U493D	emittime	2009-1-1 (1)
+U4CCC	anonymous	2009-1-1 (1)
+U493E	emittime	2009-1-1 (1)
+U4444	anonymous	2009-1-1 (1)
+U41DE	anonymous	2009-1-1 (1)
+U52EC	anonymous	2009-1-1 (1)
+U3946	anonymous	2009-1-1 (1)
+U3AFB	emittime	2009-1-1 (1)
+U3947	anonymous	2009-1-1 (1)
+U429A	anonymous	2009-1-1 (1)
+U72AB	anonymous	2009-1-1 (1)
+U3948	anonymous	2009-1-1 (1)
+U3948	anonymous	2009-1-1 (2)
+U3AFC	emittime	2009-1-1 (1)
+U49BD	anonymous	2009-1-1 (1)
+U3AFD	emittime	2009-1-1 (1)
+U41E0	anonymous	2009-1-1 (1)
+U49BF	anonymous	2009-1-1 (1)
+U3AE0	anonymous	2009-1-1 (1)
+U4B8C	anonymous	2009-1-1 (1)
+U3D7D	anonymous	2009-1-1 (1)
+U7FFA	anonymous	2009-1-1 (1)
+U4B8B	anonymous	2009-1-1 (1)
+U39F2	anonymous	2009-1-1 (1)
+U3AE1	anonymous	2009-1-1 (1)
+U39F4	anonymous	2009-1-1 (1)
+U4B8A	anonymous	2009-1-1 (1)
+U441C	anonymous	2009-1-1 (1)
+U4CCE	anonymous	2009-1-1 (1)
+U803C	anonymous	2009-1-1 (1)
+U43A2	anonymous	2009-1-1 (1)
+U3BDA	anonymous	2009-1-1 (1)
+U4420	anonymous	2009-1-1 (1)
+U4923	anonymous	2009-1-1 (1)
+U4924	anonymous	2009-1-1 (1)
+U3630	anonymous	2009-1-1 (1)
+U4922	anonymous	2009-1-1 (1)
+U5DED	anonymous	2009-1-1 (1)
+U3631	anonymous	2009-1-1 (1)
+U9767	anonymous	2009-1-1 (1)
+U4175	anonymous	2009-1-1 (1)
+U4D9F	emittime	2009-1-1 (1)
+U4176	anonymous	2009-1-1 (1)
+U37FE	anonymous	2009-1-1 (1)
+U3C19	anonymous	2009-1-1 (1)
+U97D1	anonymous	2009-1-1 (1)
+U3910	anonymous	2009-1-1 (1)
+U40AC	anonymous	2009-1-1 (1)
+U481D	anonymous	2009-1-1 (1)
+U420F	anonymous	2009-1-1 (1)
+U481E	anonymous	2009-1-1 (1)
+U4343	anonymous	2009-1-1 (1)
+U488E	anonymous	2009-1-1 (1)
+U4750	anonymous	2009-1-1 (1)
+U4018	anonymous	2009-1-1 (1)
+U4019	anonymous	2009-1-1 (1)
+U41CC	emittime	2009-1-1 (1)
+U45E5	anonymous	2009-1-1 (1)
+U3719	anonymous	2009-1-1 (1)
+U488F	anonymous	2009-1-1 (1)
+U45E6	anonymous	2009-1-1 (1)
+U3EE3	anonymous	2009-1-1 (1)
+U5719	anonymous	2009-1-1 (1)
+U41CD	emittime	2009-1-1 (1)
+U3EE4	anonymous	2009-1-1 (1)
+U41CF	emittime	2009-1-1 (1)
+U4890	anonymous	2009-1-1 (1)
+U45E7	anonymous	2009-1-1 (1)
+U5719	anonymous	2009-1-1 (2)
+U4347	anonymous	2009-1-1 (1)
+U3EE5	anonymous	2009-1-1 (1)
+U3D13	emittime	2009-1-1 (1)
+U442F	anonymous	2009-1-1 (1)
+U4348	anonymous	2009-1-1 (1)
+U38C5	anonymous	2009-1-1 (1)
+U4916	anonymous	2009-1-1 (1)
+U42CE	anonymous	2009-1-1 (1)
+U4435	anonymous	2009-1-1 (1)
+U38E0	anonymous	2009-1-1 (1)
+U42CF	anonymous	2009-1-1 (1)
+U4260	anonymous	2009-1-1 (1)
+U38E3	anonymous	2009-1-1 (1)
+U42D0	anonymous	2009-1-1 (1)
+U76D5	anonymous	2009-1-1 (1)
+U395C	anonymous	2009-1-1 (1)
+U395E	anonymous	2009-1-1 (1)
+U34CF	anonymous	2009-1-1 (1)
+U3A2F	emittime	2009-1-1 (1)
+U34D0	anonymous	2009-1-1 (1)
+U4D5D	anonymous	2009-1-1 (1)
+U42C9	anonymous	2009-1-1 (1)
+U34D1	anonymous	2009-1-1 (1)
+U3A30	emittime	2009-1-1 (1)
+U4D62	anonymous	2009-1-1 (1)
+U76E0	anonymous	2009-1-1 (1)
+U3A52	anonymous	2009-1-1 (1)
+U42CA	anonymous	2009-1-1 (1)
+U42CB	anonymous	2009-1-1 (1)
+U40F0	emittime	2009-1-1 (1)
+U37E3	anonymous	2009-1-1 (1)
+U4D15	anonymous	2009-1-1 (1)
+U44C5	anonymous	2009-1-1 (1)
+U4D16	anonymous	2009-1-1 (1)
+U3A54	anonymous	2009-1-1 (1)
+U44C6	anonymous	2009-1-1 (1)
+U4D17	anonymous	2009-1-1 (1)
+U76E8	anonymous	2009-1-1 (1)
+U461C	anonymous	2009-1-1 (1)
+U497C	anonymous	2009-1-1 (1)
+U35E9	anonymous	2009-1-1 (1)
+U3DB4	anonymous	2009-1-1 (1)
+U36A4	anonymous	2009-1-1 (1)
+U40D9	anonymous	2009-1-1 (1)
+U45E3	anonymous	2009-1-1 (1)
+U3F69	emittime	2009-1-1 (1)
+U3F6A	emittime	2009-1-1 (1)
+U3BA9	anonymous	2009-1-1 (1)
+U49D0	anonymous	2009-1-1 (1)
+U4302	anonymous	2009-1-1 (1)
+U82F8	anonymous	2009-1-1 (1)
+U4C1D	anonymous	2009-1-1 (1)
+U3D74	emittime	2009-1-1 (1)
+U45E4	anonymous	2009-1-1 (1)
+U368A	anonymous	2009-1-1 (1)
+U3F6C	anonymous	2009-1-1 (1)
+U49D1	anonymous	2009-1-1 (1)
+U4C1D	anonymous	2009-1-1 (2)
+U368B	anonymous	2009-1-1 (1)
+U4777	anonymous	2009-1-1 (1)
+U368C	anonymous	2009-1-1 (1)
+U4C1D	anonymous	2009-1-1 (3)
+U45A0	anonymous	2009-1-1 (1)
+U3BAB	anonymous	2009-1-1 (1)
+U4776	anonymous	2009-1-1 (1)
+U45A1	anonymous	2009-1-1 (1)
+U393C	anonymous	2009-1-1 (1)
+U35E2	anonymous	2009-1-1 (1)
+U3F5E	anonymous	2009-1-1 (1)
+U393D	anonymous	2009-1-1 (1)
+U393E	anonymous	2009-1-1 (1)
+U3B8C	emittime	2009-1-1 (1)
+U4778	anonymous	2009-1-1 (1)
+U383C	anonymous	2009-1-1 (1)
+U42A3	anonymous	2009-1-1 (1)
+U64D1	anonymous	2009-1-1 (1)
+U3B96	emittime	2009-1-1 (1)
+U42A4	anonymous	2009-1-1 (1)
+U45C2	anonymous	2009-1-1 (1)
+U4D4E	anonymous	2009-1-1 (1)
+U45C3	anonymous	2009-1-1 (1)
+U4B90	anonymous	2009-1-1 (1)
+U46B8	emittime	2009-1-1 (1)
+U3B4E	anonymous	2009-1-1 (1)
+U474E	anonymous	2009-1-1 (1)
+U3B53	anonymous	2009-1-1 (1)
+U340D	anonymous	2009-1-1 (1)
+U3BCC	anonymous	2009-1-1 (1)
+U4B8E	anonymous	2009-1-1 (1)
+U40F6	anonymous	2009-1-1 (1)
+U588D	anonymous	2009-1-1 (1)
+U4B3D	anonymous	2009-1-1 (1)
+U4B3C	anonymous	2009-1-1 (1)
+U39FE	anonymous	2009-1-1 (1)
+U3A32	anonymous	2009-1-1 (1)
+U53D2	anonymous	2009-1-1 (1)
+U46C7	anonymous	2009-1-1 (1)
+U3A00	anonymous	2009-1-1 (1)
+U46C9	anonymous	2009-1-1 (1)
+U4AD3	anonymous	2009-1-1 (1)
+U3A02	anonymous	2009-1-1 (1)
+U4AD5	anonymous	2009-1-1 (1)
+U4B8D	anonymous	2009-1-1 (1)
+U367C	anonymous	2009-1-1 (1)
+U516F	anonymous	2009-1-1 (1)
+U4078	anonymous	2009-1-1 (1)
+U367B	anonymous	2009-1-1 (1)
+U3EF4	anonymous	2009-1-1 (1)
+U3C92	anonymous	2009-1-1 (1)
+U368D	anonymous	2009-1-1 (1)
+U42A5	anonymous	2009-1-1 (1)
+U37D9	anonymous	2009-1-1 (1)
+U4431	anonymous	2009-1-1 (1)
+U8745	anonymous	2009-1-1 (1)
+U37DB	anonymous	2009-1-1 (1)
+U8812	anonymous	2009-1-1 (1)
+U56BB	anonymous	2009-1-1 (1)
+U46B6	anonymous	2009-1-1 (1)
+U3809	anonymous	2009-1-1 (1)
+U9856	anonymous	2009-1-1 (1)
+U3E5E	anonymous	2009-1-1 (1)
+U3E5D	anonymous	2009-1-1 (1)
+U6EE3	anonymous	2009-1-1 (1)
+U3973	anonymous	2009-1-1 (1)
+U64D3	anonymous	2009-1-1 (1)
+U4AA9	anonymous	2009-1-1 (1)
+U3ED0	anonymous	2009-1-1 (1)
+U64D5	anonymous	2009-1-1 (1)
+U3974	anonymous	2009-1-1 (1)
+U4DAE	anonymous	2009-1-1 (1)
+U344F	anonymous	2009-1-1 (1)
+U3C59	anonymous	2009-1-1 (1)
+U5518	anonymous	2009-1-1 (1)
+U6F34	anonymous	2009-1-1 (1)
+U7C35	anonymous	2009-1-1 (1)
+U4927	anonymous	2009-1-1 (1)
+U4929	anonymous	2009-1-1 (1)
+U4928	anonymous	2009-1-1 (1)
+U4920	anonymous	2009-1-1 (1)
+U4759	anonymous	2009-1-1 (1)
+U4927	anonymous	2009-1-1 (2)
+U4758	anonymous	2009-1-1 (1)
+U49CF	anonymous	2009-1-1 (1)
+U4757	anonymous	2009-1-1 (1)
+U617B	anonymous	2009-1-1 (1)
+U49D2	anonymous	2009-1-1 (1)
+U49D3	anonymous	2009-1-1 (1)
+U462F	anonymous	2009-1-1 (1)
+U53D5	anonymous	2009-1-1 (1)
+U4630	anonymous	2009-1-1 (1)
+U3504	anonymous	2009-1-1 (1)
+U3EE6	anonymous	2009-1-1 (1)
+U3EE7	anonymous	2009-1-1 (1)
+U3502	anonymous	2009-1-1 (1)
+U3EE7	anonymous	2009-1-1 (2)
+U8850	anonymous	2009-1-1 (1)
+U49CE	anonymous	2009-1-1 (1)
+U49D5	anonymous	2009-1-1 (1)
+U49D4	anonymous	2009-1-1 (1)
+U378C	anonymous	2009-1-1 (1)
+U6FD6	anonymous	2009-1-1 (1)
+U38E6	anonymous	2009-1-1 (1)
+U4A81	anonymous	2009-1-1 (1)
+U3AD7	anonymous	2009-1-1 (1)
+U5B67	anonymous	2009-1-1 (1)
+U3AD8	anonymous	2009-1-1 (1)
+U493C	anonymous	2009-1-1 (1)
+U3AD9	anonymous	2009-1-1 (1)
+U3AA3	anonymous	2009-1-1 (1)
+U4645	anonymous	2009-1-1 (1)
+U5B6F	anonymous	2009-1-1 (1)
+U408A	anonymous	2009-1-1 (1)
+U4646	anonymous	2009-1-1 (1)
+U3E95	anonymous	2009-1-1 (1)
+U408C	anonymous	2009-1-1 (1)
+U45DC		2009-1-1 (1)
+U4948	anonymous	2009-1-1 (1)
+U48E6	anonymous	2009-1-1 (1)
+U4948	anonymous	2009-1-1 (2)
+U48E7	anonymous	2009-1-1 (1)
+U6550	anonymous	2009-1-1 (1)
+U44A0		2009-1-1 (1)
+U35B5	anonymous	2009-1-1 (1)
+U3CD3	anonymous	2009-1-1 (1)
+U35B9	anonymous	2009-1-1 (1)
+U48E6	anonymous	2009-1-1 (2)
+U3641	anonymous	2009-1-1 (1)
+U35B6	anonymous	2009-1-1 (1)
+U48E6	anonymous	2009-1-1 (3)
+U44A1		2009-1-1 (1)
+U7C36	anonymous	2009-1-1 (1)
+U3C1E	anonymous	2009-1-1 (1)
+U8CFF	anonymous	2009-1-1 (2)
+U8492	anonymous	2009-1-1 (1)
+U44A2		2009-1-1 (1)
+U3DCD	anonymous	2009-1-1 (1)
+U4149		2009-1-1 (1)
+U8493	anonymous	2009-1-1 (1)
+U414A		2009-1-1 (1)
+U46A2	anonymous	2009-1-1 (1)
+U361E		2009-1-1 (1)
+U347D	anonymous	2009-1-1 (1)
+U361D		2009-1-1 (1)
+U3419		2009-1-1 (1)
+U46A3	anonymous	2009-1-1 (1)
+U341A		2009-1-1 (1)
+U4B5B	anonymous	2009-1-1 (1)
+U4A03	anonymous	2009-1-1 (1)
+U39CF	anonymous	2009-1-1 (1)
+U4B5A	anonymous	2009-1-1 (1)
+U3A67	anonymous	2009-1-1 (1)
+U3EC6		2009-1-1 (1)
+U3ECF		2009-1-1 (1)
+U36BB	anonymous	2009-1-1 (1)
+U47EF	anonymous	2009-1-1 (1)
+U3FBF		2009-1-1 (1)
+U36BC	anonymous	2009-1-1 (1)
+U3DCC	anonymous	2009-1-1 (1)
+U415D	anonymous	2009-1-1 (1)
+U47F0	anonymous	2009-1-1 (1)
+U415F	anonymous	2009-1-1 (1)
+U43D5	anonymous	2009-1-1 (1)
+U43D4	anonymous	2009-1-1 (1)
+U3FC0		2009-1-1 (1)
+U4160	anonymous	2009-1-1 (1)
+U43D3	anonymous	2009-1-1 (1)
+U4835	anonymous	2009-1-1 (1)
+U4ABD	anonymous	2009-1-1 (1)
+U3FC1		2009-1-1 (1)
+U3E36	anonymous	2009-1-1 (1)
+U3DD5	anonymous	2009-1-1 (1)
+U4A65		2009-1-1 (1)
+U405C	anonymous	2009-1-1 (1)
+U3E37	anonymous	2009-1-1 (1)
+U4B4F	anonymous	2009-1-1 (1)
+U3E38	anonymous	2009-1-1 (1)
+U40CF	anonymous	2009-1-1 (1)
+U4A67		2009-1-1 (1)
+U4B52	anonymous	2009-1-1 (1)
+U4059	anonymous	2009-1-1 (1)
+U40D0	anonymous	2009-1-1 (1)
+U3866	anonymous	2009-1-1 (1)
+U4D72	anonymous	2009-1-1 (1)
+U4B51	anonymous	2009-1-1 (1)
+U4A66		2009-1-1 (1)
+U3ADC	anonymous	2009-1-1 (1)
+U4CB8	anonymous	2009-1-1 (1)
+U41B3	anonymous	2009-1-1 (1)
+U367A		2009-1-1 (1)
+U4CBC	anonymous	2009-1-1 (1)
+U3D86	anonymous	2009-1-1 (1)
+U3488	anonymous	2009-1-1 (1)
+U35DE	anonymous	2009-1-1 (1)
+U3D87	anonymous	2009-1-1 (1)
+U3488	anonymous	2009-1-1 (2)
+U3488	anonymous	2009-1-1 (3)
+U36A3	anonymous	2009-1-1 (1)
+U3B7A	anonymous	2009-1-1 (1)
+U36A2	anonymous	2009-1-1 (1)
+U3B7B	anonymous	2009-1-1 (1)
+U36A1	anonymous	2009-1-1 (1)
+U3489	anonymous	2009-1-1 (1)
+U3C44	anonymous	2009-1-1 (1)
+U3D07		2009-1-1 (1)
+U64AF	anonymous	2009-1-1 (1)
+U3C46	anonymous	2009-1-1 (1)
+U4705	anonymous	2009-1-1 (1)
+U4708	anonymous	2009-1-1 (1)
+U3C45	anonymous	2009-1-1 (1)
+U36A0	anonymous	2009-1-1 (1)
+U36A5	anonymous	2009-1-1 (1)
+U3B47	anonymous	2009-1-1 (1)
+U3673	anonymous	2009-1-1 (1)
+U41C4	anonymous	2009-1-1 (1)
+U41C5	anonymous	2009-1-1 (1)
+U6449	anonymous	2009-1-1 (1)
+U41C3	anonymous	2009-1-1 (1)
+U39EA	anonymous	2009-1-1 (1)
+U9F8E	anonymous	2009-1-1 (1)
+U39EC	anonymous	2009-1-1 (1)
+U39EB	anonymous	2009-1-1 (1)
+U462C	anonymous	2009-1-1 (1)
+U370A	anonymous	2009-1-1 (1)
+U9F0C	anonymous	2009-1-1 (1)
+U370B	anonymous	2009-1-1 (1)
+U46CC	anonymous	2009-1-1 (1)
+U9F8E	anonymous	2009-1-1 (2)
+U3709	anonymous	2009-1-1 (1)
+U4121	anonymous	2009-1-1 (1)
+U74C9	anonymous	2009-1-1 (1)
+U4122	anonymous	2009-1-1 (1)
+U4128	anonymous	2009-1-1 (1)
+U365B	anonymous	2009-1-1 (1)
+U74B3	anonymous	2009-1-1 (1)
+U4954	anonymous	2009-1-1 (1)
+U3E8D	anonymous	2009-1-1 (1)
+U3E8E	anonymous	2009-1-1 (1)
+U3E8F	anonymous	2009-1-1 (1)
+U372C	anonymous	2009-1-1 (1)
+U4660	anonymous	2009-1-1 (1)
+U43DF	anonymous	2009-1-1 (1)
+U43DD	anonymous	2009-1-1 (1)
+U6EA8	anonymous	2009-1-1 (1)
+U4CC2	anonymous	2009-1-1 (1)
+U4CC4	anonymous	2009-1-1 (1)
+U6F10	anonymous	2009-1-1 (1)
+U4057	anonymous	2009-1-1 (1)
+U4857	anonymous	2009-1-1 (1)
+U4655	anonymous	2009-1-1 (1)
+U4656	anonymous	2009-1-1 (1)
+U4657	anonymous	2009-1-1 (1)
+U3710	anonymous	2009-1-1 (1)
+U7C42	anonymous	2009-1-1 (1)
+U4585	anonymous	2009-1-1 (1)
+U410E	anonymous	2009-1-1 (1)
+U4527	anonymous	2009-1-1 (1)
+U356C	anonymous	2009-1-1 (1)
+U356B	anonymous	2009-1-1 (1)
+U356D	anonymous	2009-1-1 (1)
+U8645	anonymous	2009-1-1 (1)
+U9F1F	anonymous	2009-1-1 (1)
+U37A3	anonymous	2009-1-1 (1)
+U6F49	anonymous	2009-1-1 (1)
+U49D7	anonymous	2009-1-1 (1)
+U348B	anonymous	2009-1-1 (1)
+U3545	anonymous	2009-1-1 (1)
+U3546	anonymous	2009-1-1 (1)
+U3EAB	anonymous	2009-1-1 (1)
+U3EAA	anonymous	2009-1-1 (1)
+U3A16	anonymous	2009-1-1 (1)
+U8834	FangQ	2009-1-1 (1)
+U34E7	anonymous	2009-1-1 (1)
+U47AE	anonymous	2009-1-1 (1)
+U3A27	anonymous	2009-1-1 (1)
+U3453	anonymous	2009-1-1 (1)
+U403A	anonymous	2009-1-1 (1)
+U403D	anonymous	2009-1-1 (1)
+U40E1	anonymous	2009-1-1 (1)
+U40E1	anonymous	2009-1-1 (2)
+U5628	anonymous	2009-1-1 (1)
+U3EAC	anonymous	2009-1-1 (1)
+U4A57	anonymous	2009-1-1 (1)
+U4026	anonymous	2009-1-1 (1)
+U4028	anonymous	2009-1-1 (1)
+U4029	anonymous	2009-1-1 (1)
+U64DD	anonymous	2009-1-1 (1)
+U3E2F	anonymous	2009-1-1 (1)
+U854F	anonymous	2009-1-1 (1)
+U8533	anonymous	2009-1-1 (1)
+U4792	anonymous	2009-1-1 (1)
+U40E1	FangQ	2009-1-1 (3)
+U3546	FangQ	2009-1-1 (2)
+U48CE	anonymous	2009-1-1 (1)
+U3545	FangQ	2009-1-1 (2)
+U3EAA	FangQ	2009-1-1 (2)
+U3CF8	anonymous	2009-1-1 (1)
+U3EAB	FangQ	2009-1-1 (2)
+U3EAB	FangQ	2009-1-1 (3)
+U348B	FangQ	2009-1-1 (2)
+U37A3	FangQ	2009-1-1 (2)
+U454A	anonymous	2009-1-1 (1)
+U3DB5	anonymous	2009-1-1 (1)
+U3DB6	anonymous	2009-1-1 (1)
+U36C8	anonymous	2009-1-1 (1)
+U36C5	anonymous	2009-1-1 (1)
+U410B	anonymous	2009-1-1 (1)
+U410C	anonymous	2009-1-1 (1)
+U364D	anonymous	2009-1-1 (1)
+U3AAD	anonymous	2009-1-1 (1)
+U9F93	shaken	2009-1-1 (1)
+U4285	anonymous	2009-1-1 (1)
+U4283	anonymous	2009-1-1 (1)
+U464F	anonymous	2009-1-1 (1)
+U4650	anonymous	2009-1-1 (1)
+U3D98	anonymous	2009-1-1 (1)
+U4A4B	anonymous	2009-1-1 (1)
+U36C5	FangQ	2009-1-1 (2)
+U3448	anonymous	2009-1-1 (1)
+U492A	anonymous	2009-1-1 (1)
+U3721	anonymous	2009-1-1 (1)
+U344A	anonymous	2009-1-1 (1)
+U3783	anonymous	2009-1-1 (1)
+U4A53	anonymous	2009-1-1 (1)
+U4A59	anonymous	2009-1-1 (1)
+U3638	anonymous	2009-1-1 (1)
+U3639	anonymous	2009-1-1 (1)
+U40B7	anonymous	2009-1-1 (1)
+U47F6	anonymous	2009-1-1 (1)
+U3A2B	anonymous	2009-1-1 (1)
+U47A5	anonymous	2009-1-1 (1)
+U3CCD	anonymous	2009-1-1 (1)
+U3CCB	anonymous	2009-1-1 (1)
+U46A1	anonymous	2009-1-1 (1)
+U3CCE	anonymous	2009-1-1 (1)
+U4A4D	anonymous	2009-1-1 (1)
+U362E	anonymous	2009-1-1 (1)
+U4C7A	anonymous	2009-1-1 (1)
+U3A99	anonymous	2009-1-1 (1)
+U425E	anonymous	2009-1-1 (1)
+U344E	anonymous	2009-1-1 (1)
+U3E9A	anonymous	2009-1-1 (1)
+U43A3	anonymous	2009-1-1 (1)
+U35BD	anonymous	2009-1-1 (1)
+U3F51	anonymous	2009-1-1 (1)
+U3A34	anonymous	2009-1-1 (1)
+U4C29	anonymous	2009-1-1 (1)
+U45BE	anonymous	2009-1-1 (1)
+U3884	anonymous	2009-1-1 (1)
+U3E81	anonymous	2009-1-1 (1)
+U397C	anonymous	2009-1-1 (1)
+U364A	anonymous	2009-1-1 (1)
+U3581	anonymous	2009-1-1 (1)
+U40AD	anonymous	2009-1-1 (1)
+U40AD	anonymous	2009-1-1 (2)
+U46CD	anonymous	2009-1-1 (1)
+U3BE2	anonymous	2009-1-1 (1)
+U4221	anonymous	2009-1-1 (1)
+U439B	anonymous	2009-1-1 (1)
+U46CE	anonymous	2009-1-1 (1)
+U4AC9	anonymous	2009-1-1 (1)
+U3656	anonymous	2009-1-1 (1)
+U45B3	anonymous	2009-1-1 (1)
+U4BA5	anonymous	2009-1-1 (1)
+U3DBA	anonymous	2009-1-1 (1)
+U4102	anonymous	2009-1-1 (1)
+U3881	anonymous	2009-1-1 (1)
+U45E9	anonymous	2009-1-1 (1)
+U41DF	anonymous	2009-1-1 (1)
+U404E	anonymous	2009-1-1 (1)
+U3439	anonymous	2009-1-1 (1)
+U6FE5	anonymous	2009-1-1 (1)
+U3438	anonymous	2009-1-1 (1)
+U4BE1	anonymous	2009-1-1 (1)
+U3436	anonymous	2009-1-1 (1)
+U370D	anonymous	2009-1-1 (1)
+U3DD9	anonymous	2009-1-1 (1)
+U37D2	anonymous	2009-1-1 (1)
+U40CB	anonymous	2009-1-1 (1)
+U3B99	anonymous	2009-1-1 (1)
+U4468	anonymous	2009-1-1 (1)
+U4C41	anonymous	2009-1-1 (1)
+U4D6D		2009-1-1 (1)
+U48D2	anonymous	2009-1-1 (1)
+U4D6D		2009-1-1 (2)
+U4740	anonymous	2009-1-1 (1)
+U446B	anonymous	2009-1-1 (1)
+U38F4	anonymous	2009-1-1 (1)
+U446A	anonymous	2009-1-1 (1)
+U38F3	anonymous	2009-1-1 (1)
+U76E2	anonymous	2009-1-1 (1)
+U76E2	anonymous	2009-1-1 (2)
+U408F	anonymous	2009-1-1 (1)
+U4090	anonymous	2009-1-1 (1)
+U37B9	anonymous	2009-1-1 (1)
+U34CB	anonymous	2009-1-1 (1)
+U3AF4	anonymous	2009-1-1 (1)
+U4D6D		2009-1-1 (3)
+U3AF2	anonymous	2009-1-1 (1)
+U4161		2009-1-1 (1)
+U46AC	anonymous	2009-1-1 (1)
+U6BEE	anonymous	2009-1-1 (1)
+U3F6D	anonymous	2009-1-1 (1)
+U42C1	anonymous	2009-1-1 (1)
+U42DB	anonymous	2009-1-1 (1)
+U8117	anonymous	2009-1-1 (1)
+U75A9	anonymous	2009-1-1 (1)
+U380F	anonymous	2009-1-1 (1)
+U4723	anonymous	2009-1-1 (1)
+U380F	anonymous	2009-1-1 (2)
+U3848	anonymous	2009-1-1 (1)
+U75DC	anonymous	2009-1-1 (1)
+U3CBA	anonymous	2009-1-1 (1)
+U3D0E	anonymous	2009-1-1 (1)
+U4AE1	anonymous	2009-1-1 (1)
+U3B33	anonymous	2009-1-1 (1)
+U36D2	anonymous	2009-1-1 (1)
+U36D0	anonymous	2009-1-1 (1)
+U49C3	anonymous	2009-1-1 (1)
+U4CBD	anonymous	2009-1-1 (1)
+U48FB	anonymous	2009-1-1 (1)
+U4C49	anonymous	2009-1-1 (1)
+U36D3	anonymous	2009-1-1 (1)
+U36D4	anonymous	2009-1-1 (1)
+U48FC	anonymous	2009-1-1 (1)
+U4424	anonymous	2009-1-1 (1)
+U4836	anonymous	2009-1-1 (1)
+U4426	anonymous	2009-1-1 (1)
+U41FC	anonymous	2009-1-1 (1)
+U3B54	anonymous	2009-1-1 (1)
+U4415	anonymous	2009-1-1 (1)
+U3B54	anonymous	2009-1-1 (2)
+U3B54	anonymous	2009-1-1 (3)
+U39FC	anonymous	2009-1-1 (1)
+U3B54	anonymous	2009-1-1 (4)
+U3EBF	anonymous	2009-1-1 (1)
+U3EC1	anonymous	2009-1-1 (1)
+U3F8B	FangQ	2009-1-1 (1)
+U4D6C	anonymous	2009-1-1 (1)
+U3F8C	FangQ	2009-1-1 (1)
+U34E8	anonymous	2009-1-1 (1)
+U34E9	anonymous	2009-1-1 (1)
+U3B8E	anonymous	2009-1-1 (1)
+U3F8D	FangQ	2009-1-1 (1)
+U34E6	anonymous	2009-1-1 (1)
+U460F	FangQ	2009-1-1 (1)
+U4610	FangQ	2009-1-1 (1)
+U3A4C	anonymous	2009-1-1 (1)
+U3A4D	anonymous	2009-1-1 (1)
+U3C3F		2009-1-1 (1)
+U464E	anonymous	2009-1-1 (1)
+U48E0	anonymous	2009-1-1 (1)
+U81EF	anonymous	2009-1-1 (1)
+U3B7E		2009-1-1 (1)
+U45F0	anonymous	2009-1-1 (1)
+U3B41	anonymous	2009-1-1 (1)
+U3B43	anonymous	2009-1-1 (1)
+U7C44	anonymous	2009-1-2 (1)
+U7C3A	anonymous	2009-1-2 (1)
+U46D7		2009-1-2 (1)
+U3757	anonymous	2009-1-2 (1)
+U7C55	anonymous	2009-1-2 (1)
+U3570	anonymous	2009-1-2 (1)
+U7C5D	anonymous	2009-1-2 (1)
+U480D	anonymous	2009-1-2 (1)
+U6F4C	anonymous	2009-1-2 (1)
+U4B9D	anonymous	2009-1-2 (1)
+U3591	anonymous	2009-1-2 (1)
+U4E75	anonymous	2009-1-2 (1)
+U3593	anonymous	2009-1-2 (1)
+U3559	anonymous	2009-1-2 (1)
+U4E72	anonymous	2009-1-2 (1)
+U3B6C	anonymous	2009-1-2 (1)
+U446C	anonymous	2009-1-2 (1)
+U4AA6	anonymous	2009-1-2 (1)
+U4470	anonymous	2009-1-2 (1)
+U843E	anonymous	2009-1-2 (1)
+U6FD7	anonymous	2009-1-2 (1)
+U4A44	anonymous	2009-1-2 (1)
+U40D1	anonymous	2009-1-2 (1)
+U40D2	anonymous	2009-1-2 (1)
+U3AE2	anonymous	2009-1-2 (1)
+U4A43	anonymous	2009-1-2 (1)
+U40D3	anonymous	2009-1-2 (1)
+U47FE	anonymous	2009-1-2 (1)
+U3FA4	anonymous	2009-1-2 (1)
+U47FF	anonymous	2009-1-2 (1)
+U3FA4	anonymous	2009-1-2 (2)
+U6FB7	anonymous	2009-1-2 (1)
+U4AA8	anonymous	2009-1-2 (1)
+U4A45	anonymous	2009-1-2 (1)
+U4801	anonymous	2009-1-2 (1)
+U49DB	anonymous	2009-1-2 (1)
+U447F	anonymous	2009-1-2 (1)
+U3428	anonymous	2009-1-2 (1)
+U39B4	anonymous	2009-1-2 (1)
+U39B6	anonymous	2009-1-2 (1)
+U472F	anonymous	2009-1-2 (1)
+U3F46	anonymous	2009-1-2 (1)
+U4779	anonymous	2009-1-2 (1)
+U4731	anonymous	2009-1-2 (1)
+U4943	anonymous	2009-1-2 (1)
+U47AC	anonymous	2009-1-2 (1)
+U3E6B	anonymous	2009-1-2 (1)
+U477B	anonymous	2009-1-2 (1)
+U40EB	anonymous	2009-1-2 (1)
+U3967	anonymous	2009-1-2 (1)
+U6F56	anonymous	2009-1-2 (1)
+U4882	anonymous	2009-1-2 (1)
+U4425	anonymous	2009-1-2 (1)
+U75EE	anonymous	2009-1-2 (1)
+U442A	anonymous	2009-1-2 (1)
+U64DF	anonymous	2009-1-2 (1)
+U3734	anonymous	2009-1-2 (1)
+U3733	anonymous	2009-1-2 (1)
+U3602	anonymous	2009-1-2 (1)
+U617F	anonymous	2009-1-2 (1)
+U3732	anonymous	2009-1-2 (1)
+U442B	anonymous	2009-1-2 (1)
+U442C	anonymous	2009-1-2 (1)
+U3463	anonymous	2009-1-2 (1)
+U442D	anonymous	2009-1-2 (1)
+U4EAF	anonymous	2009-1-2 (1)
+U3B1D	anonymous	2009-1-2 (1)
+U3B1B	anonymous	2009-1-2 (1)
+U3904	anonymous	2009-1-2 (1)
+U4080	anonymous	2009-1-2 (1)
+U4082	anonymous	2009-1-2 (1)
+U4ED0	anonymous	2009-1-2 (1)
+U45C9	anonymous	2009-1-2 (1)
+U45C9	anonymous	2009-1-2 (2)
+U53B7	anonymous	2009-1-2 (1)
+U437F	anonymous	2009-1-2 (1)
+U34DC	anonymous	2009-1-2 (1)
+U34DD	anonymous	2009-1-2 (1)
+U4A7D	anonymous	2009-1-2 (1)
+U4A7B	anonymous	2009-1-2 (1)
+U4A7C	anonymous	2009-1-2 (1)
+U363E	anonymous	2009-1-2 (1)
+U449E	pem	2009-1-2 (1)
+U4309	anonymous	2009-1-2 (1)
+U363E	anonymous	2009-1-2 (2)
+U3706	anonymous	2009-1-2 (1)
+U9AE9	anonymous	2009-1-2 (1)
+U363E	anonymous	2009-1-2 (3)
+U3705	anonymous	2009-1-2 (1)
+U430B	anonymous	2009-1-2 (1)
+U4BA6	anonymous	2009-1-2 (1)
+U45A9	anonymous	2009-1-2 (1)
+U46FB	anonymous	2009-1-2 (1)
+U46FD	anonymous	2009-1-2 (1)
+U419A	anonymous	2009-1-2 (1)
+U419A	anonymous	2009-1-2 (2)
+U37CB	anonymous	2009-1-2 (1)
+U449F	pem	2009-1-2 (1)
+U37CD	anonymous	2009-1-2 (1)
+U4251	anonymous	2009-1-2 (1)
+U4338	anonymous	2009-1-2 (1)
+U4339	anonymous	2009-1-2 (1)
+U3A1A	anonymous	2009-1-2 (1)
+U4252	anonymous	2009-1-2 (1)
+U3A1B	anonymous	2009-1-2 (1)
+U491F	anonymous	2009-1-2 (1)
+U4ABA	pem	2009-1-2 (1)
+U4809	anonymous	2009-1-2 (1)
+U34C5	anonymous	2009-1-2 (1)
+U4ABB	pem	2009-1-2 (1)
+U37B2	anonymous	2009-1-2 (1)
+U4ABC	pem	2009-1-2 (1)
+U4A8D	anonymous	2009-1-2 (1)
+U3464	anonymous	2009-1-2 (1)
+U45AE	anonymous	2009-1-2 (1)
+U4962	anonymous	2009-1-2 (1)
+U37B2	anonymous	2009-1-2 (2)
+U4093	anonymous	2009-1-2 (1)
+U416D	anonymous	2009-1-2 (1)
+U4091	anonymous	2009-1-2 (1)
+U377F	anonymous	2009-1-2 (1)
+U4B85	anonymous	2009-1-2 (1)
+U4060	anonymous	2009-1-2 (1)
+U4094	anonymous	2009-1-2 (1)
+U3A2E	pem	2009-1-2 (1)
+U3C34	anonymous	2009-1-2 (1)
+U4CD5	anonymous	2009-1-2 (1)
+U4720	anonymous	2009-1-2 (1)
+U3DC4	anonymous	2009-1-2 (1)
+U4721	anonymous	2009-1-2 (1)
+U4B3E	anonymous	2009-1-2 (1)
+U4C61	anonymous	2009-1-2 (1)
+U433A	anonymous	2009-1-2 (1)
+U3DC7	anonymous	2009-1-2 (1)
+U4B3F	anonymous	2009-1-2 (1)
+U4C62	anonymous	2009-1-2 (1)
+U3A2D	pem	2009-1-2 (1)
+U4C63	anonymous	2009-1-2 (1)
+U3A2C	pem	2009-1-2 (1)
+U7314	anonymous	2009-1-2 (2)
+U3E71	anonymous	2009-1-2 (1)
+U4AAC	anonymous	2009-1-2 (1)
+U4C9D	anonymous	2009-1-2 (1)
+U731A	anonymous	2009-1-2 (2)
+U37B5	anonymous	2009-1-2 (1)
+U39D7	anonymous	2009-1-2 (1)
+U7320	anonymous	2009-1-2 (2)
+U3E76	anonymous	2009-1-2 (1)
+U3698	anonymous	2009-1-2 (1)
+U4C9E	anonymous	2009-1-2 (1)
+U4020	anonymous	2009-1-2 (1)
+U484A	anonymous	2009-1-2 (1)
+U385B	anonymous	2009-1-2 (1)
+U369A	anonymous	2009-1-2 (1)
+U484B	anonymous	2009-1-2 (1)
+U3E75	anonymous	2009-1-2 (1)
+U4851	anonymous	2009-1-2 (1)
+U3E97	anonymous	2009-1-2 (1)
+U3661	anonymous	2009-1-2 (1)
+U4D14	anonymous	2009-1-2 (1)
+U3E6D	anonymous	2009-1-2 (1)
+U369B	anonymous	2009-1-2 (1)
+U3DFF	anonymous	2009-1-2 (1)
+U3E0A	anonymous	2009-1-2 (1)
+U4D9D	anonymous	2009-1-2 (1)
+U3A28	anonymous	2009-1-2 (1)
+U4DA1	anonymous	2009-1-2 (1)
+U39D5	anonymous	2009-1-2 (1)
+U3C7B	anonymous	2009-1-2 (1)
+U3696	anonymous	2009-1-2 (1)
+U4870	anonymous	2009-1-2 (1)
+U4911	anonymous	2009-1-2 (1)
+U3C7D	anonymous	2009-1-2 (1)
+U3785	anonymous	2009-1-2 (1)
+U429E	anonymous	2009-1-2 (1)
+U4912	anonymous	2009-1-2 (1)
+U493B	anonymous	2009-1-2 (1)
+U389B	anonymous	2009-1-2 (1)
+U3B6D	anonymous	2009-1-2 (1)
+U3B5F	anonymous	2009-1-2 (1)
+U46DF	anonymous	2009-1-2 (1)
+U3B60	anonymous	2009-1-2 (1)
+U3DDB	anonymous	2009-1-2 (1)
+U3D67	anonymous	2009-1-2 (1)
+U3578	anonymous	2009-1-2 (1)
+U37D3	anonymous	2009-1-2 (1)
+U517A	anonymous	2009-1-2 (1)
+U3579	anonymous	2009-1-2 (1)
+U3F5F	anonymous	2009-1-2 (1)
+U4238	anonymous	2009-1-2 (1)
+U3ED4	anonymous	2009-1-2 (1)
+U3ED7	anonymous	2009-1-2 (1)
+U3CB5	anonymous	2009-1-2 (1)
+U3B4F	anonymous	2009-1-2 (1)
+U49B6	anonymous	2009-1-2 (1)
+U532B	anonymous	2009-1-2 (1)
+U3CB6	anonymous	2009-1-2 (1)
+U396A	anonymous	2009-1-2 (1)
+U3CB7	anonymous	2009-1-2 (1)
+U396C	anonymous	2009-1-2 (1)
+U3E39	anonymous	2009-1-2 (1)
+U3BBD	anonymous	2009-1-2 (1)
+U3CB8	anonymous	2009-1-2 (1)
+U6184	anonymous	2009-1-2 (1)
+U3CB9	anonymous	2009-1-2 (1)
+U3CBB	anonymous	2009-1-2 (1)
+U3E3A	anonymous	2009-1-2 (1)
+U3E3B	anonymous	2009-1-2 (1)
+U42C7	anonymous	2009-1-2 (1)
+U4414	anonymous	2009-1-2 (1)
+U43E4	anonymous	2009-1-2 (1)
+U3F35	anonymous	2009-1-2 (1)
+U3F36	anonymous	2009-1-2 (1)
+U982E	anonymous	2009-1-2 (1)
+U43E5	anonymous	2009-1-2 (1)
+U3F37	anonymous	2009-1-2 (1)
+U464B	anonymous	2009-1-2 (1)
+U43E6	anonymous	2009-1-2 (1)
+U983F	anonymous	2009-1-2 (1)
+U4891	anonymous	2009-1-2 (1)
+U4C5E	anonymous	2009-1-2 (1)
+U3A03	anonymous	2009-1-2 (1)
+U4C5F	anonymous	2009-1-2 (1)
+U3A06	anonymous	2009-1-2 (1)
+U4C60	anonymous	2009-1-2 (1)
+U4892	anonymous	2009-1-2 (1)
+U49C8	anonymous	2009-1-2 (1)
+U49C9	anonymous	2009-1-2 (1)
+U4B65	anonymous	2009-1-2 (1)
+U4B67	anonymous	2009-1-2 (1)
+U49D6	anonymous	2009-1-2 (1)
+U3538	anonymous	2009-1-2 (1)
+U9F96	anonymous	2009-1-2 (1)
+U4381	anonymous	2009-1-2 (1)
+U353B	anonymous	2009-1-2 (1)
+U43AC	anonymous	2009-1-2 (1)
+U3707	anonymous	2009-1-2 (1)
+U43AD	anonymous	2009-1-2 (1)
+U4AAA	anonymous	2009-1-2 (1)
+U4AAB	anonymous	2009-1-2 (1)
+U4AAE	anonymous	2009-1-2 (1)
+U3C33	anonymous	2009-1-2 (1)
+U3C35	anonymous	2009-1-2 (1)
+U4437	anonymous	2009-1-2 (1)
+U4438	anonymous	2009-1-2 (1)
+U4C18	anonymous	2009-1-2 (1)
+U9F97	anonymous	2009-1-2 (1)
+U4C19	anonymous	2009-1-2 (1)
+U4C1A	anonymous	2009-1-2 (1)
+U4C72	anonymous	2009-1-2 (1)
+U3727	anonymous	2009-1-2 (1)
+U3817	anonymous	2009-1-2 (1)
+U3728	anonymous	2009-1-2 (1)
+U4287	anonymous	2009-1-2 (1)
+U8379	anonymous	2009-1-2 (1)
+U4828	anonymous	2009-1-2 (1)
+U4829	anonymous	2009-1-2 (1)
+U3EAE	anonymous	2009-1-2 (1)
+U485A	anonymous	2009-1-2 (1)
+U447E	anonymous	2009-1-2 (1)
+U35D3	anonymous	2009-1-2 (1)
+U362A	anonymous	2009-1-2 (1)
+U35D5	anonymous	2009-1-2 (1)
+U3972	anonymous	2009-1-2 (1)
+U4A74	anonymous	2009-1-2 (1)
+U4A75	anonymous	2009-1-2 (1)
+U42E6	anonymous	2009-1-2 (1)
+U3C04	anonymous	2009-1-2 (1)
+U42EB	anonymous	2009-1-2 (1)
+U4129	lsz	2009-1-2 (1)
+U412B	lsz	2009-1-2 (1)
+U42C4	anonymous	2009-1-2 (1)
+U42C6	anonymous	2009-1-2 (1)
+U6185	anonymous	2009-1-2 (1)
+U412A	lsz	2009-1-2 (1)
+U64EA	anonymous	2009-1-2 (1)
+U44D3	anonymous	2009-1-2 (1)
+U411A	anonymous	2009-1-2 (1)
+U4119	anonymous	2009-1-2 (1)
+U42F4	anonymous	2009-1-2 (1)
+U6197	anonymous	2009-1-2 (1)
+U43BB	anonymous	2009-1-2 (1)
+U3AB7	anonymous	2009-1-2 (1)
+U43BC	anonymous	2009-1-2 (1)
+U43BD	anonymous	2009-1-2 (1)
+U884F	anonymous	2009-1-2 (1)
+U3E5F	anonymous	2009-1-2 (1)
+U36E6	anonymous	2009-1-2 (1)
+U36EA	anonymous	2009-1-2 (1)
+U9868	anonymous	2009-1-2 (1)
+U485F	anonymous	2009-1-2 (1)
+U363A	anonymous	2009-1-2 (1)
+U4860	anonymous	2009-1-2 (1)
+U6AA7	anonymous	2009-1-2 (1)
+U3CAD	anonymous	2009-1-2 (1)
+U483A	anonymous	2009-1-2 (1)
+U43E7	anonymous	2009-1-2 (1)
+U43E9	anonymous	2009-1-2 (1)
+U3E4E	anonymous	2009-1-2 (1)
+U3E4D	anonymous	2009-1-2 (1)
+U3E4F	anonymous	2009-1-2 (1)
+U4901	anonymous	2009-1-2 (1)
+U4A95	anonymous	2009-1-2 (1)
+U4902	anonymous	2009-1-2 (1)
+U4903	anonymous	2009-1-2 (1)
+U4B60	anonymous	2009-1-2 (1)
+U4B61	anonymous	2009-1-2 (1)
+U372F	anonymous	2009-1-2 (1)
+U3A35	anonymous	2009-1-2 (1)
+U4471	anonymous	2009-1-2 (1)
+U4321	anonymous	2009-1-2 (1)
+U41D5	anonymous	2009-1-2 (1)
+U4476	anonymous	2009-1-2 (1)
+U41D5	anonymous	2009-1-2 (2)
+U3A39	anonymous	2009-1-2 (1)
+U401E	anonymous	2009-1-2 (1)
+U3A38	anonymous	2009-1-2 (1)
+U49DA	anonymous	2009-1-2 (1)
+U49DC	anonymous	2009-1-2 (1)
+U401D	anonymous	2009-1-2 (1)
+U4ADD	anonymous	2009-1-2 (1)
+U401F	anonymous	2009-1-2 (1)
+U351A	anonymous	2009-1-2 (1)
+U3921	anonymous	2009-1-2 (1)
+U42BC	anonymous	2009-1-2 (1)
+U4C64	anonymous	2009-1-2 (1)
+U3920	anonymous	2009-1-2 (1)
+U5183	anonymous	2009-1-2 (1)
+U4865	anonymous	2009-1-2 (1)
+U3E27	anonymous	2009-1-2 (1)
+U4A5A	anonymous	2009-1-2 (1)
+U3440	anonymous	2009-1-2 (1)
+U4032	anonymous	2009-1-2 (1)
+U3441	anonymous	2009-1-2 (1)
+U4496	anonymous	2009-1-2 (1)
+U48D8	anonymous	2009-1-2 (1)
+U417D	anonymous	2009-1-2 (1)
+U4C7B	anonymous	2009-1-2 (1)
+U48F7	anonymous	2009-1-2 (1)
+U487F	anonymous	2009-1-2 (1)
+U3BF2	anonymous	2009-1-2 (1)
+U40BD	anonymous	2009-1-2 (1)
+U36CA	anonymous	2009-1-2 (1)
+U40BF	anonymous	2009-1-2 (1)
+U3500	anonymous	2009-1-2 (1)
+U4235	anonymous	2009-1-2 (1)
+U3520	anonymous	2009-1-2 (1)
+U3629	anonymous	2009-1-2 (1)
+U6ABE	anonymous	2009-1-2 (1)
+U3628	anonymous	2009-1-2 (1)
+U3501	anonymous	2009-1-2 (1)
+U42C8	anonymous	2009-1-2 (1)
+U3C75	anonymous	2009-1-2 (1)
+U4C1B	anonymous	2009-1-2 (1)
+U3467	anonymous	2009-1-2 (1)
+U37A8	anonymous	2009-1-2 (1)
+U4C93	anonymous	2009-1-2 (1)
+U4A6D	anonymous	2009-1-2 (1)
+U4C95	anonymous	2009-1-2 (1)
+U3EF8	anonymous	2009-1-2 (1)
+U3BEE	anonymous	2009-1-2 (1)
+U40F1	anonymous	2009-1-2 (1)
+U4876	anonymous	2009-1-2 (1)
+U6B58	anonymous	2009-1-2 (1)
+U98EC	anonymous	2009-1-2 (1)
+U3D90	anonymous	2009-1-2 (1)
+U4873	anonymous	2009-1-2 (1)
+U43BE	anonymous	2009-1-2 (1)
+U4874	anonymous	2009-1-2 (1)
+U4875	anonymous	2009-1-2 (1)
+U3B79	anonymous	2009-1-2 (1)
+U4050	anonymous	2009-1-2 (1)
+U4052	anonymous	2009-1-2 (1)
+U9B1D	anonymous	2009-1-2 (1)
+U4BFB	anonymous	2009-1-2 (1)
+U3BAF	anonymous	2009-1-2 (1)
+U4688	anonymous	2009-1-2 (1)
+U4055	anonymous	2009-1-2 (1)
+U4BDC	anonymous	2009-1-2 (1)
+U4BDD	anonymous	2009-1-2 (1)
+U3568	anonymous	2009-1-2 (1)
+U4BDE	anonymous	2009-1-2 (1)
+U3569	anonymous	2009-1-2 (1)
+U3C0C	anonymous	2009-1-2 (1)
+U3E80	anonymous	2009-1-2 (1)
+U3EBA	anonymous	2009-1-2 (1)
+U3E7F	anonymous	2009-1-2 (1)
+U3E7E	anonymous	2009-1-2 (1)
+U3926	anonymous	2009-1-2 (1)
+U49FE	anonymous	2009-1-2 (1)
+U3927	anonymous	2009-1-2 (1)
+U42B5	anonymous	2009-1-2 (1)
+U49FF	anonymous	2009-1-2 (1)
+U3E62	anonymous	2009-1-2 (1)
+U3E61	anonymous	2009-1-2 (1)
+U3D3B	anonymous	2009-1-2 (1)
+U3C36	daliansky	2009-1-2 (1)
+U3E60	anonymous	2009-1-2 (1)
+U3D3C	anonymous	2009-1-2 (1)
+U3D3D	anonymous	2009-1-2 (1)
+U3ADA	anonymous	2009-1-2 (1)
+U4461	anonymous	2009-1-2 (1)
+U4A49	anonymous	2009-1-2 (1)
+U3A1E	anonymous	2009-1-2 (1)
+U4A46	anonymous	2009-1-2 (1)
+U4C28	daliansky	2009-1-2 (1)
+U4A48	anonymous	2009-1-2 (1)
+U4763	anonymous	2009-1-2 (1)
+U4871	anonymous	2009-1-2 (1)
+U3A21	anonymous	2009-1-2 (1)
+U3DC8	anonymous	2009-1-2 (1)
+U4872	anonymous	2009-1-2 (1)
+U4877	anonymous	2009-1-2 (1)
+U4B75	anonymous	2009-1-2 (1)
+U4C2B	daliansky	2009-1-2 (1)
+U490E	anonymous	2009-1-2 (1)
+U4910	anonymous	2009-1-2 (1)
+U3D32	anonymous	2009-1-2 (1)
+U44A8	anonymous	2009-1-2 (1)
+U3C62	anonymous	2009-1-2 (1)
+U7651	lsz	2009-1-2 (1)
+U3C5E	anonymous	2009-1-2 (1)
+U34EA	anonymous	2009-1-2 (1)
+U34EA	anonymous	2009-1-2 (2)
+U44AA	anonymous	2009-1-2 (1)
+U3C5D	anonymous	2009-1-2 (1)
+U3E63	anonymous	2009-1-2 (1)
+U4985	daliansky	2009-1-2 (1)
+U414D	anonymous	2009-1-2 (1)
+U45F5	lsz	2009-1-2 (1)
+U4986	daliansky	2009-1-2 (1)
+U4986	anonymous	2009-1-2 (2)
+U4A13	anonymous	2009-1-2 (1)
+U4168	anonymous	2009-1-2 (1)
+U4B6A	anonymous	2009-1-2 (1)
+U3EB5	anonymous	2009-1-2 (1)
+U47F5	anonymous	2009-1-2 (1)
+U3EB2	anonymous	2009-1-2 (1)
+U4A4A	anonymous	2009-1-2 (1)
+U3BCA	daliansky	2009-1-2 (1)
+U3EB3	anonymous	2009-1-2 (1)
+U3E2B	anonymous	2009-1-2 (1)
+U48C4	anonymous	2009-1-2 (1)
+U48D6	anonymous	2009-1-2 (1)
+U3FDE	anonymous	2009-1-2 (1)
+U433B	anonymous	2009-1-2 (1)
+U433C	anonymous	2009-1-2 (1)
+U3FE1	anonymous	2009-1-2 (1)
+U433D	anonymous	2009-1-2 (1)
+U38EA	anonymous	2009-1-2 (1)
+U495B	anonymous	2009-1-2 (1)
+U38EB	anonymous	2009-1-2 (1)
+U3EDF	anonymous	2009-1-2 (1)
+U36AB	anonymous	2009-1-2 (1)
+U3EE1	anonymous	2009-1-2 (1)
+U36AC	anonymous	2009-1-2 (1)
+U36AD	anonymous	2009-1-2 (1)
+U4AB4	anonymous	2009-1-2 (1)
+U3FFF	anonymous	2009-1-2 (1)
+U366E	anonymous	2009-1-2 (1)
+U366D	anonymous	2009-1-2 (1)
+U4C5A	anonymous	2009-1-2 (1)
+U4C5D	anonymous	2009-1-2 (1)
+U46EF	anonymous	2009-1-2 (1)
+U4CB0	daliansky	2009-1-2 (1)
+U353C	anonymous	2009-1-2 (1)
+U4CB2	daliansky	2009-1-2 (1)
+U3450	anonymous	2009-1-2 (1)
+U3451	anonymous	2009-1-2 (1)
+U43FB	anonymous	2009-1-2 (1)
+U3CF5	anonymous	2009-1-2 (1)
+U4A1C	anonymous	2009-1-2 (1)
+U37C2	anonymous	2009-1-2 (1)
+U3CF3	anonymous	2009-1-2 (1)
+U37C3	anonymous	2009-1-2 (1)
+U396D	anonymous	2009-1-2 (1)
+U4CB3	daliansky	2009-1-2 (1)
+U40AF	anonymous	2009-1-2 (1)
+U40B0	anonymous	2009-1-2 (1)
+U3F2B	anonymous	2009-1-2 (1)
+U3F2C	anonymous	2009-1-2 (1)
+U39C6	anonymous	2009-1-2 (1)
+U3F8F	anonymous	2009-1-2 (1)
+U467F	anonymous	2009-1-2 (1)
+U3F90	anonymous	2009-1-2 (1)
+U40B1	anonymous	2009-1-2 (1)
+U4794	anonymous	2009-1-2 (1)
+U4652	anonymous	2009-1-2 (1)
+U40B3	anonymous	2009-1-2 (1)
+U40B1	anonymous	2009-1-2 (2)
+U4C66	anonymous	2009-1-2 (1)
+U4653	anonymous	2009-1-2 (1)
+U4654	anonymous	2009-1-2 (1)
+U4C67	anonymous	2009-1-2 (1)
+U4483	anonymous	2009-1-2 (1)
+U4CE1	anonymous	2009-1-2 (1)
+U4794	anonymous	2009-1-2 (2)
+U41E6	anonymous	2009-1-2 (1)
+U43F9	anonymous	2009-1-2 (1)
+U4CE2	anonymous	2009-1-2 (1)
+U3C70	anonymous	2009-1-2 (1)
+U3E53	anonymous	2009-1-2 (1)
+U43FC	anonymous	2009-1-2 (1)
+U3C74	anonymous	2009-1-2 (1)
+U3E54	anonymous	2009-1-2 (1)
+U4A5C	anonymous	2009-1-2 (1)
+U397D	anonymous	2009-1-2 (1)
+U397E	anonymous	2009-1-2 (1)
+U4A5B	anonymous	2009-1-2 (1)
+U3E3D	anonymous	2009-1-2 (1)
+U397F	anonymous	2009-1-2 (1)
+U3E3E	anonymous	2009-1-2 (1)
+U61CE		2009-1-2 (1)
+U4685	anonymous	2009-1-2 (1)
+U3A68	anonymous	2009-1-2 (1)
+U3513	anonymous	2009-1-2 (1)
+U3514	anonymous	2009-1-2 (1)
+U4686	anonymous	2009-1-2 (1)
+U45B4	anonymous	2009-1-2 (1)
+U387E	anonymous	2009-1-2 (1)
+U45B5	anonymous	2009-1-2 (1)
+U4687	anonymous	2009-1-2 (1)
+U387F	anonymous	2009-1-2 (1)
+U3607	anonymous	2009-1-2 (1)
+U3621	anonymous	2009-1-2 (1)
+U41F2	anonymous	2009-1-2 (1)
+U4659	anonymous	2009-1-2 (1)
+U3B87	anonymous	2009-1-2 (1)
+U4767	anonymous	2009-1-2 (1)
+U4768	anonymous	2009-1-2 (1)
+U4769	anonymous	2009-1-2 (1)
+U35C1	anonymous	2009-1-2 (1)
+U47D7	anonymous	2009-1-2 (1)
+U47D6	anonymous	2009-1-2 (1)
+U47D5	anonymous	2009-1-2 (1)
+U4B2E	anonymous	2009-1-2 (1)
+U4B2F	anonymous	2009-1-2 (1)
+U42EC	anonymous	2009-1-2 (1)
+U4B30	anonymous	2009-1-2 (1)
+U38D4	anonymous	2009-1-2 (1)
+U433F	anonymous	2009-1-2 (1)
+U42EA	anonymous	2009-1-2 (1)
+U4340	anonymous	2009-1-2 (1)
+U4341	anonymous	2009-1-2 (1)
+U412C	anonymous	2009-1-2 (1)
+U412D	anonymous	2009-1-2 (1)
+U412E	anonymous	2009-1-2 (1)
+U3649	anonymous	2009-1-2 (1)
+U364C	anonymous	2009-1-2 (1)
+U3CAA	anonymous	2009-1-2 (1)
+U364E	anonymous	2009-1-2 (1)
+U4D19	anonymous	2009-1-2 (1)
+U4477	anonymous	2009-1-2 (1)
+U4478	anonymous	2009-1-2 (1)
+U3645	anonymous	2009-1-2 (1)
+U4A68	anonymous	2009-1-2 (1)
+U4A6A	anonymous	2009-1-2 (1)
+U4A69	anonymous	2009-1-2 (1)
+U3A3C	anonymous	2009-1-2 (1)
+U4B72	anonymous	2009-1-2 (1)
+U4AD0	anonymous	2009-1-2 (1)
+U4021	anonymous	2009-1-2 (1)
+U38DA	anonymous	2009-1-2 (1)
+U4AD1	anonymous	2009-1-2 (1)
+U38DB	anonymous	2009-1-2 (1)
+U8441	anonymous	2009-1-2 (1)
+U49DD	anonymous	2009-1-2 (1)
+U4AD2	anonymous	2009-1-2 (1)
+U844A	anonymous	2009-1-2 (1)
+U4739	anonymous	2009-1-2 (1)
+U473A	anonymous	2009-1-2 (1)
+U473B	anonymous	2009-1-2 (1)
+U3A0A	anonymous	2009-1-2 (1)
+U3CBF	anonymous	2009-1-2 (1)
+U35C6	anonymous	2009-1-2 (1)
+U7C46	anonymous	2009-1-2 (1)
+U49DE	anonymous	2009-1-2 (1)
+U3E96	anonymous	2009-1-2 (1)
+U36F6	anonymous	2009-1-2 (1)
+U7C5E	anonymous	2009-1-2 (1)
+U486C	anonymous	2009-1-2 (1)
+U39A5	anonymous	2009-1-2 (1)
+U8504	anonymous	2009-1-2 (1)
+U3F56	anonymous	2009-1-2 (1)
+U7C61	anonymous	2009-1-2 (1)
+U3AD3	anonymous	2009-1-2 (1)
+U3DF0	anonymous	2009-1-2 (1)
+U4A76	anonymous	2009-1-2 (1)
+U4A77	anonymous	2009-1-2 (1)
+U8464	anonymous	2009-1-2 (1)
+U81A5	anonymous	2009-1-2 (1)
+U49BB	anonymous	2009-1-2 (1)
+U49BC	anonymous	2009-1-2 (1)
+U81F1	anonymous	2009-1-2 (1)
+U9B09	anonymous	2009-1-2 (1)
+U3EFB	anonymous	2009-1-2 (1)
+U3EFC	anonymous	2009-1-2 (1)
+U8416	anonymous	2009-1-2 (1)
+U3B59	anonymous	2009-1-2 (1)
+U3B5A	anonymous	2009-1-2 (1)
+U5B42	anonymous	2009-1-2 (1)
+U5930	anonymous	2009-1-2 (1)
+U41EA	anonymous	2009-1-2 (1)
+U5BB2	anonymous	2009-1-2 (1)
+U3AEE	anonymous	2009-1-2 (1)
+U347A	anonymous	2009-1-2 (1)
+U69BA	anonymous	2009-1-2 (1)
+U4A78	anonymous	2009-1-2 (1)
+U43EA	anonymous	2009-1-2 (1)
+U3DBC	anonymous	2009-1-2 (1)
+U9B1C	anonymous	2009-1-2 (1)
+U3DBD	anonymous	2009-1-2 (1)
+U3622	anonymous	2009-1-2 (1)
+U491B	anonymous	2009-1-2 (1)
+U9B21	anonymous	2009-1-2 (1)
+U3F92	anonymous	2009-1-2 (1)
+U3FFD	anonymous	2009-1-2 (1)
+U491D	anonymous	2009-1-2 (1)
+U9B26	anonymous	2009-1-2 (1)
+U3A59	anonymous	2009-1-2 (1)
+U3741	anonymous	2009-1-2 (1)
+U43EB	anonymous	2009-1-2 (1)
+U4B2B	anonymous	2009-1-2 (1)
+U3D0F	anonymous	2009-1-2 (1)
+U4B2C	anonymous	2009-1-2 (1)
+U3574	anonymous	2009-1-2 (1)
+U4B2D	anonymous	2009-1-2 (1)
+U3DF6	anonymous	2009-1-2 (1)
+U377C	anonymous	2009-1-2 (1)
+U4A91	anonymous	2009-1-2 (1)
+U3EEF	anonymous	2009-1-2 (1)
+U4A92	anonymous	2009-1-2 (1)
+U4A93	anonymous	2009-1-2 (1)
+U377D	anonymous	2009-1-2 (1)
+U377E	anonymous	2009-1-2 (1)
+U5BDA	anonymous	2009-1-2 (1)
+U4BB2	anonymous	2009-1-2 (1)
+U4BB3	anonymous	2009-1-2 (1)
+U4CD2	anonymous	2009-1-2 (1)
+U483B	anonymous	2009-1-2 (1)
+U5BF4	anonymous	2009-1-2 (1)
+U3F66	anonymous	2009-1-2 (1)
+U47E0	anonymous	2009-1-2 (1)
+U3F6B	anonymous	2009-1-2 (1)
+U47E1	anonymous	2009-1-2 (1)
+U47E2	anonymous	2009-1-2 (1)
+U4000	lsz	2009-1-2 (1)
+U3F6E	anonymous	2009-1-2 (1)
+U3819	anonymous	2009-1-2 (1)
+U36CF	anonymous	2009-1-2 (1)
+U36D1	anonymous	2009-1-2 (1)
+U366F	anonymous	2009-1-2 (1)
+U36D5	anonymous	2009-1-2 (1)
+U420E	anonymous	2009-1-2 (1)
+U4210	anonymous	2009-1-2 (1)
+U3DA5	anonymous	2009-1-2 (1)
+U3DA4	anonymous	2009-1-2 (1)
+U4095	anonymous	2009-1-2 (1)
+U3B65	anonymous	2009-1-2 (1)
+U3B66	anonymous	2009-1-2 (1)
+U4CA4	anonymous	2009-1-2 (1)
+U3B67	anonymous	2009-1-2 (1)
+U5BF7	anonymous	2009-1-2 (1)
+U4E02	anonymous	2009-1-2 (1)
+U7212	anonymous	2009-1-2 (1)
+U4147	anonymous	2009-1-2 (1)
+U4148	anonymous	2009-1-2 (1)
+U3598	anonymous	2009-1-2 (1)
+U414B	anonymous	2009-1-2 (1)
+U405D	anonymous	2009-1-2 (1)
+U4BA0	anonymous	2009-1-2 (1)
+U40D5	anonymous	2009-1-2 (1)
+U3E8C	anonymous	2009-1-2 (1)
+U46C3	anonymous	2009-1-2 (1)
+U3AB0	anonymous	2009-1-2 (1)
+U4D80	anonymous	2009-1-2 (1)
+U3A3A	anonymous	2009-1-2 (1)
+U46B9	anonymous	2009-1-2 (1)
+U3C97	anonymous	2009-1-2 (1)
+U46BA	anonymous	2009-1-2 (1)
+U3C98	anonymous	2009-1-2 (1)
+U41D7	anonymous	2009-1-2 (1)
+U49E2	anonymous	2009-1-2 (1)
+U46BB	anonymous	2009-1-2 (1)
+U49E3	anonymous	2009-1-2 (1)
+U49E4	anonymous	2009-1-2 (1)
+U3601	anonymous	2009-1-2 (1)
+U4C02	anonymous	2009-1-2 (1)
+U38DD	anonymous	2009-1-2 (1)
+U4C00	anonymous	2009-1-2 (1)
+U7C62	anonymous	2009-1-2 (1)
+U4B93	anonymous	2009-1-2 (1)
+U485C	anonymous	2009-1-2 (1)
+U4B92	anonymous	2009-1-2 (1)
+U37EC	anonymous	2009-1-2 (1)
+U37ED	anonymous	2009-1-2 (1)
+U4B86	anonymous	2009-1-2 (1)
+U49F1	anonymous	2009-1-2 (1)
+U3980	anonymous	2009-1-2 (1)
+U4804	anonymous	2009-1-2 (1)
+U48B7		2009-1-2 (1)
+U48B8		2009-1-2 (1)
+U4806	anonymous	2009-1-2 (1)
+U3834	anonymous	2009-1-2 (1)
+U3CE5		2009-1-2 (1)
+U3CE3		2009-1-2 (1)
+U3EE8	anonymous	2009-1-2 (1)
+U38DC	anonymous	2009-1-2 (1)
+U3B0D	anonymous	2009-1-2 (1)
+U486D	anonymous	2009-1-2 (1)
+U4940	anonymous	2009-1-2 (1)
+U4A6C		2009-1-2 (1)
+U486E	anonymous	2009-1-2 (1)
+U4878	anonymous	2009-1-2 (1)
+U4BA8	lsz	2009-1-2 (1)
+U4151	anonymous	2009-1-2 (1)
+U414E	anonymous	2009-1-2 (1)
+U4A4F	anonymous	2009-1-2 (1)
+U414F	anonymous	2009-1-2 (1)
+U4394	anonymous	2009-1-2 (1)
+U4A4E	anonymous	2009-1-2 (1)
+U4A4C	anonymous	2009-1-2 (1)
+U4240		2009-1-2 (1)
+U5DFC	anonymous	2009-1-2 (1)
+U4442	lsz	2009-1-2 (1)
+U4BC7	anonymous	2009-1-2 (1)
+U423F		2009-1-2 (1)
+U4396	anonymous	2009-1-2 (1)
+U4C94	anonymous	2009-1-2 (1)
+U4BCB	anonymous	2009-1-2 (1)
+U4C8F	anonymous	2009-1-2 (1)
+U4446	lsz	2009-1-2 (1)
+U436D		2009-1-2 (1)
+U4C90	anonymous	2009-1-2 (1)
+U36F1	anonymous	2009-1-2 (1)
+U436E		2009-1-2 (1)
+U4AB5	anonymous	2009-1-2 (1)
+U4AB6	anonymous	2009-1-2 (1)
+U436E		2009-1-2 (2)
+U4445	lsz	2009-1-2 (1)
+U5547	anonymous	2009-1-2 (1)
+U4B5F	anonymous	2009-1-2 (1)
+U436F		2009-1-2 (1)
+U4B62	anonymous	2009-1-2 (1)
+U4B63	anonymous	2009-1-2 (1)
+U4AB3	anonymous	2009-1-2 (1)
+U407E	anonymous	2009-1-2 (1)
+U43C6		2009-1-2 (1)
+U367F	anonymous	2009-1-2 (1)
+U5515	anonymous	2009-1-2 (1)
+U43D6	anonymous	2009-1-2 (1)
+U43C7		2009-1-2 (1)
+U43C5		2009-1-2 (1)
+U49E5	anonymous	2009-1-2 (1)
+U43D1	anonymous	2009-1-2 (1)
+U4243	anonymous	2009-1-2 (1)
+U49E7	anonymous	2009-1-2 (1)
+U3A3E		2009-1-2 (1)
+U3495	anonymous	2009-1-2 (1)
+U4681	anonymous	2009-1-2 (1)
+U5554	anonymous	2009-1-2 (1)
+U3CEC	anonymous	2009-1-2 (1)
+U40BE		2009-1-2 (1)
+U41F9	anonymous	2009-1-2 (1)
+U3CEE	anonymous	2009-1-2 (1)
+U41FA	anonymous	2009-1-2 (1)
+U6F65	anonymous	2009-1-2 (1)
+U40C2		2009-1-2 (1)
+U40C0		2009-1-2 (1)
+U3C3A	anonymous	2009-1-2 (1)
+U3775	anonymous	2009-1-2 (1)
+U3C39	anonymous	2009-1-2 (1)
+U432C	anonymous	2009-1-2 (1)
+U7C68	anonymous	2009-1-2 (1)
+U3B23	anonymous	2009-1-2 (1)
+U7C6D	anonymous	2009-1-2 (1)
+U4370	anonymous	2009-1-2 (1)
+U4375	anonymous	2009-1-2 (1)
+U4379	anonymous	2009-1-2 (1)
+U3C3B	anonymous	2009-1-2 (1)
+U8573	anonymous	2009-1-2 (1)
+U40B4	anonymous	2009-1-2 (1)
+U3CF0	anonymous	2009-1-2 (1)
+U40B6	anonymous	2009-1-2 (1)
+U36F2	anonymous	2009-1-2 (1)
+U357D	anonymous	2009-1-2 (1)
+U4770	anonymous	2009-1-2 (1)
+U3746	anonymous	2009-1-2 (1)
+U4046	anonymous	2009-1-2 (1)
+U3E46	anonymous	2009-1-2 (1)
+U3BBC	anonymous	2009-1-2 (1)
+U3CB0	anonymous	2009-1-2 (1)
+U3BBB	anonymous	2009-1-2 (1)
+U85D4	anonymous	2009-1-2 (1)
+U85D6	anonymous	2009-1-2 (1)
+U4704	anonymous	2009-1-2 (1)
+U470A	anonymous	2009-1-2 (1)
+U47BE	anonymous	2009-1-2 (1)
+U370E	anonymous	2009-1-2 (1)
+U4C78	anonymous	2009-1-2 (1)
+U4C7C	anonymous	2009-1-2 (1)
+U46E3	anonymous	2009-1-2 (1)
+U3B37	anonymous	2009-1-2 (1)
+U3D77	anonymous	2009-1-2 (1)
+U3B38	anonymous	2009-1-2 (1)
+U36B5	anonymous	2009-1-2 (1)
+U39E6	anonymous	2009-1-2 (1)
+U3E9E	anonymous	2009-1-2 (1)
+U3E9F	anonymous	2009-1-2 (1)
+U3934	anonymous	2009-1-2 (1)
+U497A	anonymous	2009-1-2 (1)
+U497B	anonymous	2009-1-2 (1)
+U497D	anonymous	2009-1-2 (1)
+U43BF	anonymous	2009-1-2 (1)
+U43C0	anonymous	2009-1-2 (1)
+U34EE	anonymous	2009-1-2 (1)
+U34EF	anonymous	2009-1-2 (1)
+U42F9	anonymous	2009-1-2 (1)
+U7C70	anonymous	2009-1-2 (1)
+U43C9	anonymous	2009-1-2 (1)
+U43CA	anonymous	2009-1-2 (1)
+U3D82	anonymous	2009-1-2 (1)
+U5DCE	anonymous	2009-1-2 (1)
+U5DCE	anonymous	2009-1-2 (2)
+U5DCE	anonymous	2009-1-2 (3)
+U3D83	anonymous	2009-1-2 (1)
+U3D84	anonymous	2009-1-2 (1)
+U38E8	anonymous	2009-1-2 (1)
+U34BF	anonymous	2009-1-2 (1)
+U4A5D	anonymous	2009-1-2 (1)
+U4A5E	anonymous	2009-1-2 (1)
+U4A6B	anonymous	2009-1-2 (1)
+U3992	anonymous	2009-1-2 (1)
+U3993	anonymous	2009-1-2 (1)
+U3EEA	anonymous	2009-1-2 (1)
+U3EEB	anonymous	2009-1-2 (1)
+U3EEC	anonymous	2009-1-2 (1)
+U4C07	anonymous	2009-1-2 (1)
+U442E	anonymous	2009-1-2 (1)
+U4BF1	anonymous	2009-1-2 (1)
+U4611	anonymous	2009-1-2 (1)
+U4612	anonymous	2009-1-2 (1)
+U4613	anonymous	2009-1-2 (1)
+U4805	anonymous	2009-1-2 (1)
+U4807	anonymous	2009-1-2 (1)
+U4808	anonymous	2009-1-2 (1)
+U38E1	anonymous	2009-1-2 (1)
+U38E4	anonymous	2009-1-2 (1)
+U38E5	anonymous	2009-1-2 (1)
+U4A84	anonymous	2009-1-2 (1)
+U3476	emittime	2009-1-2 (1)
+U3764	emittime	2009-1-2 (1)
+U4DAB	emittime	2009-1-2 (1)
+U3D19	emittime	2009-1-2 (1)
+U3D1A	emittime	2009-1-2 (1)
+U3D1B	emittime	2009-1-2 (1)
+U3EDC	anonymous	2009-1-2 (1)
+U349A	emittime	2009-1-2 (1)
+U3484	anonymous	2009-1-2 (1)
+U349C	emittime	2009-1-2 (1)
+U3937	anonymous	2009-1-2 (1)
+U3E66	emittime	2009-1-2 (1)
+U3939	anonymous	2009-1-2 (1)
+U3E77	emittime	2009-1-2 (1)
+U3A55	anonymous	2009-1-2 (1)
+U3A56	anonymous	2009-1-2 (1)
+U468B	anonymous	2009-1-2 (1)
+U474F	anonymous	2009-1-2 (1)
+U391E	anonymous	2009-1-2 (1)
+U4403	anonymous	2009-1-2 (1)
+U4C9B	anonymous	2009-1-2 (1)
+U3644	anonymous	2009-1-2 (1)
+U3643	anonymous	2009-1-2 (1)
+U3642	anonymous	2009-1-2 (1)
+U49C7	anonymous	2009-1-2 (1)
+U49DF	anonymous	2009-1-2 (1)
+U3B29	anonymous	2009-1-2 (1)
+U6F42	FangQ	2009-1-2 (1)
+U4624	anonymous	2009-1-2 (1)
+U4627	anonymous	2009-1-2 (1)
+U37C8	anonymous	2009-1-2 (1)
+U4BB4	anonymous	2009-1-2 (1)
+U4BB5	anonymous	2009-1-2 (1)
+U485D	anonymous	2009-1-2 (1)
+U44CA	lsz	2009-1-2 (1)
+U374A	anonymous	2009-1-2 (1)
+U5DEC	anonymous	2009-1-2 (1)
+U61BD	anonymous	2009-1-2 (1)
+U3E82	anonymous	2009-1-2 (1)
+U61BD	anonymous	2009-1-2 (2)
+U3E84	anonymous	2009-1-2 (1)
+U61BD	anonymous	2009-1-2 (3)
+U61BD	anonymous	2009-1-2 (4)
+U36A9	lsz	2009-1-2 (1)
+U36AE	lsz	2009-1-2 (1)
+U36AF	lsz	2009-1-2 (1)
+U3903	anonymous	2009-1-2 (1)
+U3BBE	lsz	2009-1-2 (1)
+U4BCD	anonymous	2009-1-2 (1)
+U3BC0	lsz	2009-1-2 (1)
+U4BCF	anonymous	2009-1-2 (1)
+U3BBF	lsz	2009-1-2 (1)
+U477C	anonymous	2009-1-2 (1)
+U39BE	lsz	2009-1-2 (1)
+U39BF	lsz	2009-1-2 (1)
+U4A7F	anonymous	2009-1-2 (1)
+U47B6	lsz	2009-1-2 (1)
+U4786	anonymous	2009-1-2 (1)
+U9B5E	anonymous	2009-1-2 (1)
+U4A2D	anonymous	2009-1-2 (1)
+U38B9	lsz	2009-1-2 (1)
+U4E20	anonymous	2009-1-2 (1)
+U4A2F	anonymous	2009-1-2 (1)
+U7606	anonymous	2009-1-2 (1)
+U40C3		2009-1-2 (1)
+U3B58	anonymous	2009-1-2 (1)
+U3B5D	anonymous	2009-1-2 (1)
+U463C	anonymous	2009-1-2 (1)
+U463E	anonymous	2009-1-2 (1)
+U463D	anonymous	2009-1-2 (1)
+U40A7	anonymous	2009-1-2 (1)
+U40A8	anonymous	2009-1-2 (1)
+U34A5	anonymous	2009-1-2 (1)
+U7602	anonymous	2009-1-3 (1)
+U7655	anonymous	2009-1-3 (1)
+U355C	anonymous	2009-1-3 (1)
+U3EBE	anonymous	2009-1-3 (1)
+U7666	anonymous	2009-1-3 (1)
+U355E	anonymous	2009-1-3 (1)
+U760E	anonymous	2009-1-3 (1)
+U4C4C	anonymous	2009-1-3 (1)
+U762C	anonymous	2009-1-3 (1)
+U5C00	anonymous	2009-1-3 (1)
+U4CB4	anonymous	2009-1-3 (1)
+U47E8	anonymous	2009-1-3 (1)
+U881E	anonymous	2009-1-3 (1)
+U4C4C	anonymous	2009-1-3 (2)
+U411B	anonymous	2009-1-3 (1)
+U4894	pem	2009-1-3 (1)
+U411C	anonymous	2009-1-3 (1)
+U4812	pem	2009-1-3 (1)
+U46CA	anonymous	2009-1-3 (1)
+U40EE	anonymous	2009-1-3 (1)
+U39C5	anonymous	2009-1-3 (1)
+U4BCE	anonymous	2009-1-3 (1)
+U4C39	anonymous	2009-1-3 (1)
+U762E	anonymous	2009-1-3 (1)
+U4C3A	anonymous	2009-1-3 (1)
+U4C3B	anonymous	2009-1-3 (1)
+U3F3A	anonymous	2009-1-3 (1)
+U391B	anonymous	2009-1-3 (1)
+U3AB8	anonymous	2009-1-3 (1)
+U7636	anonymous	2009-1-3 (1)
+U3EA2	anonymous	2009-1-3 (1)
+U764A	anonymous	2009-1-3 (1)
+U4A6E	anonymous	2009-1-3 (1)
+U651A	anonymous	2009-1-3 (1)
+U4A6F	anonymous	2009-1-3 (1)
+U3CBD	anonymous	2009-1-3 (1)
+U3CBE	anonymous	2009-1-3 (1)
+U4097	anonymous	2009-1-3 (1)
+U4098	anonymous	2009-1-3 (1)
+U4086	anonymous	2009-1-3 (1)
+U4141	anonymous	2009-1-3 (1)
+U49E0	anonymous	2009-1-3 (1)
+U49E1	anonymous	2009-1-3 (1)
+U4142	anonymous	2009-1-3 (1)
+U35F0	anonymous	2009-1-3 (1)
+U4BBA	anonymous	2009-1-3 (1)
+U35F1	anonymous	2009-1-3 (1)
+U3E1F	anonymous	2009-1-3 (1)
+U35F2	anonymous	2009-1-3 (1)
+U3492	anonymous	2009-1-3 (1)
+U3493	anonymous	2009-1-3 (1)
+U3E20	anonymous	2009-1-3 (1)
+U3494	anonymous	2009-1-3 (1)
+U4D4A	anonymous	2009-1-3 (1)
+U365C	anonymous	2009-1-3 (1)
+U3662	anonymous	2009-1-3 (1)
+U3E1E	anonymous	2009-1-3 (1)
+U6F79	anonymous	2009-1-3 (1)
+U3435	anonymous	2009-1-3 (1)
+U365D	anonymous	2009-1-3 (1)
+U43D2	anonymous	2009-1-3 (1)
+U497E	anonymous	2009-1-3 (1)
+U3CC0	anonymous	2009-1-3 (1)
+U40A1	anonymous	2009-1-3 (1)
+U40A3	anonymous	2009-1-3 (1)
+U497F	anonymous	2009-1-3 (1)
+U4617	anonymous	2009-1-3 (1)
+U40A4	anonymous	2009-1-3 (1)
+U4980	anonymous	2009-1-3 (1)
+U427D	anonymous	2009-1-3 (1)
+U382E	anonymous	2009-1-3 (1)
+U4419	anonymous	2009-1-3 (1)
+U441A	anonymous	2009-1-3 (1)
+U427E	anonymous	2009-1-3 (1)
+U4A72	anonymous	2009-1-3 (1)
+U427F	anonymous	2009-1-3 (1)
+U43C1	anonymous	2009-1-3 (1)
+U4615	anonymous	2009-1-3 (1)
+U43C1	anonymous	2009-1-3 (2)
+U3700	anonymous	2009-1-3 (1)
+U3761	anonymous	2009-1-3 (1)
+U3C76	anonymous	2009-1-3 (1)
+U3442	anonymous	2009-1-3 (1)
+U3C78	anonymous	2009-1-3 (1)
+U3442	anonymous	2009-1-3 (2)
+U3444	anonymous	2009-1-3 (1)
+U3BA3	anonymous	2009-1-3 (1)
+U3CC8	anonymous	2009-1-3 (1)
+U3762	anonymous	2009-1-3 (1)
+U3CC9	anonymous	2009-1-3 (1)
+U65DC	wanghong	2009-1-3 (1)
+U38F6	anonymous	2009-1-3 (1)
+U65DC	wanghong	2009-1-3 (2)
+U38F7	anonymous	2009-1-3 (1)
+U3763	anonymous	2009-1-3 (1)
+U4A0F	anonymous	2009-1-3 (1)
+U34FC	anonymous	2009-1-3 (1)
+U4322	anonymous	2009-1-3 (1)
+U4B42	anonymous	2009-1-3 (1)
+U4324	anonymous	2009-1-3 (1)
+U43F3	anonymous	2009-1-3 (1)
+U65DC	wanghong	2009-1-3 (3)
+U4B7F	anonymous	2009-1-3 (1)
+U347F	anonymous	2009-1-3 (1)
+U3480	anonymous	2009-1-3 (1)
+U4921	anonymous	2009-1-3 (1)
+U4925	anonymous	2009-1-3 (1)
+U39F8	anonymous	2009-1-3 (1)
+U42B1	anonymous	2009-1-3 (1)
+U42B3	anonymous	2009-1-3 (1)
+U375F	anonymous	2009-1-3 (1)
+U4772	anonymous	2009-1-3 (1)
+U39FD	anonymous	2009-1-3 (1)
+U4A83	anonymous	2009-1-3 (1)
+U3760	anonymous	2009-1-3 (1)
+U4A85	anonymous	2009-1-3 (1)
+U483C	anonymous	2009-1-3 (1)
+U483D	anonymous	2009-1-3 (1)
+U8140	wanghong	2009-1-3 (1)
+U3765	anonymous	2009-1-3 (1)
+U4157	anonymous	2009-1-3 (1)
+U3D62	anonymous	2009-1-3 (1)
+U4152	anonymous	2009-1-3 (1)
+U4788	anonymous	2009-1-3 (1)
+U45C7	anonymous	2009-1-3 (1)
+U4454	anonymous	2009-1-3 (1)
+U936F	wanghong	2009-1-3 (1)
+U4329	anonymous	2009-1-3 (1)
+U3ED1	anonymous	2009-1-3 (1)
+U3ED2	anonymous	2009-1-3 (1)
+U3B51	anonymous	2009-1-3 (1)
+U3606	anonymous	2009-1-3 (1)
+U36D6	anonymous	2009-1-3 (1)
+U36D7	anonymous	2009-1-3 (1)
+U4C6E	anonymous	2009-1-3 (1)
+U36D8	anonymous	2009-1-3 (1)
+U407D	anonymous	2009-1-3 (1)
+U49BE	anonymous	2009-1-3 (1)
+U49C0	anonymous	2009-1-3 (1)
+U49C1	anonymous	2009-1-3 (1)
+U4793	anonymous	2009-1-3 (1)
+U4818	anonymous	2009-1-3 (1)
+U4C6F	anonymous	2009-1-3 (1)
+U481B	anonymous	2009-1-3 (1)
+U3F0A	anonymous	2009-1-3 (1)
+U4011	anonymous	2009-1-3 (1)
+U4012	anonymous	2009-1-3 (1)
+U35FF	anonymous	2009-1-3 (1)
+U42CC	anonymous	2009-1-3 (1)
+U42CD	anonymous	2009-1-3 (1)
+U42D1	anonymous	2009-1-3 (1)
+U3DA7	anonymous	2009-1-3 (1)
+U4BDB	anonymous	2009-1-3 (1)
+U3600	anonymous	2009-1-3 (1)
+U3DA9	anonymous	2009-1-3 (1)
+U3EEE	anonymous	2009-1-3 (1)
+U3603	anonymous	2009-1-3 (1)
+U3EF2	anonymous	2009-1-3 (1)
+U4BDF	anonymous	2009-1-3 (1)
+U460E	anonymous	2009-1-3 (1)
+U42D4	anonymous	2009-1-3 (1)
+U3A94	anonymous	2009-1-3 (1)
+U42D4	anonymous	2009-1-3 (2)
+U4614	anonymous	2009-1-3 (1)
+U3DAD	anonymous	2009-1-3 (1)
+U3DAF	anonymous	2009-1-3 (1)
+U45FE	anonymous	2009-1-3 (1)
+U45FF	anonymous	2009-1-3 (1)
+U4B27	anonymous	2009-1-3 (1)
+U4616	anonymous	2009-1-3 (1)
+U3A72	anonymous	2009-1-3 (1)
+U46ED	anonymous	2009-1-3 (1)
+U4A86	anonymous	2009-1-3 (1)
+U3A75	anonymous	2009-1-3 (1)
+U4A88	anonymous	2009-1-3 (1)
+U3A76	anonymous	2009-1-3 (1)
+U4A87	anonymous	2009-1-3 (1)
+U3E78	anonymous	2009-1-3 (1)
+U3E7A	anonymous	2009-1-3 (1)
+U37AC	anonymous	2009-1-3 (1)
+U3EAF	anonymous	2009-1-3 (1)
+U4D4B	anonymous	2009-1-3 (1)
+U764B		2009-1-3 (1)
+U3EB0	anonymous	2009-1-3 (1)
+U4D4C	anonymous	2009-1-3 (1)
+U3FC5	anonymous	2009-1-3 (1)
+U4D4D	anonymous	2009-1-3 (1)
+U37B1	anonymous	2009-1-3 (1)
+U3FE3	anonymous	2009-1-3 (1)
+U3FE4	anonymous	2009-1-3 (1)
+U3CE9	anonymous	2009-1-3 (1)
+U4045	anonymous	2009-1-3 (1)
+U4044	anonymous	2009-1-3 (1)
+U3824	anonymous	2009-1-3 (1)
+U4AD4	anonymous	2009-1-3 (1)
+U4043	anonymous	2009-1-3 (1)
+U5559		2009-1-3 (1)
+U4AD7	anonymous	2009-1-3 (1)
+U3825	anonymous	2009-1-3 (1)
+U3826	anonymous	2009-1-3 (1)
+U4AD8	anonymous	2009-1-3 (1)
+U477D	anonymous	2009-1-3 (2)
+U3CE6	anonymous	2009-1-3 (1)
+U477D	anonymous	2009-1-3 (3)
+U4726	anonymous	2009-1-3 (1)
+U4288	anonymous	2009-1-3 (1)
+U37C7	anonymous	2009-1-3 (1)
+U48CD	anonymous	2009-1-3 (1)
+U428E	anonymous	2009-1-3 (1)
+U3582	anonymous	2009-1-3 (1)
+U594D		2009-1-3 (1)
+U3584	anonymous	2009-1-3 (1)
+U43F4	anonymous	2009-1-3 (1)
+U43F5	anonymous	2009-1-3 (1)
+U38AC	anonymous	2009-1-3 (1)
+U427B	anonymous	2009-1-3 (1)
+U38AD	anonymous	2009-1-3 (1)
+U427C	anonymous	2009-1-3 (1)
+U38AF	anonymous	2009-1-3 (1)
+U3583	anonymous	2009-1-3 (1)
+U4A8C	anonymous	2009-1-3 (1)
+U3588	anonymous	2009-1-3 (1)
+U3583	anonymous	2009-1-3 (2)
+U35CF	anonymous	2009-1-3 (1)
+U4A97	anonymous	2009-1-3 (1)
+U35D0	anonymous	2009-1-3 (1)
+U35D1	anonymous	2009-1-3 (1)
+U4A98	anonymous	2009-1-3 (1)
+U46D6	anonymous	2009-1-3 (1)
+U4A99	anonymous	2009-1-3 (1)
+U46D8	anonymous	2009-1-3 (1)
+U448E	anonymous	2009-1-3 (1)
+U448F	anonymous	2009-1-3 (1)
+U4490	anonymous	2009-1-3 (1)
+U3C80	anonymous	2009-1-3 (1)
+U41FF	anonymous	2009-1-3 (1)
+U41FF	anonymous	2009-1-3 (2)
+U41B4	lsz	2009-1-3 (1)
+U41B6	lsz	2009-1-3 (1)
+U41B5	lsz	2009-1-3 (1)
+U64EE	anonymous	2009-1-3 (1)
+U64F5	anonymous	2009-1-3 (1)
+U6508	anonymous	2009-1-3 (1)
+U4114	anonymous	2009-1-3 (1)
+U3CD9	anonymous	2009-1-3 (1)
+U3B17	anonymous	2009-1-3 (1)
+U368F	anonymous	2009-1-3 (1)
+U447B	anonymous	2009-1-3 (1)
+U3690	anonymous	2009-1-3 (1)
+U4037	anonymous	2009-1-3 (1)
+U4BBC	anonymous	2009-1-3 (1)
+U4BBE	anonymous	2009-1-3 (1)
+U4BBD	anonymous	2009-1-3 (1)
+U34F1	anonymous	2009-1-3 (1)
+U34F2	anonymous	2009-1-3 (1)
+U3AE5	anonymous	2009-1-3 (1)
+U4734	anonymous	2009-1-3 (1)
+U4734	anonymous	2009-1-3 (2)
+U3D3E	anonymous	2009-1-3 (1)
+U3D3F	anonymous	2009-1-3 (1)
+U7234	anonymous	2009-1-3 (1)
+U7234	anonymous	2009-1-3 (2)
+U4D41	anonymous	2009-1-3 (1)
+U4D42	anonymous	2009-1-3 (1)
+U4D43	anonymous	2009-1-3 (1)
+U3C02	anonymous	2009-1-3 (1)
+U35CB	lsz	2009-1-3 (1)
+U6F9A	anonymous	2009-1-3 (1)
+U3C03	anonymous	2009-1-3 (1)
+U6F68	anonymous	2009-1-3 (1)
+U35C8	lsz	2009-1-3 (1)
+U3C05	anonymous	2009-1-3 (1)
+U3860	anonymous	2009-1-3 (1)
+U49D9	anonymous	2009-1-3 (1)
+U3861	anonymous	2009-1-3 (1)
+U4C48	anonymous	2009-1-3 (1)
+U49E8	anonymous	2009-1-3 (1)
+U45B8	anonymous	2009-1-3 (1)
+U3A3B	anonymous	2009-1-3 (1)
+U4298	anonymous	2009-1-3 (1)
+U38DF	anonymous	2009-1-3 (1)
+U44F4	anonymous	2009-1-3 (1)
+U43FF	anonymous	2009-1-3 (1)
+U38DE	anonymous	2009-1-3 (1)
+U44F5	anonymous	2009-1-3 (1)
+U8203	anonymous	2009-1-3 (1)
+U42F6	anonymous	2009-1-3 (1)
+U4C7E	anonymous	2009-1-3 (1)
+U42F8	anonymous	2009-1-3 (1)
+U44F6	anonymous	2009-1-3 (1)
+U42F7	anonymous	2009-1-3 (1)
+U4C7F	anonymous	2009-1-3 (1)
+U483F	anonymous	2009-1-3 (1)
+U4189	anonymous	2009-1-3 (1)
+U4840	anonymous	2009-1-3 (1)
+U3F2A	anonymous	2009-1-3 (1)
+U34F3	anonymous	2009-1-3 (1)
+U3BF3	anonymous	2009-1-3 (1)
+U3663	anonymous	2009-1-3 (1)
+U3F2D	anonymous	2009-1-3 (1)
+U8227	anonymous	2009-1-3 (1)
+U384E	anonymous	2009-1-3 (1)
+U3664	anonymous	2009-1-3 (1)
+U3665	anonymous	2009-1-3 (1)
+U36D9	anonymous	2009-1-3 (1)
+U3C4C	anonymous	2009-1-3 (1)
+U36DA	anonymous	2009-1-3 (1)
+U384F	anonymous	2009-1-3 (1)
+U8219	anonymous	2009-1-3 (1)
+U35BE	anonymous	2009-1-3 (1)
+U40F4	anonymous	2009-1-3 (1)
+U4C59	anonymous	2009-1-3 (1)
+U40F7	anonymous	2009-1-3 (1)
+U4C68	anonymous	2009-1-3 (1)
+U3C4D	anonymous	2009-1-3 (1)
+U4846	anonymous	2009-1-3 (1)
+U4847	anonymous	2009-1-3 (1)
+U4848	anonymous	2009-1-3 (1)
+U651F	anonymous	2009-1-3 (1)
+U42ED	anonymous	2009-1-3 (1)
+U4893	anonymous	2009-1-3 (1)
+U48FA	anonymous	2009-1-3 (1)
+U46D9	anonymous	2009-1-3 (1)
+U6527	anonymous	2009-1-3 (1)
+U3B9D	anonymous	2009-1-3 (1)
+U4B43	anonymous	2009-1-3 (1)
+U9B36	anonymous	2009-1-3 (1)
+U4B45	anonymous	2009-1-3 (1)
+U42EF	anonymous	2009-1-3 (1)
+U9B57	anonymous	2009-1-3 (1)
+U42F0	anonymous	2009-1-3 (1)
+U487D	anonymous	2009-1-3 (1)
+U3703	anonymous	2009-1-3 (1)
+U5BBC	anonymous	2009-1-3 (1)
+U3708	anonymous	2009-1-3 (1)
+U4393	anonymous	2009-1-3 (1)
+U3F98	anonymous	2009-1-3 (1)
+U4280	anonymous	2009-1-3 (1)
+U3702	anonymous	2009-1-3 (1)
+U65B1	anonymous	2009-1-3 (1)
+U37E1	anonymous	2009-1-3 (1)
+U4395	anonymous	2009-1-3 (1)
+U4281	anonymous	2009-1-3 (1)
+U37E2	anonymous	2009-1-3 (1)
+U37E4	anonymous	2009-1-3 (1)
+U8382	fujianwzh	2009-1-3 (1)
+U65B4	anonymous	2009-1-3 (1)
+U38FF	anonymous	2009-1-3 (1)
+U4D73	anonymous	2009-1-3 (1)
+U42DD	anonymous	2009-1-3 (1)
+U4B94	anonymous	2009-1-3 (1)
+U61C4	anonymous	2009-1-3 (1)
+U4B96	anonymous	2009-1-3 (1)
+U42DA	anonymous	2009-1-3 (1)
+U42DD	anonymous	2009-1-3 (2)
+U4C10	anonymous	2009-1-3 (1)
+U4B95	anonymous	2009-1-3 (1)
+U3E7B	anonymous	2009-1-3 (1)
+U4D74	anonymous	2009-1-3 (1)
+U4C11	anonymous	2009-1-3 (1)
+U3472	anonymous	2009-1-3 (1)
+U4C12	anonymous	2009-1-3 (1)
+U3F4B	anonymous	2009-1-3 (1)
+U412F	anonymous	2009-1-3 (1)
+U3B68	anonymous	2009-1-3 (1)
+U4D75	anonymous	2009-1-3 (1)
+U3F1B	anonymous	2009-1-3 (1)
+U3E64	anonymous	2009-1-3 (1)
+U3B68	anonymous	2009-1-3 (2)
+U3E65	anonymous	2009-1-3 (1)
+U3F1D	anonymous	2009-1-3 (1)
+U3E6C	anonymous	2009-1-3 (1)
+U3B69	anonymous	2009-1-3 (1)
+U34DA	anonymous	2009-1-3 (1)
+U447C	anonymous	2009-1-3 (1)
+U3F1E	anonymous	2009-1-3 (1)
+U34DB	anonymous	2009-1-3 (1)
+U34DE	anonymous	2009-1-3 (1)
+U4735	anonymous	2009-1-3 (1)
+U3B3B	anonymous	2009-1-3 (1)
+U4AF0	anonymous	2009-1-3 (1)
+U4E74	anonymous	2009-1-3 (1)
+U4732	anonymous	2009-1-3 (1)
+U40FE	anonymous	2009-1-3 (1)
+U487A	lsz	2009-1-3 (1)
+U4E6F	anonymous	2009-1-3 (1)
+U83BE	fujianwzh	2009-1-3 (1)
+U4100	anonymous	2009-1-3 (1)
+U3CD8	anonymous	2009-1-3 (1)
+U47A2	anonymous	2009-1-3 (1)
+U487C	lsz	2009-1-3 (1)
+U4AF1	anonymous	2009-1-3 (1)
+U47A3	anonymous	2009-1-3 (1)
+U47A4	anonymous	2009-1-3 (1)
+U48CA	anonymous	2009-1-3 (1)
+U4AF2	anonymous	2009-1-3 (1)
+U4B64	anonymous	2009-1-3 (1)
+U36DB	anonymous	2009-1-3 (1)
+U3A71	anonymous	2009-1-3 (1)
+U4B9E	anonymous	2009-1-3 (1)
+U443B	anonymous	2009-1-3 (1)
+U49E9	anonymous	2009-1-3 (1)
+U4638	anonymous	2009-1-3 (1)
+U43D7	anonymous	2009-1-3 (1)
+U83D2	anonymous	2009-1-3 (1)
+U34F5	anonymous	2009-1-3 (1)
+U34F6	anonymous	2009-1-3 (1)
+U3774	anonymous	2009-1-3 (1)
+U4955	anonymous	2009-1-3 (1)
+U4C69	anonymous	2009-1-3 (1)
+U492D	anonymous	2009-1-3 (1)
+U3C9D	anonymous	2009-1-3 (1)
+U659A	anonymous	2009-1-3 (1)
+U4C6A	anonymous	2009-1-3 (1)
+U492E	anonymous	2009-1-3 (1)
+U3C9F	anonymous	2009-1-3 (1)
+U39D2	anonymous	2009-1-3 (1)
+U3B8D	anonymous	2009-1-3 (1)
+U4849	anonymous	2009-1-3 (1)
+U83BB	anonymous	2009-1-3 (1)
+U83BB	anonymous	2009-1-3 (2)
+U83E6	anonymous	2009-1-3 (1)
+U44E2	anonymous	2009-1-3 (1)
+U38D9	anonymous	2009-1-3 (1)
+U3C38	anonymous	2009-1-3 (1)
+U485E	anonymous	2009-1-3 (1)
+U7221	anonymous	2009-1-3 (1)
+U4864	anonymous	2009-1-3 (1)
+U4866	anonymous	2009-1-3 (1)
+U42D7	anonymous	2009-1-3 (1)
+U3F60	anonymous	2009-1-3 (1)
+U3A57	anonymous	2009-1-3 (1)
+U3A58	anonymous	2009-1-3 (1)
+U3A5A	anonymous	2009-1-3 (1)
+U46E4	anonymous	2009-1-3 (1)
+U3D4E	anonymous	2009-1-3 (1)
+U4C6B	anonymous	2009-1-3 (1)
+U49C5	anonymous	2009-1-3 (1)
+U3788	emittime	2009-1-3 (1)
+U49C6	anonymous	2009-1-3 (1)
+U4C6D	anonymous	2009-1-3 (1)
+U3C55	anonymous	2009-1-3 (1)
+U4C73	anonymous	2009-1-3 (1)
+U3AF5	emittime	2009-1-3 (1)
+U43C3	anonymous	2009-1-3 (1)
+U4C73	anonymous	2009-1-3 (2)
+U3B45	anonymous	2009-1-3 (1)
+U3818	emittime	2009-1-3 (1)
+U4AD9	anonymous	2009-1-3 (1)
+U4336	anonymous	2009-1-3 (1)
+U4ADA	anonymous	2009-1-3 (1)
+U3BCE	anonymous	2009-1-3 (1)
+U381A	emittime	2009-1-3 (1)
+U8402	anonymous	2009-1-3 (1)
+U3F19	anonymous	2009-1-3 (1)
+U4ADB	anonymous	2009-1-3 (1)
+U8408	emittime	2009-1-3 (1)
+U3F1A	anonymous	2009-1-3 (1)
+U3979	anonymous	2009-1-3 (1)
+U47E3	anonymous	2009-1-3 (1)
+U47E4	anonymous	2009-1-3 (1)
+U3F1F	anonymous	2009-1-3 (1)
+U4112	anonymous	2009-1-3 (1)
+U4385	anonymous	2009-1-3 (1)
+U8402	anonymous	2009-1-3 (2)
+U3978	anonymous	2009-1-3 (1)
+U47E5	anonymous	2009-1-3 (1)
+U3B7C	anonymous	2009-1-3 (1)
+U4384	anonymous	2009-1-3 (1)
+U42FB	anonymous	2009-1-3 (1)
+U3B7D	anonymous	2009-1-3 (1)
+U47E9	anonymous	2009-1-3 (1)
+U402F	anonymous	2009-1-3 (1)
+U4030	anonymous	2009-1-3 (1)
+U35A4	anonymous	2009-1-3 (1)
+U44E4	anonymous	2009-1-3 (1)
+U3BB6	anonymous	2009-1-3 (1)
+U3AFE	anonymous	2009-1-3 (1)
+U3AFF	anonymous	2009-1-3 (1)
+U887B	anonymous	2009-1-3 (1)
+U46BD	anonymous	2009-1-3 (1)
+U482D	anonymous	2009-1-3 (1)
+U3A86	anonymous	2009-1-3 (1)
+U4AE8	anonymous	2009-1-3 (1)
+U4AE7	anonymous	2009-1-3 (1)
+U4AE6	anonymous	2009-1-3 (1)
+U3C65	anonymous	2009-1-3 (1)
+U3C63	anonymous	2009-1-3 (1)
+U3C64	anonymous	2009-1-3 (1)
+U47EA	anonymous	2009-1-3 (1)
+U4802	lsz	2009-1-3 (1)
+U3A7D	anonymous	2009-1-3 (1)
+U3A7E	anonymous	2009-1-3 (1)
+U4803	lsz	2009-1-3 (1)
+U4845	anonymous	2009-1-3 (1)
+U3A7C	anonymous	2009-1-3 (1)
+U6FEA	emittime	2009-1-3 (1)
+U3C08	anonymous	2009-1-3 (1)
+U4C53	anonymous	2009-1-3 (1)
+U4858	anonymous	2009-1-3 (1)
+U4C7D	anonymous	2009-1-3 (1)
+U4679	anonymous	2009-1-3 (1)
+U39C8	anonymous	2009-1-3 (1)
+U39CC	anonymous	2009-1-3 (1)
+U464C	anonymous	2009-1-3 (1)
+U39F1	anonymous	2009-1-3 (1)
+U4D03	anonymous	2009-1-3 (1)
+U4D04	anonymous	2009-1-3 (1)
+U4651	anonymous	2009-1-3 (1)
+U3A9E	anonymous	2009-1-3 (1)
+U4BB8	lsz	2009-1-3 (1)
+U3A9A	anonymous	2009-1-3 (1)
+U39EE	anonymous	2009-1-3 (1)
+U3B80	anonymous	2009-1-3 (1)
+U3A98	anonymous	2009-1-3 (1)
+U3E92	anonymous	2009-1-3 (1)
+U3E91	anonymous	2009-1-3 (1)
+U3F38	anonymous	2009-1-3 (1)
+U3E90	anonymous	2009-1-3 (1)
+U4BBB	lsz	2009-1-3 (1)
+U4BF8	anonymous	2009-1-3 (1)
+U3577	anonymous	2009-1-3 (1)
+U3576	anonymous	2009-1-3 (1)
+U47A9	anonymous	2009-1-3 (1)
+U8414	emittime	2009-1-3 (1)
+U3E47	anonymous	2009-1-3 (1)
+U39AB	anonymous	2009-1-3 (1)
+U3E49	anonymous	2009-1-3 (1)
+U385A	anonymous	2009-1-3 (1)
+U34C6	anonymous	2009-1-3 (1)
+U385C	anonymous	2009-1-3 (1)
+U385D	anonymous	2009-1-3 (1)
+U4867	anonymous	2009-1-3 (1)
+U3E94	anonymous	2009-1-3 (1)
+U409D	anonymous	2009-1-3 (1)
+U409C	anonymous	2009-1-3 (1)
+U409A	anonymous	2009-1-3 (1)
+U463A	anonymous	2009-1-3 (1)
+U4639	anonymous	2009-1-3 (1)
+U4421	落单的虫子	2009-1-3 (1)
+U463B	anonymous	2009-1-3 (1)
+U3F50	anonymous	2009-1-3 (1)
+U3F4E	anonymous	2009-1-3 (1)
+U8405	anonymous	2009-1-3 (1)
+U49EC	anonymous	2009-1-3 (1)
+U3666	anonymous	2009-1-3 (1)
+U416E	anonymous	2009-1-3 (1)
+U35D8	anonymous	2009-1-3 (1)
+U405F	anonymous	2009-1-3 (1)
+U440E	anonymous	2009-1-3 (1)
+U4411	anonymous	2009-1-3 (1)
+U5DFA	FangQ	2009-1-3 (1)
+U4410	anonymous	2009-1-3 (1)
+U39DC	anonymous	2009-1-3 (1)
+U39DD	anonymous	2009-1-3 (1)
+U5EBB	FangQ	2009-1-3 (1)
+U4C3E	anonymous	2009-1-3 (1)
+U3496	anonymous	2009-1-3 (1)
+U3755	anonymous	2009-1-3 (1)
+U3F3C		2009-1-3 (1)
+U3FE5		2009-1-3 (1)
+U3FE2		2009-1-3 (1)
+U3FE6		2009-1-3 (1)
+U3759	anonymous	2009-1-3 (1)
+U4109		2009-1-3 (1)
+U410A		2009-1-3 (1)
+U4D83		2009-1-3 (1)
+U4D84		2009-1-3 (1)
+U4D82		2009-1-3 (1)
+U4992		2009-1-3 (1)
+U3E44		2009-1-3 (1)
+U3E45		2009-1-3 (1)
+U3525	anonymous	2009-1-3 (1)
+U4024		2009-1-3 (1)
+U3F4D		2009-1-3 (1)
+U4898	anonymous	2009-1-3 (1)
+U43F0		2009-1-3 (1)
+U4753	anonymous	2009-1-3 (1)
+U4752		2009-1-3 (1)
+U4753		2009-1-3 (2)
+U4754	anonymous	2009-1-3 (1)
+U4754		2009-1-3 (2)
+U3C95		2009-1-3 (1)
+U4353	anonymous	2009-1-3 (1)
+U3CA3	anonymous	2009-1-3 (1)
+U4353	anonymous	2009-1-3 (2)
+U3C96		2009-1-3 (1)
+U40FC		2009-1-3 (1)
+U40FD		2009-1-3 (1)
+U4352	anonymous	2009-1-3 (1)
+U3B2D	anonymous	2009-1-3 (1)
+U40FF		2009-1-3 (1)
+U48B6	anonymous	2009-1-3 (1)
+U3542	anonymous	2009-1-3 (1)
+U48B5	anonymous	2009-1-3 (1)
+U47D9	anonymous	2009-1-3 (1)
+U3AB6		2009-1-3 (1)
+U47FA	anonymous	2009-1-3 (1)
+U3CDC		2009-1-3 (1)
+U47FC	anonymous	2009-1-3 (1)
+U3543	anonymous	2009-1-3 (1)
+U3CDD		2009-1-3 (1)
+U47FD	anonymous	2009-1-3 (1)
+U3BE8	anonymous	2009-1-3 (1)
+U3487	anonymous	2009-1-3 (1)
+U4CEB		2009-1-3 (1)
+U4D36	anonymous	2009-1-3 (1)
+U4CC5	anonymous	2009-1-3 (1)
+U4D39	anonymous	2009-1-3 (1)
+U4D38	anonymous	2009-1-3 (1)
+U4A71		2009-1-3 (1)
+U4A79		2009-1-3 (1)
+U65DC	FangQ	2009-1-3 (4)
+U4CC6	anonymous	2009-1-3 (1)
+U3C10	anonymous	2009-1-3 (1)
+U445A		2009-1-3 (1)
+U47EC	anonymous	2009-1-3 (1)
+U47F1	anonymous	2009-1-3 (1)
+U4215		2009-1-3 (1)
+U47F2	anonymous	2009-1-3 (1)
+U4216		2009-1-3 (1)
+U4632	anonymous	2009-1-3 (1)
+U346C	anonymous	2009-1-3 (1)
+U4217		2009-1-3 (1)
+U36DE		2009-1-3 (1)
+U4AB7	anonymous	2009-1-3 (1)
+U36DD		2009-1-3 (1)
+U4664	anonymous	2009-1-3 (1)
+U49C2	anonymous	2009-1-3 (1)
+U36DC		2009-1-3 (1)
+U3A6D	FangQ	2009-1-3 (1)
+U3A6E	FangQ	2009-1-3 (1)
+U46AD		2009-1-3 (1)
+U3B72	anonymous	2009-1-3 (1)
+U46AE		2009-1-3 (1)
+U3C66	anonymous	2009-1-3 (1)
+U46AE		2009-1-3 (2)
+U46AF		2009-1-3 (1)
+U3C6B	anonymous	2009-1-3 (1)
+U3EED	anonymous	2009-1-3 (1)
+U3EF5	anonymous	2009-1-3 (1)
+U403C	anonymous	2009-1-3 (1)
+U4039	anonymous	2009-1-3 (1)
+U4038	anonymous	2009-1-3 (1)
+U39F5	anonymous	2009-1-3 (1)
+U39F6	anonymous	2009-1-3 (1)
+U430A	anonymous	2009-1-3 (1)
+U345D	anonymous	2009-1-3 (1)
+U3465	anonymous	2009-1-3 (1)
+U4479	anonymous	2009-1-3 (1)
+U47ED	anonymous	2009-1-3 (1)
+U841A	anonymous	2009-1-3 (1)
+U5C23	anonymous	2009-1-3 (1)
+U4479	FangQ	2009-1-3 (2)
+U841A	FangQ	2009-1-3 (2)
+U490B	anonymous	2009-1-3 (1)
+U483E	anonymous	2009-1-3 (1)
+U3759	FangQ	2009-1-3 (2)
+U483E	FangQ	2009-1-3 (2)
+U490B	FangQ	2009-1-3 (2)
+U53BA	anonymous	2009-1-3 (1)
+U3465	FangQ	2009-1-3 (2)
+U4352	FangQ	2009-1-3 (2)
+U4353	FangQ	2009-1-3 (3)
+U4353	FangQ	2009-1-3 (4)
+U7602	FangQ	2009-1-3 (2)
+U5C52	anonymous	2009-1-3 (1)
+U5C52	anonymous	2009-1-3 (2)
+U3627	anonymous	2009-1-3 (1)
+U483E	anonymous	2009-1-3 (3)
+U84B3	FangQ	2009-1-3 (1)
+U4E6C	FangQ	2009-1-3 (1)
+U4E6E	FangQ	2009-1-3 (1)
+U5C52	FangQ	2009-1-3 (3)
+U3618	FangQ	2009-1-3 (1)
+U43C8	FangQ	2009-1-3 (1)
+U43C8	FangQ	2009-1-3 (2)
+U43C8	FangQ	2009-1-3 (3)
+U39D8	FangQ	2009-1-3 (1)
+U39D9	FangQ	2009-1-3 (1)
+U39DA	FangQ	2009-1-3 (1)
+U433E	anonymous	2009-1-3 (1)
+U433E	anonymous	2009-1-3 (2)
+U8405	FangQ	2009-1-3 (2)
+U44C1	FangQ	2009-1-3 (1)
+U44C1	FangQ	2009-1-3 (2)
+U4ACB	FangQ	2009-1-3 (1)
+U4A58	FangQ	2009-1-3 (1)
+U4A73	FangQ	2009-1-3 (1)
+U4E96	FangQ	2009-1-3 (1)
+U4E35	FangQ	2009-1-3 (1)
+U6A8B	FangQ	2009-1-3 (1)
+U517E	FangQ	2009-1-3 (1)
+U5184	FangQ	2009-1-3 (1)
+U5BBA	FangQ	2009-1-3 (1)
+U621C	FangQ	2009-1-3 (1)
+U84B7	FangQ	2009-1-3 (1)
+U84C3	FangQ	2009-1-3 (1)
+U519A	anonymous	2009-1-3 (1)
+U7073	anonymous	2009-1-3 (1)
+U7077	anonymous	2009-1-3 (1)
+U89FD	anonymous	2009-1-3 (1)
+U452E	anonymous	2009-1-3 (1)
+U5637	anonymous	2009-1-3 (1)
+U61CF	anonymous	2009-1-3 (1)
+U6A70	anonymous	2009-1-3 (1)
+U6AB1	anonymous	2009-1-3 (1)
+U4A11	anonymous	2009-1-3 (1)
+U76EB	anonymous	2009-1-3 (1)
+U536A	anonymous	2009-1-3 (1)
+U61D5	anonymous	2009-1-3 (1)
+U429C	anonymous	2009-1-3 (1)
+U61EF	anonymous	2009-1-3 (1)
+U35C3	anonymous	2009-1-3 (1)
+U595E	anonymous	2009-1-3 (1)
+U8415	anonymous	2009-1-3 (1)
+U393B	anonymous	2009-1-3 (1)
+U841E	anonymous	2009-1-3 (1)
+U4A7A	anonymous	2009-1-3 (1)
+U885F	anonymous	2009-1-3 (1)
+U4A7E	anonymous	2009-1-3 (1)
+U4A82	anonymous	2009-1-3 (1)
+U3AA4	anonymous	2009-1-3 (1)
+U39C2	anonymous	2009-1-3 (1)
+U3AA5	anonymous	2009-1-3 (1)
+U3AA7	anonymous	2009-1-3 (1)
+U42F5	anonymous	2009-1-3 (1)
+U42FA	anonymous	2009-1-3 (1)
+U42FC	anonymous	2009-1-3 (1)
+U447D	anonymous	2009-1-3 (1)
+U3647	anonymous	2009-1-3 (1)
+U4DA6	anonymous	2009-1-3 (1)
+U4DA4	anonymous	2009-1-3 (1)
+U4BE0	anonymous	2009-1-3 (1)
+U4BC0	anonymous	2009-1-3 (1)
+U4BBF	anonymous	2009-1-3 (1)
+U3D1C	anonymous	2009-1-3 (1)
+U6FF9	anonymous	2009-1-3 (1)
+U36DF	anonymous	2009-1-3 (1)
+U36E0	anonymous	2009-1-3 (1)
+U3D2A	anonymous	2009-1-3 (1)
+U4698	anonymous	2009-1-3 (1)
+U45B6	anonymous	2009-1-3 (1)
+U3C1F	feewang	2009-1-3 (1)
+U45B7	anonymous	2009-1-3 (1)
+U475A	anonymous	2009-1-3 (1)
+U4761	anonymous	2009-1-3 (1)
+U3735	anonymous	2009-1-3 (1)
+U475F	anonymous	2009-1-3 (1)
+U3736	anonymous	2009-1-3 (1)
+U3738	anonymous	2009-1-3 (1)
+U6FF9	FangQ	2009-1-3 (2)
+U6FF9	FangQ	2009-1-3 (3)
+U4D9C	anonymous	2009-1-3 (1)
+U3AA4	FangQ	2009-1-3 (2)
+U48FD	feewang	2009-1-3 (1)
+U48FD	feewang	2009-1-3 (2)
+U3BA6	birbird	2009-1-3 (1)
+U3931	birbird	2009-1-3 (1)
+U4DA2	anonymous	2009-1-3 (1)
+U38EE	anonymous	2009-1-3 (1)
+U38ED	anonymous	2009-1-3 (1)
+U3FE7	anonymous	2009-1-3 (1)
+U3FE8	anonymous	2009-1-3 (1)
+U6205	anonymous	2009-1-3 (1)
+U841F	anonymous	2009-1-3 (1)
+U3EB6	anonymous	2009-1-3 (1)
+U3EB7	anonymous	2009-1-3 (1)
+U846A	anonymous	2009-1-3 (1)
+U4481	anonymous	2009-1-3 (1)
+U4482	anonymous	2009-1-3 (1)
+U6ABF	anonymous	2009-1-3 (1)
+U3A8D	anonymous	2009-1-3 (1)
+U3BB4	anonymous	2009-1-3 (1)
+U56BF	anonymous	2009-1-3 (1)
+U9F9E	anonymous	2009-1-3 (1)
+U4CC3	anonymous	2009-1-3 (1)
+U56C4	anonymous	2009-1-3 (1)
+U56D0	anonymous	2009-1-3 (1)
+U3B85	anonymous	2009-1-3 (1)
+U4CC8	anonymous	2009-1-3 (1)
+U56DC	anonymous	2009-1-3 (1)
+U3893	anonymous	2009-1-3 (1)
+U44F3	anonymous	2009-1-3 (1)
+U56BF	anonymous	2009-1-3 (2)
+U5C57	anonymous	2009-1-3 (1)
+U42FF	anonymous	2009-1-3 (1)
+U44F9	anonymous	2009-1-3 (1)
+U6528	anonymous	2009-1-3 (1)
+U6AD5	anonymous	2009-1-3 (1)
+U8472	anonymous	2009-1-3 (1)
+U42FD	anonymous	2009-1-3 (1)
+U43C2	anonymous	2009-1-3 (1)
+U65B5	anonymous	2009-1-3 (1)
+U41A3	anonymous	2009-1-3 (1)
+U4CC0	anonymous	2009-1-3 (1)
+U3B42	anonymous	2009-1-3 (1)
+U3A83	anonymous	2009-1-3 (1)
+U847C	anonymous	2009-1-3 (1)
+U3A82	anonymous	2009-1-3 (1)
+U3A84	anonymous	2009-1-3 (1)
+U6AC9	anonymous	2009-1-3 (1)
+U6AD6	anonymous	2009-1-3 (1)
+U5C5A	anonymous	2009-1-3 (1)
+U6AD7	anonymous	2009-1-3 (1)
+U478F	anonymous	2009-1-3 (1)
+U847F	anonymous	2009-1-3 (1)
+U4E7A	anonymous	2009-1-3 (1)
+U4521	fujiansszx	2009-1-3 (1)
+U4796	anonymous	2009-1-3 (1)
+U4797	anonymous	2009-1-3 (1)
+U4A89	anonymous	2009-1-3 (1)
+U8481	anonymous	2009-1-3 (1)
+U4A2E	anonymous	2009-1-3 (1)
+U49C4	anonymous	2009-1-3 (1)
+U36B0	anonymous	2009-1-3 (1)
+U36B1	anonymous	2009-1-3 (1)
+U4625	anonymous	2009-1-3 (1)
+U4628	anonymous	2009-1-3 (1)
+U4629	anonymous	2009-1-3 (1)
+U4BC3	anonymous	2009-1-3 (1)
+U3F71	anonymous	2009-1-3 (1)
+U346F	anonymous	2009-1-3 (1)
+U3471	anonymous	2009-1-3 (1)
+U4C3C	anonymous	2009-1-3 (1)
+U4C3D	anonymous	2009-1-3 (1)
+U4C3F	anonymous	2009-1-3 (1)
+U4406	anonymous	2009-1-3 (1)
+U5313	anonymous	2009-1-3 (1)
+U6AD8	anonymous	2009-1-3 (1)
+U3E04	anonymous	2009-1-3 (1)
+U6AD8	anonymous	2009-1-3 (2)
+U6AE3	anonymous	2009-1-3 (1)
+U6AE3	anonymous	2009-1-3 (2)
+U3FCB	anonymous	2009-1-3 (1)
+U36C4	anonymous	2009-1-3 (1)
+U85CC	anonymous	2009-1-3 (1)
+U4E7A	FangQ	2009-1-3 (2)
+U85DB	anonymous	2009-1-3 (1)
+U36CB	anonymous	2009-1-3 (1)
+U56DC	FangQ	2009-1-3 (2)
+U4B34	anonymous	2009-1-3 (1)
+U46AF	FangQ	2009-1-3 (2)
+U83BB	FangQ	2009-1-3 (3)
+U48D9	anonymous	2009-1-3 (1)
+U5901	anonymous	2009-1-3 (1)
+U7221	FangQ	2009-1-3 (2)
+U3C9F	FangQ	2009-1-3 (2)
+U44E2	FangQ	2009-1-3 (2)
+U38EF	anonymous	2009-1-3 (1)
+U661A	FangQ	2009-1-3 (1)
+U7233	FangQ	2009-1-4 (1)
+U85E7	anonymous	2009-1-4 (1)
+U45DF	Kardinal	2009-1-4 (1)
+U83D0	anonymous	2009-1-4 (1)
+U3890	Kardinal	2009-1-4 (1)
+U4475	anonymous	2009-1-4 (1)
+U5913	anonymous	2009-1-4 (1)
+U46B7	Kardinal	2009-1-4 (1)
+U340E	anonymous	2009-1-4 (1)
+U340F	anonymous	2009-1-4 (1)
+U3410	anonymous	2009-1-4 (1)
+U4554	Kardinal	2009-1-4 (1)
+U43B9	Kardinal	2009-1-4 (1)
+U43B9	Kardinal	2009-1-4 (2)
+U410F	Kardinal	2009-1-4 (1)
+U37D4	Kardinal	2009-1-4 (1)
+U38F0	anonymous	2009-1-4 (1)
+U39D6	Kardinal	2009-1-4 (1)
+U35AD	anonymous	2009-1-4 (1)
+U41D0	anonymous	2009-1-4 (1)
+U40AE	anonymous	2009-1-4 (1)
+U3E05	Kardinal	2009-1-4 (1)
+U3FB4	Kardinal	2009-1-4 (1)
+U3C8F	anonymous	2009-1-4 (1)
+U8485	anonymous	2009-1-4 (1)
+U3BFD	Kardinal	2009-1-4 (1)
+U4D55	anonymous	2009-1-4 (1)
+U43C4	Kardinal	2009-1-4 (1)
+U4143	anonymous	2009-1-4 (1)
+U4452	Kardinal	2009-1-4 (1)
+U437A	Kardinal	2009-1-4 (1)
+U3FF6	anonymous	2009-1-4 (1)
+U4B77	anonymous	2009-1-4 (1)
+U465A	Kardinal	2009-1-4 (1)
+U6FD9	anonymous	2009-1-4 (1)
+U4CD6	Kardinal	2009-1-4 (1)
+U470B	anonymous	2009-1-4 (1)
+U4C2F	anonymous	2009-1-4 (1)
+U48EB	anonymous	2009-1-4 (1)
+U48EB	anonymous	2009-1-4 (2)
+U8485	anonymous	2009-1-4 (2)
+U48EA	anonymous	2009-1-4 (1)
+U36E1	anonymous	2009-1-4 (1)
+U48E9	anonymous	2009-1-4 (1)
+U35D7	anonymous	2009-1-4 (1)
+U35D6	anonymous	2009-1-4 (1)
+U36E4	anonymous	2009-1-4 (1)
+U35D4	anonymous	2009-1-4 (1)
+U3469	anonymous	2009-1-4 (1)
+U3BF4	anonymous	2009-1-4 (1)
+U3466	anonymous	2009-1-4 (1)
+U4572	anonymous	2009-1-4 (1)
+U8642	anonymous	2009-1-4 (1)
+U6FFD	anonymous	2009-1-4 (1)
+U3C56	anonymous	2009-1-4 (1)
+U3C57	anonymous	2009-1-4 (1)
+U4B97	anonymous	2009-1-4 (1)
+U3B64	anonymous	2009-1-4 (1)
+U3E2E	anonymous	2009-1-4 (1)
+U472C	anonymous	2009-1-4 (1)
+U472C	anonymous	2009-1-4 (2)
+U472C	anonymous	2009-1-4 (3)
+U472C	anonymous	2009-1-4 (4)
+U3B55	anonymous	2009-1-4 (1)
+U4457	anonymous	2009-1-4 (1)
+U6FFD	anonymous	2009-1-4 (2)
+U3983	anonymous	2009-1-4 (1)
+U3648	anonymous	2009-1-4 (1)
+U3646	anonymous	2009-1-4 (1)
+U3ADB	anonymous	2009-1-4 (1)
+U3FFC	anonymous	2009-1-4 (1)
+U4386	anonymous	2009-1-4 (1)
+U3BDE	anonymous	2009-1-4 (1)
+U4301	anonymous	2009-1-4 (1)
+U401A	anonymous	2009-1-4 (1)
+U401B	anonymous	2009-1-4 (1)
+U401C	anonymous	2009-1-4 (1)
+U4408	anonymous	2009-1-4 (1)
+U4AB8	anonymous	2009-1-4 (1)
+U46C4	anonymous	2009-1-4 (1)
+U42FE	anonymous	2009-1-4 (1)
+U8496	anonymous	2009-1-4 (1)
+U8496	anonymous	2009-1-4 (2)
+U85FC	anonymous	2009-1-4 (1)
+U8495	anonymous	2009-1-4 (1)
+U532C	anonymous	2009-1-4 (1)
+U84A3	anonymous	2009-1-4 (1)
+U454C	anonymous	2009-1-4 (1)
+U3723	anonymous	2009-1-4 (1)
+U8610	anonymous	2009-1-4 (1)
+U4E87	anonymous	2009-1-4 (1)
+U3E30	anonymous	2009-1-4 (1)
+U3E31	anonymous	2009-1-4 (1)
+U84A6	anonymous	2009-1-4 (1)
+U3722	anonymous	2009-1-4 (1)
+U3F5B	anonymous	2009-1-4 (1)
+U3F5A	anonymous	2009-1-4 (1)
+U3F59	anonymous	2009-1-4 (1)
+U445B	anonymous	2009-1-4 (1)
+U3CC2	anonymous	2009-1-4 (1)
+U8657	anonymous	2009-1-4 (1)
+U3BD9	anonymous	2009-1-4 (1)
+U387D	anonymous	2009-1-4 (1)
+U47EE	anonymous	2009-1-4 (1)
+U38F1	anonymous	2009-1-4 (1)
+U86E7	anonymous	2009-1-4 (1)
+U4418	anonymous	2009-1-4 (1)
+U372A	anonymous	2009-1-4 (1)
+U6AE9	anonymous	2009-1-4 (1)
+U3BD5	anonymous	2009-1-4 (1)
+U4BD1	anonymous	2009-1-4 (1)
+U480F	anonymous	2009-1-4 (1)
+U848A	anonymous	2009-1-4 (1)
+U3882	anonymous	2009-1-4 (1)
+U3E48	anonymous	2009-1-4 (1)
+U41EC	anonymous	2009-1-4 (1)
+U6AF2	anonymous	2009-1-4 (1)
+U443D	anonymous	2009-1-4 (1)
+U443E	anonymous	2009-1-4 (1)
+U6AFD	anonymous	2009-1-4 (1)
+U443F	anonymous	2009-1-4 (1)
+U38CA	anonymous	2009-1-4 (1)
+U4284	anonymous	2009-1-4 (1)
+U4286	anonymous	2009-1-4 (1)
+U3C54	anonymous	2009-1-4 (1)
+U492C	anonymous	2009-1-4 (1)
+U38BD	anonymous	2009-1-4 (1)
+U5C26	lsz	2009-1-4 (1)
+U5F60	anonymous	2009-1-4 (1)
+U4D76	anonymous	2009-1-4 (1)
+U7008	anonymous	2009-1-4 (1)
+U5C29	lsz	2009-1-4 (1)
+U4D77	anonymous	2009-1-4 (1)
+U7673	anonymous	2009-1-4 (1)
+U3AE8	anonymous	2009-1-4 (1)
+U3766	anonymous	2009-1-4 (1)
+U3C40	anonymous	2009-1-4 (1)
+U3768	anonymous	2009-1-4 (1)
+U4C40	anonymous	2009-1-4 (1)
+U42D2	anonymous	2009-1-4 (1)
+U4C43	anonymous	2009-1-4 (1)
+U4813	anonymous	2009-1-4 (1)
+U4C42	anonymous	2009-1-4 (1)
+U480E	anonymous	2009-1-4 (1)
+U4811	anonymous	2009-1-4 (1)
+U4B41	anonymous	2009-1-4 (1)
+U3A8F	anonymous	2009-1-4 (1)
+U3A91	anonymous	2009-1-4 (1)
+U48E4	anonymous	2009-1-4 (1)
+U3C21	anonymous	2009-1-4 (1)
+U3C21	anonymous	2009-1-4 (2)
+U395A	anonymous	2009-1-4 (1)
+U4450	anonymous	2009-1-4 (1)
+U4B44	anonymous	2009-1-4 (1)
+U3AF6	anonymous	2009-1-4 (1)
+U3AF7	anonymous	2009-1-4 (1)
+U84A5	anonymous	2009-1-4 (1)
+U3A07	anonymous	2009-1-4 (1)
+U3E42	anonymous	2009-1-4 (1)
+U84B5	anonymous	2009-1-4 (1)
+U402E	anonymous	2009-1-4 (1)
+U4031	anonymous	2009-1-4 (1)
+U84D8	anonymous	2009-1-4 (1)
+U39F3	anonymous	2009-1-4 (1)
+U39F9	anonymous	2009-1-4 (1)
+U42D3	anonymous	2009-1-4 (1)
+U42D8	anonymous	2009-1-4 (1)
+U437E	anonymous	2009-1-4 (1)
+U357A	anonymous	2009-1-4 (1)
+U3DF7	anonymous	2009-1-4 (1)
+U84E4	anonymous	2009-1-4 (1)
+U3AE7	anonymous	2009-1-4 (1)
+U357B	anonymous	2009-1-4 (1)
+U4842	anonymous	2009-1-4 (1)
+U84ED	anonymous	2009-1-4 (1)
+U4843	anonymous	2009-1-4 (1)
+U3AE9	anonymous	2009-1-4 (1)
+U3FB2	anonymous	2009-1-4 (1)
+U445C	anonymous	2009-1-4 (1)
+U3F22	anonymous	2009-1-4 (1)
+U84F5	anonymous	2009-1-4 (1)
+U39F7	anonymous	2009-1-4 (1)
+U571D	anonymous	2009-1-4 (1)
+U4BEF	anonymous	2009-1-4 (1)
+U4BF0	anonymous	2009-1-4 (1)
+U362D	anonymous	2009-1-4 (1)
+U84E1	anonymous	2009-1-4 (1)
+U3A5F	yanqian	2009-1-4 (1)
+U4BEE	anonymous	2009-1-4 (1)
+U4C74	anonymous	2009-1-4 (1)
+U430D	anonymous	2009-1-4 (1)
+U4C75	anonymous	2009-1-4 (1)
+U46DC	anonymous	2009-1-4 (1)
+U3C86	lsz	2009-1-4 (1)
+U46E1	anonymous	2009-1-4 (1)
+U430F	anonymous	2009-1-4 (1)
+U3EF3	anonymous	2009-1-4 (1)
+U46DD	anonymous	2009-1-4 (1)
+U3EF6	anonymous	2009-1-4 (1)
+U3EF7	anonymous	2009-1-4 (1)
+U4CA1	anonymous	2009-1-4 (1)
+U3F10	anonymous	2009-1-4 (1)
+U3DA6	anonymous	2009-1-4 (1)
+U3F0F	anonymous	2009-1-4 (1)
+U3A60	anonymous	2009-1-4 (1)
+U3EC5	anonymous	2009-1-4 (1)
+U45C1	anonymous	2009-1-4 (1)
+U41D2	anonymous	2009-1-4 (1)
+U45C4	anonymous	2009-1-4 (1)
+U42BA	anonymous	2009-1-4 (1)
+U45C8	anonymous	2009-1-4 (1)
+U3560	anonymous	2009-1-4 (1)
+U473D	anonymous	2009-1-4 (1)
+U3E08	anonymous	2009-1-4 (1)
+U42C0	anonymous	2009-1-4 (1)
+U473E	anonymous	2009-1-4 (1)
+U42C2	anonymous	2009-1-4 (1)
+U4737	anonymous	2009-1-4 (1)
+U4738	anonymous	2009-1-4 (1)
+U8505	anonymous	2009-1-4 (1)
+U8501	anonymous	2009-1-4 (1)
+U4022	anonymous	2009-1-4 (1)
+U3D5B	anonymous	2009-1-4 (1)
+U4947	anonymous	2009-1-4 (1)
+U5380	anonymous	2009-1-4 (1)
+U41D3	anonymous	2009-1-4 (1)
+U494A	anonymous	2009-1-4 (1)
+U3D1D	anonymous	2009-1-4 (1)
+U42AE	anonymous	2009-1-4 (1)
+U3B02	anonymous	2009-1-4 (1)
+U416F	anonymous	2009-1-4 (1)
+U42AF	anonymous	2009-1-4 (1)
+U3FEC	anonymous	2009-1-4 (1)
+U4170	anonymous	2009-1-4 (1)
+U492B	anonymous	2009-1-4 (1)
+U48EC	anonymous	2009-1-4 (1)
+U4844	anonymous	2009-1-4 (1)
+U45C0	anonymous	2009-1-4 (1)
+U48ED	anonymous	2009-1-4 (1)
+U465F	anonymous	2009-1-4 (1)
+U48EE	anonymous	2009-1-4 (1)
+U4665	anonymous	2009-1-4 (1)
+U39AD	anonymous	2009-1-4 (1)
+U39AC	anonymous	2009-1-4 (1)
+U3DAA	anonymous	2009-1-4 (1)
+U36E2	anonymous	2009-1-4 (1)
+U36E5	anonymous	2009-1-4 (1)
+U3B73	anonymous	2009-1-4 (1)
+U3A3D	anonymous	2009-1-4 (1)
+U45D1	anonymous	2009-1-4 (1)
+U35DA	anonymous	2009-1-4 (1)
+U3B77	anonymous	2009-1-4 (1)
+U3ED3	anonymous	2009-1-4 (1)
+U4D96	anonymous	2009-1-4 (1)
+U3ED6	anonymous	2009-1-4 (1)
+U4D95	anonymous	2009-1-4 (1)
+U4300	anonymous	2009-1-4 (1)
+U40C4	anonymous	2009-1-4 (1)
+U40C5	anonymous	2009-1-4 (1)
+U40C6	anonymous	2009-1-4 (1)
+U39C3	anonymous	2009-1-4 (1)
+U3590	anonymous	2009-1-4 (1)
+U40C7	anonymous	2009-1-4 (1)
+U40C8	anonymous	2009-1-4 (1)
+U45EB	anonymous	2009-1-4 (1)
+U376C	anonymous	2009-1-4 (1)
+U4C55	anonymous	2009-1-4 (1)
+U49F8	anonymous	2009-1-4 (1)
+U4736	anonymous	2009-1-4 (1)
+U3739	anonymous	2009-1-4 (1)
+U3C82	anonymous	2009-1-4 (1)
+U48EF	anonymous	2009-1-4 (1)
+U45F9	anonymous	2009-1-4 (1)
+U39C3	FangQ	2009-1-4 (2)
+U49F9	anonymous	2009-1-4 (1)
+U84F8	anonymous	2009-1-4 (1)
+U46A5	anonymous	2009-1-4 (1)
+U46A0	anonymous	2009-1-4 (1)
+U4C81	anonymous	2009-1-4 (1)
+U469F	anonymous	2009-1-4 (1)
+U4A12	anonymous	2009-1-4 (1)
+U4869	anonymous	2009-1-4 (1)
+U5721	anonymous	2009-1-4 (1)
+U4A10	anonymous	2009-1-4 (1)
+U37F8	anonymous	2009-1-4 (1)
+U3ABD	anonymous	2009-1-4 (1)
+U5787	anonymous	2009-1-4 (1)
+U3779	FangQ	2009-1-4 (1)
+U4A14	anonymous	2009-1-4 (1)
+U46BC	anonymous	2009-1-4 (1)
+U46C2	anonymous	2009-1-4 (1)
+U8510	anonymous	2009-1-4 (1)
+U40ED	anonymous	2009-1-4 (1)
+U53BE	anonymous	2009-1-4 (1)
+U35C0	anonymous	2009-1-4 (1)
+U45DE	anonymous	2009-1-4 (1)
+U53C4	anonymous	2009-1-4 (1)
+U43A1	anonymous	2009-1-4 (1)
+U53C5	anonymous	2009-1-4 (1)
+U8534	anonymous	2009-1-4 (1)
+U3B0B	anonymous	2009-1-4 (1)
+U47F7	anonymous	2009-1-4 (1)
+U402A	anonymous	2009-1-4 (1)
+U8536	FangQ	2009-1-4 (1)
+U3C7E	anonymous	2009-1-4 (1)
+U4C45	anonymous	2009-1-4 (1)
+U8542	FangQ	2009-1-4 (1)
+U3B1A	anonymous	2009-1-4 (1)
+U468C	anonymous	2009-1-4 (1)
+U47A7	anonymous	2009-1-4 (1)
+U4DA3	anonymous	2009-1-4 (1)
+U47A0	anonymous	2009-1-4 (1)
+U3B57	anonymous	2009-1-4 (1)
+U5332	FangQ	2009-1-4 (1)
+U4DA5	anonymous	2009-1-4 (1)
+U37F3	anonymous	2009-1-4 (1)
+U37F2	anonymous	2009-1-4 (1)
+U48E5	anonymous	2009-1-4 (1)
+U37F3	anonymous	2009-1-4 (2)
+U48F0	anonymous	2009-1-4 (1)
+U37F0	anonymous	2009-1-4 (1)
+U5332	anonymous	2009-1-4 (2)
+U381C	anonymous	2009-1-4 (1)
+U381C	anonymous	2009-1-4 (2)
+U47BA	anonymous	2009-1-4 (1)
+U381D	anonymous	2009-1-4 (1)
+U47B9	anonymous	2009-1-4 (1)
+U4BE5	anonymous	2009-1-4 (1)
+U47A1	anonymous	2009-1-4 (1)
+U3EC3	anonymous	2009-1-4 (1)
+U4B5E	anonymous	2009-1-4 (1)
+U4B5D	anonymous	2009-1-4 (1)
+U4B5C	anonymous	2009-1-4 (1)
+U411D	anonymous	2009-1-4 (1)
+U4A96	anonymous	2009-1-4 (1)
+U534B	anonymous	2009-1-4 (1)
+U3C6D	anonymous	2009-1-4 (1)
+U4A9A	anonymous	2009-1-4 (1)
+U3C6C	anonymous	2009-1-4 (1)
+U4A9C	anonymous	2009-1-4 (1)
+U3FAE	anonymous	2009-1-4 (1)
+U3DEA	anonymous	2009-1-4 (1)
+U3E93	anonymous	2009-1-4 (1)
+U3DEC	anonymous	2009-1-4 (1)
+U53D0	anonymous	2009-1-4 (1)
+U3DEB	anonymous	2009-1-4 (1)
+U4491	anonymous	2009-1-4 (1)
+U3E9B	anonymous	2009-1-4 (1)
+U3EA1	anonymous	2009-1-4 (1)
+U3652	anonymous	2009-1-4 (1)
+U53E7	anonymous	2009-1-4 (1)
+U3653	anonymous	2009-1-4 (1)
+U3EA0	anonymous	2009-1-4 (1)
+U42DC	anonymous	2009-1-4 (1)
+U42DC	anonymous	2009-1-4 (2)
+U3DCB	anonymous	2009-1-4 (1)
+U38F2	anonymous	2009-1-4 (1)
+U7025	anonymous	2009-1-4 (1)
+U4491	FangQ	2009-1-4 (2)
+U4491	FangQ	2009-1-4 (3)
+U3B19	anonymous	2009-1-4 (1)
+U430C	anonymous	2009-1-4 (1)
+U347E	anonymous	2009-1-4 (1)
+U42DE	anonymous	2009-1-4 (1)
+U7036	anonymous	2009-1-4 (1)
+U42DF	anonymous	2009-1-4 (1)
+U703D	anonymous	2009-1-4 (1)
+U3C21	FangQ	2009-1-4 (3)
+U5C29	FangQ	2009-1-4 (2)
+U4196	anonymous	2009-1-4 (1)
+U452C	anonymous	2009-1-4 (1)
+U4B32	anonymous	2009-1-4 (1)
+U46C6	anonymous	2009-1-4 (1)
+U4B35	anonymous	2009-1-4 (1)
+U46C5	anonymous	2009-1-4 (1)
+U3481	anonymous	2009-1-4 (1)
+U4B31	anonymous	2009-1-4 (1)
+U3482	anonymous	2009-1-4 (1)
+U39DB	lsz	2009-1-4 (1)
+U3688	anonymous	2009-1-4 (1)
+U452F	anonymous	2009-1-4 (1)
+U4D8C	anonymous	2009-1-4 (1)
+U3580	anonymous	2009-1-4 (1)
+U4D8D	anonymous	2009-1-4 (1)
+U38B3	anonymous	2009-1-4 (1)
+U36C0	anonymous	2009-1-4 (1)
+U4D8E	anonymous	2009-1-4 (1)
+U36C1	anonymous	2009-1-4 (1)
+U53D3	lsz	2009-1-4 (1)
+U462B	anonymous	2009-1-4 (1)
+U37D5	anonymous	2009-1-4 (1)
+U4885	anonymous	2009-1-4 (1)
+U40C9	anonymous	2009-1-4 (1)
+U4798	anonymous	2009-1-4 (1)
+U37D6	anonymous	2009-1-4 (1)
+U40CA	anonymous	2009-1-4 (1)
+U37D7	anonymous	2009-1-4 (1)
+U40CE	anonymous	2009-1-4 (1)
+U417F	anonymous	2009-1-4 (1)
+U41E2	anonymous	2009-1-4 (1)
+U41E2	anonymous	2009-1-4 (2)
+U4183	anonymous	2009-1-4 (1)
+U4183	anonymous	2009-1-4 (2)
+U437C	anonymous	2009-1-4 (1)
+U437D	anonymous	2009-1-4 (1)
+U4432	anonymous	2009-1-4 (1)
+U4380	anonymous	2009-1-4 (1)
+U3BCF	anonymous	2009-1-4 (1)
+U3BD0	anonymous	2009-1-4 (1)
+U3BD3	anonymous	2009-1-4 (1)
+U3849	anonymous	2009-1-4 (1)
+U384A	anonymous	2009-1-4 (1)
+U384B	anonymous	2009-1-4 (1)
+U4B40	anonymous	2009-1-4 (1)
+U5C75	anonymous	2009-1-4 (1)
+U85B2	anonymous	2009-1-4 (1)
+U4ACC	anonymous	2009-1-4 (1)
+U704D	anonymous	2009-1-4 (1)
+U3CF9	anonymous	2009-1-4 (1)
+U3CFA	anonymous	2009-1-4 (1)
+U4106	anonymous	2009-1-4 (1)
+U3CFD	anonymous	2009-1-4 (1)
+U3714	anonymous	2009-1-4 (1)
+U3DE5	anonymous	2009-1-4 (1)
+U486A	anonymous	2009-1-4 (1)
+U486B	anonymous	2009-1-4 (1)
+U4061	anonymous	2009-1-4 (1)
+U4062	anonymous	2009-1-4 (1)
+U38C6	anonymous	2009-1-4 (1)
+U4016	anonymous	2009-1-4 (1)
+U4017	anonymous	2009-1-4 (1)
+U4D70	anonymous	2009-1-4 (1)
+U5C75	FangQ	2009-1-4 (2)
+U4D71	anonymous	2009-1-4 (1)
+U5725	anonymous	2009-1-4 (1)
+U47F4	anonymous	2009-1-4 (1)
+U37D7	FangQ	2009-1-4 (2)
+U47F8	anonymous	2009-1-4 (1)
+U5725	FangQ	2009-1-4 (2)
+U495F	anonymous	2009-1-4 (1)
+U4D78	anonymous	2009-1-4 (1)
+U45EC	anonymous	2009-1-4 (1)
+U4961	anonymous	2009-1-4 (1)
+U403F	anonymous	2009-1-4 (1)
+U4040	anonymous	2009-1-4 (1)
+U704B	FangQ	2009-1-4 (1)
+U4BD2	anonymous	2009-1-4 (1)
+U4BD3	anonymous	2009-1-4 (1)
+U3929	anonymous	2009-1-4 (1)
+U392A	anonymous	2009-1-4 (1)
+U392B	anonymous	2009-1-4 (1)
+U3452	anonymous	2009-1-4 (1)
+U3454	anonymous	2009-1-4 (1)
+U3455	anonymous	2009-1-4 (1)
+U5EC0	FangQ	2009-1-4 (1)
+U477E	anonymous	2009-1-4 (1)
+U3452	FangQ	2009-1-4 (2)
+U47F8	FangQ	2009-1-4 (2)
+U477A	anonymous	2009-1-4 (1)
+U3929	FangQ	2009-1-4 (2)
+U3D1F	anonymous	2009-1-4 (1)
+U3D21	anonymous	2009-1-4 (1)
+U3D20	anonymous	2009-1-4 (1)
+U37D5	FangQ	2009-1-4 (2)
+U38CB	anonymous	2009-1-4 (1)
+U477A	FangQ	2009-1-4 (2)
+U3B18	anonymous	2009-1-4 (1)
+U4D57	anonymous	2009-1-4 (1)
+U3B1C	anonymous	2009-1-4 (1)
+U357F	anonymous	2009-1-4 (1)
+U357E	anonymous	2009-1-4 (1)
+U4B4C	anonymous	2009-1-4 (1)
+U386E	anonymous	2009-1-4 (1)
+U3585	anonymous	2009-1-4 (1)
+U4BA1	anonymous	2009-1-4 (1)
+U4B4E	anonymous	2009-1-4 (1)
+U386F	anonymous	2009-1-4 (1)
+U4BA2	anonymous	2009-1-4 (1)
+U4C05	anonymous	2009-1-4 (1)
+U4B4D	anonymous	2009-1-4 (1)
+U3CBC	anonymous	2009-1-4 (1)
+U3CC1	anonymous	2009-1-4 (1)
+U4C09	anonymous	2009-1-4 (1)
+U4C08	anonymous	2009-1-4 (1)
+U37F4	anonymous	2009-1-4 (1)
+U3CC3	anonymous	2009-1-4 (1)
+U44C8	anonymous	2009-1-4 (1)
+U4C77	anonymous	2009-1-4 (1)
+U4C83	anonymous	2009-1-4 (1)
+U4C84	anonymous	2009-1-4 (1)
+U4C83	anonymous	2009-1-4 (2)
+U3F75	anonymous	2009-1-4 (1)
+U4C85	anonymous	2009-1-4 (1)
+U422F	anonymous	2009-1-4 (1)
+U3F77	anonymous	2009-1-4 (1)
+U3CD7	anonymous	2009-1-4 (1)
+U3CDE	anonymous	2009-1-4 (1)
+U4230	anonymous	2009-1-4 (1)
+U3F76	anonymous	2009-1-4 (1)
+U4231	anonymous	2009-1-4 (1)
+U3B48	anonymous	2009-1-4 (1)
+U3C9E	anonymous	2009-1-4 (1)
+U3B49	anonymous	2009-1-4 (1)
+U4493	anonymous	2009-1-4 (1)
+U4497	anonymous	2009-1-4 (1)
+U3F43	anonymous	2009-1-4 (1)
+U3F44	anonymous	2009-1-4 (1)
+U4BB6	anonymous	2009-1-4 (1)
+U48BE	anonymous	2009-1-4 (1)
+U3483	anonymous	2009-1-4 (1)
+U4B24	anonymous	2009-1-4 (1)
+U49AE	anonymous	2009-1-4 (1)
+U4B25	anonymous	2009-1-4 (1)
+U4C4A	anonymous	2009-1-4 (1)
+U4C4B	anonymous	2009-1-4 (1)
+U4C4B	anonymous	2009-1-4 (2)
+U4C4D	anonymous	2009-1-4 (1)
+U42E1	anonymous	2009-1-4 (1)
+U42E0	anonymous	2009-1-4 (1)
+U4B28	anonymous	2009-1-4 (1)
+U42E2	anonymous	2009-1-4 (1)
+U4C33	anonymous	2009-1-4 (1)
+U4C30	anonymous	2009-1-4 (1)
+U3851	anonymous	2009-1-4 (1)
+U4BDA	anonymous	2009-1-4 (1)
+U4BE6	anonymous	2009-1-4 (1)
+U3547	anonymous	2009-1-4 (1)
+U3548	anonymous	2009-1-4 (1)
+U37A6	anonymous	2009-1-4 (1)
+U37A7	anonymous	2009-1-4 (1)
+U3B4A	anonymous	2009-1-4 (1)
+U465B	anonymous	2009-1-4 (1)
+U34FF	anonymous	2009-1-4 (1)
+U3FED	anonymous	2009-1-4 (1)
+U4BC4	anonymous	2009-1-4 (1)
+U3751	anonymous	2009-1-4 (1)
+U3449	anonymous	2009-1-4 (1)
+U3CC4	anonymous	2009-1-4 (1)
+U4952	anonymous	2009-1-4 (1)
+U362F	anonymous	2009-1-4 (1)
+U4387	anonymous	2009-1-4 (1)
+U4D23	anonymous	2009-1-4 (1)
+U4756	anonymous	2009-1-4 (1)
+U34B9	anonymous	2009-1-4 (1)
+U3F2E	anonymous	2009-1-4 (1)
+U3D14	anonymous	2009-1-4 (1)
+U4B6B	anonymous	2009-1-4 (1)
+U3B62	mosoplyr	2009-1-4 (1)
+U3751	FangQ	2009-1-4 (2)
+U48F1	mosoplyr	2009-1-4 (1)
+U3B62	FangQ	2009-1-4 (2)
+U4387	FangQ	2009-1-4 (2)
+U48F3	mosoplyr	2009-1-4 (1)
+U3A61	mosoplyr	2009-1-4 (1)
+U385F	FangQ	2009-1-4 (1)
+U374E	anonymous	2009-1-4 (1)
+U43B5	anonymous	2009-1-4 (1)
+U8593	anonymous	2009-1-4 (1)
+U8603	anonymous	2009-1-4 (1)
+U43B1	anonymous	2009-1-4 (1)
+U43B1	anonymous	2009-1-4 (2)
+U43B1	anonymous	2009-1-4 (3)
+U43B1	anonymous	2009-1-4 (4)
+U43B1	anonymous	2009-1-4 (5)
+U5EEB	anonymous	2009-1-4 (1)
+U4B36	anonymous	2009-1-4 (1)
+U5EED	anonymous	2009-1-4 (1)
+U88A0	anonymous	2009-1-4 (1)
+U4B37	anonymous	2009-1-4 (1)
+U411E	anonymous	2009-1-4 (1)
+U3DB0	anonymous	2009-1-4 (1)
+U47A8	anonymous	2009-1-4 (1)
+U358D	FangQ	2009-1-4 (1)
+U4647	FangQ	2009-1-4 (1)
+U465D	FangQ	2009-1-4 (1)
+U45ED	FangQ	2009-1-4 (1)
+U45EE	FangQ	2009-1-4 (1)
+U45EF	FangQ	2009-1-4 (1)
+U5717	FangQ	2009-1-4 (1)
+U7674	anonymous	2009-1-4 (1)
+U5E07	FangQ	2009-1-4 (1)
+U5EE4	FangQ	2009-1-4 (1)
+U704E	anonymous	2009-1-4 (1)
+U704E	FangQ	2009-1-4 (2)
+U7054	anonymous	2009-1-4 (1)
+U7054	FangQ	2009-1-4 (2)
+U70C9	FangQ	2009-1-4 (1)
+U70D6	FangQ	2009-1-4 (1)
+U7097	FangQ	2009-1-4 (1)
+U7101	FangQ	2009-1-4 (1)
+U7108	FangQ	2009-1-4 (1)
+U860F	wanghong	2009-1-4 (1)
+U716D	FangQ	2009-1-4 (1)
+U8550	FangQ	2009-1-4 (1)
+U860F	FangQ	2009-1-4 (2)
+U8612	FangQ	2009-1-4 (1)
+U8614	FangQ	2009-1-4 (1)
+U8614	FangQ	2009-1-4 (2)
+U5EFD	wanghong	2009-1-4 (1)
+U88E6	FangQ	2009-1-4 (1)
+U8615	FangQ	2009-1-4 (1)
+U8628	wanghong	2009-1-4 (1)
+U8628	FangQ	2009-1-4 (2)
+U862B	wanghong	2009-1-4 (1)
+U5EFD	wanghong	2009-1-4 (2)
+U862B	wanghong	2009-1-4 (2)
+U862B	FangQ	2009-1-4 (3)
+U355A	anonymous	2009-1-4 (1)
+U8658	wanghong	2009-1-4 (1)
+U5896	FangQ	2009-1-4 (1)
+U35A8	anonymous	2009-1-4 (1)
+U58F5	FangQ	2009-1-5 (1)
+U7F53	FangQ	2009-1-5 (1)
+U5E07	FangQ	2009-1-5 (2)
+U4A8A	anonymous	2009-1-5 (1)
+U4A8A	FangQ	2009-1-5 (2)
+U7F56	anonymous	2009-1-5 (1)
+U3CE0	anonymous	2009-1-5 (1)
+U7CD3	anonymous	2009-1-5 (1)
+U5CDC	anonymous	2009-1-5 (1)
+U8A64	wanghong	2009-1-5 (1)
+U768D	anonymous	2009-1-5 (1)
+U3FFB	anonymous	2009-1-5 (1)
+U8A67	wanghong	2009-1-5 (1)
+U3506	anonymous	2009-1-5 (1)
+U4289	anonymous	2009-1-5 (1)
+U3950	anonymous	2009-1-5 (1)
+U4179	anonymous	2009-1-5 (1)
+U42A6	anonymous	2009-1-5 (1)
+U35E3	anonymous	2009-1-5 (1)
+U368E	anonymous	2009-1-5 (1)
+U7714	anonymous	2009-1-5 (1)
+U64A1	FangQ	2009-1-5 (1)
+U3E79	anonymous	2009-1-5 (1)
+U64A1	FangQ	2009-1-5 (2)
+U3C0B	anonymous	2009-1-5 (1)
+U6D05	FangQ	2009-1-5 (1)
+U3F47	FangQ	2009-1-5 (1)
+U3F45	anonymous	2009-1-5 (1)
+U4CEA	anonymous	2009-1-5 (1)
+U653A	FangQ	2009-1-5 (1)
+U3C26	anonymous	2009-1-5 (1)
+U6569	FangQ	2009-1-5 (1)
+U4C86	anonymous	2009-1-5 (1)
+U3C26	FangQ	2009-1-5 (2)
+U3917	anonymous	2009-1-5 (1)
+U4D94	anonymous	2009-1-5 (1)
+U49EF	anonymous	2009-1-5 (1)
+U4C86	FangQ	2009-1-5 (2)
+U38FB	anonymous	2009-1-5 (1)
+U4D97	anonymous	2009-1-5 (1)
+U4D99	anonymous	2009-1-5 (1)
+U368E	FangQ	2009-1-5 (2)
+U4C86	FangQ	2009-1-5 (3)
+U4AE3	anonymous	2009-1-5 (1)
+U4A8A	anonymous	2009-1-5 (3)
+U3C6E	anonymous	2009-1-5 (1)
+U3C6A	anonymous	2009-1-5 (1)
+U42A9	anonymous	2009-1-5 (1)
+U42A7	anonymous	2009-1-5 (1)
+U4A8F	anonymous	2009-1-5 (1)
+U38F5	anonymous	2009-1-5 (1)
+U374B	anonymous	2009-1-5 (1)
+U5E2C	anonymous	2009-1-5 (1)
+U4063	anonymous	2009-1-5 (1)
+U3BB0	anonymous	2009-1-5 (1)
+U4618	anonymous	2009-1-5 (1)
+U3CCA	anonymous	2009-1-5 (1)
+U67D7	wanghong	2009-1-5 (1)
+U5E51	wanghong	2009-1-5 (1)
+U5E51	wanghong	2009-1-5 (2)
+U5E51	wanghong	2009-1-5 (3)
+U42C3	anonymous	2009-1-5 (1)
+U388C	anonymous	2009-1-5 (1)
+U453A	anonymous	2009-1-5 (1)
+U36BE	anonymous	2009-1-5 (1)
+U70BF	wanghong	2009-1-5 (1)
+U4539	anonymous	2009-1-5 (1)
+U5E51	wanghong	2009-1-5 (4)
+U5A99	wanghong	2009-1-5 (1)
+U4CA0	anonymous	2009-1-5 (1)
+U7536	anonymous	2009-1-5 (1)
+U6FD0	wanghong	2009-1-5 (1)
+U6061	anonymous	2009-1-5 (1)
+U8AEC	wanghong	2009-1-5 (1)
+U60A5	anonymous	2009-1-5 (1)
+U3549	anonymous	2009-1-5 (1)
+U4C9C	lsz	2009-1-5 (1)
+U3D18	anonymous	2009-1-5 (1)
+U42A8	lsz	2009-1-5 (1)
+U42AA	lsz	2009-1-5 (1)
+U42AC	lsz	2009-1-5 (1)
+U3615	anonymous	2009-1-5 (1)
+U382F	lsz	2009-1-5 (1)
+U4C89	anonymous	2009-1-5 (1)
+U3830	lsz	2009-1-5 (1)
+U9682	lsz	2009-1-5 (1)
+U43A4	anonymous	2009-1-5 (1)
+U69D7	anonymous	2009-1-5 (1)
+U90D2	anonymous	2009-1-5 (1)
+U95B3	lsz	2009-1-5 (1)
+U3D47	anonymous	2009-1-5 (1)
+U9030	anonymous	2009-1-5 (1)
+U3D49	anonymous	2009-1-5 (1)
+U5763	anonymous	2009-1-5 (1)
+U6E7B	anonymous	2009-1-5 (1)
+U61E1	anonymous	2009-1-5 (1)
+U3804	anonymous	2009-1-5 (1)
+U6C48	anonymous	2009-1-5 (1)
+U5318	anonymous	2009-1-5 (1)
+U7AC6	anonymous	2009-1-5 (1)
+U9195	anonymous	2009-1-5 (1)
+U923B	anonymous	2009-1-5 (1)
+U8D9A	anonymous	2009-1-5 (1)
+U73DF	anonymous	2009-1-5 (1)
+U6702	anonymous	2009-1-5 (1)
+U9809	anonymous	2009-1-5 (1)
+U4FB4	anonymous	2009-1-5 (1)
+U43E8	anonymous	2009-1-5 (1)
+U48BA	anonymous	2009-1-5 (1)
+U42AC	wanghong	2009-1-5 (2)
+U387B	anonymous	2009-1-5 (1)
+U3713	anonymous	2009-1-5 (1)
+U47F9	anonymous	2009-1-5 (1)
+U4A2A	anonymous	2009-1-5 (1)
+U3DC1	anonymous	2009-1-5 (1)
+U4C65	anonymous	2009-1-5 (1)
+U4237	anonymous	2009-1-5 (1)
+U3F03	anonymous	2009-1-5 (1)
+U5EFD	lsz	2009-1-5 (3)
+U3F05	anonymous	2009-1-5 (1)
+U4ADE	anonymous	2009-1-5 (1)
+U95B3	lsz	2009-1-5 (2)
+U37B8	anonymous	2009-1-5 (1)
+U37BA	anonymous	2009-1-5 (1)
+U35EA	anonymous	2009-1-5 (1)
+U8F3D	lsz	2009-1-5 (1)
+U3935	anonymous	2009-1-5 (1)
+U4096	anonymous	2009-1-5 (1)
+U439D		2009-1-5 (1)
+U3C6F	anonymous	2009-1-5 (1)
+U3F87	anonymous	2009-1-5 (1)
+U3F87	anonymous	2009-1-5 (2)
+U4A9D	anonymous	2009-1-5 (1)
+U41FD	anonymous	2009-1-5 (1)
+U469B		2009-1-5 (1)
+U416C	anonymous	2009-1-5 (1)
+U41FE	anonymous	2009-1-5 (1)
+U4171	anonymous	2009-1-5 (1)
+U4699		2009-1-5 (1)
+U4C35	anonymous	2009-1-5 (1)
+U3BDF	anonymous	2009-1-5 (1)
+U384D	anonymous	2009-1-5 (1)
+U3BDF	anonymous	2009-1-5 (2)
+U4C44	anonymous	2009-1-5 (1)
+U4312	anonymous	2009-1-5 (1)
+U469A		2009-1-5 (1)
+U3604	anonymous	2009-1-5 (1)
+U3A5E	anonymous	2009-1-5 (1)
+U35D2	anonymous	2009-1-5 (1)
+U4042	anonymous	2009-1-5 (1)
+U35D9	anonymous	2009-1-5 (1)
+U4620	anonymous	2009-1-5 (1)
+U39DF	anonymous	2009-1-5 (1)
+U3565	anonymous	2009-1-5 (1)
+U39DF	anonymous	2009-1-5 (2)
+U4620	anonymous	2009-1-5 (2)
+U3820	anonymous	2009-1-5 (1)
+U4064	anonymous	2009-1-5 (1)
+U425C	anonymous	2009-1-5 (1)
+U3ECE	anonymous	2009-1-5 (1)
+U425C	anonymous	2009-1-5 (2)
+U4787	anonymous	2009-1-5 (1)
+U451C	anonymous	2009-1-5 (1)
+U9018	anonymous	2009-1-5 (1)
+U45F8	anonymous	2009-1-5 (1)
+U3D73	anonymous	2009-1-5 (1)
+U6CCB	anonymous	2009-1-5 (1)
+U3589	anonymous	2009-1-5 (1)
+U425F	anonymous	2009-1-5 (1)
+U3E28	anonymous	2009-1-5 (1)
+U38D5	anonymous	2009-1-5 (1)
+U46D0	anonymous	2009-1-5 (1)
+U48C3	anonymous	2009-1-5 (1)
+U8714	anonymous	2009-1-5 (1)
+U3F30	anonymous	2009-1-5 (1)
+U3F30	anonymous	2009-1-5 (2)
+U38E7	anonymous	2009-1-5 (1)
+U4713		2009-1-5 (1)
+U4715		2009-1-5 (1)
+U3686	anonymous	2009-1-5 (1)
+U4A3E	anonymous	2009-1-5 (1)
+U3F73	anonymous	2009-1-5 (1)
+U3434	anonymous	2009-1-5 (1)
+U3A29	anonymous	2009-1-5 (1)
+U35CC	anonymous	2009-1-5 (1)
+U46D0	FangQ	2009-1-5 (2)
+U3E13	anonymous	2009-1-5 (1)
+U41FE	FangQ	2009-1-5 (2)
+U37F5	anonymous	2009-1-5 (1)
+U4C50	anonymous	2009-1-5 (1)
+U3954	anonymous	2009-1-5 (1)
+U38FA	anonymous	2009-1-5 (1)
+U4185		2009-1-5 (1)
+U3CD0	anonymous	2009-1-5 (1)
+U3A05	anonymous	2009-1-5 (1)
+U4187		2009-1-5 (1)
+U3E50	anonymous	2009-1-5 (1)
+U39B8	anonymous	2009-1-5 (1)
+U496A	anonymous	2009-1-5 (1)
+U3D40	anonymous	2009-1-5 (1)
+U3669	anonymous	2009-1-5 (1)
+U3668	anonymous	2009-1-5 (1)
+U3CEA		2009-1-5 (1)
+U4409	anonymous	2009-1-5 (1)
+U3CF1		2009-1-5 (1)
+U4CA7	anonymous	2009-1-5 (1)
+U4CA8	anonymous	2009-1-5 (1)
+U3B9B	anonymous	2009-1-5 (1)
+U4C47	anonymous	2009-1-5 (1)
+U392E	anonymous	2009-1-5 (1)
+U3EDB	anonymous	2009-1-5 (1)
+U44B4	anonymous	2009-1-5 (1)
+U392F	anonymous	2009-1-5 (1)
+U462A		2009-1-5 (1)
+U36FA	anonymous	2009-1-5 (1)
+U369E	anonymous	2009-1-5 (1)
+U36FB	anonymous	2009-1-5 (1)
+U3D75		2009-1-5 (1)
+U3B01		2009-1-5 (1)
+U3A80	anonymous	2009-1-5 (1)
+U3A7F	anonymous	2009-1-5 (1)
+U3A81	anonymous	2009-1-5 (1)
+U3858	anonymous	2009-1-5 (1)
+U3859	anonymous	2009-1-5 (1)
+U3857	anonymous	2009-1-5 (1)
+U3C79	anonymous	2009-1-5 (1)
+U3C77	anonymous	2009-1-5 (1)
+U36FE	anonymous	2009-1-5 (1)
+U36FF	anonymous	2009-1-5 (1)
+U4A94	anonymous	2009-1-5 (1)
+U42C5		2009-1-5 (1)
+U4A9E	anonymous	2009-1-5 (1)
+U42E3		2009-1-5 (1)
+U42E3		2009-1-5 (2)
+U4388	anonymous	2009-1-5 (1)
+U3B4D	anonymous	2009-1-5 (1)
+U3F6F	anonymous	2009-1-5 (1)
+U3F72	anonymous	2009-1-5 (1)
+U946C	anonymous	2009-1-5 (1)
+U7B7C	anonymous	2009-1-5 (1)
+U38FA	FangQ	2009-1-5 (2)
+U384D	FangQ	2009-1-5 (2)
+U41C2	FangQ	2009-1-5 (1)
+U591E	FangQ	2009-1-5 (1)
+U5923	FangQ	2009-1-5 (1)
+U7FF6	FangQ	2009-1-5 (1)
+U800A	FangQ	2009-1-5 (1)
+U5008	FangQ	2009-1-5 (1)
+U45CD	anonymous	2009-1-5 (1)
+U4E65	FangQ	2009-1-5 (1)
+U9DF1	FangQ	2009-1-5 (1)
+U4E7B	FangQ	2009-1-5 (1)
+U4277	anonymous	2009-1-5 (1)
+U4E7C	FangQ	2009-1-5 (1)
+U4E7D	FangQ	2009-1-5 (1)
+U35DC	anonymous	2009-1-5 (1)
+U806B	FangQ	2009-1-5 (1)
+U45CF	anonymous	2009-1-5 (1)
+U806E	FangQ	2009-1-5 (1)
+U4BD4	anonymous	2009-1-5 (1)
+U3F72	FangQ	2009-1-5 (2)
+U45CF	FangQ	2009-1-5 (2)
+U406F	anonymous	2009-1-5 (1)
+U406F	anonymous	2009-1-5 (2)
+U4070	anonymous	2009-1-5 (1)
+U4994	anonymous	2009-1-5 (1)
+U4995	anonymous	2009-1-5 (1)
+U49E6	anonymous	2009-1-5 (1)
+U4D50	anonymous	2009-1-5 (1)
+U4D51	anonymous	2009-1-5 (1)
+U4AC6	anonymous	2009-1-5 (1)
+U440A	anonymous	2009-1-5 (1)
+U4D52	anonymous	2009-1-5 (1)
+U4A8B	anonymous	2009-1-5 (1)
+U3E2A	anonymous	2009-1-5 (1)
+U3E2D	anonymous	2009-1-5 (1)
+U4A8E	anonymous	2009-1-5 (1)
+U4A90	anonymous	2009-1-5 (1)
+U4ADF	anonymous	2009-1-5 (1)
+U3E2C	anonymous	2009-1-5 (1)
+U4232	anonymous	2009-1-5 (1)
+U3EE2	anonymous	2009-1-5 (1)
+U81FD	anonymous	2009-1-5 (1)
+U3F17	anonymous	2009-1-5 (1)
+U38B5	anonymous	2009-1-5 (1)
+U3F18	anonymous	2009-1-5 (1)
+U38B6	anonymous	2009-1-5 (1)
+U38B7	anonymous	2009-1-5 (1)
+U5383	FangQ	2009-1-5 (1)
+U539B	FangQ	2009-1-5 (1)
+U56EC	FangQ	2009-1-5 (1)
+U3A88	anonymous	2009-1-5 (1)
+U570E	FangQ	2009-1-5 (1)
+U4B69	anonymous	2009-1-5 (1)
+U7541	FangQ	2009-1-5 (1)
+U7557	FangQ	2009-1-5 (1)
+U4AEB	anonymous	2009-1-5 (1)
+U4AED	anonymous	2009-1-5 (1)
+U44B5	anonymous	2009-1-5 (1)
+U408D	anonymous	2009-1-5 (1)
+U6929	pem	2009-1-5 (1)
+U43AF	anonymous	2009-1-5 (1)
+U43AE	anonymous	2009-1-5 (1)
+U371B	anonymous	2009-1-6 (1)
+U4714	anonymous	2009-1-6 (1)
+U4718	anonymous	2009-1-6 (1)
+U4368	anonymous	2009-1-6 (1)
+U4369	anonymous	2009-1-6 (1)
+U4640	anonymous	2009-1-6 (1)
+U3498	anonymous	2009-1-6 (1)
+U7AF5	anonymous	2009-1-6 (1)
+U3ED9	anonymous	2009-1-6 (1)
+U3EDA	anonymous	2009-1-6 (1)
+U3F24	anonymous	2009-1-6 (1)
+U4E81	anonymous	2009-1-6 (1)
+U3F25	anonymous	2009-1-6 (1)
+U3EE0	anonymous	2009-1-6 (1)
+U3EE0	anonymous	2009-1-6 (2)
+U3EE0	anonymous	2009-1-6 (3)
+U34F7	anonymous	2009-1-6 (1)
+U48C2	anonymous	2009-1-6 (1)
+U4382	anonymous	2009-1-6 (1)
+U469C	anonymous	2009-1-6 (1)
+U469C	anonymous	2009-1-6 (2)
+U469D	anonymous	2009-1-6 (1)
+U344B	anonymous	2009-1-6 (1)
+U3456	anonymous	2009-1-6 (1)
+U3456	anonymous	2009-1-6 (2)
+U3456	anonymous	2009-1-6 (3)
+U3456	anonymous	2009-1-6 (4)
+U3456	anonymous	2009-1-6 (5)
+U3456	anonymous	2009-1-6 (6)
+U3459	anonymous	2009-1-6 (1)
+U38BA	anonymous	2009-1-6 (1)
+U4528	anonymous	2009-1-6 (1)
+U4528	anonymous	2009-1-6 (2)
+U4528	anonymous	2009-1-6 (3)
+U4528	anonymous	2009-1-6 (4)
+U53B8	anonymous	2009-1-6 (1)
+U3C7A	anonymous	2009-1-6 (1)
+U63D1	anonymous	2009-1-6 (1)
+U45E2	anonymous	2009-1-6 (1)
+U3B3C	anonymous	2009-1-6 (1)
+U3C85	anonymous	2009-1-6 (1)
+U48BF	anonymous	2009-1-6 (1)
+U44E7	anonymous	2009-1-6 (1)
+U48F2	anonymous	2009-1-6 (1)
+U9A51	wanghong	2009-1-6 (1)
+U3CE1	anonymous	2009-1-6 (1)
+U3651	anonymous	2009-1-6 (1)
+U48F8	anonymous	2009-1-6 (1)
+U346A	anonymous	2009-1-6 (1)
+U3B63	anonymous	2009-1-6 (1)
+U3F9F	anonymous	2009-1-6 (1)
+U4BAA	anonymous	2009-1-6 (1)
+U3FA0	anonymous	2009-1-6 (1)
+U3CFF	anonymous	2009-1-6 (1)
+U3D00	anonymous	2009-1-6 (1)
+U49F4	anonymous	2009-1-6 (1)
+U3D01	anonymous	2009-1-6 (1)
+U4D24	anonymous	2009-1-6 (1)
+U498C	anonymous	2009-1-6 (1)
+U49F5	anonymous	2009-1-6 (1)
+U3DFE	anonymous	2009-1-6 (1)
+U9CFE	wanghong	2009-1-6 (1)
+U9D02	wanghong	2009-1-6 (1)
+U3EFA	anonymous	2009-1-6 (1)
+U461A	anonymous	2009-1-6 (1)
+U3EFD	anonymous	2009-1-6 (1)
+U3DDF	anonymous	2009-1-6 (1)
+U4EA3	wanghong	2009-1-6 (1)
+U3F37	anonymous	2009-1-6 (2)
+U3802	anonymous	2009-1-6 (1)
+U3933	anonymous	2009-1-6 (1)
+U3F38	anonymous	2009-1-6 (2)
+U3E21	anonymous	2009-1-6 (1)
+U3E22	anonymous	2009-1-6 (1)
+U3566	anonymous	2009-1-6 (1)
+U3E23	anonymous	2009-1-6 (1)
+U3E52	anonymous	2009-1-6 (1)
+U3E83	anonymous	2009-1-6 (1)
+U8B29	wanghong	2009-1-6 (1)
+U8B29	wanghong	2009-1-6 (2)
+U429F	anonymous	2009-1-6 (1)
+U3ED8	anonymous	2009-1-6 (1)
+U4383	anonymous	2009-1-6 (1)
+U438A	anonymous	2009-1-6 (1)
+U439A	anonymous	2009-1-6 (1)
+U44EA	anonymous	2009-1-6 (1)
+U44EC	anonymous	2009-1-6 (1)
+U45D2	anonymous	2009-1-6 (1)
+U453D	anonymous	2009-1-6 (1)
+U4081	anonymous	2009-1-6 (1)
+U4083	anonymous	2009-1-6 (1)
+U3A95	anonymous	2009-1-6 (1)
+U4074	anonymous	2009-1-6 (1)
+U4075	anonymous	2009-1-6 (1)
+U4BC5	anonymous	2009-1-6 (1)
+U4236	anonymous	2009-1-6 (1)
+U9B1B		2009-1-6 (1)
+U6F48		2009-1-6 (1)
+U3A09	lsz	2009-1-6 (1)
+U7010		2009-1-6 (1)
+U3FEA	anonymous	2009-1-6 (1)
+U3443	anonymous	2009-1-6 (1)
+U45BA	anonymous	2009-1-6 (1)
+U3847	anonymous	2009-1-6 (1)
+U3850	anonymous	2009-1-6 (1)
+U42E4	anonymous	2009-1-6 (1)
+U3EFE	anonymous	2009-1-6 (1)
+U3EFF	anonymous	2009-1-6 (1)
+U35F3	anonymous	2009-1-6 (1)
+U35F4	anonymous	2009-1-6 (1)
+U41C6	anonymous	2009-1-6 (1)
+U41C8	anonymous	2009-1-6 (1)
+U4EB4		2009-1-6 (1)
+U3468	anonymous	2009-1-6 (1)
+U3CC7	anonymous	2009-1-6 (1)
+U4239	anonymous	2009-1-6 (1)
+U4065	anonymous	2009-1-6 (1)
+U37C9	anonymous	2009-1-6 (1)
+U3A96	anonymous	2009-1-6 (1)
+U3C7C	FangQ	2009-1-6 (1)
+U5900		2009-1-6 (1)
+U5900		2009-1-6 (2)
+U5900		2009-1-6 (3)
+U4899	anonymous	2009-1-6 (1)
+U4899	anonymous	2009-1-6 (2)
+U3F00	anonymous	2009-1-6 (1)
+U45B9	anonymous	2009-1-6 (1)
+U3411	anonymous	2009-1-6 (1)
+U3805	anonymous	2009-1-6 (1)
+U3412	anonymous	2009-1-6 (1)
+U71A6	anonymous	2009-1-6 (1)
+U4D4F	anonymous	2009-1-6 (1)
+U5A73		2009-1-6 (1)
+U481A	anonymous	2009-1-6 (1)
+U5A73		2009-1-6 (2)
+U429D	anonymous	2009-1-6 (1)
+U429D	anonymous	2009-1-6 (2)
+U481A	anonymous	2009-1-6 (2)
+U38FC	anonymous	2009-1-6 (1)
+U36C6	anonymous	2009-1-6 (1)
+U3883	anonymous	2009-1-6 (1)
+U3887	anonymous	2009-1-6 (1)
+U3F2F	anonymous	2009-1-6 (1)
+U3F49	anonymous	2009-1-6 (1)
+U4D9B	anonymous	2009-1-6 (1)
+U47AB	anonymous	2009-1-6 (1)
+U38B8	anonymous	2009-1-6 (1)
+U39DE	anonymous	2009-1-6 (1)
+U3955	anonymous	2009-1-6 (1)
+U45BF	anonymous	2009-1-6 (1)
+U3632	anonymous	2009-1-6 (1)
+U3633	anonymous	2009-1-6 (1)
+U3634	anonymous	2009-1-6 (1)
+U60D2	anonymous	2009-1-6 (1)
+U5933	anonymous	2009-1-6 (1)
+U53AF	anonymous	2009-1-6 (1)
+U83AC	anonymous	2009-1-6 (1)
+U7347	anonymous	2009-1-6 (1)
+U5B39	anonymous	2009-1-6 (1)
+U5B39	anonymous	2009-1-6 (2)
+U5B39	anonymous	2009-1-6 (3)
+U56B8	FangQ	2009-1-6 (1)
+U5715	FangQ	2009-1-6 (1)
+U6138	FangQ	2009-1-6 (1)
+U61A0	FangQ	2009-1-6 (1)
+U3634	FangQ	2009-1-6 (2)
+U4262	yanqian	2009-1-6 (1)
+U3AA8	yanqian	2009-1-6 (1)
+U3AA9	yanqian	2009-1-6 (1)
+U65D5	wanghong	2009-1-6 (1)
+U38FD	anonymous	2009-1-6 (1)
+U64AA	wanghong	2009-1-6 (1)
+U64AA	wanghong	2009-1-6 (2)
+U5B91	anonymous	2009-1-6 (1)
+U4EBD	wanghong	2009-1-6 (1)
+U4EBE	wanghong	2009-1-6 (1)
+U4EBD	wanghong	2009-1-6 (2)
+U4101	anonymous	2009-1-6 (1)
+U4105	anonymous	2009-1-6 (1)
+U396E	FangQ	2009-1-6 (1)
+U41B8	anonymous	2009-1-6 (1)
+U41B9	anonymous	2009-1-6 (1)
+U3FEB	anonymous	2009-1-6 (1)
+U4001	anonymous	2009-1-6 (1)
+U4313	anonymous	2009-1-6 (1)
+U4001	anonymous	2009-1-6 (2)
+U4002	anonymous	2009-1-6 (1)
+U4002	anonymous	2009-1-6 (2)
+U4003	anonymous	2009-1-6 (1)
+U45A5	anonymous	2009-1-6 (1)
+U3888	anonymous	2009-1-6 (1)
+U3693	anonymous	2009-1-6 (1)
+U3F01	anonymous	2009-1-6 (1)
+U37C0	anonymous	2009-1-6 (1)
+U3B3E	anonymous	2009-1-6 (1)
+U3636	anonymous	2009-1-6 (1)
+U3B3F	anonymous	2009-1-6 (1)
+U4358	anonymous	2009-1-6 (1)
+U3975	anonymous	2009-1-6 (1)
+U48FE	anonymous	2009-1-6 (1)
+U45AD	anonymous	2009-1-6 (1)
+U418A	anonymous	2009-1-6 (1)
+U3B40	anonymous	2009-1-6 (1)
+U4CB7	anonymous	2009-1-6 (1)
+U4AF3	anonymous	2009-1-6 (1)
+U4D0B	anonymous	2009-1-6 (1)
+U4D0C	anonymous	2009-1-6 (1)
+U4973	anonymous	2009-1-6 (1)
+U3796	anonymous	2009-1-6 (1)
+U444E	anonymous	2009-1-6 (1)
+U3A14	anonymous	2009-1-6 (1)
+U3F3B	anonymous	2009-1-6 (1)
+U471E	anonymous	2009-1-6 (1)
+U3458	anonymous	2009-1-6 (1)
+U471F	anonymous	2009-1-6 (1)
+U37BD	anonymous	2009-1-6 (1)
+U3E01	anonymous	2009-1-6 (1)
+U3BD7	anonymous	2009-1-6 (1)
+U4076	anonymous	2009-1-6 (1)
+U482A	anonymous	2009-1-6 (1)
+U47EB	anonymous	2009-1-6 (1)
+U4841	anonymous	2009-1-6 (1)
+U3608	anonymous	2009-1-6 (1)
+U3A0F	anonymous	2009-1-6 (1)
+U4311	anonymous	2009-1-6 (1)
+U3AD4	anonymous	2009-1-6 (1)
+U4314	anonymous	2009-1-6 (1)
+U3AD6	anonymous	2009-1-6 (1)
+U4AFA	anonymous	2009-1-6 (1)
+U37E6	anonymous	2009-1-6 (1)
+U3A41	anonymous	2009-1-6 (1)
+U390A	anonymous	2009-1-6 (1)
+U3AB9	anonymous	2009-1-6 (1)
+U3457	anonymous	2009-1-6 (1)
+U46B0	anonymous	2009-1-6 (1)
+U4D8A	anonymous	2009-1-7 (1)
+U4D8B	anonymous	2009-1-7 (1)
+U6AB2	anonymous	2009-1-7 (1)
+U9C6A	anonymous	2009-1-7 (1)
+U9BF3	anonymous	2009-1-7 (1)
+U9C6A	FangQ	2009-1-7 (2)
+U4D7A	anonymous	2009-1-7 (1)
+U9BF3	FangQ	2009-1-7 (2)
+U3626	anonymous	2009-1-7 (1)
+U39B5	anonymous	2009-1-7 (1)
+U39B7	anonymous	2009-1-7 (1)
+U417E	anonymous	2009-1-7 (1)
+U463F	anonymous	2009-1-7 (1)
+U3A64	anonymous	2009-1-7 (1)
+U350A	anonymous	2009-1-7 (1)
+U4BA9	anonymous	2009-1-7 (1)
+U4BAC	anonymous	2009-1-7 (1)
+U4D44	anonymous	2009-1-7 (1)
+U35DD	anonymous	2009-1-7 (1)
+U4D46	anonymous	2009-1-7 (1)
+U406E	anonymous	2009-1-7 (1)
+U4073	anonymous	2009-1-7 (1)
+U4072	anonymous	2009-1-7 (1)
+U3B70	anonymous	2009-1-7 (1)
+U40FB	anonymous	2009-1-7 (1)
+U4BAE	anonymous	2009-1-7 (1)
+U41F4	anonymous	2009-1-7 (1)
+U3BED	anonymous	2009-1-7 (1)
+U3F0D	anonymous	2009-1-7 (1)
+U3801	anonymous	2009-1-7 (1)
+U37FF	anonymous	2009-1-7 (1)
+U4486	anonymous	2009-1-7 (1)
+U407B	anonymous	2009-1-7 (1)
+U418E	anonymous	2009-1-7 (1)
+U418D	anonymous	2009-1-7 (1)
+U460B	anonymous	2009-1-7 (1)
+U456C	anonymous	2009-1-7 (1)
+U456C	anonymous	2009-1-7 (2)
+U370C	anonymous	2009-1-7 (1)
+U3711	anonymous	2009-1-7 (1)
+U3712	anonymous	2009-1-7 (1)
+U3A4F	anonymous	2009-1-7 (1)
+U4430	anonymous	2009-1-7 (1)
+U40D7	anonymous	2009-1-7 (1)
+U4587	anonymous	2009-1-7 (1)
+U48A9	anonymous	2009-1-7 (1)
+U48AA	anonymous	2009-1-7 (1)
+U4177	anonymous	2009-1-7 (1)
+U38AA	anonymous	2009-1-7 (1)
+U3DB3	anonymous	2009-1-7 (1)
+U3A12	anonymous	2009-1-7 (1)
+U3A10	anonymous	2009-1-7 (1)
+U43B3	anonymous	2009-1-7 (1)
+U3901	anonymous	2009-1-7 (1)
+U3C15	anonymous	2009-1-7 (1)
+U34B4	anonymous	2009-1-7 (1)
+U3E85	anonymous	2009-1-7 (1)
+U4706	anonymous	2009-1-7 (1)
+U480C	anonymous	2009-1-7 (1)
+U387C	anonymous	2009-1-7 (1)
+U480C	anonymous	2009-1-7 (2)
+U38BC	anonymous	2009-1-7 (1)
+U37AA	anonymous	2009-1-7 (1)
+U3F5D	anonymous	2009-1-7 (1)
+U902C	anonymous	2009-1-7 (1)
+U3BC3	anonymous	2009-1-7 (1)
+U4C8B	anonymous	2009-1-7 (1)
+U4904	anonymous	2009-1-7 (1)
+U4904	anonymous	2009-1-7 (2)
+U4742	anonymous	2009-1-7 (1)
+U40DC	anonymous	2009-1-7 (1)
+U3B3A	anonymous	2009-1-7 (1)
+U386B	pem	2009-1-7 (1)
+U363D	anonymous	2009-1-7 (1)
+U4BB1		2009-1-7 (1)
+U3B50	anonymous	2009-1-7 (1)
+U3B52	anonymous	2009-1-7 (1)
+U3B56	anonymous	2009-1-7 (1)
+U9740	anonymous	2009-1-7 (1)
+U47E6	anonymous	2009-1-7 (1)
+U481C	anonymous	2009-1-7 (1)
+U4C51	anonymous	2009-1-7 (1)
+U461D	anonymous	2009-1-7 (1)
+U461D	anonymous	2009-1-7 (2)
+U4C52	anonymous	2009-1-7 (1)
+U461D	anonymous	2009-1-7 (3)
+U4367	anonymous	2009-1-7 (1)
+U464D	anonymous	2009-1-7 (1)
+U7758	lsz	2009-1-7 (1)
+U4637	anonymous	2009-1-7 (1)
+U3984	anonymous	2009-1-7 (1)
+U3984	anonymous	2009-1-7 (2)
+U77C1	lsz	2009-1-7 (1)
+U3F9D	anonymous	2009-1-7 (1)
+U4C54	anonymous	2009-1-7 (1)
+U3A1D	anonymous	2009-1-7 (1)
+U3718	anonymous	2009-1-7 (1)
+U4821	anonymous	2009-1-7 (1)
+U4966	anonymous	2009-1-7 (1)
+U4B53	anonymous	2009-1-7 (1)
+U3B24	anonymous	2009-1-7 (1)
+U3B26	anonymous	2009-1-7 (1)
+U4CF6	anonymous	2009-1-7 (1)
+U3823	anonymous	2009-1-7 (1)
+U46EE	anonymous	2009-1-7 (1)
+U5335	anonymous	2009-1-7 (1)
+U3DD3	anonymous	2009-1-7 (1)
+U5329	anonymous	2009-1-7 (1)
+U3695	anonymous	2009-1-7 (1)
+U3E03	anonymous	2009-1-7 (1)
+U375D	anonymous	2009-1-7 (1)
+U4048	anonymous	2009-1-7 (1)
+U4622	anonymous	2009-1-7 (1)
+U4047	anonymous	2009-1-7 (1)
+U403E	anonymous	2009-1-7 (1)
+U9740	wanghong	2009-1-7 (2)
+U9740	wanghong	2009-1-7 (3)
+U9740	wanghong	2009-1-7 (4)
+U9740	wanghong	2009-1-7 (5)
+U5705	wanghong	2009-1-7 (1)
+U4ECC	anonymous	2009-1-7 (1)
+U4BD5	anonymous	2009-1-7 (1)
+U4BD6	anonymous	2009-1-7 (1)
+U3518	anonymous	2009-1-7 (1)
+U3519	anonymous	2009-1-7 (1)
+U92BD	anonymous	2009-1-7 (1)
+U9046	anonymous	2009-1-7 (1)
+U9046	anonymous	2009-1-7 (2)
+U9046	anonymous	2009-1-7 (3)
+U3ABC	anonymous	2009-1-7 (1)
+U3ABE	anonymous	2009-1-7 (1)
+U4433	anonymous	2009-1-7 (1)
+U80BB	wanghong	2009-1-7 (1)
+U44B9	anonymous	2009-1-7 (1)
+U3863	anonymous	2009-1-7 (1)
+U3864	anonymous	2009-1-7 (1)
+U4C80	anonymous	2009-1-7 (1)
+U8C53	wanghong	2009-1-7 (1)
+U4D0A	anonymous	2009-1-7 (1)
+U3ACB	anonymous	2009-1-7 (1)
+U4359	anonymous	2009-1-7 (1)
+U9B30	wanghong	2009-1-7 (1)
+U354F	anonymous	2009-1-7 (1)
+U3551	anonymous	2009-1-7 (1)
+U7474	wanghong	2009-1-7 (1)
+U4BAD	anonymous	2009-1-7 (1)
+U8458	wanghong	2009-1-7 (1)
+U371C	anonymous	2009-1-7 (1)
+U67BD	wanghong	2009-1-7 (1)
+U4D6E	anonymous	2009-1-7 (1)
+U67BF	wanghong	2009-1-7 (1)
+U687A	wanghong	2009-1-7 (1)
+U687A	wanghong	2009-1-7 (2)
+U4D6E	anonymous	2009-1-7 (2)
+U4ED2	wanghong	2009-1-7 (1)
+U4EE7	wanghong	2009-1-7 (1)
+U469E	anonymous	2009-1-7 (1)
+U929F	wanghong	2009-1-7 (1)
+U535D	FangQ	2009-1-7 (1)
+U5336	FangQ	2009-1-7 (1)
+U5314	FangQ	2009-1-7 (1)
+U4F16	FangQ	2009-1-7 (1)
+U4F31	FangQ	2009-1-7 (1)
+U811C	FangQ	2009-1-7 (1)
+U7571	wanghong	2009-1-7 (1)
+U890F	FangQ	2009-1-7 (1)
+U883A	FangQ	2009-1-7 (1)
+U887A	FangQ	2009-1-7 (1)
+U7081	FangQ	2009-1-7 (1)
+U7124	FangQ	2009-1-7 (1)
+U3609	anonymous	2009-1-7 (1)
+U4727	anonymous	2009-1-7 (1)
+U4727	anonymous	2009-1-7 (2)
+U3D88	anonymous	2009-1-7 (1)
+U46FA	anonymous	2009-1-7 (1)
+U495C	anonymous	2009-1-7 (1)
+U5BBB	anonymous	2009-1-7 (1)
+U3B61	anonymous	2009-1-7 (1)
+U4434	anonymous	2009-1-8 (1)
+U4436	anonymous	2009-1-8 (1)
+U5BCF	anonymous	2009-1-8 (1)
+U7BB0	anonymous	2009-1-8 (1)
+U446D	anonymous	2009-1-8 (1)
+U4621	anonymous	2009-1-8 (1)
+U7124	wanghong	2009-1-8 (2)
+U7124	wanghong	2009-1-8 (3)
+U669C	wanghong	2009-1-8 (1)
+U68B7	wanghong	2009-1-8 (1)
+U82C9	wanghong	2009-1-8 (1)
+U8312	wanghong	2009-1-8 (1)
+U7124	wanghong	2009-1-8 (4)
+U898E	wanghong	2009-1-8 (1)
+U8990	wanghong	2009-1-8 (1)
+U89BC	wanghong	2009-1-8 (1)
+U5BDC	wanghong	2009-1-8 (1)
+U5C2B	wanghong	2009-1-8 (1)
+U4E23	wanghong	2009-1-8 (1)
+U898E	wanghong	2009-1-8 (2)
+U8990	wanghong	2009-1-8 (2)
+U3A87	anonymous	2009-1-8 (1)
+U434D	anonymous	2009-1-8 (1)
+U434E	anonymous	2009-1-8 (1)
+U44B1	anonymous	2009-1-8 (1)
+U46D2	anonymous	2009-1-8 (1)
+U3CF2	anonymous	2009-1-8 (1)
+U3E1C	anonymous	2009-1-8 (1)
+U3E24	anonymous	2009-1-8 (1)
+U4A01	anonymous	2009-1-8 (1)
+U400E	anonymous	2009-1-8 (1)
+U4010	anonymous	2009-1-8 (1)
+U3F9B	anonymous	2009-1-8 (1)
+U48E8	wanghong	2009-1-8 (1)
+U48E8	wanghong	2009-1-8 (2)
+U3EA4	anonymous	2009-1-8 (1)
+U3EA5	anonymous	2009-1-8 (1)
+U3FBE	anonymous	2009-1-8 (1)
+U427A	anonymous	2009-1-8 (1)
+U3DBF	anonymous	2009-1-8 (1)
+U3854	anonymous	2009-1-8 (1)
+U4440	anonymous	2009-1-8 (1)
+U36BF	anonymous	2009-1-8 (1)
+U36BF	anonymous	2009-1-8 (2)
+U36BF	anonymous	2009-1-8 (3)
+U4350	anonymous	2009-1-8 (1)
+U351D	anonymous	2009-1-8 (1)
+U371A	anonymous	2009-1-8 (1)
+U3C81	anonymous	2009-1-8 (1)
+U353D	anonymous	2009-1-8 (1)
+U49EE	anonymous	2009-1-8 (1)
+U4666	anonymous	2009-1-8 (1)
+U4CC1	anonymous	2009-1-8 (1)
+U36B6	anonymous	2009-1-8 (1)
+U4ABE	anonymous	2009-1-8 (1)
+U4ABF	anonymous	2009-1-8 (1)
+U4391	anonymous	2009-1-8 (1)
+U8CF2	anonymous	2009-1-8 (1)
+U41ED	anonymous	2009-1-8 (1)
+U3F74	anonymous	2009-1-8 (1)
+U366A	anonymous	2009-1-8 (1)
+U41EE	anonymous	2009-1-8 (1)
+U366A	anonymous	2009-1-8 (2)
+U4935	anonymous	2009-1-8 (1)
+U4936	anonymous	2009-1-8 (1)
+U3F97	anonymous	2009-1-8 (1)
+U3865	anonymous	2009-1-8 (1)
+U385E	anonymous	2009-1-8 (1)
+U40F8	anonymous	2009-1-8 (1)
+U36B7	anonymous	2009-1-8 (1)
+U36BD	anonymous	2009-1-8 (1)
+U3D91	anonymous	2009-1-8 (1)
+U44C4	anonymous	2009-1-8 (1)
+U5C5F	anonymous	2009-1-8 (1)
+U9385	anonymous	2009-1-8 (1)
+U3A79	anonymous	2009-1-8 (1)
+U3D5C	anonymous	2009-1-8 (1)
+U5C80	anonymous	2009-1-8 (1)
+U7BB0	wanghong	2009-1-8 (2)
+U4BE7	anonymous	2009-1-8 (1)
+U5C80	wanghong	2009-1-8 (2)
+U4D79	anonymous	2009-1-8 (1)
+U479B	yanqian	2009-1-8 (1)
+U3F78	yanqian	2009-1-8 (1)
+U3F79	yanqian	2009-1-8 (1)
+U3F7A	yanqian	2009-1-8 (1)
+U4AB9	yanqian	2009-1-8 (1)
+U4AC0	yanqian	2009-1-8 (1)
+U3868	yanqian	2009-1-8 (1)
+U481F	anonymous	2009-1-8 (1)
+U4C87	anonymous	2009-1-8 (1)
+U4C88	anonymous	2009-1-8 (1)
+U4C8A	anonymous	2009-1-8 (1)
+U371D	anonymous	2009-1-8 (1)
+U4725	anonymous	2009-1-8 (1)
+U4728	anonymous	2009-1-8 (1)
+U4729	anonymous	2009-1-8 (1)
+U3DA1	anonymous	2009-1-8 (1)
+U3C84	FangQ	2009-1-8 (1)
+U7BEF	FangQ	2009-1-8 (1)
+U3DA3	anonymous	2009-1-8 (1)
+U3DA8	anonymous	2009-1-8 (1)
+U518E	FangQ	2009-1-8 (1)
+U51AD	FangQ	2009-1-8 (1)
+U51A1	FangQ	2009-1-8 (1)
+U8CF7	FangQ	2009-1-8 (1)
+U8CEB	FangQ	2009-1-8 (1)
+U8641	FangQ	2009-1-8 (1)
+U8637	FangQ	2009-1-8 (1)
+U8B8F	FangQ	2009-1-8 (1)
+U8B8F	FangQ	2009-1-8 (2)
+U8E9B	FangQ	2009-1-8 (1)
+U5BD5	FangQ	2009-1-8 (1)
+U4413	anonymous	2009-1-8 (1)
+U4824	anonymous	2009-1-8 (1)
+U4825	anonymous	2009-1-8 (1)
+U48D0	anonymous	2009-1-8 (1)
+U8157	FangQ	2009-1-8 (1)
+U41EF	anonymous	2009-1-8 (1)
+U3AA1	anonymous	2009-1-8 (1)
+U3DF1	anonymous	2009-1-8 (1)
+U4087	anonymous	2009-1-8 (1)
+U3C24	anonymous	2009-1-8 (1)
+U3DF2	anonymous	2009-1-8 (1)
+U4621	FangQ	2009-1-8 (2)
+U41EF	anonymous	2009-1-8 (2)
+U41F0	anonymous	2009-1-8 (1)
+U3E89	FangQ	2009-1-8 (1)
+U40E4	anonymous	2009-1-8 (1)
+U41CA	anonymous	2009-1-8 (1)
+U41F1	anonymous	2009-1-9 (1)
+U47AD	anonymous	2009-1-9 (1)
+U47AF	anonymous	2009-1-9 (1)
+U905F	mozbug	2009-1-9 (1)
+U373D	anonymous	2009-1-9 (1)
+U4439	anonymous	2009-1-9 (1)
+U3EB9	anonymous	2009-1-9 (1)
+U3EB8	anonymous	2009-1-9 (1)
+U4823	anonymous	2009-1-9 (1)
+U377B	anonymous	2009-1-9 (1)
+U36F5	anonymous	2009-1-9 (1)
+U3938	anonymous	2009-1-9 (1)
+U4441	anonymous	2009-1-9 (1)
+U4066	anonymous	2009-1-9 (1)
+U3FA3	anonymous	2009-1-9 (1)
+U3FA5	anonymous	2009-1-9 (1)
+U4448	anonymous	2009-1-9 (1)
+U38F9	anonymous	2009-1-9 (1)
+U3DFC	anonymous	2009-1-9 (1)
+U3DFC	anonymous	2009-1-9 (2)
+U3E00	anonymous	2009-1-9 (1)
+U3E06	anonymous	2009-1-9 (1)
+U48C0	anonymous	2009-1-9 (1)
+U43D8	anonymous	2009-1-9 (1)
+U4CDA	anonymous	2009-1-9 (1)
+U4BF3	anonymous	2009-1-9 (1)
+U7012	wanghong	2009-1-9 (1)
+U472A	anonymous	2009-1-9 (1)
+U472B	anonymous	2009-1-9 (1)
+U76A5	wanghong	2009-1-9 (1)
+U48C5	anonymous	2009-1-9 (1)
+U7012	wanghong	2009-1-9 (2)
+U3E0C	anonymous	2009-1-9 (1)
+U3D92	anonymous	2009-1-9 (1)
+U3807	anonymous	2009-1-9 (1)
+U4B49	anonymous	2009-1-9 (1)
+U3A08	anonymous	2009-1-9 (1)
+U4449	anonymous	2009-1-9 (1)
+U3BCB	anonymous	2009-1-9 (1)
+U3DAE		2009-1-9 (1)
+U4826	anonymous	2009-1-9 (1)
+U3F21	anonymous	2009-1-9 (1)
+U3F23	anonymous	2009-1-9 (1)
+U4D63	anonymous	2009-1-9 (1)
+U4D65	anonymous	2009-1-9 (1)
+U3AE3	anonymous	2009-1-9 (1)
+U3433	anonymous	2009-1-9 (1)
+U4905	anonymous	2009-1-9 (1)
+U3D2C	anonymous	2009-1-9 (1)
+U4906	anonymous	2009-1-9 (1)
+U43BA	anonymous	2009-1-9 (1)
+U46FE	anonymous	2009-1-9 (1)
+U3960	anonymous	2009-1-9 (1)
+U3730	anonymous	2009-1-9 (1)
+U3731	anonymous	2009-1-9 (1)
+U479A	anonymous	2009-1-9 (1)
+U45D5	anonymous	2009-1-9 (1)
+U478B	anonymous	2009-1-9 (1)
+U4CF0	anonymous	2009-1-9 (1)
+U3F7B	anonymous	2009-1-9 (1)
+U4315	anonymous	2009-1-9 (1)
+U4310	anonymous	2009-1-9 (1)
+U3F7D	anonymous	2009-1-9 (1)
+U3F06	anonymous	2009-1-9 (1)
+U3D41	anonymous	2009-1-9 (1)
+U3D42	anonymous	2009-1-9 (1)
+U4B54	anonymous	2009-1-9 (1)
+U4B56	anonymous	2009-1-9 (1)
+U4084	anonymous	2009-1-9 (1)
+U407C	anonymous	2009-1-9 (1)
+U42B0	anonymous	2009-1-9 (1)
+U8371	anonymous	2009-1-9 (1)
+U39A0	anonymous	2009-1-9 (1)
+U3A22	anonymous	2009-1-9 (1)
+U7C18	anonymous	2009-1-9 (1)
+U3A23	anonymous	2009-1-9 (1)
+U37CA	anonymous	2009-1-9 (1)
+U381B	anonymous	2009-1-9 (1)
+U4A34	anonymous	2009-1-9 (1)
+U466C	anonymous	2009-1-9 (1)
+U466B	anonymous	2009-1-9 (1)
+U3AE3	FangQ	2009-1-9 (2)
+U3EB1	anonymous	2009-1-9 (1)
+U5C32	anonymous	2009-1-9 (1)
+U36EE	anonymous	2009-1-9 (1)
+U36F3	anonymous	2009-1-9 (1)
+U4532	anonymous	2009-1-9 (1)
+U4531	anonymous	2009-1-9 (1)
+U43B4	anonymous	2009-1-9 (1)
+U43CC	anonymous	2009-1-9 (1)
+U490D	anonymous	2009-1-9 (1)
+U490F	anonymous	2009-1-9 (1)
+U4914	anonymous	2009-1-9 (1)
+U4AC1	anonymous	2009-1-9 (1)
+U4AC2	anonymous	2009-1-9 (1)
+U4211	anonymous	2009-1-9 (1)
+U4212	anonymous	2009-1-9 (1)
+U4218	anonymous	2009-1-9 (1)
+U3BD8	anonymous	2009-1-9 (1)
+U3BE0	anonymous	2009-1-9 (1)
+U354C	anonymous	2009-1-9 (1)
+U354D	anonymous	2009-1-9 (1)
+U354E	anonymous	2009-1-9 (1)
+U3D06	anonymous	2009-1-9 (1)
+U3D08	anonymous	2009-1-9 (1)
+U4C8C	anonymous	2009-1-9 (1)
+U4C96	anonymous	2009-1-9 (1)
+U37A9	anonymous	2009-1-9 (1)
+U41A1	anonymous	2009-1-9 (1)
+U41A2	anonymous	2009-1-9 (1)
+U45D0	FangQ	2009-1-9 (1)
+U3985	anonymous	2009-1-9 (1)
+U3F88	anonymous	2009-1-9 (1)
+U3F89	anonymous	2009-1-9 (1)
+U5C6B	anonymous	2009-1-9 (1)
+U903A	anonymous	2009-1-9 (1)
+U903A	FangQ	2009-1-9 (2)
+U4498	anonymous	2009-1-9 (1)
+U9C7B	FangQ	2009-1-9 (1)
+U908C	FangQ	2009-1-9 (1)
+U93AB	FangQ	2009-1-9 (1)
+U9BF4	FangQ	2009-1-9 (1)
+U5084	FangQ	2009-1-9 (1)
+U3DBB	anonymous	2009-1-9 (1)
+U3DBE	anonymous	2009-1-9 (1)
+U34F4	anonymous	2009-1-9 (1)
+U4B98	pem	2009-1-9 (1)
+U43CD	pem	2009-1-10 (1)
+U4B57	anonymous	2009-1-10 (1)
+U4B58	anonymous	2009-1-10 (1)
+U4B58	anonymous	2009-1-10 (2)
+U4355	anonymous	2009-1-10 (1)
+U4162	pem	2009-1-10 (1)
+U3AE6	anonymous	2009-1-10 (1)
+U3AEA	anonymous	2009-1-10 (1)
+U3AEB	anonymous	2009-1-10 (1)
+U3E51	anonymous	2009-1-10 (1)
+U3FCE	anonymous	2009-1-10 (1)
+U47B3	anonymous	2009-1-10 (1)
+U47B4	anonymous	2009-1-10 (1)
+U47B7	anonymous	2009-1-10 (1)
+U3782	anonymous	2009-1-10 (1)
+U3782	anonymous	2009-1-10 (2)
+U3A3F	pem	2009-1-10 (1)
+U40E3	anonymous	2009-1-10 (1)
+U3A3F	pem	2009-1-10 (2)
+U438B	anonymous	2009-1-10 (1)
+U40E2	anonymous	2009-1-10 (1)
+U66C5	anonymous	2009-1-10 (1)
+U66C5	anonymous	2009-1-10 (2)
+U3A50	anonymous	2009-1-10 (1)
+U3A51	anonymous	2009-1-10 (1)
+U3A51	anonymous	2009-1-10 (2)
+U3A51	anonymous	2009-1-10 (3)
+U66C5	FangQ	2009-1-10 (3)
+U3E87	anonymous	2009-1-10 (1)
+U3E87	anonymous	2009-1-10 (2)
+U4989	anonymous	2009-1-10 (1)
+U3D4A	anonymous	2009-1-10 (1)
+U3E8A	anonymous	2009-1-10 (1)
+U3672	anonymous	2009-1-10 (1)
+U3F9E	anonymous	2009-1-10 (1)
+U4932	anonymous	2009-1-10 (1)
+U3DCA	anonymous	2009-1-10 (1)
+U3FA2	anonymous	2009-1-10 (1)
+U3680	anonymous	2009-1-10 (1)
+U3EA3	anonymous	2009-1-10 (1)
+U3EA6	anonymous	2009-1-10 (1)
+U3EA7	anonymous	2009-1-10 (1)
+U356F	anonymous	2009-1-10 (1)
+U358B	anonymous	2009-1-10 (1)
+U4C57	anonymous	2009-1-10 (1)
+U4C58	anonymous	2009-1-10 (1)
+U9402	wanghong	2009-1-10 (1)
+U3A8C	anonymous	2009-1-10 (1)
+U3A8E	anonymous	2009-1-10 (1)
+U7718	wanghong	2009-1-10 (1)
+U3A90	anonymous	2009-1-10 (1)
+U514F	wanghong	2009-1-10 (1)
+U4049	anonymous	2009-1-10 (1)
+U404A	anonymous	2009-1-10 (1)
+U4053	anonymous	2009-1-10 (1)
+U5158	wanghong	2009-1-10 (1)
+U4C8D	anonymous	2009-1-10 (1)
+U7C52	wanghong	2009-1-10 (1)
+U4C97	anonymous	2009-1-10 (1)
+U4C97	anonymous	2009-1-10 (2)
+U4C97	anonymous	2009-1-10 (3)
+U4C97	anonymous	2009-1-10 (4)
+U514F	wanghong	2009-1-10 (2)
+U514F	wanghong	2009-1-10 (3)
+U4C98	anonymous	2009-1-10 (1)
+U4069	anonymous	2009-1-10 (1)
+U4069	anonymous	2009-1-10 (2)
+U4068	anonymous	2009-1-10 (1)
+U3F7C	anonymous	2009-1-10 (1)
+U3F7C	anonymous	2009-1-10 (2)
+U3F7C	anonymous	2009-1-10 (3)
+U3F7C	anonymous	2009-1-10 (4)
+U3F7C	anonymous	2009-1-10 (5)
+U3F7C	anonymous	2009-1-10 (6)
+U3F7E	anonymous	2009-1-10 (1)
+U3DC9	anonymous	2009-1-10 (1)
+U3DC9	anonymous	2009-1-10 (2)
+U3DC9	anonymous	2009-1-10 (3)
+U3DD0	anonymous	2009-1-10 (1)
+U3DCF	anonymous	2009-1-10 (1)
+U3DCF	anonymous	2009-1-10 (2)
+U3A11	anonymous	2009-1-10 (1)
+U3A0C	anonymous	2009-1-10 (1)
+U3A0E	anonymous	2009-1-10 (1)
+U453B	anonymous	2009-1-10 (1)
+U4B9C	anonymous	2009-1-10 (1)
+U453B	anonymous	2009-1-10 (2)
+U453E	anonymous	2009-1-10 (1)
+U360E	anonymous	2009-1-10 (1)
+U453E	anonymous	2009-1-10 (2)
+U462E	anonymous	2009-1-10 (1)
+U462E	anonymous	2009-1-10 (2)
+U5160	wanghong	2009-1-10 (1)
+U4405	anonymous	2009-1-10 (1)
+U4B99	anonymous	2009-1-10 (1)
+U81A1	wanghong	2009-1-10 (1)
+U3B78	anonymous	2009-1-10 (1)
+U3B78	anonymous	2009-1-10 (2)
+U4694	anonymous	2009-1-10 (1)
+U3505	anonymous	2009-1-10 (1)
+U35C2	anonymous	2009-1-10 (1)
+U375A	anonymous	2009-1-10 (1)
+U487B	anonymous	2009-1-10 (1)
+U4CED	anonymous	2009-1-10 (1)
+U6AED	anonymous	2009-1-10 (1)
+U37DC	anonymous	2009-1-10 (1)
+U3F80	anonymous	2009-1-10 (1)
+U35F5	anonymous	2009-1-10 (1)
+U3474	anonymous	2009-1-10 (1)
+U3A13	anonymous	2009-1-10 (1)
+U3A15	anonymous	2009-1-10 (1)
+U50C3	FangQ	2009-1-10 (1)
+U7C34	FangQ	2009-1-10 (1)
+U498B	anonymous	2009-1-10 (1)
+U8286	FangQ	2009-1-10 (1)
+U4A1D	anonymous	2009-1-10 (1)
+U5365	FangQ	2009-1-10 (1)
+U4B2A	anonymous	2009-1-10 (1)
+U5381	FangQ	2009-1-10 (1)
+U6B0E	FangQ	2009-1-10 (1)
+U974C	FangQ	2009-1-10 (1)
+U5166	FangQ	2009-1-10 (1)
+U51E2	FangQ	2009-1-10 (1)
+U5153	FangQ	2009-1-10 (1)
+U487E	anonymous	2009-1-10 (1)
+U4C9A	anonymous	2009-1-10 (1)
+U432E	anonymous	2009-1-10 (1)
+U4741	anonymous	2009-1-10 (1)
+U7C08	FangQ	2009-1-10 (1)
+U3E0E	anonymous	2009-1-10 (1)
+U51E3	FangQ	2009-1-10 (1)
+U5205	FangQ	2009-1-10 (1)
+U354B	anonymous	2009-1-10 (1)
+U522F	FangQ	2009-1-10 (1)
+U3550	anonymous	2009-1-10 (1)
+U53C0	FangQ	2009-1-10 (1)
+U354A	anonymous	2009-1-10 (1)
+U438D	anonymous	2009-1-10 (1)
+U53B5	FangQ	2009-1-10 (1)
+U4719	anonymous	2009-1-10 (1)
+U53CF	FangQ	2009-1-10 (1)
+U40F3	anonymous	2009-1-10 (1)
+U53C0	FangQ	2009-1-10 (2)
+U432F	anonymous	2009-1-10 (1)
+U4335	anonymous	2009-1-10 (1)
+U3A19	anonymous	2009-1-10 (1)
+U4B6F	anonymous	2009-1-10 (1)
+U4B71	anonymous	2009-1-10 (1)
+U3509	anonymous	2009-1-10 (1)
+U438E	anonymous	2009-1-10 (1)
+U489C	anonymous	2009-1-10 (1)
+U489C	anonymous	2009-1-10 (2)
+U489A	anonymous	2009-1-10 (1)
+U4953	anonymous	2009-1-10 (1)
+U41C0	anonymous	2009-1-10 (1)
+U40DA	anonymous	2009-1-10 (1)
+U40D8	anonymous	2009-1-10 (1)
+U3486	anonymous	2009-1-10 (1)
+U3794	anonymous	2009-1-10 (1)
+U3797	anonymous	2009-1-10 (1)
+U3CB4	anonymous	2009-1-10 (1)
+U3ABB	FangQ	2009-1-10 (1)
+U374C	FangQ	2009-1-10 (1)
+U3750	FangQ	2009-1-10 (1)
+U3752	FangQ	2009-1-10 (1)
+U3D85	FangQ	2009-1-10 (1)
+U4173	FangQ	2009-1-10 (1)
+U3D79	anonymous	2009-1-10 (1)
+U4162	FangQ	2009-1-10 (2)
+U3997	anonymous	2009-1-10 (1)
+U4967	anonymous	2009-1-10 (1)
+U43B2	anonymous	2009-1-10 (1)
+U4988	anonymous	2009-1-10 (1)
+U35B0	anonymous	2009-1-10 (1)
+U35AF	anonymous	2009-1-10 (1)
+U35B1	anonymous	2009-1-10 (1)
+U4672	anonymous	2009-1-10 (1)
+U4673	anonymous	2009-1-10 (1)
+U3E3F	anonymous	2009-1-10 (1)
+U3E3F	anonymous	2009-1-10 (2)
+U3E56	anonymous	2009-1-10 (1)
+U810B	anonymous	2009-1-10 (1)
+U54F6	FangQ	2009-1-10 (1)
+U810B	anonymous	2009-1-10 (2)
+U810B	anonymous	2009-1-10 (3)
+U810B	anonymous	2009-1-10 (4)
+U810B	anonymous	2009-1-10 (5)
+U810B	anonymous	2009-1-10 (6)
+U810B	anonymous	2009-1-10 (7)
+U810B	anonymous	2009-1-10 (8)
+U355B	anonymous	2009-1-10 (1)
+U355D	anonymous	2009-1-10 (1)
+U48C8	FangQ	2009-1-10 (1)
+U45D3	FangQ	2009-1-10 (1)
+U355D	FangQ	2009-1-10 (2)
+U3936	FangQ	2009-1-10 (1)
+U355B	FangQ	2009-1-10 (2)
+U9402		2009-1-10 (2)
+U8F3A		2009-1-10 (1)
+U3D66	anonymous	2009-1-10 (1)
+U99F5		2009-1-10 (1)
+U40D4	anonymous	2009-1-10 (1)
+U6729		2009-1-10 (1)
+U623C		2009-1-10 (1)
+U623C		2009-1-10 (2)
+U54F6		2009-1-10 (2)
+U4E4A	FangQ	2009-1-10 (1)
+U4E37	FangQ	2009-1-10 (1)
+U4E05	FangQ	2009-1-10 (1)
+U4E04	FangQ	2009-1-10 (1)
+U5C72	FangQ	2009-1-10 (1)
+U5DDC	FangQ	2009-1-10 (1)
+U5DEA	FangQ	2009-1-10 (1)
+U66F1	FangQ	2009-1-10 (1)
+U66F1	FangQ	2009-1-10 (2)
+U7534	FangQ	2009-1-10 (1)
+U7534	FangQ	2009-1-10 (2)
+U66F1	FangQ	2009-1-10 (3)
+U5303	FangQ	2009-1-10 (1)
+U3BB9	anonymous	2009-1-10 (1)
+U4E29	FangQ	2009-1-10 (1)
+U4ACA	anonymous	2009-1-10 (1)
+U5350	FangQ	2009-1-10 (1)
+U3429	anonymous	2009-1-10 (1)
+U738D	FangQ	2009-1-10 (1)
+U6B7A	FangQ	2009-1-10 (1)
+U4822	anonymous	2009-1-10 (1)
+U4827	anonymous	2009-1-10 (1)
+U698B	FangQ	2009-1-10 (1)
+U4663	anonymous	2009-1-10 (1)
+U3F20	pem	2009-1-10 (1)
+U3F32	pem	2009-1-10 (1)
+U466A	anonymous	2009-1-10 (1)
+U3ADE	anonymous	2009-1-10 (1)
+U3AEC	anonymous	2009-1-10 (1)
+U4263	anonymous	2009-1-10 (1)
+U3F40	anonymous	2009-1-10 (1)
+U45F6	anonymous	2009-1-10 (1)
+U395F	anonymous	2009-1-10 (1)
+U4447	anonymous	2009-1-10 (1)
+U444D	anonymous	2009-1-10 (1)
+U44AE	anonymous	2009-1-10 (1)
+U46CB	anonymous	2009-1-10 (1)
+U35DB	anonymous	2009-1-10 (1)
+U47B0	anonymous	2009-1-10 (1)
+U3640	pem	2009-1-11 (1)
+U46A7	pem	2009-1-11 (1)
+U444A	anonymous	2009-1-11 (1)
+U46A9	anonymous	2009-1-11 (1)
+U46A6	anonymous	2009-1-11 (1)
+U49A3	anonymous	2009-1-11 (1)
+U4D34	anonymous	2009-1-11 (1)
+U4D32	anonymous	2009-1-11 (1)
+U4451	anonymous	2009-1-11 (1)
+U3FF3	anonymous	2009-1-11 (1)
+U3FF2	anonymous	2009-1-11 (1)
+U3F7F	anonymous	2009-1-11 (1)
+U4004	anonymous	2009-1-11 (1)
+U3FF0	anonymous	2009-1-11 (1)
+U3987	anonymous	2009-1-11 (1)
+U3C87	anonymous	2009-1-11 (1)
+U4D33	anonymous	2009-1-11 (1)
+U38BB	anonymous	2009-1-11 (1)
+U36F8	anonymous	2009-1-11 (1)
+U36F9	anonymous	2009-1-11 (1)
+U3F82	pem	2009-1-11 (1)
+U4A31	anonymous	2009-1-11 (1)
+U388F	anonymous	2009-1-11 (1)
+U4204	anonymous	2009-1-11 (1)
+U38FE	anonymous	2009-1-11 (1)
+U399C	anonymous	2009-1-11 (1)
+U41DB	anonymous	2009-1-11 (1)
+U41DC	anonymous	2009-1-11 (1)
+U34C1	FangQ	2009-1-11 (1)
+U3A47	anonymous	2009-1-11 (1)
+U3D70	anonymous	2009-1-11 (1)
+U341C	anonymous	2009-1-11 (1)
+U3C53	anonymous	2009-1-11 (1)
+U440B	anonymous	2009-1-11 (1)
+U3D99	anonymous	2009-1-11 (1)
+U4273	anonymous	2009-1-11 (1)
+U3535	anonymous	2009-1-11 (1)
+U349D	anonymous	2009-1-11 (1)
+U47B1	anonymous	2009-1-11 (1)
+U47B2	anonymous	2009-1-11 (1)
+U4780	anonymous	2009-1-11 (1)
+U4781	anonymous	2009-1-11 (1)
+U3896	anonymous	2009-1-11 (1)
+U3F81	anonymous	2009-1-11 (1)
+U3F86	anonymous	2009-1-11 (1)
+U4CC9	anonymous	2009-1-11 (1)
+U470C	FangQ	2009-1-11 (1)
+U4CCA	anonymous	2009-1-11 (1)
+U438C	anonymous	2009-1-11 (1)
+U4D3C	anonymous	2009-1-11 (1)
+U4D3A	anonymous	2009-1-11 (1)
+U4915	anonymous	2009-1-11 (1)
+U3D27	anonymous	2009-1-11 (1)
+U34DF	anonymous	2009-1-11 (1)
+U3BAC	anonymous	2009-1-11 (1)
+U40DB	anonymous	2009-1-11 (1)
+U3742	anonymous	2009-1-11 (1)
+U4326	anonymous	2009-1-11 (1)
+U4327	anonymous	2009-1-11 (1)
+U3957	anonymous	2009-1-11 (1)
+U45FC	anonymous	2009-1-11 (1)
+U38B1	anonymous	2009-1-11 (1)
+U4D35	anonymous	2009-1-11 (1)
+U4D3D	anonymous	2009-1-11 (1)
+U38B2	anonymous	2009-1-11 (1)
+U4933	anonymous	2009-1-11 (1)
+U4934	anonymous	2009-1-11 (1)
+U3BE1	anonymous	2009-1-11 (1)
+U48C9	anonymous	2009-1-11 (1)
+U37E7	anonymous	2009-1-11 (1)
+U37E7	anonymous	2009-1-11 (2)
+U48D1	anonymous	2009-1-11 (1)
+U44EB	anonymous	2009-1-11 (1)
+U431A	anonymous	2009-1-11 (1)
+U4782	anonymous	2009-1-11 (1)
+U44EE	anonymous	2009-1-11 (1)
+U4CB6	anonymous	2009-1-11 (1)
+U4330	anonymous	2009-1-11 (1)
+U4D58	anonymous	2009-1-11 (1)
+U35C9	anonymous	2009-1-11 (1)
+U3BC9	anonymous	2009-1-11 (1)
+U4D59	anonymous	2009-1-11 (1)
+U4D5A	anonymous	2009-1-11 (1)
+U3BCD	anonymous	2009-1-11 (1)
+U3E99	anonymous	2009-1-11 (1)
+U3E59	anonymous	2009-1-11 (1)
+U3E5A	anonymous	2009-1-11 (1)
+U3BC7	anonymous	2009-1-11 (1)
+U3BC8	anonymous	2009-1-11 (1)
+U4D08	anonymous	2009-1-11 (1)
+U4D09	anonymous	2009-1-11 (1)
+U4D0D	anonymous	2009-1-11 (1)
+U3B71	anonymous	2009-1-11 (1)
+U4077	anonymous	2009-1-11 (1)
+U432A	anonymous	2009-1-11 (1)
+U34EB	anonymous	2009-1-11 (1)
+U432B	anonymous	2009-1-11 (1)
+U432D	anonymous	2009-1-11 (1)
+U4229	anonymous	2009-1-11 (1)
+U422A	anonymous	2009-1-11 (1)
+U9763	wanghong	2009-1-11 (1)
+U41B0	anonymous	2009-1-11 (1)
+U6C6C	wanghong	2009-1-11 (1)
+U6B6C	wanghong	2009-1-11 (1)
+U4E12	wanghong	2009-1-11 (1)
+U56D9	wanghong	2009-1-11 (1)
+U5F3B	wanghong	2009-1-11 (1)
+U4303	lsz	2009-1-11 (1)
+U5E00	wanghong	2009-1-11 (1)
+U555A	wanghong	2009-1-11 (1)
+U3BF8	anonymous	2009-1-11 (1)
+U3D16	anonymous	2009-1-11 (1)
+U3D17	anonymous	2009-1-11 (1)
+U3813	anonymous	2009-1-11 (1)
+U54DB	wanghong	2009-1-11 (1)
+U706E	wanghong	2009-1-11 (1)
+U48E1	anonymous	2009-1-11 (1)
+U34C2	anonymous	2009-1-11 (1)
+U3B3D	anonymous	2009-1-11 (1)
+U3BC1	anonymous	2009-1-11 (1)
+U3BC2	anonymous	2009-1-11 (1)
+U3BC4	anonymous	2009-1-11 (1)
+U34B1	anonymous	2009-1-11 (1)
+U49F2	anonymous	2009-1-11 (1)
+U49F3	anonymous	2009-1-11 (1)
+U3DC0	anonymous	2009-1-11 (1)
+U4783	anonymous	2009-1-11 (1)
+U3991	anonymous	2009-1-11 (1)
+U3F34	anonymous	2009-1-11 (1)
+U3E25	anonymous	2009-1-11 (1)
+U36C3	anonymous	2009-1-11 (1)
+U34A0	anonymous	2009-1-11 (1)
+U3872	anonymous	2009-1-11 (1)
+U3872	anonymous	2009-1-11 (2)
+U3871	anonymous	2009-1-11 (1)
+U3870	anonymous	2009-1-11 (1)
+U3C48	anonymous	2009-1-11 (1)
+U3F99	anonymous	2009-1-11 (1)
+U4234	anonymous	2009-1-11 (1)
+U3BC6	anonymous	2009-1-11 (1)
+U3682	anonymous	2009-1-11 (1)
+U38A8	anonymous	2009-1-11 (1)
+U3A26	anonymous	2009-1-11 (1)
+U53BD	FangQ	2009-1-11 (1)
+U7B53	FangQ	2009-1-11 (1)
+U343F	anonymous	2009-1-11 (1)
+U5626	FangQ	2009-1-11 (1)
+U7F97	FangQ	2009-1-11 (1)
+U7A6F	FangQ	2009-1-11 (1)
+U380E	anonymous	2009-1-11 (1)
+U5B68	FangQ	2009-1-11 (1)
+U55F4	FangQ	2009-1-11 (1)
+U4AFB		2009-1-11 (1)
+U3902	anonymous	2009-1-11 (1)
+U365A	anonymous	2009-1-11 (1)
+U3659	anonymous	2009-1-11 (1)
+U496F	anonymous	2009-1-11 (1)
+U496E	anonymous	2009-1-11 (1)
+U35EC	anonymous	2009-1-11 (1)
+U3667	anonymous	2009-1-11 (1)
+U366C	anonymous	2009-1-11 (1)
+U3869	FangQ	2009-1-11 (1)
+U366B	anonymous	2009-1-11 (1)
+U4D7D	anonymous	2009-1-11 (1)
+U3C73	anonymous	2009-1-11 (1)
+U35F7	FangQ	2009-1-11 (1)
+U3B75	anonymous	2009-1-11 (1)
+U40B2	anonymous	2009-1-11 (1)
+U40B5	anonymous	2009-1-11 (1)
+U40B9	anonymous	2009-1-11 (1)
+U4BCC	anonymous	2009-1-11 (1)
+U3B21	anonymous	2009-1-11 (1)
+U4C27	anonymous	2009-1-11 (1)
+U40F9	anonymous	2009-1-11 (1)
+U4785	anonymous	2009-1-11 (1)
+U4178	anonymous	2009-1-11 (1)
+U3B2F	anonymous	2009-1-11 (1)
+U3F3F	anonymous	2009-1-11 (1)
+U3F41	anonymous	2009-1-11 (1)
+U407F	anonymous	2009-1-11 (1)
+U3EC4	anonymous	2009-1-11 (1)
+U4A3C	anonymous	2009-1-11 (1)
+U3F8A	anonymous	2009-1-11 (1)
+U408E	anonymous	2009-1-11 (1)
+U40DE	anonymous	2009-1-11 (1)
+U3D35	anonymous	2009-1-11 (1)
+U9578	wanghong	2009-1-11 (1)
+U5B52	wanghong	2009-1-11 (1)
+U5142	wanghong	2009-1-11 (1)
+U5142	wanghong	2009-1-11 (2)
+U41B7	FangQ	2009-1-11 (1)
+U372B	FangQ	2009-1-11 (1)
+U373B	FangQ	2009-1-11 (1)
+U373B	FangQ	2009-1-11 (2)
+U39A1	FangQ	2009-1-11 (1)
+U3A65	FangQ	2009-1-11 (1)
+U3A66	FangQ	2009-1-11 (1)
+U346D	FangQ	2009-1-11 (1)
+U5142	wanghong	2009-1-11 (3)
+U77E6	wanghong	2009-1-11 (1)
+U77E6	wanghong	2009-1-11 (2)
+U7012	FangQ	2009-1-11 (3)
+U6EAC	wanghong	2009-1-11 (1)
+U755E	wanghong	2009-1-11 (1)
+U755E	wanghong	2009-1-11 (2)
+U7742	wanghong	2009-1-11 (1)
+U5928	wanghong	2009-1-11 (1)
+U5928	wanghong	2009-1-11 (2)
+U569E	wanghong	2009-1-11 (1)
+U569E	wanghong	2009-1-11 (2)
+U4907	anonymous	2009-1-11 (1)
+U367D	anonymous	2009-1-11 (1)
+U367E	anonymous	2009-1-11 (1)
+U3681	anonymous	2009-1-11 (1)
+U4282	anonymous	2009-1-11 (1)
+U3F91	yanqian	2009-1-11 (1)
+U4E2F	wanghong	2009-1-11 (1)
+U4E2F	FangQ	2009-1-11 (2)
+U4E06	wanghong	2009-1-11 (1)
+U38D0		2009-1-11 (1)
+U4E41	FangQ	2009-1-11 (1)
+U4E40	FangQ	2009-1-11 (1)
+U6C3A	FangQ	2009-1-11 (1)
+U4E5B	FangQ	2009-1-11 (1)
+U5C70	FangQ	2009-1-11 (1)
+U4316	anonymous	2009-1-11 (1)
+U45E8	anonymous	2009-1-12 (1)
+U4E51	FangQ	2009-1-12 (1)
+U4E51	FangQ	2009-1-12 (2)
+U38A2	anonymous	2009-1-12 (1)
+U45D9	anonymous	2009-1-12 (1)
+U96BA	wanghong	2009-1-12 (1)
+U80F7	wanghong	2009-1-12 (1)
+U89C3	wanghong	2009-1-12 (1)
+U7F80	wanghong	2009-1-12 (1)
+U96BA	wanghong	2009-1-12 (2)
+U8FA5	wanghong	2009-1-12 (1)
+U8FAA	wanghong	2009-1-12 (1)
+U4318	anonymous	2009-1-12 (1)
+U3D71	anonymous	2009-1-12 (1)
+U3D72	anonymous	2009-1-12 (1)
+U3D76	anonymous	2009-1-12 (1)
+U46A8	anonymous	2009-1-12 (1)
+U46AA	anonymous	2009-1-12 (1)
+U46AB	anonymous	2009-1-12 (1)
+U4357	anonymous	2009-1-12 (1)
+U3FA6	anonymous	2009-1-12 (1)
+U3FA7	anonymous	2009-1-12 (1)
+U9C9D	wanghong	2009-1-12 (1)
+U4598	anonymous	2009-1-12 (1)
+U459A	anonymous	2009-1-12 (1)
+U451F	anonymous	2009-1-12 (1)
+U3DD1	anonymous	2009-1-12 (1)
+U46FF	anonymous	2009-1-12 (1)
+U4EB7	wanghong	2009-1-12 (1)
+U4EAA	wanghong	2009-1-12 (1)
+U5F42	wanghong	2009-1-12 (1)
+U44E6		2009-1-12 (1)
+U3994		2009-1-12 (1)
+U44F7		2009-1-12 (1)
+U44F7		2009-1-12 (2)
+U3D7A		2009-1-12 (1)
+U360C		2009-1-12 (1)
+U3DC2	anonymous	2009-1-12 (1)
+U4EB7	wanghong	2009-1-12 (2)
+U4E06	lsz	2009-1-12 (2)
+U8330	lsz	2009-1-12 (1)
+U356E	lsz	2009-1-12 (1)
+U6FD3	wanghong	2009-1-12 (1)
+U48AB	lsz	2009-1-12 (1)
+U4789	anonymous	2009-1-12 (1)
+U428B	anonymous	2009-1-12 (1)
+U4BEA	anonymous	2009-1-12 (1)
+U4485	lsz	2009-1-12 (1)
+U494E	anonymous	2009-1-12 (1)
+U3B8B	anonymous	2009-1-12 (1)
+U4B4B	anonymous	2009-1-12 (1)
+U3874	anonymous	2009-1-12 (1)
+U4417	anonymous	2009-1-12 (1)
+U4201	anonymous	2009-1-12 (1)
+U44C3	anonymous	2009-1-12 (1)
+U44C9	anonymous	2009-1-12 (1)
+U3FD4	anonymous	2009-1-12 (1)
+U482F	anonymous	2009-1-12 (1)
+U3670	anonymous	2009-1-12 (1)
+U3671	anonymous	2009-1-12 (1)
+U4711	anonymous	2009-1-12 (1)
+U441B	anonymous	2009-1-12 (1)
+U3BAE	anonymous	2009-1-12 (1)
+U4088	anonymous	2009-1-12 (1)
+U4191	anonymous	2009-1-12 (1)
+U4192	anonymous	2009-1-12 (1)
+U4193	anonymous	2009-1-12 (1)
+U3D24	anonymous	2009-1-12 (1)
+U46C1	anonymous	2009-1-12 (1)
+U4193	FangQ	2009-1-12 (2)
+U45D7	anonymous	2009-1-12 (1)
+U4272	anonymous	2009-1-12 (1)
+U3DD4	anonymous	2009-1-12 (1)
+U3558	lsz	2009-1-12 (1)
+U3822	lsz	2009-1-12 (1)
+U3827	lsz	2009-1-12 (1)
+U3828	lsz	2009-1-12 (1)
+U3828	lsz	2009-1-12 (2)
+U4969	anonymous	2009-1-12 (1)
+U3D78	lsz	2009-1-12 (1)
+U3D7B	lsz	2009-1-12 (1)
+U3D7B	lsz	2009-1-12 (2)
+U3D7C	lsz	2009-1-12 (1)
+U498A	lsz	2009-1-12 (1)
+U498A	lsz	2009-1-12 (2)
+U4931	anonymous	2009-1-12 (1)
+U492F	anonymous	2009-1-12 (1)
+U4089	anonymous	2009-1-12 (1)
+U4480	lsz	2009-1-12 (1)
+U4484	lsz	2009-1-12 (1)
+U4969	FangQ	2009-1-12 (2)
+U3677	anonymous	2009-1-12 (1)
+U3AED	anonymous	2009-1-12 (1)
+U419F	anonymous	2009-1-12 (1)
+U479C		2009-1-12 (1)
+U41A0	anonymous	2009-1-12 (1)
+U38D1		2009-1-12 (1)
+U4D66		2009-1-13 (1)
+U3675		2009-1-13 (1)
+U48AE	pem	2009-1-13 (1)
+U48B0	pem	2009-1-13 (1)
+U39B3	yanqian	2009-1-13 (1)
+U4C99	anonymous	2009-1-13 (1)
+U3BA7	anonymous	2009-1-13 (1)
+U3413	anonymous	2009-1-13 (1)
+U3F5C	anonymous	2009-1-13 (1)
+U3790	anonymous	2009-1-13 (1)
+U3790	anonymous	2009-1-13 (2)
+U3BA8	anonymous	2009-1-13 (1)
+U3BEC	anonymous	2009-1-13 (1)
+U3BEC	anonymous	2009-1-13 (2)
+U3BEC	anonymous	2009-1-13 (3)
+U3BEC	anonymous	2009-1-13 (4)
+U3BEC	anonymous	2009-1-13 (5)
+U3BEC	anonymous	2009-1-13 (6)
+U41F5	anonymous	2009-1-13 (1)
+U4209	anonymous	2009-1-13 (1)
+U420A	anonymous	2009-1-13 (1)
+U3479	anonymous	2009-1-13 (1)
+U3479	anonymous	2009-1-13 (2)
+U3479	anonymous	2009-1-13 (3)
+U3479	anonymous	2009-1-13 (4)
+U3C47	anonymous	2009-1-13 (1)
+U3C42	anonymous	2009-1-13 (1)
+U4392	anonymous	2009-1-13 (1)
+U347C	anonymous	2009-1-13 (1)
+U3C22	anonymous	2009-1-13 (1)
+U438F	anonymous	2009-1-13 (1)
+U4603	anonymous	2009-1-13 (1)
+U3C23	anonymous	2009-1-13 (1)
+U3C25	anonymous	2009-1-13 (1)
+U49F6	anonymous	2009-1-13 (1)
+U49F0	anonymous	2009-1-13 (1)
+U49F7	anonymous	2009-1-13 (1)
+U4B38	anonymous	2009-1-13 (1)
+U4B46	anonymous	2009-1-13 (1)
+U4B46	anonymous	2009-1-13 (2)
+U4484		2009-1-13 (2)
+U4484		2009-1-13 (3)
+U4831	anonymous	2009-1-13 (1)
+U348A	anonymous	2009-1-13 (1)
+U4B70	anonymous	2009-1-13 (1)
+U4B70	anonymous	2009-1-13 (2)
+U3BA1	anonymous	2009-1-13 (1)
+U4743	anonymous	2009-1-13 (1)
+U473F	anonymous	2009-1-13 (1)
+U473C	anonymous	2009-1-13 (1)
+U4695	anonymous	2009-1-13 (1)
+U4696	anonymous	2009-1-13 (1)
+U3C49	anonymous	2009-1-13 (1)
+U395B	anonymous	2009-1-13 (1)
+U41E1	anonymous	2009-1-13 (1)
+U398E	anonymous	2009-1-13 (1)
+U398F	anonymous	2009-1-13 (1)
+U479D	anonymous	2009-1-13 (1)
+U3873	anonymous	2009-1-13 (1)
+U3875	anonymous	2009-1-13 (1)
+U479F	anonymous	2009-1-13 (1)
+U3986	anonymous	2009-1-13 (1)
+U3989	anonymous	2009-1-13 (1)
+U4B59	anonymous	2009-1-13 (1)
+U41A6	anonymous	2009-1-13 (1)
+U450B	anonymous	2009-1-13 (1)
+U450B	anonymous	2009-1-13 (2)
+U3D29	anonymous	2009-1-13 (1)
+U3FC8	anonymous	2009-1-13 (1)
+U3D46	anonymous	2009-1-13 (1)
+U3D45	anonymous	2009-1-13 (1)
+U423A	anonymous	2009-1-13 (1)
+U4202	anonymous	2009-1-13 (1)
+U48DC	anonymous	2009-1-13 (1)
+U3DDD	anonymous	2009-1-13 (1)
+U4B3B	anonymous	2009-1-13 (1)
+U4CFE	anonymous	2009-1-13 (1)
+U4CFD	anonymous	2009-1-13 (1)
+U347B	anonymous	2009-1-13 (1)
+U3477	anonymous	2009-1-13 (1)
+U471C	anonymous	2009-1-13 (1)
+U3F58	anonymous	2009-1-13 (1)
+U4976	anonymous	2009-1-13 (1)
+U3BFC	anonymous	2009-1-13 (1)
+U4220	anonymous	2009-1-13 (1)
+U4D85	anonymous	2009-1-13 (1)
+U352C	anonymous	2009-1-13 (1)
+U41E3	anonymous	2009-1-13 (1)
+U4A3D	anonymous	2009-1-13 (1)
+U4A3D	anonymous	2009-1-13 (2)
+U4A3D	anonymous	2009-1-13 (3)
+U4499	anonymous	2009-1-13 (1)
+U4499	anonymous	2009-1-13 (2)
+U4499	anonymous	2009-1-13 (3)
+U4487		2009-1-13 (1)
+U4499		2009-1-13 (4)
+U4499		2009-1-13 (5)
+U3A24	anonymous	2009-1-13 (1)
+U3676	anonymous	2009-1-13 (1)
+U40DD	anonymous	2009-1-13 (1)
+U40E7	anonymous	2009-1-13 (1)
+U40E6	anonymous	2009-1-13 (1)
+U3678	anonymous	2009-1-13 (1)
+U3679	anonymous	2009-1-13 (1)
+U4389	anonymous	2009-1-13 (1)
+U4397	anonymous	2009-1-13 (1)
+U4398	anonymous	2009-1-13 (1)
+U3D7E	anonymous	2009-1-13 (1)
+U3D7F	anonymous	2009-1-13 (1)
+U3D80	anonymous	2009-1-13 (1)
+U3737	anonymous	2009-1-13 (1)
+U373C	anonymous	2009-1-13 (1)
+U3745	anonymous	2009-1-13 (1)
+U4909	anonymous	2009-1-13 (1)
+U490A	anonymous	2009-1-13 (1)
+U428D	anonymous	2009-1-13 (1)
+U420C	anonymous	2009-1-13 (1)
+U3AAB	anonymous	2009-1-13 (1)
+U3AAC	anonymous	2009-1-13 (1)
+U3C4A	anonymous	2009-1-13 (1)
+U4773	anonymous	2009-1-13 (1)
+U4774	anonymous	2009-1-13 (1)
+U4771	anonymous	2009-1-13 (1)
+U40E8	anonymous	2009-1-13 (1)
+U49FA	anonymous	2009-1-13 (1)
+U4A00	anonymous	2009-1-13 (1)
+U3AE4	anonymous	2009-1-13 (1)
+U3685	anonymous	2009-1-13 (1)
+U3753	anonymous	2009-1-13 (1)
+U3D6D	anonymous	2009-1-13 (1)
+U4CBE	anonymous	2009-1-13 (1)
+U4CC7	anonymous	2009-1-13 (1)
+U44FD	anonymous	2009-1-13 (1)
+U44FD	anonymous	2009-1-13 (2)
+U3D30	anonymous	2009-1-13 (1)
+U6B2A	FangQ	2009-1-13 (2)
+U902C	FangQ	2009-1-13 (2)
+U9C26	FangQ	2009-1-13 (2)
+U4AFD	anonymous	2009-1-13 (1)
+U4AC8		2009-1-13 (1)
+U4974	anonymous	2009-1-13 (1)
+U41BE	anonymous	2009-1-13 (1)
+U41BF	anonymous	2009-1-13 (1)
+U4CD9		2009-1-13 (1)
+U8965	FangQ	2009-1-13 (4)
+U6617	FangQ	2009-1-13 (2)
+U49B9	anonymous	2009-1-14 (1)
+U4BB9	anonymous	2009-1-14 (1)
+U4B6D	anonymous	2009-1-14 (1)
+U3748	anonymous	2009-1-14 (1)
+U3748	anonymous	2009-1-14 (2)
+U3747	anonymous	2009-1-14 (1)
+U3754	anonymous	2009-1-14 (1)
+U4566	anonymous	2009-1-14 (1)
+U34D8	anonymous	2009-1-14 (1)
+U47C2	anonymous	2009-1-14 (1)
+U4730	anonymous	2009-1-14 (1)
+U4508	anonymous	2009-1-14 (1)
+U3932	anonymous	2009-1-14 (1)
+U3AC0	anonymous	2009-1-14 (1)
+U9C35		2009-1-14 (2)
+U65C0		2009-1-14 (2)
+U7BFA		2009-1-14 (2)
+U7C24		2009-1-14 (2)
+U96E4		2009-1-14 (2)
+U8B9B		2009-1-14 (2)
+U560A		2009-1-14 (2)
+U882D		2009-1-14 (2)
+U85BC		2009-1-14 (2)
+U96E4		2009-1-14 (3)
+U85BC		2009-1-14 (3)
+U560A		2009-1-14 (3)
+U4BEB	anonymous	2009-1-14 (1)
+U3AC0		2009-1-14 (2)
+U4AFF	wanghong	2009-1-14 (1)
+U394B	anonymous	2009-1-14 (1)
+U48F9	pem	2009-1-14 (1)
+U48FF	pem	2009-1-14 (1)
+U4544	anonymous	2009-1-14 (1)
+U3FEE	anonymous	2009-1-14 (1)
+U34D9	anonymous	2009-1-14 (1)
+U4671	anonymous	2009-1-14 (1)
+U3D4B	anonymous	2009-1-14 (1)
+U3DE3	anonymous	2009-1-14 (1)
+U4D53	anonymous	2009-1-14 (1)
+U4D53	anonymous	2009-1-14 (2)
+U4D54	anonymous	2009-1-14 (1)
+U4D5C	anonymous	2009-1-14 (1)
+U4D5B	anonymous	2009-1-14 (1)
+U49BA	anonymous	2009-1-14 (1)
+U49B8	anonymous	2009-1-14 (1)
+U49B7	anonymous	2009-1-14 (1)
+U4CE4	anonymous	2009-1-14 (1)
+U431D	anonymous	2009-1-14 (1)
+U96E4	wanghong	2009-1-14 (4)
+U5753	wanghong	2009-1-14 (2)
+U375C	anonymous	2009-1-14 (1)
+U4588	anonymous	2009-1-14 (1)
+U4588	anonymous	2009-1-14 (2)
+U3FF4	anonymous	2009-1-14 (1)
+U4588	FangQ	2009-1-14 (3)
+U3FF4	FangQ	2009-1-14 (2)
+U375C	FangQ	2009-1-14 (2)
+U49B9	FangQ	2009-1-14 (2)
+U5172	lsz	2009-1-14 (2)
+U5342	lsz	2009-1-14 (2)
+U3E17	anonymous	2009-1-14 (1)
+U3C88	anonymous	2009-1-14 (1)
+U3C88	anonymous	2009-1-14 (2)
+U3C88	anonymous	2009-1-14 (3)
+U3AF3	anonymous	2009-1-14 (1)
+U40EC	anonymous	2009-1-14 (1)
+U4631	anonymous	2009-1-14 (1)
+U4631	anonymous	2009-1-14 (2)
+U4B02	anonymous	2009-1-15 (1)
+U3DD8	anonymous	2009-1-15 (1)
+U3BB7	anonymous	2009-1-15 (1)
+U9025	wanghong	2009-1-15 (2)
+U3B7F		2009-1-15 (1)
+U3F3E		2009-1-15 (1)
+U3F3E		2009-1-15 (2)
+U48E1		2009-1-15 (2)
+U431E	anonymous	2009-1-15 (1)
+U4CF4	lsz	2009-1-15 (1)
+U4CF4	lsz	2009-1-15 (2)
+U3EF9	lsz	2009-1-15 (1)
+U423B	anonymous	2009-1-15 (1)
+U423B	anonymous	2009-1-15 (2)
+U4D86	anonymous	2009-1-15 (1)
+U38D2	anonymous	2009-1-15 (1)
+U3B9F	anonymous	2009-1-15 (1)
+U46DA	anonymous	2009-1-15 (1)
+U40EF	anonymous	2009-1-15 (1)
+U3A1C	anonymous	2009-1-15 (1)
+U48DF	anonymous	2009-1-15 (1)
+U3FA1	lsz	2009-1-15 (1)
+U3B09	lsz	2009-1-15 (1)
+U4264	anonymous	2009-1-15 (1)
+U4264	anonymous	2009-1-15 (2)
+U4A15	anonymous	2009-1-15 (1)
+U4A16	anonymous	2009-1-15 (1)
+U4A15	FangQ	2009-1-15 (2)
+U4A16	FangQ	2009-1-15 (2)
+U4E68	FangQ	2009-1-15 (2)
+U4F0C	FangQ	2009-1-15 (2)
+U40FA		2009-1-15 (1)
+U4F23	FangQ	2009-1-15 (2)
+U4F28	FangQ	2009-1-15 (2)
+U4F66	FangQ	2009-1-15 (2)
+U4F8C	FangQ	2009-1-15 (2)
+U4884		2009-1-15 (1)
+U4FE2	FangQ	2009-1-15 (2)
+U5422	FangQ	2009-1-15 (2)
+U5422	FangQ	2009-1-15 (3)
+U4FE7	FangQ	2009-1-15 (2)
+U4FEB	FangQ	2009-1-15 (2)
+U4FF2	FangQ	2009-1-15 (2)
+U5A91	anonymous	2009-1-15 (2)
+U5ACF	anonymous	2009-1-15 (2)
+U5ACF	anonymous	2009-1-15 (3)
+U4FF9	FangQ	2009-1-16 (2)
+U503D	FangQ	2009-1-16 (2)
+U63B6	pem	2009-1-16 (2)
+U6393	pem	2009-1-16 (2)
+U51E5	FangQ	2009-1-16 (2)
+U51F4	FangQ	2009-1-16 (2)
+U638B	pem	2009-1-16 (2)
+U638B	pem	2009-1-16 (3)
+U638B	pem	2009-1-16 (4)
+U4ED0	FangQ	2009-1-16 (2)
+U5183	FangQ	2009-1-16 (2)
+U518B	FangQ	2009-1-16 (2)
+U4F71	FangQ	2009-1-16 (2)
+U4E72	FangQ	2009-1-16 (2)
+U4E72	FangQ	2009-1-16 (3)
+U4E6E	FangQ	2009-1-16 (2)
+U4E64	FangQ	2009-1-16 (2)
+U63FB	pem	2009-1-16 (2)
+U63FE	pem	2009-1-16 (2)
+U6455	pem	2009-1-16 (2)
+U645A	pem	2009-1-16 (2)
+U6480	pem	2009-1-16 (2)
+U64A7	pem	2009-1-16 (2)
+U64A7	pem	2009-1-16 (3)
+U6542	pem	2009-1-16 (2)
+U6544	pem	2009-1-16 (2)
+U6547	pem	2009-1-16 (2)
+U654B	pem	2009-1-16 (2)
+U655A	pem	2009-1-16 (2)
+U655F	pem	2009-1-16 (2)
+U655F	pem	2009-1-16 (3)
+U6560	pem	2009-1-16 (2)
+U657D	pem	2009-1-16 (2)
+U658F	pem	2009-1-16 (2)
+U6598	pem	2009-1-16 (2)
+U6598	pem	2009-1-16 (3)
+U6598	pem	2009-1-16 (4)
+U6758	pem	2009-1-16 (2)
+U6758	pem	2009-1-16 (3)
+U6856	pem	2009-1-16 (2)
+U6856	pem	2009-1-16 (3)
+U685A	pem	2009-1-16 (2)
+U685B	pem	2009-1-16 (2)
+U6830	pem	2009-1-16 (2)
+U6830	pem	2009-1-16 (3)
+U683F	pem	2009-1-16 (2)
+U683F	pem	2009-1-16 (3)
+U683F	pem	2009-1-16 (4)
+U681B	pem	2009-1-16 (3)
+U6824	pem	2009-1-16 (2)
+U6824	pem	2009-1-16 (3)
+U6847	pem	2009-1-16 (2)
+U682C	pem	2009-1-16 (2)
+U67E8	pem	2009-1-16 (2)
+U6815	pem	2009-1-16 (2)
+U6754	pem	2009-1-16 (2)
+U6724	pem	2009-1-16 (2)
+U6724	pem	2009-1-16 (3)
+U671A	pem	2009-1-16 (2)
+U66EA	pem	2009-1-16 (2)
+U66E7	pem	2009-1-16 (2)
+U66E7	pem	2009-1-16 (3)
+U66E7	pem	2009-1-16 (4)
+U671A	wanghong	2009-1-16 (3)
+U3780	anonymous	2009-1-16 (1)
+U3792	anonymous	2009-1-16 (1)
+U9CC2	lsz	2009-1-16 (2)
+U44AF	anonymous	2009-1-16 (1)
+U9CDA	lsz	2009-1-16 (2)
+U9CE3	lsz	2009-1-16 (2)
+U44AC	anonymous	2009-1-16 (1)
+U9CEE	lsz	2009-1-16 (2)
+U9CEF	lsz	2009-1-16 (2)
+U39A4	anonymous	2009-1-16 (1)
+U9D47	lsz	2009-1-16 (2)
+U9D95	lsz	2009-1-16 (2)
+U9DE0	lsz	2009-1-16 (2)
+U3594	anonymous	2009-1-16 (1)
+U9DEA	lsz	2009-1-16 (2)
+U348C	anonymous	2009-1-16 (1)
+U4B01	anonymous	2009-1-16 (1)
+U3CDA	anonymous	2009-1-16 (1)
+U38D3	anonymous	2009-1-16 (1)
+U4A02	anonymous	2009-1-16 (1)
+U4AE4	anonymous	2009-1-16 (1)
+U4AE9	anonymous	2009-1-16 (1)
+U4AE2	anonymous	2009-1-16 (1)
+U3958	anonymous	2009-1-16 (1)
+U343A	anonymous	2009-1-16 (1)
+U4C34	anonymous	2009-1-16 (1)
+U4926	anonymous	2009-1-16 (1)
+U3AA0	anonymous	2009-1-16 (1)
+U3AA2	anonymous	2009-1-16 (1)
+U9E27	lsz	2009-1-16 (2)
+U9E5F	lsz	2009-1-16 (2)
+U9E65	lsz	2009-1-16 (2)
+U9E96	lsz	2009-1-16 (2)
+U9EC7	lsz	2009-1-16 (2)
+U9ECA	lsz	2009-1-16 (2)
+U9EF1	lsz	2009-1-16 (2)
+U9F02	lsz	2009-1-16 (2)
+U9F3C	lsz	2009-1-16 (2)
+U9F68	lsz	2009-1-16 (2)
+U9F7C	lsz	2009-1-16 (2)
+U9F93	lsz	2009-1-16 (2)
+U9F9E	lsz	2009-1-16 (2)
+U9FA8	lsz	2009-1-16 (2)
+U9FB1	lsz	2009-1-16 (2)
+U67E8	pem	2009-1-16 (3)
+U65D4	pem	2009-1-16 (2)
+U65E4	pem	2009-1-16 (2)
+U65E4	pem	2009-1-16 (3)
+U521F	FangQ	2009-1-16 (2)
+U65E4	pem	2009-1-16 (4)
+U5223	FangQ	2009-1-16 (2)
+U523C	FangQ	2009-1-16 (3)
+U523E	FangQ	2009-1-16 (2)
+U5248	FangQ	2009-1-16 (2)
+U5257	FangQ	2009-1-16 (2)
+U5260	FangQ	2009-1-16 (2)
+U5276	FangQ	2009-1-16 (2)
+U65F9	pem	2009-1-16 (2)
+U52ED	FangQ	2009-1-16 (2)
+U52C8	FangQ	2009-1-16 (2)
+U5285	FangQ	2009-1-16 (2)
+U52B8	FangQ	2009-1-16 (2)
+U52C6	FangQ	2009-1-16 (2)
+U52E1	FangQ	2009-1-16 (2)
+U6618	pem	2009-1-16 (2)
+U52DC	FangQ	2009-1-16 (2)
+U5AF0	anonymous	2009-1-16 (2)
+U6648	pem	2009-1-16 (2)
+U5387	FangQ	2009-1-16 (2)
+U664E	pem	2009-1-16 (2)
+U545A	FangQ	2009-1-16 (4)
+U54CB	FangQ	2009-1-16 (2)
+U5B00	anonymous	2009-1-16 (2)
+U551D	FangQ	2009-1-16 (3)
+U5B00	anonymous	2009-1-16 (3)
+U5B61	anonymous	2009-1-16 (2)
+U67E8	FangQ	2009-1-16 (4)
+U378B	anonymous	2009-1-16 (1)
+U6660	pem	2009-1-16 (2)
+U6660	pem	2009-1-16 (3)
+U3FAB	anonymous	2009-1-16 (1)
+U6663	pem	2009-1-16 (2)
+U6663	pem	2009-1-16 (3)
+U669A	pem	2009-1-16 (2)
+U3A46	anonymous	2009-1-16 (1)
+U3990	anonymous	2009-1-16 (1)
+U4B81	anonymous	2009-1-16 (1)
+U4555	anonymous	2009-1-16 (1)
+U5529	FangQ	2009-1-16 (2)
+U4956	anonymous	2009-1-16 (1)
+U4951	anonymous	2009-1-16 (1)
+U4950	anonymous	2009-1-16 (1)
+U377A	anonymous	2009-1-16 (1)
+U6374	anonymous	2009-1-16 (2)
+U5CC2	kmc	2009-1-16 (2)
+U5CB2	kmc	2009-1-16 (2)
+U55BA	FangQ	2009-1-16 (2)
+U55D8	FangQ	2009-1-16 (2)
+U559B	FangQ	2009-1-16 (2)
+U55E0	FangQ	2009-1-16 (2)
+U55EE	FangQ	2009-1-16 (2)
+U560B	FangQ	2009-1-16 (2)
+U562B	FangQ	2009-1-16 (2)
+U5644	FangQ	2009-1-16 (2)
+U5675	FangQ	2009-1-16 (2)
+U510E	FangQ	2009-1-16 (2)
+U50A4	FangQ	2009-1-16 (2)
+U50A4	FangQ	2009-1-16 (3)
+U50A4	FangQ	2009-1-16 (4)
+U5388	FangQ	2009-1-16 (2)
+U55BA	FangQ	2009-1-16 (3)
+U53DA	FangQ	2009-1-16 (2)
+U53DA	FangQ	2009-1-16 (3)
+U5A2A	anonymous	2009-1-16 (2)
+U5921	anonymous	2009-1-16 (2)
+U5921	anonymous	2009-1-16 (3)
+U593F	anonymous	2009-1-16 (2)
+U593F	anonymous	2009-1-16 (3)
+U57CA	anonymous	2009-1-16 (2)
+U5812	anonymous	2009-1-16 (2)
+U57FF	anonymous	2009-1-16 (2)
+U5A6B	anonymous	2009-1-16 (2)
+U5736	anonymous	2009-1-16 (3)
+U967B	lsz	2009-1-16 (2)
+U967F	lsz	2009-1-16 (2)
+U9681	lsz	2009-1-16 (2)
+U96AD	lsz	2009-1-16 (2)
+U9731	lsz	2009-1-16 (2)
+U9737	lsz	2009-1-16 (2)
+U9763	lsz	2009-1-16 (2)
+U979F	lsz	2009-1-16 (2)
+U97BA	lsz	2009-1-16 (2)
+U97BE	lsz	2009-1-16 (2)
+U97DA	lsz	2009-1-16 (2)
+U97EF	lsz	2009-1-16 (2)
+U980B	lsz	2009-1-16 (2)
+U9823	lsz	2009-1-16 (2)
+U9825	lsz	2009-1-16 (2)
+U988B	lsz	2009-1-16 (2)
+U9823	lsz	2009-1-16 (3)
+U9825	lsz	2009-1-16 (3)
+U4930	anonymous	2009-1-16 (1)
+U4939	anonymous	2009-1-16 (1)
+U6724	FangQ	2009-1-16 (4)
+U6480	FangQ	2009-1-16 (3)
+U63B6	FangQ	2009-1-16 (3)
+U98C5	lsz	2009-1-16 (2)
+U98C5	lsz	2009-1-16 (3)
+U56BA	FangQ	2009-1-16 (2)
+U56BF	FangQ	2009-1-16 (3)
+U57FF	FangQ	2009-1-16 (3)
+U567D	FangQ	2009-1-16 (2)
+U586E	FangQ	2009-1-16 (2)
+U5843	FangQ	2009-1-16 (2)
+U57EA	FangQ	2009-1-16 (2)
+U57DE	FangQ	2009-1-16 (2)
+U5812	FangQ	2009-1-16 (3)
+U5736	FangQ	2009-1-16 (4)
+U5748	FangQ	2009-1-16 (2)
+U5A0E	FangQ	2009-1-16 (2)
+U58CD	FangQ	2009-1-16 (2)
+U5A26	FangQ	2009-1-16 (3)
+U5A59	FangQ	2009-1-16 (2)
+U5A68	FangQ	2009-1-16 (2)
+U5A6B	FangQ	2009-1-16 (3)
+U59E2	FangQ	2009-1-16 (2)
+U5A71	FangQ	2009-1-16 (2)
+U5AA3	FangQ	2009-1-16 (2)
+U5A85	FangQ	2009-1-16 (2)
+U5AAD	FangQ	2009-1-16 (2)
+U5B0A	FangQ	2009-1-17 (3)
+U5AD1	FangQ	2009-1-17 (3)
+U5B8A	FangQ	2009-1-17 (2)
+U5C2E	FangQ	2009-1-17 (2)
+U5BAF	FangQ	2009-1-17 (2)
+U5C36	FangQ	2009-1-17 (2)
+U5B00	FangQ	2009-1-17 (4)
+U57CA	FangQ	2009-1-17 (3)
+U5A8D	FangQ	2009-1-17 (2)
+U5AE4	FangQ	2009-1-17 (2)
+U5AEF	FangQ	2009-1-17 (2)
+U3D89		2009-1-17 (1)
+U42B2	anonymous	2009-1-17 (1)
+U3A18	anonymous	2009-1-17 (1)
+U4460	anonymous	2009-1-17 (1)
+U47C0	anonymous	2009-1-17 (1)
+U47C0	anonymous	2009-1-17 (2)
+U375E	anonymous	2009-1-17 (1)
+U98CA	lsz	2009-1-17 (2)
+U98CF	lsz	2009-1-17 (2)
+U9926	lsz	2009-1-17 (2)
+U999B	lsz	2009-1-17 (2)
+U999F	lsz	2009-1-17 (2)
+U99AA	lsz	2009-1-17 (2)
+U99B6	lsz	2009-1-17 (2)
+U99B8	lsz	2009-1-17 (2)
+U99E1	lsz	2009-1-17 (2)
+U9AB2	lsz	2009-1-17 (2)
+U9AB5	lsz	2009-1-17 (2)
+U9ADB	lsz	2009-1-17 (2)
+U9AE4	lsz	2009-1-17 (2)
+U9AF5	lsz	2009-1-17 (2)
+U9B38	lsz	2009-1-17 (3)
+U9B40	lsz	2009-1-17 (2)
+U9B5D	lsz	2009-1-17 (2)
+U9B78	lsz	2009-1-17 (2)
+U9BB0	lsz	2009-1-17 (3)
+U9BB7	lsz	2009-1-17 (2)
+U6918		2009-1-17 (2)
+U9BC2	lsz	2009-1-17 (3)
+U685E		2009-1-17 (2)
+U9BC5	lsz	2009-1-17 (3)
+U6888		2009-1-17 (2)
+U9C19	lsz	2009-1-17 (2)
+U68ED		2009-1-17 (2)
+U9C5D	lsz	2009-1-17 (2)
+U68FE		2009-1-17 (2)
+U9C7D	lsz	2009-1-17 (2)
+U9C7D	lsz	2009-1-17 (3)
+U9C7E	lsz	2009-1-17 (2)
+U9C8C	lsz	2009-1-17 (2)
+U9C93	lsz	2009-1-17 (2)
+U9CAC	lsz	2009-1-17 (2)
+U6909		2009-1-17 (2)
+U692E		2009-1-17 (3)
+U6931		2009-1-17 (4)
+U698F		2009-1-17 (2)
+U69B8		2009-1-17 (2)
+U69C5		2009-1-17 (2)
+U70A3		2009-1-17 (2)
+U7087		2009-1-17 (2)
+U7053		2009-1-17 (2)
+U6FF8		2009-1-17 (4)
+U69DA		2009-1-17 (2)
+U69FA		2009-1-17 (2)
+U6A43		2009-1-17 (3)
+U6A45		2009-1-17 (2)
+U69D5		2009-1-17 (2)
+U6A74		2009-1-17 (2)
+U6A75		2009-1-17 (2)
+U6A7A		2009-1-17 (3)
+U6A7D		2009-1-17 (2)
+U6F04		2009-1-17 (2)
+U6F44		2009-1-17 (2)
+U6E6C		2009-1-17 (2)
+U6E6C		2009-1-17 (3)
+U6F59		2009-1-17 (2)
+U6E01		2009-1-17 (2)
+U6E6A		2009-1-17 (3)
+U6DE7		2009-1-17 (2)
+U6AF5		2009-1-17 (2)
+U6D1C		2009-1-17 (2)
+U6CA8		2009-1-17 (2)
+U6BFA		2009-1-17 (2)
+U6BF6		2009-1-17 (2)
+U6BE9		2009-1-17 (2)
+U6BBE		2009-1-17 (2)
+U6B52		2009-1-17 (2)
+U6B4F		2009-1-17 (2)
+U6B44		2009-1-17 (2)
+U6B26		2009-1-17 (2)
+U6B1C		2009-1-17 (2)
+U69DA		2009-1-17 (3)
+U6F9D		2009-1-17 (2)
+U6A63		2009-1-17 (9)
+U6BEE		2009-1-17 (2)
+U6A86		2009-1-17 (3)
+U6E59		2009-1-17 (2)
+U6E59	wanghong	2009-1-17 (3)
+U6E59	wanghong	2009-1-17 (4)
+U6E59	wanghong	2009-1-17 (5)
+U4D22	anonymous	2009-1-17 (1)
+U4B79	anonymous	2009-1-17 (1)
+U4B7B	anonymous	2009-1-17 (1)
+U4D1A	anonymous	2009-1-17 (1)
+U4D1B	anonymous	2009-1-17 (1)
+U360B	anonymous	2009-1-17 (1)
+U3D2E	anonymous	2009-1-17 (1)
+U3D93	anonymous	2009-1-17 (1)
+U3D69	anonymous	2009-1-17 (1)
+U3F08	anonymous	2009-1-17 (1)
+U4529	anonymous	2009-1-17 (1)
+U450D	anonymous	2009-1-17 (1)
+U4D1C	anonymous	2009-1-17 (1)
+U3C4F	anonymous	2009-1-17 (1)
+U3508	anonymous	2009-1-17 (1)
+U44FB	anonymous	2009-1-17 (1)
+U4407	anonymous	2009-1-17 (1)
+U39B9	anonymous	2009-1-17 (1)
+U4008	anonymous	2009-1-17 (1)
+U3C4F	FangQ	2009-1-17 (2)
+U66D0	FangQ	2009-1-17 (2)
+U66DF	FangQ	2009-1-17 (2)
+U66DF	FangQ	2009-1-17 (3)
+U66E1	FangQ	2009-1-17 (2)
+U66E1	FangQ	2009-1-17 (3)
+U5817	FangQ	2009-1-17 (2)
+U5921	FangQ	2009-1-17 (4)
+U59DF	FangQ	2009-1-17 (2)
+U5A10	FangQ	2009-1-17 (2)
+U5A2A	FangQ	2009-1-17 (3)
+U3B86	anonymous	2009-1-17 (1)
+U5B3B	FangQ	2009-1-17 (2)
+U5AF0	FangQ	2009-1-17 (3)
+U5B18	FangQ	2009-1-17 (2)
+U5B12	FangQ	2009-1-17 (2)
+U5ACF	FangQ	2009-1-17 (4)
+U5A91	FangQ	2009-1-17 (3)
+U5A82	FangQ	2009-1-17 (2)
+U5C2E	FangQ	2009-1-17 (3)
+U5B06	FangQ	2009-1-17 (2)
+U577E	FangQ	2009-1-17 (2)
+U4E02	FangQ	2009-1-17 (2)
+U4E20	FangQ	2009-1-17 (2)
+U4E20	FangQ	2009-1-17 (3)
+U4EAF	FangQ	2009-1-17 (2)
+U517A	FangQ	2009-1-17 (2)
+U5003	FangQ	2009-1-17 (2)
+U5079	FangQ	2009-1-17 (3)
+U5079	FangQ	2009-1-17 (4)
+U4FA2	FangQ	2009-1-17 (2)
+U50A1	FangQ	2009-1-17 (2)
+U3D38	anonymous	2009-1-17 (1)
+U5304	FangQ	2009-1-17 (2)
+U5205	FangQ	2009-1-17 (2)
+U5205	FangQ	2009-1-17 (3)
+U5205	FangQ	2009-1-17 (4)
+U51E8	FangQ	2009-1-17 (2)
+U51EE	FangQ	2009-1-17 (2)
+U4700	anonymous	2009-1-17 (1)
+U4702	anonymous	2009-1-17 (1)
+U51F2	FangQ	2009-1-17 (2)
+U501D	FangQ	2009-1-17 (2)
+U51A7	FangQ	2009-1-17 (2)
+U3B1E	anonymous	2009-1-17 (1)
+U5166	FangQ	2009-1-17 (2)
+U5166	FangQ	2009-1-17 (3)
+U6E6C		2009-1-17 (4)
+U9FB4	FangQ	2009-1-17 (1)
+U9FB9	FangQ	2009-1-17 (1)
+U9FB8	FangQ	2009-1-17 (1)
+U8002	FangQ	2009-1-17 (1)
+U713D		2009-1-17 (2)
+U7151		2009-1-17 (2)
+U7175		2009-1-17 (3)
+U718B		2009-1-17 (2)
+U71AD		2009-1-17 (2)
+U71AE		2009-1-17 (2)
+U71B6		2009-1-17 (2)
+U71CD		2009-1-17 (2)
+U71E9		2009-1-17 (2)
+U479E	kmc	2009-1-17 (1)
+U71EA		2009-1-17 (2)
+U71EF		2009-1-17 (2)
+U720B		2009-1-17 (2)
+U7224		2009-1-17 (2)
+U4799	kmc	2009-1-17 (1)
+U7250		2009-1-17 (2)
+U7255		2009-1-17 (3)
+U72C7		2009-1-17 (2)
+U72C7		2009-1-17 (3)
+U7306		2009-1-17 (2)
+U7346		2009-1-17 (2)
+U7348		2009-1-17 (2)
+U7353		2009-1-17 (2)
+U735C		2009-1-17 (2)
+U7371		2009-1-17 (2)
+U7399		2009-1-17 (2)
+U73D5		2009-1-17 (2)
+U7402		2009-1-17 (2)
+U9402	wanghong	2009-1-17 (3)
+U741E		2009-1-17 (2)
+U741F		2009-1-17 (2)
+U743B		2009-1-17 (2)
+U3F07	kmc	2009-1-17 (1)
+U7461		2009-1-17 (2)
+U746B		2009-1-17 (3)
+U7478		2009-1-17 (2)
+U4399	kmc	2009-1-17 (1)
+U74A4		2009-1-17 (2)
+U74CD		2009-1-17 (2)
+U74D3		2009-1-17 (2)
+U74F3		2009-1-17 (2)
+U7509		2009-1-17 (2)
+U750A		2009-1-17 (2)
+U42B4	kmc	2009-1-17 (1)
+U4D6F	kmc	2009-1-17 (1)
+U76CC		2009-1-17 (2)
+U76C0		2009-1-17 (2)
+U76BC		2009-1-17 (2)
+U76A9		2009-1-17 (2)
+U76A1		2009-1-17 (2)
+U7677		2009-1-17 (2)
+U488A	kmc	2009-1-17 (1)
+U765B		2009-1-17 (2)
+U76B6		2009-1-17 (2)
+U41AD	kmc	2009-1-17 (1)
+U41AE	kmc	2009-1-17 (1)
+U75D3		2009-1-17 (2)
+U759E		2009-1-17 (2)
+U75A8		2009-1-17 (2)
+U4428	kmc	2009-1-17 (1)
+U8FB8		2009-1-17 (2)
+U4512	kmc	2009-1-17 (1)
+U3D52	kmc	2009-1-17 (1)
+U7527		2009-1-17 (2)
+U76D9		2009-1-17 (2)
+U76F6		2009-1-17 (2)
+U771C		2009-1-17 (2)
+U773F		2009-1-17 (3)
+U7748		2009-1-17 (2)
+U7757		2009-1-17 (2)
+U7757		2009-1-17 (3)
+U7771		2009-1-17 (2)
+U7777		2009-1-17 (2)
+U7778		2009-1-17 (2)
+U777A		2009-1-17 (2)
+U77AF		2009-1-17 (2)
+U7794		2009-1-17 (2)
+U7807		2009-1-17 (2)
+U7808		2009-1-17 (2)
+U781B		2009-1-17 (2)
+U781E		2009-1-17 (2)
+U783D		2009-1-17 (2)
+U7841		2009-1-17 (2)
+U7842		2009-1-17 (2)
+U784B		2009-1-17 (2)
+U7854		2009-1-17 (2)
+U785F		2009-1-17 (2)
+U7863		2009-1-17 (2)
+U7876		2009-1-17 (2)
+U788B		2009-1-17 (2)
+U7890		2009-1-17 (2)
+U7892		2009-1-17 (2)
+U9FB0	FangQ	2009-1-17 (1)
+U9F11	FangQ	2009-1-17 (1)
+U7088	FangQ	2009-1-17 (2)
+U910C	FangQ	2009-1-17 (2)
+U7BC8	FangQ	2009-1-17 (2)
+U5C21	FangQ	2009-1-17 (2)
+U664D	FangQ	2009-1-17 (2)
+U6AC8	FangQ	2009-1-17 (1)
+U8834	FangQ	2009-1-17 (2)
+U9FA7	FangQ	2009-1-17 (1)
+U8FB5	FangQ	2009-1-17 (1)
+U8FB5	FangQ	2009-1-17 (2)
+U4E5A	FangQ	2009-1-17 (1)
+U4E46	FangQ	2009-1-17 (1)
+U9F11	wanghong	2009-1-17 (2)
+U9F11	wanghong	2009-1-17 (3)
+U9F11	wanghong	2009-1-17 (4)
+U9FB5	FangQ	2009-1-17 (1)
+U9DC0	FangQ	2009-1-17 (2)
+U4E44	FangQ	2009-1-17 (1)
+U4E44	FangQ	2009-1-17 (2)
+U78A6		2009-1-17 (2)
+U78AE		2009-1-17 (2)
+U78D7		2009-1-17 (2)
+U7906		2009-1-17 (2)
+U78EE		2009-1-17 (4)
+U7908		2009-1-17 (2)
+U7932		2009-1-17 (2)
+U7937		2009-1-17 (2)
+U794D		2009-1-17 (2)
+U794E		2009-1-17 (2)
+U7975		2009-1-17 (2)
+U799E		2009-1-17 (2)
+U79A5		2009-1-17 (2)
+U79CC		2009-1-17 (2)
+U79E2		2009-1-17 (2)
+U7A5D		2009-1-17 (2)
+U7A73		2009-1-17 (3)
+U79C2		2009-1-17 (2)
+U78E4		2009-1-17 (2)
+U792E		2009-1-17 (2)
+U7793		2009-1-17 (2)
+U77C8		2009-1-17 (2)
+U77C8		2009-1-17 (3)
+U7D95		2009-1-17 (2)
+U7D97		2009-1-17 (2)
+U7D5D		2009-1-17 (2)
+U7D49		2009-1-17 (2)
+U7D49		2009-1-17 (3)
+U7D2A		2009-1-17 (2)
+U7CE6		2009-1-17 (2)
+U7CC6		2009-1-17 (2)
+U7CA9		2009-1-17 (2)
+U7A7C		2009-1-17 (2)
+U7A82		2009-1-17 (2)
+U7A8E		2009-1-17 (2)
+U7AB9		2009-1-17 (2)
+U7AE8		2009-1-17 (2)
+U7AE9		2009-1-17 (2)
+U7AF2		2009-1-17 (2)
+U7AF3		2009-1-17 (2)
+U7AF3		2009-1-17 (3)
+U7B17		2009-1-17 (2)
+U7B1C		2009-1-17 (2)
+U7B43		2009-1-17 (2)
+U7B6F		2009-1-17 (2)
+U7B81		2009-1-17 (2)
+U7BAE		2009-1-17 (2)
+U7F40		2009-1-17 (2)
+U7F1E		2009-1-17 (2)
+U7EEC		2009-1-17 (2)
+U7DFE		2009-1-17 (2)
+U7DFD		2009-1-17 (2)
+U7DED		2009-1-17 (2)
+U7DEB		2009-1-17 (2)
+U7DE2		2009-1-17 (2)
+U7DD4		2009-1-17 (2)
+U7DD0		2009-1-17 (2)
+U7DC8		2009-1-17 (2)
+U7C4E		2009-1-17 (2)
+U7BF5		2009-1-17 (2)
+U7C15		2009-1-17 (2)
+U7C2F		2009-1-17 (2)
+U7BEC		2009-1-17 (2)
+U7BD7		2009-1-17 (2)
+U7BCD		2009-1-17 (2)
+U7BBF		2009-1-17 (2)
+U7E5B		2009-1-17 (2)
+U7DA5		2009-1-17 (2)
+U7E9E		2009-1-17 (3)
+U7C71		2009-1-17 (2)
+U7C4E		2009-1-17 (3)
+U7BBD		2009-1-17 (2)
+U7B41	wanghong	2009-1-17 (2)
+U7C71	FangQ	2009-1-17 (3)
+U9F11	FangQ	2009-1-17 (5)
+U93BC	FangQ	2009-1-17 (1)
+U5AAB	FangQ	2009-1-17 (1)
+U517F	FangQ	2009-1-17 (1)
+U9F1D	FangQ	2009-1-17 (1)
+U6C0E	FangQ	2009-1-17 (1)
+U6C0E	FangQ	2009-1-17 (2)
+U6C0E	FangQ	2009-1-17 (3)
+U6C0E	FangQ	2009-1-17 (4)
+U6C0E	FangQ	2009-1-17 (5)
+U6C0E	FangQ	2009-1-17 (6)
+U9750	FangQ	2009-1-18 (2)
+U7F46		2009-1-18 (2)
+U3AC7		2009-1-18 (1)
+U3AC7		2009-1-18 (1)
+U3767		2009-1-18 (1)
+U3AC7	FangQ	2009-1-18 (2)
+U376A		2009-1-18 (1)
+U40F2		2009-1-18 (1)
+U34F9	anonymous	2009-1-18 (1)
+U7FC4		2009-1-18 (2)
+U7FD6		2009-1-18 (2)
+U7FDD		2009-1-18 (2)
+U7FE4		2009-1-18 (2)
+U803A		2009-1-18 (2)
+U8053		2009-1-18 (2)
+U8059		2009-1-18 (2)
+U805B		2009-1-18 (2)
+U807A		2009-1-18 (2)
+U807C		2009-1-18 (2)
+U8081		2009-1-18 (2)
+U8094		2009-1-18 (2)
+U8097		2009-1-18 (2)
+U809E		2009-1-18 (2)
+U80A6		2009-1-18 (2)
+U80D2		2009-1-18 (2)
+U80E2		2009-1-18 (2)
+U812E		2009-1-18 (2)
+U8135		2009-1-18 (2)
+U8145		2009-1-18 (2)
+U8156		2009-1-18 (2)
+U8168		2009-1-18 (2)
+U8184		2009-1-18 (2)
+U8185		2009-1-18 (2)
+U81F0		2009-1-18 (2)
+U8678		2009-1-18 (2)
+U8675		2009-1-18 (2)
+U8224		2009-1-18 (2)
+U8241		2009-1-18 (2)
+U8254		2009-1-18 (2)
+U8281		2009-1-18 (2)
+U8281		2009-1-18 (3)
+U8289		2009-1-18 (2)
+U830A		2009-1-18 (2)
+U8355		2009-1-18 (2)
+U8419		2009-1-18 (2)
+U8421		2009-1-18 (2)
+U844F		2009-1-18 (2)
+U84D5		2009-1-18 (2)
+U5E0D	anonymous	2009-1-18 (2)
+U5E65	anonymous	2009-1-18 (2)
+U5E65	anonymous	2009-1-18 (3)
+U5E65	anonymous	2009-1-18 (4)
+U5E1E	anonymous	2009-1-18 (2)
+U5CD5	anonymous	2009-1-18 (2)
+U5DB6	anonymous	2009-1-18 (2)
+U5D78	anonymous	2009-1-18 (2)
+U5E9D	anonymous	2009-1-18 (2)
+U5DBE	anonymous	2009-1-18 (2)
+U5DBE	anonymous	2009-1-18 (3)
+U5D48	anonymous	2009-1-18 (2)
+U5DCA	anonymous	2009-1-18 (2)
+U8532		2009-1-18 (2)
+U855C		2009-1-18 (2)
+U85F3		2009-1-18 (2)
+U860E		2009-1-18 (2)
+U8649		2009-1-18 (2)
+U81F1		2009-1-18 (2)
+U8532		2009-1-18 (3)
+U8532		2009-1-18 (4)
+U85F3		2009-1-18 (3)
+U860E		2009-1-18 (3)
+U7F59		2009-1-18 (2)
+U9F11		2009-1-18 (6)
+U9F11	wanghong	2009-1-18 (7)
+U49A7	anonymous	2009-1-18 (1)
+U3D8D	anonymous	2009-1-18 (1)
+U90AD	lsz	2009-1-18 (2)
+U90B7	lsz	2009-1-18 (2)
+U90BC	lsz	2009-1-18 (2)
+U90C0	lsz	2009-1-18 (2)
+U90C9	lsz	2009-1-18 (2)
+U90CC	lsz	2009-1-18 (2)
+U90D2	lsz	2009-1-18 (2)
+U90EE	lsz	2009-1-18 (2)
+U86E0		2009-1-18 (2)
+U86E5		2009-1-18 (2)
+U86FF		2009-1-18 (2)
+U910A	lsz	2009-1-18 (2)
+U9142	lsz	2009-1-18 (2)
+U9151	lsz	2009-1-18 (2)
+U9159	lsz	2009-1-18 (2)
+U915B	lsz	2009-1-18 (2)
+U9188	lsz	2009-1-18 (2)
+U918E	lsz	2009-1-18 (2)
+U434F	anonymous	2009-1-18 (1)
+U5067	FangQ	2009-1-18 (2)
+U512C	FangQ	2009-1-18 (2)
+U488D	anonymous	2009-1-18 (1)
+U488D	anonymous	2009-1-18 (2)
+U52B0	FangQ	2009-1-18 (2)
+U5266	FangQ	2009-1-18 (2)
+U5328	FangQ	2009-1-18 (2)
+U532B	FangQ	2009-1-18 (2)
+U52CF	FangQ	2009-1-18 (2)
+U52E8	FangQ	2009-1-18 (2)
+U4689	FangQ	2009-1-18 (1)
+U8FC0	FangQ	2009-1-18 (2)
+U902A	FangQ	2009-1-18 (2)
+U91BF	lsz	2009-1-18 (2)
+U91FE	lsz	2009-1-18 (3)
+U9242	lsz	2009-1-18 (2)
+U9247	lsz	2009-1-18 (2)
+U9269	lsz	2009-1-18 (2)
+U926A	lsz	2009-1-18 (3)
+U929F	lsz	2009-1-18 (2)
+U3876	anonymous	2009-1-18 (1)
+U92BD	lsz	2009-1-18 (2)
+U498E		2009-1-18 (1)
+U3877	anonymous	2009-1-18 (1)
+U3880	anonymous	2009-1-18 (1)
+U92D6	lsz	2009-1-18 (2)
+U92F5	lsz	2009-1-18 (2)
+U931C	lsz	2009-1-18 (2)
+U9330	lsz	2009-1-18 (2)
+U9331	lsz	2009-1-18 (2)
+U9345	lsz	2009-1-18 (2)
+U93F1	lsz	2009-1-18 (2)
+U9424	lsz	2009-1-18 (3)
+U9426	lsz	2009-1-18 (2)
+U945F	lsz	2009-1-18 (2)
+U9491	lsz	2009-1-18 (2)
+U9496	lsz	2009-1-18 (2)
+U9498	lsz	2009-1-18 (2)
+U95CE	lsz	2009-1-18 (2)
+U86FF		2009-1-18 (3)
+U873D		2009-1-18 (2)
+U8804		2009-1-18 (2)
+U8847		2009-1-18 (2)
+U8849		2009-1-18 (2)
+U888A		2009-1-18 (2)
+U8894		2009-1-18 (2)
+U88A6		2009-1-18 (2)
+U88BB		2009-1-18 (2)
+U88C7		2009-1-18 (2)
+U88E0		2009-1-18 (2)
+U88ED		2009-1-18 (2)
+U890D		2009-1-18 (2)
+U8939		2009-1-18 (2)
+U894E		2009-1-18 (2)
+U8978		2009-1-18 (2)
+U897D		2009-1-18 (2)
+U8991		2009-1-18 (2)
+U89A5		2009-1-18 (2)
+U89AB		2009-1-18 (2)
+U89D8		2009-1-18 (2)
+U89EA		2009-1-18 (2)
+U8A09		2009-1-18 (2)
+U8A14		2009-1-18 (2)
+U8A24		2009-1-18 (2)
+U8A49		2009-1-18 (2)
+U8A53		2009-1-18 (2)
+U8AAF		2009-1-18 (2)
+U8AB5		2009-1-18 (2)
+U8B2D		2009-1-18 (2)
+U8B32		2009-1-18 (2)
+U8B43		2009-1-18 (2)
+U8B5E		2009-1-18 (2)
+U8B62		2009-1-18 (2)
+U8B64		2009-1-18 (2)
+U8B69		2009-1-18 (2)
+U8B75		2009-1-18 (2)
+U8C38		2009-1-18 (2)
+U8C44		2009-1-18 (2)
+U8C51		2009-1-18 (2)
+U8C59		2009-1-18 (2)
+U8C5B		2009-1-18 (2)
+U8C83		2009-1-18 (2)
+U8C96		2009-1-18 (2)
+U8C9F		2009-1-18 (2)
+U8C9F		2009-1-18 (3)
+U8CC9		2009-1-18 (2)
+U4C9F	anonymous	2009-1-19 (1)
+U4C9F	wanghong	2009-1-19 (2)
+U4C9F	wanghong	2009-1-19 (3)
+U3CD1	anonymous	2009-1-19 (1)
+U3D1E	kmc	2009-1-19 (1)
+U3D22	kmc	2009-1-19 (1)
+U3D23	kmc	2009-1-19 (1)
+U95EC	lsz	2009-1-19 (3)
+U3988	kmc	2009-1-19 (1)
+U398A	kmc	2009-1-19 (1)
+U398B	kmc	2009-1-19 (1)
+U35F9	kmc	2009-1-19 (1)
+U95FF	lsz	2009-1-19 (2)
+U445D	kmc	2009-1-19 (1)
+U9607	lsz	2009-1-19 (2)
+U9613	lsz	2009-1-19 (2)
+U961B	lsz	2009-1-19 (2)
+U963E	lsz	2009-1-19 (2)
+U9652	lsz	2009-1-19 (2)
+U9657	lsz	2009-1-19 (2)
+U9659	lsz	2009-1-19 (2)
+U965A	lsz	2009-1-19 (2)
+U9763	lsz	2009-1-19 (3)
+U3D0C	kmc	2009-1-19 (1)
+U8A06	lsz	2009-1-19 (2)
+U8A1A	lsz	2009-1-19 (2)
+U3517	kmc	2009-1-19 (1)
+U8A20	lsz	2009-1-19 (2)
+U8A24	lsz	2009-1-19 (3)
+U8A6F	lsz	2009-1-19 (2)
+U8A7E	lsz	2009-1-19 (2)
+U8AFD	lsz	2009-1-19 (2)
+U8B69	lsz	2009-1-19 (3)
+U8B73	lsz	2009-1-19 (2)
+U8C60	lsz	2009-1-19 (2)
+U8C63	lsz	2009-1-19 (2)
+U8C87	lsz	2009-1-19 (2)
+U8C9F	lsz	2009-1-19 (4)
+U8CA6	lsz	2009-1-19 (2)
+U8CFF	lsz	2009-1-19 (3)
+U8D01	lsz	2009-1-19 (2)
+U8D0C	lsz	2009-1-19 (2)
+U8D57	lsz	2009-1-19 (2)
+U44C0		2009-1-19 (1)
+U37FB		2009-1-19 (1)
+U37FC		2009-1-19 (1)
+U3800		2009-1-19 (1)
+U35E5		2009-1-19 (1)
+U624F	kmc	2009-1-19 (2)
+U6245	kmc	2009-1-19 (2)
+U61D3	kmc	2009-1-19 (2)
+U619C	kmc	2009-1-19 (2)
+U615C	kmc	2009-1-19 (2)
+U3B03		2009-1-19 (1)
+U6150	kmc	2009-1-19 (2)
+U610C	kmc	2009-1-19 (2)
+U5F3F	kmc	2009-1-19 (2)
+U5C8E	kmc	2009-1-19 (3)
+U5D2B	kmc	2009-1-19 (2)
+U5D48	kmc	2009-1-19 (3)
+U5D70	kmc	2009-1-19 (2)
+U5D78	kmc	2009-1-19 (3)
+U48AC		2009-1-19 (1)
+U3781		2009-1-19 (1)
+U4746		2009-1-19 (1)
+U50F2	FangQ	2009-1-19 (3)
+U5127	FangQ	2009-1-19 (2)
+U5327	FangQ	2009-1-19 (2)
+U52EC	FangQ	2009-1-19 (2)
+U52CE	FangQ	2009-1-19 (2)
+U52E8	FangQ	2009-1-19 (3)
+U52E8	FangQ	2009-1-19 (4)
+U4FF2	FangQ	2009-1-19 (3)
+U5003	FangQ	2009-1-19 (3)
+U518B	FangQ	2009-1-19 (3)
+U53FE	FangQ	2009-1-19 (2)
+U55B8	FangQ	2009-1-19 (2)
+U551F	FangQ	2009-1-19 (2)
+U53BC	FangQ	2009-1-19 (2)
+U53D5	FangQ	2009-1-19 (2)
+U53B8	FangQ	2009-1-19 (2)
+U5483	FangQ	2009-1-19 (2)
+U5518	FangQ	2009-1-19 (2)
+U5590	FangQ	2009-1-19 (2)
+U9625	wanghong	2009-1-19 (2)
+U969F	wanghong	2009-1-19 (2)
+U96A6	wanghong	2009-1-19 (2)
+U96FC	wanghong	2009-1-19 (2)
+U9721	wanghong	2009-1-19 (2)
+U9754	wanghong	2009-1-19 (2)
+U9757	wanghong	2009-1-19 (2)
+U9796	wanghong	2009-1-19 (2)
+U979B	wanghong	2009-1-19 (2)
+U979F	wanghong	2009-1-19 (3)
+U97BC	wanghong	2009-1-19 (2)
+U97BE	wanghong	2009-1-19 (3)
+U97CA	wanghong	2009-1-19 (2)
+U97D2	wanghong	2009-1-19 (2)
+U97E8	wanghong	2009-1-19 (2)
+U9819	wanghong	2009-1-19 (2)
+U9823	wanghong	2009-1-19 (4)
+U9831	wanghong	2009-1-19 (2)
+U9836	wanghong	2009-1-19 (2)
+U986C	wanghong	2009-1-19 (2)
+U98C8	wanghong	2009-1-19 (2)
+U98C8	wanghong	2009-1-19 (3)
+U5FC8	FangQ	2009-1-19 (2)
+U98F0	wanghong	2009-1-19 (2)
+U9904	wanghong	2009-1-19 (2)
+U990B	wanghong	2009-1-19 (2)
+U4E97	FangQ	2009-1-19 (2)
+U990E	wanghong	2009-1-19 (2)
+U9919	wanghong	2009-1-19 (2)
+U991C	wanghong	2009-1-19 (2)
+U9922	wanghong	2009-1-19 (2)
+U9926	wanghong	2009-1-19 (3)
+U9936	wanghong	2009-1-19 (2)
+U994A	wanghong	2009-1-19 (2)
+U990B	wanghong	2009-1-19 (3)
+U994F	wanghong	2009-1-19 (2)
+U9989	wanghong	2009-1-19 (2)
+U999A	wanghong	2009-1-19 (2)
+U99A9	wanghong	2009-1-19 (2)
+U99C0	wanghong	2009-1-19 (2)
+U99CA	wanghong	2009-1-19 (2)
+U99DA	wanghong	2009-1-19 (2)
+U99E6	wanghong	2009-1-19 (2)
+U99EB	wanghong	2009-1-19 (2)
+U99F3	wanghong	2009-1-19 (2)
+U9A1F	wanghong	2009-1-19 (2)
+U9A17	wanghong	2009-1-19 (2)
+U99E6	wanghong	2009-1-19 (3)
+U3B89		2009-1-19 (1)
+U3B8A		2009-1-19 (1)
+U3B8A	wanghong	2009-1-19 (2)
+U53FE	wanghong	2009-1-19 (3)
+U9A2F	wanghong	2009-1-19 (2)
+U9A61	wanghong	2009-1-19 (2)
+U9A63	wanghong	2009-1-19 (2)
+U9A95	wanghong	2009-1-19 (2)
+U9A99	wanghong	2009-1-19 (2)
+U9AD7	wanghong	2009-1-19 (2)
+U9ADA	wanghong	2009-1-19 (2)
+U9AE4	wanghong	2009-1-19 (3)
+U4F40	FangQ	2009-1-19 (2)
+U9AF8	wanghong	2009-1-19 (2)
+U9B34	wanghong	2009-1-19 (2)
+U53D2	FangQ	2009-1-19 (2)
+U5C1B	FangQ	2009-1-19 (2)
+U5C1B	FangQ	2009-1-19 (3)
+U5C23	FangQ	2009-1-19 (2)
+U6569	FangQ	2009-1-19 (2)
+U7637	FangQ	2009-1-19 (2)
+U7641	FangQ	2009-1-19 (2)
+U5796	FangQ	2009-1-19 (2)
+U5905	FangQ	2009-1-19 (2)
+U5D46	FangQ	2009-1-19 (2)
+U5E8E	FangQ	2009-1-19 (3)
+U7C9A	FangQ	2009-1-19 (2)
+U81FD	FangQ	2009-1-19 (2)
+U81FD	FangQ	2009-1-19 (3)
+U8E4F	FangQ	2009-1-19 (2)
+U7C70	FangQ	2009-1-19 (2)
+U7C70	FangQ	2009-1-19 (3)
+U9B3D	wanghong	2009-1-19 (2)
+U9B6D	wanghong	2009-1-19 (4)
+U9B81	wanghong	2009-1-20 (2)
+U9B89	wanghong	2009-1-20 (2)
+U9B8B	wanghong	2009-1-20 (3)
+U9B8B	wanghong	2009-1-20 (4)
+U9B98	wanghong	2009-1-20 (2)
+U9BA3	wanghong	2009-1-20 (2)
+U9BA9	wanghong	2009-1-20 (2)
+U9BCB	wanghong	2009-1-20 (3)
+U9BD8	wanghong	2009-1-20 (2)
+U9BE9	wanghong	2009-1-20 (2)
+U9C01	wanghong	2009-1-20 (2)
+U9C03	wanghong	2009-1-20 (2)
+U9C19	wanghong	2009-1-20 (3)
+U9C1F	wanghong	2009-1-20 (2)
+U9B81	FangQ	2009-1-20 (3)
+U9C22	wanghong	2009-1-20 (2)
+U9C51	wanghong	2009-1-20 (2)
+U5547	FangQ	2009-1-20 (2)
+U5571	FangQ	2009-1-20 (2)
+U9C64	wanghong	2009-1-20 (2)
+U9C65	wanghong	2009-1-20 (2)
+U9C6B	wanghong	2009-1-20 (2)
+U5554	FangQ	2009-1-20 (2)
+U9C7E	wanghong	2009-1-20 (3)
+U9C96	wanghong	2009-1-20 (2)
+U55ED	FangQ	2009-1-20 (2)
+U9C98	wanghong	2009-1-20 (2)
+U9C99	wanghong	2009-1-20 (3)
+U55F8	FangQ	2009-1-20 (2)
+U9CAF	wanghong	2009-1-20 (2)
+U5515	FangQ	2009-1-20 (2)
+U54EC	FangQ	2009-1-20 (2)
+U9CC9	wanghong	2009-1-20 (2)
+U5572	FangQ	2009-1-20 (2)
+U53D3	FangQ	2009-1-20 (2)
+U9F5A	wanghong	2009-1-20 (2)
+U9F73	wanghong	2009-1-20 (2)
+U9F3A	wanghong	2009-1-20 (2)
+U9EA3	wanghong	2009-1-20 (2)
+U8117	wanghong	2009-1-20 (2)
+U9CDB	wanghong	2009-1-20 (2)
+U9CE0	wanghong	2009-1-20 (2)
+U9CE8	wanghong	2009-1-20 (2)
+U9E96	wanghong	2009-1-20 (3)
+U9E84	wanghong	2009-1-20 (2)
+U9E59	wanghong	2009-1-20 (2)
+U9E50	wanghong	2009-1-20 (2)
+U9E34	wanghong	2009-1-20 (2)
+U9E0C	wanghong	2009-1-20 (2)
+U9DA5	wanghong	2009-1-20 (2)
+U9D95	wanghong	2009-1-20 (3)
+U9D8D	wanghong	2009-1-20 (2)
+U9D83	wanghong	2009-1-20 (2)
+U9D66	wanghong	2009-1-20 (2)
+U9D3C	wanghong	2009-1-20 (2)
+U9D0F	wanghong	2009-1-20 (2)
+U9D3A	wanghong	2009-1-20 (2)
+U9CF8	wanghong	2009-1-20 (2)
+U3FA8	anonymous	2009-1-20 (1)
+U3C50	anonymous	2009-1-20 (1)
+U3C51	anonymous	2009-1-20 (1)
+U393A	anonymous	2009-1-20 (1)
+U3BB2	kmc	2009-1-20 (1)
+U35AC	kmc	2009-1-20 (1)
+U3BF7	kmc	2009-1-20 (1)
+U3BF9	kmc	2009-1-20 (1)
+U3BFA	kmc	2009-1-20 (1)
+U4BFD	kmc	2009-1-20 (1)
+U4BFF	kmc	2009-1-20 (1)
+U4C21	kmc	2009-1-20 (1)
+U439F	kmc	2009-1-20 (1)
+U4115	kmc	2009-1-20 (1)
+U4412	kmc	2009-1-20 (1)
+U472D	kmc	2009-1-20 (1)
+U3ACA	kmc	2009-1-20 (1)
+U4A06	kmc	2009-1-20 (1)
+U35FD	kmc	2009-1-20 (1)
+U4D1E	kmc	2009-1-20 (1)
+U4D1D	kmc	2009-1-20 (1)
+U4591	kmc	2009-1-20 (1)
+U4592	kmc	2009-1-20 (1)
+U56EF	FangQ	2009-1-20 (2)
+U56EF	FangQ	2009-1-20 (3)
+U3B6E	anonymous	2009-1-20 (1)
+U3B6E	anonymous	2009-1-20 (2)
+U3959	anonymous	2009-1-20 (1)
+U395D	anonymous	2009-1-20 (1)
+U395D	FangQ	2009-1-20 (2)
+U551E	FangQ	2009-1-20 (2)
+U5596	FangQ	2009-1-20 (2)
+U55F0	FangQ	2009-1-20 (2)
+U5656	FangQ	2009-1-20 (2)
+U53A1	FangQ	2009-1-20 (2)
+U5611	FangQ	2009-1-20 (2)
+U5611	FangQ	2009-1-20 (3)
+U5560	FangQ	2009-1-20 (2)
+U5560	FangQ	2009-1-20 (3)
+U5390	FangQ	2009-1-20 (2)
+U5497	FangQ	2009-1-20 (2)
+U5542	FangQ	2009-1-20 (2)
+U55AF	FangQ	2009-1-20 (2)
+U5625	FangQ	2009-1-20 (2)
+U561A	FangQ	2009-1-20 (2)
+U5655	FangQ	2009-1-20 (2)
+U565D	FangQ	2009-1-20 (2)
+U5444	FangQ	2009-1-20 (2)
+U53DE	FangQ	2009-1-20 (2)
+U5391	FangQ	2009-1-20 (2)
+U53B1	FangQ	2009-1-20 (2)
+U5380	FangQ	2009-1-20 (2)
+U8E6E	FangQ	2009-1-20 (2)
+U8EB9	FangQ	2009-1-20 (2)
+U8E7E	FangQ	2009-1-20 (2)
+U8F80	FangQ	2009-1-20 (2)
+U8FA1	FangQ	2009-1-20 (2)
+U8EB5	FangQ	2009-1-20 (2)
+U8EB7	FangQ	2009-1-20 (2)
+U8E83	FangQ	2009-1-20 (2)
+U8E71	FangQ	2009-1-20 (2)
+U4DA7	FangQ	2009-1-20 (1)
+U8D5F	FangQ	2009-1-20 (2)
+U8E75	FangQ	2009-1-20 (2)
+U9007	FangQ	2009-1-20 (2)
+U906C	FangQ	2009-1-20 (2)
+U8EDA	FangQ	2009-1-20 (2)
+U8E58	FangQ	2009-1-20 (2)
+U8F8C	FangQ	2009-1-20 (2)
+U8F04	FangQ	2009-1-20 (2)
+U8EEA	FangQ	2009-1-20 (2)
+U909A	FangQ	2009-1-20 (2)
+U8E32	FangQ	2009-1-20 (2)
+U56F6	FangQ	2009-1-20 (2)
+U5756	FangQ	2009-1-20 (2)
+U56BB	FangQ	2009-1-20 (2)
+U56FB	FangQ	2009-1-20 (2)
+U585C	FangQ	2009-1-20 (2)
+U8126	wanghong	2009-1-21 (2)
+U824A	wanghong	2009-1-21 (2)
+U8372	wanghong	2009-1-21 (2)
+U83AC	wanghong	2009-1-21 (2)
+U83D0	wanghong	2009-1-21 (2)
+U8455	wanghong	2009-1-21 (2)
+U847B	wanghong	2009-1-21 (2)
+U8483	wanghong	2009-1-21 (2)
+U848A	wanghong	2009-1-21 (2)
+U856F	wanghong	2009-1-21 (2)
+U856F	wanghong	2009-1-21 (3)
+U8570	wanghong	2009-1-21 (2)
+U85F4	wanghong	2009-1-21 (2)
+U87F5	wanghong	2009-1-21 (2)
+U87F8	wanghong	2009-1-21 (2)
+U898E	wanghong	2009-1-21 (3)
+U898E	wanghong	2009-1-21 (4)
+U8994	wanghong	2009-1-21 (2)
+U89B4	wanghong	2009-1-21 (2)
+U89C3	wanghong	2009-1-21 (2)
+U89F9	wanghong	2009-1-21 (2)
+U811C	wanghong	2009-1-21 (2)
+U8145	wanghong	2009-1-21 (3)
+U812E	wanghong	2009-1-21 (3)
+U8372	wanghong	2009-1-21 (3)
+U844F	wanghong	2009-1-21 (3)
+U8570	wanghong	2009-1-21 (3)
+U871D	wanghong	2009-1-21 (5)
+U9579	wanghong	2009-1-21 (2)
+U46C8	anonymous	2009-1-21 (1)
+U5E8E		2009-1-21 (4)
+U6093		2009-1-21 (3)
+U5E0D		2009-1-21 (3)
+U5E12		2009-1-21 (2)
+U493A	anonymous	2009-1-21 (1)
+U493F	anonymous	2009-1-21 (1)
+U3CF4	anonymous	2009-1-21 (1)
+U3CF7	anonymous	2009-1-21 (1)
+U468F	anonymous	2009-1-21 (1)
+U3AD5		2009-1-21 (1)
+U8D6A	lsz	2009-1-21 (2)
+U8D7E	lsz	2009-1-21 (2)
+U8D82	lsz	2009-1-21 (2)
+U8D86	lsz	2009-1-21 (2)
+U8D87	lsz	2009-1-21 (2)
+U8D87	lsz	2009-1-21 (3)
+U8D88	lsz	2009-1-21 (2)
+U8D9D	lsz	2009-1-21 (2)
+U8DA2	lsz	2009-1-21 (2)
+U8E01	lsz	2009-1-21 (2)
+U8DD2	lsz	2009-1-21 (2)
+U8E58	lsz	2009-1-21 (3)
+U8E6E	lsz	2009-1-21 (3)
+U8E7E	lsz	2009-1-21 (3)
+U8E80	lsz	2009-1-21 (2)
+U8EA7	lsz	2009-1-21 (2)
+U8EBF	lsz	2009-1-21 (2)
+U8EDA	lsz	2009-1-21 (3)
+U9033	lsz	2009-1-21 (2)
+U9092	lsz	2009-1-21 (2)
+U9092	lsz	2009-1-21 (3)
+U90A9	lsz	2009-1-21 (2)
+U91FA	wanghong	2009-1-21 (2)
+U925C	wanghong	2009-1-21 (2)
+U926B	wanghong	2009-1-21 (2)
+U9275	wanghong	2009-1-21 (2)
+U9284	wanghong	2009-1-21 (2)
+U928F	wanghong	2009-1-21 (2)
+U92BA	wanghong	2009-1-21 (2)
+U92BA	wanghong	2009-1-21 (3)
+U92D4	wanghong	2009-1-21 (2)
+U92DA	wanghong	2009-1-21 (2)
+U9303	wanghong	2009-1-21 (2)
+U931C	wanghong	2009-1-21 (3)
+U9330	wanghong	2009-1-21 (3)
+U9341	wanghong	2009-1-21 (2)
+U935D	wanghong	2009-1-21 (2)
+U936B	wanghong	2009-1-21 (2)
+U938B	wanghong	2009-1-21 (3)
+U939C	wanghong	2009-1-21 (2)
+U93B8	wanghong	2009-1-21 (2)
+U93C1	wanghong	2009-1-21 (2)
+U93C9	wanghong	2009-1-21 (2)
+U93ED	wanghong	2009-1-21 (2)
+U93F1	wanghong	2009-1-21 (3)
+U9405	wanghong	2009-1-21 (2)
+U9408	wanghong	2009-1-21 (2)
+U9417	wanghong	2009-1-21 (2)
+U94DA	wanghong	2009-1-21 (2)
+U94DA	wanghong	2009-1-21 (3)
+U94FB	wanghong	2009-1-21 (2)
+U9543	wanghong	2009-1-21 (2)
+U9574	wanghong	2009-1-21 (2)
+U956E	wanghong	2009-1-21 (2)
+U9196	wanghong	2009-1-21 (2)
+U9188	wanghong	2009-1-21 (3)
+U916D	wanghong	2009-1-21 (2)
+U916B	wanghong	2009-1-21 (2)
+U9159	wanghong	2009-1-21 (3)
+U9151	wanghong	2009-1-21 (3)
+U915B	wanghong	2009-1-21 (3)
+U9166	wanghong	2009-1-21 (2)
+U9167	wanghong	2009-1-21 (2)
+U9167	wanghong	2009-1-21 (3)
+U9194	wanghong	2009-1-21 (2)
+U741E	anonymous	2009-1-21 (3)
+U74A4	anonymous	2009-1-21 (3)
+U7794	lsz	2009-1-21 (3)
+U8D0C	FangQ	2009-1-21 (3)
+U7798	lsz	2009-1-21 (2)
+U77AF	lsz	2009-1-21 (3)
+U8D11	FangQ	2009-1-21 (2)
+U8F31	FangQ	2009-1-21 (2)
+U77B8	lsz	2009-1-21 (2)
+U8ED6	FangQ	2009-1-21 (2)
+U8EE4	FangQ	2009-1-21 (2)
+U77BE	lsz	2009-1-21 (2)
+U77C6	lsz	2009-1-21 (2)
+U77E4	lsz	2009-1-21 (2)
+U8D83	FangQ	2009-1-21 (2)
+U8DB0	FangQ	2009-1-21 (2)
+U8E80	FangQ	2009-1-21 (3)
+U382B		2009-1-21 (1)
+U77F5	lsz	2009-1-21 (2)
+U4169		2009-1-21 (1)
+U5711	FangQ	2009-1-21 (2)
+U596F	FangQ	2009-1-21 (2)
+U5952	FangQ	2009-1-21 (2)
+U7844	lsz	2009-1-21 (2)
+U784B	lsz	2009-1-21 (3)
+U7858	lsz	2009-1-21 (2)
+U56B0	FangQ	2009-1-21 (2)
+U5688	FangQ	2009-1-21 (2)
+U471A		2009-1-21 (1)
+U56A4	FangQ	2009-1-21 (2)
+U56A1	FangQ	2009-1-21 (2)
+U56A1	FangQ	2009-1-21 (3)
+U7875	lsz	2009-1-21 (2)
+U5901	FangQ	2009-1-21 (2)
+U7892	lsz	2009-1-21 (3)
+U5721	FangQ	2009-1-21 (2)
+U78C7	lsz	2009-1-21 (2)
+U5943	FangQ	2009-1-21 (2)
+U56D6	FangQ	2009-1-21 (2)
+U56C4	FangQ	2009-1-21 (2)
+U5710	FangQ	2009-1-21 (2)
+U5710	FangQ	2009-1-21 (3)
+U73E1	wanghong	2009-1-21 (2)
+U7415	wanghong	2009-1-21 (4)
+U7418	wanghong	2009-1-21 (2)
+U7411	wanghong	2009-1-21 (2)
+U7458	wanghong	2009-1-21 (2)
+U74B4	wanghong	2009-1-21 (2)
+U74C7	wanghong	2009-1-21 (2)
+U7534	wanghong	2009-1-21 (3)
+U7536	wanghong	2009-1-21 (2)
+U7542	wanghong	2009-1-21 (2)
+U7555	wanghong	2009-1-21 (2)
+U7571	wanghong	2009-1-21 (2)
+U7764	wanghong	2009-1-21 (3)
+U7749	wanghong	2009-1-21 (2)
+U7730	wanghong	2009-1-21 (2)
+U772A	wanghong	2009-1-21 (2)
+U770E	wanghong	2009-1-21 (2)
+U7716	wanghong	2009-1-21 (2)
+U8203	FangQ	2009-1-21 (2)
+U7536	FangQ	2009-1-21 (3)
+U5AF2	anonymous	2009-1-22 (2)
+U768D	wanghong	2009-1-22 (2)
+U768D	wanghong	2009-1-22 (3)
+U768D	wanghong	2009-1-22 (4)
+U5DB6	kmc	2009-1-22 (3)
+U5DBB	kmc	2009-1-22 (2)
+U5E12	kmc	2009-1-22 (3)
+U5E1E	kmc	2009-1-22 (3)
+U5E2A	kmc	2009-1-22 (2)
+U5E50	kmc	2009-1-22 (2)
+U5E5A	kmc	2009-1-22 (2)
+U5E65	kmc	2009-1-22 (5)
+U5E9D	kmc	2009-1-22 (3)
+U5EAF	kmc	2009-1-22 (3)
+U5F06	kmc	2009-1-22 (2)
+U5F47	kmc	2009-1-22 (2)
+U5F6E	kmc	2009-1-22 (3)
+U5FCE	kmc	2009-1-22 (2)
+U6018	kmc	2009-1-22 (2)
+U6023	kmc	2009-1-22 (2)
+U6038	kmc	2009-1-22 (2)
+U6074	kmc	2009-1-22 (2)
+U6093	kmc	2009-1-22 (4)
+U60E5	kmc	2009-1-22 (2)
+U7DA8	wanghong	2009-1-22 (2)
+U7EB4	wanghong	2009-1-22 (2)
+U7ED6	wanghong	2009-1-22 (3)
+U7F37	wanghong	2009-1-22 (2)
+U7F64	wanghong	2009-1-22 (2)
+U7FDA	wanghong	2009-1-22 (2)
+U6DB1	wanghong	2009-1-22 (2)
+U6DFF	wanghong	2009-1-22 (2)
+U6E0F	wanghong	2009-1-22 (3)
+U6E81	wanghong	2009-1-22 (2)
+U6EAD	wanghong	2009-1-22 (2)
+U6EB5	wanghong	2009-1-22 (2)
+U6F4C	wanghong	2009-1-22 (2)
+U6F71	wanghong	2009-1-22 (2)
+U6FD6	wanghong	2009-1-22 (2)
+U7059	wanghong	2009-1-22 (2)
+U70B6	wanghong	2009-1-22 (2)
+U7134	wanghong	2009-1-22 (3)
+U7157	wanghong	2009-1-22 (2)
+U72BB	wanghong	2009-1-22 (2)
+U6782	wanghong	2009-1-22 (3)
+U59E7	wanghong	2009-1-22 (2)
+U5A1D	wanghong	2009-1-22 (2)
+U5A30	wanghong	2009-1-22 (2)
+U3981		2009-1-22 (1)
+U423C		2009-1-22 (1)
+U4C20	anonymous	2009-1-22 (1)
+U7987	lsz	2009-1-22 (4)
+U79C4	lsz	2009-1-22 (3)
+U79FF	lsz	2009-1-22 (2)
+U79FF	lsz	2009-1-22 (3)
+U7A25	lsz	2009-1-22 (2)
+U7A29	lsz	2009-1-22 (2)
+U7A2D	lsz	2009-1-22 (2)
+U67D5	lsz	2009-1-22 (2)
+U6858	lsz	2009-1-22 (2)
+U6884	lsz	2009-1-22 (2)
+U6985	lsz	2009-1-22 (2)
+U698C	lsz	2009-1-22 (2)
+U6AC4	lsz	2009-1-22 (2)
+U6AD4	lsz	2009-1-22 (2)
+U6B7A	lsz	2009-1-22 (2)
+U5C87	anonymous	2009-1-22 (2)
+U5C87	anonymous	2009-1-22 (3)
+U5CE2	anonymous	2009-1-22 (2)
+U5CF2	anonymous	2009-1-22 (2)
+U5CF2	anonymous	2009-1-22 (3)
+U5CF2	anonymous	2009-1-22 (4)
+U6244	anonymous	2009-1-22 (3)
+U6299	anonymous	2009-1-22 (2)
+U6299	FangQ	2009-1-22 (3)
+U4C20	FangQ	2009-1-22 (2)
+U4C20	FangQ	2009-1-22 (3)
+U6C3A	lsz	2009-1-22 (2)
+U6C44	lsz	2009-1-22 (2)
+U6C51	lsz	2009-1-22 (2)
+U6C6E	lsz	2009-1-22 (2)
+U6C77	lsz	2009-1-22 (2)
+U5CF3	anonymous	2009-1-22 (2)
+U5CFC	anonymous	2009-1-22 (2)
+U66A5	wanghong	2009-1-22 (2)
+U6629	wanghong	2009-1-22 (2)
+U5D2F	anonymous	2009-1-22 (2)
+U6601	wanghong	2009-1-22 (2)
+U5D3B	anonymous	2009-1-22 (2)
+U5D46	anonymous	2009-1-22 (3)
+U6C97	lsz	2009-1-22 (2)
+U6CB5	lsz	2009-1-22 (2)
+U6C9E	lsz	2009-1-22 (2)
+U6CF4	lsz	2009-1-22 (2)
+U6CF4	lsz	2009-1-22 (3)
+U6D56	lsz	2009-1-22 (2)
+U66F1	lsz	2009-1-22 (4)
+U613A	lsz	2009-1-22 (2)
+U61D9	lsz	2009-1-22 (2)
+U623C	lsz	2009-1-22 (3)
+U6278	lsz	2009-1-22 (2)
+U62B7	lsz	2009-1-22 (3)
+U632E	lsz	2009-1-22 (3)
+U5D83	anonymous	2009-1-22 (2)
+U5DAB	anonymous	2009-1-22 (2)
+U5DD9	anonymous	2009-1-22 (2)
+U5AF2	wanghong	2009-1-22 (3)
+U5A3F	wanghong	2009-1-22 (2)
+U5AC3	wanghong	2009-1-22 (2)
+U5B0E	wanghong	2009-1-22 (2)
+U491C	anonymous	2009-1-23 (1)
+U5DE4	anonymous	2009-1-23 (2)
+U5DED	anonymous	2009-1-23 (2)
+U5DED	anonymous	2009-1-23 (3)
+U5DF8	anonymous	2009-1-23 (2)
+U5DFC	anonymous	2009-1-23 (2)
+U5B1C	wanghong	2009-1-23 (2)
+U5B31	wanghong	2009-1-23 (2)
+U5B3A	wanghong	2009-1-23 (2)
+U5B41	wanghong	2009-1-23 (2)
+U5E98	anonymous	2009-1-23 (2)
+U5B42	wanghong	2009-1-23 (2)
+U5B1C	wanghong	2009-1-23 (3)
+U5EA9	anonymous	2009-1-23 (2)
+U5B1C	wanghong	2009-1-23 (4)
+U5EBA	anonymous	2009-1-23 (2)
+U5EBA	anonymous	2009-1-23 (3)
+U5EBA	anonymous	2009-1-23 (3)
+U5EBF	anonymous	2009-1-23 (2)
+U5ECD	anonymous	2009-1-23 (2)
+U5EF9	anonymous	2009-1-23 (2)
+U5DED	wanghong	2009-1-23 (4)
+U5C83	wanghong	2009-1-23 (2)
+U5C77	wanghong	2009-1-23 (2)
+U5C77	wanghong	2009-1-23 (3)
+U5F5F	anonymous	2009-1-23 (2)
+U5F60	anonymous	2009-1-23 (2)
+U5F72	anonymous	2009-1-23 (2)
+U5F94	anonymous	2009-1-23 (2)
+U5FB0	anonymous	2009-1-23 (2)
+U5FB0	anonymous	2009-1-23 (3)
+U5FC8	anonymous	2009-1-23 (3)
+U5FDF	wanghong	2009-1-23 (2)
+U5F4D	wanghong	2009-1-23 (2)
+U5F32	wanghong	2009-1-23 (2)
+U5EF5	wanghong	2009-1-23 (2)
+U5DDC	wanghong	2009-1-23 (2)
+U5DEA	wanghong	2009-1-23 (2)
+U5DF6	wanghong	2009-1-23 (2)
+U5D60	wanghong	2009-1-23 (2)
+U5D6E	wanghong	2009-1-23 (2)
+U5D05	wanghong	2009-1-23 (2)
+U5D56	wanghong	2009-1-23 (2)
+U5C72	wanghong	2009-1-23 (2)
+U60A1	wanghong	2009-1-23 (2)
+U586A	wanghong	2009-1-23 (2)
+U5753	wanghong	2009-1-23 (3)
+U5754	wanghong	2009-1-23 (2)
+U5763	wanghong	2009-1-23 (2)
+U578D	wanghong	2009-1-23 (2)
+U57C4	wanghong	2009-1-23 (2)
+U57C9	wanghong	2009-1-23 (2)
+U57D1	wanghong	2009-1-23 (2)
+U57FE	wanghong	2009-1-23 (2)
+U3B8F		2009-1-23 (1)
+U6463	lsz	2009-1-23 (2)
+U6540	lsz	2009-1-23 (2)
+U65A6	lsz	2009-1-23 (2)
+U65B5	lsz	2009-1-23 (2)
+U65BE	lsz	2009-1-23 (2)
+U65EB	lsz	2009-1-23 (2)
+U6601	lsz	2009-1-23 (3)
+U661A	lsz	2009-1-23 (2)
+U3A6A		2009-1-23 (1)
+U5C2F	wanghong	2009-1-23 (2)
+U5DDC	FangQ	2009-1-23 (3)
+U48DD	anonymous	2009-1-23 (1)
+U6629	lsz	2009-1-23 (3)
+U669B	lsz	2009-1-23 (2)
+U66A5	lsz	2009-1-23 (3)
+U66CE	lsz	2009-1-23 (2)
+U4B7D	anonymous	2009-1-23 (1)
+U599F	wanghong	2009-1-23 (2)
+U58F8	wanghong	2009-1-23 (2)
+U5A3D	wanghong	2009-1-23 (3)
+U5B94	wanghong	2009-1-23 (2)
+U5C00	wanghong	2009-1-23 (2)
+U5C70	wanghong	2009-1-23 (2)
+U5866	wanghong	2009-1-23 (2)
+U5803	wanghong	2009-1-23 (2)
+U5BB7	wanghong	2009-1-23 (2)
+U5BA9	wanghong	2009-1-23 (2)
+U5B76	wanghong	2009-1-23 (2)
+U5C35	wanghong	2009-1-23 (2)
+U5B67	wanghong	2009-1-23 (2)
+U5B74	wanghong	2009-1-23 (2)
+U5BDA	wanghong	2009-1-23 (2)
+U5BB2	wanghong	2009-1-23 (2)
+U5BF4	wanghong	2009-1-23 (2)
+U3F31		2009-1-23 (1)
+U5BF7	wanghong	2009-1-23 (2)
+U3F39		2009-1-23 (1)
+U556F	wanghong	2009-1-23 (2)
+U5579	wanghong	2009-1-23 (3)
+U5585	wanghong	2009-1-23 (2)
+U55BC	wanghong	2009-1-23 (3)
+U55D7	wanghong	2009-1-23 (2)
+U563C	wanghong	2009-1-23 (2)
+U56D2	wanghong	2009-1-23 (2)
+U56E8	wanghong	2009-1-23 (2)
+U56EC	wanghong	2009-1-23 (2)
+U56F8	wanghong	2009-1-23 (2)
+U5705	wanghong	2009-1-23 (2)
+U5719	wanghong	2009-1-23 (3)
+U572B	wanghong	2009-1-23 (2)
+U55D7	lsz	2009-1-23 (3)
+U8890	wanghong	2009-1-23 (2)
+U563C	lsz	2009-1-23 (3)
+U56D2	lsz	2009-1-23 (3)
+U56DC	lsz	2009-1-23 (3)
+U56E6	lsz	2009-1-23 (2)
+U56E9	lsz	2009-1-23 (2)
+U56E9	wanghong	2009-1-23 (3)
+U570E	lsz	2009-1-23 (2)
+U572B	lsz	2009-1-23 (3)
+U8592	wanghong	2009-1-23 (2)
+U5735	lsz	2009-1-23 (2)
+U532C	lsz	2009-1-23 (2)
+U5376	lsz	2009-1-23 (2)
+U85B2	wanghong	2009-1-23 (2)
+U53FF	lsz	2009-1-24 (2)
+U5405	lsz	2009-1-24 (2)
+U48E2	anonymous	2009-1-24 (1)
+U53D2	lsz	2009-1-24 (3)
+U53D2	lsz	2009-1-24 (4)
+U3BF0	anonymous	2009-1-24 (1)
+U53E7	lsz	2009-1-24 (2)
+U543F	lsz	2009-1-24 (2)
+U3885	anonymous	2009-1-24 (1)
+U4205	anonymous	2009-1-24 (1)
+U544D	lsz	2009-1-24 (2)
+U545E	lsz	2009-1-24 (2)
+U546D	lsz	2009-1-24 (2)
+U549F	lsz	2009-1-24 (2)
+U54B5	lsz	2009-1-24 (2)
+U4207	anonymous	2009-1-24 (1)
+U4D8F	anonymous	2009-1-24 (1)
+U4D90	anonymous	2009-1-24 (1)
+U54CA	lsz	2009-1-24 (2)
+U54E3	lsz	2009-1-24 (2)
+U5528	lsz	2009-1-24 (2)
+U5528	lsz	2009-1-24 (3)
+U3A25	bt4wang	2009-1-24 (1)
+U3A40	bt4wang	2009-1-24 (1)
+U435E	bt4wang	2009-1-24 (1)
+U4351	bt4wang	2009-1-24 (1)
+U3A7A	anonymous	2009-1-24 (1)
+U4153	bt4wang	2009-1-24 (1)
+U85E0	wanghong	2009-1-24 (2)
+U8850	wanghong	2009-1-24 (2)
+U8812	wanghong	2009-1-24 (2)
+U8645	wanghong	2009-1-24 (2)
+U8641	wanghong	2009-1-24 (2)
+U861D	wanghong	2009-1-24 (2)
+U8610	wanghong	2009-1-24 (2)
+U85D6	wanghong	2009-1-24 (2)
+U85D4	wanghong	2009-1-24 (2)
+U85BB	wanghong	2009-1-24 (2)
+U860D	wanghong	2009-1-24 (2)
+U86AE	wanghong	2009-1-24 (2)
+U86E7	wanghong	2009-1-24 (2)
+U8739	wanghong	2009-1-24 (2)
+U87C1	wanghong	2009-1-24 (2)
+U4456		2009-1-24 (1)
+U88D1	wanghong	2009-1-24 (3)
+U88D3	wanghong	2009-1-24 (2)
+U8947	wanghong	2009-1-24 (2)
+U8984	wanghong	2009-1-24 (2)
+U8994	wanghong	2009-1-24 (3)
+U89EE	wanghong	2009-1-25 (2)
+U89F9	wanghong	2009-1-25 (3)
+U8A05	wanghong	2009-1-25 (2)
+U8AD0	wanghong	2009-1-25 (2)
+U8B87	wanghong	2009-1-25 (2)
+U8CEF	wanghong	2009-1-25 (2)
+U8D7C	wanghong	2009-1-25 (2)
+U8D01	wanghong	2009-1-25 (3)
+U4456	anonymous	2009-1-25 (2)
+U466D		2009-1-25 (1)
+U4007	bt4wang	2009-1-25 (1)
+U8DA4	wanghong	2009-1-25 (3)
+U3F09		2009-1-26 (1)
+U906A	wanghong	2009-1-26 (2)
+U8F21	wanghong	2009-1-26 (2)
+U8E77	wanghong	2009-1-26 (2)
+U8DA9	wanghong	2009-1-26 (3)
+U8DA6	wanghong	2009-1-26 (3)
+U8DA4	wanghong	2009-1-26 (4)
+U8DA2	wanghong	2009-1-26 (3)
+U8E79	wanghong	2009-1-26 (2)
+U8EBC	wanghong	2009-1-26 (2)
+U8F0F	wanghong	2009-1-26 (2)
+U8F21	wanghong	2009-1-26 (3)
+U8F2B	wanghong	2009-1-26 (2)
+U8F2B	wanghong	2009-1-26 (3)
+U8FA2	wanghong	2009-1-26 (2)
+U8FA4	wanghong	2009-1-26 (2)
+U8FC3	wanghong	2009-1-26 (2)
+U8FCA	wanghong	2009-1-26 (2)
+U8FCA	wanghong	2009-1-26 (3)
+U8FCC	wanghong	2009-1-26 (2)
+U8FCF	wanghong	2009-1-26 (2)
+U8FE7	wanghong	2009-1-26 (2)
+U8FEC	wanghong	2009-1-26 (2)
+U8FEC	wanghong	2009-1-26 (3)
+U8FF1	wanghong	2009-1-26 (2)
+U9029	wanghong	2009-1-26 (2)
+U902C	wanghong	2009-1-26 (3)
+U9040	wanghong	2009-1-26 (3)
+U9046	wanghong	2009-1-26 (4)
+U904C	wanghong	2009-1-26 (2)
+U9064	wanghong	2009-1-26 (2)
+U9071	wanghong	2009-1-26 (2)
+U908C	wanghong	2009-1-26 (2)
+U9043	wanghong	2009-1-26 (3)
+U7054	anonymous	2009-1-26 (3)
+U625F	anonymous	2009-1-26 (2)
+U6299	anonymous	2009-1-26 (4)
+U6318	anonymous	2009-1-26 (2)
+U6318	anonymous	2009-1-26 (3)
+U6318	anonymous	2009-1-26 (4)
+U643B	anonymous	2009-1-26 (2)
+U64DD	anonymous	2009-1-26 (2)
+U4CA2		2009-1-26 (1)
+U4CA2		2009-1-26 (2)
+U4CA2		2009-1-26 (3)
+U4CA6		2009-1-26 (1)
+U3D0A		2009-1-26 (1)
+U9113	wanghong	2009-1-26 (2)
+U918E	wanghong	2009-1-26 (3)
+U9269	wanghong	2009-1-26 (3)
+U92BD	wanghong	2009-1-26 (3)
+U92F5	wanghong	2009-1-26 (3)
+U933F	wanghong	2009-1-26 (3)
+U9373	wanghong	2009-1-26 (2)
+U93BA	wanghong	2009-1-26 (2)
+U93BA	wanghong	2009-1-26 (3)
+U93BB	wanghong	2009-1-27 (2)
+U93BD	wanghong	2009-1-27 (2)
+U9401	wanghong	2009-1-27 (2)
+U944D	wanghong	2009-1-27 (2)
+U94E6	wanghong	2009-1-27 (2)
+U9585	wanghong	2009-1-27 (2)
+U9595	wanghong	2009-1-27 (2)
+U959A	wanghong	2009-1-27 (2)
+U95AA	wanghong	2009-1-27 (2)
+U95AF	wanghong	2009-1-27 (2)
+U95B4	wanghong	2009-1-27 (2)
+U95B8	wanghong	2009-1-27 (2)
+U95C2	wanghong	2009-1-27 (2)
+U4B9B	anonymous	2009-1-27 (1)
+U95C4	wanghong	2009-1-27 (2)
+U4BA7	anonymous	2009-1-27 (1)
+U95CF	wanghong	2009-1-27 (2)
+U95D7	wanghong	2009-1-27 (2)
+U3623	anonymous	2009-1-27 (1)
+U3624	anonymous	2009-1-27 (1)
+U361F	anonymous	2009-1-27 (1)
+U9892	wanghong	2009-1-27 (2)
+U9899	wanghong	2009-1-27 (2)
+U9585	wanghong	2009-1-27 (3)
+U9585	wanghong	2009-1-27 (4)
+U95EC	wanghong	2009-1-27 (4)
+U9607	wanghong	2009-1-27 (3)
+U982E	wanghong	2009-1-27 (2)
+U9613	wanghong	2009-1-27 (3)
+U965A	wanghong	2009-1-27 (3)
+U9679	wanghong	2009-1-27 (2)
+U968C	wanghong	2009-1-27 (3)
+U96D0	wanghong	2009-1-27 (2)
+U9703	wanghong	2009-1-27 (2)
+U9714	wanghong	2009-1-27 (2)
+U9717	wanghong	2009-1-27 (2)
+U971B	wanghong	2009-1-27 (2)
+U9731	wanghong	2009-1-27 (3)
+U9737	wanghong	2009-1-27 (3)
+U974C	wanghong	2009-1-27 (2)
+U975F	wanghong	2009-1-27 (2)
+U97A9	wanghong	2009-1-27 (2)
+U97B5	wanghong	2009-1-27 (2)
+U97C0	wanghong	2009-1-27 (3)
+U97E2	wanghong	2009-1-27 (2)
+U9825	wanghong	2009-1-27 (4)
+U9866	wanghong	2009-1-27 (2)
+U9868	wanghong	2009-1-27 (2)
+U9EC6	wanghong	2009-1-27 (2)
+U9ECB	wanghong	2009-1-27 (2)
+U9F02	wanghong	2009-1-27 (3)
+U9FA8	wanghong	2009-1-27 (3)
+U9FA9	wanghong	2009-1-27 (2)
+U9FAD	wanghong	2009-1-27 (2)
+U9FAF	wanghong	2009-1-27 (2)
+U9FBF	wanghong	2009-1-27 (2)
+U9F97	wanghong	2009-1-27 (2)
+U9F97	wanghong	2009-1-27 (3)
+U6244	anonymous	2009-1-27 (4)
+U61A3	anonymous	2009-1-27 (2)
+U6244	wanghong	2009-1-27 (5)
+U6160	anonymous	2009-1-27 (2)
+U60EA	anonymous	2009-1-27 (2)
+U6071	anonymous	2009-1-27 (2)
+U6071	wanghong	2009-1-27 (3)
+U60EA	wanghong	2009-1-27 (3)
+U6071	wanghong	2009-1-27 (4)
+U9F97	wanghong	2009-1-27 (4)
+U9FAF	wanghong	2009-1-27 (3)
+U3624	wanghong	2009-1-27 (2)
+U9D4E		2009-1-28 (2)
+U9D6E		2009-1-28 (2)
+U9D7C		2009-1-28 (2)
+U9E08		2009-1-28 (2)
+U9E16		2009-1-28 (2)
+U9E27		2009-1-28 (3)
+U9EA2		2009-1-28 (2)
+U9EA2		2009-1-28 (3)
+U9EA8		2009-1-28 (2)
+U9EB3		2009-1-28 (2)
+U9EC1		2009-1-28 (2)
+U39C7	anonymous	2009-1-28 (1)
+U580F	anonymous	2009-1-28 (2)
+U56A9	anonymous	2009-1-28 (2)
+U57C5	anonymous	2009-1-28 (2)
+U3D63	anonymous	2009-1-28 (1)
+U3596	anonymous	2009-1-28 (1)
+U3596	anonymous	2009-1-28 (2)
+U580F		2009-1-28 (3)
+U8FA0	anonymous	2009-1-28 (3)
+U8DC9	anonymous	2009-1-28 (2)
+U65C9	anonymous	2009-1-28 (2)
+U65FE	anonymous	2009-1-28 (2)
+U662C	anonymous	2009-1-28 (2)
+U66D3	anonymous	2009-1-28 (2)
+U66D3	anonymous	2009-1-28 (3)
+U662A	anonymous	2009-1-28 (2)
+U6730	anonymous	2009-1-28 (2)
+U67BC	anonymous	2009-1-28 (2)
+U67BC		2009-1-28 (3)
+U35B2	anonymous	2009-1-28 (1)
+U3F33	anonymous	2009-1-28 (1)
+U3C99	anonymous	2009-1-28 (1)
+U98CF		2009-1-28 (3)
+U98D7		2009-1-28 (2)
+U98B4		2009-1-28 (2)
+U98B7		2009-1-28 (2)
+U98B5		2009-1-28 (2)
+U857D		2009-1-28 (2)
+U855F		2009-1-28 (2)
+U352D	anonymous	2009-1-28 (1)
+U35CD	anonymous	2009-1-28 (1)
+U3BE4	anonymous	2009-1-28 (1)
+U3CDF	anonymous	2009-1-28 (1)
+U3D68	anonymous	2009-1-28 (1)
+U6299	anonymous	2009-1-28 (5)
+U643B	anonymous	2009-1-28 (3)
+U47C1	anonymous	2009-1-28 (1)
+U47C4	anonymous	2009-1-28 (1)
+U3F83	anonymous	2009-1-28 (1)
+U49B4	anonymous	2009-1-28 (1)
+U49B5	anonymous	2009-1-28 (1)
+U60EA	anonymous	2009-1-28 (4)
+U60EA	anonymous	2009-1-28 (5)
+U6299	anonymous	2009-1-28 (6)
+U3511		2009-1-28 (1)
+U64DD	FangQ	2009-1-29 (3)
+U6508	FangQ	2009-1-29 (2)
+U6719	FangQ	2009-1-29 (2)
+U688E	FangQ	2009-1-29 (3)
+U66D1	FangQ	2009-1-29 (2)
+U658D	FangQ	2009-1-29 (2)
+U6685	FangQ	2009-1-29 (2)
+U6870	FangQ	2009-1-29 (2)
+U658D	wanghong	2009-1-29 (3)
+U6873	FangQ	2009-1-29 (2)
+U65CA	FangQ	2009-1-29 (2)
+U65B4	FangQ	2009-1-29 (2)
+U66C3	FangQ	2009-1-29 (2)
+U6550	FangQ	2009-1-29 (2)
+U65B1	FangQ	2009-1-29 (2)
+U66C5	FangQ	2009-1-29 (4)
+U65C7	FangQ	2009-1-29 (2)
+U68E5	FangQ	2009-1-29 (2)
+U68BB	FangQ	2009-1-29 (2)
+U68BE	FangQ	2009-1-29 (2)
+U675B	FangQ	2009-1-29 (2)
+U6707	FangQ	2009-1-29 (2)
+U6586	FangQ	2009-1-29 (2)
+U6527	FangQ	2009-1-29 (2)
+U6527	FangQ	2009-1-29 (3)
+U650A	FangQ	2009-1-29 (2)
+U6916	FangQ	2009-1-29 (2)
+U6ABE	FangQ	2009-1-29 (2)
+U6BF1	FangQ	2009-1-29 (2)
+U6B6E	FangQ	2009-1-29 (2)
+U6BDD	FangQ	2009-1-29 (2)
+U3414	upsuper	2009-1-30 (1)
+U3692	upsuper	2009-1-30 (1)
+U50C0	lsz	2009-1-30 (2)
+U50D0	lsz	2009-1-30 (2)
+U5153	lsz	2009-1-30 (2)
+U516F	lsz	2009-1-30 (2)
+U5184	lsz	2009-1-30 (2)
+U5184	lsz	2009-1-30 (3)
+U522C	lsz	2009-1-30 (2)
+U522F	lsz	2009-1-30 (2)
+U63FC	anonymous	2009-1-30 (2)
+U6432	anonymous	2009-1-30 (3)
+U64F5	wanghong	2009-1-30 (2)
+U3692	FangQ	2009-1-31 (2)
+U6BDD	anonymous	2009-1-31 (3)
+U6B2E	anonymous	2009-1-31 (2)
+U98EC	wanghong	2009-1-31 (2)
+U9939	wanghong	2009-1-31 (2)
+U9940	wanghong	2009-1-31 (2)
+U9ADB	wanghong	2009-1-31 (3)
+U9AE9	wanghong	2009-1-31 (2)
+U9B00	wanghong	2009-1-31 (2)
+U9B02	wanghong	2009-1-31 (2)
+U9B09	wanghong	2009-1-31 (2)
+U9B14	wanghong	2009-1-31 (2)
+U9B26	wanghong	2009-1-31 (2)
+U9B36	wanghong	2009-1-31 (2)
+U9B39	wanghong	2009-1-31 (2)
+U9B57	wanghong	2009-1-31 (2)
+U5245	lsz	2009-1-31 (2)
+U5253	lsz	2009-1-31 (2)
+U5279	lsz	2009-1-31 (2)
+U5279	lsz	2009-1-31 (3)
+U52E5	lsz	2009-1-31 (2)
+U52FD	lsz	2009-1-31 (2)
+U5303	lsz	2009-1-31 (2)
+U5303	lsz	2009-1-31 (3)
+U530C	lsz	2009-1-31 (3)
+U530C	lsz	2009-1-31 (4)
+U5318	lsz	2009-1-31 (2)
+U531B	lsz	2009-1-31 (2)
+U77E1	lsz	2009-1-31 (2)
+U69BA	FangQ	2009-1-31 (2)
+U697F	FangQ	2009-1-31 (2)
+U6B2E	FangQ	2009-1-31 (3)
+U6B29	FangQ	2009-1-31 (3)
+U6B58	FangQ	2009-1-31 (2)
+U6BB9	FangQ	2009-1-31 (2)
+U6C1C	FangQ	2009-1-31 (2)
+U6C0A	FangQ	2009-1-31 (2)
+U6BF4	FangQ	2009-1-31 (2)
+U6A10	FangQ	2009-1-31 (2)
+U69C8	FangQ	2009-1-31 (2)
+U6A98	FangQ	2009-1-31 (2)
+U530C	FangQ	2009-1-31 (5)
+U52FD	FangQ	2009-1-31 (3)
+U8370	wanghong	2009-1-31 (2)
+U8371	wanghong	2009-1-31 (2)
+U8379	wanghong	2009-1-31 (2)
+U8370	wanghong	2009-1-31 (3)
+U8379	wanghong	2009-1-31 (3)
+U8370	wanghong	2009-1-31 (4)
+U8380	wanghong	2009-1-31 (2)
+U8382	wanghong	2009-1-31 (2)
+U8391	wanghong	2009-1-31 (2)
+U83A1	wanghong	2009-1-31 (2)
+U83BE	wanghong	2009-1-31 (2)
+U83BE	wanghong	2009-1-31 (3)
+U83E6	wanghong	2009-1-31 (2)
+U841F	wanghong	2009-1-31 (2)
+U843E	wanghong	2009-1-31 (2)
+U8441	wanghong	2009-1-31 (2)
+U844A	wanghong	2009-1-31 (2)
+U8464	wanghong	2009-1-31 (2)
+U846A	wanghong	2009-1-31 (2)
+U8472	wanghong	2009-1-31 (2)
+U847F	wanghong	2009-1-31 (2)
+U8485	wanghong	2009-1-31 (3)
+U847F	wanghong	2009-2-1 (3)
+U8493	wanghong	2009-2-1 (2)
+U84A6	wanghong	2009-2-1 (2)
+U84B5	wanghong	2009-2-1 (2)
+U84C8	wanghong	2009-2-1 (2)
+U84E1	wanghong	2009-2-1 (2)
+U84E2	wanghong	2009-2-1 (2)
+U84C8	wanghong	2009-2-1 (3)
+U855F	wanghong	2009-2-1 (3)
+U8533	wanghong	2009-2-1 (2)
+U854F	wanghong	2009-2-1 (2)
+U8504	wanghong	2009-2-1 (2)
+U8504	wanghong	2009-2-1 (3)
+U394E	anonymous	2009-2-1 (1)
+U3956	anonymous	2009-2-1 (1)
+U3951	anonymous	2009-2-1 (1)
+U4CA9	extc	2009-2-1 (1)
+U7C34	anonymous	2009-2-1 (2)
+U7C2E	anonymous	2009-2-1 (2)
+U4CA9	FangQ	2009-2-1 (2)
+U449A	anonymous	2009-2-1 (1)
+U449A	anonymous	2009-2-1 (2)
+U449A	anonymous	2009-2-1 (3)
+U449A	anonymous	2009-2-1 (4)
+U449A	anonymous	2009-2-1 (5)
+U46EA	anonymous	2009-2-2 (1)
+U3A43	anonymous	2009-2-2 (1)
+U4219	anonymous	2009-2-2 (1)
+U7C2E	FangQ	2009-2-2 (3)
+U49AF	anonymous	2009-2-2 (1)
+U46F6	anonymous	2009-2-2 (1)
+U46FC	anonymous	2009-2-2 (1)
+U49AF	FangQ	2009-2-2 (2)
+U49AF	wanghong	2009-2-2 (3)
+U3D25	anonymous	2009-2-2 (1)
+U3ACE	anonymous	2009-2-2 (1)
+U3D81	anonymous	2009-2-2 (1)
+U3599	anonymous	2009-2-2 (1)
+U359A	anonymous	2009-2-2 (1)
+U359B	anonymous	2009-2-2 (1)
+U41BB	anonymous	2009-2-3 (1)
+U41BC	anonymous	2009-2-3 (1)
+U78F8	lsz	2009-2-3 (2)
+U7918	lsz	2009-2-3 (3)
+U7933	lsz	2009-2-3 (2)
+U797B	lsz	2009-2-3 (2)
+U7999	lsz	2009-2-3 (2)
+U7A52	lsz	2009-2-3 (2)
+U7A6A	lsz	2009-2-3 (2)
+U7A9A	lsz	2009-2-3 (2)
+U7A9B	lsz	2009-2-3 (2)
+U7ABB	lsz	2009-2-3 (2)
+U7ABC	lsz	2009-2-3 (2)
+U7ABD	lsz	2009-2-3 (2)
+U7AC2	lsz	2009-2-3 (2)
+U7AEC	lsz	2009-2-3 (2)
+U7AFE	lsz	2009-2-3 (2)
+U7AFE	lsz	2009-2-3 (3)
+U7AFE	lsz	2009-2-3 (4)
+U7B16	lsz	2009-2-3 (2)
+U7B29	lsz	2009-2-3 (2)
+U7B42	lsz	2009-2-3 (2)
+U7B57	lsz	2009-2-3 (2)
+U625F	anonymous	2009-2-3 (3)
+U6160	anonymous	2009-2-3 (3)
+U6299	anonymous	2009-2-3 (7)
+U3A49	anonymous	2009-2-3 (1)
+U3A4A	anonymous	2009-2-3 (1)
+U3A4B	anonymous	2009-2-3 (1)
+U4085	anonymous	2009-2-4 (1)
+U7B5C	lsz	2009-2-4 (2)
+U7B5C	lsz	2009-2-4 (3)
+U7B5E	lsz	2009-2-4 (2)
+U7B5E	lsz	2009-2-4 (3)
+U7B6A	lsz	2009-2-4 (2)
+U7B6B	lsz	2009-2-4 (2)
+U6056	anonymous	2009-2-4 (3)
+U6098	anonymous	2009-2-4 (2)
+U6098	anonymous	2009-2-4 (3)
+U7B7F	lsz	2009-2-4 (2)
+U7B83	lsz	2009-2-4 (2)
+U7B89	lsz	2009-2-4 (4)
+U7BB2	lsz	2009-2-4 (2)
+U7BBB	lsz	2009-2-4 (2)
+U7BC2	lsz	2009-2-4 (2)
+U7BC2	lsz	2009-2-4 (3)
+U7BC2	lsz	2009-2-4 (4)
+U359E	anonymous	2009-2-4 (1)
+U36EF	mozbug	2009-2-4 (1)
+U36F7	mozbug	2009-2-4 (1)
+U6119	anonymous	2009-2-4 (2)
+U6133	anonymous	2009-2-4 (2)
+U6157	anonymous	2009-2-4 (2)
+U617B	anonymous	2009-2-4 (2)
+U617B	anonymous	2009-2-4 (3)
+U6184	anonymous	2009-2-4 (2)
+U6184	anonymous	2009-2-4 (3)
+U6184	anonymous	2009-2-4 (4)
+U6C3C	mozbug	2009-2-4 (2)
+U6185	anonymous	2009-2-4 (2)
+U6102	anonymous	2009-2-4 (2)
+U6D81	mozbug	2009-2-4 (2)
+U6D73	mozbug	2009-2-4 (2)
+U6197	anonymous	2009-2-4 (2)
+U6EA8	mozbug	2009-2-4 (2)
+U61A5	anonymous	2009-2-4 (2)
+U61BD	anonymous	2009-2-4 (5)
+U61C4	anonymous	2009-2-4 (2)
+U7550	lsz	2009-2-4 (2)
+U63FC	anonymous	2009-2-4 (3)
+U63FC	anonymous	2009-2-4 (4)
+U63FC	anonymous	2009-2-4 (5)
+U7552	lsz	2009-2-4 (2)
+U6407	anonymous	2009-2-4 (2)
+U6431	anonymous	2009-2-4 (2)
+U7588	lsz	2009-2-4 (2)
+U643C	anonymous	2009-2-4 (2)
+U75A6	lsz	2009-2-4 (2)
+U75A9	lsz	2009-2-4 (2)
+U75A9	lsz	2009-2-4 (3)
+U75AD	lsz	2009-2-4 (5)
+U75C6	lsz	2009-2-4 (2)
+U5093	mozbug	2009-2-4 (2)
+U508F	mozbug	2009-2-4 (2)
+U64AF	anonymous	2009-2-4 (2)
+U5089	mozbug	2009-2-4 (2)
+U5058	mozbug	2009-2-4 (2)
+U5001	mozbug	2009-2-4 (2)
+U4FF0	mozbug	2009-2-4 (2)
+U64D1	anonymous	2009-2-4 (2)
+U6098	anonymous	2009-2-4 (4)
+U64D3	anonymous	2009-2-4 (2)
+U75E5	lsz	2009-2-4 (2)
+U7673	lsz	2009-2-4 (2)
+U7673	lsz	2009-2-4 (3)
+U64DC	anonymous	2009-2-4 (2)
+U7606	lsz	2009-2-4 (2)
+U64EA	anonymous	2009-2-4 (2)
+U64D1	anonymous	2009-2-4 (3)
+U64EE	anonymous	2009-2-4 (2)
+U4E06	anonymous	2009-2-4 (3)
+U76E2	lsz	2009-2-4 (3)
+U4E12	anonymous	2009-2-4 (2)
+U4E2F	anonymous	2009-2-4 (3)
+U4E2F	anonymous	2009-2-4 (4)
+U4E4A	anonymous	2009-2-4 (2)
+U4E63	anonymous	2009-2-4 (2)
+U4E65	anonymous	2009-2-4 (2)
+U4EBE	anonymous	2009-2-4 (2)
+U4ECC	anonymous	2009-2-4 (2)
+U4EE2	anonymous	2009-2-4 (2)
+U4EE6	anonymous	2009-2-4 (2)
+U6C3C	anonymous	2009-2-4 (3)
+U4E2F	FangQ	2009-2-4 (5)
+U4EE6	FangQ	2009-2-4 (3)
+U6AA7	FangQ	2009-2-4 (2)
+U6AC9	FangQ	2009-2-4 (2)
+U6AE3	FangQ	2009-2-4 (3)
+U6AE3	FangQ	2009-2-4 (4)
+U6A9D	FangQ	2009-2-4 (2)
+U6AFE	FangQ	2009-2-4 (2)
+U6AF2	FangQ	2009-2-4 (2)
+U4F35	mozbug	2009-2-4 (2)
+U4F37	mozbug	2009-2-4 (2)
+U4FB0	mozbug	2009-2-4 (2)
+U98DD	mozbug	2009-2-4 (1)
+U4E78	mozbug	2009-2-4 (1)
+U5B90	mozbug	2009-2-4 (1)
+U5F63	mozbug	2009-2-4 (1)
+U616D	mozbug	2009-2-4 (1)
+U6A77	mozbug	2009-2-4 (1)
+U6AE6	mozbug	2009-2-4 (1)
+U6AFD	FangQ	2009-2-5 (2)
+U6FC5	mozbug	2009-2-5 (1)
+U7217	mozbug	2009-2-5 (1)
+U73F3	mozbug	2009-2-5 (1)
+U7524	mozbug	2009-2-5 (1)
+U7C1A	mozbug	2009-2-5 (1)
+U81D6	mozbug	2009-2-5 (1)
+U8644	mozbug	2009-2-5 (1)
+U9459	mozbug	2009-2-5 (1)
+U6EE3	anonymous	2009-2-5 (2)
+U6EE7	anonymous	2009-2-5 (2)
+U6EE7	anonymous	2009-2-5 (3)
+U6EE7	anonymous	2009-2-5 (4)
+U6EFA	anonymous	2009-2-5 (2)
+U64AF	wanghong	2009-2-5 (3)
+U64D1	wanghong	2009-2-5 (4)
+U6318	wanghong	2009-2-5 (5)
+U4FF0	wanghong	2009-2-5 (3)
+U7730	wanghong	2009-2-5 (3)
+U6E06	wanghong	2009-2-5 (2)
+U5763	wanghong	2009-2-5 (3)
+U5A3D	wanghong	2009-2-5 (4)
+U833D	wanghong	2009-2-5 (2)
+U832E	wanghong	2009-2-5 (2)
+U8313	wanghong	2009-2-5 (2)
+U8310	wanghong	2009-2-5 (2)
+U830B	wanghong	2009-2-5 (2)
+U82EE	wanghong	2009-2-5 (2)
+U82E9	wanghong	2009-2-5 (2)
+U828C	wanghong	2009-2-5 (2)
+U8296	wanghong	2009-2-5 (2)
+U82DD	wanghong	2009-2-5 (2)
+U82B2	wanghong	2009-2-5 (2)
+U8265	wanghong	2009-2-5 (2)
+U81CB	wanghong	2009-2-5 (2)
+U81A5	wanghong	2009-2-5 (2)
+U8190	wanghong	2009-2-5 (2)
+U8126	wanghong	2009-2-5 (3)
+U82F8	wanghong	2009-2-5 (2)
+U7FFA	wanghong	2009-2-5 (2)
+U8066	wanghong	2009-2-5 (2)
+U7C31	wanghong	2009-2-5 (2)
+U7BC5	wanghong	2009-2-5 (2)
+U7C18	wanghong	2009-2-5 (2)
+U7C18	wanghong	2009-2-5 (3)
+U7C35	wanghong	2009-2-5 (2)
+U7C36	wanghong	2009-2-5 (2)
+U7C3A	wanghong	2009-2-5 (2)
+U7C1A	wanghong	2009-2-5 (2)
+U760E	lsz	2009-2-5 (2)
+U7612	lsz	2009-2-5 (2)
+U7C44	wanghong	2009-2-5 (2)
+U762C	lsz	2009-2-5 (2)
+U7C46	wanghong	2009-2-5 (2)
+U7C55	wanghong	2009-2-5 (2)
+U7C5E	wanghong	2009-2-5 (2)
+U7636	lsz	2009-2-5 (2)
+U7C61	wanghong	2009-2-5 (2)
+U7C62	wanghong	2009-2-5 (2)
+U7C68	wanghong	2009-2-5 (2)
+U7C6D	wanghong	2009-2-5 (2)
+U7CC3	wanghong	2009-2-5 (2)
+U7CC3	wanghong	2009-2-5 (3)
+U7637	lsz	2009-2-5 (3)
+U7CDA	wanghong	2009-2-5 (2)
+U7CE5	wanghong	2009-2-5 (2)
+U7D25	wanghong	2009-2-5 (2)
+U7E71	wanghong	2009-2-5 (2)
+U7DA4	wanghong	2009-2-5 (2)
+U7639	lsz	2009-2-5 (2)
+U7DFF	wanghong	2009-2-5 (2)
+U7DFF	wanghong	2009-2-5 (3)
+U7F64	wanghong	2009-2-5 (3)
+U70D5	wanghong	2009-2-5 (2)
+U73AA	wanghong	2009-2-5 (2)
+U73E2	wanghong	2009-2-5 (2)
+U73EC	wanghong	2009-2-5 (2)
+U740E	wanghong	2009-2-5 (2)
+U70D5	wanghong	2009-2-5 (3)
+U73EC	wanghong	2009-2-5 (3)
+U6ED9	anonymous	2009-2-5 (2)
+U6EA8	anonymous	2009-2-5 (3)
+U6E95	anonymous	2009-2-5 (2)
+U6E84	anonymous	2009-2-5 (2)
+U6E84	anonymous	2009-2-5 (3)
+U6E84	anonymous	2009-2-5 (4)
+U6E84	anonymous	2009-2-5 (5)
+U6E84	anonymous	2009-2-5 (6)
+U6E6D	anonymous	2009-2-5 (2)
+U6E50	anonymous	2009-2-5 (2)
+U7651	lsz	2009-2-5 (2)
+U6D21	anonymous	2009-2-5 (2)
+U7054	anonymous	2009-2-5 (4)
+U704E	anonymous	2009-2-5 (3)
+U704D	anonymous	2009-2-5 (2)
+U703D	anonymous	2009-2-5 (2)
+U702E	anonymous	2009-2-5 (2)
+U702E	anonymous	2009-2-5 (3)
+U76D5	lsz	2009-2-5 (2)
+U76E0	lsz	2009-2-5 (2)
+U74C9	wanghong	2009-2-5 (2)
+U72AB	anonymous	2009-2-5 (2)
+U7257	anonymous	2009-2-5 (2)
+U7234	wanghong	2009-2-5 (3)
+U7211	wanghong	2009-2-5 (2)
+U7103	wanghong	2009-2-5 (2)
+U71BB	wanghong	2009-2-5 (2)
+U70A2	wanghong	2009-2-5 (2)
+U70F5	wanghong	2009-2-5 (2)
+U79BC	mozbug	2009-2-5 (1)
+U70FE	wanghong	2009-2-5 (2)
+U71DE	wanghong	2009-2-5 (2)
+U7212	wanghong	2009-2-5 (2)
+U712D	wanghong	2009-2-5 (2)
+U4553	anonymous	2009-2-6 (1)
+U712D	wanghong	2009-2-6 (3)
+U41AC	anonymous	2009-2-6 (1)
+U4B29	anonymous	2009-2-6 (1)
+U47B8	anonymous	2009-2-6 (1)
+U3552	anonymous	2009-2-6 (1)
+U38A7	anonymous	2009-2-6 (1)
+U405E	anonymous	2009-2-6 (1)
+U4670	mozbug	2009-2-6 (1)
+U4361	mozbug	2009-2-6 (1)
+U4361	mozbug	2009-2-6 (2)
+U45AF	anonymous	2009-2-6 (1)
+U3BE5	mozbug	2009-2-6 (1)
+U3FE9	mozbug	2009-2-6 (1)
+U4A18	mozbug	2009-2-6 (1)
+U3BB8	mozbug	2009-2-6 (1)
+U3567	mozbug	2009-2-6 (1)
+U423D	mozbug	2009-2-6 (1)
+U3E5C	mozbug	2009-2-6 (1)
+U44B2	mozbug	2009-2-6 (1)
+U4CD8	mozbug	2009-2-6 (1)
+U3976	mozbug	2009-2-6 (1)
+U4CDE	anonymous	2009-2-6 (1)
+U4CE0	anonymous	2009-2-6 (1)
+U4CDF	anonymous	2009-2-6 (1)
+U4CDE	anonymous	2009-2-6 (2)
+U34B2	anonymous	2009-2-6 (1)
+U3ACC	anonymous	2009-2-6 (1)
+U4BF2	mozbug	2009-2-6 (1)
+U423E	anonymous	2009-2-6 (1)
+U4233	anonymous	2009-2-6 (1)
+U4675	mozbug	2009-2-6 (1)
+U48B4	mozbug	2009-2-6 (1)
+U4AC3	anonymous	2009-2-6 (1)
+U4CE9	anonymous	2009-2-6 (1)
+U3B95	mozbug	2009-2-6 (1)
+U4CF8	mozbug	2009-2-6 (1)
+U4CF8	mozbug	2009-2-6 (2)
+U468D	anonymous	2009-2-6 (1)
+U4D0F	mozbug	2009-2-6 (1)
+U47C6	anonymous	2009-2-6 (1)
+U39A2	anonymous	2009-2-6 (1)
+U3FF9	mozbug	2009-2-6 (1)
+U3FF7	mozbug	2009-2-6 (1)
+U3FFA	mozbug	2009-2-6 (1)
+U388A	anonymous	2009-2-6 (1)
+U43AB	mozbug	2009-2-6 (1)
+U4360	mozbug	2009-2-6 (1)
+U48E3	mozbug	2009-2-6 (1)
+U4208	mozbug	2009-2-6 (1)
+U4A05	mozbug	2009-2-6 (1)
+U494D	mozbug	2009-2-6 (1)
+U4DA8	mozbug	2009-2-6 (1)
+U4B74	mozbug	2009-2-6 (1)
+U4B78	mozbug	2009-2-6 (1)
+U4CD7	mozbug	2009-2-6 (1)
+U4CD4	mozbug	2009-2-6 (1)
+U3C52	mozbug	2009-2-6 (1)
+U3812	mozbug	2009-2-6 (1)
+U4BED	mozbug	2009-2-6 (1)
+U44B7	mozbug	2009-2-6 (1)
+U4D61	mozbug	2009-2-6 (1)
+U4244	mozbug	2009-2-6 (1)
+U421F	mozbug	2009-2-6 (1)
+U468A	mozbug	2009-2-6 (1)
+U4CFB	mozbug	2009-2-6 (1)
+U4CFB	mozbug	2009-2-6 (2)
+U4D68	mozbug	2009-2-6 (1)
+U4897	anonymous	2009-2-6 (1)
+U4194	mozbug	2009-2-6 (1)
+U4222	mozbug	2009-2-6 (1)
+U4D0E	anonymous	2009-2-6 (1)
+U82FF	wanghong	2009-2-6 (2)
+U865D	wanghong	2009-2-6 (2)
+U6AD2	FangQ	2009-2-6 (2)
+U6AC9	FangQ	2009-2-6 (3)
+U6B0D	FangQ	2009-2-6 (2)
+U69E3	FangQ	2009-2-6 (2)
+U82FF	wanghong	2009-2-6 (3)
+U4D31	mozbug	2009-2-6 (1)
+U6B68	FangQ	2009-2-6 (2)
+U6A10	FangQ	2009-2-6 (3)
+U3527	mozbug	2009-2-6 (1)
+U6AE3	FangQ	2009-2-6 (5)
+U39BA	mozbug	2009-2-6 (1)
+U37CC	mozbug	2009-2-6 (1)
+U4D88	mozbug	2009-2-6 (1)
+U3FF5	mozbug	2009-2-6 (1)
+U431F	mozbug	2009-2-6 (1)
+U4D2C	mozbug	2009-2-6 (1)
+U4BE8	mozbug	2009-2-6 (1)
+U4BE9	mozbug	2009-2-6 (1)
+U3B97	mozbug	2009-2-6 (1)
+U3B97	mozbug	2009-2-6 (2)
+U4D2D	mozbug	2009-2-6 (1)
+U421A	mozbug	2009-2-7 (1)
+U6E50	anonymous	2009-2-7 (3)
+U37D3	mozbug	2009-2-7 (2)
+U4A1B	mozbug	2009-2-7 (1)
+U4195	mozbug	2009-2-7 (1)
+U3619	mozbug	2009-2-7 (1)
+U3C0D	mozbug	2009-2-7 (1)
+U3C0E	mozbug	2009-2-7 (1)
+U7008	anonymous	2009-2-7 (2)
+U7003	anonymous	2009-2-7 (2)
+U6FE5	anonymous	2009-2-7 (2)
+U6FD7	anonymous	2009-2-7 (2)
+U6F56	anonymous	2009-2-7 (2)
+U6FB7	anonymous	2009-2-7 (2)
+U6F9A	anonymous	2009-2-7 (2)
+U6F99	anonymous	2009-2-7 (2)
+U6306	anonymous	2009-2-7 (2)
+U6F79	anonymous	2009-2-7 (2)
+U6F68	anonymous	2009-2-7 (2)
+U6F56	anonymous	2009-2-7 (3)
+U6F49	anonymous	2009-2-7 (2)
+U6F34	anonymous	2009-2-7 (2)
+U6F0B	anonymous	2009-2-7 (2)
+U6C31	anonymous	2009-2-7 (2)
+U6CCB	anonymous	2009-2-7 (2)
+U6CE6	anonymous	2009-2-7 (2)
+U6D6B	anonymous	2009-2-7 (2)
+U6E37	anonymous	2009-2-7 (2)
+U6CCB	wanghong	2009-2-7 (3)
+U6CCB	wanghong	2009-2-7 (4)
+U6CCB	wanghong	2009-2-7 (5)
+U4A17	anonymous	2009-2-7 (1)
+U6FE5	FangQ	2009-2-7 (3)
+U3F15	anonymous	2009-2-7 (1)
+U3F3D	anonymous	2009-2-7 (1)
+U56B9	wanghong	2009-2-8 (1)
+U9FC3	FangQ	2009-2-8 (2)
+U705C	wanghong	2009-2-8 (1)
+U3DD6	bt4wang	2009-2-8 (1)
+U4C1F	mozbug	2009-2-8 (1)
+U3FEF	mozbug	2009-2-8 (1)
+U3FF1	mozbug	2009-2-8 (1)
+U3C1C	bt4wang	2009-2-8 (1)
+U3BF6	mozbug	2009-2-8 (1)
+U3E0D	mozbug	2009-2-8 (1)
+U460A	mozbug	2009-2-8 (1)
+U3D5E	mozbug	2009-2-8 (1)
+U4B55	mozbug	2009-2-8 (1)
+U4978	mozbug	2009-2-8 (1)
+U3D9A	mozbug	2009-2-8 (1)
+U4A23	mozbug	2009-2-8 (1)
+U4A23	mozbug	2009-2-8 (2)
+U39B0	mozbug	2009-2-8 (1)
+U95E6	mozbug	2009-2-8 (1)
+U7B27	wanghong	2009-2-8 (2)
+U7B27	wanghong	2009-2-8 (3)
+U46E2	bt4wang	2009-2-8 (1)
+U46E2	bt4wang	2009-2-8 (2)
+U459E	anonymous	2009-2-9 (1)
+U4AF4	anonymous	2009-2-9 (1)
+U48CF		2009-2-9 (1)
+U3CD2		2009-2-9 (1)
+U3CD2		2009-2-9 (2)
+U449D		2009-2-9 (1)
+U3889		2009-2-9 (1)
+U8D9A	wanghong	2009-2-9 (2)
+U8D9A	wanghong	2009-2-9 (3)
+U3B90	anonymous	2009-2-10 (1)
+U4AEE	anonymous	2009-2-10 (1)
+U4CE8	bt4wang	2009-2-10 (1)
+U3A9F	bt4wang	2009-2-10 (1)
+U378D	anonymous	2009-2-10 (1)
+U378D	anonymous	2009-2-10 (2)
+U4968		2009-2-11 (1)
+U496C		2009-2-11 (1)
+U4883		2009-2-11 (1)
+U351F	mozbug	2009-2-11 (1)
+U342C	mozbug	2009-2-11 (1)
+U342D	mozbug	2009-2-11 (1)
+U342E	mozbug	2009-2-11 (1)
+U34BB		2009-2-11 (1)
+U380D		2009-2-11 (1)
+U3810		2009-2-11 (1)
+U398C	mozbug	2009-2-11 (1)
+U3D4D	mozbug	2009-2-11 (1)
+U3526		2009-2-11 (1)
+U411F	mozbug	2009-2-11 (1)
+U47C7	mozbug	2009-2-11 (1)
+U3B1F	mozbug	2009-2-11 (1)
+U349E	mozbug	2009-2-11 (1)
+U4B68	mozbug	2009-2-11 (1)
+U3512	mozbug	2009-2-11 (1)
+U3697	anonymous	2009-2-12 (1)
+U426A	anonymous	2009-2-12 (1)
+U3697	FangQ	2009-2-12 (2)
+U3FFE	anonymous	2009-2-13 (1)
+U4993	anonymous	2009-2-13 (1)
+U3D2F	anonymous	2009-2-14 (1)
+U3DE8	anonymous	2009-2-14 (1)
+U3DE8	anonymous	2009-2-14 (2)
+U4D67	anonymous	2009-2-14 (1)
+U3811	anonymous	2009-2-14 (1)
+U439C	anonymous	2009-2-14 (1)
+U3BBA	anonymous	2009-2-14 (1)
+U3BBA	anonymous	2009-2-14 (2)
+U3BBA	anonymous	2009-2-14 (3)
+U3BBA	anonymous	2009-2-14 (4)
+U3BBA	anonymous	2009-2-14 (5)
+U3BBA	anonymous	2009-2-14 (6)
+U3BBA	anonymous	2009-2-14 (7)
+U3BBA	anonymous	2009-2-14 (8)
+U3BBA	anonymous	2009-2-14 (9)
+U4CBF	anonymous	2009-2-14 (1)
+U359C	anonymous	2009-2-14 (1)
+U489E	anonymous	2009-2-14 (1)
+U489B	anonymous	2009-2-14 (1)
+U489D	anonymous	2009-2-14 (1)
+U41A8	anonymous	2009-2-14 (1)
+U494B	anonymous	2009-2-14 (1)
+U499F	anonymous	2009-2-14 (1)
+U49A0	anonymous	2009-2-14 (1)
+U4CD3	anonymous	2009-2-14 (1)
+U4B08	anonymous	2009-2-14 (1)
+U4B0A	anonymous	2009-2-14 (1)
+U49ED	anonymous	2009-2-14 (1)
+U4253	anonymous	2009-2-14 (1)
+U4255	anonymous	2009-2-14 (1)
+U3D03	anonymous	2009-2-14 (1)
+U4896	anonymous	2009-2-14 (1)
+U489F	anonymous	2009-2-14 (1)
+U3D8A	anonymous	2009-2-14 (1)
+U416B	anonymous	2009-2-14 (1)
+U3D8A	anonymous	2009-2-14 (2)
+U450F	anonymous	2009-2-14 (1)
+U4455	anonymous	2009-2-14 (1)
+U4455	anonymous	2009-2-14 (2)
+U4455	anonymous	2009-2-14 (3)
+U4455	anonymous	2009-2-14 (4)
+U4455	anonymous	2009-2-14 (5)
+U4455	anonymous	2009-2-14 (6)
+U352B	anonymous	2009-2-14 (1)
+U348D	anonymous	2009-2-14 (1)
+U3CB3	anonymous	2009-2-14 (1)
+U37DF	anonymous	2009-2-14 (1)
+U345E	anonymous	2009-2-14 (1)
+U3445	anonymous	2009-2-15 (1)
+U4B06	anonymous	2009-2-15 (1)
+U4B05	anonymous	2009-2-15 (1)
+U4BFC	anonymous	2009-2-15 (1)
+U3B98	anonymous	2009-2-15 (1)
+U4674	anonymous	2009-2-15 (1)
+U358C	anonymous	2009-2-15 (1)
+U4C01	anonymous	2009-2-15 (1)
+U466F	anonymous	2009-2-15 (1)
+U466F	anonymous	2009-2-15 (2)
+U3407	anonymous	2009-2-15 (1)
+U3408	anonymous	2009-2-15 (1)
+U3407	anonymous	2009-2-15 (2)
+U3CA4	anonymous	2009-2-15 (1)
+U3786		2009-2-15 (1)
+U3786		2009-2-15 (2)
+U3786		2009-2-15 (3)
+U3786		2009-2-15 (4)
+U3787		2009-2-15 (1)
+U3789		2009-2-15 (1)
+U4242		2009-2-15 (1)
+U3CA1	anonymous	2009-2-15 (1)
+U3C9A	anonymous	2009-2-15 (1)
+U3D04	anonymous	2009-2-15 (1)
+U3CA0	anonymous	2009-2-15 (1)
+U3D02	anonymous	2009-2-15 (1)
+U3D09	anonymous	2009-2-15 (1)
+U34C4	wanghong	2009-2-16 (1)
+U34D2	wanghong	2009-2-16 (1)
+U3814	anonymous	2009-2-16 (1)
+U4676	anonymous	2009-2-16 (1)
+U4703	anonymous	2009-2-16 (1)
+U44B8	anonymous	2009-2-16 (1)
+U44B6	anonymous	2009-2-16 (1)
+U3687	anonymous	2009-2-16 (1)
+U44B6		2009-2-17 (2)
+U369D	anonymous	2009-2-17 (1)
+U369C	anonymous	2009-2-17 (1)
+U3694	anonymous	2009-2-17 (1)
+U3E1B		2009-2-17 (1)
+U44AB		2009-2-17 (1)
+U3687	anonymous	2009-2-17 (2)
+U369D	anonymous	2009-2-17 (2)
+U4245	gaoxuewei	2009-2-17 (1)
+U3784	gaoxuewei	2009-2-17 (1)
+U389E	gaoxuewei	2009-2-17 (1)
+U3CAF	anonymous	2009-2-18 (1)
+U4744	gaoxuewei	2009-2-18 (1)
+U4596	gaoxuewei	2009-2-18 (1)
+U3D64	anonymous	2009-2-18 (1)
+U4257	anonymous	2009-2-19 (1)
+U4258	anonymous	2009-2-19 (1)
+U4135	anonymous	2009-2-19 (1)
+U35B3	anonymous	2009-2-19 (1)
+U4D87	anonymous	2009-2-19 (1)
+U4D89	anonymous	2009-2-19 (1)
+U4D92	anonymous	2009-2-19 (1)
+U4D92	anonymous	2009-2-19 (2)
+U4D92	anonymous	2009-2-19 (3)
+U4D92	anonymous	2009-2-19 (4)
+U4CDB	anonymous	2009-2-19 (1)
+U4258	FangQ	2009-2-20 (2)
+U4258	FangQ	2009-2-20 (3)
+U3A7B	anonymous	2009-2-21 (1)
+U384C	anonymous	2009-2-21 (1)
+U3B31	anonymous	2009-2-21 (1)
+U384C	FangQ	2009-2-21 (2)
+U376D	anonymous	2009-2-22 (1)
+U499E	anonymous	2009-2-22 (1)
+U49A1	anonymous	2009-2-22 (1)
+U3CA5	anonymous	2009-2-22 (1)
+U3CA6	anonymous	2009-2-22 (1)
+U3CA7	anonymous	2009-2-22 (1)
+U4856	anonymous	2009-2-22 (1)
+U36FD	anonymous	2009-2-22 (1)
+U4A08	anonymous	2009-2-22 (1)
+U4D2E	anonymous	2009-2-22 (1)
+U47BC	anonymous	2009-2-22 (1)
+U45FB	anonymous	2009-2-22 (1)
+U36FD	FangQ	2009-2-22 (2)
+U4A08	FangQ	2009-2-22 (2)
+U4856	FangQ	2009-2-22 (2)
+U3CAB	mozbug	2009-2-23 (1)
+U389D	mozbug	2009-2-23 (1)
+U3F48	anonymous	2009-2-23 (1)
+U3D26	anonymous	2009-2-24 (1)
+U3FA9	anonymous	2009-2-25 (1)
+U3C8D	anonymous	2009-2-25 (1)
+U4198	bt4wang	2009-2-25 (1)
+U4199	bt4wang	2009-2-25 (1)
+U36BA	extc	2009-2-26 (1)
+U4139	extc	2009-2-26 (1)
+U413C	extc	2009-2-26 (1)
+U424E	bt4wang	2009-2-26 (1)
+U4250	bt4wang	2009-2-26 (1)
+U4B47	bt4wang	2009-2-26 (1)
+U400F	bt4wang	2009-2-26 (1)
+U3FB7	anonymous	2009-2-27 (1)
+U3FB8	anonymous	2009-2-27 (1)
+U3FB9	anonymous	2009-2-27 (1)
+U4602	anonymous	2009-2-27 (1)
+U44ED	anonymous	2009-2-27 (1)
+U4944	bt4wang	2009-2-28 (1)
+U3964	bt4wang	2009-2-28 (1)
+U3AAF	bt4wang	2009-2-28 (1)
+U34C0	bt4wang	2009-2-28 (1)
+U3CE8	bt4wang	2009-2-28 (1)
+U36C2	bt4wang	2009-2-28 (1)
+U44A4	bt4wang	2009-2-28 (1)
+U43B0	anonymous	2009-3-1 (1)
+U439E	anonymous	2009-3-1 (1)
+U388B		2009-3-1 (1)
+U4820	anonymous	2009-3-2 (1)
+U4868	anonymous	2009-3-2 (1)
+U3CF6	anonymous	2009-3-3 (1)
+U379C		2009-3-3 (1)
+U3531	anonymous	2009-3-4 (1)
+U4971	bt4wang	2009-3-4 (1)
+U4975	bt4wang	2009-3-4 (1)
+U4748	bt4wang	2009-3-4 (1)
+U4677	bt4wang	2009-3-4 (1)
+U3C8A	bt4wang	2009-3-4 (1)
+U3C8C	bt4wang	2009-3-4 (1)
+U3D4C	bt4wang	2009-3-4 (1)
+U3C00	bt4wang	2009-3-4 (1)
+U348E	bt4wang	2009-3-4 (1)
+U48A7	bt4wang	2009-3-5 (1)
+U4502	bt4wang	2009-3-5 (1)
+U37F6	bt4wang	2009-3-5 (1)
+U435D	anonymous	2009-3-5 (1)
+U4362	anonymous	2009-3-5 (1)
+U3BB1	anonymous	2009-3-5 (1)
+U47C3	anonymous	2009-3-5 (1)
+U3689	anonymous	2009-3-5 (1)
+U3689	anonymous	2009-3-5 (2)
+U3689	anonymous	2009-3-5 (3)
+U3689	anonymous	2009-3-5 (4)
+U3689	anonymous	2009-3-5 (5)
+U3689	anonymous	2009-3-5 (6)
+U37AE	anonymous	2009-3-5 (1)
+U37AE	anonymous	2009-3-5 (2)
+U37B7	anonymous	2009-3-5 (1)
+U3DD7	anonymous	2009-3-5 (1)
+U3DE0	anonymous	2009-3-5 (1)
+U3DE0	anonymous	2009-3-5 (2)
+U3DDE	anonymous	2009-3-5 (1)
+U3415		2009-3-5 (1)
+U3415		2009-3-5 (2)
+U3415		2009-3-5 (3)
+U3415		2009-3-5 (4)
+U3415		2009-3-5 (5)
+U3415		2009-3-5 (6)
+U3415		2009-3-5 (7)
+U3415		2009-3-5 (8)
+U3415		2009-3-5 (9)
+U3418		2009-3-5 (1)
+U4D13	anonymous	2009-3-6 (1)
+U44C7	anonymous	2009-3-6 (1)
+U44C7	anonymous	2009-3-6 (2)
+U44C7	anonymous	2009-3-6 (3)
+U3405	anonymous	2009-3-6 (1)
+U3406	anonymous	2009-3-6 (1)
+U38CE	anonymous	2009-3-7 (1)
+U4A04	anonymous	2009-3-7 (1)
+U3D5F	anonymous	2009-3-7 (1)
+U375B	anonymous	2009-3-7 (1)
+U4CE5		2009-3-8 (1)
+U4CE6		2009-3-8 (1)
+U44A5		2009-3-8 (1)
+U4A07		2009-3-8 (1)
+U4A07		2009-3-8 (2)
+U4A09		2009-3-8 (1)
+U45FD		2009-3-8 (1)
+U421E		2009-3-8 (1)
+U361C		2009-3-8 (1)
+U4CE7		2009-3-8 (1)
+U4459		2009-3-8 (1)
+U4CE7	FangQ	2009-3-8 (2)
+U421E	FangQ	2009-3-8 (2)
+U3AD2	anonymous	2009-3-8 (1)
+U4CE7	FangQ	2009-3-9 (3)
+U4691	anonymous	2009-3-10 (1)
+U3CEB	anonymous	2009-3-10 (1)
+U3D0D	anonymous	2009-3-10 (1)
+U3F4A	mozbug	2009-3-11 (1)
+U4A1E	mozbug	2009-3-11 (1)
+U4A1F	mozbug	2009-3-11 (1)
+U418F	anonymous	2009-3-11 (1)
+U418F	anonymous	2009-3-11 (2)
+U4BD0	anonymous	2009-3-11 (1)
+U4BD0	anonymous	2009-3-11 (2)
+U3553	extc	2009-3-11 (1)
+U3553	FangQ	2009-3-11 (2)
+U369F	FangQ	2009-3-12 (1)
+U4AEA	FangQ	2009-3-12 (1)
+U4AEF	FangQ	2009-3-12 (1)
+U3998	FangQ	2009-3-12 (1)
+U4CAA	FangQ	2009-3-12 (1)
+U3544	FangQ	2009-3-12 (1)
+U46D5	anonymous	2009-3-15 (1)
+U4CA5	anonymous	2009-3-15 (1)
+U3AEF	FangQ	2009-3-15 (1)
+U3F02	FangQ	2009-3-16 (1)
+U4BC1	FangQ	2009-3-16 (1)
+U359D	FangQ	2009-3-16 (1)
+U4755	anonymous	2009-3-16 (1)
+U4755	anonymous	2009-3-16 (2)
+U47BB	anonymous	2009-3-17 (1)
+U37EE	bt4wang	2009-3-17 (1)
+U4570	anonymous	2009-3-17 (1)
+U4CF1	anonymous	2009-3-20 (1)
+U4568	anonymous	2009-3-20 (1)
+U47BD	anonymous	2009-3-20 (1)
+U47BD	anonymous	2009-3-20 (2)
+U4B7C	anonymous	2009-3-25 (1)
+U4458	anonymous	2009-3-27 (1)
+U35CE	anonymous	2009-3-27 (1)
+U4996	anonymous	2009-3-27 (1)
+U4998	anonymous	2009-3-27 (1)
+U4999	anonymous	2009-3-27 (1)
+U39AF	anonymous	2009-3-27 (1)
+U3478	fujianwzh	2009-3-31 (1)
+U3485	fujianwzh	2009-3-31 (1)
+U43A0	fujianwzh	2009-3-31 (1)
+U4223	anonymous	2009-3-31 (1)
+U44BA	anonymous	2009-3-31 (1)
+U3C37	felicity	2009-4-2 (1)
+U3B5E	felicity	2009-4-2 (1)
+U3F4F	felicity	2009-4-2 (1)
+U4A0B	felicity	2009-4-2 (1)
+U4A0C	felicity	2009-4-2 (1)
+U3FAA	felicity	2009-4-2 (1)
+U471B	felicity	2009-4-2 (1)
+U4942	anonymous	2009-4-2 (1)
+U39C0	anonymous	2009-4-2 (1)
+U41EB	anonymous	2009-4-2 (1)
+U3A44	anonymous	2009-4-2 (1)
+U4A0C	FangQ	2009-4-2 (2)
+U44A9	felicity	2009-4-2 (1)
+U3DE6	anonymous	2009-4-3 (1)
+U3DE6	FangQ	2009-4-3 (2)
+U351C		2009-4-8 (1)
+U431C		2009-4-9 (1)
+U341F	anonymous	2009-4-12 (1)
+U4504	anonymous	2009-4-12 (1)
+U4BE2	FangQ	2009-4-12 (1)
+U4BE2	FangQ	2009-4-12 (2)
+U4BF4	FangQ	2009-4-12 (1)
+U4BF4	FangQ	2009-4-12 (2)
+U44FE	anonymous	2009-4-12 (1)
+U4500	anonymous	2009-4-12 (1)
+U4500	FangQ	2009-4-12 (2)
+U4363	anonymous	2009-4-19 (1)
+U376F	anonymous	2009-4-19 (1)
+U4C26	anonymous	2009-4-19 (1)
+U4C26	anonymous	2009-4-19 (2)
+U3DAB	FangQ	2009-4-25 (1)
+U3CAE	FangQ	2009-4-25 (1)
+U3CB1	FangQ	2009-4-25 (1)
+U4259	FangQ	2009-4-25 (1)
+U467E	FangQ	2009-4-25 (1)
+U399A	FangQ	2009-4-25 (1)
+U348F	FangQ	2009-4-25 (1)
+U3490	FangQ	2009-4-25 (1)
+U4CAB	FangQ	2009-4-25 (1)
+U4CAF	FangQ	2009-4-25 (1)
+U440C	FangQ	2009-4-25 (1)
+U4DAC	FangQ	2009-4-25 (1)
+U4DAC	FangQ	2009-4-25 (2)
+U36A6	FangQ	2009-4-25 (1)
+U4DAC	FangQ	2009-4-25 (3)
+U431B	anonymous	2009-4-26 (1)
+U341B	anonymous	2009-4-26 (1)
+U3D9B	anonymous	2009-4-26 (1)
+U41DD	anonymous	2009-4-26 (1)
+U41DD	anonymous	2009-4-26 (2)
+U4B9F	anonymous	2009-4-26 (1)
+U4299	anonymous	2009-4-26 (1)
+U389C	anonymous	2009-4-26 (1)
+U3683	anonymous	2009-4-26 (1)
+U3503	anonymous	2009-4-26 (1)
+U341E	anonymous	2009-4-26 (1)
+U48AD	anonymous	2009-4-26 (1)
+U3B46	anonymous	2009-4-26 (1)
+U4C22	anonymous	2009-4-26 (1)
+U49A2	anonymous	2009-4-26 (1)
+U49A8	anonymous	2009-4-26 (1)
+U49A8	anonymous	2009-4-26 (2)
+U4DA9	anonymous	2009-4-26 (1)
+U48DE	anonymous	2009-4-26 (1)
+U3D51	anonymous	2009-4-26 (1)
+U3769	anonymous	2009-4-26 (1)
+U4A21	anonymous	2009-4-28 (1)
+U429B	anonymous	2009-4-29 (1)
+U4331	anonymous	2009-4-30 (1)
+U4331	FangQ	2009-4-30 (2)
+U34EC	FangQ	2009-5-7 (1)
+U34EC	FangQ	2009-5-7 (2)
+U649B	FangQ	2009-5-11 (2)
+U67E2	FangQ	2009-5-11 (1)
+U80E1	FangQ	2009-5-11 (1)
+U79B5	FangQ	2009-5-11 (2)
+U8657	FangQ	2009-5-11 (2)
+U8745	FangQ	2009-5-11 (2)
+U8745	FangQ	2009-5-11 (3)
+U4E12	FangQ	2009-5-17 (3)
+U47AA	anonymous	2009-5-17 (1)
+U4334	anonymous	2009-5-17 (1)
+U3D5A	anonymous	2009-5-17 (1)
+U3D5A	anonymous	2009-5-17 (2)
+U4BF5	FangQ	2009-5-17 (1)
+U3D5D	anonymous	2009-5-17 (1)
+U3D5D	anonymous	2009-5-17 (2)
+U4D25	anonymous	2009-5-17 (1)
+U41E7	FangQ	2009-5-17 (1)
+U41D6	FangQ	2009-5-19 (1)
+U807C	FangQ	2009-5-20 (3)
+U378E	anonymous	2009-5-21 (1)
+U3EBC	anonymous	2009-5-22 (1)
+U3EBC	FangQ	2009-5-22 (2)
+U3FB5	FangQ	2009-5-22 (1)
+U3FB6	FangQ	2009-5-22 (1)
+U3FB6	FangQ	2009-5-22 (2)
+U3FB6	FangQ	2009-5-22 (3)
+U3FB5	FangQ	2009-5-22 (2)
+U3919	FangQ	2009-5-23 (1)
diff --git a/songmanagement/game/fonts/wqy-microhei/LICENSE_Apache2.txt b/songmanagement/game/fonts/wqy-microhei/LICENSE_Apache2.txt
new file mode 100644
index 00000000..79fd69c9
--- /dev/null
+++ b/songmanagement/game/fonts/wqy-microhei/LICENSE_Apache2.txt
@@ -0,0 +1,122 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this 
+document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common 
+control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the 
+direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, 
+documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not 
+limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a 
+copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which 
+the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. 
+For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by 
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to 
+that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner 
+or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, 
+"submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including 
+but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are 
+managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is 
+conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor 
+and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a 
+perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works 
+of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, 
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, 
+use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable 
+by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with 
+the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim 
+or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or 
+contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the 
+date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without 
+modifications, and in Source or Object form, provided that You meet the following conditions:
+
+   1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+   2. You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+   3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and 
+attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative 
+Works; and
+
+   4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must 
+include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to 
+any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the 
+Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display 
+generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for 
+informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You 
+distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot 
+be construed as modifying the License.
+
+You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions 
+for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, 
+reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the 
+Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. 
+Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have 
+executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the 
+Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of 
+the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each 
+Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
+implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 
+PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume 
+any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, 
+unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be 
+liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as 
+a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, 
+work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has 
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, 
+and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this 
+License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf 
+of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred 
+by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" 
+replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment 
+syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed 
+page" as the copyright notice for easier identification within third-party archives.
+Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
+except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless 
+required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, 
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing 
+permissions and limitations under the License.
diff --git a/songmanagement/game/fonts/wqy-microhei/LICENSE_GPLv3.txt b/songmanagement/game/fonts/wqy-microhei/LICENSE_GPLv3.txt
new file mode 100644
index 00000000..94a9ed02
--- /dev/null
+++ b/songmanagement/game/fonts/wqy-microhei/LICENSE_GPLv3.txt
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/songmanagement/game/fonts/wqy-microhei/README.txt b/songmanagement/game/fonts/wqy-microhei/README.txt
new file mode 100644
index 00000000..16b8ac24
--- /dev/null
+++ b/songmanagement/game/fonts/wqy-microhei/README.txt
@@ -0,0 +1,378 @@
+
+==========================================================
+
+                 Wen Quan Yi Micro Hei
+
+                    Release Notes
+
+----------------------------------------------------------
+
+Summary:
+
+    Author   : WenQuanYi Project Contributors
+    Webpage  : http://wenq.org/en/ or http://wqy.sourceforge.net/en/
+    Font Name: WenQuanYi Micro Hei
+    Version  : 0.2.0-beta (Big-Bang)
+    Release  : 0
+    Copyright  Digitized data copyright � 2007, Google Corporation.
+               Copyright � 2008-2009, WenQuanYi Project Board of
+               Trustees, All rights reserved.
+
+               Droid Sans Fallback extension interface
+               ( http://wenq.org/index.cgi?Fontopia(cn) ),
+               copyright � 2008-2009 mozbug and Qianqian Fang
+    License  : This font is licensed under Apache2.0 or GPLv3
+               with font embedding exceptions (see Appendix B).
+               Read LICENSE_Apache2.txt and LICENSE_GPLv3.txt for details
+
+----------------------------------------------------------
+
+Table of Content
+
+ I.    About this font
+ II.   Development History
+ III.  Credits
+ IV.   Language Coverage
+ V.    About "WenQuanYi Project"
+ VI.   Links
+ VII.  Appendix
+
+----------------------------------------------------------
+
+
+ I. About this font
+
+WenQuanYi Micro Hei font family is a Sans-Serif style (also known as Hei,
+Gothic or Dotum among the Chinese/Japanese/Korean users) high quality
+CJK outline font. It was derived from "Droid Sans Fallback", "Droid
+Sans" and "Droid Sans Mono" released by Google Corp. This font package
+contains two faces, "Micro Hei" and "Micro Hei Mono", in form of a
+True-Type Collection (ttc) file. All the unified CJK Han glyphs, i.e.
+GBK Hanzi, in the range of U+4E00-U+9FC3 defined in Unicode Standard 5.1
+are covered, with additional support to many other international
+languages such as Latin, Extended Latin, Hanguls and Kanas. The font
+file is extremely compact (~5M) compared with most known CJK fonts.
+As a result, it can be used for hand-held devices or embedded systems, or
+used on PC with a significantly small memory footprint. Because both
+font faces carry hinting and kerning instructions for Latin glyphs,
+they are the excellent choices for desktop fonts.
+
+
+ II. Development History
+
+The original Droid Sans Fallback font contain 16,000 Unified Han glyphs,
+and was officially released by Google under Apache2 license on Dec. 9,
+2008 [2]. With a Javascript-based web interface, Fontopia(TM) [1], developed
+by mozbug and Qianqian Fang, the WenQuanYi contributors had completed
+over 10,000 new glyphs by combining the spline contours from the existing
+Droid Han glyphs. By the end of 2008, project phase-1 had almost
+completed, and phase-2 for CJK Extension A (U+3400-U+4DB5) was brought
+online on Dec. 29, 2009. A review panel was formed to reinforce the
+quality of all submitted glyphs [3]. In Jan. 2009, the reviewers
+had redone over 2000 Hanzi and completed all the missing characters.
+The nightly-build font has become online since Jan. 16. As of Feb. 2009, there
+has been over 5500 CJK Extension A Han glyphs completed, which led this
+font toward a complete GB18030 coverage.
+
+In this font, we incorporated the high quality Latin glyphs from "Droid Sans"
+and "Droid Sans Mono", which contain not only a better coverage but also
+the additional hinting and kerning information. The EM of MicroHei
+and MicroHeiMono fonts were unified to 2048 to retain all the advanced
+typesetting features.
+
+
+ III. Credits
+
+We cordially thank Google(TM) for generously releasing Droid fonts to
+public under an open-source license. Google purchased the font from
+Ascenders Corp. (which was originally designed by a Chinese company).
+
+The project for extending the Droid fonts is based on the web-based
+glyph-composing applet [1], created by mozbug and Qianqian Fang
+jointly. They are constantly improving this application targeting at
+a web-based collaborative font development environment.
+
+Over a thousand anonymous contributors have participated the project;
+they submitted over 10,000 new Hanzi glyphs and many modifications.
+The full update history of the glyphs can be found at [4].
+
+The key members of the review panel, i.e. lsz, FangQ, kmc, Xhacker,
+philacorns, and an "anonymous" (as requested) contributor, had
+spent significant amount of efforts to redesign nearly half of the
+submitted glyphs. We appreciate the incredible effort from this team
+to make this font available. The detailed review credit can be found
+at [3]
+
+
+ IV.    Language Coverage
+
+The following table is based on the locale data provided by fontconfig
+(generated by langcover.pl from Dejavu Project
+http://dejavu.sourceforge.net/wiki/index.php/Font_utilities).
+  ----------------------------------------------------------------
+    Locale                                           MicroHei
+  ----------------------------------------------------------------
+  aa     Afar                                     100% (62/62)
+  ab     Abkhazia                                 100% (90/90)
+  af     Afrikaans                                100% (69/69)
+  am     Amharic                                       (0/264)
+  ar     Arabic                                        (0/125)
+  as                                                   (0/89)
+  ast    Asturian                                 100% (72/72)
+  ava    Avaric                                   100% (67/67)
+  ay     Aymara                                   100% (60/60)
+  az     Azerbaijani                               98% (146/148)
+  az-ir  Azerbaijani in Iran                           (0/130)
+  ba     Bashkir                                  100% (82/82)
+  bam    Bambara                                   90% (54/60)
+  be     Byelorussian                             100% (68/68)
+  bg     Bulgarian                                100% (60/60)
+  bh     Bihari (Devanagari script)                    (0/68)
+  bho    Bhojpuri (Devanagari script)                  (0/68)
+  bi     Bislama                                  100% (58/58)
+  bin    Edo or Bini                              100% (78/78)
+  bn     Bengali                                       (0/89)
+  bo     Tibetan                                       (0/95)
+  br     Breton                                   100% (64/64)
+  bs     Bosnian                                  100% (62/62)
+  bua    Buriat (Buryat)                          100% (70/70)
+  ca     Catalan                                  100% (74/74)
+  ce     Chechen                                  100% (67/67)
+  ch     Chamorro                                 100% (58/58)
+  chm    Mari (Lower Cheremis / Upper Cheremis)   100% (76/76)
+  chr    Cherokee                                      (0/85)
+  co     Corsican                                 100% (85/85)
+  cs     Czech                                    100% (82/82)
+  cu     Old Church Slavonic                      100% (103/103)
+  cv     Chuvash                                  100% (74/74)
+  cy     Welsh                                    100% (78/78)
+  da     Danish                                   100% (70/70)
+  de     German                                   100% (60/60)
+  dz     Dzongkha                                      (0/95)
+  el     Greek                                    100% (70/70)
+  en     English                                  100% (73/73)
+  eo     Esperanto                                100% (64/64)
+  es     Spanish                                  100% (67/67)
+  et     Estonian                                 100% (64/64)
+  eu     Basque                                   100% (56/56)
+  fa     Persian                                       (0/129)
+  fi     Finnish                                  100% (63/63)
+  fj     Fijian                                   100% (52/52)
+  fo     Faroese                                  100% (68/68)
+  fr     French                                   100% (85/85)
+  ful    Fulah (Fula)                              87% (54/62)
+  fur    Friulian                                 100% (66/66)
+  fy     Frisian                                  100% (75/75)
+  ga     Irish                                     82% (66/80)
+  gd     Scots Gaelic                             100% (70/70)
+  gez    Ethiopic (Geez)                               (0/218)
+  gl     Galician                                 100% (66/66)
+  gn     Guarani                                  100% (70/70)
+  gu     Gujarati                                      (0/78)
+  gv     Manx Gaelic                              100% (54/54)
+  ha     Hausa                                     86% (52/60)
+  haw    Hawaiian                                  98% (62/63)
+  he     Hebrew                                        (0/27)
+  hi     Hindi (Devanagari script)                     (0/68)
+  ho     Hiri Motu                                100% (52/52)
+  hr     Croatian                                 100% (62/62)
+  hu     Hungarian                                100% (70/70)
+  hy     Armenian                                      (0/77)
+  ia     Interlingua                              100% (52/52)
+  ibo    Igbo                                     100% (58/58)
+  id     Indonesian                               100% (54/54)
+  ie     Interlingue                              100% (52/52)
+  ik     Inupiaq (Inupiak, Eskimo)                100% (68/68)
+  io     Ido                                      100% (52/52)
+  is     Icelandic                                100% (70/70)
+  it     Italian                                  100% (73/73)
+  iu     Inuktitut                                     (0/161)
+  ja     Japanese                                  99% (6526/6538)
+  ka     Georgian                                      (0/33)
+  kaa    Kara-Kalpak (Karakalpak)                 100% (78/78)
+  ki     Kikuyu                                   100% (56/56)
+  kk     Kazakh                                   100% (77/77)
+  kl     Greenlandic                              100% (81/81)
+  km     Khmer                                         (0/70)
+  kn     Kannada                                       (0/80)
+  ko     Korean                                   100% (2443/2443)
+  kok    Kokani (Devanagari script)                    (0/68)
+  ks     Kashmiri (Devanagari script)                  (0/68)
+  ku     Kurdish                                  100% (64/64)
+  ku-ir  Kurdish in Iran                               (0/32)
+  kum    Kumyk                                    100% (66/66)
+  kv     Komi (Komi-Permyak/Komi-Siryan)          100% (70/70)
+  kw     Cornish                                   96% (62/64)
+  ky     Kirgiz                                   100% (70/70)
+  la     Latin                                    100% (68/68)
+  lb     Luxembourgish (Letzeburgesch)            100% (75/75)
+  lez    Lezghian (Lezgian)                       100% (67/67)
+  ln     Lingala                                   92% (75/81)
+  lo     Lao                                           (0/65)
+  lt     Lithuanian                               100% (70/70)
+  lv     Latvian                                  100% (78/78)
+  mg     Malagasy                                 100% (56/56)
+  mh     Marshallese                              100% (62/62)
+  mi     Maori                                     96% (62/64)
+  mk     Macedonian                               100% (42/42)
+  ml     Malayalam                                     (0/78)
+  mn     Mongolian                                     (0/130)
+  mo     Moldavian                                 98% (126/128)
+  mr     Marathi (Devanagari script)                   (0/68)
+  mt     Maltese                                  100% (72/72)
+  my     Burmese (Myanmar)                             (0/48)
+  nb     Norwegian Bokmal                         100% (70/70)
+  nds    Low Saxon                                100% (59/59)
+  ne     Nepali (Devanagari script)                    (0/68)
+  nl     Dutch                                    100% (83/83)
+  nn     Norwegian Nynorsk                        100% (76/76)
+  no     Norwegian (Bokmal)                       100% (70/70)
+  ny     Chichewa                                 100% (54/54)
+  oc     Occitan                                  100% (70/70)
+  om     Oromo or Galla                           100% (52/52)
+  or     Oriya                                         (0/79)
+  os     Ossetic                                  100% (66/66)
+  pa     Punjabi (Gurumukhi script)                    (0/63)
+  pl     Polish                                   100% (70/70)
+  ps-af  Pashto in Afghanistan                         (0/49)
+  ps-pk  Pashto in Pakistan                            (0/49)
+  pt     Portuguese                               100% (83/83)
+  rm     Rhaeto-Romance (Romansch)                100% (66/66)
+  ro     Romanian                                  96% (60/62)
+  ru     Russian                                  100% (66/66)
+  sa     Sanskrit (Devanagari script)                  (0/68)
+  sah    Yakut                                    100% (76/76)
+  sco    Scots                                     92% (52/56)
+  se     North Sami                               100% (66/66)
+  sel    Selkup (Ostyak-Samoyed)                  100% (66/66)
+  sh     Serbo-Croatian                           100% (76/76)
+  si     Sinhala (Sinhalese)                           (0/77)
+  sk     Slovak                                   100% (86/86)
+  sl     Slovenian                                100% (62/62)
+  sm     Samoan                                    98% (52/53)
+  sma    South Sami                               100% (60/60)
+  smj    Lule Sami                                100% (60/60)
+  smn    Inari Sami                               100% (68/68)
+  sms    Skolt Sami                                87% (70/80)
+  so     Somali                                   100% (52/52)
+  sq     Albanian                                 100% (56/56)
+  sr     Serbian                                  100% (76/76)
+  sv     Swedish                                  100% (68/68)
+  sw     Swahili                                  100% (52/52)
+  syr    Syriac                                        (0/45)
+  ta     Tamil                                         (0/48)
+  te     Telugu                                        (0/80)
+  tg     Tajik                                    100% (78/78)
+  th     Thai                                       1% (1/87)
+  ti-er  Eritrean Tigrinya                             (0/256)
+  ti-et  Ethiopian Tigrinya                            (0/282)
+  tig    Tigre                                         (0/221)
+  tk     Turkmen                                  100% (74/74)
+  tl     Tagalog                                       (0/19)
+  tn     Tswana                                   100% (56/56)
+  to     Tonga                                     98% (52/53)
+  tr     Turkish                                  100% (70/70)
+  ts     Tsonga                                   100% (52/52)
+  tt     Tatar                                    100% (76/76)
+  tw     Twi                                       91% (67/73)
+  tyv    Tuvinian                                 100% (70/70)
+  ug     Uighur                                        (0/125)
+  uk     Ukrainian                                100% (72/72)
+  ur     Urdu                                          (0/145)
+  uz     Uzbek                                    100% (68/68)
+  ven    Venda                                     83% (52/62)
+  vi     Vietnamese                                98% (191/194)
+  vo     Volapuk                                  100% (54/54)
+  vot    Votic                                    100% (62/62)
+  wa     Walloon                                  100% (70/70)
+  wen    Sorbian languages (lower and upper)      100% (76/76)
+  wo     Wolof                                    100% (66/66)
+  xh     Xhosa                                    100% (52/52)
+  yap    Yapese                                   100% (58/58)
+  yi     Yiddish                                       (0/27)
+  yo     Yoruba                                    91% (109/119)
+  zh-936                                           99% (21873/21920)
+  zh-cn  Chinese (simplified)                      99% (6754/6765)
+  zh-hk  Chinese Hong Kong Supplementary Character Set  99% (2212/2213)
+  zh-mo  Chinese in Macau                          99% (2212/2213)
+  zh-sg  Chinese in Singapore                      99% (6754/6765)
+  zh-tw  Chinese (traditional)                     99% (13051/13063)
+  zu     Zulu                                     100% (52/52)
+  ----------------------------------------------------------------
+
+ V.    About "WenQuanYi Project"
+
+The "Wen Quan Yi" Project [5] was founded by Qianqian Fang [6] in
+Oct. 2004. The goal of this project is to create a web-based
+collaborative environment for open-source type-face development.
+The initial focus of the project is to create high quality bitmap
+character glyphs and outline fonts for all 70,000+ CJK characters
+currently encoded by the Unicode Consortium. Some of the fonts
+released by this project have been widely used as the default
+Chinese desktop fonts by main-stream GNU/Linux distributions.
+
+The Wen Quan Yi Project uses wiki [5] as the primary development
+tool for glyph creation, documentation and coordinations. Wen Quan Yi
+wiki also supports glyph version control and nightly build.
+
+
+ VI.    Links
+
+[1] http://wenq.org/index.cgi?Fontopia(cn)
+[2] http://android.git.kernel.org/?p=platform/frameworks/base.git;a=commit;h=1a2
+d9dbe9c6f54c5e0dc26386dc01df1d18073ad
+[3] http://wenq.org/dev/index.cgi?BigBang_TASK
+[4] http://wenq.org/WQYHistory.html.gz
+[5] http://wenq.org/en/
+[6] http://nmr.mgh.harvard.edu/~fangq/
+
+
+ VII. Appendix
+
+Appendix A.
+
+Copyright disclaimer for UmeFont
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+3. Neither the name of the Wada Laboratory, the University of Tokyo nor
+   the names of its contributors may be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY WADA LABORATORY, THE UNIVERSITY OF TOKYO AND
+CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
+NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE LABORATORY OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Appendix B.
+
+GPL with font embedding exception:
+
+http://www.gnu.org/licenses/old-licenses/gpl-2.0-faq.html#FontException
+
+As a special exception, if you create a document which uses this
+font, and embed this font or unaltered portions of this font into
+the document, this font does not by itself cause the resulting
+document to be covered by the GNU General Public License. This
+exception does not however invalidate any other reasons why the
+document might be covered by the GNU General Public License. If you
+modify this font, you may extend this exception to your version of
+the font, but you are not obligated to do so. If you do not wish to
+do so, delete this exception statement from your version.
+
+
+
diff --git a/songmanagement/game/fonts/wqy-microhei/wqy-microhei.ttc b/songmanagement/game/fonts/wqy-microhei/wqy-microhei.ttc
new file mode 100644
index 00000000..2c9bc2d4
Binary files /dev/null and b/songmanagement/game/fonts/wqy-microhei/wqy-microhei.ttc differ
diff --git a/songmanagement/game/languages/Catalan.ini b/songmanagement/game/languages/Catalan.ini
new file mode 100644
index 00000000..a9164c0c
--- /dev/null
+++ b/songmanagement/game/languages/Catalan.ini
@@ -0,0 +1,443 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Carregant...
+
+SING_CHOOSE_MODE=Triar mode
+SING_SING=cantar
+SING_SING_DESC=joc ràpid: cantar un solo o un duet
+
+SING_MULTI=festa
+SING_MULTI_DESC=cantar en mode festa
+
+SING_TOOLS=eines
+
+SING_STATS=estadístiques
+SING_STATS_DESC=veure estadístiques
+
+SING_EDITOR=editor
+SING_EDITOR_DESC=crea les teves propies cançons
+
+SING_GAME_OPTIONS=opcions de joc
+SING_GAME_OPTIONS_DESC=canviar preferències de joc
+
+SING_EXIT=sortir
+SING_EXIT_DESC=sortir del joc
+
+SING_OPTIONS=opcions
+SING_OPTIONS_DESC=canviar preferències
+SING_OPTIONS_WHEREAMI=Opcions
+
+SING_OPTIONS_GAME=joc
+SING_OPTIONS_GRAPHICS=gràfics
+SING_OPTIONS_SOUND=so
+SING_OPTIONS_LYRICS=lletres
+SING_OPTIONS_THEMES=aparença
+SING_OPTIONS_RECORD=gravar
+SING_OPTIONS_ADVANCED=avançat
+SING_OPTIONS_EXIT=enrere
+
+SING_OPTIONS_GAME_WHEREAMI=Opcions de joc
+SING_OPTIONS_GAME_DESC=opcions generals del joc
+SING_OPTIONS_GAME_PLAYERS=Jugadors
+SING_OPTIONS_GAME_DIFFICULTY=Dificultat
+SING_OPTIONS_GAME_LANGUAGE=Idioma
+SING_OPTIONS_GAME_TABS=Pestanyes
+SING_OPTIONS_GAME_SORTING=Ordenació
+SING_OPTIONS_GAME_DEBUG=Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Opcions Gràfiques
+SING_OPTIONS_GRAPHICS_DESC=configurar gràfics
+SING_OPTIONS_GRAPHICS_RESOLUTION=Resolucị
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Pantalla complerta
+SING_OPTIONS_GRAPHICS_DEPTH=Profunditat
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualització
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscil·loscopi
+SING_OPTIONS_GRAPHICS_LINEBONUS=Bonus de línia
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Mida pel·lícula
+
+SING_OPTIONS_SOUND_WHEREAMI=Opcions de so
+SING_OPTIONS_SOUND_DESC=configurar so
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Reproducció del micro
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Música de fons
+SING_OPTIONS_SOUND_MIC_BOOST=Ampli Micro
+SING_OPTIONS_SOUND_CLICK_ASSIST=Assistència Click
+SING_OPTIONS_SOUND_BEAT_CLICK=Clic de ritme
+SING_OPTIONS_SOUND_THRESHOLD=Llindar
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Mode dos jugadors
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Volum previsualitzar
+SING_OPTIONS_SOUND_PREVIEWFADING=Fos previsualitzar
+
+SING_OPTIONS_LYRICS_WHEREAMI=Opcions Lletra
+SING_OPTIONS_LYRICS_DESC=configuració de lletres
+SING_OPTIONS_LYRICS_FONT=Font
+SING_OPTIONS_LYRICS_EFFECT=Efecte
+SING_OPTIONS_LYRICS_SOLMIZATION=Solfeig
+SING_OPTIONS_LYRICS_NOTELINES=Pentagrama
+
+SING_OPTIONS_THEMES_WHEREAMI=Options d'Aparença
+SING_OPTIONS_THEMES_DESC=Configuració d'aparença
+SING_OPTIONS_THEMES_THEME=Aparença
+SING_OPTIONS_THEMES_SKIN=Pell
+SING_OPTIONS_THEMES_COLOR=Color
+
+SING_OPTIONS_RECORD_WHEREAMI=Opcions de micro
+SING_OPTIONS_RECORD_DESC=configuració del micro
+SING_OPTIONS_RECORD_CARD=Tarjeta de so
+SING_OPTIONS_RECORD_INPUT=Entrada
+SING_OPTIONS_RECORD_CHANNEL=Canal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Opcions Avançades
+SING_OPTIONS_ADVANCED_DESC=opcions avançades
+SING_OPTIONS_ADVANCED_EFFECTSING=Efectes de cantar
+SING_OPTIONS_ADVANCED_SCREENFADE=Fos de pantalla
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animació càrrega
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Prequnta abans d'esborrar
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus de línia
+SING_OPTIONS_ADVANCED_ONSONGCLICK=després de triar cançó
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Menú Automàtic de festa
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=crea cançons
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importar text de fitxer midi
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=tornar
+SING_EDIT_BUTTON_CONVERT=Importar
+SING_EDIT_BUTTON_EXIT=enrere
+
+SING_EDIT_NAVIGATE=navegar
+SING_EDIT_SELECT=triar
+SING_EDIT_EXIT=enrere
+
+SING_LEGEND_SELECT=seleccionar
+SING_LEGEND_NAVIGATE=navegar
+SING_LEGEND_CONTINUE=continuar
+SING_LEGEND_ESC=enrere
+
+SING_PLAYER_DESC=entrar nom de jugador/s
+SING_PLAYER_WHEREAMI=Nom dels jugadors
+SING_PLAYER_ENTER_NAME=introduir nom
+
+SING_DIFFICULTY_DESC=triar dificultat
+SING_DIFFICULTY_WHEREAMI=Dificultat
+SING_DIFFICULTY_CONTINUE=a selecció de cançó
+SING_EASY=Fàcil
+SING_MEDIUM=Mitjà
+SING_HARD=Difícil
+
+SING_SONG_SELECTION_DESC=triar cançó
+SING_SONG_SELECTION_WHEREAMI=Selecció de cançons
+SING_SONG_SELECTION_GOTO=Anar a ..
+SING_SONG_SELECTION=selecció de cançons
+SING_SONG_SELECTION_MENU=menú
+SING_SONG_SELECTION_PLAYLIST=llista
+SING_SONGS_IN_CAT=Cançons
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=TEMPS
+SING_TOTAL=total
+SING_MODE=cantar sol
+SING_NOTES=notes
+SING_GOLDEN_NOTES=notes daurades
+SING_PHRASE_BONUS=bonus de línia
+
+SING_MENU=Menú principal
+
+SONG_SCORE=puntuació cançó
+SONG_SCORE_WHEREAMI=Puntuació
+
+SING_SCORE_TONE_DEAF=Sense oïda
+SING_SCORE_AMATEUR=Novell
+SING_SCORE_WANNABE=Aficionat
+SING_SCORE_HOPEFUL=Esperançador
+SING_SCORE_RISING_STAR=Futura estrella
+SING_SCORE_LEAD_SINGER=Bon cantant
+SING_SCORE_SUPERSTAR=Estrella
+SING_SCORE_ULTRASTAR=Super estrella
+
+SING_TOP_5_CHARTS=millors 5 jugadors
+SING_TOP_5_CHARTS_WHEREAMI=millors 5
+SING_TOP_5_CHARTS_CONTINUE=a selecció de cançó
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=perfecte!
+POPUP_AWESOME=genial!
+POPUP_GREAT=molt bo!
+POPUP_GOOD=esta bé!
+POPUP_NOTBAD=pots millorar!
+POPUP_BAD=malament!
+POPUP_POOR=pobre!
+POPUP_AWFUL=boo fora!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= i
+
+SONG_MENU_NAME_MAIN=menú de cançons
+SONG_MENU_PLAY=Cantar
+SONG_MENU_CHANGEPLAYERS=Canviar jugadors
+SONG_MENU_EDIT=Editar
+SONG_MENU_MODI=Cantar un Modi
+SONG_MENU_CANCEL=Cancel·lar
+
+SONG_MENU_NAME_PLAYLIST=Menú de cançons
+SONG_MENU_PLAYLIST_ADD=Afegir Cançó
+SONG_MENU_PLAYLIST_DEL=Esborrar Cançó
+
+SONG_MENU_NAME_PLAYLIST_ADD=Afegir Song
+SONG_MENU_PLAYLIST_ADD_NEW=a nova llista
+SONG_MENU_PLAYLIST_ADD_EXISTING=a llista existent
+SONG_MENU_PLAYLIST_NOEXISTING=No hi ha llistes
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nova llista
+SONG_MENU_PLAYLIST_NEW_CREATE=Crear
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Sense nom
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Segur que vols esborrar?
+SONG_MENU_YES=Si
+SONG_MENU_NO=No
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Obrir llista
+SONG_MENU_PLAYLIST_LOAD=obrir
+SONG_MENU_PLAYLIST_DELCURRENT=esborrar llista
+
+SONG_MENU_NAME_PLAYLIST_DEL=Esborrar llista?
+
+SONG_MENU_NAME_PARTY_MAIN=Menú festa
+SONG_MENU_JOKER=Comodí
+
+SONG_MENU_NAME_PARTY_JOKER=utilitzar comodí
+
+SONG_JUMPTO_DESC=buscar cançó
+SONG_JUMPTO_TYPE_DESC=Buscar:
+SONG_JUMPTO_TYPE1=Tot
+SONG_JUMPTO_TYPE2=Títol
+SONG_JUMPTO_TYPE3=Artista
+SONG_JUMPTO_SONGSFOUND=%d Cançons trobades
+SONG_JUMPTO_NOSONGSFOUND=No s'han trobat cançons
+SONG_JUMPTO_HELP=Introduir text a cercar
+SONG_JUMPTO_CATTEXT=Cercant: %s
+
+PARTY_MODE=mode festa
+PARTY_DIFFICULTY=Dificultat
+PARTY_PLAYLIST=Mode llista
+PARTY_PLAYLIST_ALL=Tot
+PARTY_PLAYLIST_CATEGORY=Directori
+PARTY_PLAYLIST_PLAYLIST=llista
+PARTY_TEAMS=Equips
+PARTY_TEAMS_PLAYER1=Player Team1
+PARTY_TEAMS_PLAYER2=Player Team2
+PARTY_TEAMS_PLAYER3=Player Team3
+
+PARTY_LEGEND_CONTINUE=continuar
+
+PARTY_OPTIONS_DESC=opcions mode festa
+PARTY_OPTIONS_WHEREAMI=Opcions Festa
+
+PARTY_PLAYER_DESC=introduïr noms de jugadors i equips
+PARTY_PLAYER_WHEREAMI=Noms
+PARTY_PLAYER_ENTER_NAME=introduïr noms
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=iniciar festa
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=següent jugador al micro
+PARTY_ROUND_WHEREAMI=Següent Ronda
+PARTY_ROUND_LEGEND_CONTINUE=iniciar ronda
+
+PARTY_SONG_WHEREAMI=Selecció de cançó mode festa
+PARTY_SONG_LEGEND_CONTINUE=cantar
+PARTY_SONG_MENU=menú festa
+
+PARTY_SCORE_DESC=puntuació de l'última ronda
+PARTY_SCORE_WHEREAMI=Punts mode festa
+
+PARTY_WIN_DESC=guanyador de la festa
+PARTY_WIN_WHEREAMI=Guanyador
+PARTY_WIN_LEGEND_CONTINUE=tornar al menú principal
+
+PARTY_ROUND=Ronda
+PARTY_ROUND_WINNER=Guanyador
+PARTY_NOTPLAYEDYET=no s'ha jugat encara
+PARTY_NOBODY=ningú
+NEXT_ROUND=Següent ronda:
+
+PARTY_DISMISSED=Abandona!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=guanya!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Aguantar la línia
+MODE_HOLDTHELINE_DESC=No baixis de la fletxa a la barra de qualitat
+
+MODE_5000POINTS_NAME=Fins a 5000
+MODE_5000POINTS_DESC=El primer a arribar a 5000 punts guanya
+
+MODE_DUEL_NAME=Duel
+MODE_DUEL_DESC=Cantar un duela fins a 10000 punts
+
+;TODO: MODE_TEAMDUEL_NAME=Team Duell
+;TODO: MODE_TEAMDUEL_DESC=Pass The Mic!
+
+MODE_BLIND_NAME=Mode cec
+MODE_BLIND_DESC=Duel sense veure les notes
+
+STAT_MAIN=Estadístiques
+STAT_MAIN_DESC=General
+STAT_MAIN_WHEREAMI=Estadístiques
+
+STAT_OVERVIEW_INTRO=%0:s Estadístiques\nÚltima reinicialització %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Cançons(%3:d amb Video), de les que %1:d ya han sonat i %2:d encara no s'han jugat mai.\n La cançó més popular és %5:s de %4:s.
+STAT_OVERVIEW_PLAYER=Des de l'última reinicialització hi han hagut %0:d jugadors diferents.\n El millor jugador és %1:s amb una mitjana de %2:d Punts.\n %3:s ha fet la màxima puntuació amb %4:d Punts.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Estadístques
+STAT_DETAIL_WHEREAMI=Estadístiques
+
+STAT_NEXT=Següent pàgina
+STAT_PREV=Pàgina anterior
+STAT_REVERSE=Ordre invers
+STAT_PAGE=%0:d de %1:d Pàgines\n (%2:d de %3:d Entrades)
+
+STAT_DESC_SCORES=Màximes puntuacions
+STAT_DESC_SCORES_REVERSED=Mínimes puntuacions
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Millors cantants
+STAT_DESC_SINGERS_REVERSED=Pitjors cantants
+STAT_FORMAT_SINGERS=%0:s \n Puntuació mitjana: %1:d
+
+STAT_DESC_SONGS=Cançons més populars
+STAT_DESC_SONGS_REVERSED=Cançons menys populars
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx cantades
+
+STAT_DESC_BANDS=Grups més populars
+STAT_DESC_BANDS_REVERSED=Grups menys populars
+STAT_FORMAT_BANDS=%0:s \n %1:dx Cantades
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Error
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Qüestió
+MSG_QUIT_USDX=Realment vols sortir d'UltraStar?
+MSG_END_PARTY=Realment vols sortir del mode festa?
+
+ERROR_NO_SONGS=No hi ha cançons
+ERROR_NO_PLUGINS=No hi ha Plugins
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=No es poden carregar les cançons
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=No es pot carregar: Fitxer no trobat
+ERROR_CORRUPT_SONG_NO_NOTES=No es pot carregar: No s'han trobat notes
+ERROR_CORRUPT_SONG_NO_BREAKS=No es pot carregar: No s'han trobat línies
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=No es pot carregar: Error llegint línia %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Quantes vegades cantada
+;UNUSED: PARTY_ROUNDS=Rondes
diff --git a/songmanagement/game/languages/Chinese.ini b/songmanagement/game/languages/Chinese.ini
new file mode 100644
index 00000000..549947d5
--- /dev/null
+++ b/songmanagement/game/languages/Chinese.ini
@@ -0,0 +1,443 @@
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+OPTION_VALUE_CZECH=Czech
+OPTION_VALUE_DANISH=Danish
+OPTION_VALUE_DUTCH=Dutch
+OPTION_VALUE_ENGLISH=English
+OPTION_VALUE_EUSKARA=Euskara
+OPTION_VALUE_FINNISH=Finnish
+OPTION_VALUE_FRENCH=French
+OPTION_VALUE_GERMAN=German
+OPTION_VALUE_GREEK=Greek
+OPTION_VALUE_HUNGARIAN=Hungarian
+OPTION_VALUE_ICELANDIC=Icelandic
+OPTION_VALUE_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_NORWEGIAN=Norwegian
+OPTION_VALUE_POLISH=Polish
+OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+OPTION_VALUE_SERBIAN=Serbian
+OPTION_VALUE_SLOVAK=Slovak
+OPTION_VALUE_SLOVENIAN=Slovenian
+OPTION_VALUE_SPANISH=Spanish
+OPTION_VALUE_SWEDISH=Swedish
+
+OPTION_VALUE_EASY=简单
+OPTION_VALUE_MEDIUM=中等
+OPTION_VALUE_HARD=困难
+
+OPTION_VALUE_ON=开
+OPTION_VALUE_OFF=关
+
+OPTION_VALUE_EDITION=版本
+OPTION_VALUE_GENRE=流派
+OPTION_VALUE_LANGUAGE=语言
+OPTION_VALUE_FOLDER=文件夹
+OPTION_VALUE_TITLE=标题
+OPTION_VALUE_ARTIST=艺术家
+OPTION_VALUE_TITLE2=标题2
+OPTION_VALUE_ARTIST2=艺术家2
+
+OPTION_VALUE_WHENNOVIDEO=无视频时
+
+OPTION_VALUE_SMALL=小
+OPTION_VALUE_BIG=大
+
+OPTION_VALUE_HALF=一半
+OPTION_VALUE_FULL_VID=全屏 (视频)
+OPTION_VALUE_FULL_VID_BG=全屏 (背景加视频)
+
+OPTION_VALUE_AUTO=自动
+OPTION_VALUE_SEC=秒
+OPTION_VALUE_SECS=秒
+
+OPTION_VALUE_PLAIN=空白
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=简单
+OPTION_VALUE_ZOOM=缩放
+OPTION_VALUE_SLIDE=滑动
+OPTION_VALUE_BALL=滚动
+OPTION_VALUE_SHIFT=移位
+
+OPTION_VALUE_EURO=欧洲
+OPTION_VALUE_JAPAN=日本
+OPTION_VALUE_AMERICAN=美国
+
+OPTION_VALUE_BLUE=蓝
+OPTION_VALUE_GREEN=绿
+OPTION_VALUE_PINK=粉
+OPTION_VALUE_RED=红
+OPTION_VALUE_VIOLET=紫
+OPTION_VALUE_ORANGE=橙
+OPTION_VALUE_YELLOW=黄
+OPTION_VALUE_BROWN=棕
+OPTION_VALUE_BLACK=黑
+
+OPTION_VALUE_SING=K歌
+OPTION_VALUE_SELECT_PLAYERS=选择玩家
+OPTION_VALUE_OPEN_MENU=打开菜单
+
+OPTION_VALUE_HARDWARE_CURSOR=系统指针
+OPTION_VALUE_SOFTWARE_CURSOR=自带指针
+
+SING_LOADING=载入……
+
+SING_CHOOSE_MODE=选择模式
+SING_SING=唱歌
+SING_SING_DESC=快速游戏:独唱或对唱
+
+SING_MULTI=派对
+SING_MULTI_DESC=派对模式唱歌
+
+SING_TOOLS=工具
+
+SING_STATS=统计
+SING_STATS_DESC=查看统计资料
+
+SING_EDITOR=编辑器
+SING_EDITOR_DESC=制作自己的歌曲
+
+SING_GAME_OPTIONS=游戏选项
+SING_GAME_OPTIONS_DESC=更改游戏设置
+
+SING_EXIT=退出
+SING_EXIT_DESC=退出游戏
+
+SING_OPTIONS=选项
+SING_OPTIONS_DESC=更改设置
+SING_OPTIONS_WHEREAMI=选项
+
+SING_OPTIONS_GAME=游戏
+SING_OPTIONS_GRAPHICS=画面
+SING_OPTIONS_SOUND=声音
+SING_OPTIONS_LYRICS=歌词
+SING_OPTIONS_THEMES=主题
+SING_OPTIONS_RECORD=录音
+SING_OPTIONS_ADVANCED=高级
+SING_OPTIONS_EXIT=返回
+
+SING_OPTIONS_GAME_WHEREAMI=游戏选项
+SING_OPTIONS_GAME_DESC=通用游戏设置
+SING_OPTIONS_GAME_PLAYERS=玩家
+SING_OPTIONS_GAME_DIFFICULTY=难度
+SING_OPTIONS_GAME_LANGUAGE=语言
+SING_OPTIONS_GAME_TABS=标签
+SING_OPTIONS_GAME_SORTING=排列
+SING_OPTIONS_GAME_DEBUG=调试
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=画面选项
+SING_OPTIONS_GRAPHICS_DESC=画面设置
+SING_OPTIONS_GRAPHICS_RESOLUTION=分辨率
+SING_OPTIONS_GRAPHICS_FULLSCREEN=全屏
+SING_OPTIONS_GRAPHICS_DEPTH=色深
+SING_OPTIONS_GRAPHICS_VISUALIZER=可视化
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=示波器
+SING_OPTIONS_GRAPHICS_LINEBONUS=加分线
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=影片大小
+
+SING_OPTIONS_SOUND_WHEREAMI=声音选项
+SING_OPTIONS_SOUND_DESC=声音设置
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=麦克风回放
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=背景音乐
+SING_OPTIONS_SOUND_MIC_BOOST=麦克风增强
+SING_OPTIONS_SOUND_CLICK_ASSIST=“卡嗒”助手
+SING_OPTIONS_SOUND_BEAT_CLICK=节拍“卡嗒”
+SING_OPTIONS_SOUND_THRESHOLD=阈值
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=双人模式
+SING_OPTIONS_SOUND_PREVIEWVOLUME=预览音量
+SING_OPTIONS_SOUND_PREVIEWFADING=预览渐变
+
+SING_OPTIONS_LYRICS_WHEREAMI=歌词选项
+SING_OPTIONS_LYRICS_DESC=歌词设置
+SING_OPTIONS_LYRICS_FONT=字体
+SING_OPTIONS_LYRICS_EFFECT=效果
+SING_OPTIONS_LYRICS_SOLMIZATION=阶名唱法
+SING_OPTIONS_LYRICS_NOTELINES=五线谱
+
+SING_OPTIONS_THEMES_WHEREAMI=主题选项
+SING_OPTIONS_THEMES_DESC=主题和皮肤设置
+SING_OPTIONS_THEMES_THEME=主题
+SING_OPTIONS_THEMES_SKIN=皮肤
+SING_OPTIONS_THEMES_COLOR=颜色
+
+SING_OPTIONS_RECORD_WHEREAMI=录音选项
+SING_OPTIONS_RECORD_DESC=麦克风设置
+SING_OPTIONS_RECORD_CARD=声卡
+SING_OPTIONS_RECORD_INPUT=输入
+SING_OPTIONS_RECORD_CHANNEL=频道
+
+SING_OPTIONS_ADVANCED_WHEREAMI=高级选项
+SING_OPTIONS_ADVANCED_DESC=高级设置
+SING_OPTIONS_ADVANCED_EFFECTSING=演唱效果
+SING_OPTIONS_ADVANCED_SCREENFADE=画面渐变
+SING_OPTIONS_ADVANCED_LOADANIMATION=载入动画
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=安全问题
+SING_OPTIONS_ADVANCED_LINEBONUS=加分线
+SING_OPTIONS_ADVANCED_ONSONGCLICK=选歌之后
+SING_OPTIONS_ADVANCED_PARTYPOPUP=自动派对菜单
+
+SING_EDIT=编辑器
+SING_EDIT_MENU_DESCRIPTION=制作自己的歌曲
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=从midi文件导入文本
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=返回
+SING_EDIT_BUTTON_CONVERT=导入
+SING_EDIT_BUTTON_EXIT=返回
+
+SING_EDIT_NAVIGATE=导航
+SING_EDIT_SELECT=选择
+SING_EDIT_EXIT=返回
+
+SING_LEGEND_SELECT=选择
+SING_LEGEND_NAVIGATE=导航
+SING_LEGEND_CONTINUE=继续
+SING_LEGEND_ESC=返回
+
+SING_PLAYER_DESC=输入玩家名
+SING_PLAYER_WHEREAMI=玩家名
+SING_PLAYER_ENTER_NAME=输入名字
+
+SING_DIFFICULTY_DESC=选择难度
+SING_DIFFICULTY_WHEREAMI=难度
+SING_DIFFICULTY_CONTINUE=到歌曲选择
+SING_EASY=简单
+SING_MEDIUM=中等
+SING_HARD=困难
+
+SING_SONG_SELECTION_DESC=选择您的歌曲
+SING_SONG_SELECTION_WHEREAMI=歌曲选择
+SING_SONG_SELECTION_GOTO=转到……
+SING_SONG_SELECTION=歌曲选择
+SING_SONG_SELECTION_MENU=菜单
+SING_SONG_SELECTION_PLAYLIST=播放列表
+SING_SONGS_IN_CAT=歌曲
+PLAYLIST_CATTEXT=播放列表: %s
+
+SING_TIME=时间
+SING_TOTAL=全部
+SING_MODE=独唱
+SING_NOTES=音符
+SING_GOLDEN_NOTES=金色音符
+SING_PHRASE_BONUS=加分线
+
+SING_MENU=主菜单
+
+SONG_SCORE=歌曲分数
+SONG_SCORE_WHEREAMI=分数
+
+SING_SCORE_TONE_DEAF=缺乏细胞
+SING_SCORE_AMATEUR=略知一二
+SING_SCORE_WANNABE=有志此道
+SING_SCORE_HOPEFUL=孺子可教
+SING_SCORE_RISING_STAR=歌坛新秀
+SING_SCORE_LEAD_SINGER=一线歌星
+SING_SCORE_SUPERSTAR=超级明星
+SING_SCORE_ULTRASTAR=天王巨星
+
+SING_TOP_5_CHARTS=五佳玩家
+SING_TOP_5_CHARTS_WHEREAMI=五佳玩家
+SING_TOP_5_CHARTS_CONTINUE=到歌曲选择
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=转换难度
+
+POPUP_PERFECT=完美浮现!
+POPUP_AWESOME=牛逼哄哄!
+POPUP_GREAT=值得表扬!
+POPUP_GOOD=表现良好!
+POPUP_NOTBAD=不错还行!
+POPUP_BAD=不咋地!
+POPUP_POOR=好差劲!
+POPUP_AWFUL=真丢人!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= 和
+
+SONG_MENU_NAME_MAIN=歌曲菜单
+SONG_MENU_PLAY=演唱
+SONG_MENU_CHANGEPLAYERS=变更玩家
+SONG_MENU_EDIT=编辑
+SONG_MENU_MODI=修正唱法
+SONG_MENU_CANCEL=取消
+
+SONG_MENU_NAME_PLAYLIST=歌曲菜单
+SONG_MENU_PLAYLIST_ADD=添加歌曲
+SONG_MENU_PLAYLIST_DEL=删除歌曲
+
+SONG_MENU_NAME_PLAYLIST_ADD=添加歌曲
+SONG_MENU_PLAYLIST_ADD_NEW=到新播放列表
+SONG_MENU_PLAYLIST_ADD_EXISTING=到已有播放列表
+SONG_MENU_PLAYLIST_NOEXISTING=无可用播放列表
+
+SONG_MENU_NAME_PLAYLIST_NEW=新播放列表
+SONG_MENU_PLAYLIST_NEW_CREATE=创建
+SONG_MENU_PLAYLIST_NEW_UNNAMED=未命名
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=确定删除?
+SONG_MENU_YES=是
+SONG_MENU_NO=否
+
+SONG_MENU_NAME_PLAYLIST_LOAD=打开播放列表
+SONG_MENU_PLAYLIST_LOAD=打开
+SONG_MENU_PLAYLIST_DELCURRENT=删除当前播放列表
+
+SONG_MENU_NAME_PLAYLIST_DEL=删除播放列表?
+
+SONG_MENU_NAME_PARTY_MAIN=派对菜单
+SONG_MENU_JOKER=王牌
+
+SONG_MENU_NAME_PARTY_JOKER=使用王牌
+
+SONG_JUMPTO_DESC=搜索歌曲
+SONG_JUMPTO_TYPE_DESC=查询方式:
+SONG_JUMPTO_TYPE1=所有
+SONG_JUMPTO_TYPE2=标题
+SONG_JUMPTO_TYPE3=艺术家
+SONG_JUMPTO_SONGSFOUND=%d 找到的歌曲
+SONG_JUMPTO_NOSONGSFOUND=未找到歌曲
+SONG_JUMPTO_HELP=输入要查询内容
+SONG_JUMPTO_CATTEXT=搜索: %s
+
+PARTY_MODE=派对模式
+PARTY_DIFFICULTY=难度
+PARTY_PLAYLIST=列表模式
+PARTY_PLAYLIST_ALL=所有歌曲
+PARTY_PLAYLIST_CATEGORY=文件夹
+PARTY_PLAYLIST_PLAYLIST=播放列表
+PARTY_TEAMS=团队数量
+PARTY_TEAMS_PLAYER1=歌手数量
+PARTY_TEAMS_PLAYER2=歌手数量
+PARTY_TEAMS_PLAYER3=歌手数量
+
+PARTY_LEGEND_CONTINUE=继续
+
+PARTY_OPTIONS_DESC=派对游戏设置
+PARTY_OPTIONS_WHEREAMI=派对选项
+
+PARTY_PLAYER_DESC=输入玩家和团队名称!
+PARTY_PLAYER_WHEREAMI=派对名称
+PARTY_PLAYER_ENTER_NAME=输入名称
+
+
+PARTY_ROUNDS_DESC=选择你想玩的模式
+PARTY_ROUNDS_WHEREAMI=派对回合
+PARTY_ROUNDS_LEGEND_CONTINUE=开始派对游戏
+PARTY_ROUNDCOUNT=回合数量
+PARTY_SELECTMODE1=回合1
+PARTY_SELECTMODE2=回合2
+PARTY_SELECTMODE3=回合3
+PARTY_SELECTMODE4=回合4
+PARTY_SELECTMODE5=回合5
+PARTY_SELECTMODE6=回合6
+PARTY_SELECTMODE7=回合7
+
+PARTY_ROUND_DESC=下位演唱歌手
+PARTY_ROUND_WHEREAMI=派对下一回合
+PARTY_ROUND_LEGEND_CONTINUE=回合开始
+
+PARTY_SONG_WHEREAMI=派对歌曲选择
+PARTY_SONG_LEGEND_CONTINUE=演唱
+PARTY_SONG_MENU=派对菜单
+
+PARTY_SCORE_DESC=最后一回合分数
+PARTY_SCORE_WHEREAMI=派对得分
+
+PARTY_WIN_DESC=派对游戏赢家
+PARTY_WIN_WHEREAMI=派对赢家
+PARTY_WIN_LEGEND_CONTINUE=返回主菜单
+
+PARTY_ROUND=回合
+PARTY_ROUND_WINNER=赢家
+PARTY_NOTPLAYEDYET=尚未游戏
+PARTY_NOBODY=空缺
+NEXT_ROUND=下一回合:
+
+PARTY_DISMISSED=解散!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=胜出!
+
+MODE_RANDOM_NAME=随机模式
+MODE_RANDOM_DESC=将随机选取一种模式
+
+MODE_HOLDTHELINE_NAME=保持分数线
+MODE_HOLDTHELINE_DESC=不要低于评分栏所显示的分数。
+
+MODE_5000POINTS_NAME=5000争夺赛
+MODE_5000POINTS_DESC=首先赢得5000分的玩家胜出。
+
+MODE_DUEL_NAME=挑战赛
+MODE_DUEL_DESC=挑战10000分。
+
+MODE_TEAMDUEL_NAME=团队挑战
+MODE_TEAMDUEL_DESC=麦克风接力!
+
+MODE_BLIND_NAME=盲人模式
+MODE_BLIND_DESC=不看提示挑战。
+
+STAT_MAIN=统计
+STAT_MAIN_DESC=常规
+STAT_MAIN_WHEREAMI=统计
+
+STAT_OVERVIEW_INTRO=%0:s 统计。  \n 最后重置在 %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d 歌曲(%3:d 带视频) \n %1:d 已播放  以及 %2:d 尚未播放。\n 最热门的歌曲是来自%4:s的%5:s
+STAT_OVERVIEW_PLAYER=截至最后一次重置共有 %0:d 位玩家。\n 最佳玩家是 %1:s 。其均分为 %2:d 分。\n %3:s 的 %4:d 分为最高得分。
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=统计
+STAT_DETAIL_WHEREAMI=统计详情
+
+STAT_NEXT=下一页
+STAT_PREV=前一页
+STAT_REVERSE=倒序
+STAT_PAGE= %1:d 页中的第 %0:d 页\n ( %3:d 条目中的 %2:d )
+
+STAT_DESC_SCORES=高分
+STAT_DESC_SCORES_REVERSED=低分
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=最佳歌手
+STAT_DESC_SINGERS_REVERSED=最差歌手
+STAT_FORMAT_SINGERS=%0:s \n 平均分: %1:d
+
+STAT_DESC_SONGS=最热门歌曲
+STAT_DESC_SONGS_REVERSED=最冷门歌曲
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx 唱过
+
+STAT_DESC_BANDS=最热门乐队
+STAT_DESC_BANDS_REVERSED=最冷门乐队
+STAT_FORMAT_BANDS=%0:s \n %1:dx 唱过
+
+SCREENSHOT_SAVED=截图已保存
+SCREENSHOT_FAILED=无法保存截图
+
+INFO_FILE_SAVED=文件已保存
+ERROR_SAVE_FILE_FAILED=无法保存文件
+ERROR_FILE_NOT_FOUND=文件未找到
+
+ENCODING_ERROR_ASK_FOR_UTF8=以当前编码无法保存变更,是否转换为UTF-8?
+EDITOR_ERROR_NO_TRACK_SELECTED=无音轨选中
+
+MSG_ERROR_TITLE=错误
+MSG_INFO_TITLE=信息
+MSG_QUESTION_TITLE=确认
+MSG_QUIT_USDX=确定离开UltraStar?
+MSG_END_PARTY=确定离开派对模式?
+
+ERROR_NO_SONGS=未载入歌曲
+ERROR_NO_PLUGINS=未载入插件
+ERROR_NO_MODES_FOR_CURRENT_SETUP=无适合当前玩家/团队设置的模式
+ERROR_CAN_NOT_START_PARTY=派对游戏初始化出现问题
+ERROR_CORRUPT_SONG=无法载入歌曲。
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=无法载入歌曲:文件未找到
+ERROR_CORRUPT_SONG_NO_NOTES=无法载入歌曲:找不到任何注释
+ERROR_CORRUPT_SONG_NO_BREAKS=无法载入歌曲:找不到任何分秆
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=无法载入歌曲:行 %0:d 解析错误
+ERROR_NO_EDITOR=此特性在Linux/Mac上不可用
+ERROR_PLAYER_DEVICE_ASSIGNMENT=玩家 %d 被指定给多个麦克风,请检查您的录音选项
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=玩家 %d 没有指定麦克风,请检查您的录音选项
+;UNUSED: OPTION_VALUE_CHINESE=中文
+ ;TRANSLATOR: Qiao Xiaohui
diff --git a/songmanagement/game/languages/Croatian.ini b/songmanagement/game/languages/Croatian.ini
new file mode 100644
index 00000000..155b84ff
--- /dev/null
+++ b/songmanagement/game/languages/Croatian.ini
@@ -0,0 +1,446 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Učitavanje...
+
+SING_CHOOSE_MODE=Izaberi način igre
+SING_SING=pjevaj
+SING_SING_DESC=brza igra: pjevaj solo ili duet
+
+SING_MULTI=party
+SING_MULTI_DESC=pjevaj u party mode-u
+
+SING_TOOLS=alati
+
+SING_STATS=statistika
+SING_STATS_DESC=pogledaj statistiku
+
+SING_EDITOR=editor
+SING_EDITOR_DESC=napravi svoje pjesme
+
+SING_GAME_OPTIONS=opcije igre
+SING_GAME_OPTIONS_DESC=promijeni postavke
+
+SING_EXIT=izlaz
+SING_EXIT_DESC=izlaz iz igre
+
+SING_OPTIONS=opcije
+SING_OPTIONS_DESC=promijeni postavke
+SING_OPTIONS_WHEREAMI=Opcije
+
+SING_OPTIONS_GAME=igra
+SING_OPTIONS_GRAPHICS=video
+SING_OPTIONS_SOUND=audio
+SING_OPTIONS_LYRICS=tekstovi
+SING_OPTIONS_THEMES=teme
+SING_OPTIONS_RECORD=snimanje
+SING_OPTIONS_ADVANCED=ostalo
+SING_OPTIONS_EXIT=natrag
+
+SING_OPTIONS_GAME_WHEREAMI=Opcije Igre
+SING_OPTIONS_GAME_DESC=osnovne opcije igre
+SING_OPTIONS_GAME_PLAYERS=Br. igrača
+SING_OPTIONS_GAME_DIFFICULTY=Težina
+SING_OPTIONS_GAME_LANGUAGE=Jezik
+SING_OPTIONS_GAME_TABS=Tabovi
+SING_OPTIONS_GAME_SORTING=Sortiranje
+SING_OPTIONS_GAME_DEBUG=Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Opcije Videa
+SING_OPTIONS_GRAPHICS_DESC=video opcije
+SING_OPTIONS_GRAPHICS_RESOLUTION=Rezolucija
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Cijeli ekran
+SING_OPTIONS_GRAPHICS_DEPTH=Dubina boja
+SING_OPTIONS_GRAPHICS_VISUALIZER=Vizualizacije
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Osciloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Bonus linije
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Veličina videa
+
+SING_OPTIONS_SOUND_WHEREAMI=Opcije Zvuka
+SING_OPTIONS_SOUND_DESC=postavke zvuka
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Microphone Playback
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Pozadinska glazba
+SING_OPTIONS_SOUND_MIC_BOOST=Mic boost
+SING_OPTIONS_SOUND_CLICK_ASSIST=Pomoć klikovima
+SING_OPTIONS_SOUND_BEAT_CLICK=Klik na udarce
+SING_OPTIONS_SOUND_THRESHOLD=Threshold
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Igra za dva igrača
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Glasnoća prikaza
+SING_OPTIONS_SOUND_PREVIEWFADING=Fade-in vrijeme
+
+SING_OPTIONS_LYRICS_WHEREAMI=Opcije Tekstova
+SING_OPTIONS_LYRICS_DESC=postavke tekstova
+SING_OPTIONS_LYRICS_FONT=Font
+SING_OPTIONS_LYRICS_EFFECT=Efekt
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmizacija
+SING_OPTIONS_LYRICS_NOTELINES=Crtovlje
+
+SING_OPTIONS_THEMES_WHEREAMI=Opcije Tema
+SING_OPTIONS_THEMES_DESC=postavke tema i skinova
+SING_OPTIONS_THEMES_THEME=Tema
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Boja
+
+SING_OPTIONS_RECORD_WHEREAMI=Opcije Snimanja
+SING_OPTIONS_RECORD_DESC=postavke mikrofona
+SING_OPTIONS_RECORD_CARD=Zv. kartica
+SING_OPTIONS_RECORD_INPUT=Ulaz
+SING_OPTIONS_RECORD_CHANNEL=Kanal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Ostale Opcije
+SING_OPTIONS_ADVANCED_DESC=ostale postavke
+SING_OPTIONS_ADVANCED_EFFECTSING=Efekti kod pjevanja
+SING_OPTIONS_ADVANCED_SCREENFADE=Fade-out ekrana
+SING_OPTIONS_ADVANCED_LOADANIMATION=Anim. tijekom učit.
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Sigurn. pitanja
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus linije
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Nakon pjesme
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto party meni
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=napravi svoje pjesme
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Učitaj tekst iz midi datoteke
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=natrag
+SING_EDIT_BUTTON_CONVERT=Učitaj
+SING_EDIT_BUTTON_EXIT=natrag
+
+SING_EDIT_NAVIGATE=upravljanje
+SING_EDIT_SELECT=odaberi
+SING_EDIT_EXIT=natrag
+
+SING_LEGEND_SELECT=odaberi
+SING_LEGEND_NAVIGATE=navigacija
+SING_LEGEND_CONTINUE=nastavi
+SING_LEGEND_ESC=natrag
+
+SING_PLAYER_DESC=unesi ime igrača
+SING_PLAYER_WHEREAMI=Imena igrača
+SING_PLAYER_ENTER_NAME=unesi ime
+
+SING_DIFFICULTY_DESC=odaberi težinu
+SING_DIFFICULTY_WHEREAMI=Težina
+SING_DIFFICULTY_CONTINUE=odabir pjesme
+SING_EASY=Lako
+SING_MEDIUM=Srednje
+SING_HARD=Teško
+
+SING_SONG_SELECTION_DESC=odaberi pjesmu
+SING_SONG_SELECTION_WHEREAMI=Odabir Pjesme
+SING_SONG_SELECTION_GOTO=idi na ..
+SING_SONG_SELECTION=odabir pjesme
+SING_SONG_SELECTION_MENU=meni
+SING_SONG_SELECTION_PLAYLIST=playlista
+SING_SONGS_IN_CAT=Pjesme
+PLAYLIST_CATTEXT=Playlista: %s
+
+SING_TIME=TIME
+SING_TOTAL=ukupno
+SING_MODE=pjevaj solo
+SING_NOTES=note
+SING_GOLDEN_NOTES=zlatne note
+SING_PHRASE_BONUS=bonus
+
+SING_MENU=Glavni Meni
+
+SONG_SCORE=bodovi
+SONG_SCORE_WHEREAMI=Rezultat
+
+SING_SCORE_TONE_DEAF=Bez sluha
+SING_SCORE_AMATEUR=Amater
+SING_SCORE_WANNABE=Wannabe
+SING_SCORE_HOPEFUL=Pun nade
+SING_SCORE_RISING_STAR=Zvijezda u usponu
+SING_SCORE_LEAD_SINGER=Vodeći pjevač
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=top 5 Igrača
+SING_TOP_5_CHARTS_WHEREAMI=top 5
+SING_TOP_5_CHARTS_CONTINUE=odabir pjesme
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=izvanredno!
+POPUP_AWESOME=predivno!
+POPUP_GREAT=odlično!
+POPUP_GOOD=dobro!
+POPUP_NOTBAD=nije loše!
+POPUP_BAD=loše!
+POPUP_POOR=jadno!
+POPUP_AWFUL=grozno!
+
+IMPLODE_GLUE1=, 
+IMPLODE_GLUE2= i 
+
+SONG_MENU_NAME_MAIN=Kolekcija pjesama
+SONG_MENU_PLAY=Pjevaj
+SONG_MENU_CHANGEPLAYERS=Promijeni igrače
+SONG_MENU_EDIT=Uredi
+SONG_MENU_MODI=Pjevaj Modi
+SONG_MENU_CANCEL=Poništi
+
+SONG_MENU_NAME_PLAYLIST=Playliste
+SONG_MENU_PLAYLIST_ADD=Dodaj Pjesmu
+SONG_MENU_PLAYLIST_DEL=Izbriši Pjesmu
+
+SONG_MENU_NAME_PLAYLIST_ADD=Dodaj Pjesmu
+SONG_MENU_PLAYLIST_ADD_NEW=na novu playlistu
+SONG_MENU_PLAYLIST_ADD_EXISTING=na postojeću playlistu
+SONG_MENU_PLAYLIST_NOEXISTING=Nema playlisti.
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nova Playlista
+SONG_MENU_PLAYLIST_NEW_CREATE=Napravi
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Bez imena
+
+;TODO: SONG_MENU_NAME_PLAYLIST_DELITEM=Really Delete?
+SONG_MENU_YES=Da
+SONG_MENU_NO=Ne
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Otvori Playlistu
+SONG_MENU_PLAYLIST_LOAD=otvori
+SONG_MENU_PLAYLIST_DELCURRENT=obriši trenutnu Playlistu
+
+SONG_MENU_NAME_PLAYLIST_DEL=Stvarno obrisati?
+
+SONG_MENU_NAME_PARTY_MAIN=Party Meni
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=iskoristi joker
+
+SONG_JUMPTO_DESC=pretraži pjesme
+SONG_JUMPTO_TYPE_DESC=Traži :
+SONG_JUMPTO_TYPE1=Sve
+SONG_JUMPTO_TYPE2=Naslov
+SONG_JUMPTO_TYPE3=Izvođač
+SONG_JUMPTO_SONGSFOUND=%d pjes(a)ma nađeno
+SONG_JUMPTO_NOSONGSFOUND=Niti jedna pjesma nije pronađena.
+SONG_JUMPTO_HELP=Unesi tekst koji želiš tražiti.
+SONG_JUMPTO_CATTEXT=Traži: %s
+
+PARTY_MODE=party mod
+PARTY_DIFFICULTY=Težina
+PARTY_PLAYLIST=Playlist Mod
+PARTY_PLAYLIST_ALL=Sve pjesme
+PARTY_PLAYLIST_CATEGORY=Folder
+PARTY_PLAYLIST_PLAYLIST=Playliste
+PARTY_TEAMS=Br. Timova
+PARTY_TEAMS_PLAYER1=Br. Igrača - Tim1
+PARTY_TEAMS_PLAYER2=Br. Igrača - Tim2
+PARTY_TEAMS_PLAYER3=Br. Igrača - Tim3
+
+PARTY_LEGEND_CONTINUE=nastavi
+
+PARTY_OPTIONS_DESC=postavke za party igru
+PARTY_OPTIONS_WHEREAMI=Party Opcije
+
+PARTY_PLAYER_DESC=unesi imena timova i igrača!
+PARTY_PLAYER_WHEREAMI=Party Imena
+PARTY_PLAYER_ENTER_NAME=unesi imena
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=započni party-igru
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=sljed. igrači za mikr.
+PARTY_ROUND_WHEREAMI=Party Sljed runda
+PARTY_ROUND_LEGEND_CONTINUE=započni rundu
+
+PARTY_SONG_WHEREAMI=Party Odabir pjesme	 
+PARTY_SONG_LEGEND_CONTINUE=pjevaj	 
+PARTY_SONG_MENU=party meni
+
+PARTY_SCORE_DESC=bodovi zadnje runde
+PARTY_SCORE_WHEREAMI=Party Bodovi
+
+PARTY_WIN_DESC=pobjednik party igre
+PARTY_WIN_WHEREAMI=Party Pobjednik
+PARTY_WIN_LEGEND_CONTINUE=natrag na glavni meni
+
+PARTY_ROUND=Runda
+PARTY_ROUND_WINNER=Pobjednik
+PARTY_NOTPLAYEDYET=nije još odigr.
+PARTY_NOBODY=nitko ni
+NEXT_ROUND=Sljed. runda:
+
+PARTY_DISMISSED=Izbacen!
+PARTY_SCORE_WINS=%s je
+PARTY_SCORE_WINS2=pobijedio!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Zadrži liniju
+MODE_HOLDTHELINE_DESC=Nemoj biti gori od pokazivača na 'rating' baru.
+
+MODE_5000POINTS_NAME=Do 5000
+MODE_5000POINTS_DESC=Pobjeđuje onaj tko prvi dođe do 5000 bodova.
+
+MODE_DUEL_NAME=Dvoboj
+MODE_DUEL_DESC=Pjevaj dvoboj do 10000 bodova.
+
+MODE_TEAMDUEL_NAME=Dvoboj timova
+MODE_TEAMDUEL_DESC=Dodaj mikrofon!
+
+MODE_BLIND_NAME=Slijepi način
+MODE_BLIND_DESC=Dvoboj bez gledanja nota.
+
+STAT_MAIN=Statistika
+STAT_MAIN_DESC=General
+STAT_MAIN_WHEREAMI=Statistika
+
+STAT_OVERVIEW_INTRO=%0:s Statistika.  \n Zadnji reset je bio %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d pjesama (%3:d sa Videom), od čega je %1:d pjesama otpjevano a %2:d nije.\n Najpopularnija pjesma je %5:s od %4:s.
+STAT_OVERVIEW_PLAYER=Od zadnjeg reseta bilo je %0:d različitih igrača.\n Najbolji igrač je %1:s sa prosjekom od %2:d bodova.\n %3:s je napravio/la najveći rezultat sa %4:d bodova.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statistika
+STAT_DETAIL_WHEREAMI=Detaljna statistika
+
+STAT_NEXT=Sljed. strana
+STAT_PREV=Preth. strana
+STAT_REVERSE=Obrnuti redoslijed
+STAT_PAGE=Strana %0:d od %1:d\n (%2:d od %3:d unosa)
+
+STAT_DESC_SCORES=HighScores
+STAT_DESC_SCORES_REVERSED=LowScores
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Najbolji pjevači
+STAT_DESC_SINGERS_REVERSED=Najgori pjevači
+STAT_FORMAT_SINGERS=%0:s \n Prosječni bodovi: %1:d
+
+STAT_DESC_SONGS=Popularne pjesme
+STAT_DESC_SONGS_REVERSED=Nepopularne pjesme
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx otpjevano
+
+STAT_DESC_BANDS=Popularni bendovi
+STAT_DESC_BANDS_REVERSED=Nepopularni bendovi
+STAT_FORMAT_BANDS=%0:s \n %1:dx otpjevano
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Greška
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Pitanje
+MSG_QUIT_USDX=Napustiti UltraStar?
+MSG_END_PARTY=Napustiti Party igru?
+
+ERROR_NO_SONGS=Nema učitanih pjesama
+ERROR_NO_PLUGINS=Nema učitanih pluginova
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Pjesma se ne može učitati.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Pjesma se ne može učitati: Datoteka nije nađena
+ERROR_CORRUPT_SONG_NO_NOTES=Pjesma se ne može učitati: Nije nađena niti jedna nota
+ERROR_CORRUPT_SONG_NO_BREAKS=Pjesma se ne može učitati: Nije nađen niti jedan 'linebreak'
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Pjesma se ne može učitati: Greška u obradi linije %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Zapamti broj pjev.
+;UNUSED: SING_SCORE_HIT_ARTIST=Hit Artist
+;UNUSED: PARTY_ROUNDS=Runde
+;UNUSED: MODE_MORE1000_NAME=1000 Više
+;UNUSED: MODE_MORE1000_DESC=Pjevajte dok jedan od igrača ne skupi 1000 bod više.
diff --git a/songmanagement/game/languages/Czech.ini b/songmanagement/game/languages/Czech.ini
new file mode 100644
index 00000000..002479d8
--- /dev/null
+++ b/songmanagement/game/languages/Czech.ini
@@ -0,0 +1,442 @@
+[Text]
+OPTION_VALUE_CATALAN=Katalánsky
+OPTION_VALUE_CROATIAN=Chorvatsky
+OPTION_VALUE_CZECH=Česky
+OPTION_VALUE_DANISH=Dánsky
+OPTION_VALUE_DUTCH=Holandsky
+OPTION_VALUE_ENGLISH=Anglicky
+OPTION_VALUE_EUSKARA=Baskicky
+OPTION_VALUE_FINNISH=Finsky
+OPTION_VALUE_FRENCH=Francouzsky
+OPTION_VALUE_GERMAN=Německy
+OPTION_VALUE_GREEK=Řecky
+OPTION_VALUE_HUNGARIAN=Maďarsky
+OPTION_VALUE_ICELANDIC=Islandsky
+OPTION_VALUE_ITALIAN=Italsky
+OPTION_VALUE_JAPANESE=Japonsky
+OPTION_VALUE_LUXEMBOURGISH=Lucembursky
+OPTION_VALUE_NORWEGIAN=Norsky
+OPTION_VALUE_POLISH=Polsky
+OPTION_VALUE_PORTUGUESE=Portugalsky
+OPTION_VALUE_RUSSIAN=Rusky
+OPTION_VALUE_SERBIAN=Srbsky
+OPTION_VALUE_SLOVAK=Slovensky
+OPTION_VALUE_SLOVENIAN=Slovinsky
+OPTION_VALUE_SPANISH=Španělsky
+OPTION_VALUE_SWEDISH=Švédsky
+
+OPTION_VALUE_EASY=Snadná
+OPTION_VALUE_MEDIUM=Střední
+OPTION_VALUE_HARD=Těžká
+
+OPTION_VALUE_ON=Zap
+OPTION_VALUE_OFF=Vyp
+
+OPTION_VALUE_EDITION=Edice
+OPTION_VALUE_GENRE=Žánr
+OPTION_VALUE_LANGUAGE=Jazyk
+OPTION_VALUE_FOLDER=Složka
+OPTION_VALUE_TITLE=Název
+OPTION_VALUE_ARTIST=Interpret
+OPTION_VALUE_TITLE2=Název 2
+OPTION_VALUE_ARTIST2=Interpret 2
+
+OPTION_VALUE_WHENNOVIDEO=Neobsahuje-li video
+
+OPTION_VALUE_SMALL=Malé
+OPTION_VALUE_BIG=Velké
+
+OPTION_VALUE_HALF=Poloviční
+OPTION_VALUE_FULL_VID=Úplné (video)
+OPTION_VALUE_FULL_VID_BG=Úplné (pozadí & video)
+
+OPTION_VALUE_AUTO=Auto
+OPTION_VALUE_SEC=sekunda
+OPTION_VALUE_SECS=sekundy
+
+OPTION_VALUE_PLAIN=Prosté
+OPTION_VALUE_OLINE1=Obtažené 1
+OPTION_VALUE_OLINE2=Obtažené 2
+
+OPTION_VALUE_SIMPLE=Jednoduchý
+OPTION_VALUE_ZOOM=Zvětšení
+OPTION_VALUE_SLIDE=Skluz
+OPTION_VALUE_BALL=Míč
+OPTION_VALUE_SHIFT=Posun
+
+OPTION_VALUE_EURO=Evropské
+OPTION_VALUE_JAPAN=Japonské
+OPTION_VALUE_AMERICAN=Americké
+
+OPTION_VALUE_BLUE=Modrá
+OPTION_VALUE_GREEN=Zelená
+OPTION_VALUE_PINK=Růžová
+OPTION_VALUE_RED=Červená
+OPTION_VALUE_VIOLET=Fialová
+OPTION_VALUE_ORANGE=Oranžová
+OPTION_VALUE_YELLOW=Žlutá
+OPTION_VALUE_BROWN=Hnědá
+OPTION_VALUE_BLACK=Černá
+
+OPTION_VALUE_SING=Zpívat
+OPTION_VALUE_SELECT_PLAYERS=Výběr hráčů
+OPTION_VALUE_OPEN_MENU=Otevřít menu
+
+OPTION_VALUE_HARDWARE_CURSOR=Hardwarový kurzor
+OPTION_VALUE_SOFTWARE_CURSOR=Softwarový kurzor
+
+SING_LOADING=Načítání...
+
+SING_CHOOSE_MODE=vybrat mód
+SING_SING=zpívat
+SING_SING_DESC=rychlá hra: zpívej sólo nebo duet
+
+SING_MULTI=párty
+SING_MULTI_DESC=zpívejte v párty-módu
+
+SING_TOOLS=nástroje
+
+SING_STATS=statistiky
+SING_STATS_DESC=zobrazit statistiky
+
+SING_EDITOR=editor
+SING_EDITOR_DESC=vytvořit vlastní skladbu
+
+SING_GAME_OPTIONS=herní možnosti
+SING_GAME_OPTIONS_DESC=změnit nastavení hry
+
+SING_EXIT=ukončit
+SING_EXIT_DESC=ukončit hru
+
+SING_OPTIONS=možnosti
+SING_OPTIONS_DESC=změnit nastavení
+SING_OPTIONS_WHEREAMI=Možnosti
+
+SING_OPTIONS_GAME=hra
+SING_OPTIONS_GRAPHICS=grafika
+SING_OPTIONS_SOUND=zvuk
+SING_OPTIONS_LYRICS=text
+SING_OPTIONS_THEMES=vzhled
+SING_OPTIONS_RECORD=záznam
+SING_OPTIONS_ADVANCED=pokročilé
+SING_OPTIONS_EXIT=zpět
+
+SING_OPTIONS_GAME_WHEREAMI=Možnosti hry
+SING_OPTIONS_GAME_DESC=obecné herní nastavení
+SING_OPTIONS_GAME_PLAYERS=Hráči
+SING_OPTIONS_GAME_DIFFICULTY=Obtížnost
+SING_OPTIONS_GAME_LANGUAGE=Jazyk
+SING_OPTIONS_GAME_TABS=Složky
+SING_OPTIONS_GAME_SORTING=Řazení
+SING_OPTIONS_GAME_DEBUG=Ladění programu
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Možnosti grafiky
+SING_OPTIONS_GRAPHICS_DESC=grafické nastavení
+SING_OPTIONS_GRAPHICS_RESOLUTION=Rozlišení
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Na celou obrazovku
+SING_OPTIONS_GRAPHICS_DEPTH=Barevná hloubka
+SING_OPTIONS_GRAPHICS_VISUALIZER=Vizualizace
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Osciloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Bonus za řádek
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Velikost videa
+
+SING_OPTIONS_SOUND_WHEREAMI=Možnosti zvuku
+SING_OPTIONS_SOUND_DESC=zvukové nastavení
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Přehrávání z mikrof.
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Hudba na pozadí
+SING_OPTIONS_SOUND_MIC_BOOST=Zesílení mikrofonu
+SING_OPTIONS_SOUND_CLICK_ASSIST=Pomocné tikání
+SING_OPTIONS_SOUND_BEAT_CLICK=Další rytmika
+SING_OPTIONS_SOUND_THRESHOLD=Práh
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Pro dva hráče
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Hlasitost ukázky
+SING_OPTIONS_SOUND_PREVIEWFADING=Odeznění ukázky
+
+SING_OPTIONS_LYRICS_WHEREAMI=Možnosti textů
+SING_OPTIONS_LYRICS_DESC=nastavení textů
+SING_OPTIONS_LYRICS_FONT=Písmo
+SING_OPTIONS_LYRICS_EFFECT=Efekt
+SING_OPTIONS_LYRICS_SOLMIZATION=Názvy tónů
+SING_OPTIONS_LYRICS_NOTELINES=Notová osnova
+
+SING_OPTIONS_THEMES_WHEREAMI=Možnosti vzhledu
+SING_OPTIONS_THEMES_DESC=nastavení vzhledu
+SING_OPTIONS_THEMES_THEME=Téma
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Barva
+
+SING_OPTIONS_RECORD_WHEREAMI=Možnosti záznamu
+SING_OPTIONS_RECORD_DESC=nastavení mikrofonu
+SING_OPTIONS_RECORD_CARD=Zvuková karta
+SING_OPTIONS_RECORD_INPUT=Vstup
+SING_OPTIONS_RECORD_CHANNEL=Kanál
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Pokročilé možnosti
+SING_OPTIONS_ADVANCED_DESC=pokročilé nastavení
+SING_OPTIONS_ADVANCED_EFFECTSING=Efekty u zpěvu
+SING_OPTIONS_ADVANCED_SCREENFADE=Přechody obrazu
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animace načítání
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Potvrzovací dialogy
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus za řádek
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Po výběru skladby
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto párty-menu
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=Vytvořit vlastní skladbu
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importovat ze souboru midi
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=zpět
+SING_EDIT_BUTTON_CONVERT=Importovat
+SING_EDIT_BUTTON_EXIT=zpět
+
+SING_EDIT_NAVIGATE=navigace
+SING_EDIT_SELECT=vybrat
+SING_EDIT_EXIT=zpět
+
+SING_LEGEND_SELECT=vybrat
+SING_LEGEND_NAVIGATE=navigace
+SING_LEGEND_CONTINUE=pokračovat
+SING_LEGEND_ESC=zpět
+
+SING_PLAYER_DESC=zadejte jméno hráče (jména hráčů)
+SING_PLAYER_WHEREAMI=Jména hráčů
+SING_PLAYER_ENTER_NAME=zadejte jména
+
+SING_DIFFICULTY_DESC=zvolte obtížnost
+SING_DIFFICULTY_WHEREAMI=Otížnost
+SING_DIFFICULTY_CONTINUE=na výběr skladby
+SING_EASY=Snadná
+SING_MEDIUM=Střední
+SING_HARD=Těžká
+
+SING_SONG_SELECTION_DESC=vyberte skladbu
+SING_SONG_SELECTION_WHEREAMI=Výběr skladby
+SING_SONG_SELECTION_GOTO=jdi na ..
+SING_SONG_SELECTION=výběr skladby
+SING_SONG_SELECTION_MENU=menu
+SING_SONG_SELECTION_PLAYLIST=seznam stop
+SING_SONGS_IN_CAT=skladby
+PLAYLIST_CATTEXT=Seznam stop: %s
+
+SING_TIME=TIME
+SING_TOTAL=celkem
+SING_MODE=zpívat sólo
+SING_NOTES=noty
+SING_GOLDEN_NOTES=zlaté noty
+SING_PHRASE_BONUS=bonus za řádek
+
+SING_MENU=Hlavní menu
+
+SONG_SCORE=skóre za skladbu
+SONG_SCORE_WHEREAMI=Skóre
+
+SING_SCORE_TONE_DEAF=Hudební hluch
+SING_SCORE_AMATEUR=Amatér
+SING_SCORE_WANNABE=Snaživý
+SING_SCORE_HOPEFUL=Nadějný
+SING_SCORE_RISING_STAR=Vycházející hvězda
+SING_SCORE_LEAD_SINGER=Sólový zpěvák
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=5 nejlepších
+SING_TOP_5_CHARTS_WHEREAMI=5 nej
+SING_TOP_5_CHARTS_CONTINUE=na výběr skladby
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=přepnout obtížnost
+
+POPUP_PERFECT=výborně!
+POPUP_AWESOME=paráda!
+POPUP_GREAT=super!
+POPUP_GOOD=dobře!
+POPUP_NOTBAD=šlo to!
+POPUP_BAD=špatně!
+POPUP_POOR=bída!
+POPUP_AWFUL=hrůza!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= a
+
+SONG_MENU_NAME_MAIN=menu skladby
+SONG_MENU_PLAY=Zpívat
+SONG_MENU_CHANGEPLAYERS=Změnit hráče
+SONG_MENU_EDIT=Upravit
+SONG_MENU_MODI=Zpívat "Modi"
+SONG_MENU_CANCEL=Zrušit
+
+SONG_MENU_NAME_PLAYLIST=Menu skladeb
+SONG_MENU_PLAYLIST_ADD=Přidat skladbu
+SONG_MENU_PLAYLIST_DEL=Odebrat skladbu
+
+SONG_MENU_NAME_PLAYLIST_ADD=Přidat skladbu
+SONG_MENU_PLAYLIST_ADD_NEW=do nového playlistu
+SONG_MENU_PLAYLIST_ADD_EXISTING=do existujícího seznamu stop
+SONG_MENU_PLAYLIST_NOEXISTING=Žádný seznam stop nevytvořen
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nový seznam stop
+SONG_MENU_PLAYLIST_NEW_CREATE=Vytvořit
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Nepojmenovaný
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Opravdu smazat?
+SONG_MENU_YES=Ano
+SONG_MENU_NO=Ne
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Otevřít seznam stop
+SONG_MENU_PLAYLIST_LOAD=otevřít
+SONG_MENU_PLAYLIST_DELCURRENT=smazat tento seznam stop
+
+SONG_MENU_NAME_PLAYLIST_DEL=Smazat seznam stop?
+
+SONG_MENU_NAME_PARTY_MAIN=Párty menu
+SONG_MENU_JOKER=Žolík
+
+SONG_MENU_NAME_PARTY_JOKER=vzít žolíka
+
+SONG_JUMPTO_DESC=hledat skladbu
+SONG_JUMPTO_TYPE_DESC=Hledat:
+SONG_JUMPTO_TYPE1=Všude
+SONG_JUMPTO_TYPE2=V názvech
+SONG_JUMPTO_TYPE3=V interpretech
+SONG_JUMPTO_SONGSFOUND=Nalezeno %d skladeb
+SONG_JUMPTO_NOSONGSFOUND=Žádné skladby nenalezeny
+SONG_JUMPTO_HELP=Zadejte text pro hledání
+SONG_JUMPTO_CATTEXT=Hledat: %s
+
+PARTY_MODE=párty mód
+PARTY_DIFFICULTY=Obtížnost
+PARTY_PLAYLIST=Mód seznamu stop
+PARTY_PLAYLIST_ALL=Všechny skladby
+PARTY_PLAYLIST_CATEGORY=Složka
+PARTY_PLAYLIST_PLAYLIST=Seznam stop
+PARTY_TEAMS=Počet týmů
+PARTY_TEAMS_PLAYER1=Hráčů týmu 1
+PARTY_TEAMS_PLAYER2=Hráčů týmu 2
+PARTY_TEAMS_PLAYER3=Hráčů týmu 3
+
+PARTY_LEGEND_CONTINUE=pokračovat
+
+PARTY_OPTIONS_DESC=nastavení pro hru na párty
+PARTY_OPTIONS_WHEREAMI=Možnosti párty
+
+PARTY_PLAYER_DESC=zadejte jména hráčů a týmů!
+PARTY_PLAYER_WHEREAMI=Jména párty
+PARTY_PLAYER_ENTER_NAME=vložit jména
+
+
+PARTY_ROUNDS_DESC=Vyberte, ve kterých režimech chcete hrát
+PARTY_ROUNDS_WHEREAMI=Kola párty
+PARTY_ROUNDS_LEGEND_CONTINUE=spustit párty-hru
+PARTY_ROUNDCOUNT=počet kol
+PARTY_SELECTMODE1=režim 1. kola
+PARTY_SELECTMODE2=režim 2. kola
+PARTY_SELECTMODE3=režim 3. kola
+PARTY_SELECTMODE4=režim 4. kola
+PARTY_SELECTMODE5=režim 5. kola
+PARTY_SELECTMODE6=režim 6. kola
+PARTY_SELECTMODE7=režim 7. kola
+
+PARTY_ROUND_DESC=další hráč k mikrofonu
+PARTY_ROUND_WHEREAMI=Další kolo
+PARTY_ROUND_LEGEND_CONTINUE=začít kolo
+
+PARTY_SONG_WHEREAMI=Výběr skladeb na párty
+PARTY_SONG_LEGEND_CONTINUE=zpívat
+PARTY_SONG_MENU=párty menu
+
+PARTY_SCORE_DESC=skóre posledního kola
+PARTY_SCORE_WHEREAMI=Párty body
+
+PARTY_WIN_DESC=Vítěz hry párty
+PARTY_WIN_WHEREAMI=Vítěz párty
+PARTY_WIN_LEGEND_CONTINUE=zpět do hlavního menu
+
+PARTY_ROUND=Kolo
+PARTY_ROUND_WINNER=Vítěz
+PARTY_NOTPLAYEDYET=ještě se nehrálo
+PARTY_NOBODY=nikdo
+NEXT_ROUND=Další kolo:
+
+PARTY_DISMISSED=Zrušeno!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=vítězství!
+
+MODE_RANDOM_NAME=Náhodný režim
+MODE_RANDOM_DESC=Jeden režim bude vybrán náhodně.
+
+MODE_HOLDTHELINE_NAME=Drž úroveň
+MODE_HOLDTHELINE_DESC=Nesmíš klesnout pod hranici ukazatele úspešnosti.
+
+MODE_5000POINTS_NAME=Do 5000
+MODE_5000POINTS_DESC=Kdo získá první 5000 bodů, vyhrál.
+
+MODE_DUEL_NAME=Duel
+MODE_DUEL_DESC=Zpívej duel do 10 000 bodů.
+
+MODE_TEAMDUEL_NAME=Duel týmů
+MODE_TEAMDUEL_DESC=Předej mikrofon dál!
+
+MODE_BLIND_NAME=Slepý režim
+MODE_BLIND_DESC=Duel bez not.
+
+STAT_MAIN=Statistiky
+STAT_MAIN_DESC=Obecné
+STAT_MAIN_WHEREAMI=Statistiky
+
+STAT_OVERVIEW_INTRO=%0:s Statistiky.  \n Naposledy vynulováno %1:.2d. %2:.2d. %3:d
+STAT_OVERVIEW_SONG=%0:d skladeb (%3:d s videem), z čehož %1:d už bylo hráno  a %2:d zatím hráno nebylo.\n Nejpopulárnější skladba je %5:s od %4:s.
+STAT_OVERVIEW_PLAYER=Od posledního nulování se vystřídalo %0:d různých hráčů.\n Nejlepší hráč je %1:s s průměrným skóre %2:d bodů.\n %3:s získal nejvyšší skóre %4:d bodů.
+
+STAT_FORMAT_DATE=%0:.2d. %1:.2d. %2:d
+
+STAT_DETAIL=Statistiky
+STAT_DETAIL_WHEREAMI=Podrobné statistiky
+
+STAT_NEXT=Další stránka
+STAT_PREV=Předchozí stránka
+STAT_REVERSE=Opačné pořadí
+STAT_PAGE=Strana %0:d z %1:d stránek\n (%2:d z %3:d záznamů)
+
+STAT_DESC_SCORES=Nejvyšší skóre
+STAT_DESC_SCORES_REVERSED=Nejnižší skóre
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Nejlepší zpěváci
+STAT_DESC_SINGERS_REVERSED=Nejhorší zpěváci
+STAT_FORMAT_SINGERS=%0:s \n Průměrné skóre: %1:d
+
+STAT_DESC_SONGS=Nejoblíbenější skladba
+STAT_DESC_SONGS_REVERSED=Nejneoblíbenější skladba
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx zpívána
+
+STAT_DESC_BANDS=Nejoblíbenější kapela
+STAT_DESC_BANDS_REVERSED=Nejneoblíbenější kapela
+STAT_FORMAT_BANDS=%0:s \n %1:dx zpíváno
+
+SCREENSHOT_SAVED=Snímek obrazovky uložen
+SCREENSHOT_FAILED=Uložení snímku obrazovky selhalo
+
+INFO_FILE_SAVED=Soubor uložen
+ERROR_SAVE_FILE_FAILED=Uložení souboru selhalo 
+ERROR_FILE_NOT_FOUND=Soubor nenalezen
+
+ENCODING_ERROR_ASK_FOR_UTF8=Nelze uložit změny v tomto kódování. Změnit na UTF-8?
+EDITOR_ERROR_NO_TRACK_SELECTED=Nevybrána žádná stopa
+
+MSG_ERROR_TITLE=Chyba
+MSG_INFO_TITLE=Info
+MSG_QUESTION_TITLE=Potvrzení
+MSG_QUIT_USDX=Opravdu ukončit UltraStar?
+MSG_END_PARTY=Opravdu ukončit párty mód?
+
+ERROR_NO_SONGS=Žádné skladby nenačteny
+ERROR_NO_PLUGINS=Žádné doplňky nenačteny
+ERROR_NO_MODES_FOR_CURRENT_SETUP=pro vybrané nastavení hráčů/týmů nejsou dostupné žádné režimy
+ERROR_CAN_NOT_START_PARTY= během spouštění párty-módu se objevila chyba
+ERROR_CORRUPT_SONG=Skladbu se nepodařilo načíst.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Skladbu se nepodařilo načíst: Soubor nenalezen
+ERROR_CORRUPT_SONG_NO_NOTES=Skladbu se nepodařilo načíst: Noty nenalezeny
+ERROR_CORRUPT_SONG_NO_BREAKS=Skladbu se nepodařilo načíst: Nenalezeny informace o rozdělení do řádků
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Skladbu se nepodařilo načíst: Chyba při zpracování řádku %0:d
+ERROR_NO_EDITOR=Tato funkce není dostupná pro Linux/Mac
+ERROR_PLAYER_DEVICE_ASSIGNMENT=Hráč %d je přiřazen k vícero mikrofonům. Zkontrolujte prosím nastavení záznamu
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Hráč %d není přiřazen k mikrofonu. Zkontrolujte prosím nastavení záznamu
+;TRANSLATOR: Oblack
diff --git a/songmanagement/game/languages/Danish.ini b/songmanagement/game/languages/Danish.ini
new file mode 100644
index 00000000..2f7495de
--- /dev/null
+++ b/songmanagement/game/languages/Danish.ini
@@ -0,0 +1,443 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Loader...
+
+SING_CHOOSE_MODE=Vælg modus
+SING_SING=Syng
+SING_SING_DESC=Hurtigt spil: Syng solo eller duet
+
+SING_MULTI=Fest
+SING_MULTI_DESC=Syng i fest modus
+
+SING_TOOLS=Værktøjer
+
+SING_STATS=stats
+SING_STATS_DESC=Se statestikker
+
+SING_EDITOR=editor
+SING_EDITOR_DESC=Lav dine egne sange
+
+SING_GAME_OPTIONS=Spil Indstillinger
+SING_GAME_OPTIONS_DESC=Ændre spil Indstillinger
+
+SING_EXIT=Forlad
+SING_EXIT_DESC=Forlad spillet
+
+SING_OPTIONS=Indstillinger
+SING_OPTIONS_DESC=Ændre Instillinger
+SING_OPTIONS_WHEREAMI=Indstillinger
+
+SING_OPTIONS_GAME=Spil
+SING_OPTIONS_GRAPHICS=Grafik
+SING_OPTIONS_SOUND=Lyd
+SING_OPTIONS_LYRICS=Tekster
+SING_OPTIONS_THEMES=Temaer
+SING_OPTIONS_RECORD=Optag
+SING_OPTIONS_ADVANCED=Advanceret
+SING_OPTIONS_EXIT=Tilbage
+
+SING_OPTIONS_GAME_WHEREAMI=Spil Indstillinger
+SING_OPTIONS_GAME_DESC=Generelle Spil Indstillinger
+SING_OPTIONS_GAME_PLAYERS=Spillere
+SING_OPTIONS_GAME_DIFFICULTY=Sværhedsgrad
+SING_OPTIONS_GAME_LANGUAGE=Sprog
+SING_OPTIONS_GAME_TABS=Tabs
+SING_OPTIONS_GAME_SORTING=Sorting
+SING_OPTIONS_GAME_DEBUG=Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Grafik Indstillinger
+SING_OPTIONS_GRAPHICS_DESC=Grafik Indstillinger
+SING_OPTIONS_GRAPHICS_RESOLUTION=Opløsning
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Fuldskærm
+SING_OPTIONS_GRAPHICS_DEPTH=Farve dybte
+;TODO: SING_OPTIONS_GRAPHICS_VISUALIZER=Visualization
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Linie Bonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Film Størrelse
+
+SING_OPTIONS_SOUND_WHEREAMI=Lyd Indstillinger
+SING_OPTIONS_SOUND_DESC=Lyd Indstillinger
+;TODO: SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Microphone Playback
+;TODO: SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Background music
+SING_OPTIONS_SOUND_MIC_BOOST=Mikrofon Boost
+SING_OPTIONS_SOUND_CLICK_ASSIST=Click assist
+SING_OPTIONS_SOUND_BEAT_CLICK=Beat click
+SING_OPTIONS_SOUND_THRESHOLD=Tærskel
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=2 Spiller modus
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Frosmag Volume
+SING_OPTIONS_SOUND_PREVIEWFADING=Forsmag Fader
+
+SING_OPTIONS_LYRICS_WHEREAMI=Tekst Indstillinger
+SING_OPTIONS_LYRICS_DESC=Tekst Indstillinger
+SING_OPTIONS_LYRICS_FONT=Tekst Type
+SING_OPTIONS_LYRICS_EFFECT=Effekt
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmization
+;TODO: SING_OPTIONS_LYRICS_NOTELINES=Staves
+
+SING_OPTIONS_THEMES_WHEREAMI=Tema Indstillinger
+SING_OPTIONS_THEMES_DESC=Tema og Skin Indstillinger
+SING_OPTIONS_THEMES_THEME=Tema
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Farve
+
+SING_OPTIONS_RECORD_WHEREAMI=Optagelses Indstillinger
+SING_OPTIONS_RECORD_DESC=Mikrofon Indstillinger
+SING_OPTIONS_RECORD_CARD=Lydkort
+SING_OPTIONS_RECORD_INPUT=Input
+SING_OPTIONS_RECORD_CHANNEL=Kanal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Advancerede Indstillinger
+SING_OPTIONS_ADVANCED_DESC=Advancerede Indstillinger
+SING_OPTIONS_ADVANCED_EFFECTSING=Sang Effekter
+SING_OPTIONS_ADVANCED_SCREENFADE=Skærm Fading
+SING_OPTIONS_ADVANCED_LOADANIMATION=Load Animation
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Savety Questions
+SING_OPTIONS_ADVANCED_LINEBONUS=Linie Bonus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Efter sang valg
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto Festmodus
+
+;TODO: SING_EDIT=Editor
+;TODO: SING_EDIT_MENU_DESCRIPTION=create your own song
+
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Import text from midi file
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_EXIT=back
+;TODO: SING_EDIT_BUTTON_CONVERT=Import
+;TODO: SING_EDIT_BUTTON_EXIT=back
+
+;TODO: SING_EDIT_NAVIGATE=navigate
+;TODO: SING_EDIT_SELECT=select
+;TODO: SING_EDIT_EXIT=back
+
+SING_LEGEND_SELECT=Vælg
+SING_LEGEND_NAVIGATE=Naviger
+SING_LEGEND_CONTINUE=Fortsæt
+SING_LEGEND_ESC=Tilbage
+
+SING_PLAYER_DESC=Skriv Spiller Navn/e
+SING_PLAYER_WHEREAMI=Spiller Navne
+SING_PLAYER_ENTER_NAME=Skriv navn
+
+SING_DIFFICULTY_DESC=Vælg Sværhedsgrad
+SING_DIFFICULTY_WHEREAMI=Sværhedsgrad
+SING_DIFFICULTY_CONTINUE=Til sang valg
+SING_EASY=Let
+SING_MEDIUM=Normal
+SING_HARD=Svær
+
+SING_SONG_SELECTION_DESC=Vælg Din Sang
+SING_SONG_SELECTION_WHEREAMI=Sang Valg
+SING_SONG_SELECTION_GOTO=Gå Til ..
+SING_SONG_SELECTION=Sang Valg
+SING_SONG_SELECTION_MENU=Menu
+SING_SONG_SELECTION_PLAYLIST=Afspilningsliste
+SING_SONGS_IN_CAT=Songs
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=TID
+SING_TOTAL=Total
+SING_MODE=Syng Solo
+SING_NOTES=Noder
+SING_GOLDEN_NOTES=Gyldne Noder
+SING_PHRASE_BONUS=Linie Bonus
+
+SING_MENU=Hoved Menu
+
+SONG_SCORE=Sang score
+SONG_SCORE_WHEREAMI=Score
+
+SING_SCORE_TONE_DEAF=Tone Døv!
+SING_SCORE_AMATEUR=Amatør!
+;TODO: SING_SCORE_WANNABE=Wannabe
+;TODO: SING_SCORE_HOPEFUL=Hopeful
+SING_SCORE_RISING_STAR=Aspirende Stjerne
+SING_SCORE_LEAD_SINGER=Forsanger
+SING_SCORE_SUPERSTAR=Super Stjerne
+SING_SCORE_ULTRASTAR=Ultra Stjerne
+
+SING_TOP_5_CHARTS=Top 5 Spillere
+SING_TOP_5_CHARTS_WHEREAMI=Top 5
+SING_TOP_5_CHARTS_CONTINUE=Til Sang Valg
+;TODO: SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=Perfekt!
+POPUP_AWESOME=Utroligt!
+POPUP_GREAT=Meget Godt!
+POPUP_GOOD=Godt!
+POPUP_NOTBAD=Ikke dårligt!
+POPUP_BAD=Dårligt!
+POPUP_POOR=Meget Dårligt!
+POPUP_AWFUL=Ringe!
+
+IMPLODE_GLUE1=, 
+IMPLODE_GLUE2= og 
+
+SONG_MENU_NAME_MAIN=Sang Menu
+SONG_MENU_PLAY=Syng
+SONG_MENU_CHANGEPLAYERS=Skift Spillere
+SONG_MENU_EDIT=Ændre
+SONG_MENU_MODI=Sing a Modi
+SONG_MENU_CANCEL=Annuller
+
+SONG_MENU_NAME_PLAYLIST=Sang Menu
+SONG_MENU_PLAYLIST_ADD=Tilføj Sang
+SONG_MENU_PLAYLIST_DEL=Slet Sang
+
+SONG_MENU_NAME_PLAYLIST_ADD=Tilføj Song
+SONG_MENU_PLAYLIST_ADD_NEW=Til Ny Afspilningsliste
+SONG_MENU_PLAYLIST_ADD_EXISTING=Til Eksisterende Afspilningsliste
+SONG_MENU_PLAYLIST_NOEXISTING=Ingen Tilgængelige Afspilningslister 
+
+SONG_MENU_NAME_PLAYLIST_NEW=Ny Afspilningsliste
+SONG_MENU_PLAYLIST_NEW_CREATE=Skab
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Unavngiven
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Vil Du Virkelig Slette?
+SONG_MENU_YES=Ja
+SONG_MENU_NO=Nej
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Åben Afspilningsliste
+SONG_MENU_PLAYLIST_LOAD=Åben
+SONG_MENU_PLAYLIST_DELCURRENT=Slet Nuværende Afspilningsliste
+
+SONG_MENU_NAME_PLAYLIST_DEL=Slet Afspilningslisten?
+
+SONG_MENU_NAME_PARTY_MAIN=Fest Menu
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=Brug Jokeren
+
+SONG_JUMPTO_DESC=Søg Sang
+SONG_JUMPTO_TYPE_DESC=Søg Efter:
+SONG_JUMPTO_TYPE1=Alle
+SONG_JUMPTO_TYPE2=Titel
+SONG_JUMPTO_TYPE3=Kunstner
+SONG_JUMPTO_SONGSFOUND=%d Sang(e) fundet!
+SONG_JUMPTO_NOSONGSFOUND=Ingen Sange Fundet
+SONG_JUMPTO_HELP=Skriv Teksten Du Vil Søge Efter
+SONG_JUMPTO_CATTEXT=Søg Efter: %s
+
+PARTY_MODE=Fest modus
+PARTY_DIFFICULTY=Sværhedsgrad
+PARTY_PLAYLIST=Afspilningsliste modus
+PARTY_PLAYLIST_ALL=Alle sange
+PARTY_PLAYLIST_CATEGORY=Mappe
+PARTY_PLAYLIST_PLAYLIST=Afspilningsliste
+PARTY_TEAMS=Teams
+PARTY_TEAMS_PLAYER1=Spiller Team 1
+PARTY_TEAMS_PLAYER2=Spiller Team 2
+PARTY_TEAMS_PLAYER3=Spiller Team 3
+
+PARTY_LEGEND_CONTINUE=Fortsæt
+
+PARTY_OPTIONS_DESC=Indstillinger for Fest spil
+PARTY_OPTIONS_WHEREAMI=Fest Indstillinger
+
+PARTY_PLAYER_DESC=Skriv Spiller of Team Navn!
+PARTY_PLAYER_WHEREAMI=Fest navne
+PARTY_PLAYER_ENTER_NAME=Skriv Navne
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE==Start Fest Spil
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=Næste spillere til mikrofonerne
+PARTY_ROUND_WHEREAMI=Fest Næste runde
+PARTY_ROUND_LEGEND_CONTINUE=Start runde
+
+PARTY_SONG_WHEREAMI=Fest Sang-Valg 	 
+PARTY_SONG_LEGEND_CONTINUE=Syng 	 
+PARTY_SONG_MENU=Fest menu
+
+PARTY_SCORE_DESC=Sidste Rundes Score
+PARTY_SCORE_WHEREAMI=Fest Point
+
+PARTY_WIN_DESC=Vinderen Af Fest Spillet
+PARTY_WIN_WHEREAMI=Fest Vinder
+PARTY_WIN_LEGEND_CONTINUE=Tilbage til Hoved Menuen
+
+PARTY_ROUND=Runde
+PARTY_ROUND_WINNER=vinder
+PARTY_NOTPLAYEDYET=Ikke spillet endnu
+PARTY_NOBODY=Ingen
+NEXT_ROUND=Næste Runde:
+
+PARTY_DISMISSED=Afsluttet!
+PARTY_SCORE_WINS=%s 
+PARTY_SCORE_WINS2=Vinder!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Hold Linien
+MODE_HOLDTHELINE_DESC=Få ikke værrer end pilen på skalaen peger på
+
+MODE_5000POINTS_NAME=Until 5000
+MODE_5000POINTS_DESC=Hvem får 5000 point først vinder the kampen.
+
+MODE_DUEL_NAME=Duell
+MODE_DUEL_DESC=Syng en duel intil 10000 point.
+
+;TODO: MODE_TEAMDUEL_NAME=Team Duell
+;TODO: MODE_TEAMDUEL_DESC=Pass The Mic!
+
+MODE_BLIND_NAME=Blind Modus
+MODE_BLIND_DESC=Duel med usynlige noder.
+
+STAT_MAIN=Statestikker
+STAT_MAIN_DESC=Generelle
+STAT_MAIN_WHEREAMI=Statestikker
+
+STAT_OVERVIEW_INTRO=%0:s Statistics.  \n Last Reset at %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Songs(%3:d with Video), whereof %1:d already were played  and %2:d were not played yet.\n The most popular Song is %5:s from %4:s.
+STAT_OVERVIEW_PLAYER=Since the last Reset there were/was %0:d different Player(s).\n The best Player is %1:s with an average Score of %2:d Points.\n %3:s did the highest Score with %4:d Points.
+
+;TODO: STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statestikker
+STAT_DETAIL_WHEREAMI=Detaljerede Statestikker
+
+STAT_NEXT=Næste Side
+STAT_PREV=Tidligere Side
+STAT_REVERSE=Omvendt Orden
+STAT_PAGE=Seite %0:d of %1:d Pages\n (%2:d of %3:d Entrys)
+
+STAT_DESC_SCORES=HighScore
+STAT_DESC_SCORES_REVERSED=LowScore
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s] \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Bedste Sangere
+STAT_DESC_SINGERS_REVERSED=Værste Sangere
+STAT_FORMAT_SINGERS=%0:s \n Average Score: %1:d
+
+STAT_DESC_SONGS=Mest Populære Sange
+STAT_DESC_SONGS_REVERSED=Mindst Populære Sange
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx sung
+
+STAT_DESC_BANDS=Mest Populære Bands
+STAT_DESC_BANDS_REVERSED=Mindst Populære Bands
+STAT_FORMAT_BANDS=%0:s \n %1:dx Sung
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Fejl 
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Spørgsmål
+MSG_QUIT_USDX=Vil du virkelig forlade UltraStar?
+MSG_END_PARTY=Vil du virkelig forlade fest Modus?
+
+ERROR_NO_SONGS=Ingen Sange hentet
+ERROR_NO_PLUGINS=Igen Plugins hentet
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Sangen kunne ikke hentes.
+;TODO: ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Song could not be loaded: File not found
+;TODO: ERROR_CORRUPT_SONG_NO_NOTES=Song could not be loaded: Can''t find any notes
+;TODO: ERROR_CORRUPT_SONG_NO_BREAKS=Song could not be loaded: Can''t find any linebreaks
+;TODO: ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Song could not be loaded: Error parsing line %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: SING_SCORE_HIT_ARTIST=Etableret Stjerne
+;UNUSED: PARTY_ROUNDS=Runder
diff --git a/songmanagement/game/languages/Dutch.ini b/songmanagement/game/languages/Dutch.ini
new file mode 100644
index 00000000..1177754d
--- /dev/null
+++ b/songmanagement/game/languages/Dutch.ini
@@ -0,0 +1,443 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Laden...
+
+SING_CHOOSE_MODE=kies mode
+SING_SING=zing
+SING_SING_DESC=snel spelletje: zing een solo of duet
+
+SING_MULTI=party
+SING_MULTI_DESC=zing in party-mode
+
+SING_TOOLS=tools
+
+SING_STATS=stats
+SING_STATS_DESC=bekijk de statistieken
+
+SING_EDITOR=editor
+SING_EDITOR_DESC=Maak je eigen liedje
+
+SING_GAME_OPTIONS=spelopties
+SING_GAME_OPTIONS_DESC=verander de spelopties
+
+SING_EXIT=Stoppen
+SING_EXIT_DESC=stop het spelletje
+
+SING_OPTIONS=opties
+SING_OPTIONS_DESC=Verander de opties
+SING_OPTIONS_WHEREAMI=Opties
+
+SING_OPTIONS_GAME=Spel
+SING_OPTIONS_GRAPHICS=graphics
+SING_OPTIONS_SOUND=Geluid
+SING_OPTIONS_LYRICS=Tekst
+SING_OPTIONS_THEMES=Thema
+SING_OPTIONS_RECORD=Opname
+SING_OPTIONS_ADVANCED=Geavanceerd
+SING_OPTIONS_EXIT=Terug
+
+SING_OPTIONS_GAME_WHEREAMI=Spel Opties
+SING_OPTIONS_GAME_DESC=Algemene spelinstellingen
+SING_OPTIONS_GAME_PLAYERS=Spelers
+SING_OPTIONS_GAME_DIFFICULTY=Moeilijkheidsgraad
+SING_OPTIONS_GAME_LANGUAGE=Taal
+SING_OPTIONS_GAME_TABS=Tabs
+SING_OPTIONS_GAME_SORTING=Sorteren
+SING_OPTIONS_GAME_DEBUG=Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Grafische opties
+SING_OPTIONS_GRAPHICS_DESC=Grafische instellingen
+SING_OPTIONS_GRAPHICS_RESOLUTION=Resolutie
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Fullscreen
+SING_OPTIONS_GRAPHICS_DEPTH=Diepte
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualisatie
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloscoop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Lijnbonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Video grootte
+
+SING_OPTIONS_SOUND_WHEREAMI=Geluidsopties
+SING_OPTIONS_SOUND_DESC=Geluidsinstellingen
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Microfoon Playback
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Achtergrond Muziek
+SING_OPTIONS_SOUND_MIC_BOOST=Microfoon boost
+SING_OPTIONS_SOUND_CLICK_ASSIST=Klik assistent
+SING_OPTIONS_SOUND_BEAT_CLICK=Beat klik
+SING_OPTIONS_SOUND_THRESHOLD=Drempelwaarde
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Twee spelers mode
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Voorbeeld volume
+SING_OPTIONS_SOUND_PREVIEWFADING=Voorbeeld Faden
+
+SING_OPTIONS_LYRICS_WHEREAMI=Tekst Opties
+SING_OPTIONS_LYRICS_DESC=Tekst instellingen
+SING_OPTIONS_LYRICS_FONT=Lettertype
+SING_OPTIONS_LYRICS_EFFECT=Effecten
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmizatie
+SING_OPTIONS_LYRICS_NOTELINES=Staafjes
+
+SING_OPTIONS_THEMES_WHEREAMI=Thema opties
+SING_OPTIONS_THEMES_DESC=Thema- en skinopties
+SING_OPTIONS_THEMES_THEME=Thema
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Kleur
+
+SING_OPTIONS_RECORD_WHEREAMI=Opname opties
+SING_OPTIONS_RECORD_DESC=Microfoon instellingen
+SING_OPTIONS_RECORD_CARD=Geluidskaart
+SING_OPTIONS_RECORD_INPUT=Input
+SING_OPTIONS_RECORD_CHANNEL=Kanaal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Geavanceerde opties
+SING_OPTIONS_ADVANCED_DESC=geavanceerde instellingen
+SING_OPTIONS_ADVANCED_EFFECTSING=Zing effecten
+SING_OPTIONS_ADVANCED_SCREENFADE=Faden
+SING_OPTIONS_ADVANCED_LOADANIMATION=Laad animaties
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Veiligheidsvragen
+SING_OPTIONS_ADVANCED_LINEBONUS=Lijnbonus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Selecties na het Liedje
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto PartyMenu
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=Maak je eigen liedje
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importeer tekst van midi file
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Terug
+SING_EDIT_BUTTON_CONVERT=Importeer
+SING_EDIT_BUTTON_EXIT=Terug
+
+SING_EDIT_NAVIGATE=Navigeer
+SING_EDIT_SELECT=Selecteer
+SING_EDIT_EXIT=Terug
+
+SING_LEGEND_SELECT=Selecteer
+SING_LEGEND_NAVIGATE=Navigeer
+SING_LEGEND_CONTINUE=Ga Verder
+SING_LEGEND_ESC=Terug
+
+SING_PLAYER_DESC=Kies Namen
+SING_PLAYER_WHEREAMI=Namen
+SING_PLAYER_ENTER_NAME=Kies namen
+
+SING_DIFFICULTY_DESC=selecteer moeilijkheidsgraad
+SING_DIFFICULTY_WHEREAMI=Moeilijkheidsgraad
+SING_DIFFICULTY_CONTINUE=Ga verder
+SING_EASY=Gemakkelijk
+SING_MEDIUM=Gemiddeled
+SING_HARD=Moeilijk
+
+SING_SONG_SELECTION_DESC=Kies je liedje
+SING_SONG_SELECTION_WHEREAMI=Selecteer een liedje
+SING_SONG_SELECTION_GOTO=Ga naar
+SING_SONG_SELECTION=Liedjes Selectie
+SING_SONG_SELECTION_MENU=menu
+SING_SONG_SELECTION_PLAYLIST=playlist
+SING_SONGS_IN_CAT=Liedjes
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=TIJD
+SING_TOTAL=totaal
+SING_MODE=zing solo
+SING_NOTES=noten
+SING_GOLDEN_NOTES=gouden noten
+SING_PHRASE_BONUS=lijn bonus
+
+SING_MENU=Hoofd Menu
+
+SONG_SCORE=Score
+SONG_SCORE_WHEREAMI=Score
+
+SING_SCORE_TONE_DEAF=Toondoof
+SING_SCORE_AMATEUR=Amateur
+SING_SCORE_WANNABE=Wannabe
+SING_SCORE_HOPEFUL=Hoopvol
+SING_SCORE_RISING_STAR=Opkomende Ster
+SING_SCORE_LEAD_SINGER=Hoofdzanger
+SING_SCORE_SUPERSTAR=Superster
+SING_SCORE_ULTRASTAR=ULTRASTAR
+
+SING_TOP_5_CHARTS=top 5 Spelers
+SING_TOP_5_CHARTS_WHEREAMI=top 5
+SING_TOP_5_CHARTS_CONTINUE=Ga Verder
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=perfect!
+POPUP_AWESOME=ongelooflijk!
+POPUP_GREAT=fantastisch!
+POPUP_GOOD=goed!
+POPUP_NOTBAD=niet slecht!
+POPUP_BAD=slecht!
+POPUP_POOR=zwak!
+POPUP_AWFUL=pijnlijk!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= en
+
+SONG_MENU_NAME_MAIN=Liedjes Menu
+SONG_MENU_PLAY=Zingen
+SONG_MENU_CHANGEPLAYERS=Verander de spelers
+SONG_MENU_EDIT=Bewerken
+SONG_MENU_MODI=Zing een Mode
+SONG_MENU_CANCEL=Cancel
+
+SONG_MENU_NAME_PLAYLIST=Liedjes Menu
+SONG_MENU_PLAYLIST_ADD=Voeg een liedje toe
+SONG_MENU_PLAYLIST_DEL=Verwijder Liedje
+
+SONG_MENU_NAME_PLAYLIST_ADD=Voeg een liedje toe
+SONG_MENU_PLAYLIST_ADD_NEW=aan een nieuwe Playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=aan een bestaande playlist
+SONG_MENU_PLAYLIST_NOEXISTING=Geen playlist beschikbaar
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nieuwe Playlist
+SONG_MENU_PLAYLIST_NEW_CREATE=Maak aan
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Zonder naam
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Wil je dit echt verwijderen?
+SONG_MENU_YES=Ja
+SONG_MENU_NO=Nee
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Open Playlist
+SONG_MENU_PLAYLIST_LOAD=open
+SONG_MENU_PLAYLIST_DELCURRENT=Verwijder huidige Playlist
+
+SONG_MENU_NAME_PLAYLIST_DEL=Verwijder de Playlist?
+
+SONG_MENU_NAME_PARTY_MAIN=Party Menu
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=Joker inzetten?
+
+SONG_JUMPTO_DESC=Zoek liedje
+SONG_JUMPTO_TYPE_DESC=Zoek naar:
+SONG_JUMPTO_TYPE1=Alles
+SONG_JUMPTO_TYPE2=Titel
+SONG_JUMPTO_TYPE3=Artiest
+SONG_JUMPTO_SONGSFOUND=%d Liedje(s) gevonden
+SONG_JUMPTO_NOSONGSFOUND=Niks gevonden
+SONG_JUMPTO_HELP=Typ waarnaar moet gezocht worden
+SONG_JUMPTO_CATTEXT=Zoek naar: %s
+
+PARTY_MODE=party mode
+PARTY_DIFFICULTY=Moeilijkheidsgraad
+PARTY_PLAYLIST=Playlist Mode
+PARTY_PLAYLIST_ALL=Alle liedjes
+PARTY_PLAYLIST_CATEGORY=Map
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_TEAMS=Teams
+PARTY_TEAMS_PLAYER1=Speler Team1
+PARTY_TEAMS_PLAYER2=Speler Team2
+PARTY_TEAMS_PLAYER3=Speler Team3
+
+PARTY_LEGEND_CONTINUE=Ga Verder
+
+PARTY_OPTIONS_DESC=Instellingen voor het Partyspelletje
+PARTY_OPTIONS_WHEREAMI=Party Opties
+
+PARTY_PLAYER_DESC=Kies Speler en Teamnamen
+PARTY_PLAYER_WHEREAMI=Party Namen
+PARTY_PLAYER_ENTER_NAME=Kies de namen
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE==start partyspelletje
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=Volgende spelers aan de Microfoon
+PARTY_ROUND_WHEREAMI=Party Volgende ronde
+PARTY_ROUND_LEGEND_CONTINUE=start de ronde
+
+PARTY_SONG_WHEREAMI=Party Song-Selectie
+PARTY_SONG_LEGEND_CONTINUE=Zing
+PARTY_SONG_MENU=partymenu
+
+PARTY_SCORE_DESC=score van de laatste ronde
+PARTY_SCORE_WHEREAMI=Partypunten
+
+PARTY_WIN_DESC=winnaar van de party-game
+PARTY_WIN_WHEREAMI=Party Winnaar
+PARTY_WIN_LEGEND_CONTINUE=Terug naar het hoofdmenu
+
+PARTY_ROUND=Ronde
+PARTY_ROUND_WINNER=Winnaar
+PARTY_NOTPLAYEDYET=Nog niet gespeeld
+PARTY_NOBODY=niemand
+NEXT_ROUND=Volgende Ronde:
+
+PARTY_DISMISSED=Uitgeschakeld!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=overwinningen!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Hold the Line
+MODE_HOLDTHELINE_DESC=Zing niet slechter dan het pijltje aangeeft!
+
+MODE_5000POINTS_NAME=Tot 5000
+MODE_5000POINTS_DESC=De eerste aan 5000 wint.
+
+MODE_DUEL_NAME=Duel
+MODE_DUEL_DESC=Zing een duel to 10000 punten.
+
+MODE_TEAMDUEL_NAME=Team Duel
+MODE_TEAMDUEL_DESC=Geef de microfoon door!
+
+MODE_BLIND_NAME=Blinde Mode
+MODE_BLIND_DESC=Duel zonder de noten te zien.
+
+STAT_MAIN=Statistieken
+STAT_MAIN_DESC=Algemeen
+STAT_MAIN_WHEREAMI=Statistieken
+
+STAT_OVERVIEW_INTRO=%0:s Statistieken.  \n Laatst gereset op %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Liedjes(%3:d met Video), waarvan %1:d al gespeeld zijn en %2:d nog niet.\n Het populairste liedje is %5:s van %4:s.
+STAT_OVERVIEW_PLAYER=Sinds de laatste reset waren er %0:d verschillende spelers.\n De beste speler is %1:s met een gemiddelde score van %2:d punten.\n %3:s had de hoogste score met %4:d punten.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statistieken
+STAT_DETAIL_WHEREAMI=Gedetailleerde statistieken
+
+STAT_NEXT=Volgende Pagina
+STAT_PREV=Vorige Pagina
+STAT_REVERSE=Omgekeerde Volgorde
+STAT_PAGE=Pagina %0:d van de %1:d Paginas\n (%2:d van de %3:d scores)
+
+STAT_DESC_SCORES=Topscore
+STAT_DESC_SCORES_REVERSED=Laagste scores
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Beste Spelers
+STAT_DESC_SINGERS_REVERSED=Slechtste Spelers
+STAT_FORMAT_SINGERS=%0:s \n Gemiddlede score: %1:d
+
+STAT_DESC_SONGS=Populairste liedje
+STAT_DESC_SONGS_REVERSED=Minst populaire liedjes
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx gezongen
+
+STAT_DESC_BANDS=Populairste Artiesten
+STAT_DESC_BANDS_REVERSED=Minst populaire artiesten
+STAT_FORMAT_BANDS=%0:s \n %1:dx gezongen
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Error
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Vraag
+MSG_QUIT_USDX=Uit met de pret?
+MSG_END_PARTY=Stoppen met de Party?
+
+ERROR_NO_SONGS=Geen liedjes geladen
+ERROR_NO_PLUGINS=Geen plugins geladen
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Liedje kon niet geladen worden
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Liedje kon niet geladen worden: File niet gevonden
+ERROR_CORRUPT_SONG_NO_NOTES=Liedje kon niet geladen worden: Geen noten gevonden
+ERROR_CORRUPT_SONG_NO_BREAKS=Liedje kon niet geladen worden: Geen linebreaks gevonden
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Liedje kon niet geladen worden: Probleem met regel %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Telling
+;UNUSED: PARTY_ROUNDS=Rondes
diff --git a/songmanagement/game/languages/English.ini b/songmanagement/game/languages/English.ini
new file mode 100644
index 00000000..775aedbb
--- /dev/null
+++ b/songmanagement/game/languages/English.ini
@@ -0,0 +1,442 @@
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+OPTION_VALUE_CZECH=Czech
+OPTION_VALUE_DANISH=Danish
+OPTION_VALUE_DUTCH=Dutch
+OPTION_VALUE_ENGLISH=English
+OPTION_VALUE_EUSKARA=Euskara
+OPTION_VALUE_FINNISH=Finnish
+OPTION_VALUE_FRENCH=French
+OPTION_VALUE_GERMAN=German
+OPTION_VALUE_GREEK=Greek
+OPTION_VALUE_HUNGARIAN=Hungarian
+OPTION_VALUE_ICELANDIC=Icelandic
+OPTION_VALUE_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_NORWEGIAN=Norwegian
+OPTION_VALUE_POLISH=Polish
+OPTION_VALUE_PORTUGUESE=Portuguese
+OPTION_VALUE_RUSSIAN=Russian
+OPTION_VALUE_SERBIAN=Serbian
+OPTION_VALUE_SLOVAK=Slovak
+OPTION_VALUE_SLOVENIAN=Slovenian
+OPTION_VALUE_SPANISH=Spanish
+OPTION_VALUE_SWEDISH=Swedish
+
+OPTION_VALUE_EASY=Easy
+OPTION_VALUE_MEDIUM=Medium
+OPTION_VALUE_HARD=Hard
+
+OPTION_VALUE_ON=On
+OPTION_VALUE_OFF=Off
+
+OPTION_VALUE_EDITION=Edition
+OPTION_VALUE_GENRE=Genre
+OPTION_VALUE_LANGUAGE=Language
+OPTION_VALUE_FOLDER=Folder
+OPTION_VALUE_TITLE=Title
+OPTION_VALUE_ARTIST=Artist
+OPTION_VALUE_TITLE2=Title2
+OPTION_VALUE_ARTIST2=Artist2
+
+OPTION_VALUE_WHENNOVIDEO=When No Video
+
+OPTION_VALUE_SMALL=Small
+OPTION_VALUE_BIG=Big
+
+OPTION_VALUE_HALF=Half
+OPTION_VALUE_FULL_VID=Full (Video)
+OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+OPTION_VALUE_AUTO=Auto
+OPTION_VALUE_SEC=Second
+OPTION_VALUE_SECS=Seconds
+
+OPTION_VALUE_PLAIN=Plain
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Simple
+OPTION_VALUE_ZOOM=Zoom
+OPTION_VALUE_SLIDE=Slide
+OPTION_VALUE_BALL=Ball
+OPTION_VALUE_SHIFT=Shift
+
+OPTION_VALUE_EURO=Euro
+OPTION_VALUE_JAPAN=Japan
+OPTION_VALUE_AMERICAN=American
+
+OPTION_VALUE_BLUE=Blue
+OPTION_VALUE_GREEN=Green
+OPTION_VALUE_PINK=Pink
+OPTION_VALUE_RED=Red
+OPTION_VALUE_VIOLET=Violet
+OPTION_VALUE_ORANGE=Orange
+OPTION_VALUE_YELLOW=Yellow
+OPTION_VALUE_BROWN=Brown
+OPTION_VALUE_BLACK=Black
+
+OPTION_VALUE_SING=Sing
+OPTION_VALUE_SELECT_PLAYERS=Select Players
+OPTION_VALUE_OPEN_MENU=Open Menu
+
+OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Loading...
+
+SING_CHOOSE_MODE=choose mode
+SING_SING=sing
+SING_SING_DESC=quick game: sing solo or duet
+
+SING_MULTI=party
+SING_MULTI_DESC=sing in party-mode
+
+SING_TOOLS=tools
+
+SING_STATS=stats
+SING_STATS_DESC=view the statistics
+
+SING_EDITOR=editor
+SING_EDITOR_DESC=create your own song
+
+SING_GAME_OPTIONS=game options
+SING_GAME_OPTIONS_DESC=change game settings
+
+SING_EXIT=quit
+SING_EXIT_DESC=quit game
+
+SING_OPTIONS=options
+SING_OPTIONS_DESC=change settings
+SING_OPTIONS_WHEREAMI=Options
+
+SING_OPTIONS_GAME=game
+SING_OPTIONS_GRAPHICS=graphics
+SING_OPTIONS_SOUND=sound
+SING_OPTIONS_LYRICS=lyrics
+SING_OPTIONS_THEMES=themes
+SING_OPTIONS_RECORD=record
+SING_OPTIONS_ADVANCED=advanced
+SING_OPTIONS_EXIT=back
+
+SING_OPTIONS_GAME_WHEREAMI=Options Game
+SING_OPTIONS_GAME_DESC=general game settings
+SING_OPTIONS_GAME_PLAYERS=Players
+SING_OPTIONS_GAME_DIFFICULTY=Difficulty
+SING_OPTIONS_GAME_LANGUAGE=Language
+SING_OPTIONS_GAME_TABS=Tabs
+SING_OPTIONS_GAME_SORTING=Sorting
+SING_OPTIONS_GAME_DEBUG=Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Options Graphics
+SING_OPTIONS_GRAPHICS_DESC=graphic settings
+SING_OPTIONS_GRAPHICS_RESOLUTION=Resolution
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Fullscreen
+SING_OPTIONS_GRAPHICS_DEPTH=Depth
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualization
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloscope
+SING_OPTIONS_GRAPHICS_LINEBONUS=Line Bonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Movie size
+
+SING_OPTIONS_SOUND_WHEREAMI=Options Sound
+SING_OPTIONS_SOUND_DESC=sound settings
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Microphone Playback
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Background music
+SING_OPTIONS_SOUND_MIC_BOOST=Mic boost
+SING_OPTIONS_SOUND_CLICK_ASSIST=Click assist
+SING_OPTIONS_SOUND_BEAT_CLICK=Beat click
+SING_OPTIONS_SOUND_THRESHOLD=Threshold
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Two players mode
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Preview Volume
+SING_OPTIONS_SOUND_PREVIEWFADING=Preview Fading
+
+SING_OPTIONS_LYRICS_WHEREAMI=Options Lyrics
+SING_OPTIONS_LYRICS_DESC=lyrics settings
+SING_OPTIONS_LYRICS_FONT=Font
+SING_OPTIONS_LYRICS_EFFECT=Effect
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmization
+SING_OPTIONS_LYRICS_NOTELINES=Staves
+
+SING_OPTIONS_THEMES_WHEREAMI=Options Themes
+SING_OPTIONS_THEMES_DESC=theme and skin settings
+SING_OPTIONS_THEMES_THEME=Theme
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Color
+
+SING_OPTIONS_RECORD_WHEREAMI=Options Record
+SING_OPTIONS_RECORD_DESC=microphone settings
+SING_OPTIONS_RECORD_CARD=Soundcard
+SING_OPTIONS_RECORD_INPUT=Input
+SING_OPTIONS_RECORD_CHANNEL=Channel
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Options Advanced
+SING_OPTIONS_ADVANCED_DESC=advanced settings
+SING_OPTIONS_ADVANCED_EFFECTSING=Sing Effects
+SING_OPTIONS_ADVANCED_SCREENFADE=Screen Fading
+SING_OPTIONS_ADVANCED_LOADANIMATION=Load Animation
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Safety Questions
+SING_OPTIONS_ADVANCED_LINEBONUS=Line Bonus
+;SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=
+SING_OPTIONS_ADVANCED_ONSONGCLICK=after Song Select
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto PartyMenu
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=create your own song
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Import text from midi file
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=back
+SING_EDIT_BUTTON_CONVERT=Import
+SING_EDIT_BUTTON_EXIT=back
+
+SING_EDIT_NAVIGATE=navigate
+SING_EDIT_SELECT=select
+SING_EDIT_EXIT=back
+
+SING_LEGEND_SELECT=select
+SING_LEGEND_NAVIGATE=navigate
+SING_LEGEND_CONTINUE=continue
+SING_LEGEND_ESC=back
+
+SING_PLAYER_DESC=enter player name/s
+SING_PLAYER_WHEREAMI=Playernames
+SING_PLAYER_ENTER_NAME=enter name
+
+SING_DIFFICULTY_DESC=select difficulty
+SING_DIFFICULTY_WHEREAMI=Difficulty
+SING_DIFFICULTY_CONTINUE=to song selection
+SING_EASY=Easy
+SING_MEDIUM=Medium
+SING_HARD=Hard
+
+SING_SONG_SELECTION_DESC=choose your song
+SING_SONG_SELECTION_WHEREAMI=Song Selection
+SING_SONG_SELECTION_GOTO=go to ..
+SING_SONG_SELECTION=song selection
+SING_SONG_SELECTION_MENU=menu
+SING_SONG_SELECTION_PLAYLIST=playlist
+SING_SONGS_IN_CAT=Songs
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=TIME
+SING_TOTAL=total
+SING_MODE=sing solo
+SING_NOTES=notes
+SING_GOLDEN_NOTES=golden notes
+SING_PHRASE_BONUS=line bonus
+
+SING_MENU=Main Menu
+
+SONG_SCORE=song score
+SONG_SCORE_WHEREAMI=Score
+
+SING_SCORE_TONE_DEAF=Tone Deaf
+SING_SCORE_AMATEUR=Amateur
+SING_SCORE_WANNABE=Wannabe
+SING_SCORE_HOPEFUL=Hopeful
+SING_SCORE_RISING_STAR=Rising Star
+SING_SCORE_LEAD_SINGER=Lead Singer
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=top 5 Players
+SING_TOP_5_CHARTS_WHEREAMI=top 5
+SING_TOP_5_CHARTS_CONTINUE=to song selection
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=perfect!
+POPUP_AWESOME=awesome!
+POPUP_GREAT=great!
+POPUP_GOOD=good!
+POPUP_NOTBAD=not bad!
+POPUP_BAD=bad!
+POPUP_POOR=poor!
+POPUP_AWFUL=awful!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= and
+
+SONG_MENU_NAME_MAIN=song menu
+SONG_MENU_PLAY=Sing
+SONG_MENU_CHANGEPLAYERS=Change Players
+SONG_MENU_EDIT=Edit
+SONG_MENU_MODI=Sing a Modi
+SONG_MENU_CANCEL=Cancel
+
+SONG_MENU_NAME_PLAYLIST=Song Menu
+SONG_MENU_PLAYLIST_ADD=Add Song
+SONG_MENU_PLAYLIST_DEL=Delete Song
+
+SONG_MENU_NAME_PLAYLIST_ADD=Add Song
+SONG_MENU_PLAYLIST_ADD_NEW=to new playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=to existing playlist
+SONG_MENU_PLAYLIST_NOEXISTING=No playlist available
+
+SONG_MENU_NAME_PLAYLIST_NEW=New Playlist
+SONG_MENU_PLAYLIST_NEW_CREATE=Create
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Unnamed
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Really Delete?
+SONG_MENU_YES=Yes
+SONG_MENU_NO=No
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Open Playlist
+SONG_MENU_PLAYLIST_LOAD=open
+SONG_MENU_PLAYLIST_DELCURRENT=delete current Playlist
+
+SONG_MENU_NAME_PLAYLIST_DEL=Delete Playlist?
+
+SONG_MENU_NAME_PARTY_MAIN=Party Menu
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=take joker
+
+SONG_JUMPTO_DESC=search song
+SONG_JUMPTO_TYPE_DESC=Search for:
+SONG_JUMPTO_TYPE1=All
+SONG_JUMPTO_TYPE2=Title
+SONG_JUMPTO_TYPE3=Artist
+SONG_JUMPTO_SONGSFOUND=%d Song(s) found
+SONG_JUMPTO_NOSONGSFOUND=No Song found
+SONG_JUMPTO_HELP=Type Text to Search for
+SONG_JUMPTO_CATTEXT=Search for: %s
+
+PARTY_MODE=party mode
+PARTY_DIFFICULTY=Difficulty
+PARTY_PLAYLIST=Playlist Mode
+PARTY_PLAYLIST_ALL=All songs
+PARTY_PLAYLIST_CATEGORY=Folder
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_TEAMS=number of teams
+PARTY_TEAMS_PLAYER1=num. of singers
+PARTY_TEAMS_PLAYER2=num. of singers
+PARTY_TEAMS_PLAYER3=num. of singers
+
+PARTY_LEGEND_CONTINUE=continue
+
+PARTY_OPTIONS_DESC=settings for the party-game
+PARTY_OPTIONS_WHEREAMI=Party Options
+
+PARTY_PLAYER_DESC=enter player- and teamnames!
+PARTY_PLAYER_WHEREAMI=Party Names
+PARTY_PLAYER_ENTER_NAME=enter names
+
+
+PARTY_ROUNDS_DESC=select which modes you want to play
+PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=start party-game
+PARTY_ROUNDCOUNT=number of rounds
+PARTY_SELECTMODE1=mode round 1
+PARTY_SELECTMODE2=mode round 2
+PARTY_SELECTMODE3=mode round 3
+PARTY_SELECTMODE4=mode round 4
+PARTY_SELECTMODE5=mode round 5
+PARTY_SELECTMODE6=mode round 6
+PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=next players to the mics
+PARTY_ROUND_WHEREAMI=Party Next Round
+PARTY_ROUND_LEGEND_CONTINUE=start round
+
+PARTY_SONG_WHEREAMI=Party Song-Selection
+PARTY_SONG_LEGEND_CONTINUE=sing
+PARTY_SONG_MENU=party menu
+
+PARTY_SCORE_DESC=score of the last round
+PARTY_SCORE_WHEREAMI=Party Points
+
+PARTY_WIN_DESC=winner of the party-game
+PARTY_WIN_WHEREAMI=Party Winner
+PARTY_WIN_LEGEND_CONTINUE=back to main-menu
+
+PARTY_ROUND=Round
+PARTY_ROUND_WINNER=Winner
+PARTY_NOTPLAYEDYET=not played yet
+PARTY_NOBODY=nobody
+NEXT_ROUND=Next round:
+
+PARTY_DISMISSED=Dismissed!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=wins!
+
+MODE_RANDOM_NAME=Random Mode
+MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Hold the Line
+MODE_HOLDTHELINE_DESC=Don't get worse than the pointer at the rating bar shows you.
+
+MODE_5000POINTS_NAME=Until 5000
+MODE_5000POINTS_DESC=Who gets 5000 points first wins the match.
+
+MODE_DUEL_NAME=Duel
+MODE_DUEL_DESC=Sing a duel until 10000 points.
+
+MODE_TEAMDUEL_NAME=Team Duell
+MODE_TEAMDUEL_DESC=Pass The Mic!
+
+MODE_BLIND_NAME=Blind Mode
+MODE_BLIND_DESC=Duel without seeing the notes.
+
+STAT_MAIN=Statistics
+STAT_MAIN_DESC=General
+STAT_MAIN_WHEREAMI=Statistics
+
+STAT_OVERVIEW_INTRO=%0:s Statistics.  \n Last Reset at %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Songs(%3:d with Video), whereof %1:d already were played  and %2:d were not played yet.\n The most popular Song is %5:s from %4:s.
+STAT_OVERVIEW_PLAYER=Since the last Reset there were/was %0:d different Player(s).\n The best Player is %1:s with an average Score of %2:d Points.\n %3:s did the highest Score with %4:d Points.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statistics
+STAT_DETAIL_WHEREAMI=Detail Statistics
+
+STAT_NEXT=Next Page
+STAT_PREV=Previous Page
+STAT_REVERSE=Reverse Order
+STAT_PAGE=page %0:d of %1:d pages\n (%2:d of %3:d Entrys)
+
+STAT_DESC_SCORES=HighScores
+STAT_DESC_SCORES_REVERSED=LowScores
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Best Singers
+STAT_DESC_SINGERS_REVERSED=Worst Singers
+STAT_FORMAT_SINGERS=%0:s \n Average Score: %1:d
+
+STAT_DESC_SONGS=Most popular Songs
+STAT_DESC_SONGS_REVERSED=Least popular Songs
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx sung
+
+STAT_DESC_BANDS=Most popular Bands
+STAT_DESC_BANDS_REVERSED=Least popular Bands
+STAT_FORMAT_BANDS=%0:s \n %1:dx Sung
+
+SCREENSHOT_SAVED=Screenshot saved
+SCREENSHOT_FAILED=Couldn''t save screenshot
+
+INFO_FILE_SAVED=File saved
+ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+ERROR_FILE_NOT_FOUND=File not found
+
+ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Error
+MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Question
+MSG_QUIT_USDX=Really leave UltraStar?
+MSG_END_PARTY=Really leave Party Mode?
+
+ERROR_NO_SONGS=No Songs loaded
+ERROR_NO_PLUGINS=No Plugins loaded
+ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Song could not be loaded.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Song could not be loaded: File not found
+ERROR_CORRUPT_SONG_NO_NOTES=Song could not be loaded: Can''t find any notes
+ERROR_CORRUPT_SONG_NO_BREAKS=Song could not be loaded: Can''t find any linebreaks
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Song could not be loaded: Error parsing line %0:d
+ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
diff --git a/songmanagement/game/languages/Euskara.ini b/songmanagement/game/languages/Euskara.ini
new file mode 100644
index 00000000..496dad5b
--- /dev/null
+++ b/songmanagement/game/languages/Euskara.ini
@@ -0,0 +1,441 @@
+[Text]
+OPTION_VALUE_CATALAN=Katalana
+OPTION_VALUE_CROATIAN=Kroaziera
+OPTION_VALUE_CZECH=Txekiarra
+OPTION_VALUE_DANISH=Daniera
+OPTION_VALUE_DUTCH=Nederlandera
+OPTION_VALUE_ENGLISH=Ingelesa
+OPTION_VALUE_EUSKARA=Euskara
+OPTION_VALUE_FINNISH=Finlandiera
+OPTION_VALUE_FRENCH=Frantseza
+OPTION_VALUE_GERMAN=Alemaniera
+OPTION_VALUE_GREEK=Greziera
+OPTION_VALUE_HUNGARIAN=Hungarian
+OPTION_VALUE_ICELANDIC=Icelandic
+OPTION_VALUE_ITALIAN=Italianoa
+OPTION_VALUE_JAPANESE=Japoniera
+OPTION_VALUE_LUXEMBOURGISH=Luxenburgera
+OPTION_VALUE_NORWEGIAN=Norvegiera
+OPTION_VALUE_POLISH=Poloniera
+OPTION_VALUE_PORTUGUESE=Portuguesa
+OPTION_VALUE_RUSSIAN=Errusiera
+OPTION_VALUE_SERBIAN=Serbiera
+OPTION_VALUE_SLOVAK=Eslovakiera
+OPTION_VALUE_SLOVENIAN=Esloveniera
+OPTION_VALUE_SPANISH=Erdara
+OPTION_VALUE_SWEDISH=Suediera
+
+OPTION_VALUE_EASY=Erraza
+OPTION_VALUE_MEDIUM=Bitartekoa
+OPTION_VALUE_HARD=Zaila
+
+OPTION_VALUE_ON=On
+OPTION_VALUE_OFF=Off
+
+OPTION_VALUE_EDITION=Edizioa
+OPTION_VALUE_GENRE=Generoa
+OPTION_VALUE_LANGUAGE=Hizkuntza
+OPTION_VALUE_FOLDER=Fitxategia
+OPTION_VALUE_TITLE=Titulua
+OPTION_VALUE_ARTIST=Artista
+OPTION_VALUE_TITLE2=2.titulua
+OPTION_VALUE_ARTIST2=2.artista
+
+OPTION_VALUE_WHENNOVIDEO=Bideorik ez badago
+
+OPTION_VALUE_SMALL=Txikia
+OPTION_VALUE_BIG=Handia
+
+OPTION_VALUE_HALF=Erdia
+OPTION_VALUE_FULL_VID=Osoa (Bideoa)
+OPTION_VALUE_FULL_VID_BG=Osoa (BG eta bideoa)
+
+OPTION_VALUE_AUTO=Automatikoa
+OPTION_VALUE_SEC=Segundu
+OPTION_VALUE_SECS=Segundu
+
+OPTION_VALUE_PLAIN=Plain
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Arrunta
+OPTION_VALUE_ZOOM=Zoom-a
+OPTION_VALUE_SLIDE=Slide-a
+OPTION_VALUE_BALL=Baloia
+OPTION_VALUE_SHIFT=Shift-a
+
+OPTION_VALUE_EURO=Europearra
+OPTION_VALUE_JAPAN=Japoniarra
+OPTION_VALUE_AMERICAN=Amerikarra
+
+OPTION_VALUE_BLUE=Urdina
+OPTION_VALUE_GREEN=Berdea
+OPTION_VALUE_PINK=Arrosa
+OPTION_VALUE_RED=Gorria
+OPTION_VALUE_VIOLET=Morea
+OPTION_VALUE_ORANGE=Laranja
+OPTION_VALUE_YELLOW=Horia
+OPTION_VALUE_BROWN=Marroia
+OPTION_VALUE_BLACK=Beltza
+
+OPTION_VALUE_SING=Abestu
+OPTION_VALUE_SELECT_PLAYERS=Aukeratu jokalariak
+OPTION_VALUE_OPEN_MENU=Menua zabaldu
+
+OPTION_VALUE_HARDWARE_CURSOR=Hardware kurtsorea
+OPTION_VALUE_SOFTWARE_CURSOR=Software kurtsorea
+
+SING_LOADING=Kargatzen...
+
+SING_CHOOSE_MODE=Aukeratu
+SING_SING=Abestu
+SING_SING_DESC=Abestu: bakarka edo binaka
+
+SING_MULTI=Taldea
+SING_MULTI_DESC=Taldean abestu
+
+SING_TOOLS=Tresnak
+
+SING_STATS=Estatistikak
+SING_STATS_DESC=Estatistikak ikusi
+
+SING_EDITOR=Editorea
+SING_EDITOR_DESC=Zure kantuak sortu
+
+SING_GAME_OPTIONS=Hobespenak
+SING_GAME_OPTIONS_DESC=Jokoaren hobespenak aldatu
+
+SING_EXIT=Irten
+SING_EXIT_DESC=Jokotik irten
+
+SING_OPTIONS=Hobespenak
+SING_OPTIONS_DESC=Aukerak aldatu
+SING_OPTIONS_WHEREAMI=Hobespenak
+
+SING_OPTIONS_GAME=Jokoa
+SING_OPTIONS_GRAPHICS=Grafikoak
+SING_OPTIONS_SOUND=Soinua
+SING_OPTIONS_LYRICS=Letrak
+SING_OPTIONS_THEMES=Gaiak
+SING_OPTIONS_RECORD=Grabazioa
+SING_OPTIONS_ADVANCED=Aurreratuak
+SING_OPTIONS_EXIT=Itzuli
+
+SING_OPTIONS_GAME_WHEREAMI=Jokoaren hobespenak
+SING_OPTIONS_GAME_DESC=Jokoaren hobespen orokorrak
+SING_OPTIONS_GAME_PLAYERS=Jokalariak
+SING_OPTIONS_GAME_DIFFICULTY=Zailtasuna
+SING_OPTIONS_GAME_LANGUAGE=Hizkuntza
+SING_OPTIONS_GAME_TABS=Etiketak
+SING_OPTIONS_GAME_SORTING=Sailkapena
+SING_OPTIONS_GAME_DEBUG=Araztu
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Grafikoen hobespenak
+SING_OPTIONS_GRAPHICS_DESC=Grafikoen hobespenak
+SING_OPTIONS_GRAPHICS_RESOLUTION=Erresoluzioa
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Pantaila osoa
+SING_OPTIONS_GRAPHICS_DEPTH=Kolore kalitatea
+SING_OPTIONS_GRAPHICS_VISUALIZER=Bistaratzeak
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Osziloskopioa
+SING_OPTIONS_GRAPHICS_LINEBONUS=Lerro Bonusa
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Bideo tamaina
+
+SING_OPTIONS_SOUND_WHEREAMI=Soinu hobespenak
+SING_OPTIONS_SOUND_DESC=Soinu hobespenak
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Mikrofono playback-a
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Atzeko soinua
+SING_OPTIONS_SOUND_MIC_BOOST=Mikrofonoa indartu
+SING_OPTIONS_SOUND_CLICK_ASSIST=Noten laguntza
+SING_OPTIONS_SOUND_BEAT_CLICK=Kolpeen laguntza
+SING_OPTIONS_SOUND_THRESHOLD=Arintzea
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Bi jokalari modua
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Bolumena aurreikusi
+SING_OPTIONS_SOUND_PREVIEWFADING=Desagerpena aurreikusi
+
+SING_OPTIONS_LYRICS_WHEREAMI=Letren hobespenak
+SING_OPTIONS_LYRICS_DESC=Letren hobespenak
+SING_OPTIONS_LYRICS_FONT=Letra-mota
+SING_OPTIONS_LYRICS_EFFECT=Efektua
+SING_OPTIONS_LYRICS_SOLMIZATION=Solfeoa
+SING_OPTIONS_LYRICS_NOTELINES=Pentagramak
+
+SING_OPTIONS_THEMES_WHEREAMI=Gaien hobespenak
+SING_OPTIONS_THEMES_DESC=Gaien eta azalen hobespenak
+SING_OPTIONS_THEMES_THEME=Gaia
+SING_OPTIONS_THEMES_SKIN=Azala
+SING_OPTIONS_THEMES_COLOR=Kolorea
+
+SING_OPTIONS_RECORD_WHEREAMI=Grabazioaren hobespenak
+SING_OPTIONS_RECORD_DESC=Mikrofonoaren hobespenak
+SING_OPTIONS_RECORD_CARD=Soinu-txartela
+SING_OPTIONS_RECORD_INPUT=Sarrera
+SING_OPTIONS_RECORD_CHANNEL=Kanala
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Hobespen aurreratuak
+SING_OPTIONS_ADVANCED_DESC=Hobespen aurreratuak
+SING_OPTIONS_ADVANCED_EFFECTSING=Kantu efektuak
+SING_OPTIONS_ADVANCED_SCREENFADE=Pantaila desagertu
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animazioa kargatzerakoan
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Ziurtasun galderak
+SING_OPTIONS_ADVANCED_LINEBONUS=Lerro bonusa
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Aukeratu ondoren
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Talde menu auto
+
+SING_EDIT=Editorea
+SING_EDIT_MENU_DESCRIPTION=Zure kantuak sortu
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Testua inportatu MIDI fitxategiatik
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Itzuli
+SING_EDIT_BUTTON_CONVERT=Inportatu
+SING_EDIT_BUTTON_EXIT=Itzuli
+
+SING_EDIT_NAVIGATE=Nabigatu
+SING_EDIT_SELECT=Aukeratu
+SING_EDIT_EXIT=Itzuli
+
+SING_LEGEND_SELECT=Hautatu
+SING_LEGEND_NAVIGATE=Nabigatu
+SING_LEGEND_CONTINUE=Jarraitu
+SING_LEGEND_ESC=Itzuli
+
+SING_PLAYER_DESC=Jokalarien izenak sartu
+SING_PLAYER_WHEREAMI=Jokalarien izenak
+SING_PLAYER_ENTER_NAME=Izenak idatzi
+
+SING_DIFFICULTY_DESC=Zailtasuna aukeratu
+SING_DIFFICULTY_WHEREAMI=Zailtasuna
+SING_DIFFICULTY_CONTINUE=Abestia aukeratu
+SING_EASY=Erraza
+SING_MEDIUM=Bitartekoa
+SING_HARD=Zaila
+
+SING_SONG_SELECTION_DESC=Abestia aukeratu
+SING_SONG_SELECTION_WHEREAMI=Abestia aukeratu
+SING_SONG_SELECTION_GOTO=... joan
+SING_SONG_SELECTION=Abestia aukeratu
+SING_SONG_SELECTION_MENU=Menu
+SING_SONG_SELECTION_PLAYLIST=Zerrenda
+SING_SONGS_IN_CAT=Abestiak
+PLAYLIST_CATTEXT=Zerrenda: %s
+
+SING_TIME=Denbora
+SING_TOTAL=Guztira
+SING_MODE=Bakarka abestu
+SING_NOTES=Notak
+SING_GOLDEN_NOTES=Urrezko notak
+SING_PHRASE_BONUS=Lerro bonusa
+
+SING_MENU=Menu nagusia
+
+SONG_SCORE=Puntuazioa
+SONG_SCORE_WHEREAMI=Puntuazioa
+
+SING_SCORE_TONE_DEAF=Desafinatua
+SING_SCORE_AMATEUR=Amateur
+SING_SCORE_WANNABE=Etorkizuneko Izarra
+SING_SCORE_HOPEFUL=Hautagaia
+SING_SCORE_RISING_STAR=Hobetuz Zoaz
+SING_SCORE_LEAD_SINGER=Kantari Handia
+SING_SCORE_SUPERSTAR=SuperStar
+SING_SCORE_ULTRASTAR=UltraStar
+
+SING_TOP_5_CHARTS=5 hoberenak
+SING_TOP_5_CHARTS_WHEREAMI=5 hoberenak
+SING_TOP_5_CHARTS_CONTINUE=Abestia aukeratu
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=Bikain!
+POPUP_AWESOME=Txundigarri!
+POPUP_GREAT=Sekulakoa!
+POPUP_GOOD=Ongi!
+POPUP_NOTBAD=Ez dago gaizki!
+POPUP_BAD=Gaizki!
+POPUP_POOR=Eskas!
+POPUP_AWFUL=Penagarri!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= eta
+
+SONG_MENU_NAME_MAIN=Menua
+SONG_MENU_PLAY=Abestu
+SONG_MENU_CHANGEPLAYERS=Jokalariak aukeratu
+SONG_MENU_EDIT=Editorera bidali
+SONG_MENU_MODI=Modi bat abestu
+SONG_MENU_CANCEL=Itzuli
+
+SONG_MENU_NAME_PLAYLIST=Menua
+SONG_MENU_PLAYLIST_ADD=Zerrendara gehitu
+SONG_MENU_PLAYLIST_DEL=Zerrendatik ezabatu
+
+SONG_MENU_NAME_PLAYLIST_ADD=Abestia gehitu
+SONG_MENU_PLAYLIST_ADD_NEW=Zerrenda berrira
+SONG_MENU_PLAYLIST_ADD_EXISTING=Zerrendara
+SONG_MENU_PLAYLIST_NOEXISTING=Ez dago zerrendarik
+
+SONG_MENU_NAME_PLAYLIST_NEW=Zerrenda berria
+SONG_MENU_PLAYLIST_NEW_CREATE=Sortu
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Izengabea
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Ezabatu?
+SONG_MENU_YES=Bai
+SONG_MENU_NO=Ez
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Zerrenda ireki
+SONG_MENU_PLAYLIST_LOAD=Ireki
+SONG_MENU_PLAYLIST_DELCURRENT=Zerrenda hau ezabatu
+
+SONG_MENU_NAME_PLAYLIST_DEL=Zerrenda ezabatu?
+
+SONG_MENU_NAME_PARTY_MAIN=Talde menua
+SONG_MENU_JOKER=Komodina
+
+SONG_MENU_NAME_PARTY_JOKER=Komodina erabili
+
+SONG_JUMPTO_DESC=Bilatu
+SONG_JUMPTO_TYPE_DESC=Bilatu:
+SONG_JUMPTO_TYPE1=Guztia
+SONG_JUMPTO_TYPE2=Titulua
+SONG_JUMPTO_TYPE3=Artista
+SONG_JUMPTO_SONGSFOUND=%d kantu aurkituta
+SONG_JUMPTO_NOSONGSFOUND=Ez dago kanturik
+SONG_JUMPTO_HELP=Hitz gakoak idatzi
+SONG_JUMPTO_CATTEXT=Bilatu: %s
+
+PARTY_MODE=Taldean Abestu
+PARTY_DIFFICULTY=Zailtasuna
+PARTY_PLAYLIST=Abestiak
+PARTY_PLAYLIST_ALL=Guztiak
+PARTY_PLAYLIST_CATEGORY=Karpeta
+PARTY_PLAYLIST_PLAYLIST=Zerrenda
+PARTY_TEAMS=Taldeak
+PARTY_TEAMS_PLAYER1=Jokalariak 1.an
+PARTY_TEAMS_PLAYER2=Jokalariak 2.an
+PARTY_TEAMS_PLAYER3=Jokalariak 3.an
+
+PARTY_LEGEND_CONTINUE=Jarraitu
+
+PARTY_OPTIONS_DESC=Taldean jokatzeko aukerak
+PARTY_OPTIONS_WHEREAMI=Taldeko hobespenak
+
+PARTY_PLAYER_DESC=Jokalarien eta taldeen izenak
+PARTY_PLAYER_WHEREAMI=Taldeen izenak
+PARTY_PLAYER_ENTER_NAME=Izenak idatzi
+
+
+PARTY_ROUNDS_DESC=Aukeratu zein modurekin jokatu nahi duzun
+PARTY_ROUNDS_WHEREAMI=Errondak
+PARTY_ROUNDS_LEGEND_CONTINUE==Jokoa hasi
+PARTY_ROUNDCOUNT=Erronda kopurua
+PARTY_SELECTMODE1=1.errondaren modua
+PARTY_SELECTMODE2=2.errondaren modua
+PARTY_SELECTMODE3=3.errondaren modua
+PARTY_SELECTMODE4=4.errondaren modua
+PARTY_SELECTMODE5=5.errondaren modua
+PARTY_SELECTMODE6=6.errondaren modua
+PARTY_SELECTMODE7=7.errondaren modua
+
+PARTY_ROUND_DESC=Hurrengoa mikrofonora
+PARTY_ROUND_WHEREAMI=Hurrengo erronda
+PARTY_ROUND_LEGEND_CONTINUE=Erronda hasi
+
+PARTY_SONG_WHEREAMI=Talde Abestia aukeratu
+PARTY_SONG_LEGEND_CONTINUE=Abestu
+PARTY_SONG_MENU=Talde menua
+
+PARTY_SCORE_DESC=Azken Errondako puntuazioa
+PARTY_SCORE_WHEREAMI=Talde puntuazioa
+
+PARTY_WIN_DESC=Talde irabazlea
+PARTY_WIN_WHEREAMI=Talde jokoaren irabazlea
+PARTY_WIN_LEGEND_CONTINUE=Menu nagusira itzuli
+
+PARTY_ROUND=Erronda
+PARTY_ROUND_WINNER=Irabazlea
+PARTY_NOTPLAYEDYET=Jokatu gabe
+PARTY_NOBODY=Inor
+NEXT_ROUND=Hurrengo erronda:
+
+PARTY_DISMISSED=Galdu duzu!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=irabazi du!
+
+MODE_RANDOM_NAME=Ausazko modua
+MODE_RANDOM_DESC=Modu bat ausaz auketarua izango da
+
+MODE_HOLDTHELINE_NAME=Eutsi goiari
+MODE_HOLDTHELINE_DESC=Ez jaitsi markatutako puntuazio mailatik.
+
+MODE_5000POINTS_NAME=5000 arte
+MODE_5000POINTS_DESC=Azkarrena 5000 puntu lortzen irabazten du.
+
+MODE_DUEL_NAME=Duelua
+MODE_DUEL_DESC=Duelua 10.000 punturarte.
+
+MODE_TEAMDUEL_NAME=Talde duelua
+MODE_TEAMDUEL_DESC=Mikrofonoa pasa!
+
+MODE_BLIND_NAME=Itsuan
+MODE_BLIND_DESC=Duelua notak ikusi gabe.
+
+STAT_MAIN=Estatistikak
+STAT_MAIN_DESC=Orokorrak
+STAT_MAIN_WHEREAMI=Estatistikak
+
+STAT_OVERVIEW_INTRO=%0:s estatistikak.  \n Azken aldiz ezabatutak %3:dko %2:.2daren %1:.2dan
+STAT_OVERVIEW_SONG=%0:d abesti daude (%3:d bideoarekin), hauetatik %1:d dagoeneko abestu dira, %2:d oraindik ez dira abestu.\n Gehien abestu den kantua %5:s da, %4:s-ena.
+STAT_OVERVIEW_PLAYER=Azken aldiz ezabatu zirenetik, %0:d jokalari desberdin egon dira.\n Jokalari hoberena %1:s da %2:dko batezbesteko puntuazioarekin.\n %3:s puntuaziorik altuena lortu zuen, %4:d puntu.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Estatistikak
+STAT_DETAIL_WHEREAMI=Estatistika zehatzak
+
+STAT_NEXT=Hurrengo orria
+STAT_PREV=Aurreko orria
+STAT_REVERSE=Ordena alderanztu
+STAT_PAGE=Seite %0:d orri %1:dtik \n (%2:d sarrera %3:dtik)
+
+STAT_DESC_SCORES=Puntuazio onenak
+STAT_DESC_SCORES_REVERSED=Puntuazio txarrenak
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Jokalari onenak
+STAT_DESC_SINGERS_REVERSED=Jokalari txarrenak
+STAT_FORMAT_SINGERS=%0:s \n Batezbesteko puntuazioa: %1:d
+
+STAT_DESC_SONGS=Abesti ospetsuak
+STAT_DESC_SONGS_REVERSED=Abesti ez ospetsuak
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx aldiz abestuta
+
+STAT_DESC_BANDS=Talde ospetsuak
+STAT_DESC_BANDS_REVERSED=Talde ez ospetsuak
+STAT_FORMAT_BANDS=%0:s \n %1:dx aldiz abestuta
+
+SCREENSHOT_SAVED=Pantaila-irudia gordeta
+SCREENSHOT_FAILED=Pantaila irudia ezin izan da gorde
+
+INFO_FILE_SAVED=Fitxategia gordeta
+ERROR_SAVE_FILE_FAILED=Ezin izan da fitxategia gorde
+ERROR_FILE_NOT_FOUND=Fitxategia ez da aurkitu
+
+ENCODING_ERROR_ASK_FOR_UTF8=Ezin dira aldaketan kodeaketa honetan gorde izan. UTF-8-ra bihurtu?
+EDITOR_ERROR_NO_TRACK_SELECTED=Ez da abestirik aukeratu
+
+MSG_ERROR_TITLE=Hutsa
+MSG_INFO_TITLE=Informazioa
+MSG_QUESTION_TITLE=Galdera
+MSG_QUIT_USDX=Ziur zaude irten nahi duzula?
+MSG_END_PARTY=Ziur zaude talde jokoa bukatu nahi duzula?
+
+ERROR_NO_SONGS=Ez dago abestirik
+ERROR_NO_PLUGINS=Ez dago pluginik
+ERROR_NO_MODES_FOR_CURRENT_SETUP=Ez dago modu eskuragarririk jokalari/talde honetarako
+ERROR_CAN_NOT_START_PARTY=Errore bat gertatu da jokoa hastean
+ERROR_CORRUPT_SONG=Ezin da abestia kargatu
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Ezin da abestia kargatu: Fitxategia falta da
+ERROR_CORRUPT_SONG_NO_NOTES=Ezin da abestia kargatu: Ez daude notak
+ERROR_CORRUPT_SONG_NO_BREAKS=Ezin da abestia kargatu: Ez daude lerro jauziak
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Ezin da abestia kargatu: Okerra %0:d lerroan
+ERROR_NO_EDITOR=Ezaugarri hau ez dago Linux/Mac-en
+ERROR_PLAYER_DEVICE_ASSIGNMENT= %d.jokalariak mikrofono bat baino gehiago aukeratuta ditu . Mesedez grabazioaren aukerak begiratu
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphones. Mesedez grabazioaren aukerak begiratu
\ No newline at end of file
diff --git a/songmanagement/game/languages/Finnish.ini b/songmanagement/game/languages/Finnish.ini
new file mode 100644
index 00000000..7fb6dd19
--- /dev/null
+++ b/songmanagement/game/languages/Finnish.ini
@@ -0,0 +1,445 @@
+[Text]
+OPTION_VALUE_CATALAN=katalaani
+OPTION_VALUE_CROATIAN=kroatia
+OPTION_VALUE_CZECH=tsekki
+OPTION_VALUE_DANISH=tanska
+OPTION_VALUE_DUTCH=hollanti
+OPTION_VALUE_ENGLISH=englanti
+OPTION_VALUE_EUSKARA=baski
+OPTION_VALUE_FINNISH=suomi
+OPTION_VALUE_FRENCH=ranska
+OPTION_VALUE_GERMAN=saksa
+OPTION_VALUE_GREEK=kreikka
+OPTION_VALUE_HUNGARIAN=unkari
+OPTION_VALUE_ICELANDIC=islanti
+OPTION_VALUE_ITALIAN=italia
+OPTION_VALUE_JAPANESE=japani
+OPTION_VALUE_LUXEMBOURGISH=luxembourg
+OPTION_VALUE_NORWEGIAN=norja
+OPTION_VALUE_POLISH=puola
+OPTION_VALUE_PORTUGUESE=portugali
+OPTION_VALUE_RUSSIAN=venäjä
+OPTION_VALUE_SERBIAN=serbia
+OPTION_VALUE_SLOVAK=slovakki
+OPTION_VALUE_SLOVENIAN=slovenia
+OPTION_VALUE_SPANISH=espanja
+OPTION_VALUE_SWEDISH=ruotsi
+
+OPTION_VALUE_EASY=Helppo
+OPTION_VALUE_MEDIUM=Keskitaso
+OPTION_VALUE_HARD=Vaikea
+
+OPTION_VALUE_ON=Päällä
+OPTION_VALUE_OFF=Pois
+
+OPTION_VALUE_EDITION=Editio
+OPTION_VALUE_GENRE=Tyylilaji
+OPTION_VALUE_LANGUAGE=Kieli
+OPTION_VALUE_FOLDER=Hakemisto
+OPTION_VALUE_TITLE=Otsikko
+OPTION_VALUE_ARTIST=Artisti
+OPTION_VALUE_TITLE2=Otsikko2
+OPTION_VALUE_ARTIST2=Artisti2
+
+OPTION_VALUE_WHENNOVIDEO=Kun ei videota
+
+OPTION_VALUE_SMALL=Pieni
+OPTION_VALUE_BIG=Suuri
+
+OPTION_VALUE_HALF=Puoli
+OPTION_VALUE_FULL_VID=Kokoruutu (Video)
+OPTION_VALUE_FULL_VID_BG=Kokoruutu (tausta & Video)
+
+OPTION_VALUE_AUTO=Auto
+OPTION_VALUE_SEC=Sekunti
+OPTION_VALUE_SECS=Sekunnit
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+OPTION_VALUE_ZOOM=Zoomi
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+OPTION_VALUE_EURO=Europpalainen
+OPTION_VALUE_JAPAN=Japanilainen
+OPTION_VALUE_AMERICAN=Amerikkalainen
+
+OPTION_VALUE_BLUE=Sininen
+OPTION_VALUE_GREEN=vihreä
+OPTION_VALUE_PINK=vaaleanpunainen
+OPTION_VALUE_RED=punainen
+OPTION_VALUE_VIOLET=violetti
+OPTION_VALUE_ORANGE=oranssi
+OPTION_VALUE_YELLOW=keltainen
+OPTION_VALUE_BROWN=ruskea
+OPTION_VALUE_BLACK=musta
+
+OPTION_VALUE_SING=Laula
+OPTION_VALUE_SELECT_PLAYERS=Valitse pelaajat
+OPTION_VALUE_OPEN_MENU=Avaa valikko
+
+OPTION_VALUE_HARDWARE_CURSOR=Hardiskursori
+OPTION_VALUE_SOFTWARE_CURSOR=Softakursori
+
+SING_LOADING=Ladataan...
+
+SING_CHOOSE_MODE=Valitse tapa
+SING_SING=Laula
+SING_SING_DESC=Laula soolo tai kilpaa
+
+SING_MULTI=Kilpailu
+SING_MULTI_DESC=Laulatte kilpaa vaikka useammassa tiimissä
+
+SING_TOOLS=Työkalut
+
+SING_STATS=Tilastot
+SING_STATS_DESC=Katso tilastoja
+
+SING_EDITOR=Editori
+SING_EDITOR_DESC=Luo uusia kappaleita peliin
+
+SING_GAME_OPTIONS=Peliasetukset
+SING_GAME_OPTIONS_DESC=Muuta pelin asetuksia
+
+SING_EXIT=Lopeta
+SING_EXIT_DESC=Sammuta peli
+
+SING_OPTIONS=Asetukset
+SING_OPTIONS_DESC=Muuta asetuksia
+SING_OPTIONS_WHEREAMI=Asetukset
+
+SING_OPTIONS_GAME=Peli
+SING_OPTIONS_GRAPHICS=Kuva
+SING_OPTIONS_SOUND=Äänet
+SING_OPTIONS_LYRICS=Sanasto
+SING_OPTIONS_THEMES=Teemat
+SING_OPTIONS_RECORD=Mikrofonit
+SING_OPTIONS_ADVANCED=Erikoiset
+SING_OPTIONS_EXIT=Takaisin
+
+SING_OPTIONS_GAME_WHEREAMI=Peliasetukset
+SING_OPTIONS_GAME_DESC=Yleiset peliasetukset
+SING_OPTIONS_GAME_PLAYERS=Laulajat
+SING_OPTIONS_GAME_DIFFICULTY=Vaikeustaso
+SING_OPTIONS_GAME_LANGUAGE=Kieli
+SING_OPTIONS_GAME_TABS=Välilehdet
+SING_OPTIONS_GAME_SORTING=Järjestys
+SING_OPTIONS_GAME_DEBUG=Virheentunnistus
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Kuva-asetukset
+SING_OPTIONS_GRAPHICS_DESC=Kuva-asetukset
+SING_OPTIONS_GRAPHICS_RESOLUTION=Resoluutio
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Kokoruutu
+SING_OPTIONS_GRAPHICS_DEPTH=Syvyys
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualisointi
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Ääniaallokko
+SING_OPTIONS_GRAPHICS_LINEBONUS=Rivibonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Videon koko
+
+SING_OPTIONS_SOUND_WHEREAMI=Ääniasetukset
+SING_OPTIONS_SOUND_DESC=Ääniasetukset
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Laulusi kuuluu kaittimista
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Taustamusiikki
+SING_OPTIONS_SOUND_MIC_BOOST=Mikrofonin vahvistus
+SING_OPTIONS_SOUND_CLICK_ASSIST=Klikkausapuri
+SING_OPTIONS_SOUND_BEAT_CLICK=Biittiklikkaaja
+SING_OPTIONS_SOUND_THRESHOLD=Aloituspiste
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Kaksinpelimoodi
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Esikatselutaso
+SING_OPTIONS_SOUND_PREVIEWFADING=Esikatselufeidaus
+
+SING_OPTIONS_LYRICS_WHEREAMI=Sanoitusasetukset
+SING_OPTIONS_LYRICS_DESC=Sanoitusasetukset
+SING_OPTIONS_LYRICS_FONT=Fontti
+SING_OPTIONS_LYRICS_EFFECT=Tehoste
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmisaatio
+SING_OPTIONS_LYRICS_NOTELINES=Nuottiviivasto
+
+SING_OPTIONS_THEMES_WHEREAMI=Teema-asetukset
+SING_OPTIONS_THEMES_DESC=Teema- ja tyyliasetukset
+SING_OPTIONS_THEMES_THEME=Teema
+SING_OPTIONS_THEMES_SKIN=Tyyli
+SING_OPTIONS_THEMES_COLOR=Väri
+
+SING_OPTIONS_RECORD_WHEREAMI=Mikrofoniasetukset
+SING_OPTIONS_RECORD_DESC=Määritä mikrofonit
+SING_OPTIONS_RECORD_CARD=Äänikortti
+SING_OPTIONS_RECORD_INPUT=Tulo
+SING_OPTIONS_RECORD_CHANNEL=Kanava
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Erikoisasetukset
+SING_OPTIONS_ADVANCED_DESC=Erikoisasetukset
+SING_OPTIONS_ADVANCED_EFFECTSING=Laulun efektit
+SING_OPTIONS_ADVANCED_SCREENFADE=Kuvan feidaus
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animaatiot
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Turvakyselyt
+SING_OPTIONS_ADVANCED_LINEBONUS=Rivibonus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Kappaleen valinnan jälkeen
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Automaattinen tiimipeli
+
+SING_EDIT=Editori
+SING_EDIT_MENU_DESCRIPTION=Luo oma laulusi
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Tuo teksti midi tiedostosta
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Takaisin
+SING_EDIT_BUTTON_CONVERT=Tuo
+SING_EDIT_BUTTON_EXIT=Takaisin
+
+SING_EDIT_NAVIGATE=Liiku
+SING_EDIT_SELECT=Valitse
+SING_EDIT_EXIT=Takaisin
+
+SING_LEGEND_SELECT=Valitse
+SING_LEGEND_NAVIGATE=Selaa
+SING_LEGEND_CONTINUE=Eteenpäin
+SING_LEGEND_ESC=Takaisin
+
+SING_PLAYER_DESC=Kirjoita pelinimet
+SING_PLAYER_WHEREAMI=Pelinimet
+SING_PLAYER_ENTER_NAME=Kirjoita nimi
+
+SING_DIFFICULTY_DESC=Valitse vaikeustaso
+SING_DIFFICULTY_WHEREAMI=Vaikeustaso
+SING_DIFFICULTY_CONTINUE=Kappaleen valintaan
+SING_EASY=Helppo
+SING_MEDIUM=Normaali
+SING_HARD=Vaikea
+
+SING_SONG_SELECTION_DESC=Valitse kappaleesi
+SING_SONG_SELECTION_WHEREAMI=Kappaleen valinta
+SING_SONG_SELECTION_GOTO=Siirry...
+SING_SONG_SELECTION=Kappale
+SING_SONG_SELECTION_MENU=Valikko
+SING_SONG_SELECTION_PLAYLIST=Kappalelista
+SING_SONGS_IN_CAT=Kappaletta
+PLAYLIST_CATTEXT=Kappalelista: %s
+
+SING_TIME=Pituus
+SING_TOTAL=Pisteesi
+SING_MODE=Soololaulu
+SING_NOTES=Nuotilleen
+SING_GOLDEN_NOTES=Kultanuotilleen
+SING_PHRASE_BONUS=Rivibonus
+
+SING_MENU=Aloitusvalikko
+
+SONG_SCORE=Laulusi pisteytys
+SONG_SCORE_WHEREAMI=Laulun Pisteet
+
+SING_SCORE_TONE_DEAF=Sävelkorvaton
+SING_SCORE_AMATEUR=Amatööri
+SING_SCORE_WANNABE=Matkija
+SING_SCORE_HOPEFUL=Toiveikas
+SING_SCORE_RISING_STAR=Nouseva tähti
+SING_SCORE_LEAD_SINGER=Päälaulaja
+SING_SCORE_SUPERSTAR=Supertähti
+SING_SCORE_ULTRASTAR=Ultratähti
+
+SING_TOP_5_CHARTS=5 parasta laulajaa
+SING_TOP_5_CHARTS_WHEREAMI=5 parasta
+SING_TOP_5_CHARTS_CONTINUE=Kappaleen valintaan
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=vaihda vaikeustasoa
+
+POPUP_PERFECT=Täydellistä!
+POPUP_AWESOME=Mahtavaa!
+POPUP_GREAT=Hienoa!
+POPUP_GOOD=Hyvä!
+POPUP_NOTBAD=Ei huono!
+POPUP_BAD=Huono!
+POPUP_POOR=Surkeaa!
+POPUP_AWFUL=Kauheaa!
+
+IMPLODE_GLUE1=, 
+IMPLODE_GLUE2= ja 
+
+SONG_MENU_NAME_MAIN=Kappalevalikko
+SONG_MENU_PLAY=Laula
+SONG_MENU_CHANGEPLAYERS=Vaihda pelinimeä
+SONG_MENU_EDIT=Muokkaa
+SONG_MENU_MODI=Laula modi
+SONG_MENU_CANCEL=Peruuta
+
+SONG_MENU_NAME_PLAYLIST=Kappalelistavalikko
+SONG_MENU_PLAYLIST_ADD=Lisää kappale
+SONG_MENU_PLAYLIST_DEL=Poista kappale
+
+SONG_MENU_NAME_PLAYLIST_ADD=Lisää kappale
+SONG_MENU_PLAYLIST_ADD_NEW=Uuteen kappalelistaan
+SONG_MENU_PLAYLIST_ADD_EXISTING=Olemassaolevaan kappalelistaan
+SONG_MENU_PLAYLIST_NOEXISTING=Ei kappalelistoja
+
+SONG_MENU_NAME_PLAYLIST_NEW=Uusi kappalelista
+SONG_MENU_PLAYLIST_NEW_CREATE=Luo
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Nimetön
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Vahvista poisto?
+SONG_MENU_YES=Kyllä
+SONG_MENU_NO=Ei
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Avaa kappalelista
+SONG_MENU_PLAYLIST_LOAD=Avaa
+SONG_MENU_PLAYLIST_DELCURRENT=Poista nykyinen kappalelista
+
+SONG_MENU_NAME_PLAYLIST_DEL=Poistetaanko todella?
+
+SONG_MENU_NAME_PARTY_MAIN=Tiimivalikko
+SONG_MENU_JOKER=Jokeri
+
+SONG_MENU_NAME_PARTY_JOKER=Ota jokeri
+
+SONG_JUMPTO_DESC=Etsi kappaletta
+SONG_JUMPTO_TYPE_DESC=Etsi kappaletta:
+SONG_JUMPTO_TYPE1=Kaikki
+SONG_JUMPTO_TYPE2=Otsikko
+SONG_JUMPTO_TYPE3=Esittäjä
+SONG_JUMPTO_SONGSFOUND=%d kappaletta löydetty
+SONG_JUMPTO_NOSONGSFOUND=Ei löytynyt kappaleita
+SONG_JUMPTO_HELP=Kirjoita tekstiä etsimiselle
+SONG_JUMPTO_CATTEXT=Etsi: %s
+
+PARTY_MODE=Tiimit
+PARTY_DIFFICULTY=Vaikeustaso
+PARTY_PLAYLIST=Soittolista
+PARTY_PLAYLIST_ALL=Kaikki kappaleet
+PARTY_PLAYLIST_CATEGORY=Kansio
+PARTY_PLAYLIST_PLAYLIST=Soittolista
+PARTY_TEAMS=Tiimit
+PARTY_TEAMS_PLAYER1=Laulaja 1 tiimi
+PARTY_TEAMS_PLAYER2=Laulaja 2 tiimi
+PARTY_TEAMS_PLAYER3=Laulaja 3 tiimi
+
+PARTY_LEGEND_CONTINUE=Eteenpäin
+
+PARTY_OPTIONS_DESC=Tiimilaulun asetukset
+PARTY_OPTIONS_WHEREAMI=Tiimilaulun asetukset
+
+PARTY_PLAYER_DESC=Kirjoita Laulaja ja tiimiläiset!
+PARTY_PLAYER_WHEREAMI=Tiiminimet
+PARTY_PLAYER_ENTER_NAME=Kirjoita nimi
+
+
+PARTY_ROUNDS_DESC=valitse mitä moodeja haluat pelata
+PARTY_ROUNDS_WHEREAMI=Tiimilaulun kierrokset
+PARTY_ROUNDS_LEGEND_CONTINUE=Aloita tiimilaulu
+PARTY_ROUNDCOUNT=kierrosten lukumäärä
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=Seuraavat laulajat mikrofonille
+PARTY_ROUND_WHEREAMI=Tiimilaulun seuraava kierros
+PARTY_ROUND_LEGEND_CONTINUE=Aloita kierros
+
+PARTY_SONG_WHEREAMI=Tiimilaulun kappaleen valinta	 
+PARTY_SONG_LEGEND_CONTINUE=Laula
+PARTY_SONG_MENU=Tiimilauluvalikko
+
+PARTY_SCORE_DESC=Edellisen kierroksen pisteet
+PARTY_SCORE_WHEREAMI=Tiimilaulun pisteet
+
+PARTY_WIN_DESC=Tiimilaulun voitttaja
+PARTY_WIN_WHEREAMI=Tiimilaulun voittaja
+PARTY_WIN_LEGEND_CONTINUE=Takaisin edelliseen valikkoon
+
+PARTY_ROUND=Kierros
+PARTY_ROUND_WINNER=Voittaja
+PARTY_NOTPLAYEDYET=Ei laulettu vielä
+PARTY_NOBODY=Nimetön
+NEXT_ROUND=Seuraava kierros:
+
+PARTY_DISMISSED=hylättyä!
+PARTY_SCORE_WINS=%s 
+PARTY_SCORE_WINS2=voittoa!
+
+MODE_RANDOM_NAME=Satunnainen
+MODE_RANDOM_DESC=Valitsee yhden laulumoodeista satunnaisesti
+
+MODE_HOLDTHELINE_NAME=Pysy linjoissa
+MODE_HOLDTHELINE_DESC=Älä laula huonommin kuin mitä viivat ruudulla sallivat.
+
+MODE_5000POINTS_NAME=Kunnes 5000
+MODE_5000POINTS_DESC=5000 pistettä ensin saanut voittaa laulun.
+
+MODE_DUEL_NAME=Yhteislaulu
+MODE_DUEL_DESC=Laulakaa yhteislaulua 1000:een pisteeseen asti.
+
+MODE_TEAMDUEL_NAME=Tiimin yhteislaulu
+MODE_TEAMDUEL_DESC=Liikuta mikkiä!
+
+MODE_BLIND_NAME=Sokeamoodi
+MODE_BLIND_DESC=Yhteislaulu ilman nuottitasojen näkymää.
+
+STAT_MAIN=Tilastot
+STAT_MAIN_DESC=Yleiset
+STAT_MAIN_WHEREAMI=Tilastot
+
+STAT_OVERVIEW_INTRO=%0:s Tilastot.  \n Viimeksi resetoitu %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Lauluja(%3:d Videolla), joista %1:d aiemmin soitettu ja joista %2:d joita ei ole vielä soitettu.\n Suosituin laulu on %5:s %4:s.
+STAT_OVERVIEW_PLAYER=Viime nollauksen jälkeen on ollut %0:d eri pelaajaa.\n Paras pelaaja on %1:s pistekeskiarvolla %2:d .\n Korkeimman pistemäärän on tehnyt %3:s %4:d pisteellä.
+
+;TODO: STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Tilastot
+STAT_DETAIL_WHEREAMI=Tarkat tilastot
+
+STAT_NEXT=Seuraava sivu
+STAT_PREV=Edellinen sivu 
+STAT_REVERSE=Käänteinen järjestys
+STAT_PAGE=Sivu %0:d %1:d sivusta\n (%2:d %3:d alkiosta)
+
+STAT_DESC_SCORES=Korkeimmat pisteet
+STAT_DESC_SCORES_REVERSED=Heikoimmat pisteet
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s] \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Parhaat laulajat
+STAT_DESC_SINGERS_REVERSED=Heikoimmmat laulajat
+STAT_FORMAT_SINGERS=%0:s \n Pisteiden keskiarvo: %1:d
+
+STAT_DESC_SONGS=Suosituimmat kappaleet
+STAT_DESC_SONGS_REVERSED=Vähiten suositut kappaleet
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx Laulettu
+
+STAT_DESC_BANDS=Suosituimmat yhtyeet
+STAT_DESC_BANDS_REVERSED=Vähiten suositut yhtyeet
+STAT_FORMAT_BANDS=%0:s \n %1:dx Laulettu
+
+SCREENSHOT_SAVED=Kuvakaappaus tallennettu
+SCREENSHOT_FAILED=Kuvakaappauksen tallennus ei onnistunut
+
+INFO_FILE_SAVED=Tiedosto tallennettu
+ERROR_SAVE_FILE_FAILED=Tallennus epäonnistui
+ERROR_FILE_NOT_FOUND=Tiedostoa ei löydy
+
+ENCODING_ERROR_ASK_FOR_UTF8=Muutoksia ei voi tallettaa tällä koodauksella (encoding). Muunnetaanko UTF-8:aan?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Virhe
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Kysymys
+MSG_QUIT_USDX=Tahdotko todella lopettaa UltraStarin?
+MSG_END_PARTY=Tahdotko todella lopettaa Tiimilaulun?
+
+ERROR_NO_SONGS=Ei kappaleita
+ERROR_NO_PLUGINS=Ei liitännäisiä ladattu
+ERROR_NO_MODES_FOR_CURRENT_SETUP=nykyiselle pelaajalle/tiimille ei moodeja saatavilla
+ERROR_CAN_NOT_START_PARTY=virhe tapahtui käynnistettäessä Tiimipeliä
+ERROR_CORRUPT_SONG=Kappaletta ei voitu avata.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Kappaletta ei voitu avata: Tiedostoa ei löytynyt
+ERROR_CORRUPT_SONG_NO_NOTES=Kappaletta ei voitu avata: Ei löytynyt yhtään nuottia
+ERROR_CORRUPT_SONG_NO_BREAKS=Kappaletta ei voitu avata: Ei löytynyt yhtään rivinvaihtoa
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Kappaletta ei voitu avata: Virhe jäsentäessä riviä %0:d
+ERROR_NO_EDITOR=Tämä toiminto ei ole käytettävissä Linux/Mac:ssä
+ERROR_PLAYER_DEVICE_ASSIGNMENT=Pelaajalle %d on asetettu monta mikrofonia. Ole hyvä ja tarkista asetukset.
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Pelaajalla %d ei ole asetettu mikrofonia. Ole hyvä ja tarkista asetukset. 
+;UNUSED: SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Kuinka usein laulettu
+;UNUSED: SING_SCORE_HIT_ARTIST=Hittiartisti
+;UNUSED: PARTY_ROUNDS=Kierroksia
+;TRANSLATOR: Jeremi Roivas; anonymous
diff --git a/songmanagement/game/languages/French.ini b/songmanagement/game/languages/French.ini
new file mode 100644
index 00000000..6e80ccb7
--- /dev/null
+++ b/songmanagement/game/languages/French.ini
@@ -0,0 +1,441 @@
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croate
+OPTION_VALUE_CZECH=Tchèque
+OPTION_VALUE_DANISH=Danois
+OPTION_VALUE_DUTCH=Néerlandais
+OPTION_VALUE_ENGLISH=Anglais
+OPTION_VALUE_EUSKARA=Basque
+OPTION_VALUE_FINNISH=Finnois
+OPTION_VALUE_FRENCH=Français
+OPTION_VALUE_GERMAN=Allemand
+OPTION_VALUE_GREEK=Grec
+OPTION_VALUE_HUNGARIAN=Hongrois
+OPTION_VALUE_ICELANDIC=Islandais
+OPTION_VALUE_ITALIAN=Italien
+OPTION_VALUE_JAPANESE=Japonais
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgeois
+OPTION_VALUE_NORWEGIAN=Norvégien
+OPTION_VALUE_POLISH=Polonais
+OPTION_VALUE_PORTUGUESE=Portugais
+OPTION_VALUE_RUSSIAN=Russe
+OPTION_VALUE_SERBIAN=Serbe
+OPTION_VALUE_SLOVAK=Slovaque
+OPTION_VALUE_SLOVENIAN=Slovène
+OPTION_VALUE_SPANISH=Espagnol
+OPTION_VALUE_SWEDISH=Suédois
+
+OPTION_VALUE_EASY=Facile
+OPTION_VALUE_MEDIUM=Moyen
+OPTION_VALUE_HARD=Difficile
+
+OPTION_VALUE_ON=Activé
+OPTION_VALUE_OFF=Désactivé
+
+OPTION_VALUE_EDITION=Édition
+OPTION_VALUE_GENRE=Genre
+OPTION_VALUE_LANGUAGE=Langue
+OPTION_VALUE_FOLDER=Dossier
+OPTION_VALUE_TITLE=Titre
+OPTION_VALUE_ARTIST=Artiste
+OPTION_VALUE_TITLE2=Titre2
+OPTION_VALUE_ARTIST2=Artiste2
+
+OPTION_VALUE_WHENNOVIDEO=Si pas de vidéo
+
+OPTION_VALUE_SMALL=Petit
+OPTION_VALUE_BIG=Grand
+
+OPTION_VALUE_HALF=Moitiée
+OPTION_VALUE_FULL_VID=Complète
+OPTION_VALUE_FULL_VID_BG=Complète (Fond + Vidéo)
+
+OPTION_VALUE_AUTO=Automatique
+OPTION_VALUE_SEC=Seconde
+OPTION_VALUE_SECS=Secondes
+
+OPTION_VALUE_PLAIN=Classique
+OPTION_VALUE_OLINE1=Bordures
+OPTION_VALUE_OLINE2=Gras
+
+OPTION_VALUE_SIMPLE=Syllabes
+OPTION_VALUE_ZOOM=Zoomer
+OPTION_VALUE_SLIDE=Glisser
+OPTION_VALUE_BALL=Balle
+OPTION_VALUE_SHIFT=Bond
+
+OPTION_VALUE_EURO=Européen
+OPTION_VALUE_JAPAN=Japonais
+OPTION_VALUE_AMERICAN=Américain
+
+OPTION_VALUE_BLUE=Bleu
+OPTION_VALUE_GREEN=Vert
+OPTION_VALUE_PINK=Rose
+OPTION_VALUE_RED=Rouge
+OPTION_VALUE_VIOLET=Violet
+OPTION_VALUE_ORANGE=Orange
+OPTION_VALUE_YELLOW=Jaune
+OPTION_VALUE_BROWN=Marron
+OPTION_VALUE_BLACK=Noir
+
+OPTION_VALUE_SING=Chanter
+OPTION_VALUE_SELECT_PLAYERS=Choix des joueurs
+OPTION_VALUE_OPEN_MENU=Ouvrir le menu
+
+OPTION_VALUE_HARDWARE_CURSOR=Pointeur matériel
+OPTION_VALUE_SOFTWARE_CURSOR=Pointeur logiciel
+
+SING_LOADING=Chargement...
+
+SING_CHOOSE_MODE=Choisissez un mode de jeu
+SING_SING=Chanter
+SING_SING_DESC=Chantez en solo
+
+SING_MULTI=Fête
+SING_MULTI_DESC=Faites la fête
+
+SING_TOOLS=Outils
+
+SING_STATS=Statistiques
+SING_STATS_DESC=Consultez les statistiques
+
+SING_EDITOR=Éditeur
+SING_EDITOR_DESC=Créez vos propres chansons
+
+SING_GAME_OPTIONS=Options
+SING_GAME_OPTIONS_DESC=Modifiez les paramètres du jeu
+
+SING_EXIT=Quitter
+SING_EXIT_DESC=Quitter le jeu
+
+SING_OPTIONS=Options
+SING_OPTIONS_DESC=Changez les paramètres
+SING_OPTIONS_WHEREAMI=Options
+
+SING_OPTIONS_GAME=Jeu
+SING_OPTIONS_GRAPHICS=Graphismes
+SING_OPTIONS_SOUND=Audio
+SING_OPTIONS_LYRICS=Paroles
+SING_OPTIONS_THEMES=Thèmes
+SING_OPTIONS_RECORD=Micros
+SING_OPTIONS_ADVANCED=Avancé
+SING_OPTIONS_EXIT=Retour
+
+SING_OPTIONS_GAME_WHEREAMI=Options du jeu
+SING_OPTIONS_GAME_DESC=Options générales du jeu
+SING_OPTIONS_GAME_PLAYERS=Joueur(s)
+SING_OPTIONS_GAME_DIFFICULTY=Difficulté
+SING_OPTIONS_GAME_LANGUAGE=Langue
+SING_OPTIONS_GAME_TABS=Dossier
+SING_OPTIONS_GAME_SORTING=Tri par
+SING_OPTIONS_GAME_DEBUG=Débogage
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Options graphiques
+SING_OPTIONS_GRAPHICS_DESC=Paramètres des graphismes
+SING_OPTIONS_GRAPHICS_RESOLUTION=Résolution
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Plein écran
+SING_OPTIONS_GRAPHICS_DEPTH=Profondeur
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualisation
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloscope
+SING_OPTIONS_GRAPHICS_LINEBONUS=Bonus de phrases
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Taille vidéo
+
+SING_OPTIONS_SOUND_WHEREAMI=Options du son
+SING_OPTIONS_SOUND_DESC=Paramètres du son
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Entendre le micro
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Musique de fond
+SING_OPTIONS_SOUND_MIC_BOOST=Amplifier le micro
+SING_OPTIONS_SOUND_CLICK_ASSIST=Clics d'aide
+SING_OPTIONS_SOUND_BEAT_CLICK=Métronome
+SING_OPTIONS_SOUND_THRESHOLD=Suppression du bruit
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Mode 2 joueurs
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Prévisualiser volume
+SING_OPTIONS_SOUND_PREVIEWFADING=Prévisualiser fondu
+
+SING_OPTIONS_LYRICS_WHEREAMI=Options des paroles
+SING_OPTIONS_LYRICS_DESC=Paramètres des paroles
+SING_OPTIONS_LYRICS_FONT=Caractères
+SING_OPTIONS_LYRICS_EFFECT=Effet
+SING_OPTIONS_LYRICS_SOLMIZATION=Afficher gamme
+SING_OPTIONS_LYRICS_NOTELINES=Barres
+
+SING_OPTIONS_THEMES_WHEREAMI=Options des thèmes
+SING_OPTIONS_THEMES_DESC=Paramètres des thèmes
+SING_OPTIONS_THEMES_THEME=Thèmes
+SING_OPTIONS_THEMES_SKIN=Aspect
+SING_OPTIONS_THEMES_COLOR=Couleur
+
+SING_OPTIONS_RECORD_WHEREAMI=Options d'enregistrement
+SING_OPTIONS_RECORD_DESC=Paramètres des micros
+SING_OPTIONS_RECORD_CARD=Carte son
+SING_OPTIONS_RECORD_INPUT=Entrée
+SING_OPTIONS_RECORD_CHANNEL=Canal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Options avancées
+SING_OPTIONS_ADVANCED_DESC=Paramètres avancés
+SING_OPTIONS_ADVANCED_EFFECTSING=Effet de chant
+SING_OPTIONS_ADVANCED_SCREENFADE=Fondu écran
+SING_OPTIONS_ADVANCED_LOADANIMATION=Charge animation
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Confirm. suppression
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus des phrases
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Choix ap. chanson
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Menu fête auto
+
+SING_EDIT=Éditeur
+SING_EDIT_MENU_DESCRIPTION=Créez vos propres chansons
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Exporter du texte depuis un fichier MIDI
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Retour
+SING_EDIT_BUTTON_CONVERT=Importer
+SING_EDIT_BUTTON_EXIT=Retour
+
+SING_EDIT_NAVIGATE=Naviguer
+SING_EDIT_SELECT=Valider
+SING_EDIT_EXIT=Retour
+
+SING_LEGEND_SELECT=Valider
+SING_LEGEND_NAVIGATE=Naviguer
+SING_LEGEND_CONTINUE=Continuer
+SING_LEGEND_ESC=Retour
+
+SING_PLAYER_DESC=Entrez le nom du/des joueur(s)
+SING_PLAYER_WHEREAMI=Nom du joueur
+SING_PLAYER_ENTER_NAME=Modifier
+
+SING_DIFFICULTY_DESC=Sélectionnez le niveau de difficulté
+SING_DIFFICULTY_WHEREAMI=Difficulté
+SING_DIFFICULTY_CONTINUE=Valider
+SING_EASY=Facile
+SING_MEDIUM=Moyen
+SING_HARD=Difficile
+
+SING_SONG_SELECTION_DESC=Choisissez une chanson
+SING_SONG_SELECTION_WHEREAMI=Sélection du titre
+SING_SONG_SELECTION_GOTO=Atteindre
+SING_SONG_SELECTION=Choix de chansons
+SING_SONG_SELECTION_MENU=Menu
+SING_SONG_SELECTION_PLAYLIST=Playlist
+SING_SONGS_IN_CAT=Chansons
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=TEMPS
+SING_TOTAL=Total
+SING_MODE=Mode chanter
+SING_NOTES=Notes
+SING_GOLDEN_NOTES=Notes en or
+SING_PHRASE_BONUS=Bonus de phrases
+
+SING_MENU=Menu principal
+
+SONG_SCORE=Score
+SONG_SCORE_WHEREAMI=Points
+
+SING_SCORE_TONE_DEAF=Casserole
+SING_SCORE_AMATEUR=Amateur
+SING_SCORE_WANNABE=Aspirant chant.
+SING_SCORE_HOPEFUL=Espoir
+SING_SCORE_RISING_STAR=Star en herbe
+SING_SCORE_LEAD_SINGER=Artiste
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=Top 5
+SING_TOP_5_CHARTS_WHEREAMI=Meilleurs joueurs
+SING_TOP_5_CHARTS_CONTINUE=Continuer
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=Changer de difficulté
+
+POPUP_PERFECT=Parfait !
+POPUP_AWESOME=Cool !
+POPUP_GREAT=Génial !
+POPUP_GOOD=Bien !
+POPUP_NOTBAD=Pas mal
+POPUP_BAD=Bof...
+POPUP_POOR=Mauvais !
+POPUP_AWFUL=Nul !
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= et
+
+SONG_MENU_NAME_MAIN=Menu
+SONG_MENU_PLAY=Chanter
+SONG_MENU_CHANGEPLAYERS=Changer de joueurs
+SONG_MENU_EDIT=Éditeur
+SONG_MENU_MODI=Chanter un mode
+SONG_MENU_CANCEL=Annuler
+
+SONG_MENU_NAME_PLAYLIST=Menu
+SONG_MENU_PLAYLIST_ADD=Ajouter la chanson
+SONG_MENU_PLAYLIST_DEL=Supprimer la chanson
+
+SONG_MENU_NAME_PLAYLIST_ADD=Ajouter la chanson
+SONG_MENU_PLAYLIST_ADD_NEW=À une nouvelle playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=Ajouter à la playlist
+SONG_MENU_PLAYLIST_NOEXISTING=Playlists indisponibles
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nouvelle playlist
+SONG_MENU_PLAYLIST_NEW_CREATE=Créer
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Sans-nom
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Supprimer ?
+SONG_MENU_YES=Oui
+SONG_MENU_NO=Non
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Ouvrir la playlist
+SONG_MENU_PLAYLIST_LOAD=Ouvrir
+SONG_MENU_PLAYLIST_DELCURRENT=Supprimer la playlist
+
+SONG_MENU_NAME_PLAYLIST_DEL=Êtes-vous sûr(e) ?
+
+SONG_MENU_NAME_PARTY_MAIN=Menu fête
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=Utiliser Joker
+
+SONG_JUMPTO_DESC=Rechercher
+SONG_JUMPTO_TYPE_DESC=Recherche :
+SONG_JUMPTO_TYPE1=Tout
+SONG_JUMPTO_TYPE2=Titre
+SONG_JUMPTO_TYPE3=Artiste
+SONG_JUMPTO_SONGSFOUND=%d Chanson(s) trouvée(s)
+SONG_JUMPTO_NOSONGSFOUND=Aucune chanson trouvée
+SONG_JUMPTO_HELP=Entrez le texte à rechercher
+SONG_JUMPTO_CATTEXT=Recherche : %s
+
+PARTY_MODE=Mode fête
+PARTY_DIFFICULTY=Difficulté
+PARTY_PLAYLIST=Playlist
+PARTY_PLAYLIST_ALL=Toutes les chansons
+PARTY_PLAYLIST_CATEGORY=Dossier
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_TEAMS=Nbre d'équipes
+PARTY_TEAMS_PLAYER1=Nbre de joueurs
+PARTY_TEAMS_PLAYER2=Nbre de joueurs
+PARTY_TEAMS_PLAYER3=Nbre de joueurs
+
+PARTY_LEGEND_CONTINUE=Suivant
+
+PARTY_OPTIONS_DESC=Paramètres du mode fête
+PARTY_OPTIONS_WHEREAMI=Mode fête : Options
+
+PARTY_PLAYER_DESC=Entrez le nom des équipes et des joueurs
+PARTY_PLAYER_WHEREAMI=Mode fête : Équipes
+PARTY_PLAYER_ENTER_NAME=Modifier
+
+
+PARTY_ROUNDS_DESC= Sélectionnez les modes
+PARTY_ROUNDS_WHEREAMI=Mode fête : Manches
+PARTY_ROUNDS_LEGEND_CONTINUE=Commencer la fête
+PARTY_ROUNDCOUNT=Nbre des manches
+PARTY_SELECTMODE1=1ère manche
+PARTY_SELECTMODE2=2e manche
+PARTY_SELECTMODE3=3e manche
+PARTY_SELECTMODE4=4e manche
+PARTY_SELECTMODE5=5e manche
+PARTY_SELECTMODE6=6e manche
+PARTY_SELECTMODE7=7e manche
+
+PARTY_ROUND_DESC=Joueurs suivants, à vos micros !
+PARTY_ROUND_WHEREAMI=Mode fête : Manche suivante
+PARTY_ROUND_LEGEND_CONTINUE=Commencer la manche
+
+PARTY_SONG_WHEREAMI=Mode fête : Choix de la chanson
+PARTY_SONG_LEGEND_CONTINUE=Chanter
+PARTY_SONG_MENU=Menu fête
+
+PARTY_SCORE_DESC=Score de la manche
+PARTY_SCORE_WHEREAMI=Mode fête : Score
+
+PARTY_WIN_DESC=Gagnant de la partie
+PARTY_WIN_WHEREAMI=Mode fête : Gagnant
+PARTY_WIN_LEGEND_CONTINUE=Retour au menu principal
+
+PARTY_ROUND=Manche
+PARTY_ROUND_WINNER=Gagnant
+PARTY_NOTPLAYEDYET=-
+PARTY_NOBODY=Personne ne
+NEXT_ROUND=Manche suivante :
+
+PARTY_DISMISSED=Rétrogradé !
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=l'emporte !
+
+MODE_RANDOM_NAME=Mode hasard
+MODE_RANDOM_DESC=Un mode sera choisi au hasard.
+
+MODE_HOLDTHELINE_NAME=Tenez la barre
+MODE_HOLDTHELINE_DESC=Maintenez la jauge dans le secteur indiqué.
+
+MODE_5000POINTS_NAME=Jusqu'à 5000
+MODE_5000POINTS_DESC=Remportez la manche en étant le 1er à atteindre 5000 points.
+
+MODE_DUEL_NAME=Duel
+MODE_DUEL_DESC=L'équipe victorieuse sera celle qui a le meilleur score.
+
+MODE_TEAMDUEL_NAME=Duel par équipe
+MODE_TEAMDUEL_DESC=Passez le micro !
+
+MODE_BLIND_NAME=À l'aveugle
+MODE_BLIND_DESC=Obtenez le meilleur score sans l'aide des notes.
+
+STAT_MAIN=Statistiques
+STAT_MAIN_DESC=Général
+STAT_MAIN_WHEREAMI=Statistiques
+
+STAT_OVERVIEW_INTRO=Statistiques d'%0:s \n Dernière réinitialisation le %1:.2d.%2:.2d.%3:d
+STAT_OVERVIEW_SONG=Le jeu contient %0:d chansons dont %3:d avec vidéo.\n%1:d ont déjà été chantées une fois et %2:d pas encore. \n\n La chanson la plus chantée est %5:s de %4:s.
+STAT_OVERVIEW_PLAYER=%0:d joueurs différents ont chantés depuis la dernière réinitialisation. \n\n Le meilleur joueur est %1:s avec %2:d points. \n %3:s a atteint le meilleur score avec %4:d points.
+
+STAT_FORMAT_DATE=%0:.2d.%1:.2d.%2:d
+
+STAT_DETAIL=Statistiques
+STAT_DETAIL_WHEREAMI=Statistiques détaillées
+
+STAT_NEXT=Page suiv.
+STAT_PREV=Page préc.
+STAT_REVERSE=Inverser
+STAT_PAGE=Page %0:d de %1:d \n (%2:d entrées sur %3:d)
+
+STAT_DESC_SCORES=Meilleurs Scores
+STAT_DESC_SCORES_REVERSED=Pires scores
+STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Meill. Chanteurs
+STAT_DESC_SINGERS_REVERSED=Pires chanteurs
+STAT_FORMAT_SINGERS=%0:s \n Score moyen: %1:d
+
+STAT_DESC_SONGS=Chansons favorites
+STAT_DESC_SONGS_REVERSED=Chansons impopulaires
+STAT_FORMAT_SONGS=%0:s - %1:s \n Chanté %2:dx
+
+STAT_DESC_BANDS=Artistes favoris 
+STAT_DESC_BANDS_REVERSED=Artistes impopulaires
+STAT_FORMAT_BANDS=%0:s \n Chansons chantées: %1:d
+
+SCREENSHOT_SAVED=Capture d'écran sauvegardée
+SCREENSHOT_FAILED=Impossible de sauvegarder la capture
+
+INFO_FILE_SAVED=Fichier sauvegardé
+ERROR_SAVE_FILE_FAILED=Impossible de sauvegarder le fichier
+ERROR_FILE_NOT_FOUND=Fichier introuvable
+
+ENCODING_ERROR_ASK_FOR_UTF8=Impossible de sauvegarder sous l'encodage actuel. Convertir en UTF-8 ?
+EDITOR_ERROR_NO_TRACK_SELECTED=Aucune piste n'est sélectionnée
+
+MSG_ERROR_TITLE=Erreur
+MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Confirmation
+MSG_QUIT_USDX=Quitter le jeu ?
+MSG_END_PARTY=Quitter la fête ?
+
+ERROR_NO_SONGS=Chansons introuvables
+ERROR_NO_PLUGINS=Plugins introuvables
+ERROR_NO_MODES_FOR_CURRENT_SETUP=Aucun mode n'est disponible pour les équipes/joueurs actuels.
+ERROR_CAN_NOT_START_PARTY= Une erreur s'est produite au démarrage du mode fête.
+ERROR_CORRUPT_SONG=Impossible de charger la chanson.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Chargement impossible : Fichier non trouvé
+ERROR_CORRUPT_SONG_NO_NOTES=Chargement impossible : Pas de partition trouvée
+ERROR_CORRUPT_SONG_NO_BREAKS=Chargement impossible : Saut de ligne introuvable
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Chargement impossible : Erreur analyseur à la ligne %0:d
+ERROR_NO_EDITOR=Éditeur introuvable
+ERROR_PLAYER_DEVICE_ASSIGNMENT=Plusieurs micros sont attribués au joueur %d. Merci de vérifier vos options d'enregistrement
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Aucun micro n'est attribué au joueur %d. Merci de vérifier vos options d'enregistrement
diff --git a/songmanagement/game/languages/German.ini b/songmanagement/game/languages/German.ini
new file mode 100644
index 00000000..8c9212c3
--- /dev/null
+++ b/songmanagement/game/languages/German.ini
@@ -0,0 +1,442 @@
+[Text]
+OPTION_VALUE_CATALAN=Katalanisch
+OPTION_VALUE_CROATIAN=Kroatisch
+;TODO: OPTION_VALUE_CZECH=Czech
+OPTION_VALUE_DANISH=Dänisch
+OPTION_VALUE_DUTCH=Niederländisch
+OPTION_VALUE_ENGLISH=Englisch
+OPTION_VALUE_EUSKARA=Baskisch
+OPTION_VALUE_FINNISH=Finnisch
+OPTION_VALUE_FRENCH=Französisch
+OPTION_VALUE_GERMAN=Deutsch
+OPTION_VALUE_GREEK=Griechisch
+OPTION_VALUE_HUNGARIAN=Ungarisch
+OPTION_VALUE_ICELANDIC=Isländisch
+OPTION_VALUE_ITALIAN=Italienisch
+OPTION_VALUE_JAPANESE=Japanisch
+OPTION_VALUE_LUXEMBOURGISH=Luxemburgisch
+OPTION_VALUE_NORWEGIAN=Norwegisch
+OPTION_VALUE_POLISH=Polnisch
+OPTION_VALUE_PORTUGUESE=Portugiesisch
+OPTION_VALUE_RUSSIAN=Russisch
+OPTION_VALUE_SERBIAN=Serbisch
+OPTION_VALUE_SLOVAK=Slowakisch
+OPTION_VALUE_SLOVENIAN=Slowenisch
+OPTION_VALUE_SPANISH=Spanisch
+OPTION_VALUE_SWEDISH=Schwedisch
+
+OPTION_VALUE_EASY=Einfach
+OPTION_VALUE_MEDIUM=Mittel
+OPTION_VALUE_HARD=Schwierig
+
+OPTION_VALUE_ON=An
+OPTION_VALUE_OFF=Aus
+
+OPTION_VALUE_EDITION=Edition
+OPTION_VALUE_GENRE=Genre
+OPTION_VALUE_LANGUAGE=Sprache
+OPTION_VALUE_FOLDER=Ordner
+OPTION_VALUE_TITLE=Titel
+OPTION_VALUE_ARTIST=Künstler
+OPTION_VALUE_TITLE2=Titel2
+OPTION_VALUE_ARTIST2=Künstler2
+
+OPTION_VALUE_WHENNOVIDEO=Wenn kein Video
+
+OPTION_VALUE_SMALL=Klein
+OPTION_VALUE_BIG=Gross
+
+OPTION_VALUE_HALF=Halb
+OPTION_VALUE_FULL_VID=Voll (Video)
+OPTION_VALUE_FULL_VID_BG=Voll (HG & Video)
+
+OPTION_VALUE_AUTO=Automatisch
+OPTION_VALUE_SEC=Sekunde
+OPTION_VALUE_SECS=Sekunden
+
+OPTION_VALUE_PLAIN=Einfach
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Einfach
+OPTION_VALUE_ZOOM=Vergrössern
+OPTION_VALUE_SLIDE=Rutschen
+OPTION_VALUE_BALL=Ball
+OPTION_VALUE_SHIFT=Schieben
+
+OPTION_VALUE_EURO=Europäisch
+OPTION_VALUE_JAPAN=Japanisch
+OPTION_VALUE_AMERICAN=Amerikanisch
+
+OPTION_VALUE_BLUE=Blau
+OPTION_VALUE_GREEN=Grün
+OPTION_VALUE_PINK=Lila
+OPTION_VALUE_RED=Rot
+OPTION_VALUE_VIOLET=Violett
+OPTION_VALUE_ORANGE=Orange
+OPTION_VALUE_YELLOW=Gelb
+OPTION_VALUE_BROWN=Braun
+OPTION_VALUE_BLACK=Schwarz
+
+OPTION_VALUE_SING=Singen
+OPTION_VALUE_SELECT_PLAYERS=Spieler auswählen
+OPTION_VALUE_OPEN_MENU=Menu öffnen
+
+OPTION_VALUE_HARDWARE_CURSOR=Hardware Zeiger
+OPTION_VALUE_SOFTWARE_CURSOR=Software Zeiger
+
+SING_LOADING=Lädt...
+
+SING_CHOOSE_MODE=Modus wählen
+SING_SING=Singen
+SING_SING_DESC=Singen
+
+SING_MULTI=Party
+SING_MULTI_DESC=Ein rundenbasiertes Teamspiel spielen
+
+SING_TOOLS=Werkzeuge
+
+SING_STATS=Statistiken
+SING_STATS_DESC=Die Statistiken anschauen
+
+SING_EDITOR=Editor
+SING_EDITOR_DESC=Erstelle deinen eigenen Song
+
+SING_GAME_OPTIONS=Spieloptionen
+SING_GAME_OPTIONS_DESC=Verändere die Spieleinstellungen
+
+SING_EXIT=Beenden
+SING_EXIT_DESC=Spiel verlassen
+
+SING_OPTIONS=Optionen
+SING_OPTIONS_DESC=Einstellungen verändern
+SING_OPTIONS_WHEREAMI=Optionen
+
+SING_OPTIONS_GAME=Spiel
+SING_OPTIONS_GRAPHICS=Grafik
+SING_OPTIONS_SOUND=Sound
+SING_OPTIONS_LYRICS=Lyrics
+SING_OPTIONS_THEMES=Design
+SING_OPTIONS_RECORD=Aufnahme
+SING_OPTIONS_ADVANCED=Erweitert
+SING_OPTIONS_EXIT=zurück
+
+SING_OPTIONS_GAME_WHEREAMI=Spieloptionen
+SING_OPTIONS_GAME_DESC=Allgemeine Spieleinstellungen
+SING_OPTIONS_GAME_PLAYERS=Spieler
+SING_OPTIONS_GAME_DIFFICULTY=Schwierigkeit
+SING_OPTIONS_GAME_LANGUAGE=Sprache
+SING_OPTIONS_GAME_TABS=Ordner
+SING_OPTIONS_GAME_SORTING=Sortierung
+SING_OPTIONS_GAME_DEBUG=Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Grafikoptionen
+SING_OPTIONS_GRAPHICS_DESC=Grafikeinstellungen
+SING_OPTIONS_GRAPHICS_RESOLUTION=Auflösung
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Vollbild
+SING_OPTIONS_GRAPHICS_DEPTH=Farbtiefe
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualisierung
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oszilloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Phrasenbonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Videogröße
+
+SING_OPTIONS_SOUND_WHEREAMI=Soundoptionen
+SING_OPTIONS_SOUND_DESC=Soundeinstellungen
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Mikrofon Wiedergabe
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Hintergrundmusik
+SING_OPTIONS_SOUND_MIC_BOOST=Mic-Anhebung
+SING_OPTIONS_SOUND_CLICK_ASSIST=Click-Assistent
+SING_OPTIONS_SOUND_BEAT_CLICK=Beat-Click
+SING_OPTIONS_SOUND_THRESHOLD=Rauschunterdr.
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=2-Spieler-Modus
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Vorschau Lautst.
+SING_OPTIONS_SOUND_PREVIEWFADING=Vorschau Fading
+
+SING_OPTIONS_LYRICS_WHEREAMI=Lyricsoptionen
+SING_OPTIONS_LYRICS_DESC=Einstellungen für die Lyrics
+SING_OPTIONS_LYRICS_FONT=Schriftart
+SING_OPTIONS_LYRICS_EFFECT=Effekt
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmisation
+SING_OPTIONS_LYRICS_NOTELINES=Notenlinien
+
+SING_OPTIONS_THEMES_WHEREAMI=Designoptionen
+SING_OPTIONS_THEMES_DESC=Design und Skineinstellungen
+SING_OPTIONS_THEMES_THEME=Design
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Farbe
+
+SING_OPTIONS_RECORD_WHEREAMI=Aufnahmeoptionen
+SING_OPTIONS_RECORD_DESC=Mikrofoneinstellungen
+SING_OPTIONS_RECORD_CARD=Soundkarte
+SING_OPTIONS_RECORD_INPUT=Eingang
+SING_OPTIONS_RECORD_CHANNEL=Kanal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Erweiterte Optionen
+SING_OPTIONS_ADVANCED_DESC=Erweiterte Einstellungen
+SING_OPTIONS_ADVANCED_EFFECTSING=Singeffekte
+SING_OPTIONS_ADVANCED_SCREENFADE=Bildschirm-Fade
+SING_OPTIONS_ADVANCED_LOADANIMATION=Lade-Animation
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Sicherheitsabfr.
+SING_OPTIONS_ADVANCED_LINEBONUS=Phrasenbonus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Nach Songauswahl
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto Party-Menü
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=Erstelle deinen eigenen Song
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Midi/Kar-Datei in Text exportieren
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=zurück
+SING_EDIT_BUTTON_CONVERT=Importieren
+SING_EDIT_BUTTON_EXIT=zurück
+
+SING_EDIT_NAVIGATE=Navigieren
+SING_EDIT_SELECT=Auswählen
+SING_EDIT_EXIT=zurück
+
+SING_LEGEND_SELECT=Auswählen
+SING_LEGEND_NAVIGATE=Navigieren
+SING_LEGEND_CONTINUE=Weiter
+SING_LEGEND_ESC=zurück
+
+SING_PLAYER_DESC=Spielernamen eingeben.
+SING_PLAYER_WHEREAMI=Spielernamen
+SING_PLAYER_ENTER_NAME=Namen eingeben
+
+SING_DIFFICULTY_DESC=Schwierigkeitsgrad auswählen
+SING_DIFFICULTY_WHEREAMI=Schwierigkeitsgrad
+SING_DIFFICULTY_CONTINUE=zur Song-Auswahl
+SING_EASY=Einfach
+SING_MEDIUM=Mittel
+SING_HARD=Schwierig
+
+SING_SONG_SELECTION_DESC=Wähle deinen Song
+SING_SONG_SELECTION_WHEREAMI=Song-Auswahl
+SING_SONG_SELECTION_GOTO=Gehe zu ..
+SING_SONG_SELECTION=Song-Auswahl
+SING_SONG_SELECTION_MENU=Menü
+SING_SONG_SELECTION_PLAYLIST=Playlist
+SING_SONGS_IN_CAT=Songs
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=ZEIT
+SING_TOTAL=Gesamt
+SING_MODE=Singmodus
+SING_NOTES=Noten
+SING_GOLDEN_NOTES=Goldener Ton
+SING_PHRASE_BONUS=Phrasenbonus
+
+SING_MENU=Hauptmenü
+
+SONG_SCORE=Songpunktzahl
+SONG_SCORE_WHEREAMI=Punkte
+
+SING_SCORE_TONE_DEAF=Nichtskönner
+SING_SCORE_AMATEUR=Amateur
+SING_SCORE_WANNABE=Möchtegern
+SING_SCORE_HOPEFUL=Fortgeschritten
+SING_SCORE_RISING_STAR=Sternchen
+SING_SCORE_LEAD_SINGER=Hit-Künstler
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=UltraStar
+
+SING_TOP_5_CHARTS=Top-5-Spieler
+SING_TOP_5_CHARTS_WHEREAMI=Top 5
+SING_TOP_5_CHARTS_CONTINUE=Zur Songauswahl
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=Schwierigkeitsstufen
+
+POPUP_PERFECT=Perfekt!
+POPUP_AWESOME=Cool!
+POPUP_GREAT=Toll!
+POPUP_GOOD=Gut!
+POPUP_NOTBAD=O.K.!
+POPUP_BAD=Schlecht!
+POPUP_POOR=Mies!
+POPUP_AWFUL=Grausam!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= und
+
+SONG_MENU_NAME_MAIN=Menü
+SONG_MENU_PLAY=Singen
+SONG_MENU_CHANGEPLAYERS=Spieler wechseln
+SONG_MENU_EDIT=Editor
+SONG_MENU_MODI=Einen Modus singen
+SONG_MENU_CANCEL=Abbrechen
+
+SONG_MENU_NAME_PLAYLIST=Menü
+SONG_MENU_PLAYLIST_ADD=Song hinzufügen
+SONG_MENU_PLAYLIST_DEL=Song löschen
+
+SONG_MENU_NAME_PLAYLIST_ADD=Song hinzufügen
+SONG_MENU_PLAYLIST_ADD_NEW=Zu neuer Playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=Zu bestehender Playlist
+SONG_MENU_PLAYLIST_NOEXISTING=Keine Playlist vorhanden
+
+SONG_MENU_NAME_PLAYLIST_NEW=Neue Playlist
+SONG_MENU_PLAYLIST_NEW_CREATE=Erstellen
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Unbenannt
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Wirklich löschen?
+SONG_MENU_YES=Ja
+SONG_MENU_NO=Nein
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Playlist öffnen
+SONG_MENU_PLAYLIST_LOAD=öffnen
+SONG_MENU_PLAYLIST_DELCURRENT=Aktuelle Playlist löschen
+
+SONG_MENU_NAME_PLAYLIST_DEL=Playlist löschen?
+
+SONG_MENU_NAME_PARTY_MAIN=Party-Menü
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=Joker einsetzen
+
+SONG_JUMPTO_DESC=Song suchen
+SONG_JUMPTO_TYPE_DESC=Suchen in:
+SONG_JUMPTO_TYPE1=Allem
+SONG_JUMPTO_TYPE2=Titel
+SONG_JUMPTO_TYPE3=Artist
+SONG_JUMPTO_SONGSFOUND=%d Song(s) gefunden
+SONG_JUMPTO_NOSONGSFOUND=Keinen Song gefunden
+SONG_JUMPTO_HELP=Suchtext eingeben
+SONG_JUMPTO_CATTEXT=Suche nach: %s
+
+PARTY_MODE=Party-Modus
+PARTY_DIFFICULTY=Schwierigkeit
+PARTY_PLAYLIST=Playlist-Modus
+PARTY_PLAYLIST_ALL=Alle Lieder
+PARTY_PLAYLIST_CATEGORY=Ordner
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_TEAMS=Anzahl der Teams
+PARTY_TEAMS_PLAYER1=Spieleranzahl
+PARTY_TEAMS_PLAYER2=Spieleranzahl
+PARTY_TEAMS_PLAYER3=Spieleranzahl
+
+PARTY_LEGEND_CONTINUE=weiter
+
+PARTY_OPTIONS_DESC=Einstellungen für das Partyspiel.
+PARTY_OPTIONS_WHEREAMI=Party Optionen
+
+PARTY_PLAYER_DESC=Team- und Spielernamen eingeben.
+PARTY_PLAYER_WHEREAMI=Party Spielernamen
+PARTY_PLAYER_ENTER_NAME=Namen eingeben
+
+
+PARTY_ROUNDS_DESC= Wähle welche Modi du spielen möchtest
+PARTY_ROUNDS_WHEREAMI=Party Runden
+PARTY_ROUNDS_LEGEND_CONTINUE=Partyspiel starten
+PARTY_ROUNDCOUNT=Anzahl der Runden
+PARTY_SELECTMODE1=Modus Runde 1
+PARTY_SELECTMODE2=Modus Runde 2
+PARTY_SELECTMODE3=Modus Runde 3
+PARTY_SELECTMODE4=Modus Runde 4
+PARTY_SELECTMODE5=Modus Runde 5
+PARTY_SELECTMODE6=Modus Runde 6
+PARTY_SELECTMODE7=Modus Runde 7
+
+PARTY_ROUND_DESC=Die nächsten Spieler an die Mikros!
+PARTY_ROUND_WHEREAMI=Party nächste Runde
+PARTY_ROUND_LEGEND_CONTINUE=Runde starten
+
+PARTY_SONG_WHEREAMI=Party Song-Auswahl
+PARTY_SONG_LEGEND_CONTINUE=Singen
+PARTY_SONG_MENU=Party-Menü
+
+PARTY_SCORE_DESC=Punkte der letzten Runde.
+PARTY_SCORE_WHEREAMI=Party Punkte
+
+PARTY_WIN_DESC=Gewinner des Partyspiels.
+PARTY_WIN_WHEREAMI=Party Gewinner
+PARTY_WIN_LEGEND_CONTINUE=Zurück zum Hauptmenü
+
+PARTY_ROUND=Runde
+PARTY_ROUND_WINNER=Sieger
+PARTY_NOTPLAYEDYET=Noch nicht gespielt
+PARTY_NOBODY=Niemand
+NEXT_ROUND=Nächste Runde:
+
+PARTY_DISMISSED=Ausgeschieden!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=hat gewonnen!
+
+MODE_RANDOM_NAME= zufälliger Modus
+MODE_RANDOM_DESC= Wählt einen zufälligen Modus aus
+
+MODE_HOLDTHELINE_NAME=Balken halten
+MODE_HOLDTHELINE_DESC=Halte die Bewertungsanzeige im angezeigten Bereich.
+
+MODE_5000POINTS_NAME=Bis 5000
+MODE_5000POINTS_DESC=Wer zuerst 5000 Punkte hat, gewinnt.
+
+MODE_DUEL_NAME=Duell
+MODE_DUEL_DESC=Normales Spiel. Höchste Punktzahl gewinnt.
+
+MODE_TEAMDUEL_NAME=Teamsingen
+MODE_TEAMDUEL_DESC=Gib das Mikro weiter!
+
+MODE_BLIND_NAME=Blind Modus
+MODE_BLIND_DESC=Erreiche blind die höchste Punktzahl.
+
+STAT_MAIN=Statistiken
+STAT_MAIN_DESC=Allgemein
+STAT_MAIN_WHEREAMI=Statistiken
+
+STAT_OVERVIEW_INTRO=%0:s Statistiken. \n Letzter Reset am %1:.2d.%2:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Songs(%3:d mit Video), davon wurden %1:d schon einmal gesungen und %2:d noch nicht. \n Der am häufigsten gesungene Song ist %5:s von %4:s.
+STAT_OVERVIEW_PLAYER=Seit dem letzten Reset haben %0:d verschiedene Spieler gesungen. \n Der beste Spieler ist %1:s mit %2:d Punkten. \n Die höchste Punktzahl, %4:d, wurde von %3:s erreicht.
+
+STAT_FORMAT_DATE=%0:.2d.%1:.2d.%2:d
+
+STAT_DETAIL=Statistiken
+STAT_DETAIL_WHEREAMI=Detaillierte Statistiken
+
+STAT_NEXT=Nächste Seite
+STAT_PREV=Vorherige Seite
+STAT_REVERSE=Umkehren
+STAT_PAGE=Seite %0:d von %1:d \n (%2:d von %3:d Einträgen)
+
+STAT_DESC_SCORES=Highscores
+STAT_DESC_SCORES_REVERSED=Lowscores
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Beste Sänger
+STAT_DESC_SINGERS_REVERSED=Schlechteste Sänger
+STAT_FORMAT_SINGERS=%0:s \n Durchschnittliche Punktzahl: %1:d
+
+STAT_DESC_SONGS=Beliebteste Songs
+STAT_DESC_SONGS_REVERSED=Unbeliebteste Songs
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx gesungen
+
+STAT_DESC_BANDS=Beliebteste Bands
+STAT_DESC_BANDS_REVERSED=Unbeliebteste Bands
+STAT_FORMAT_BANDS=%0:s \n Gesungene Songs: %1:d
+
+SCREENSHOT_SAVED=Bildschirmfoto gesichert
+SCREENSHOT_FAILED=Konnte Bildschirmfoto nicht sichern
+
+INFO_FILE_SAVED=Datei gesichert
+ERROR_SAVE_FILE_FAILED=Konnte Datei nicht sichern
+ERROR_FILE_NOT_FOUND=Datei nicht gefunden
+
+ENCODING_ERROR_ASK_FOR_UTF8=Änderungen können nicht in der aktuellen Kodierung gesichert werden. Nach UTF-8 konvertieren?
+EDITOR_ERROR_NO_TRACK_SELECTED=Keine Spur ausgewählt
+
+MSG_ERROR_TITLE=Fehler
+MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Frage
+MSG_QUIT_USDX=UltraStar wirklich beenden?
+MSG_END_PARTY=Party-Modus wirklich beenden?
+
+ERROR_NO_SONGS=Keine Songs vorhanden.
+ERROR_NO_PLUGINS=Keine Plugins vorhanden.
+ERROR_NO_MODES_FOR_CURRENT_SETUP=Es sind keine Modi für die akutellen Spieler und/oder Teameinstellungen vorhanden
+ERROR_CAN_NOT_START_PARTY= Ein Fehler ist beim Starten des Partyspiels aufgetreten
+ERROR_CORRUPT_SONG=Song konnte nicht geladen werden.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Song konnte nicht geladen werden: Datei wurde nicht gefunden.
+ERROR_CORRUPT_SONG_NO_NOTES=Song konnte nicht geladen werden: Es wurden keine Noten gefunden.
+ERROR_CORRUPT_SONG_NO_BREAKS=Song konnte nicht geladen werden: Es wurden keine Satzwechsel gefunden.
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Song konnte nicht geladen werden: Fehler beim parsen der Zeile %0:d
+ERROR_NO_EDITOR=Diese Funktion ist unter Linux/Mac noch nicht verfügbar
+ERROR_PLAYER_DEVICE_ASSIGNMENT=Mehrere Mikrofone für Spieler %d gewählt.\nAufnahmeoptionen überprüfen.
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Kein Mikrofon für Spieler %d gewählt.\nAufnahmeoptionen überprüfen.
+;UNUSED: SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Wie oft gesungen mitzählen
diff --git a/songmanagement/game/languages/Greek.ini b/songmanagement/game/languages/Greek.ini
new file mode 100644
index 00000000..99f277f1
--- /dev/null
+++ b/songmanagement/game/languages/Greek.ini
@@ -0,0 +1,443 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Φόρτωνει...
+
+SING_CHOOSE_MODE=Επιλογή τρόπου παιχνιδιού
+SING_SING=Τραγούδηστε
+SING_SING_DESC=Γρήγορο παιχνίδι: Τραγουδήστε σολο ή ντουέτο
+
+SING_MULTI="Πάρτυ"
+SING_MULTI_DESC=Τραγουδήστε σε παιχνίδι "Πάρτυ"
+
+SING_TOOLS=Εργαλεία
+
+SING_STATS=Στατιστικά
+SING_STATS_DESC=Δείτε τα στατιστικά
+
+SING_EDITOR=Δημιουργία
+SING_EDITOR_DESC=Φτιάξτε το δικό σας τραγούδι
+
+SING_GAME_OPTIONS=Επιλογές παιχνιδιού
+SING_GAME_OPTIONS_DESC=Αλλάξτε τις επιλογές του παιχνιδιού
+
+SING_EXIT=Έξοδος
+SING_EXIT_DESC=Έξοδος απο το παιχνίδι
+
+SING_OPTIONS=Επιλογές
+SING_OPTIONS_DESC=Αλλάξτε τις επιλογές
+SING_OPTIONS_WHEREAMI=Επιλογές
+
+SING_OPTIONS_GAME=Παιχνίδι
+SING_OPTIONS_GRAPHICS=Γραφικά
+SING_OPTIONS_SOUND=Ήχος
+SING_OPTIONS_LYRICS=Στίχοι
+SING_OPTIONS_THEMES=Θέματα
+SING_OPTIONS_RECORD=Ηχογράφηση
+SING_OPTIONS_ADVANCED=Για προχωρημένους
+SING_OPTIONS_EXIT=Πίσω
+
+SING_OPTIONS_GAME_WHEREAMI=Επιλογές παιχνιδιού
+SING_OPTIONS_GAME_DESC=Κύριες επιλογές παιχνιδιού
+SING_OPTIONS_GAME_PLAYERS=Παίχτες
+SING_OPTIONS_GAME_DIFFICULTY=Δυσκολία
+SING_OPTIONS_GAME_LANGUAGE=Γλώσσα
+SING_OPTIONS_GAME_TABS=Ετικέτες
+SING_OPTIONS_GAME_SORTING=Ταξινόμιση
+SING_OPTIONS_GAME_DEBUG=Αποσυμφόρηση
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Επιλογές γραφικών
+SING_OPTIONS_GRAPHICS_DESC=Ρυθμίσεις γραφικών
+SING_OPTIONS_GRAPHICS_RESOLUTION=Ανάλυση
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Πλήρης οθόνη
+SING_OPTIONS_GRAPHICS_DEPTH=Βάθος
+SING_OPTIONS_GRAPHICS_VISUALIZER=Κινούμενο φόντο
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Οσκιλοσκόπιο
+SING_OPTIONS_GRAPHICS_LINEBONUS=Μπόνους γραμμής
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Μέγεθος βίντεο
+
+SING_OPTIONS_SOUND_WHEREAMI=Επιλογές ήχου
+SING_OPTIONS_SOUND_DESC=Επιλογές ήχου
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Ήχος μικροφώνου
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Μουσική στο μενού
+SING_OPTIONS_SOUND_MIC_BOOST=Ισχύς μικροφώνου
+SING_OPTIONS_SOUND_CLICK_ASSIST=Βοήθεια με κλίκ
+SING_OPTIONS_SOUND_BEAT_CLICK=Βοήθεια ρυθμού
+SING_OPTIONS_SOUND_THRESHOLD=Ευαισθησία μικροφώνου
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Με δύο παίχτες
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Ένταση προεπισκόπισης
+SING_OPTIONS_SOUND_PREVIEWFADING=Σβήσιμο προεπισκόπισης
+
+SING_OPTIONS_LYRICS_WHEREAMI=Επιλογές στίχων
+SING_OPTIONS_LYRICS_DESC=Ρυθμίσιες στίχων
+SING_OPTIONS_LYRICS_FONT=Γραμματοσειρά
+SING_OPTIONS_LYRICS_EFFECT=Εφέ
+SING_OPTIONS_LYRICS_SOLMIZATION=Εμφάνιση νότας αντί στίχων
+SING_OPTIONS_LYRICS_NOTELINES=Πεντάγραμμο
+
+SING_OPTIONS_THEMES_WHEREAMI=Επιλογές θεμάτων
+SING_OPTIONS_THEMES_DESC=Ρυθμίσεις θεμάτων
+SING_OPTIONS_THEMES_THEME=Θέμα
+SING_OPTIONS_THEMES_SKIN=Μορφή θέματος
+SING_OPTIONS_THEMES_COLOR=Χρώμα
+
+SING_OPTIONS_RECORD_WHEREAMI=Επιλογές μικροφώνου
+SING_OPTIONS_RECORD_DESC=Ρυθμίσεις μικροφώνου
+SING_OPTIONS_RECORD_CARD=Κάρτα ήχου
+SING_OPTIONS_RECORD_INPUT=Επιλογή μικροφώνου
+SING_OPTIONS_RECORD_CHANNEL=Κανάλι
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Επιλογές για προχωρημένους
+SING_OPTIONS_ADVANCED_DESC=Ρυθμίσεις για προχωρημένους
+SING_OPTIONS_ADVANCED_EFFECTSING=Εφέ τραγουδιού
+SING_OPTIONS_ADVANCED_SCREENFADE=Σβήσιμο εικόνας
+SING_OPTIONS_ADVANCED_LOADANIMATION=Φόρτωση κινούμενων εικόνων
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Ερωτήσεις ασφαλείας
+SING_OPTIONS_ADVANCED_LINEBONUS=Μπόνους γραμμής
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Μετά απο την επιλογή τραγουδιού
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Αυτόματο μενού "Πάρτυ"
+
+SING_EDIT=Δημιουργία
+SING_EDIT_MENU_DESCRIPTION=Φτιάξτε το δικό σας τραγούδι
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Εισαγωγή αρχείου κειμένου
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Πίσω
+SING_EDIT_BUTTON_CONVERT=Εισαγωγή
+SING_EDIT_BUTTON_EXIT=Πίσω
+
+SING_EDIT_NAVIGATE=Εξερέυνηση
+SING_EDIT_SELECT=Επέλεξε
+SING_EDIT_EXIT=Πίσω
+
+SING_LEGEND_SELECT=Επέλεξε
+SING_LEGEND_NAVIGATE=Εξερέυνηση
+SING_LEGEND_CONTINUE=Συνέχισε
+SING_LEGEND_ESC=Πίσω
+
+SING_PLAYER_DESC=Γράψε ονόμα(τα) παιχτ-η/ων
+SING_PLAYER_WHEREAMI=Ονόματα παιχτών
+SING_PLAYER_ENTER_NAME=Γράψε όνομα
+
+SING_DIFFICULTY_DESC=Διάλεξε δυσκολία
+SING_DIFFICULTY_WHEREAMI=Δυσκολία
+SING_DIFFICULTY_CONTINUE=Στην επιλογή τραγουδιού
+SING_EASY=Εύκολο
+SING_MEDIUM=Μέτριο
+SING_HARD=Δύσκολο
+
+SING_SONG_SELECTION_DESC=Διάλεξε τραγούδι
+SING_SONG_SELECTION_WHEREAMI=Επιλογή τραγουδιού
+SING_SONG_SELECTION_GOTO=Πήγαινε σε...
+SING_SONG_SELECTION=Επιλογή τραγουδιου
+SING_SONG_SELECTION_MENU=Μενού
+SING_SONG_SELECTION_PLAYLIST=Λίστα
+SING_SONGS_IN_CAT=Τραγούδια
+PLAYLIST_CATTEXT=Λίστα: %s
+
+SING_TIME=Χρόνος
+SING_TOTAL=Σύνολο
+SING_MODE=Τραγούδα σόλο
+SING_NOTES=Νότες
+SING_GOLDEN_NOTES=Χρυσές νότες
+SING_PHRASE_BONUS=Μπόνους γραμμής
+
+SING_MENU=Κύριο μενού
+
+SONG_SCORE=Βαθμολογία τραγουδιού
+SONG_SCORE_WHEREAMI=Βαθμολογία
+
+SING_SCORE_TONE_DEAF=Κακοφωνίξ
+SING_SCORE_AMATEUR=Αρχάριος
+SING_SCORE_WANNABE=Το θέλει...
+SING_SCORE_HOPEFUL=Ελπιδοφόρος
+SING_SCORE_RISING_STAR=Ανερχόμενο αστέρι
+SING_SCORE_LEAD_SINGER=Επαγγελματίας
+SING_SCORE_SUPERSTAR=Σούπερσταρ
+SING_SCORE_ULTRASTAR=Απόλυτος σταρ
+
+SING_TOP_5_CHARTS=Οι καλύτεροι 5 παίχτες
+SING_TOP_5_CHARTS_WHEREAMI=Τοπ 5
+SING_TOP_5_CHARTS_CONTINUE=Στην επιλογή τραγουδιού
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=Τέλεια!
+POPUP_AWESOME=Φανταστικά!
+POPUP_GREAT=Πολύ καλά!
+POPUP_GOOD=Καλά!
+POPUP_NOTBAD=Οχι άσχημα!
+POPUP_BAD=Άσχημα!
+POPUP_POOR=πολύ άσχημα!
+POPUP_AWFUL=Απαίσια!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= και 
+
+SONG_MENU_NAME_MAIN=Μενού τραγουδιών
+SONG_MENU_PLAY=Τραγουδήστε
+SONG_MENU_CHANGEPLAYERS=Αλλάξτε παίχτες
+SONG_MENU_EDIT=Επεξεργασία
+SONG_MENU_MODI=Τραγουδήστε μιά τροποποίηση
+SONG_MENU_CANCEL=Ακύρωση
+
+SONG_MENU_NAME_PLAYLIST=Μενού τραγουδιού
+SONG_MENU_PLAYLIST_ADD=Πρόσθεσε τραγούδι
+SONG_MENU_PLAYLIST_DEL=Διέγραψε τραγούδι
+
+SONG_MENU_NAME_PLAYLIST_ADD=Πρόσθεσε τραγούδι
+SONG_MENU_PLAYLIST_ADD_NEW=Σε νέα λίστα
+SONG_MENU_PLAYLIST_ADD_EXISTING=Σε υπάρχουσα λίστα
+SONG_MENU_PLAYLIST_NOEXISTING=Δεν υπάρχει διαθέσιμη λίστα
+
+SONG_MENU_NAME_PLAYLIST_NEW=Νέα λίστα
+SONG_MENU_PLAYLIST_NEW_CREATE=Φτιαξε νέα
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Χωρίς όνομα
+
+;TODO: SONG_MENU_NAME_PLAYLIST_DELITEM=Really Delete?
+SONG_MENU_YES=Ναι
+SONG_MENU_NO=Όχι
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Άνοιξε μια λίστα
+SONG_MENU_PLAYLIST_LOAD=Άνοιξε
+SONG_MENU_PLAYLIST_DELCURRENT=Διέγραψε αυτή τη λίστα
+
+SONG_MENU_NAME_PLAYLIST_DEL=Διαγραφή?
+
+SONG_MENU_NAME_PARTY_MAIN=Μενού "Πάρτυ"
+SONG_MENU_JOKER=Μπαλαντέρ
+
+SONG_MENU_NAME_PARTY_JOKER=Επιλογή μπαλαντέρ
+
+SONG_JUMPTO_DESC=Ψάξε τραγούδι
+SONG_JUMPTO_TYPE_DESC=Ψάξε για:
+SONG_JUMPTO_TYPE1=Όλα
+SONG_JUMPTO_TYPE2=Τίτλος
+SONG_JUMPTO_TYPE3=Καλλιτέχνης
+SONG_JUMPTO_SONGSFOUND=%d Τραγούδι(α) βρέθηκαν
+SONG_JUMPTO_NOSONGSFOUND=Δεν βρέθηκε τραγούδι
+SONG_JUMPTO_HELP=Γράψε κείμενο για αναζήτηση
+SONG_JUMPTO_CATTEXT=Αναζήτηση για: %s
+
+PARTY_MODE=Είδος παιχνιδιού "Πάρτυ"
+PARTY_DIFFICULTY=Δυσκολία
+PARTY_PLAYLIST=Παίξε με μία λίστα
+PARTY_PLAYLIST_ALL=Όλα τα τραγούδια
+PARTY_PLAYLIST_CATEGORY=Φάκελος
+PARTY_PLAYLIST_PLAYLIST=Λίστα
+PARTY_TEAMS=Ομάδες
+PARTY_TEAMS_PLAYER1=Παίχτης ομάδα1
+PARTY_TEAMS_PLAYER2=Παίχτης ομάδα2
+PARTY_TEAMS_PLAYER3=Παίχτης ομάδα3
+
+PARTY_LEGEND_CONTINUE=Συνέχεια
+
+PARTY_OPTIONS_DESC=Επιλογές για το παιχνίδι "Πάρτυ"
+PARTY_OPTIONS_WHEREAMI=Επιλογές "Πάρτυ"
+
+PARTY_PLAYER_DESC=Γράψε ονόματα παιχτών και ομάδων
+PARTY_PLAYER_WHEREAMI=Ονόματα "Πάρτυ"
+PARTY_PLAYER_ENTER_NAME=Γράψε ονόματα
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=Ξεκίνα το παιχνίδι "Πάρτυ"
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=Επόμενοι παίχτες
+PARTY_ROUND_WHEREAMI=Επόμενος γύρος "Πάρτυ"
+PARTY_ROUND_LEGEND_CONTINUE=Ξεκίνα το γύρο
+
+PARTY_SONG_WHEREAMI=Επιλογή τραγουδιού "Πάρτυ"	 
+PARTY_SONG_LEGEND_CONTINUE=Τραγουδήστε	 
+PARTY_SONG_MENU=Μενού "Πάρτυ"
+
+PARTY_SCORE_DESC=Βαθμολογία τελευταίου γύρου
+PARTY_SCORE_WHEREAMI=Βαθμοί "Πάρτυ"
+
+PARTY_WIN_DESC=Νικητής του παιχνιδιού "Πάρτυ"
+PARTY_WIN_WHEREAMI=Νικητής "Πάρτυ"
+PARTY_WIN_LEGEND_CONTINUE=Επιστροφή στο κύριο μενού
+
+PARTY_ROUND=Γύρος
+PARTY_ROUND_WINNER=Νικητής
+PARTY_NOTPLAYEDYET=Δεν παίχτηκε ακόμη
+PARTY_NOBODY=Κανείς
+NEXT_ROUND=Επόμενος Γύρος:
+
+PARTY_DISMISSED=Αποβολή!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=Νίκησε!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Μείνε πάνω από τη μπάρα!
+MODE_HOLDTHELINE_DESC=Μείνε πάνω από τη μπάρα που εμφανίζεται
+
+MODE_5000POINTS_NAME=Μέχρι 5000 πόντους
+MODE_5000POINTS_DESC=Όποιος φτάσει τους 5000 πόντους κερδίζει
+
+MODE_DUEL_NAME=Μονομαχία
+MODE_DUEL_DESC=Τραγουδήστε σε μονομαχία μέχρι τους 10000 πόντους
+
+MODE_TEAMDUEL_NAME=Μονομαχία ομάδων
+MODE_TEAMDUEL_DESC=Δώσε το μικρόφωνο!
+
+MODE_BLIND_NAME=Στα τυφλά
+MODE_BLIND_DESC=Μονομαχία χωρίς να βλέπετε τις νότες
+
+STAT_MAIN=Στατιστικά
+STAT_MAIN_DESC=Κύρια
+STAT_MAIN_WHEREAMI=Στατιστικά
+
+STAT_OVERVIEW_INTRO=%0:s Στατιστικά.  \n Τελευταία έξοδος στίς %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d τραγούδια(%3:d με βίντεο), άπο τα οποία %1:d έχουν παιχτεί ήδη και %2:d δεν έχουν παιχτεί ακόμη.\n Το πιο δημοφιλές τραγούδι είναι %5:s από %4:s.
+STAT_OVERVIEW_PLAYER=Από το τελευταίο σβήσιμο υπάρχει-ουν %0:d παίχτης-ες .\n Ο καλύτερος παίχτης είναι %1:s με μέσο όρο βαθμολογίας %2:d βαθμούς.\n %3:s έκανε τη μεγαλύτερη βαθμολογία με %4:d βαθμούς.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Στατιστικά
+STAT_DETAIL_WHEREAMI=Λεπτομερή στατιστικά
+
+STAT_NEXT=Επόμενη Σελίδα
+STAT_PREV=Προηγούμενη σελίδα
+STAT_REVERSE=Αντίστροφα
+STAT_PAGE=Seite %0:d από %1:d σελίδες\n (%2:d of %3:d εισαγωγές)
+
+STAT_DESC_SCORES=Υψηλότερες Βαθμολογίες
+STAT_DESC_SCORES_REVERSED=Χαμηλότερες βαθμολογίες
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Καλύτεροι τραγουδιστές
+STAT_DESC_SINGERS_REVERSED=Χειρότεροι τραγουδιστές
+STAT_FORMAT_SINGERS=%0:s \n Μέσος όρος βαθμολογίας: %1:d
+
+STAT_DESC_SONGS=Πιο δημοφιλή τραγούδια
+STAT_DESC_SONGS_REVERSED=Λιγότερο δημοφιλή τραγούδια
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx τραγουδήθηκαν
+
+STAT_DESC_BANDS=Πιο δημοφιλής μπάντες
+STAT_DESC_BANDS_REVERSED=Λιγότερο δημοφιλής μπάντες
+STAT_FORMAT_BANDS=%0:s \n %1:dx τραγουδήθηκαν
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Σφάλμα
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Ερώτηση
+MSG_QUIT_USDX=Έξοδος από το παιχνίδι?
+MSG_END_PARTY=Έξοδος απο το παιχνίδι "Πάρτυ"?
+
+ERROR_NO_SONGS=Δεν φορτώθηκαν τραγούδια 
+ERROR_NO_PLUGINS=Δεν φορτώθηκαν βοηθητικές εφαρμογές
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Τα τραγούδια δεν ήταν δυνατό να φορτώσουν
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Το τραγούδι δεν ήταν δυνατό να φορτώσει: Το αρχείο δεν βρέθηκε
+ERROR_CORRUPT_SONG_NO_NOTES=Το τραγούδι δεν ήταν δυνατό να φορτώσει: Δεν βρέθηκαν νότες
+ERROR_CORRUPT_SONG_NO_BREAKS=Το τραγούδι δεν ήταν δυνατό να φορτώσει: Δεν βρέθηκαν κενά ανάμεσα στις νότες
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Το τραγούδι δεν ήταν δυνατό να φορτώσει: Λάθος στην επικόληση της γραμμής %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: PARTY_ROUNDS=Γύροι
+;TRANSLATOR: Leo 21
diff --git a/songmanagement/game/languages/Hungarian.ini b/songmanagement/game/languages/Hungarian.ini
new file mode 100644
index 00000000..81cad7fd
--- /dev/null
+++ b/songmanagement/game/languages/Hungarian.ini
@@ -0,0 +1,441 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+OPTION_VALUE_HUNGARIAN=Magyar
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+OPTION_VALUE_EASY=Könnyű
+OPTION_VALUE_MEDIUM=Normál
+OPTION_VALUE_HARD=Nehéz
+
+OPTION_VALUE_ON=Be
+OPTION_VALUE_OFF=Ki
+
+OPTION_VALUE_EDITION=Verzió
+OPTION_VALUE_GENRE=Műfaj
+OPTION_VALUE_LANGUAGE=Nyelv
+OPTION_VALUE_FOLDER=Mappa
+OPTION_VALUE_TITLE=Cím
+OPTION_VALUE_ARTIST=Előadó
+OPTION_VALUE_TITLE2=Cím2
+OPTION_VALUE_ARTIST2=Előadó2
+
+OPTION_VALUE_WHENNOVIDEO=Ha nincs videó
+
+OPTION_VALUE_SMALL=Kicsi
+OPTION_VALUE_BIG=Nagy
+
+OPTION_VALUE_HALF=Fél
+OPTION_VALUE_FULL_VID=Egész (Video)
+OPTION_VALUE_FULL_VID_BG=Egész (háttér & Video)
+
+OPTION_VALUE_AUTO=Automatikus
+OPTION_VALUE_SEC=Másodperc
+OPTION_VALUE_SECS=Másodperc
+
+OPTION_VALUE_PLAIN=Egyszerű
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Sima
+OPTION_VALUE_ZOOM=Zoom
+OPTION_VALUE_SLIDE=Csúszó
+OPTION_VALUE_BALL=Labda
+OPTION_VALUE_SHIFT=Nagy
+
+OPTION_VALUE_EURO=Euro
+OPTION_VALUE_JAPAN=Japán
+OPTION_VALUE_AMERICAN=Amerikai
+
+OPTION_VALUE_BLUE=Kék
+OPTION_VALUE_GREEN=Zöld
+OPTION_VALUE_PINK=Rózsaszín
+OPTION_VALUE_RED=Piros
+OPTION_VALUE_VIOLET=Lila
+OPTION_VALUE_ORANGE=Narancs
+OPTION_VALUE_YELLOW=Sárga
+OPTION_VALUE_BROWN=Barna
+OPTION_VALUE_BLACK=Fekete
+
+OPTION_VALUE_SING=dalválasztás
+OPTION_VALUE_SELECT_PLAYERS=játékos választás
+OPTION_VALUE_OPEN_MENU=Menü megnyitása
+
+OPTION_VALUE_HARDWARE_CURSOR=Hardver Kurzor
+OPTION_VALUE_SOFTWARE_CURSOR=Softver Kurzor
+
+SING_LOADING=Betöltés...
+
+SING_CHOOSE_MODE=válassz menüpontot
+SING_SING=ének
+SING_SING_DESC=gyors játék: énekelj egyedül vagy duettet
+
+SING_MULTI=Buli
+SING_MULTI_DESC=énekelj buli módban
+
+SING_TOOLS=eszközök
+
+SING_STATS=statisztika
+SING_STATS_DESC=nézd meg a statisztikát
+
+SING_EDITOR=szerkesztő
+SING_EDITOR_DESC=készíts saját zenét
+
+SING_GAME_OPTIONS=játék beállításai
+SING_GAME_OPTIONS_DESC=változtasd meg a beállításokat
+
+SING_EXIT=kilépés
+SING_EXIT_DESC=kilépés a játékból
+
+SING_OPTIONS=beállítások
+SING_OPTIONS_DESC=beállítások megváltoztatása
+SING_OPTIONS_WHEREAMI=beállítások
+
+SING_OPTIONS_GAME=játék
+SING_OPTIONS_GRAPHICS=grafika
+SING_OPTIONS_SOUND=hang
+SING_OPTIONS_LYRICS=szöveg
+SING_OPTIONS_THEMES=téma
+SING_OPTIONS_RECORD=felvétel
+SING_OPTIONS_ADVANCED=haladó
+SING_OPTIONS_EXIT=vissza
+
+SING_OPTIONS_GAME_WHEREAMI=játékbeállítások
+SING_OPTIONS_GAME_DESC=általános beállítások
+SING_OPTIONS_GAME_PLAYERS=játékosok
+SING_OPTIONS_GAME_DIFFICULTY=nehézség
+SING_OPTIONS_GAME_LANGUAGE=nyelv
+SING_OPTIONS_GAME_TABS=elválasztók
+SING_OPTIONS_GAME_SORTING=rendezés
+SING_OPTIONS_GAME_DEBUG=hibakezelő mód
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=grafikai beállítások
+SING_OPTIONS_GRAPHICS_DESC=grafika beállítása
+SING_OPTIONS_GRAPHICS_RESOLUTION=felbontás
+SING_OPTIONS_GRAPHICS_FULLSCREEN=teljes képernyő
+SING_OPTIONS_GRAPHICS_DEPTH=színmélység
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualization
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=oszcilloszkóp
+SING_OPTIONS_GRAPHICS_LINEBONUS=sáv bónusz
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=videó mérete
+
+SING_OPTIONS_SOUND_WHEREAMI=hang beállításai
+SING_OPTIONS_SOUND_DESC=hangbeállítások
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Microphone Playback
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Background music
+SING_OPTIONS_SOUND_MIC_BOOST=mikr. erősítése
+SING_OPTIONS_SOUND_CLICK_ASSIST=ütem segítség
+SING_OPTIONS_SOUND_BEAT_CLICK=Ütem
+SING_OPTIONS_SOUND_THRESHOLD=tűréshatár
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=két játékos mód
+SING_OPTIONS_SOUND_PREVIEWVOLUME=előzetes hang
+SING_OPTIONS_SOUND_PREVIEWFADING=előz. hang késése
+
+SING_OPTIONS_LYRICS_WHEREAMI=szöveg beállítások
+SING_OPTIONS_LYRICS_DESC=szöveg beállítása
+SING_OPTIONS_LYRICS_FONT=betűtípus
+SING_OPTIONS_LYRICS_EFFECT=effektek
+SING_OPTIONS_LYRICS_SOLMIZATION=szolmizáció
+SING_OPTIONS_LYRICS_NOTELINES=Staves
+
+SING_OPTIONS_THEMES_WHEREAMI=téma beállítása
+SING_OPTIONS_THEMES_DESC=téma és kinézet beállítása
+SING_OPTIONS_THEMES_THEME=téma
+SING_OPTIONS_THEMES_SKIN=háttér
+SING_OPTIONS_THEMES_COLOR=szín
+
+SING_OPTIONS_RECORD_WHEREAMI=felvétel beállítása
+SING_OPTIONS_RECORD_DESC=mikrofon beállítás
+SING_OPTIONS_RECORD_CARD=hangkártya
+SING_OPTIONS_RECORD_INPUT==bement
+SING_OPTIONS_RECORD_CHANNEL=csatorna:
+
+SING_OPTIONS_ADVANCED_WHEREAMI=haladó beállítások
+SING_OPTIONS_ADVANCED_DESC=további beállítások
+SING_OPTIONS_ADVANCED_EFFECTSING=hang effektek
+SING_OPTIONS_ADVANCED_SCREENFADE=háttér áttűnése
+SING_OPTIONS_ADVANCED_LOADANIMATION=betöltési animáció
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=megerősítést kér
+SING_OPTIONS_ADVANCED_LINEBONUS=sáv bónusz
+SING_OPTIONS_ADVANCED_ONSONGCLICK=éneklés után
+SING_OPTIONS_ADVANCED_PARTYPOPUP=partymenü megj.
+
+SING_EDIT=szerkesztő
+SING_EDIT_MENU_DESCRIPTION=készíts saját zenét
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importálj szöveget midiből
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=vissza
+SING_EDIT_BUTTON_CONVERT=Importálás
+SING_EDIT_BUTTON_EXIT=Vissza
+
+SING_EDIT_NAVIGATE=Navigálás
+SING_EDIT_SELECT=Választás
+SING_EDIT_EXIT=Vissza
+
+SING_LEGEND_SELECT=Választás
+SING_LEGEND_NAVIGATE=Navigálás
+SING_LEGEND_CONTINUE=Folytatás
+SING_LEGEND_ESC=Vissza
+
+SING_PLAYER_DESC=Kérem a játékos(ok) nevét
+SING_PLAYER_WHEREAMI=Játékos Neve
+SING_PLAYER_ENTER_NAME=Név
+
+SING_DIFFICULTY_DESC=Nehézségi szint választása
+SING_DIFFICULTY_WHEREAMI=Nehézség
+SING_DIFFICULTY_CONTINUE=Szám kiválasztása
+SING_EASY=Könnyű
+SING_MEDIUM=Normál
+SING_HARD=Nehéz
+
+SING_SONG_SELECTION_DESC=Válassz számot
+SING_SONG_SELECTION_WHEREAMI=Szám választása
+SING_SONG_SELECTION_GOTO=Szám keresés
+SING_SONG_SELECTION=Szám választása
+SING_SONG_SELECTION_MENU=Menü
+SING_SONG_SELECTION_PLAYLIST=számlista
+SING_SONGS_IN_CAT=Számok
+PLAYLIST_CATTEXT=Számlista: %s
+
+SING_TIME=Idő
+SING_TOTAL=Összesen
+SING_MODE=Egyszeri játékos
+SING_NOTES=Hang
+SING_GOLDEN_NOTES=Arany pont
+SING_PHRASE_BONUS=Sáv bónusz
+
+SING_MENU=Főmenü
+
+SONG_SCORE=Szám pontok
+SONG_SCORE_WHEREAMI=Pontok
+
+SING_SCORE_TONE_DEAF=Pontszámok
+SING_SCORE_AMATEUR=Amatőr
+SING_SCORE_WANNABE=Wannabe
+SING_SCORE_HOPEFUL=Hopeful
+SING_SCORE_RISING_STAR=Kezdő Sztár
+SING_SCORE_LEAD_SINGER=Főállású énekes
+SING_SCORE_SUPERSTAR=Szupersztár
+SING_SCORE_ULTRASTAR=Ultrasztár
+
+SING_TOP_5_CHARTS=Legjobb 5 játékos
+SING_TOP_5_CHARTS_WHEREAMI=Legjobb 5
+SING_TOP_5_CHARTS_CONTINUE=Szám kiválasztás
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=Hibátlan!
+POPUP_AWESOME=Nagyon jó!
+POPUP_GREAT=Elég Jó!
+POPUP_GOOD=Jó!
+POPUP_NOTBAD=Elmegy!
+POPUP_BAD=Rossz!
+POPUP_POOR=Gyenge!
+POPUP_AWFUL=Borzalmas!
+
+IMPLODE_GLUE1=, 
+IMPLODE_GLUE2= és 
+
+SONG_MENU_NAME_MAIN=Szám menü
+SONG_MENU_PLAY=Szám
+SONG_MENU_CHANGEPLAYERS=Váltó játékosok
+SONG_MENU_EDIT=Edit
+SONG_MENU_MODI=Énekeljegy modi-t 
+SONG_MENU_CANCEL=Mégsem
+
+SONG_MENU_NAME_PLAYLIST=Song Menu
+SONG_MENU_PLAYLIST_ADD=Hozzáad
+SONG_MENU_PLAYLIST_DEL=Töröl
+
+SONG_MENU_NAME_PLAYLIST_ADD=Hozzáad
+SONG_MENU_PLAYLIST_ADD_NEW=Új Számlista
+SONG_MENU_PLAYLIST_ADD_EXISTING=Kilépés a Számlistából
+SONG_MENU_PLAYLIST_NOEXISTING=Nem elérhető a számlista
+
+SONG_MENU_NAME_PLAYLIST_NEW=Új Számlista
+SONG_MENU_PLAYLIST_NEW_CREATE=Létrehoz
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Névtelen
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Biztos Törli?
+SONG_MENU_YES=Igen
+SONG_MENU_NO=Nem
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Számlista megnyitása
+SONG_MENU_PLAYLIST_LOAD=Megnyit
+SONG_MENU_PLAYLIST_DELCURRENT=Törli a számlistát
+
+SONG_MENU_NAME_PLAYLIST_DEL=Törli a számlistát?
+
+SONG_MENU_NAME_PARTY_MAIN=Buli Menu
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=joker felhasználása
+
+SONG_JUMPTO_DESC=Tovább
+SONG_JUMPTO_TYPE_DESC=Keresés:
+SONG_JUMPTO_TYPE1=Összes
+SONG_JUMPTO_TYPE2=Cím
+SONG_JUMPTO_TYPE3=Előadó
+SONG_JUMPTO_SONGSFOUND=%d Szám(ok) találat
+SONG_JUMPTO_NOSONGSFOUND=Nincs szám találat
+SONG_JUMPTO_HELP=Text típusú fájl keresése
+SONG_JUMPTO_CATTEXT=Keresés: %s
+
+PARTY_MODE=Buli mód
+PARTY_DIFFICULTY=Nehézségi Szint
+PARTY_PLAYLIST=Listából éneklés
+PARTY_PLAYLIST_ALL=Minden dal
+PARTY_PLAYLIST_CATEGORY=Mappa
+PARTY_PLAYLIST_PLAYLIST=Számlista
+PARTY_TEAMS=Csapat
+PARTY_TEAMS_PLAYER1=Csapat1
+PARTY_TEAMS_PLAYER2=Csapat2
+PARTY_TEAMS_PLAYER3=Csapat3
+
+PARTY_LEGEND_CONTINUE=Folytatás
+
+PARTY_OPTIONS_DESC=Buli beállításai
+PARTY_OPTIONS_WHEREAMI=Buli Beállítások
+
+PARTY_PLAYER_DESC=Név- és Csapatnév!
+PARTY_PLAYER_WHEREAMI=Buli nevek
+PARTY_PLAYER_ENTER_NAME=Nevek
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+;TODO: PARTY_ROUNDS_LEGEND_CONTINUE=start party-game
+PARTY_ROUNDCOUNT=number of rounds
+PARTY_SELECTMODE1=mode round 1
+PARTY_SELECTMODE2=mode round 2
+PARTY_SELECTMODE3=mode round 3
+PARTY_SELECTMODE4=mode round 4
+PARTY_SELECTMODE5=mode round 5
+PARTY_SELECTMODE6=mode round 6
+PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=következő játékosok a mikrofonhoz
+PARTY_ROUND_WHEREAMI=Következő forduló
+PARTY_ROUND_LEGEND_CONTINUE=Indul a menet
+
+PARTY_SONG_WHEREAMI=Buli szám választása	 
+PARTY_SONG_LEGEND_CONTINUE=Szám 	 
+PARTY_SONG_MENU=Buli menü
+
+PARTY_SCORE_DESC=Pontok az elöző fordulóból
+PARTY_SCORE_WHEREAMI=Buli pontok
+
+PARTY_WIN_DESC=Nyert a Buli játékban
+PARTY_WIN_WHEREAMI=Buli Nyertes
+PARTY_WIN_LEGEND_CONTINUE=Vissza a főmenübe
+
+PARTY_ROUND=Forduló
+PARTY_ROUND_WINNER=Nyertes
+PARTY_NOTPLAYEDYET=Nem játszott szám
+PARTY_NOBODY=Senki
+NEXT_ROUND=Következő menet:
+
+PARTY_DISMISSED=Hibátlan!
+PARTY_SCORE_WINS=%s 
+PARTY_SCORE_WINS2=Nem nyert!
+
+MODE_RANDOM_NAME=Random Mode
+MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Tartsd a sávot!
+MODE_HOLDTHELINE_DESC=Ne csinálj rosszabb pontszámot mint az elözőek, mert nem jelensz majd meg a Toplistán.
+
+MODE_5000POINTS_NAME=5000-ig
+MODE_5000POINTS_DESC=Ki éri el az 5000 pontot az első meccsen?
+
+MODE_DUEL_NAME=Ketten
+MODE_DUEL_DESC=Ketten énekeljetek 10000 pontig.
+
+MODE_TEAMDUEL_NAME=Team Duell
+MODE_TEAMDUEL_DESC=Pass The Mic!
+
+MODE_BLIND_NAME="Vak Mód"
+MODE_BLIND_DESC=Énekeljetek ketten kotta nélkül.
+
+STAT_MAIN=Statisztikák
+STAT_MAIN_DESC=Általános
+STAT_MAIN_WHEREAMI=Statisztika
+
+STAT_OVERVIEW_INTRO=%0:s Statistics.  \n Last Reset at %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Számok(%3:d Video-val), Melyből %1:d Lejátszott  és %2:d Még nem.\n Legtöbbet hallgatott: %5:s  %4:s-tól/től
+STAT_OVERVIEW_PLAYER=A játék kezdetétől %0:d játékos(ok) játszottak.\n A legjobb játékos: %1:s Átlageredménye: %2:d Pont.\n %3:s Legjobb eredménye: %4:d Pont.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statisztika
+STAT_DETAIL_WHEREAMI=Részletes
+
+STAT_NEXT=Következő oldal
+STAT_PREV=Elöző oldal
+STAT_REVERSE=Ellenkező sorrend
+STAT_PAGE=Seite %0:d of %1:d Oldalak\n (%2:d of %3:d Entrys)
+
+STAT_DESC_SCORES=Legjobb eredmény
+STAT_DESC_SCORES_REVERSED=Alacsony pontszám
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s] \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Legjobb énekesek
+STAT_DESC_SINGERS_REVERSED=Legrosszagg játékosok
+STAT_FORMAT_SINGERS=%0:s \n Átlag pontszám: %1:d
+
+STAT_DESC_SONGS=Közkedvelt számok
+STAT_DESC_SONGS_REVERSED=Kevésbé kedvelt számok
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx sung
+
+STAT_DESC_BANDS=Közkedvelt együttesek
+STAT_DESC_BANDS_REVERSED=Kevésbé kedvelt együttesek
+STAT_FORMAT_BANDS=%0:s \n %1:dx Ének
+
+SCREENSHOT_SAVED=Képeryő mentve
+SCREENSHOT_FAILED=Képernyő mentése sikertelen
+
+INFO_FILE_SAVED=Fájl mentve
+ERROR_SAVE_FILE_FAILED=Fájl mentése sikertelen 
+ERROR_FILE_NOT_FOUND=Fájl nem található
+
+ENCODING_ERROR_ASK_FOR_UTF8=A változtatások nem menthetők ebben a kódolásban. Konvertáljuk UTF-8-á?
+EDITOR_ERROR_NO_TRACK_SELECTED=Nincs szám kiválasztva
+
+MSG_ERROR_TITLE=Hiba
+MSG_INFO_TITLE=Infó
+MSG_QUESTION_TITLE=Kérdés
+MSG_QUIT_USDX=Tényleg elhagyod az UltraStar színpadát?
+MSG_END_PARTY=Tényleg kilépsz a Buli módból?
+
+ERROR_NO_SONGS=Nincs dal betöltve
+ERROR_NO_PLUGINS=Nincs plugin betöltve
+ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+ERROR_CAN_NOT_START_PARTY= an error occurred starting the party game
+ERROR_CORRUPT_SONG=Sikertelen dalbetöltés.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Sikertelen dalbetöltés: Dal nem található
+ERROR_CORRUPT_SONG_NO_NOTES=Sikertelen dalbetöltés: Nincs kotta hozzá
+ERROR_CORRUPT_SONG_NO_BREAKS=Sikertelen dalbetöltés: Nincs benne sortörés
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Sikertelen dalbetöltés: Sikertelen elemzési sor %0:d
+ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d was assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
diff --git a/songmanagement/game/languages/Icelandic.ini b/songmanagement/game/languages/Icelandic.ini
new file mode 100644
index 00000000..fb46644b
--- /dev/null
+++ b/songmanagement/game/languages/Icelandic.ini
@@ -0,0 +1,443 @@
+[Text]
+OPTION_VALUE_CATALAN=katalónska
+OPTION_VALUE_CROATIAN=króatíska
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+OPTION_VALUE_DUTCH=hollenska
+OPTION_VALUE_ENGLISH=enska
+OPTION_VALUE_EUSKARA=baskneska
+OPTION_VALUE_FINNISH=finnska
+OPTION_VALUE_FRENCH=franska
+OPTION_VALUE_GERMAN=Þýska
+OPTION_VALUE_GREEK=gríska
+OPTION_VALUE_HUNGARIAN=Hungarian
+OPTION_VALUE_ICELANDIC=íslenska
+OPTION_VALUE_ITALIAN=ítalska
+OPTION_VALUE_JAPANESE=japanska
+OPTION_VALUE_LUXEMBOURGISH=lúxemborgíska
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+OPTION_VALUE_PORTUGUESE=portúgalska
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+OPTION_VALUE_SPANISH=spænska
+OPTION_VALUE_SWEDISH=sænska
+
+OPTION_VALUE_EASY=Auðvelt
+OPTION_VALUE_MEDIUM=Miðlungs
+OPTION_VALUE_HARD=Erfitt
+
+OPTION_VALUE_ON=Kveikt
+OPTION_VALUE_OFF=Slökkt
+
+OPTION_VALUE_EDITION=Útgáfa 
+OPTION_VALUE_GENRE=Stíll
+OPTION_VALUE_LANGUAGE=Tungumál
+OPTION_VALUE_FOLDER=Mappa
+OPTION_VALUE_TITLE=Titill
+OPTION_VALUE_ARTIST=Flytjandi 
+OPTION_VALUE_TITLE2=Titill2
+OPTION_VALUE_ARTIST2=Flytjandi2
+
+OPTION_VALUE_WHENNOVIDEO=Þegar ekkert myndband
+
+OPTION_VALUE_SMALL=Lítill
+OPTION_VALUE_BIG=Stór
+
+OPTION_VALUE_HALF=Hálf
+OPTION_VALUE_FULL_VID=Full (Video)
+OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+OPTION_VALUE_AUTO=Sjálfvirkt
+OPTION_VALUE_SEC=Sekúnda
+OPTION_VALUE_SECS=Sekúndur
+
+OPTION_VALUE_PLAIN=Plain
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Einfalt
+OPTION_VALUE_ZOOM=Zoom
+OPTION_VALUE_SLIDE=Rennsli
+OPTION_VALUE_BALL=Bolti
+OPTION_VALUE_SHIFT=Hopp
+
+OPTION_VALUE_EURO=Euro
+OPTION_VALUE_JAPAN=Japan
+OPTION_VALUE_AMERICAN=American
+
+OPTION_VALUE_BLUE=Blár
+OPTION_VALUE_GREEN=Grænn
+OPTION_VALUE_PINK=Bleikur
+OPTION_VALUE_RED=Rauður
+OPTION_VALUE_VIOLET=Fjólublár
+OPTION_VALUE_ORANGE=Appelsínulitur
+OPTION_VALUE_YELLOW=Gulur
+OPTION_VALUE_BROWN=Brúnn
+OPTION_VALUE_BLACK=Svartur
+
+OPTION_VALUE_SING=Syngja
+OPTION_VALUE_SELECT_PLAYERS=Velja Leikmenn
+OPTION_VALUE_OPEN_MENU=Opna Valmynd
+
+OPTION_VALUE_HARDWARE_CURSOR=Vélbúnaðarbendill
+OPTION_VALUE_SOFTWARE_CURSOR=Hugbúnaðarbendill
+
+SING_LOADING=Hleður...
+
+SING_CHOOSE_MODE=velja valmynd
+SING_SING=syngja
+SING_SING_DESC=stuttur leikur: syngja soló eða dúett
+
+SING_MULTI=partí
+SING_MULTI_DESC=syngja með partí-sniði
+
+SING_TOOLS=tól
+
+SING_STATS=tölfræði
+SING_STATS_DESC=skoða tölfræði
+
+SING_EDITOR=lagasmiður
+SING_EDITOR_DESC=búa til eigið lag
+
+SING_GAME_OPTIONS=leikstillingar
+SING_GAME_OPTIONS_DESC=breyta leikstillingum
+
+SING_EXIT=hætta
+SING_EXIT_DESC=hætta leik
+
+SING_OPTIONS=stillingar
+SING_OPTIONS_DESC=breyta stillingum
+SING_OPTIONS_WHEREAMI=Stillingar
+
+SING_OPTIONS_GAME=leikur
+SING_OPTIONS_GRAPHICS=mynd
+SING_OPTIONS_SOUND=hljóð
+SING_OPTIONS_LYRICS=lagatextar
+SING_OPTIONS_THEMES=snið
+SING_OPTIONS_RECORD=upptaka
+SING_OPTIONS_ADVANCED=fleiri stillingar
+SING_OPTIONS_EXIT=til baka
+
+SING_OPTIONS_GAME_WHEREAMI=Stillingar Leikur
+SING_OPTIONS_GAME_DESC=almennar leikstillingar
+SING_OPTIONS_GAME_PLAYERS=Leikmenn
+SING_OPTIONS_GAME_DIFFICULTY=Erfiðleikastig
+SING_OPTIONS_GAME_LANGUAGE=Tungumál
+SING_OPTIONS_GAME_TABS=Flipar
+SING_OPTIONS_GAME_SORTING=Röðun
+SING_OPTIONS_GAME_DEBUG=Villuprófun
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Stillingar Mynd
+SING_OPTIONS_GRAPHICS_DESC=myndstillingar
+SING_OPTIONS_GRAPHICS_RESOLUTION=Skjáupplausn
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Skjáfyllir
+SING_OPTIONS_GRAPHICS_DEPTH=Dýpt
+SING_OPTIONS_GRAPHICS_VISUALIZER=Sýning
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Sveiflusjá
+SING_OPTIONS_GRAPHICS_LINEBONUS=Línubónus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Stærð Myndbands
+
+SING_OPTIONS_SOUND_WHEREAMI=Stillingar hljóð
+SING_OPTIONS_SOUND_DESC=hljóðstillingar
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Spilun af hljóðnema
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Bakgrunnstónlist
+SING_OPTIONS_SOUND_MIC_BOOST=Hljóðnemaaukning
+SING_OPTIONS_SOUND_CLICK_ASSIST=Taktstuðningur
+SING_OPTIONS_SOUND_BEAT_CLICK=Slá takt
+SING_OPTIONS_SOUND_THRESHOLD=Þröskuldur
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Tveir leikmenn
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Forsýn hljóðstyrkur
+SING_OPTIONS_SOUND_PREVIEWFADING=Forsýn útþynning
+
+SING_OPTIONS_LYRICS_WHEREAMI=Stillingar Textar
+SING_OPTIONS_LYRICS_DESC=textastillingar
+SING_OPTIONS_LYRICS_FONT=Leturgerð
+SING_OPTIONS_LYRICS_EFFECT=Brellur
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmization
+SING_OPTIONS_LYRICS_NOTELINES=Línur
+
+SING_OPTIONS_THEMES_WHEREAMI=Stillingar Snið
+SING_OPTIONS_THEMES_DESC=þemu- og skinnstillingar
+SING_OPTIONS_THEMES_THEME=Þema
+SING_OPTIONS_THEMES_SKIN=Skinn
+SING_OPTIONS_THEMES_COLOR=Litur
+
+SING_OPTIONS_RECORD_WHEREAMI=Stillingar Upptaka
+SING_OPTIONS_RECORD_DESC=hljóðnemastillingar
+SING_OPTIONS_RECORD_CARD=Hljóðkort
+SING_OPTIONS_RECORD_INPUT=Inntak
+SING_OPTIONS_RECORD_CHANNEL=Rás
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Stillingar Meira
+SING_OPTIONS_ADVANCED_DESC=fleiri stillingar
+SING_OPTIONS_ADVANCED_EFFECTSING=Söngbrellur
+SING_OPTIONS_ADVANCED_SCREENFADE=Skjá útþynning
+SING_OPTIONS_ADVANCED_LOADANIMATION=Hlaða hreyfimynd
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Öryggisspurningar
+SING_OPTIONS_ADVANCED_LINEBONUS=Línubónus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Eftir Lagaval
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Sjálfvirk Partívalmynd
+
+SING_EDIT=Lagasmiður
+SING_EDIT_MENU_DESCRIPTION=búðu til eigið lag
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Flytja inn texta frá midi skrá
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=til baka
+SING_EDIT_BUTTON_CONVERT=Flytja inn
+SING_EDIT_BUTTON_EXIT=til baka
+
+SING_EDIT_NAVIGATE=stýra
+SING_EDIT_SELECT=velja
+SING_EDIT_EXIT=til baka
+
+SING_LEGEND_SELECT=velja
+SING_LEGEND_NAVIGATE=stýra
+SING_LEGEND_CONTINUE=áfram
+SING_LEGEND_ESC=til baka
+
+SING_PLAYER_DESC=sláið inn nöfn leikmanna 
+SING_PLAYER_WHEREAMI=Nöfn leikmanna
+SING_PLAYER_ENTER_NAME=sláðu inn nafn
+
+SING_DIFFICULTY_DESC=veldu erfiðleikastig
+SING_DIFFICULTY_WHEREAMI=Erfiðleikastig
+SING_DIFFICULTY_CONTINUE=í lagaval
+SING_EASY=Auðvelt
+SING_MEDIUM=Miðlungs
+SING_HARD=Erfitt
+
+SING_SONG_SELECTION_DESC=veldu lag
+SING_SONG_SELECTION_WHEREAMI=Lagaval
+SING_SONG_SELECTION_GOTO=fara til ..
+SING_SONG_SELECTION=lagaval
+SING_SONG_SELECTION_MENU=valmynd
+SING_SONG_SELECTION_PLAYLIST=lagalisti
+SING_SONGS_IN_CAT=Lög
+PLAYLIST_CATTEXT=Lagalisti: %s
+
+SING_TIME=TÍMI
+SING_TOTAL=samtals
+SING_MODE=syngja sóló
+SING_NOTES=nótur
+SING_GOLDEN_NOTES=gullnótur
+SING_PHRASE_BONUS=línubónus
+
+SING_MENU=Aðalvalmynd
+
+SONG_SCORE=stigagjöf
+SONG_SCORE_WHEREAMI=Dómur
+
+SING_SCORE_TONE_DEAF=Falskt
+SING_SCORE_AMATEUR=Viðvaningur
+SING_SCORE_WANNABE=Uppblásið egó
+SING_SCORE_HOPEFUL=Eygir von
+SING_SCORE_RISING_STAR=Rísandi Stjarna
+SING_SCORE_LEAD_SINGER=Forsöngvari
+SING_SCORE_SUPERSTAR=Súperstjarna
+SING_SCORE_ULTRASTAR=Últrastjarna
+
+SING_TOP_5_CHARTS=topp 5 leikmenn
+SING_TOP_5_CHARTS_WHEREAMI=topp 5
+SING_TOP_5_CHARTS_CONTINUE=í lagaval
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=breyta erfiðleikastigi
+
+POPUP_PERFECT=fullkomið!
+POPUP_AWESOME=æðislegt!
+POPUP_GREAT=frábært!
+POPUP_GOOD=gott!
+POPUP_NOTBAD=ekki slæmt!
+POPUP_BAD=slæmt!
+POPUP_POOR=lélegt!
+POPUP_AWFUL=hræðilegt!
+
+;TODO: IMPLODE_GLUE1=,
+IMPLODE_GLUE2= og
+
+SONG_MENU_NAME_MAIN=lagavalmynd
+SONG_MENU_PLAY=Syngja
+SONG_MENU_CHANGEPLAYERS=Breyta um leikmenn
+SONG_MENU_EDIT=Breyta
+SONG_MENU_MODI=Singja Modi
+SONG_MENU_CANCEL=Hætta við
+
+SONG_MENU_NAME_PLAYLIST=Lagavalmynd
+SONG_MENU_PLAYLIST_ADD=Bæta við lagi
+SONG_MENU_PLAYLIST_DEL=Eyða lagi
+
+SONG_MENU_NAME_PLAYLIST_ADD=Bæta við
+SONG_MENU_PLAYLIST_ADD_NEW=í nýjan lagalista
+SONG_MENU_PLAYLIST_ADD_EXISTING=í núverandi lagalista
+SONG_MENU_PLAYLIST_NOEXISTING=Enginn lagalisti til staðar
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nýr Lagalisti
+SONG_MENU_PLAYLIST_NEW_CREATE=Búa til
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Ónefndur
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Virkilega Eyða?
+SONG_MENU_YES=Já
+SONG_MENU_NO=Nei
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Opna Lagalista
+SONG_MENU_PLAYLIST_LOAD=opna
+SONG_MENU_PLAYLIST_DELCURRENT=eyða núverandi Lagalista
+
+SONG_MENU_NAME_PLAYLIST_DEL=Eyða Lagalista?
+
+SONG_MENU_NAME_PARTY_MAIN=Partívalmynd
+SONG_MENU_JOKER=Jóker
+
+SONG_MENU_NAME_PARTY_JOKER=taka jóker
+
+SONG_JUMPTO_DESC=lagaleit
+SONG_JUMPTO_TYPE_DESC=Leita að:
+SONG_JUMPTO_TYPE1=Öllu
+SONG_JUMPTO_TYPE2=Titli
+SONG_JUMPTO_TYPE3=Flytjanda
+SONG_JUMPTO_SONGSFOUND=%d lög fundust
+SONG_JUMPTO_NOSONGSFOUND=Engin lög fundust
+SONG_JUMPTO_HELP=Sláðu inn texta til að leita að
+SONG_JUMPTO_CATTEXT=Leita að: %s
+
+PARTY_MODE=partísnið
+PARTY_DIFFICULTY=Erfiðleikastig
+PARTY_PLAYLIST=Lagalista Stilling
+PARTY_PLAYLIST_ALL=Öll lög
+PARTY_PLAYLIST_CATEGORY=Mappa
+PARTY_PLAYLIST_PLAYLIST=Lagalisti
+PARTY_TEAMS=fjöldi liða
+PARTY_TEAMS_PLAYER1=fjöldi söngvara
+PARTY_TEAMS_PLAYER2=fjöldi söngvara
+PARTY_TEAMS_PLAYER3=fjöldi söngvara
+
+PARTY_LEGEND_CONTINUE=áfram
+
+PARTY_OPTIONS_DESC=stillingar fyrir partíleik
+PARTY_OPTIONS_WHEREAMI=Partí Stillingar
+
+PARTY_PLAYER_DESC=sláðu inn nöfn leikmanna og liða!
+PARTY_PLAYER_WHEREAMI=Partí Nöfn
+PARTY_PLAYER_ENTER_NAME=sláðu inn nöfn
+
+
+PARTY_ROUNDS_DESC= veljið hvaða snið þið viljið spila
+PARTY_ROUNDS_WHEREAMI=Partí Umferðir
+PARTY_ROUNDS_LEGEND_CONTINUE=byrja partí-leik
+PARTY_ROUNDCOUNT=fjöldi umferða
+PARTY_SELECTMODE1=snið umferð 1
+PARTY_SELECTMODE2=snið umferð 2
+PARTY_SELECTMODE3=snið umferð 3
+PARTY_SELECTMODE4=snið umferð 4
+PARTY_SELECTMODE5=snið umferð 5
+PARTY_SELECTMODE6=snið umferð 6
+PARTY_SELECTMODE7=snið umferð 7
+
+PARTY_ROUND_DESC=næstu leikmenn að hljóðnemunum
+PARTY_ROUND_WHEREAMI=Partí Næsta Umferð
+PARTY_ROUND_LEGEND_CONTINUE=byrja umferð
+
+PARTY_SONG_WHEREAMI=Partí Lagaval
+PARTY_SONG_LEGEND_CONTINUE=syngja
+PARTY_SONG_MENU=partí valmynd
+
+PARTY_SCORE_DESC=stig síðustu umferðar
+PARTY_SCORE_WHEREAMI=Partí Stig
+
+PARTY_WIN_DESC=sigurvegari partí-leiks
+PARTY_WIN_WHEREAMI=Partí Sigurvegari
+PARTY_WIN_LEGEND_CONTINUE=aftur að aðalvalmynd
+
+PARTY_ROUND=Umferð
+PARTY_ROUND_WINNER=Sigurvegari
+PARTY_NOTPLAYEDYET=ekki spilað enn
+PARTY_NOBODY=enginn
+NEXT_ROUND=Næsta umferð:
+
+PARTY_DISMISSED=Úr leik!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=sigrar!
+
+MODE_RANDOM_NAME=Tilviljanakennt snið
+MODE_RANDOM_DESC=Eitt snið valið af handahófi
+
+MODE_HOLDTHELINE_NAME=Haltu þig á strikinu
+MODE_HOLDTHELINE_DESC=Ekki standa þig verr en stigalínan sýnir.
+
+MODE_5000POINTS_NAME=Að 5000
+MODE_5000POINTS_DESC=Leikmaður sem fyrstur nær 5000 stigum vinnur.
+
+MODE_DUEL_NAME=Einvígi
+MODE_DUEL_DESC=Söngeinvígi að 10000 stigum.
+
+MODE_TEAMDUEL_NAME=Liðaeinvígi
+MODE_TEAMDUEL_DESC=Láttu hljóðnemann ganga!
+
+MODE_BLIND_NAME=Blindandi
+MODE_BLIND_DESC=Einvígi án þess að sjá nóturnar.
+
+STAT_MAIN=Tölfræði
+STAT_MAIN_DESC=Almennt
+STAT_MAIN_WHEREAMI=Tölfræði
+
+STAT_OVERVIEW_INTRO=%0:s tölfræði.  \n Síðasta endurræsing %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Lög (%3:d með myndbandi), þar af hafa %1:d þegar verið spiluð og %2:d hafa enn ekki verið spiluð.\n Vinsælasta lagið er %5:s með %4:s.
+STAT_OVERVIEW_PLAYER=Frá síðustu endurræsingu hafa spilað  %0:d leikmenn.\n Besti leikmaðurinn er %1:s með meðalstigatölu %2:d stig.\n %3:s fékk hæstu stig með %4:d stig.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Tölfræði
+STAT_DETAIL_WHEREAMI=Ítarleg Tölfræði
+
+STAT_NEXT=Næsta síða
+STAT_PREV=Fyrri síða
+STAT_REVERSE=Öfug röð
+STAT_PAGE=Blaðsíða %0:d af %1:d blaðsíðum (%2:d af %3:d færslum)
+
+STAT_DESC_SCORES=Hæstu stig
+STAT_DESC_SCORES_REVERSED=Lægstu stig
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Bestu söngvarar
+STAT_DESC_SINGERS_REVERSED=Verstu söngvarar
+STAT_FORMAT_SINGERS=%0:s \n Meðalstig: %1:d
+
+STAT_DESC_SONGS=Vinsælustu lög
+STAT_DESC_SONGS_REVERSED=Óvinsælustu lög
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx sungið
+
+STAT_DESC_BANDS=Vinsælustu hljómsveitir
+STAT_DESC_BANDS_REVERSED=Óvinsælustu hljómsveitir
+STAT_FORMAT_BANDS=%0:s \n %1:dx Sungið
+
+SCREENSHOT_SAVED=Skjámynd vistuð
+SCREENSHOT_FAILED=Gat ekki vistað skjámynd
+
+INFO_FILE_SAVED=Skrá vistuð
+ERROR_SAVE_FILE_FAILED=Gat ekki vistað skrá 
+ERROR_FILE_NOT_FOUND=Skrá finnst ekki
+
+ENCODING_ERROR_ASK_FOR_UTF8=Get ekki vistað breytingar með núverandi stafasetti.  Breyta í UTF-8?
+EDITOR_ERROR_NO_TRACK_SELECTED=Ekkert lag valið
+
+MSG_ERROR_TITLE=Villa
+MSG_INFO_TITLE=Upplýsingar
+MSG_QUESTION_TITLE=Spurning
+MSG_QUIT_USDX=Viltu hætta í UltraStar?
+MSG_END_PARTY=Virkilega hætta í Partí?
+
+ERROR_NO_SONGS=Engum lögum hlaðið inn
+ERROR_NO_PLUGINS=Engum viðbótum hlaðið inn
+ERROR_NO_MODES_FOR_CURRENT_SETUP=engin snið tiltæk fyrir núverandi leikmann/lið
+ERROR_CAN_NOT_START_PARTY= villa kom upp við upphaf partíleiks
+ERROR_CORRUPT_SONG=Ekki var hægt að hlaða inn lagi.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Ekki var hægt að hlaða inn lagi:  Skrá finnst ekki.
+ERROR_CORRUPT_SONG_NO_NOTES=Ekki var hægt að hlaða inn lagi: Finn engar nótur
+ERROR_CORRUPT_SONG_NO_BREAKS=Ekki var hægt að hlaða inn lagi: Finn engar línuskiptingar
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Ekki var hægt að hlaða inn lagi: Villa við þáttun línu %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;TRANSLATOR: Hlynur Sigurgíslason
+;TRANSLATOR: Sigrún Huld Skúladóttir
diff --git a/songmanagement/game/languages/Italian.ini b/songmanagement/game/languages/Italian.ini
new file mode 100644
index 00000000..10597c5f
--- /dev/null
+++ b/songmanagement/game/languages/Italian.ini
@@ -0,0 +1,443 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Caricamento...
+
+SING_CHOOSE_MODE=scegli modalità
+SING_SING=canta
+SING_SING_DESC=quick game: canta da solo o duetta
+
+SING_MULTI=party
+SING_MULTI_DESC=canta in modalità party
+
+SING_TOOLS=strumenti
+
+SING_STATS=statistiche
+SING_STATS_DESC=guarda le statistiche
+
+SING_EDITOR=editor
+SING_EDITOR_DESC=crea la tua canzone
+
+SING_GAME_OPTIONS=impostazioni di gioco
+SING_GAME_OPTIONS_DESC=cambia le impostazioni di gioco
+
+SING_EXIT=chiudi
+SING_EXIT_DESC=chiudi il gioco
+
+SING_OPTIONS=impostazioni
+SING_OPTIONS_DESC=cambia impostazioni
+SING_OPTIONS_WHEREAMI=Impostazioni
+
+SING_OPTIONS_GAME=gioco
+SING_OPTIONS_GRAPHICS=grafica
+SING_OPTIONS_SOUND=suono
+SING_OPTIONS_LYRICS=testi
+SING_OPTIONS_THEMES=temi
+SING_OPTIONS_RECORD=registrazioni
+SING_OPTIONS_ADVANCED=avanzate
+SING_OPTIONS_EXIT=indietro
+
+SING_OPTIONS_GAME_WHEREAMI=Impostazioni Gioco
+SING_OPTIONS_GAME_DESC=impostazioni generali di gioco
+SING_OPTIONS_GAME_PLAYERS=Giocatori
+SING_OPTIONS_GAME_DIFFICULTY=Difficultà
+SING_OPTIONS_GAME_LANGUAGE=Lingua
+SING_OPTIONS_GAME_TABS=Schede
+SING_OPTIONS_GAME_SORTING=Ordinamento
+SING_OPTIONS_GAME_DEBUG=Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Impostazioni Grafica
+SING_OPTIONS_GRAPHICS_DESC=impostazioni grafica
+SING_OPTIONS_GRAPHICS_RESOLUTION=Risoluzione
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Fullscreen
+SING_OPTIONS_GRAPHICS_DEPTH=Profondità
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualizzazioni
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloscopio
+SING_OPTIONS_GRAPHICS_LINEBONUS=Linee Bonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Grandezza video
+
+SING_OPTIONS_SOUND_WHEREAMI=Impostazioni Suono
+SING_OPTIONS_SOUND_DESC=impostazioni suono
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Playback Microfono
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Musica in background
+SING_OPTIONS_SOUND_MIC_BOOST=Potenzia microfono
+SING_OPTIONS_SOUND_CLICK_ASSIST=Click di Assistenza
+SING_OPTIONS_SOUND_BEAT_CLICK=Click di Beat
+SING_OPTIONS_SOUND_THRESHOLD=Soglia
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Modalità due giocatori
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Volume Anteprima
+SING_OPTIONS_SOUND_PREVIEWFADING=Fading Anteprima
+
+SING_OPTIONS_LYRICS_WHEREAMI=Impostazioni Testi
+SING_OPTIONS_LYRICS_DESC=impostazioni testi
+SING_OPTIONS_LYRICS_FONT=Font
+SING_OPTIONS_LYRICS_EFFECT=Effetti
+SING_OPTIONS_LYRICS_SOLMIZATION=Solfeggio
+SING_OPTIONS_LYRICS_NOTELINES=Pentagramma
+
+SING_OPTIONS_THEMES_WHEREAMI=Impostazioni Temi
+SING_OPTIONS_THEMES_DESC=impostazioni temi e skin
+SING_OPTIONS_THEMES_THEME=Temi
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Colore
+
+SING_OPTIONS_RECORD_WHEREAMI=Impostazioni Registrazione
+SING_OPTIONS_RECORD_DESC=impostazioni microfoni
+SING_OPTIONS_RECORD_CARD=Scheda Audio
+SING_OPTIONS_RECORD_INPUT=Input
+SING_OPTIONS_RECORD_CHANNEL=Canale
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Impostazioni Avanzate
+SING_OPTIONS_ADVANCED_DESC=impostazioni avanzate
+SING_OPTIONS_ADVANCED_EFFECTSING=Effetti del canto
+SING_OPTIONS_ADVANCED_SCREENFADE=Fading dello schermo
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animazione Caricamento
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Domande di Sicurezza
+SING_OPTIONS_ADVANCED_LINEBONUS=Linee Bonus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=dopo Canzone Seleziona
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Menu Party automatico
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=crea la tua canzone
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importa testo dal file midi
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=indietro
+SING_EDIT_BUTTON_CONVERT=Importa
+SING_EDIT_BUTTON_EXIT=indietro
+
+SING_EDIT_NAVIGATE=navigare
+SING_EDIT_SELECT=seleziona
+SING_EDIT_EXIT=indietro
+
+SING_LEGEND_SELECT=seleziona
+SING_LEGEND_NAVIGATE=naviga
+SING_LEGEND_CONTINUE=continua
+SING_LEGEND_ESC=indietro
+
+SING_PLAYER_DESC=inserisci nome/i giocatore/i
+SING_PLAYER_WHEREAMI=Nomi giocatori
+SING_PLAYER_ENTER_NAME=inserisci nome
+
+SING_DIFFICULTY_DESC=seleziona difficoltà
+SING_DIFFICULTY_WHEREAMI=Difficultà
+SING_DIFFICULTY_CONTINUE=per cantare seleziona
+SING_EASY=Facile
+SING_MEDIUM=Media
+SING_HARD=Difficile
+
+SING_SONG_SELECTION_DESC=scegli la tua canzone
+SING_SONG_SELECTION_WHEREAMI=Selezione Canzone
+SING_SONG_SELECTION_GOTO=vai a ..
+SING_SONG_SELECTION=seleziona canzone
+SING_SONG_SELECTION_MENU=menu
+SING_SONG_SELECTION_PLAYLIST=playlist
+SING_SONGS_IN_CAT=Canzoni
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=TEMPO
+SING_TOTAL=totale
+SING_MODE=canta solo
+SING_NOTES=note
+SING_GOLDEN_NOTES=note dorate
+SING_PHRASE_BONUS=linee bonus
+
+SING_MENU=Menu Principale
+
+SONG_SCORE=punti canzone
+SONG_SCORE_WHEREAMI=Punti
+
+SING_SCORE_TONE_DEAF=Tone Deaf
+SING_SCORE_AMATEUR=Amatore
+SING_SCORE_WANNABE=Aspirante
+SING_SCORE_HOPEFUL=Promessa
+SING_SCORE_RISING_STAR=Stella Nascente
+SING_SCORE_LEAD_SINGER=Cantante Solista
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=migliori 5 Giocatori
+SING_TOP_5_CHARTS_WHEREAMI=migliori 5
+SING_TOP_5_CHARTS_CONTINUE=per cantare seleziona
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=perfetto!
+POPUP_AWESOME=stupendo!
+POPUP_GREAT=grande!
+POPUP_GOOD=buono!
+POPUP_NOTBAD=non male!
+POPUP_BAD=scarso!
+POPUP_POOR=pessimo!
+POPUP_AWFUL=orribile!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= e
+
+SONG_MENU_NAME_MAIN=menu canzone
+SONG_MENU_PLAY=Canta
+SONG_MENU_CHANGEPLAYERS=Cambia Giocatori
+SONG_MENU_EDIT=Modifica
+SONG_MENU_MODI=Canta un Modi
+SONG_MENU_CANCEL=Annulla
+
+SONG_MENU_NAME_PLAYLIST=Menu Canzone
+SONG_MENU_PLAYLIST_ADD=Aggiungi Canzone
+SONG_MENU_PLAYLIST_DEL=Elimina Canzone
+
+SONG_MENU_NAME_PLAYLIST_ADD=Aggiungi Canzone
+SONG_MENU_PLAYLIST_ADD_NEW=alla nuova playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=alla playlist esistente
+SONG_MENU_PLAYLIST_NOEXISTING=Nessuna playlist disponibile
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nuova Playlist
+SONG_MENU_PLAYLIST_NEW_CREATE=Crea
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Senza Nome
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Vuoi davvero eliminare?
+SONG_MENU_YES=Sì
+SONG_MENU_NO=No
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Apri Playlist
+SONG_MENU_PLAYLIST_LOAD=apri
+SONG_MENU_PLAYLIST_DELCURRENT=elimina Playlist corrente
+
+SONG_MENU_NAME_PLAYLIST_DEL=Elimina Playlist?
+
+SONG_MENU_NAME_PARTY_MAIN=Menu Party
+SONG_MENU_JOKER=Jolly
+
+SONG_MENU_NAME_PARTY_JOKER=usa jolly
+
+SONG_JUMPTO_DESC=cerca song
+SONG_JUMPTO_TYPE_DESC=Cerca per:
+SONG_JUMPTO_TYPE1=Tutto
+SONG_JUMPTO_TYPE2=Titolo
+SONG_JUMPTO_TYPE3=Artista
+SONG_JUMPTO_SONGSFOUND=%d Canzone(i) trovata(e)
+SONG_JUMPTO_NOSONGSFOUND=Nessuna Canzone trovata
+SONG_JUMPTO_HELP=Scrivi il Testo da Cercare:
+SONG_JUMPTO_CATTEXT=Cerca per: %s
+
+PARTY_MODE=modalità party
+PARTY_DIFFICULTY=Difficultà
+PARTY_PLAYLIST=Modalità Playlist
+PARTY_PLAYLIST_ALL=Tutte le Canzoni
+PARTY_PLAYLIST_CATEGORY=Cartella
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_TEAMS=Teams
+PARTY_TEAMS_PLAYER1=Giocatore Team1
+PARTY_TEAMS_PLAYER2=Giocatore Team2
+PARTY_TEAMS_PLAYER3=Giocatore Team3
+
+PARTY_LEGEND_CONTINUE=continua
+
+PARTY_OPTIONS_DESC=impostazioni per il gioco (party)
+PARTY_OPTIONS_WHEREAMI=Impostazioni Party
+
+PARTY_PLAYER_DESC=inserisci giocatore- e nomi squadre!
+PARTY_PLAYER_WHEREAMI=Nomi Party
+PARTY_PLAYER_ENTER_NAME=inserisci nomi
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=incomincia il gioco (party)
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=prossimi giocatori al microfono
+PARTY_ROUND_WHEREAMI=Prossimo Round del Party
+PARTY_ROUND_LEGEND_CONTINUE=incomincia round
+
+PARTY_SONG_WHEREAMI=Canzone Party-Seleziona
+PARTY_SONG_LEGEND_CONTINUE=canta
+PARTY_SONG_MENU=menu party
+
+PARTY_SCORE_DESC=punteggio dell''ultimo round
+PARTY_SCORE_WHEREAMI=Punti del Party
+
+PARTY_WIN_DESC=vincitore del gioco (party)
+PARTY_WIN_WHEREAMI=Vincitore Party
+PARTY_WIN_LEGEND_CONTINUE=torna al menu principale
+
+PARTY_ROUND=Round
+PARTY_ROUND_WINNER=Vincitore
+PARTY_NOTPLAYEDYET=non ancora giocato
+PARTY_NOBODY=nessuno
+NEXT_ROUND=Prossimo round:
+
+PARTY_DISMISSED=Respinto!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=vince!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Tieni la Linea
+MODE_HOLDTHELINE_DESC=Non fare peggio del puntatore che ti mostra la barra.
+
+MODE_5000POINTS_NAME=Fino a 5000
+MODE_5000POINTS_DESC=Chi fa 5000 punti per primo vince.
+
+MODE_DUEL_NAME=Duello
+MODE_DUEL_DESC=Canta in duello fino a 10000 punti.
+
+MODE_TEAMDUEL_NAME=Duello a Team
+MODE_TEAMDUEL_DESC=Passa il Microfono!
+
+MODE_BLIND_NAME=Modalità Ceca
+MODE_BLIND_DESC=Duella senza vedere le note.
+
+STAT_MAIN=Statistiche
+STAT_MAIN_DESC=Generale
+STAT_MAIN_WHEREAMI=Statistiche
+
+STAT_OVERVIEW_INTRO=%0:s Statistiche.  \n Ultimo Azzeramento a %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Canzoni(%3:d con Video), delle quali %1:d sono state già cantate e %2:d non lo sono ancora state.\n La Canzone più popolare è %5:s di %4:s.
+STAT_OVERVIEW_PLAYER=Dall''ultimo Azzeramente c''è/ci sono stato/i %0:d Giocatore/i differente/i.\n Il migliore Giocatore è %1:s con un Punteggio medio di %2:d Punti.\n %3:s ha fatto il Punteggio pià alto con %4:d Punti.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statistiche
+STAT_DETAIL_WHEREAMI=Dettagli Statistiche
+
+STAT_NEXT=Prossima Pagina
+STAT_PREV=Pagina Precedente
+STAT_REVERSE=Ordine Inverso
+STAT_PAGE=Pagina %0:d di %1:d Pagine\n (%2:d di %3:d Inserimenti)
+
+STAT_DESC_SCORES=PunteggiAlti
+STAT_DESC_SCORES_REVERSED=PunteggiBassi
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Cantanti Migliori
+STAT_DESC_SINGERS_REVERSED=Cantanti Peggiori
+STAT_FORMAT_SINGERS=%0:s \n Punteggio Medio: %1:d
+
+STAT_DESC_SONGS=La Canzone più popolare
+STAT_DESC_SONGS_REVERSED=La Canzone meno popolare
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx Cantate
+
+STAT_DESC_BANDS=Le Bands più popolari
+STAT_DESC_BANDS_REVERSED=Le Bands meno popolari
+STAT_FORMAT_BANDS=%0:s \n %1:dx Cantate
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Errore
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Domanda
+MSG_QUIT_USDX=Vuoi davvero uscire da UltraStar?
+MSG_END_PARTY=Vuoi davvero terminare la Modalità Party?
+
+ERROR_NO_SONGS=Nessuna Canzone caricata
+ERROR_NO_PLUGINS=Nessun Plugin caricato
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=La canzone non è stata caricata.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Impossibile aprire la canzone: File non trovato
+ERROR_CORRUPT_SONG_NO_NOTES=Impossibile aprire la canzone: Nessuna nota trovata
+ERROR_CORRUPT_SONG_NO_BREAKS=Impossibile aprire la canzone: Nessuna interruzione di linea trovata
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Impossibile aprire la canzone: Errore durante il parsing della linea %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Contatore
+;UNUSED: PARTY_ROUNDS=Rounds
diff --git a/songmanagement/game/languages/Japanese.ini b/songmanagement/game/languages/Japanese.ini
new file mode 100644
index 00000000..1036df3f
--- /dev/null
+++ b/songmanagement/game/languages/Japanese.ini
@@ -0,0 +1,443 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=ロード中
+
+SING_CHOOSE_MODE=モード選択
+SING_SING=歌う
+SING_SING_DESC=クイック・ゲーム:一人がデュエットで歌う
+
+SING_MULTI=パーティー
+SING_MULTI_DESC=パーティー・モードで歌う
+
+SING_TOOLS=ツール
+
+SING_STATS=統計
+SING_STATS_DESC=統計表
+
+SING_EDITOR=エディター
+SING_EDITOR_DESC=自分でウルトラ・スターの曲を作る
+
+SING_GAME_OPTIONS=ゲーム設定
+SING_GAME_OPTIONS_DESC=ゲーム設定を変える
+
+SING_EXIT=やめる
+SING_EXIT_DESC=ゲームをやめる
+
+SING_OPTIONS=設定
+SING_OPTIONS_DESC=設定を変える
+SING_OPTIONS_WHEREAMI=設定
+
+SING_OPTIONS_GAME=ゲーム
+SING_OPTIONS_GRAPHICS=グラフィックス
+SING_OPTIONS_SOUND=音
+SING_OPTIONS_LYRICS=歌詞
+SING_OPTIONS_THEMES=テーマ
+SING_OPTIONS_RECORD=録音
+SING_OPTIONS_ADVANCED=アドバンス
+SING_OPTIONS_EXIT=戻る
+
+SING_OPTIONS_GAME_WHEREAMI=ゲーム設定
+SING_OPTIONS_GAME_DESC=ゲームの基本設定
+SING_OPTIONS_GAME_PLAYERS=プレイヤー
+SING_OPTIONS_GAME_DIFFICULTY=面倒
+SING_OPTIONS_GAME_LANGUAGE=言語
+SING_OPTIONS_GAME_TABS=タッブ
+SING_OPTIONS_GAME_SORTING=ソーティング
+SING_OPTIONS_GAME_DEBUG=ディバッグ
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=グラフィックス
+SING_OPTIONS_GRAPHICS_DESC=グラフィックスの設定
+SING_OPTIONS_GRAPHICS_RESOLUTION=解像
+SING_OPTIONS_GRAPHICS_FULLSCREEN=フルスクリーン
+SING_OPTIONS_GRAPHICS_DEPTH=ビット深度
+SING_OPTIONS_GRAPHICS_VISUALIZER=可視化
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=オシロスコープ
+SING_OPTIONS_GRAPHICS_LINEBONUS=ライン・ボーナス
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=動画サイズ
+
+SING_OPTIONS_SOUND_WHEREAMI=音設定
+SING_OPTIONS_SOUND_DESC=音の設定
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=マイク再生
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=バックグラウンド・ミュージック
+SING_OPTIONS_SOUND_MIC_BOOST=マイク・ブースト
+SING_OPTIONS_SOUND_CLICK_ASSIST=クリック・アシスト
+SING_OPTIONS_SOUND_BEAT_CLICK=ビート・クリック
+SING_OPTIONS_SOUND_THRESHOLD=極限
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=二人で遊ぶ
+SING_OPTIONS_SOUND_PREVIEWVOLUME=音量・プリビュー
+SING_OPTIONS_SOUND_PREVIEWFADING=フェーディング・プリビュー
+
+SING_OPTIONS_LYRICS_WHEREAMI=歌詞設定
+SING_OPTIONS_LYRICS_DESC=歌詞の設定
+SING_OPTIONS_LYRICS_FONT=字形
+SING_OPTIONS_LYRICS_EFFECT=エフェクト
+SING_OPTIONS_LYRICS_SOLMIZATION=ソルマイゼーション
+SING_OPTIONS_LYRICS_NOTELINES=五線譜
+
+SING_OPTIONS_THEMES_WHEREAMI=テーマ設定
+SING_OPTIONS_THEMES_DESC=テーマの設定
+SING_OPTIONS_THEMES_THEME=テーマ
+SING_OPTIONS_THEMES_SKIN=スキン
+SING_OPTIONS_THEMES_COLOR=色
+
+SING_OPTIONS_RECORD_WHEREAMI=録音設定
+SING_OPTIONS_RECORD_DESC=マイク録音の設定
+SING_OPTIONS_RECORD_CARD=サウンドカード
+SING_OPTIONS_RECORD_INPUT=入力
+SING_OPTIONS_RECORD_CHANNEL=チャネル
+
+SING_OPTIONS_ADVANCED_WHEREAMI=アドバンス設定
+SING_OPTIONS_ADVANCED_DESC=アドバンス設定
+SING_OPTIONS_ADVANCED_EFFECTSING=曲のエフェクト
+SING_OPTIONS_ADVANCED_SCREENFADE=画面・フェーディング
+SING_OPTIONS_ADVANCED_LOADANIMATION=ロード・アニメーション
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=消す場合は確認
+SING_OPTIONS_ADVANCED_LINEBONUS=ライン・ボーナス
+SING_OPTIONS_ADVANCED_ONSONGCLICK=歌った後は
+SING_OPTIONS_ADVANCED_PARTYPOPUP=自動的にパーティー・メニューへ
+
+SING_EDIT=エディター
+SING_EDIT_MENU_DESCRIPTION=自分でウルトラ・スターの曲を作る
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=MIDIファイルからインポートする
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=戻る
+SING_EDIT_BUTTON_CONVERT=インポート
+SING_EDIT_BUTTON_EXIT=戻る
+
+SING_EDIT_NAVIGATE=ナビ
+SING_EDIT_SELECT=選ぶ
+SING_EDIT_EXIT=戻る
+
+SING_LEGEND_SELECT=選ぶ
+SING_LEGEND_NAVIGATE=ナビ
+SING_LEGEND_CONTINUE=続く
+SING_LEGEND_ESC=戻る
+
+SING_PLAYER_DESC=プレイヤー名記入
+SING_PLAYER_WHEREAMI=プレイヤー名
+SING_PLAYER_ENTER_NAME=名前記入
+
+SING_DIFFICULTY_DESC=面倒選択
+SING_DIFFICULTY_WHEREAMI=面倒
+SING_DIFFICULTY_CONTINUE=曲選択へ
+SING_EASY=簡単
+SING_MEDIUM=普通
+SING_HARD=難しい
+
+SING_SONG_SELECTION_DESC=曲を選ぶ
+SING_SONG_SELECTION_WHEREAMI=曲選択
+SING_SONG_SELECTION_GOTO=曲へ…
+SING_SONG_SELECTION=曲選択
+SING_SONG_SELECTION_MENU=メニュー
+SING_SONG_SELECTION_PLAYLIST=曲順
+SING_SONGS_IN_CAT=曲
+PLAYLIST_CATTEXT=曲順: %s
+
+SING_TIME=TIME
+SING_TOTAL=全部
+SING_MODE=一人で歌う
+SING_NOTES=音符
+SING_GOLDEN_NOTES=ゴールド・音符
+SING_PHRASE_BONUS=ライン・ボーナス
+
+SING_MENU=メイン・メニュー
+
+SONG_SCORE=曲点数
+SONG_SCORE_WHEREAMI=点数
+
+SING_SCORE_TONE_DEAF=耳が聞こえない
+SING_SCORE_AMATEUR= アマチュア
+SING_SCORE_WANNABE=自称歌手
+SING_SCORE_HOPEFUL=有望
+SING_SCORE_RISING_STAR=歌手の卵
+SING_SCORE_LEAD_SINGER=リードボーカリスト
+SING_SCORE_SUPERSTAR=スーパー・スター
+SING_SCORE_ULTRASTAR=ウルトラ・スター
+
+SING_TOP_5_CHARTS=トップ5プレイヤー
+SING_TOP_5_CHARTS_WHEREAMI=トップ5
+SING_TOP_5_CHARTS_CONTINUE=曲選択へ
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=完璧!
+POPUP_AWESOME=すごい!
+POPUP_GREAT=上手!
+POPUP_GOOD=良かった!
+POPUP_NOTBAD=悪くはない!
+POPUP_BAD=良くない!
+POPUP_POOR=下手!
+POPUP_AWFUL=下手くそ!
+
+IMPLODE_GLUE1=、 
+IMPLODE_GLUE2= と 
+
+SONG_MENU_NAME_MAIN=曲メイン・メニュー
+SONG_MENU_PLAY=歌う
+SONG_MENU_CHANGEPLAYERS=プレイヤーを変える
+SONG_MENU_EDIT=エディター
+SONG_MENU_MODI=モードを歌う
+SONG_MENU_CANCEL=キャンセル
+
+SONG_MENU_NAME_PLAYLIST=曲メニュー
+SONG_MENU_PLAYLIST_ADD=曲を加える
+SONG_MENU_PLAYLIST_DEL=曲を消す
+
+SONG_MENU_NAME_PLAYLIST_ADD=曲を加える
+SONG_MENU_PLAYLIST_ADD_NEW=新しい曲順に
+SONG_MENU_PLAYLIST_ADD_EXISTING=ある曲順に
+SONG_MENU_PLAYLIST_NOEXISTING=まだ曲順がない
+
+SONG_MENU_NAME_PLAYLIST_NEW=新しい曲順
+SONG_MENU_PLAYLIST_NEW_CREATE=作成
+SONG_MENU_PLAYLIST_NEW_UNNAMED=名無し
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=本当に消す?
+SONG_MENU_YES=はい
+SONG_MENU_NO=いいえ
+
+SONG_MENU_NAME_PLAYLIST_LOAD=曲順を開く
+SONG_MENU_PLAYLIST_LOAD=開く
+SONG_MENU_PLAYLIST_DELCURRENT=この曲順を消す
+
+SONG_MENU_NAME_PLAYLIST_DEL=曲順を消す?
+
+SONG_MENU_NAME_PARTY_MAIN=パーティーメニュー
+SONG_MENU_JOKER=ジョーカー
+
+SONG_MENU_NAME_PARTY_JOKER=ジョーカーを使う
+
+SONG_JUMPTO_DESC=曲検索
+SONG_JUMPTO_TYPE_DESC=検索:
+SONG_JUMPTO_TYPE1=全部
+SONG_JUMPTO_TYPE2=曲名
+SONG_JUMPTO_TYPE3=歌手
+SONG_JUMPTO_SONGSFOUND=%d曲が見つけた
+SONG_JUMPTO_NOSONGSFOUND=曲見つけれなかった
+SONG_JUMPTO_HELP=検索テクストを入力する
+SONG_JUMPTO_CATTEXT=検索: %s
+
+PARTY_MODE=パーティー・モード
+PARTY_DIFFICULTY=面倒
+PARTY_PLAYLIST=曲順・モード
+PARTY_PLAYLIST_ALL=全曲
+PARTY_PLAYLIST_CATEGORY=フォルダー
+PARTY_PLAYLIST_PLAYLIST=曲順
+PARTY_TEAMS=チーム
+PARTY_TEAMS_PLAYER1=1番チームのプレイヤー
+PARTY_TEAMS_PLAYER2=2番チームのプレイヤー
+PARTY_TEAMS_PLAYER3=3番チームのプレイヤー
+
+PARTY_LEGEND_CONTINUE=続く
+
+PARTY_OPTIONS_DESC=パーティー・ゲームの設定
+PARTY_OPTIONS_WHEREAMI=パーティー設定
+
+PARTY_PLAYER_DESC=プレイヤー、チーム名記入
+PARTY_PLAYER_WHEREAMI=パーティーの名前記入
+PARTY_PLAYER_ENTER_NAME=名前記入
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=パーティー・ゲームをスタート!
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=次のプレイヤーがマイクを
+PARTY_ROUND_WHEREAMI=パーティーの次のラウンド
+PARTY_ROUND_LEGEND_CONTINUE=パーティーをスタート!
+
+PARTY_SONG_WHEREAMI=パーティーの曲選択
+PARTY_SONG_LEGEND_CONTINUE=歌う
+PARTY_SONG_MENU=パーティー・メニュー
+
+PARTY_SCORE_DESC=先回ラウンドの点数
+PARTY_SCORE_WHEREAMI=パーティー・点数
+
+PARTY_WIN_DESC=パーティー・ゲームで勝者
+PARTY_WIN_WHEREAMI=パーティー・勝者
+PARTY_WIN_LEGEND_CONTINUE=メイン・メニューへ
+
+PARTY_ROUND=ラウンド
+PARTY_ROUND_WINNER=勝者
+PARTY_NOTPLAYEDYET=まだ歌ってない
+PARTY_NOBODY=誰もいない
+NEXT_ROUND=次のラウンド:
+
+PARTY_DISMISSED=追放す!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=が勝った!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=ラインをキープ
+MODE_HOLDTHELINE_DESC=レーティング・バーに表示された点数以上で歌う!
+
+MODE_5000POINTS_NAME=5000まで
+MODE_5000POINTS_DESC=より早く5000点までいける人は勝つ!
+
+MODE_DUEL_NAME=果たし合い
+MODE_DUEL_DESC=10000点まで果たし合い!
+
+MODE_TEAMDUEL_NAME=チーム果たし合い
+MODE_TEAMDUEL_DESC=マイクを次に回す!
+
+MODE_BLIND_NAME=盲目・モード
+MODE_BLIND_DESC=音符を見えず果たし合い!
+
+STAT_MAIN=統計
+STAT_MAIN_DESC=ジェネラル
+STAT_MAIN_WHEREAMI=統計
+
+STAT_OVERVIEW_INTRO=%0:s 統計。 \n 先回リセット %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d曲(%3:d曲は動画付)\n 一番人気の曲は%4:sの%5:s。
+STAT_OVERVIEW_PLAYER=先回リセットから%0:d人のプレイヤーがいた。\n 一番上手なプレやーは%2:d点で%1:s。
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=統計
+STAT_DETAIL_WHEREAMI=統計の詳しい事
+
+STAT_NEXT=次ページ
+STAT_PREV=先ページ
+STAT_REVERSE=逆の順番
+STAT_PAGE= %1:d ページの %0:d 番目\n (%3:d エントリーの %2:d 番目)
+
+STAT_DESC_SCORES=ハイスコア
+STAT_DESC_SCORES_REVERSED=ロースコア
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=ベスト・プレイヤー
+STAT_DESC_SINGERS_REVERSED=ワースト・プレイヤー
+STAT_FORMAT_SINGERS=%0:s \n 平均スコア: %1:d
+
+STAT_DESC_SONGS=一番人気ある曲
+STAT_DESC_SONGS_REVERSED=一番人気なし曲
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx 回歌った
+
+STAT_DESC_BANDS=一番人気ある歌手
+STAT_DESC_BANDS_REVERSED=一番人気ない歌手
+STAT_FORMAT_BANDS=%0:s \n %1:dx 回歌った
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=エラー
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=確認
+MSG_QUIT_USDX=本当にゲームをやめる?
+MSG_END_PARTY=本当にパーティーモードをやめる?
+
+ERROR_NO_SONGS=曲はロードしてない
+ERROR_NO_PLUGINS=プラグインはロードしてない
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=曲をロードできない
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=曲をロードできない: ファイルが見つからない
+ERROR_CORRUPT_SONG_NO_NOTES=曲をロードできない: 音符が見つからない
+ERROR_CORRUPT_SONG_NO_BREAKS=曲をロードできない: ライン・ブレークが見つからない
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=曲をロードできない: ライン %0:d の解析エラー 
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=何回曲を歌った数える
+;UNUSED: PARTY_ROUNDS=ラウンド
diff --git a/songmanagement/game/languages/Language.new b/songmanagement/game/languages/Language.new
new file mode 100644
index 00000000..7dade950
--- /dev/null
+++ b/songmanagement/game/languages/Language.new
@@ -0,0 +1,441 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+;TODO: SING_LOADING=Loading...
+
+;TODO: SING_CHOOSE_MODE=choose mode
+;TODO: SING_SING=sing
+;TODO: SING_SING_DESC=quick game: sing solo or duet
+
+;TODO: SING_MULTI=party
+;TODO: SING_MULTI_DESC=sing in party-mode
+
+;TODO: SING_TOOLS=tools
+
+;TODO: SING_STATS=stats
+;TODO: SING_STATS_DESC=view the statistics
+
+;TODO: SING_EDITOR=editor
+;TODO: SING_EDITOR_DESC=create your own song
+
+;TODO: SING_GAME_OPTIONS=game options
+;TODO: SING_GAME_OPTIONS_DESC=change game settings
+
+;TODO: SING_EXIT=quit
+;TODO: SING_EXIT_DESC=quit game
+
+;TODO: SING_OPTIONS=options
+;TODO: SING_OPTIONS_DESC=change settings
+;TODO: SING_OPTIONS_WHEREAMI=Options
+
+;TODO: SING_OPTIONS_GAME=game
+;TODO: SING_OPTIONS_GRAPHICS=graphics
+;TODO: SING_OPTIONS_SOUND=sound
+;TODO: SING_OPTIONS_LYRICS=lyrics
+;TODO: SING_OPTIONS_THEMES=themes
+;TODO: SING_OPTIONS_RECORD=record
+;TODO: SING_OPTIONS_ADVANCED=advanced
+;TODO: SING_OPTIONS_EXIT=back
+
+;TODO: SING_OPTIONS_GAME_WHEREAMI=Options Game
+;TODO: SING_OPTIONS_GAME_DESC=general game settings
+;TODO: SING_OPTIONS_GAME_PLAYERS=Players
+;TODO: SING_OPTIONS_GAME_DIFFICULTY=Difficulty
+;TODO: SING_OPTIONS_GAME_LANGUAGE=Language
+;TODO: SING_OPTIONS_GAME_TABS=Tabs
+;TODO: SING_OPTIONS_GAME_SORTING=Sorting
+;TODO: SING_OPTIONS_GAME_DEBUG=Debug
+
+;TODO: SING_OPTIONS_GRAPHICS_WHEREAMI=Options Graphics
+;TODO: SING_OPTIONS_GRAPHICS_DESC=graphic settings
+;TODO: SING_OPTIONS_GRAPHICS_RESOLUTION=Resolution
+;TODO: SING_OPTIONS_GRAPHICS_FULLSCREEN=Fullscreen
+;TODO: SING_OPTIONS_GRAPHICS_DEPTH=Depth
+;TODO: SING_OPTIONS_GRAPHICS_VISUALIZER=Visualization
+;TODO: SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloscope
+;TODO: SING_OPTIONS_GRAPHICS_LINEBONUS=Line Bonus
+;TODO: SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Movie size
+
+;TODO: SING_OPTIONS_SOUND_WHEREAMI=Options Sound
+;TODO: SING_OPTIONS_SOUND_DESC=sound settings
+;TODO: SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Microphone Playback
+;TODO: SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Background music
+;TODO: SING_OPTIONS_SOUND_MIC_BOOST=Mic boost
+;TODO: SING_OPTIONS_SOUND_CLICK_ASSIST=Click assist
+;TODO: SING_OPTIONS_SOUND_BEAT_CLICK=Beat click
+;TODO: SING_OPTIONS_SOUND_THRESHOLD=Threshold
+;TODO: SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Two players mode
+;TODO: SING_OPTIONS_SOUND_PREVIEWVOLUME=Preview Volume
+;TODO: SING_OPTIONS_SOUND_PREVIEWFADING=Preview Fading
+
+;TODO: SING_OPTIONS_LYRICS_WHEREAMI=Options Lyrics
+;TODO: SING_OPTIONS_LYRICS_DESC=lyrics settings
+;TODO: SING_OPTIONS_LYRICS_FONT=Font
+;TODO: SING_OPTIONS_LYRICS_EFFECT=Effect
+;TODO: SING_OPTIONS_LYRICS_SOLMIZATION=Solmization
+;TODO: SING_OPTIONS_LYRICS_NOTELINES=Staves
+
+;TODO: SING_OPTIONS_THEMES_WHEREAMI=Options Themes
+;TODO: SING_OPTIONS_THEMES_DESC=theme and skin settings
+;TODO: SING_OPTIONS_THEMES_THEME=Theme
+;TODO: SING_OPTIONS_THEMES_SKIN=Skin
+;TODO: SING_OPTIONS_THEMES_COLOR=Color
+
+;TODO: SING_OPTIONS_RECORD_WHEREAMI=Options Record
+;TODO: SING_OPTIONS_RECORD_DESC=microphone settings
+;TODO: SING_OPTIONS_RECORD_CARD=Soundcard
+;TODO: SING_OPTIONS_RECORD_INPUT=Input
+;TODO: SING_OPTIONS_RECORD_CHANNEL=Channel
+
+;TODO: SING_OPTIONS_ADVANCED_WHEREAMI=Options Advanced
+;TODO: SING_OPTIONS_ADVANCED_DESC=advanced settings
+;TODO: SING_OPTIONS_ADVANCED_EFFECTSING=Sing Effects
+;TODO: SING_OPTIONS_ADVANCED_SCREENFADE=Screen Fading
+;TODO: SING_OPTIONS_ADVANCED_LOADANIMATION=Load Animation
+;TODO: SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Safety Questions
+;TODO: SING_OPTIONS_ADVANCED_LINEBONUS=Line Bonus
+;TODO: SING_OPTIONS_ADVANCED_ONSONGCLICK=after Song Select
+;TODO: SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto PartyMenu
+
+;TODO: SING_EDIT=Editor
+;TODO: SING_EDIT_MENU_DESCRIPTION=create your own song
+
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Import text from midi file
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_EXIT=back
+;TODO: SING_EDIT_BUTTON_CONVERT=Import
+;TODO: SING_EDIT_BUTTON_EXIT=back
+
+;TODO: SING_EDIT_NAVIGATE=navigate
+;TODO: SING_EDIT_SELECT=select
+;TODO: SING_EDIT_EXIT=back
+
+;TODO: SING_LEGEND_SELECT=select
+;TODO: SING_LEGEND_NAVIGATE=navigate
+;TODO: SING_LEGEND_CONTINUE=continue
+;TODO: SING_LEGEND_ESC=back
+
+;TODO: SING_PLAYER_DESC=enter player name/s
+;TODO: SING_PLAYER_WHEREAMI=Playernames
+;TODO: SING_PLAYER_ENTER_NAME=enter name
+
+;TODO: SING_DIFFICULTY_DESC=select difficulty
+;TODO: SING_DIFFICULTY_WHEREAMI=Difficulty
+;TODO: SING_DIFFICULTY_CONTINUE=to song selection
+;TODO: SING_EASY=Easy
+;TODO: SING_MEDIUM=Medium
+;TODO: SING_HARD=Hard
+
+;TODO: SING_SONG_SELECTION_DESC=choose your song
+;TODO: SING_SONG_SELECTION_WHEREAMI=Song Selection
+;TODO: SING_SONG_SELECTION_GOTO=go to ..
+;TODO: SING_SONG_SELECTION=song selection
+;TODO: SING_SONG_SELECTION_MENU=menu
+;TODO: SING_SONG_SELECTION_PLAYLIST=playlist
+;TODO: SING_SONGS_IN_CAT=Songs
+;TODO: PLAYLIST_CATTEXT=Playlist: %s
+
+;TODO: SING_TIME=TIME
+;TODO: SING_TOTAL=total
+;TODO: SING_MODE=sing solo
+;TODO: SING_NOTES=notes
+;TODO: SING_GOLDEN_NOTES=golden notes
+;TODO: SING_PHRASE_BONUS=line bonus
+
+;TODO: SING_MENU=Main Menu
+
+;TODO: SONG_SCORE=song score
+;TODO: SONG_SCORE_WHEREAMI=Score
+
+;TODO: SING_SCORE_TONE_DEAF=Tone Deaf
+;TODO: SING_SCORE_AMATEUR=Amateur
+;TODO: SING_SCORE_WANNABE=Wannabe
+;TODO: SING_SCORE_HOPEFUL=Hopeful
+;TODO: SING_SCORE_RISING_STAR=Rising Star
+;TODO: SING_SCORE_LEAD_SINGER=Lead Singer
+;TODO: SING_SCORE_SUPERSTAR=Superstar
+;TODO: SING_SCORE_ULTRASTAR=Ultrastar
+
+;TODO: SING_TOP_5_CHARTS=top 5 Players
+;TODO: SING_TOP_5_CHARTS_WHEREAMI=top 5
+;TODO: SING_TOP_5_CHARTS_CONTINUE=to song selection
+;TODO: SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+;TODO: POPUP_PERFECT=perfect!
+;TODO: POPUP_AWESOME=awesome!
+;TODO: POPUP_GREAT=great!
+;TODO: POPUP_GOOD=good!
+;TODO: POPUP_NOTBAD=not bad!
+;TODO: POPUP_BAD=bad!
+;TODO: POPUP_POOR=poor!
+;TODO: POPUP_AWFUL=awful!
+
+;TODO: IMPLODE_GLUE1=,
+;TODO: IMPLODE_GLUE2= and
+
+;TODO: SONG_MENU_NAME_MAIN=song menu
+;TODO: SONG_MENU_PLAY=Sing
+;TODO: SONG_MENU_CHANGEPLAYERS=Change Players
+;TODO: SONG_MENU_EDIT=Edit
+;TODO: SONG_MENU_MODI=Sing a Modi
+;TODO: SONG_MENU_CANCEL=Cancel
+
+;TODO: SONG_MENU_NAME_PLAYLIST=Song Menu
+;TODO: SONG_MENU_PLAYLIST_ADD=Add Song
+;TODO: SONG_MENU_PLAYLIST_DEL=Delete Song
+
+;TODO: SONG_MENU_NAME_PLAYLIST_ADD=Add Song
+;TODO: SONG_MENU_PLAYLIST_ADD_NEW=to new playlist
+;TODO: SONG_MENU_PLAYLIST_ADD_EXISTING=to existing playlist
+;TODO: SONG_MENU_PLAYLIST_NOEXISTING=No playlist available
+
+;TODO: SONG_MENU_NAME_PLAYLIST_NEW=New Playlist
+;TODO: SONG_MENU_PLAYLIST_NEW_CREATE=Create
+;TODO: SONG_MENU_PLAYLIST_NEW_UNNAMED=Unnamed
+
+;TODO: SONG_MENU_NAME_PLAYLIST_DELITEM=Really Delete?
+;TODO: SONG_MENU_YES=Yes
+;TODO: SONG_MENU_NO=No
+
+;TODO: SONG_MENU_NAME_PLAYLIST_LOAD=Open Playlist
+;TODO: SONG_MENU_PLAYLIST_LOAD=open
+;TODO: SONG_MENU_PLAYLIST_DELCURRENT=delete current Playlist
+
+;TODO: SONG_MENU_NAME_PLAYLIST_DEL=Delete Playlist?
+
+;TODO: SONG_MENU_NAME_PARTY_MAIN=Party Menu
+;TODO: SONG_MENU_JOKER=Joker
+
+;TODO: SONG_MENU_NAME_PARTY_JOKER=take joker
+
+;TODO: SONG_JUMPTO_DESC=search song
+;TODO: SONG_JUMPTO_TYPE_DESC=Search for:
+;TODO: SONG_JUMPTO_TYPE1=All
+;TODO: SONG_JUMPTO_TYPE2=Title
+;TODO: SONG_JUMPTO_TYPE3=Artist
+;TODO: SONG_JUMPTO_SONGSFOUND=%d Song(s) found
+;TODO: SONG_JUMPTO_NOSONGSFOUND=No Song found
+;TODO: SONG_JUMPTO_HELP=Type Text to Search for
+;TODO: SONG_JUMPTO_CATTEXT=Search for: %s
+
+;TODO: PARTY_MODE=party mode
+;TODO: PARTY_DIFFICULTY=Difficulty
+;TODO: PARTY_PLAYLIST=Playlist Mode
+;TODO: PARTY_PLAYLIST_ALL=All songs
+;TODO: PARTY_PLAYLIST_CATEGORY=Folder
+;TODO: PARTY_PLAYLIST_PLAYLIST=Playlist
+;TODO: PARTY_TEAMS=number of teams
+;TODO: PARTY_TEAMS_PLAYER1=num. of singers
+;TODO: PARTY_TEAMS_PLAYER2=num. of singers
+;TODO: PARTY_TEAMS_PLAYER3=num. of singers
+
+;TODO: PARTY_LEGEND_CONTINUE=continue
+
+;TODO: PARTY_OPTIONS_DESC=settings for the party-game
+;TODO: PARTY_OPTIONS_WHEREAMI=Party Options
+
+;TODO: PARTY_PLAYER_DESC=enter player- and teamnames!
+;TODO: PARTY_PLAYER_WHEREAMI=Party Names
+;TODO: PARTY_PLAYER_ENTER_NAME=enter names
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+;TODO: PARTY_ROUNDS_LEGEND_CONTINUE=start party-game
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+;TODO: PARTY_ROUND_DESC=next players to the mics
+;TODO: PARTY_ROUND_WHEREAMI=Party Next Round
+;TODO: PARTY_ROUND_LEGEND_CONTINUE=start round
+
+;TODO: PARTY_SONG_WHEREAMI=Party Song-Selection
+;TODO: PARTY_SONG_LEGEND_CONTINUE=sing
+;TODO: PARTY_SONG_MENU=party menu
+
+;TODO: PARTY_SCORE_DESC=score of the last round
+;TODO: PARTY_SCORE_WHEREAMI=Party Points
+
+;TODO: PARTY_WIN_DESC=winner of the party-game
+;TODO: PARTY_WIN_WHEREAMI=Party Winner
+;TODO: PARTY_WIN_LEGEND_CONTINUE=back to main-menu
+
+;TODO: PARTY_ROUND=Round
+;TODO: PARTY_ROUND_WINNER=Winner
+;TODO: PARTY_NOTPLAYEDYET=not played yet
+;TODO: PARTY_NOBODY=nobody
+;TODO: NEXT_ROUND=Next round:
+
+;TODO: PARTY_DISMISSED=Dismissed!
+;TODO: PARTY_SCORE_WINS=%s
+;TODO: PARTY_SCORE_WINS2=wins!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+;TODO: MODE_HDL_NAME=Hold the Line
+;TODO: MODE_HDL_DESC=Don't get worse than the pointer at the rating bar shows you.
+
+;TODO: MODE_5000POINTS_NAME=Until 5000
+;TODO: MODE_5000POINTS_DESC=Who gets 5000 points first wins the match.
+
+;TODO: MODE_DUEL_NAME=Duel
+;TODO: MODE_DUEL_DESC=Sing a duel until 10000 points.
+
+;TODO: MODE_TEAMDUEL_NAME=Team Duell
+;TODO: MODE_TEAMDUEL_DESC=Pass The Mic!
+
+;TODO: MODE_BLIND_NAME=Blind Mode
+;TODO: MODE_BLIND_DESC=Duel without seeing the notes.
+
+;TODO: STAT_MAIN=Statistics
+;TODO: STAT_MAIN_DESC=General
+;TODO: STAT_MAIN_WHEREAMI=Statistics
+
+;TODO: STAT_OVERVIEW_INTRO=%0:s Statistics.  \n Last Reset at %2:.2d.%1:.2d.%3:d
+;TODO: STAT_OVERVIEW_SONG=%0:d Songs(%3:d with Video), whereof %1:d already were played  and %2:d were not played yet.\n The most popular Song is %5:s from %4:s.
+;TODO: STAT_OVERVIEW_PLAYER=Since the last Reset there were/was %0:d different Player(s).\n The best Player is %1:s with an average Score of %2:d Points.\n %3:s did the highest Score with %4:d Points.
+
+;TODO: STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+;TODO: STAT_DETAIL=Statistics
+;TODO: STAT_DETAIL_WHEREAMI=Detail Statistics
+
+;TODO: STAT_NEXT=Next Page
+;TODO: STAT_PREV=Previous Page
+;TODO: STAT_REVERSE=Reverse Order
+;TODO: STAT_PAGE=page %0:d of %1:d pages\n (%2:d of %3:d Entrys)
+
+;TODO: STAT_DESC_SCORES=HighScores
+;TODO: STAT_DESC_SCORES_REVERSED=LowScores
+;TODO: STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+;TODO: STAT_DESC_SINGERS=Best Singers
+;TODO: STAT_DESC_SINGERS_REVERSED=Worst Singers
+;TODO: STAT_FORMAT_SINGERS=%0:s \n Average Score: %1:d
+
+;TODO: STAT_DESC_SONGS=Most popular Songs
+;TODO: STAT_DESC_SONGS_REVERSED=Least popular Songs
+;TODO: STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx sung
+
+;TODO: STAT_DESC_BANDS=Most popular Bands
+;TODO: STAT_DESC_BANDS_REVERSED=Least popular Bands
+;TODO: STAT_FORMAT_BANDS=%0:s \n %1:dx Sung
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+;TODO: MSG_ERROR_TITLE=Error
+;TODO: MSG_INFO_TITLE=Information
+;TODO: MSG_QUESTION_TITLE=Question
+;TODO: MSG_QUIT_USDX=Really leave UltraStar?
+;TODO: MSG_END_PARTY=Really leave Party Mode?
+
+;TODO: ERROR_NO_SONGS=No Songs loaded
+;TODO: ERROR_NO_PLUGINS=No Plugins loaded
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+;TODO: ERROR_CORRUPT_SONG=Song could not be loaded.
+;TODO: ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Song could not be loaded: File not found
+;TODO: ERROR_CORRUPT_SONG_NO_NOTES=Song could not be loaded: Can''t find any notes
+;TODO: ERROR_CORRUPT_SONG_NO_BREAKS=Song could not be loaded: Can''t find any linebreaks
+;TODO: ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Song could not be loaded: Error parsing line %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
diff --git a/songmanagement/game/languages/Luxembourgish.ini b/songmanagement/game/languages/Luxembourgish.ini
new file mode 100644
index 00000000..9df50471
--- /dev/null
+++ b/songmanagement/game/languages/Luxembourgish.ini
@@ -0,0 +1,442 @@
+[Text]
+OPTION_VALUE_CATALAN=Katalanesch
+OPTION_VALUE_CROATIAN=Kroatesch
+OPTION_VALUE_CZECH=Tschechesch
+OPTION_VALUE_DANISH=Dänesch
+OPTION_VALUE_DUTCH=Nidderlännesch
+OPTION_VALUE_ENGLISH=Englesch
+OPTION_VALUE_EUSKARA=Baskesch
+OPTION_VALUE_FINNISH=Finnesch
+OPTION_VALUE_FRENCH=Franséisch
+OPTION_VALUE_GERMAN=Däitsch
+OPTION_VALUE_GREEK=Griichesch
+OPTION_VALUE_HUNGARIAN=Ungaresch
+OPTION_VALUE_ICELANDIC=Islännesch
+OPTION_VALUE_ITALIAN=Italienesch
+OPTION_VALUE_JAPANESE=Japanesch
+OPTION_VALUE_LUXEMBOURGISH=Lëtzebuergesch
+OPTION_VALUE_NORWEGIAN=Norwegesch
+OPTION_VALUE_POLISH=Polnesch
+OPTION_VALUE_PORTUGUESE=Portugisesch
+OPTION_VALUE_RUSSIAN=Russesch
+OPTION_VALUE_SERBIAN=Serbesch
+OPTION_VALUE_SLOVAK=Slowakesch
+OPTION_VALUE_SLOVENIAN=Slowenesch
+OPTION_VALUE_SPANISH=Spuenesch
+OPTION_VALUE_SWEDISH=Schwedesch
+
+OPTION_VALUE_EASY=Einfach
+OPTION_VALUE_MEDIUM=Mëttel
+OPTION_VALUE_HARD=Schwéier
+
+OPTION_VALUE_ON=Un
+OPTION_VALUE_OFF=Aus
+
+OPTION_VALUE_EDITION=Editioun
+OPTION_VALUE_GENRE=Genre
+OPTION_VALUE_LANGUAGE=Sprooch
+OPTION_VALUE_FOLDER=Ordner
+OPTION_VALUE_TITLE=Titel
+OPTION_VALUE_ARTIST=Kënschtler
+OPTION_VALUE_TITLE2=Titel2
+OPTION_VALUE_ARTIST2=Kënschtler2
+
+OPTION_VALUE_WHENNOVIDEO=Wa kee Video
+
+OPTION_VALUE_SMALL=Kleng
+OPTION_VALUE_BIG=Grouss
+
+OPTION_VALUE_HALF=Hallef
+OPTION_VALUE_FULL_VID=Voll (Video)
+OPTION_VALUE_FULL_VID_BG=Voll (HG & Video)
+
+OPTION_VALUE_AUTO=Automatesch
+OPTION_VALUE_SEC=Sekonn
+OPTION_VALUE_SECS=Sekonnen
+
+OPTION_VALUE_PLAIN=Klassesch
+OPTION_VALUE_OLINE1=Konturen
+OPTION_VALUE_OLINE2=Déck
+
+OPTION_VALUE_SIMPLE=Silben
+OPTION_VALUE_ZOOM=Vergréisseren
+OPTION_VALUE_SLIDE=Rutschen
+OPTION_VALUE_BALL=Ball
+OPTION_VALUE_SHIFT=Hopsen
+
+OPTION_VALUE_EURO=Europäesch
+OPTION_VALUE_JAPAN=Japanesch
+OPTION_VALUE_AMERICAN=Amerikanesch
+
+OPTION_VALUE_BLUE=Blo
+OPTION_VALUE_GREEN=Gréng
+OPTION_VALUE_PINK=Rosa
+OPTION_VALUE_RED=Rout
+OPTION_VALUE_VIOLET=Violett
+OPTION_VALUE_ORANGE=Orange
+OPTION_VALUE_YELLOW=Giel
+OPTION_VALUE_BROWN=Brong
+OPTION_VALUE_BLACK=Schwaarz
+
+OPTION_VALUE_SING=Sangen
+OPTION_VALUE_SELECT_PLAYERS=Spiller auswielen
+OPTION_VALUE_OPEN_MENU=Menü opmaachen
+
+OPTION_VALUE_HARDWARE_CURSOR=Hardware Zeiger
+OPTION_VALUE_SOFTWARE_CURSOR=Software Zeiger
+
+SING_LOADING=Lueden...
+
+SING_CHOOSE_MODE=Wielt e Modus aus
+SING_SING=Sangen
+SING_SING_DESC=Sangt Solo
+
+SING_MULTI=Party
+SING_MULTI_DESC=Schmäisst eng Party
+
+SING_TOOLS=Geschir
+
+SING_STATS=Statistiken
+SING_STATS_DESC=Kuckt d'Statistiken un
+
+SING_EDITOR=Editor
+SING_EDITOR_DESC=Erstellt Är eege Lidder
+
+SING_GAME_OPTIONS=Optiounen
+SING_GAME_OPTIONS_DESC=Ännert d'Astellunge vum Spill
+
+SING_EXIT=Verloossen
+SING_EXIT_DESC=Spill verloossen
+
+SING_OPTIONS=Optiounen
+SING_OPTIONS_DESC=Ännert d'Astellungen
+SING_OPTIONS_WHEREAMI=Optiounen
+
+SING_OPTIONS_GAME=Spill
+SING_OPTIONS_GRAPHICS=Graphik
+SING_OPTIONS_SOUND=Toun
+SING_OPTIONS_LYRICS=Lyric
+SING_OPTIONS_THEMES=Design
+SING_OPTIONS_RECORD=Mikro
+SING_OPTIONS_ADVANCED=Erweidert
+SING_OPTIONS_EXIT=Zeréck
+
+SING_OPTIONS_GAME_WHEREAMI=Spilloptiounen
+SING_OPTIONS_GAME_DESC=Spillastellungen
+SING_OPTIONS_GAME_PLAYERS=Spiller
+SING_OPTIONS_GAME_DIFFICULTY=Schwieregkeet
+SING_OPTIONS_GAME_LANGUAGE=Sprooch
+SING_OPTIONS_GAME_TABS=Ordner
+SING_OPTIONS_GAME_SORTING=Zortéieren no
+SING_OPTIONS_GAME_DEBUG=Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Graphikoptiounen
+SING_OPTIONS_GRAPHICS_DESC=Graphikastellungen
+SING_OPTIONS_GRAPHICS_RESOLUTION=Ofléisung
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Vollbild
+SING_OPTIONS_GRAPHICS_DEPTH=Faarfdéift
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualiséierung
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oszilloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Sazbonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Videogréisst
+
+SING_OPTIONS_SOUND_WHEREAMI=Tounoptiounen
+SING_OPTIONS_SOUND_DESC=Tounastellungen
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Mikro lauschteren
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Hannergrondmusik
+SING_OPTIONS_SOUND_MIC_BOOST=Mikro-Unhiewung
+SING_OPTIONS_SOUND_CLICK_ASSIST=Click-Assistent
+SING_OPTIONS_SOUND_BEAT_CLICK=Metronom
+SING_OPTIONS_SOUND_THRESHOLD=Rauschënnerdrëck.
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=2-Spiller-Modus
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Iwwerbléck Lautst.
+SING_OPTIONS_SOUND_PREVIEWFADING=Iwwerbléck Fading
+
+SING_OPTIONS_LYRICS_WHEREAMI=Lyricsoptiounen
+SING_OPTIONS_LYRICS_DESC=Lyricsastellungen
+SING_OPTIONS_LYRICS_FONT=Schrëftart
+SING_OPTIONS_LYRICS_EFFECT=Effekt
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmisatioun
+SING_OPTIONS_LYRICS_NOTELINES=Noutelinien
+
+SING_OPTIONS_THEMES_WHEREAMI=Designoptiounen
+SING_OPTIONS_THEMES_DESC=Designastellungen
+SING_OPTIONS_THEMES_THEME=Design
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Faarf
+
+SING_OPTIONS_RECORD_WHEREAMI=Opzeechnungsoptiounen
+SING_OPTIONS_RECORD_DESC=Mikrofonastellungen
+SING_OPTIONS_RECORD_CARD=Soundkaart
+SING_OPTIONS_RECORD_INPUT=Agank
+SING_OPTIONS_RECORD_CHANNEL=Kanal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Erweidert Optiounen
+SING_OPTIONS_ADVANCED_DESC=Erweidert Astellungen
+SING_OPTIONS_ADVANCED_EFFECTSING=Sangeffekt
+SING_OPTIONS_ADVANCED_SCREENFADE=Bildschierm-Faden
+SING_OPTIONS_ADVANCED_LOADANIMATION=Lued-Animatioun
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Sécherheetsfro
+SING_OPTIONS_ADVANCED_LINEBONUS=Sazbonus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=No Liddauswiel
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto Partymenü
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=Erstellt Är eege Lidder
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Midi/Kar Datei als Text exportéieren
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Zeréck
+SING_EDIT_BUTTON_CONVERT=Importéieren
+SING_EDIT_BUTTON_EXIT=Zeréck
+
+SING_EDIT_NAVIGATE=Navigéieren
+SING_EDIT_SELECT=Auswielen
+SING_EDIT_EXIT=Zeréck
+
+SING_LEGEND_SELECT=Auswielen
+SING_LEGEND_NAVIGATE=Navigéieren
+SING_LEGEND_CONTINUE=Weider
+SING_LEGEND_ESC=Zeréck
+
+SING_PLAYER_DESC=Gitt de Numm an
+SING_PLAYER_WHEREAMI=Numm vum Spiller
+SING_PLAYER_ENTER_NAME=Änneren
+
+SING_DIFFICULTY_DESC=Gräift e Schwieregkeetsgrad eraus
+SING_DIFFICULTY_WHEREAMI=Schwieregkeetsgrad
+SING_DIFFICULTY_CONTINUE=Weider
+SING_EASY=Einfach
+SING_MEDIUM=Mëttel
+SING_HARD=Schwéier
+
+SING_SONG_SELECTION_DESC=Sicht e Lidd eraus
+SING_SONG_SELECTION_WHEREAMI=Liddauswiel
+SING_SONG_SELECTION_GOTO=Erreechen
+SING_SONG_SELECTION=Liddauswiel
+SING_SONG_SELECTION_MENU=Menü
+SING_SONG_SELECTION_PLAYLIST=Playlist
+SING_SONGS_IN_CAT=Lidder
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=ZÄIT
+SING_TOTAL=Am Ganzen
+SING_MODE=Sangmodus
+SING_NOTES=Nouten
+SING_GOLDEN_NOTES=Gëllen Nouten
+SING_PHRASE_BONUS=Sazbonus
+
+SING_MENU=Haaptmenü
+
+SONG_SCORE=Punkten
+SONG_SCORE_WHEREAMI=Punkten
+
+SING_SCORE_TONE_DEAF=Lusch
+SING_SCORE_AMATEUR=Ufänger
+SING_SCORE_WANNABE=Bretzkëscht
+SING_SCORE_HOPEFUL=Fortgeschrëtten
+SING_SCORE_RISING_STAR=Stäerchen
+SING_SCORE_LEAD_SINGER=Sänger
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=Top 5
+SING_TOP_5_CHARTS_WHEREAMI=Bescht Spiller
+SING_TOP_5_CHARTS_CONTINUE=Weider
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=Schwieregkeetsgrad
+
+POPUP_PERFECT=Perfekt!
+POPUP_AWESOME=Chill!
+POPUP_GREAT=Gäil!
+POPUP_GOOD=Gutt!
+POPUP_NOTBAD=Net schlecht
+POPUP_BAD=Bouh!
+POPUP_POOR=Schlecht!
+POPUP_AWFUL=Schäiss!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= an
+
+SONG_MENU_NAME_MAIN=Menü
+SONG_MENU_PLAY=Sangen
+SONG_MENU_CHANGEPLAYERS=Spiller tauschen
+SONG_MENU_EDIT=Editor
+SONG_MENU_MODI=E Modus sangen
+SONG_MENU_CANCEL=Offbriechen
+
+SONG_MENU_NAME_PLAYLIST=Menü
+SONG_MENU_PLAYLIST_ADD=Lidd bäifügen
+SONG_MENU_PLAYLIST_DEL=Lidd läschen
+
+SONG_MENU_NAME_PLAYLIST_ADD=Lidd bäifügen
+SONG_MENU_PLAYLIST_ADD_NEW=Bei enger neier Playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=Bäifüge bei d'Playlist
+SONG_MENU_PLAYLIST_NOEXISTING=Keng Playlist fonnt
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nei Playlist
+SONG_MENU_PLAYLIST_NEW_CREATE=Erstellen
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Ouni-Numm
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Wierklech läschen?
+SONG_MENU_YES=Jo
+SONG_MENU_NO=Nee
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Playlist wielen
+SONG_MENU_PLAYLIST_LOAD=Opmaachen
+SONG_MENU_PLAYLIST_DELCURRENT=Aktuell Playlist läschen
+
+SONG_MENU_NAME_PLAYLIST_DEL=Playlist läschen?
+
+SONG_MENU_NAME_PARTY_MAIN=Partymenü
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=Joker asetzen
+
+SONG_JUMPTO_DESC=Sichen no
+SONG_JUMPTO_TYPE_DESC=Sichen no:
+SONG_JUMPTO_TYPE1=Alles
+SONG_JUMPTO_TYPE2=Titel
+SONG_JUMPTO_TYPE3=Kënschtler
+SONG_JUMPTO_SONGSFOUND=%d Lidd(er) fonnt
+SONG_JUMPTO_NOSONGSFOUND=Kee Lidd fonnt
+SONG_JUMPTO_HELP=Sichtext aginn
+SONG_JUMPTO_CATTEXT=Sichen no: %s
+
+PARTY_MODE=Partymodus
+PARTY_DIFFICULTY=Schwieregkeet
+PARTY_PLAYLIST=Playlist
+PARTY_PLAYLIST_ALL=All Lidder
+PARTY_PLAYLIST_CATEGORY=Ordner
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_TEAMS=Gruppenunzuel
+PARTY_TEAMS_PLAYER1=Spillerunzuel
+PARTY_TEAMS_PLAYER2=Spillerunzuel
+PARTY_TEAMS_PLAYER3=Spillerunzuel
+
+PARTY_LEGEND_CONTINUE=Weider
+
+PARTY_OPTIONS_DESC=Astellunge fir de Partymodus
+PARTY_OPTIONS_WHEREAMI=Partymodus: Optiounen
+
+PARTY_PLAYER_DESC=Tippt d'Nimm vun de Spiller an Gruppen an
+PARTY_PLAYER_WHEREAMI=Partymodus: Gruppen
+PARTY_PLAYER_ENTER_NAME=Änneren
+
+
+PARTY_ROUNDS_DESC= Wielt d'Modi
+PARTY_ROUNDS_WHEREAMI=Partymodus: Ronnen
+PARTY_ROUNDS_LEGEND_CONTINUE=Party ufänken
+PARTY_ROUNDCOUNT=Unzuel vu Ronnen
+PARTY_SELECTMODE1=1. Ronn
+PARTY_SELECTMODE2=2. Ronn
+PARTY_SELECTMODE3=3. Ronn
+PARTY_SELECTMODE4=4. Ronn
+PARTY_SELECTMODE5=5. Ronn
+PARTY_SELECTMODE6=6. Ronn
+PARTY_SELECTMODE7=7. Ronn
+
+PARTY_ROUND_DESC=Déi nächst Spiller un är Mikroen!
+PARTY_ROUND_WHEREAMI=Partymodus: Nächst Ronn
+PARTY_ROUND_LEGEND_CONTINUE=Ronn ufänken
+
+PARTY_SONG_WHEREAMI=Partymodus: Liddauswiel
+PARTY_SONG_LEGEND_CONTINUE=Sangen
+PARTY_SONG_MENU=Partymenü
+
+PARTY_SCORE_DESC=Punkten vun dëser Ronn
+PARTY_SCORE_WHEREAMI=Partymodus: Punkten
+
+PARTY_WIN_DESC=Gewënner vum Partyspill
+PARTY_WIN_WHEREAMI=Partymodus: Gewënner
+PARTY_WIN_LEGEND_CONTINUE=Zeréck am Haaptmenü
+
+PARTY_ROUND=Ronn
+PARTY_ROUND_WINNER=Gewënner
+PARTY_NOTPLAYEDYET=-
+PARTY_NOBODY=Keen
+NEXT_ROUND=Nächst Ronn:
+
+PARTY_DISMISSED=Verluer!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=huet gewonn!
+
+MODE_RANDOM_NAME=Zoufällege Modus
+MODE_RANDOM_DESC=E Modus gëtt zoufälleg gewielt.
+
+MODE_HOLDTHELINE_NAME=Balken halen
+MODE_HOLDTHELINE_DESC=Halt d'Bewäertung bis beim ugewisene Beräich.
+
+MODE_5000POINTS_NAME=Bis 5000
+MODE_5000POINTS_DESC=Wien als éischt 5000 Punkten huet, gewënnt.
+
+MODE_DUEL_NAME=Duell
+MODE_DUEL_DESC=Wien déi meeschte Punkten huet gewënnt.
+
+MODE_TEAMDUEL_NAME=Teamsangen
+MODE_TEAMDUEL_DESC=Gëft de Mikro weider!
+
+MODE_BLIND_NAME=Blann Modus
+MODE_BLIND_DESC=Erreecht blann déi héchst Punktezuel.
+
+STAT_MAIN=Statistiken
+STAT_MAIN_DESC=Allgemeng
+STAT_MAIN_WHEREAMI=Statistiken
+
+STAT_OVERVIEW_INTRO=Statistike vun %0:s \n Lescht Reinitialisatioun den %1:.2d.%2:.2d.%3:d
+STAT_OVERVIEW_SONG=Et ginn %0:d Lidder (%3:d mat Video). Dovunner goufen op mannst %1:d scho gesongen an %2:d nach net. \n\n Dat meescht gesongend Lidd ass %5:s vun %4:s.
+STAT_OVERVIEW_PLAYER=%0:d verschidde Spiller hunn gesonge säit der leschter Reinitialisatioun. \n\n De beschte Spiller ass %1:s mat %2:d Punkten. Mat %4:d Punkten huet %3:s den Highscore.
+
+STAT_FORMAT_DATE=%0:.2d.%1:.2d.%2:d
+
+STAT_DETAIL=Statistiken
+STAT_DETAIL_WHEREAMI=Detailléiert Statistiken
+
+STAT_NEXT=Nächst Säit
+STAT_PREV=Vireg Säit
+STAT_REVERSE=Ëmkéieren
+STAT_PAGE=Säit %0:d/%1:d \n (%2:d Antrag vun %3:d %3:d )
+
+STAT_DESC_SCORES=Highscore
+STAT_DESC_SCORES_REVERSED=Schlechtst Punkten
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Beschte Sänger
+STAT_DESC_SINGERS_REVERSED=Schlechtst Sänger
+STAT_FORMAT_SINGERS=%0:s \n Duerchschnëttlech Punktenzuel: %1:d
+
+STAT_DESC_SONGS=Lieblings Lidder
+STAT_DESC_SONGS_REVERSED=Onbeléiftsten Lidder
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx gesongen
+
+STAT_DESC_BANDS=Lieblings Band
+STAT_DESC_BANDS_REVERSED=Onbeléiftsten Band
+STAT_FORMAT_BANDS=%0:s \n Lidder gesongen: %1:d
+
+SCREENSHOT_SAVED=Screenshot ass gespäichert.
+SCREENSHOT_FAILED=Screenshot kann net gespäichert ginn.
+
+INFO_FILE_SAVED=Datei ass gespäichert.
+ERROR_SAVE_FILE_FAILED=Datei kann net gespäichert ginn.
+ERROR_FILE_NOT_FOUND=Datei net fonnt
+
+ENCODING_ERROR_ASK_FOR_UTF8=Ännerunge konnten net an der aktueller Kodéierung geséchert ginn. Op UTF-8 konvertéieren?
+EDITOR_ERROR_NO_TRACK_SELECTED=Keng Spuer ausgewielt
+
+MSG_ERROR_TITLE=Feeler
+MSG_INFO_TITLE=Informatioun
+MSG_QUESTION_TITLE=Bestätegung
+MSG_QUIT_USDX=UltraStar wierklech verloossen?
+MSG_END_PARTY=Party wierklech verloossen?
+
+ERROR_NO_SONGS=Keng Lidder fonnt
+ERROR_NO_PLUGINS=Kee Plugin fonnt
+ERROR_NO_MODES_FOR_CURRENT_SETUP=Et gi keng Modi fir déi aktuell Spiller- an/oder Gruppenastellungen.
+ERROR_CAN_NOT_START_PARTY=E Fehler ass beim Starte vum Partyspill opgetrueden.
+ERROR_CORRUPT_SONG=Lidd gëtt net gelueden.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Lidd gëtt net gelueden: Datei gouf net fonnt.
+ERROR_CORRUPT_SONG_NO_NOTES=Lidd gëtt net gelueden: Et goufe keng Noute fonnt.
+ERROR_CORRUPT_SONG_NO_BREAKS=Lidd gëtt net gelueden: Et goufe keng Saazwiessel fonnt.
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Lidd gëtt net gelueden: Feeler beim Parze vun der Zeil %0:d
+ERROR_NO_EDITOR=Den Editor geet net op Linux/Mac
+ERROR_PLAYER_DEVICE_ASSIGNMENT=De Spiller %d huet ze vill Mikroe gewielt. Iwwerpréift d'Opzeechnungsoptiounen.
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=De Spiller %d huet kee Mikro gewielt. Iwwerpréift d'Opzeechnungsoptiounen.
+;UNUSED: SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Wéi oft gesonge matzielen
diff --git a/songmanagement/game/languages/Norwegian.ini b/songmanagement/game/languages/Norwegian.ini
new file mode 100644
index 00000000..16c3800f
--- /dev/null
+++ b/songmanagement/game/languages/Norwegian.ini
@@ -0,0 +1,444 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Laster... 
+
+SING_CHOOSE_MODE=velg modus 
+SING_SING=syng 
+SING_SING_DESC=hurtigspill: syng solo eller duett 
+
+SING_MULTI=party 
+SING_MULTI_DESC=syng i party-modus 
+
+SING_TOOLS=verktøy 
+
+SING_STATS=statistikk 
+SING_STATS_DESC=vis statistikk 
+
+SING_EDITOR=editor 
+SING_EDITOR_DESC=lag dine egne sanger 
+
+SING_GAME_OPTIONS=spillinnstillinger 
+SING_GAME_OPTIONS_DESC=endre spillinstillinger 
+
+SING_EXIT=avslutt 
+SING_EXIT_DESC=avslutt spillet 
+
+SING_OPTIONS=innstillinger 
+SING_OPTIONS_DESC=endre innstillinger 
+SING_OPTIONS_WHEREAMI=Innstillinger 
+
+SING_OPTIONS_GAME=spill 
+SING_OPTIONS_GRAPHICS=grafikk 
+SING_OPTIONS_SOUND=lyd 
+SING_OPTIONS_LYRICS=tekst 
+SING_OPTIONS_THEMES=utseende 
+SING_OPTIONS_RECORD=opptak 
+SING_OPTIONS_ADVANCED=avansert 
+SING_OPTIONS_EXIT=tilbake 
+
+SING_OPTIONS_GAME_WHEREAMI=Innstillinger Spill 
+SING_OPTIONS_GAME_DESC=hovedspillinnstillinger 
+SING_OPTIONS_GAME_PLAYERS=Spillere 
+SING_OPTIONS_GAME_DIFFICULTY=Vanskelighet 
+SING_OPTIONS_GAME_LANGUAGE=Språk 
+SING_OPTIONS_GAME_TABS=Mappeinndeling
+SING_OPTIONS_GAME_SORTING=Sortering 
+SING_OPTIONS_GAME_DEBUG=Feilsøking 
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Innstillinger Grafikk 
+SING_OPTIONS_GRAPHICS_DESC=Grafiske innstillinger 
+SING_OPTIONS_GRAPHICS_RESOLUTION=Oppløsning 
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Fullskjerm 
+SING_OPTIONS_GRAPHICS_DEPTH=Fargedybde 
+;TODO: SING_OPTIONS_GRAPHICS_VISUALIZER=Visualization
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloskop 
+SING_OPTIONS_GRAPHICS_LINEBONUS=Linjebonus 
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Filmstørrelse 
+
+SING_OPTIONS_SOUND_WHEREAMI=Innstillinger Lyd 
+SING_OPTIONS_SOUND_DESC=lydinnstillinger 
+;TODO: SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Microphone Playback
+;TODO: SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Background music
+SING_OPTIONS_SOUND_MIC_BOOST=Mikrofon-gain 
+SING_OPTIONS_SOUND_CLICK_ASSIST=Klikke-assistanse 
+SING_OPTIONS_SOUND_BEAT_CLICK=Beat-klikk 
+SING_OPTIONS_SOUND_THRESHOLD=Toleransegrense 
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Tospiller-modus 
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Preview-volum 
+SING_OPTIONS_SOUND_PREVIEWFADING=Preview-fading 
+
+SING_OPTIONS_LYRICS_WHEREAMI=Innstillinger Tekst 
+SING_OPTIONS_LYRICS_DESC=tekstinnstillinger 
+SING_OPTIONS_LYRICS_FONT=Fonter 
+SING_OPTIONS_LYRICS_EFFECT=Effekter 
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmisasjon 
+;TODO: SING_OPTIONS_LYRICS_NOTELINES=Staves
+
+SING_OPTIONS_THEMES_WHEREAMI=Innstillinger Utseende 
+SING_OPTIONS_THEMES_DESC=tema og skin-innstillinger 
+SING_OPTIONS_THEMES_THEME=Tema 
+SING_OPTIONS_THEMES_SKIN=Skin 
+SING_OPTIONS_THEMES_COLOR=Farge 
+
+SING_OPTIONS_RECORD_WHEREAMI=Innstillinger Opptak 
+SING_OPTIONS_RECORD_DESC=mikrofoninnstillinger 
+SING_OPTIONS_RECORD_CARD=Lydkort 
+SING_OPTIONS_RECORD_INPUT=Input 
+SING_OPTIONS_RECORD_CHANNEL=Kanal 
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Innstillinger Avansert 
+SING_OPTIONS_ADVANCED_DESC=avanserte innstillinger 
+SING_OPTIONS_ADVANCED_EFFECTSING=Sangeffekter 
+SING_OPTIONS_ADVANCED_SCREENFADE=Skjermfading 
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animasjonslasting 
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Sikkerhetsspørsmål 
+SING_OPTIONS_ADVANCED_LINEBONUS=Linjebonus 
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Etter sang: 
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto partymeny 
+
+;TODO: SING_EDIT=Editor
+;TODO: SING_EDIT_MENU_DESCRIPTION=create your own song
+
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Import text from midi file
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_EXIT=back
+;TODO: SING_EDIT_BUTTON_CONVERT=Import
+;TODO: SING_EDIT_BUTTON_EXIT=back
+
+;TODO: SING_EDIT_NAVIGATE=navigate
+;TODO: SING_EDIT_SELECT=select
+;TODO: SING_EDIT_EXIT=back
+
+SING_LEGEND_SELECT=velg 
+SING_LEGEND_NAVIGATE=naviger 
+SING_LEGEND_CONTINUE=fortsett 
+SING_LEGEND_ESC=tilbake 
+
+SING_PLAYER_DESC=velg spillernavn 
+SING_PLAYER_WHEREAMI=Spillernavn 
+SING_PLAYER_ENTER_NAME=velg navn 
+
+SING_DIFFICULTY_DESC=velg vanskelighetsgrad 
+SING_DIFFICULTY_WHEREAMI=Vanskelighet 
+SING_DIFFICULTY_CONTINUE=til sangvalg 
+SING_EASY=Lett 
+SING_MEDIUM=Moderat 
+SING_HARD=Vanskelig 
+
+SING_SONG_SELECTION_DESC=velg sang 
+SING_SONG_SELECTION_WHEREAMI=Sangvalg 
+SING_SONG_SELECTION_GOTO=gå til .. 
+SING_SONG_SELECTION=Sangvalg 
+SING_SONG_SELECTION_MENU=meny 
+SING_SONG_SELECTION_PLAYLIST=spilleliste 
+SING_SONGS_IN_CAT=Sanger 
+PLAYLIST_CATTEXT=Spilleliste: %s 
+
+SING_TIME=TID 
+SING_TOTAL=total 
+SING_MODE=syng solo 
+SING_NOTES=toner 
+SING_GOLDEN_NOTES=gyldne noter 
+SING_PHRASE_BONUS=linjebonus 
+
+SING_MENU=Hovedmeny 
+
+SONG_SCORE=sangscore 
+SONG_SCORE_WHEREAMI=Score 
+
+SING_SCORE_TONE_DEAF=Tonedøv 
+SING_SCORE_AMATEUR=Amatør 
+;TODO: SING_SCORE_WANNABE=Wannabe
+;TODO: SING_SCORE_HOPEFUL=Hopeful
+SING_SCORE_RISING_STAR=Stigende stjerne 
+SING_SCORE_LEAD_SINGER=Toppvokalist 
+SING_SCORE_SUPERSTAR=Superstjerne 
+SING_SCORE_ULTRASTAR=Ultrastjerne 
+
+SING_TOP_5_CHARTS=topp 5 spillere 
+SING_TOP_5_CHARTS_WHEREAMI=topp 5 
+SING_TOP_5_CHARTS_CONTINUE=til sangvalg 
+;TODO: SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=perfekt! 
+POPUP_AWESOME=fantastisk! 
+POPUP_GREAT=kjempebra! 
+POPUP_GOOD=bra! 
+POPUP_NOTBAD=brukbart! 
+POPUP_BAD=dårlig! 
+POPUP_POOR=elendig! 
+POPUP_AWFUL=grusomt! 
+
+IMPLODE_GLUE1=,  
+IMPLODE_GLUE2= og  
+
+SONG_MENU_NAME_MAIN=sangmeny 
+SONG_MENU_PLAY=Syng 
+SONG_MENU_CHANGEPLAYERS=Endre spillere 
+SONG_MENU_EDIT=Endre 
+SONG_MENU_MODI=Syng en modus 
+SONG_MENU_CANCEL=AVbryt 
+
+SONG_MENU_NAME_PLAYLIST=Sangmeny 
+SONG_MENU_PLAYLIST_ADD=Legg til sang 
+SONG_MENU_PLAYLIST_DEL=Ta bort sang 
+
+SONG_MENU_NAME_PLAYLIST_ADD=Legg til sang 
+SONG_MENU_PLAYLIST_ADD_NEW=til ny spilleliste 
+SONG_MENU_PLAYLIST_ADD_EXISTING=til eksisterende spilleliste 
+SONG_MENU_PLAYLIST_NOEXISTING=ingen spilleliste eksisterer 
+
+SONG_MENU_NAME_PLAYLIST_NEW=Ny spilleliste 
+SONG_MENU_PLAYLIST_NEW_CREATE=Opprett 
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Uten navn 
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Virkelig slette? 
+SONG_MENU_YES=Ja 
+SONG_MENU_NO=Nei 
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Åpne spilleliste 
+SONG_MENU_PLAYLIST_LOAD=åpne 
+SONG_MENU_PLAYLIST_DELCURRENT=slett nåværende spilleliste 
+
+SONG_MENU_NAME_PLAYLIST_DEL=Slett spilleliste? 
+
+SONG_MENU_NAME_PARTY_MAIN=Partymeny 
+SONG_MENU_JOKER=Joker 
+
+SONG_MENU_NAME_PARTY_JOKER=bruk joker 
+
+SONG_JUMPTO_DESC=søk etter sang 
+SONG_JUMPTO_TYPE_DESC=Søk etter: 
+SONG_JUMPTO_TYPE1=Alt 
+SONG_JUMPTO_TYPE2=Tittel 
+SONG_JUMPTO_TYPE3=Artist 
+SONG_JUMPTO_SONGSFOUND=%d Sang(er) funnet 
+SONG_JUMPTO_NOSONGSFOUND=Ingen funnet 
+SONG_JUMPTO_HELP=Skriv inn tekst å lete etter 
+SONG_JUMPTO_CATTEXT=Søk etter: %s 
+
+PARTY_MODE=Partymodus 
+PARTY_DIFFICULTY=Vanskelighetsgrad 
+PARTY_PLAYLIST=Spilleliste-modus 
+PARTY_PLAYLIST_ALL=Alle sanger 
+PARTY_PLAYLIST_CATEGORY=Mappe 
+PARTY_PLAYLIST_PLAYLIST=Spillelist 
+PARTY_TEAMS=Lag 
+PARTY_TEAMS_PLAYER1=Spiller Lag1 
+PARTY_TEAMS_PLAYER2=Spiller Lag2 
+PARTY_TEAMS_PLAYER3=Spiller Lag3 
+
+PARTY_LEGEND_CONTINUE=Fortsett 
+
+PARTY_OPTIONS_DESC=Innstillinger for party-spillet 
+PARTY_OPTIONS_WHEREAMI=Party-innstillinger 
+
+PARTY_PLAYER_DESC=skriv spiller- og lagnavn! 
+PARTY_PLAYER_WHEREAMI=Party-navn 
+PARTY_PLAYER_ENTER_NAME=skriv navn 
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+;TODO: PARTY_ROUNDS_LEGEND_CONTINUE=start party-game
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=neste spillere til mikrofonene 
+PARTY_ROUND_WHEREAMI=Party neste runde 
+PARTY_ROUND_LEGEND_CONTINUE=start runden 
+
+PARTY_SONG_WHEREAMI=Party sangvalg  
+PARTY_SONG_LEGEND_CONTINUE=syng  
+PARTY_SONG_MENU=partymeny 
+
+PARTY_SCORE_DESC=Siste rundes poengsum 
+PARTY_SCORE_WHEREAMI=Partypoeng 
+
+PARTY_WIN_DESC=vinner av partyspillet 
+PARTY_WIN_WHEREAMI=Party-vinner 
+PARTY_WIN_LEGEND_CONTINUE=tilbake til hovedmenyen 
+
+PARTY_ROUND=Runde 
+PARTY_ROUND_WINNER=Vinner 
+PARTY_NOTPLAYEDYET=Ikke spilt ennå 
+PARTY_NOBODY=ingen 
+NEXT_ROUND=Neste runde: 
+
+PARTY_DISMISSED=Avbrutt! 
+PARTY_SCORE_WINS=%s  
+PARTY_SCORE_WINS2=Vinner! 
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Hold linja 
+MODE_HOLDTHELINE_DESC=Ikke syng dårligere enn hva markøren på statuslinja viser. 
+
+MODE_5000POINTS_NAME=Først til 5000 
+MODE_5000POINTS_DESC=Førstemann til 5000 poeng vinner. 
+
+MODE_DUEL_NAME=Duell 
+MODE_DUEL_DESC=Syng en duell - først til 10000. 
+
+;TODO: MODE_TEAMDUEL_NAME=Team Duell
+;TODO: MODE_TEAMDUEL_DESC=Pass The Mic!
+
+MODE_BLIND_NAME=Blindemodus 
+MODE_BLIND_DESC=Duell der notene ikke vises 
+
+STAT_MAIN=Statistikk 
+STAT_MAIN_DESC=Hoved 
+STAT_MAIN_WHEREAMI=Statistikk 
+
+STAT_OVERVIEW_INTRO=%0:s Statistikk. \n Siste avslutning ved %2:.2d.%1:.2d.%3:d 
+STAT_OVERVIEW_SONG=%0:d Sanger(%3:d med video), hvorav %1:d allerede har vært sunget og %2:d ennå ikke har vært sunget.\n Den mest populære sangen er %5:s av %4:s. 
+STAT_OVERVIEW_PLAYER=Siden den siste avlutningen var det %0:d ulike spillere.\n Den beste spilleren er %1:s med en gjennomsnitts-score på %2:d poeng.\n %3:s fikk høyeste score med %4:d poeng. 
+
+;TODO: STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statistikk 
+STAT_DETAIL_WHEREAMI=Detaljert statistikk 
+
+STAT_NEXT=Neste side 
+STAT_PREV=Forrige side 
+STAT_REVERSE=Bytt rekkefølge 
+STAT_PAGE=Side %0:d av %1:d Sider\n (%2:d av %3:d ) 
+
+STAT_DESC_SCORES=Toppscore 
+STAT_DESC_SCORES_REVERSED=Bunnscore 
+STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] \n (%3:s - %4:s) 
+
+STAT_DESC_SINGERS=Beste sangere 
+STAT_DESC_SINGERS_REVERSED=Dårligste sangere 
+STAT_FORMAT_SINGERS=%0:s \n Gjennomsnitts-score: %1:d 
+
+STAT_DESC_SONGS=Mest populære sang 
+STAT_DESC_SONGS_REVERSED=Minst populære sang 
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx sunget 
+
+STAT_DESC_BANDS=Mest populære artist 
+STAT_DESC_BANDS_REVERSED=Minst populære artist 
+STAT_FORMAT_BANDS=%0:s \n %1:dx Sunget 
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Feil 
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Spørsmål 
+MSG_QUIT_USDX=Vil du virkelig avslutte UltraStar? 
+MSG_END_PARTY=Vil du virkelig forlate party-modusen? 
+
+ERROR_NO_SONGS=Ingen sanger lastet 
+ERROR_NO_PLUGINS=Ingen plug-ins lastet 
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Sangen kunne ikke lastes
+;TODO: ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Song could not be loaded: File not found
+;TODO: ERROR_CORRUPT_SONG_NO_NOTES=Song could not be loaded: Can''t find any notes
+;TODO: ERROR_CORRUPT_SONG_NO_BREAKS=Song could not be loaded: Can''t find any linebreaks
+;TODO: ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Song could not be loaded: Error parsing line %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG= 
+;UNUSED: SING_SCORE_HIT_ARTIST=Hitartist 
+;UNUSED: PARTY_ROUNDS=Runder 
diff --git a/songmanagement/game/languages/Polish.ini b/songmanagement/game/languages/Polish.ini
new file mode 100644
index 00000000..2950e108
--- /dev/null
+++ b/songmanagement/game/languages/Polish.ini
@@ -0,0 +1,441 @@
+[Text]
+OPTION_VALUE_CATALAN=Kataloński
+OPTION_VALUE_CROATIAN=Chorwacki
+OPTION_VALUE_CZECH=Czeski
+OPTION_VALUE_DANISH=Duński
+OPTION_VALUE_DUTCH=Holenderski
+OPTION_VALUE_ENGLISH=Angielski
+OPTION_VALUE_EUSKARA=Baskijski
+OPTION_VALUE_FINNISH=Fiński
+OPTION_VALUE_FRENCH=Francuski
+OPTION_VALUE_GERMAN=Niemiecki
+OPTION_VALUE_GREEK=Grecki
+OPTION_VALUE_HUNGARIAN=Węgierski
+OPTION_VALUE_ICELANDIC=Islandzki
+OPTION_VALUE_ITALIAN=Włoski
+OPTION_VALUE_JAPANESE=Japoński
+OPTION_VALUE_LUXEMBOURGISH=Luksemburski
+OPTION_VALUE_NORWEGIAN=Norweski
+OPTION_VALUE_POLISH=Polski
+OPTION_VALUE_PORTUGUESE=Portugalski
+OPTION_VALUE_RUSSIAN=Rosyjski
+OPTION_VALUE_SERBIAN=Serbski
+OPTION_VALUE_SLOVAK=Słowacki
+OPTION_VALUE_SLOVENIAN=Słoweński
+OPTION_VALUE_SPANISH=Hiszpański
+OPTION_VALUE_SWEDISH=Szwedzki
+
+OPTION_VALUE_EASY=Łatwo
+OPTION_VALUE_MEDIUM=Średnio
+OPTION_VALUE_HARD=Trudno
+
+OPTION_VALUE_ON=Włączone
+OPTION_VALUE_OFF=Wyłączone
+
+OPTION_VALUE_EDITION=Edycja
+OPTION_VALUE_GENRE=Gatunek
+OPTION_VALUE_LANGUAGE=Język
+OPTION_VALUE_FOLDER=Folder
+OPTION_VALUE_TITLE=Tytuł
+OPTION_VALUE_ARTIST=Artysta
+OPTION_VALUE_TITLE2=Tytuł2
+OPTION_VALUE_ARTIST2=Artysta2
+
+OPTION_VALUE_WHENNOVIDEO=Kiedy bez Video
+
+OPTION_VALUE_SMALL=Mały
+OPTION_VALUE_BIG=Duży
+
+OPTION_VALUE_HALF=Połowa
+OPTION_VALUE_FULL_VID=Pełny (Video)
+OPTION_VALUE_FULL_VID_BG=Pełny (Tło & Video)
+
+OPTION_VALUE_AUTO=Auto
+OPTION_VALUE_SEC=Sekunda
+OPTION_VALUE_SECS=Sekundy
+
+OPTION_VALUE_PLAIN=Zwykły
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Prosty
+OPTION_VALUE_ZOOM=Zoom
+OPTION_VALUE_SLIDE=Suwak
+OPTION_VALUE_BALL=Kula
+OPTION_VALUE_SHIFT=Shift
+
+OPTION_VALUE_EURO=Euro
+OPTION_VALUE_JAPAN=Japan
+OPTION_VALUE_AMERICAN=American
+
+OPTION_VALUE_BLUE=Niebieski
+OPTION_VALUE_GREEN=Zielony
+OPTION_VALUE_PINK=Różowy
+OPTION_VALUE_RED=Czerwony
+OPTION_VALUE_VIOLET=Fioletowy
+OPTION_VALUE_ORANGE=Pomarańczowy
+OPTION_VALUE_YELLOW=Żółty
+OPTION_VALUE_BROWN=Brązowy
+OPTION_VALUE_BLACK=Czarny
+
+OPTION_VALUE_SING=Śpiew
+OPTION_VALUE_SELECT_PLAYERS=Wybierz graczy
+OPTION_VALUE_OPEN_MENU=Otwórz Menu
+
+OPTION_VALUE_HARDWARE_CURSOR=Sprzętowy Kursor
+OPTION_VALUE_SOFTWARE_CURSOR=Programowy Kursor
+
+SING_LOADING=Wczytywanie...
+
+SING_CHOOSE_MODE=Wybierz tryb
+SING_SING=Śpiewaj
+SING_SING_DESC=Szybka gra: solo lub duet
+
+SING_MULTI=Impreza
+SING_MULTI_DESC=Śpiewaj w trybie imprezy
+
+SING_TOOLS=narzędzia
+
+SING_STATS=statystyki
+SING_STATS_DESC=zobacz statystyki
+
+SING_EDITOR=edytor
+SING_EDITOR_DESC=stwórz własną piosenkę
+
+SING_GAME_OPTIONS=opcje gry
+SING_GAME_OPTIONS_DESC=zmiana ustawień gry
+
+SING_EXIT=wyjście
+SING_EXIT_DESC=wyjście z gry
+
+SING_OPTIONS=opcje
+SING_OPTIONS_DESC=zmień ustawienia
+SING_OPTIONS_WHEREAMI=Opcje
+
+SING_OPTIONS_GAME=gra
+SING_OPTIONS_GRAPHICS=grafika
+SING_OPTIONS_SOUND=dźwięk
+SING_OPTIONS_LYRICS=tekst
+SING_OPTIONS_THEMES=tematy
+SING_OPTIONS_RECORD=nagrywanie
+SING_OPTIONS_ADVANCED=zaawansow.
+SING_OPTIONS_EXIT=wstecz
+
+SING_OPTIONS_GAME_WHEREAMI=Opcje gry
+SING_OPTIONS_GAME_DESC=ogólne ustawienia gry
+SING_OPTIONS_GAME_PLAYERS=Gracze
+SING_OPTIONS_GAME_DIFFICULTY=Trudność
+SING_OPTIONS_GAME_LANGUAGE=Język
+SING_OPTIONS_GAME_TABS=Zakładki
+SING_OPTIONS_GAME_SORTING=Sortowanie
+SING_OPTIONS_GAME_DEBUG=Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Opcje Grafiki
+SING_OPTIONS_GRAPHICS_DESC=ustawienia grafiki
+SING_OPTIONS_GRAPHICS_RESOLUTION=Rozdzielczość
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Pełny ekran
+SING_OPTIONS_GRAPHICS_DEPTH=Głębia
+SING_OPTIONS_GRAPHICS_VISUALIZER=Wizualizacja
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscyloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Linia Bonusa
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Rozmiar filmu
+
+SING_OPTIONS_SOUND_WHEREAMI=Opcje Dźwięku
+SING_OPTIONS_SOUND_DESC=ustawienia dźwięku
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Podkład mikrofonu
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Podkład muzyczny
+SING_OPTIONS_SOUND_MIC_BOOST=Podbicie mikrofonu
+SING_OPTIONS_SOUND_CLICK_ASSIST=Pomoc kliknięciami
+SING_OPTIONS_SOUND_BEAT_CLICK=Kliknięcia w rytm
+SING_OPTIONS_SOUND_THRESHOLD=Próg
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Tryb dwóch graczy
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Głośność w podglądzie
+SING_OPTIONS_SOUND_PREVIEWFADING=Zanikanie w podglądzie
+
+SING_OPTIONS_LYRICS_WHEREAMI=Opcje tekstu
+SING_OPTIONS_LYRICS_DESC=ustawienie tekstu
+SING_OPTIONS_LYRICS_FONT=Czcionka
+SING_OPTIONS_LYRICS_EFFECT=Efekt
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmizacja
+SING_OPTIONS_LYRICS_NOTELINES=Drązki
+
+SING_OPTIONS_THEMES_WHEREAMI=Opcje Tematów
+SING_OPTIONS_THEMES_DESC=ustawienia tematów i skórek
+SING_OPTIONS_THEMES_THEME=Temat
+SING_OPTIONS_THEMES_SKIN=Skórka
+SING_OPTIONS_THEMES_COLOR=Kolor
+
+SING_OPTIONS_RECORD_WHEREAMI=Opcje nagrywania
+SING_OPTIONS_RECORD_DESC=ustawienia mikrofonu
+SING_OPTIONS_RECORD_CARD=karta muzyczna
+SING_OPTIONS_RECORD_INPUT=wejście
+SING_OPTIONS_RECORD_CHANNEL=kanał
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Opcje zaawansowane
+SING_OPTIONS_ADVANCED_DESC=zaawansowane ustawienia
+SING_OPTIONS_ADVANCED_EFFECTSING=Efekty śpiewania
+SING_OPTIONS_ADVANCED_SCREENFADE=Przenikanie ekranów
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animacja wczytywania
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Pytania pomocnicze
+SING_OPTIONS_ADVANCED_LINEBONUS=Linia bonusa
+SING_OPTIONS_ADVANCED_ONSONGCLICK=after Song Select
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto PartyMenu
+
+SING_EDIT=Edytor
+SING_EDIT_MENU_DESCRIPTION=stwórz własną piosenkę
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Zaimportuj tekst z pliku midi
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=wstecz
+SING_EDIT_BUTTON_CONVERT=Import
+SING_EDIT_BUTTON_EXIT=wstecz
+
+SING_EDIT_NAVIGATE=nawiguj
+SING_EDIT_SELECT=wybierz
+SING_EDIT_EXIT=wstecz
+
+SING_LEGEND_SELECT=wybierz
+SING_LEGEND_NAVIGATE=nawiguj
+SING_LEGEND_CONTINUE=kontynuacja
+SING_LEGEND_ESC=wstecz
+
+SING_PLAYER_DESC=Wpisz nazwę gracza/y
+SING_PLAYER_WHEREAMI=Nazwa graczy
+SING_PLAYER_ENTER_NAME=Wpisz nazwę
+
+SING_DIFFICULTY_DESC=wybierz trudność
+SING_DIFFICULTY_WHEREAMI=Trudność
+SING_DIFFICULTY_CONTINUE=do wybory piosenki
+SING_EASY=Łatwo
+SING_MEDIUM=Średnio
+SING_HARD=Trudno
+
+SING_SONG_SELECTION_DESC=Wybierz Piosenkę
+SING_SONG_SELECTION_WHEREAMI=Wybór piosenki
+SING_SONG_SELECTION_GOTO=idź do ..
+SING_SONG_SELECTION=wybór piosenki
+SING_SONG_SELECTION_MENU=menu
+SING_SONG_SELECTION_PLAYLIST=playlista
+SING_SONGS_IN_CAT=Piosenki
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=Czas
+SING_TOTAL=cały
+SING_MODE=śpiewaj solo
+SING_NOTES=nuty
+SING_GOLDEN_NOTES=złote nuty
+SING_PHRASE_BONUS=linia bonus
+
+SING_MENU=Główne Menu
+
+SONG_SCORE=Ocena śpiewania
+SONG_SCORE_WHEREAMI=Ocena
+
+SING_SCORE_TONE_DEAF=Drewniane ucho
+SING_SCORE_AMATEUR=Amator
+SING_SCORE_WANNABE=Początkujący artysta
+SING_SCORE_HOPEFUL=Obiecujący artysta
+SING_SCORE_RISING_STAR=Wschodząca gwiazda
+SING_SCORE_LEAD_SINGER=Wielki Artysta
+SING_SCORE_SUPERSTAR=Super gwiazda
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=Najlepszych 5 graczy
+SING_TOP_5_CHARTS_WHEREAMI=najlepszych 5
+SING_TOP_5_CHARTS_CONTINUE=Do wyboru piosenek
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=zmień trudność
+
+POPUP_PERFECT=idealnie!
+POPUP_AWESOME=wspaniale!
+POPUP_GREAT=świetnie!
+POPUP_GOOD=dobrze!
+POPUP_NOTBAD=nieźle!
+POPUP_BAD=źle!
+POPUP_POOR=słabo!
+POPUP_AWFUL=okropnie!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= oraz
+
+SONG_MENU_NAME_MAIN=menu piosenki
+SONG_MENU_PLAY=Śpiewaj
+SONG_MENU_CHANGEPLAYERS=Zmień graczy
+SONG_MENU_EDIT=Edytuj
+SONG_MENU_MODI=Śpiewaj Modi
+SONG_MENU_CANCEL=Anuluj
+
+SONG_MENU_NAME_PLAYLIST=Menu Piosenki
+SONG_MENU_PLAYLIST_ADD=Dodaj piosenkę
+SONG_MENU_PLAYLIST_DEL=Usuń piosenkę
+
+SONG_MENU_NAME_PLAYLIST_ADD=Dodaj piosenkę
+SONG_MENU_PLAYLIST_ADD_NEW=do nowej playlisty
+SONG_MENU_PLAYLIST_ADD_EXISTING=do istniejącej playlisty
+SONG_MENU_PLAYLIST_NOEXISTING=Brak playlist
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nowa Playlista
+SONG_MENU_PLAYLIST_NEW_CREATE=Stwórz
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Bez nazwy
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Usunąć?
+SONG_MENU_YES=Tak
+SONG_MENU_NO=Nie
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Otwórz Playlistę
+SONG_MENU_PLAYLIST_LOAD=otwórz
+SONG_MENU_PLAYLIST_DELCURRENT=usuń tę playlistę
+
+SONG_MENU_NAME_PLAYLIST_DEL=Usunąć playlistę?
+
+SONG_MENU_NAME_PARTY_MAIN=Menu Imprezy
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=weź jokera
+
+SONG_JUMPTO_DESC=szukaj
+SONG_JUMPTO_TYPE_DESC=Szukaj:
+SONG_JUMPTO_TYPE1=Wszędzie
+SONG_JUMPTO_TYPE2=Tytuł
+SONG_JUMPTO_TYPE3=Wykonawca
+SONG_JUMPTO_SONGSFOUND=Znaleziono %d utworów
+SONG_JUMPTO_NOSONGSFOUND=Nic nie znaleziono
+SONG_JUMPTO_HELP=Wpisz tekst do wyszukania
+SONG_JUMPTO_CATTEXT=Szukaj: %s
+
+PARTY_MODE=tryb imprezy
+PARTY_DIFFICULTY=Poziom
+PARTY_PLAYLIST=Tryb playlisty
+PARTY_PLAYLIST_ALL=Wszystkie piosenki
+PARTY_PLAYLIST_CATEGORY=Folder
+PARTY_PLAYLIST_PLAYLIST=Playlista
+PARTY_TEAMS=Drużyny
+PARTY_TEAMS_PLAYER1=Drużyna 1
+PARTY_TEAMS_PLAYER2=Drużyna 2
+PARTY_TEAMS_PLAYER3=Drużyna 3
+
+PARTY_LEGEND_CONTINUE=dalej
+
+PARTY_OPTIONS_DESC=ustawienia trybu imprezy
+PARTY_OPTIONS_WHEREAMI=Impreza - Ustawienia
+
+PARTY_PLAYER_DESC=wpisz nazwy graczy i drużyn
+PARTY_PLAYER_WHEREAMI=Nazwy drużyn
+PARTY_PLAYER_ENTER_NAME=wpisz nazwy
+
+
+PARTY_ROUNDS_DESC= wybierz tryb w którym chcesz grać
+PARTY_ROUNDS_WHEREAMI=Rundy imprezy
+PARTY_ROUNDS_LEGEND_CONTINUE=start imprezy
+PARTY_ROUNDCOUNT=liczba rund
+PARTY_SELECTMODE1=tryb rundy 1
+PARTY_SELECTMODE2=tryb rundy 2
+PARTY_SELECTMODE3=tryb rundy 3
+PARTY_SELECTMODE4=tryb rundy 4
+PARTY_SELECTMODE5=tryb rundy 5
+PARTY_SELECTMODE6=tryb rundy 6
+PARTY_SELECTMODE7=tryb rundy 7
+
+PARTY_ROUND_DESC=następni gracze do mikrofonów
+PARTY_ROUND_WHEREAMI=Następna Runda
+PARTY_ROUND_LEGEND_CONTINUE=rozpocznij rundę
+
+PARTY_SONG_WHEREAMI=Wybór piosenki 	 
+PARTY_SONG_LEGEND_CONTINUE=śpiewaj 	 
+PARTY_SONG_MENU=menu
+
+PARTY_SCORE_DESC=wynik ostatniej rundy
+PARTY_SCORE_WHEREAMI=Punkty
+
+PARTY_WIN_DESC=zwycięzca gry
+PARTY_WIN_WHEREAMI=Zwycięzca imprezy
+PARTY_WIN_LEGEND_CONTINUE=do menu głównego
+
+PARTY_ROUND=Runda
+PARTY_ROUND_WINNER=Zwycięzca
+PARTY_NOTPLAYEDYET=jeszcze nie grał
+PARTY_NOBODY=nikt
+NEXT_ROUND=Następna runda:
+
+PARTY_DISMISSED=Odpada!
+PARTY_SCORE_WINS=%s 
+PARTY_SCORE_WINS2=wygrywa!
+
+MODE_RANDOM_NAME=Tryb losowania
+MODE_RANDOM_DESC=Jeden tryb będzie wybrany losowo
+
+MODE_HOLDTHELINE_NAME=Trzymaj Linię
+MODE_HOLDTHELINE_DESC=Śpiewaj lepiej jak linia na pasku.
+
+MODE_5000POINTS_NAME=Do 5000
+MODE_5000POINTS_DESC=Wygrywa ten, kto pierwszy uzyska 5000 punktów.
+
+MODE_DUEL_NAME=Pojedynek
+MODE_DUEL_DESC=Śpiewacie w pojedynku do 10000 punktów.
+
+MODE_TEAMDUEL_NAME=Pojedynek drużyn
+MODE_TEAMDUEL_DESC=Przekaż mikrofon!
+
+MODE_BLIND_NAME=Tryb ślepca
+MODE_BLIND_DESC=Pojedynek bez pokazywania nut.
+
+STAT_MAIN=Statystyki
+STAT_MAIN_DESC=Ogólne
+STAT_MAIN_WHEREAMI=Statystyki
+
+STAT_OVERVIEW_INTRO=%0:s Statystyki.  \n Ostatni Reset o %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Piosenki(%3:d z Video), z czego %1:d było granych i %2:d nie było jeszcze śpiewanych.\n Najbardziej popularna piosenka to %5:s z %4:s.
+STAT_OVERVIEW_PLAYER=Od ostatniego resetu było %0:d różnych graczy.\n Najlepszy gracz to %1:s ze średnią %2:d Punktów.\n %3:s posiada najwyższy wynik %4:d Punktów.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statystyki
+STAT_DETAIL_WHEREAMI=Statystyki szczegółowe
+
+STAT_NEXT=Następna strona
+STAT_PREV=Poprzednia strona
+STAT_REVERSE=Odwróć kolejność
+STAT_PAGE=strona %0:d z %1:d stron\n (%2:d z %3:d wpisów)
+
+STAT_DESC_SCORES=Najwyższe wyniki
+STAT_DESC_SCORES_REVERSED=Najniższe wyniki
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Najlepsi
+STAT_DESC_SINGERS_REVERSED=Najgorsi
+STAT_FORMAT_SINGERS=%0:s \n Średni wynik: %1:d
+
+STAT_DESC_SONGS=Najpopularniejsze \n piosenki
+STAT_DESC_SONGS_REVERSED=Najmniej popularne piosenki
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx śpiewane
+
+STAT_DESC_BANDS=Najpopularniejsi \n wykonawcy
+STAT_DESC_BANDS_REVERSED=Najmniej popularni wykonawcy
+STAT_FORMAT_BANDS=%0:s \n %1:dx śpiewani
+
+SCREENSHOT_SAVED=Zrzut ekranu zapisany
+SCREENSHOT_FAILED=Nie mogę zapisać zrzutu ekranu
+
+INFO_FILE_SAVED=Plik zapisany
+ERROR_SAVE_FILE_FAILED=Nie mogę zapisać pliku
+ERROR_FILE_NOT_FOUND=Plik nieznaleziony
+
+ENCODING_ERROR_ASK_FOR_UTF8=Nie mogę zapisać zmian w obecnym kodowaniu. Skonwertuj na UTF-8?
+EDITOR_ERROR_NO_TRACK_SELECTED=Nie zaznaczona ścieżka
+
+MSG_ERROR_TITLE=Błąd
+MSG_INFO_TITLE=Informacja
+MSG_QUESTION_TITLE=Pytanie
+MSG_QUIT_USDX=Czy na prawdę chcesz opuścić UltraStar?
+MSG_END_PARTY=Na pewno chcesz zakończyć tryb imprezy?
+
+ERROR_NO_SONGS=Brak piosenek
+ERROR_NO_PLUGINS=Brak wtyczek
+ERROR_NO_MODES_FOR_CURRENT_SETUP=Brak dostępnych trybów dla obecnie ustawionych graczy/zespołów
+ERROR_CAN_NOT_START_PARTY= wystąpił błąd podczas startu trybu impreza
+ERROR_CORRUPT_SONG=Piosenka nie może być załadowana.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Piosenka nie może być załadowana: Brak pliku
+ERROR_CORRUPT_SONG_NO_NOTES=Piosenka nie może być załadowana: nie mogę znaleść nut.
+ERROR_CORRUPT_SONG_NO_BREAKS=Piosenka nie może być załadowana: nie mogę znaleść linii dzielących
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Piosenka nie może być załadowana: Błąd rozpoznawania linii %0:d
+ERROR_NO_EDITOR=Dodatek nie jest dostępny dla Linux/Mac
+ERROR_PLAYER_DEVICE_ASSIGNMENT=Gracz %d został przypisany do wielu mikrofonów. Sprawdź ustawienia w obcjach gry.
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Gracz %d nie ma przypisanego mikrofonu. Sprawdź ustawienia nagrywania.
diff --git a/songmanagement/game/languages/Portuguese.ini b/songmanagement/game/languages/Portuguese.ini
new file mode 100644
index 00000000..cfadd5d4
--- /dev/null
+++ b/songmanagement/game/languages/Portuguese.ini
@@ -0,0 +1,441 @@
+[Text]
+OPTION_VALUE_CATALAN=Catalão
+OPTION_VALUE_CROATIAN=Croata
+OPTION_VALUE_CZECH=Tcheco
+OPTION_VALUE_DANISH=Dinamarquês
+OPTION_VALUE_DUTCH=Holandês
+OPTION_VALUE_ENGLISH=Inglês
+OPTION_VALUE_EUSKARA=Euskara
+OPTION_VALUE_FINNISH=Finlandês
+OPTION_VALUE_FRENCH=Francês
+OPTION_VALUE_GERMAN=Alemão
+OPTION_VALUE_GREEK=Grego
+OPTION_VALUE_HUNGARIAN=Hungaro
+OPTION_VALUE_ICELANDIC=Islandês
+OPTION_VALUE_ITALIAN=Italiano
+OPTION_VALUE_JAPANESE=Japonês
+OPTION_VALUE_LUXEMBOURGISH=Luxemburguês
+OPTION_VALUE_NORWEGIAN=Norueguês
+OPTION_VALUE_POLISH=Polaco
+OPTION_VALUE_PORTUGUESE=Português
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+OPTION_VALUE_SERBIAN=Sérvio
+OPTION_VALUE_SLOVAK=Eslovaco
+OPTION_VALUE_SLOVENIAN=Esloveno
+OPTION_VALUE_SPANISH=Espanhol
+OPTION_VALUE_SWEDISH=Sueco
+
+OPTION_VALUE_EASY=Fácil
+OPTION_VALUE_MEDIUM=Médio
+OPTION_VALUE_HARD=Difícil
+
+OPTION_VALUE_ON=Ligado
+OPTION_VALUE_OFF=Desligado
+
+OPTION_VALUE_EDITION=Edição
+OPTION_VALUE_GENRE=Gênero
+OPTION_VALUE_LANGUAGE=Idioma
+OPTION_VALUE_FOLDER=Diretório
+OPTION_VALUE_TITLE=Título
+OPTION_VALUE_ARTIST=Artista
+OPTION_VALUE_TITLE2=Título 2
+OPTION_VALUE_ARTIST2=Artista 2
+
+OPTION_VALUE_WHENNOVIDEO=Não existi Vídeo
+
+OPTION_VALUE_SMALL=Pequeno
+OPTION_VALUE_BIG=Grande
+
+OPTION_VALUE_HALF=Parcial
+OPTION_VALUE_FULL_VID=Completo (Vídeo)
+OPTION_VALUE_FULL_VID_BG=Completo (Fundo & Vídeo)
+
+OPTION_VALUE_AUTO=Auto
+OPTION_VALUE_SEC=Segundo
+OPTION_VALUE_SECS=Segundos
+
+OPTION_VALUE_PLAIN=Plano
+OPTION_VALUE_OLINE1=Negrito 1
+OPTION_VALUE_OLINE2=Negrito 2
+
+OPTION_VALUE_SIMPLE=Simples
+OPTION_VALUE_ZOOM=Zoom
+OPTION_VALUE_SLIDE=Slide
+OPTION_VALUE_BALL=Bola
+OPTION_VALUE_SHIFT=Salto
+
+OPTION_VALUE_EURO=Europeu
+OPTION_VALUE_JAPAN=Japonês
+OPTION_VALUE_AMERICAN=Americano
+
+OPTION_VALUE_BLUE=Azul
+OPTION_VALUE_GREEN=Verde
+OPTION_VALUE_PINK=Rosa
+OPTION_VALUE_RED=Vermelho
+OPTION_VALUE_VIOLET=Violeta
+OPTION_VALUE_ORANGE=Laranja
+OPTION_VALUE_YELLOW=Amarelo
+OPTION_VALUE_BROWN=Marron
+OPTION_VALUE_BLACK=Preto
+
+OPTION_VALUE_SING=Cantar
+OPTION_VALUE_SELECT_PLAYERS=Escolher Jogadores
+OPTION_VALUE_OPEN_MENU=Abrir Menu
+
+OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=A Ler...
+
+SING_CHOOSE_MODE=Escolha o Modo
+SING_SING=Cantar
+SING_SING_DESC=Jogo Rápido: cantar Sozinho ou em Dupla
+
+SING_MULTI=Festa
+SING_MULTI_DESC=Cantar em Modo Festa
+
+SING_TOOLS=Ferramentas
+
+SING_STATS=Estatísticas
+SING_STATS_DESC=Ver Estatísticas
+
+SING_EDITOR=Editor
+SING_EDITOR_DESC=Criar canção
+
+SING_GAME_OPTIONS=Opções de Jogo
+SING_GAME_OPTIONS_DESC=Alterar configurações de Jogo
+
+SING_EXIT=Sair
+SING_EXIT_DESC=Sair do Jogo
+
+SING_OPTIONS=Opções
+SING_OPTIONS_DESC=Alterar configurações
+SING_OPTIONS_WHEREAMI=Opções
+
+SING_OPTIONS_GAME=Jogo
+SING_OPTIONS_GRAPHICS=Gráficos
+SING_OPTIONS_SOUND=Som
+SING_OPTIONS_LYRICS=Letras
+SING_OPTIONS_THEMES=Temas
+SING_OPTIONS_RECORD=Gravação
+SING_OPTIONS_ADVANCED=Avançado
+SING_OPTIONS_EXIT=Voltar
+
+SING_OPTIONS_GAME_WHEREAMI=Opções de Jogo
+SING_OPTIONS_GAME_DESC=Configurações Gerais do Jogo
+SING_OPTIONS_GAME_PLAYERS=Jogadores
+SING_OPTIONS_GAME_DIFFICULTY=Dificuldade
+SING_OPTIONS_GAME_LANGUAGE=Idioma
+SING_OPTIONS_GAME_TABS=Subpastas
+SING_OPTIONS_GAME_SORTING=Ordenação
+SING_OPTIONS_GAME_DEBUG=Modo Debug
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Opções de Gráficos
+SING_OPTIONS_GRAPHICS_DESC=Configurações dos Gráficos
+SING_OPTIONS_GRAPHICS_RESOLUTION=Resolução
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Ecrã Total
+SING_OPTIONS_GRAPHICS_DEPTH=Profundidade
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualizador
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Osciloscópio
+SING_OPTIONS_GRAPHICS_LINEBONUS=Linha Bonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Tamanho do Vídeo
+
+SING_OPTIONS_SOUND_WHEREAMI=Opções de Som
+SING_OPTIONS_SOUND_DESC=Configuração do Som
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Playback Microfone
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Música de Fundo
+SING_OPTIONS_SOUND_MIC_BOOST=Microfone Boost
+SING_OPTIONS_SOUND_CLICK_ASSIST=Click de Ajuda
+SING_OPTIONS_SOUND_BEAT_CLICK=Click de Batida
+SING_OPTIONS_SOUND_THRESHOLD=Threshold
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Modo de dois jogadores
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Preview Volume
+SING_OPTIONS_SOUND_PREVIEWFADING=Preview Fading
+
+SING_OPTIONS_LYRICS_WHEREAMI=Opções de Letras
+SING_OPTIONS_LYRICS_DESC=Configuração de Letras
+SING_OPTIONS_LYRICS_FONT=Fonte
+SING_OPTIONS_LYRICS_EFFECT=Efeitos
+SING_OPTIONS_LYRICS_SOLMIZATION=Solfejo
+SING_OPTIONS_LYRICS_NOTELINES=Pauta
+
+SING_OPTIONS_THEMES_WHEREAMI=Opção de Tema
+SING_OPTIONS_THEMES_DESC=Configuração de tema e skin
+SING_OPTIONS_THEMES_THEME=Tema
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Cor
+
+SING_OPTIONS_RECORD_WHEREAMI=Opções de Gravação
+SING_OPTIONS_RECORD_DESC=Configurações do Microfone
+SING_OPTIONS_RECORD_CARD=Placa de Som
+SING_OPTIONS_RECORD_INPUT=Entrada
+SING_OPTIONS_RECORD_CHANNEL=Canal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Opções Avançadas
+SING_OPTIONS_ADVANCED_DESC=Outras Opções
+SING_OPTIONS_ADVANCED_EFFECTSING=Efeitos
+SING_OPTIONS_ADVANCED_SCREENFADE=Fade do Ecrã
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animação
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Segurança
+SING_OPTIONS_ADVANCED_LINEBONUS=Linha de Bônus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Escolha da Canção
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Menu de Festa
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=Cria a tua própria canção
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importar texto de um arquivo MIDI
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Voltar
+SING_EDIT_BUTTON_CONVERT=Importar
+SING_EDIT_BUTTON_EXIT=Voltar
+
+SING_EDIT_NAVIGATE=Navegar
+SING_EDIT_SELECT=Seleccionar
+SING_EDIT_EXIT=Voltar
+
+SING_LEGEND_SELECT=Seleccionar
+SING_LEGEND_NAVIGATE=Navegar
+SING_LEGEND_CONTINUE=Continuar
+SING_LEGEND_ESC=Voltar
+
+SING_PLAYER_DESC=Introduza o(s) nome(s) do(s) jogador(es)
+SING_PLAYER_WHEREAMI=Nome dos Jogadores
+SING_PLAYER_ENTER_NAME=Introduzir Nome
+
+SING_DIFFICULTY_DESC=Nível de Dificuldade
+SING_DIFFICULTY_WHEREAMI=Dificuldade
+SING_DIFFICULTY_CONTINUE=para a escolha da canção
+SING_EASY=Fácil
+SING_MEDIUM=Médio
+SING_HARD=Difícil
+
+SING_SONG_SELECTION_DESC=Escolha a canção
+SING_SONG_SELECTION_WHEREAMI=Seleção da Canção
+SING_SONG_SELECTION_GOTO=Ir para ..
+SING_SONG_SELECTION=Seleção da Canção
+SING_SONG_SELECTION_MENU=Menu
+SING_SONG_SELECTION_PLAYLIST=Playlist
+SING_SONGS_IN_CAT=Canções
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=TEMPO
+SING_TOTAL=Total
+SING_MODE=Cantar Solo
+SING_NOTES=Notas
+SING_GOLDEN_NOTES=Notas de Ouro
+SING_PHRASE_BONUS=Linha de Bônus
+
+SING_MENU=Menu Principal
+
+SONG_SCORE=Pontuação da Canção
+SONG_SCORE_WHEREAMI=Pontuação
+
+SING_SCORE_TONE_DEAF=Ouvido Mouco
+SING_SCORE_AMATEUR=Amador
+SING_SCORE_WANNABE=Promessa
+SING_SCORE_HOPEFUL=Artista
+SING_SCORE_RISING_STAR=Estrela em Ascenção
+SING_SCORE_LEAD_SINGER=Cantor Principal
+SING_SCORE_SUPERSTAR=SuperStar
+SING_SCORE_ULTRASTAR=UltraStar
+
+SING_TOP_5_CHARTS=5 Melhores Jogadores
+SING_TOP_5_CHARTS_WHEREAMI=Top 5
+SING_TOP_5_CHARTS_CONTINUE=para a escolha da Canção
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=trocar de dificuldade
+
+POPUP_PERFECT=Perfeito!
+POPUP_AWESOME=Fantástico!
+POPUP_GREAT=Ótimo!
+POPUP_GOOD=Bom!
+POPUP_NOTBAD=Nada Mal!
+POPUP_BAD=Mau!
+POPUP_POOR=Péssimo!
+POPUP_AWFUL=Horrível!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= e
+
+SONG_MENU_NAME_MAIN=Menu de canções
+SONG_MENU_PLAY=Cantar
+SONG_MENU_CHANGEPLAYERS=Mudar Jogadores
+SONG_MENU_EDIT=Editar
+SONG_MENU_MODI=Cantar uma Modi
+SONG_MENU_CANCEL=Cancelar
+
+SONG_MENU_NAME_PLAYLIST=Menu de Canções
+SONG_MENU_PLAYLIST_ADD=Adicionar Canção
+SONG_MENU_PLAYLIST_DEL=Apagar Canção
+
+SONG_MENU_NAME_PLAYLIST_ADD=Adicionar Canção
+SONG_MENU_PLAYLIST_ADD_NEW=a uma nova playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=a uma playlist existente
+SONG_MENU_PLAYLIST_NOEXISTING=Sem playlist disponível
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nova Playlist
+SONG_MENU_PLAYLIST_NEW_CREATE=Criar
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Sem nome
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Deseja mesmo eliminar?
+SONG_MENU_YES=Sim
+SONG_MENU_NO=Não
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Abrir Playlist
+SONG_MENU_PLAYLIST_LOAD=abrir
+SONG_MENU_PLAYLIST_DELCURRENT=apagar Playlist atual
+
+SONG_MENU_NAME_PLAYLIST_DEL=Apagar mesmo?
+
+SONG_MENU_NAME_PARTY_MAIN=Menu de Festa
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=Usar Joker
+
+SONG_JUMPTO_DESC=Procurar
+SONG_JUMPTO_TYPE_DESC=Procurar por:
+SONG_JUMPTO_TYPE1=Todos
+SONG_JUMPTO_TYPE2=Título
+SONG_JUMPTO_TYPE3=Artista
+SONG_JUMPTO_SONGSFOUND=%d Música(s) encontrada(s)
+SONG_JUMPTO_NOSONGSFOUND=Nenhuma Canção encontrada
+SONG_JUMPTO_HELP=Escreva para procurar
+SONG_JUMPTO_CATTEXT=Procurar por: %s
+
+PARTY_MODE=Modo Festa
+PARTY_DIFFICULTY=Dificuldade
+PARTY_PLAYLIST=Modo Playlist
+PARTY_PLAYLIST_ALL=Todas as Canções
+PARTY_PLAYLIST_CATEGORY=Diretório
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_TEAMS=Equipes
+PARTY_TEAMS_PLAYER1=Jogador Equipe1
+PARTY_TEAMS_PLAYER2=Jogador Equipe2
+PARTY_TEAMS_PLAYER3=Jogador Equipe3
+
+PARTY_LEGEND_CONTINUE=Continuar
+
+PARTY_OPTIONS_DESC=Configurações para o Modo Festa
+PARTY_OPTIONS_WHEREAMI=Opções de Festa
+
+PARTY_PLAYER_DESC=Inserir nomes de jogadores e equipas
+PARTY_PLAYER_WHEREAMI=Nomes de Festa
+PARTY_PLAYER_ENTER_NAME=Inserir nomes
+
+
+PARTY_ROUNDS_DESC=Escolha os modos que deseja jogar
+PARTY_ROUNDS_WHEREAMI=Rondas da Festa
+PARTY_ROUNDS_LEGEND_CONTINUE=Iniciar Festa
+PARTY_ROUNDCOUNT=Nº de Rondas
+PARTY_SELECTMODE1=Ronda 1
+PARTY_SELECTMODE2=Ronda 2
+PARTY_SELECTMODE3=Ronda 3
+PARTY_SELECTMODE4=Ronda 4
+PARTY_SELECTMODE5=Ronda 5
+PARTY_SELECTMODE6=Ronda 6
+PARTY_SELECTMODE7=Ronda 7
+
+PARTY_ROUND_DESC=Jogadores seguintes para os microfones
+PARTY_ROUND_WHEREAMI=Rodada seguinte
+PARTY_ROUND_LEGEND_CONTINUE=Início da Rodada
+
+PARTY_SONG_WHEREAMI=Escolha da Canção
+PARTY_SONG_LEGEND_CONTINUE=Cantar
+PARTY_SONG_MENU=Menu Festa
+
+PARTY_SCORE_DESC=Pontuação da última rodada
+PARTY_SCORE_WHEREAMI=Pontos da Festa
+
+PARTY_WIN_DESC=Vencedor do Jogo Festa
+PARTY_WIN_WHEREAMI=Vencedor da Festa
+PARTY_WIN_LEGEND_CONTINUE=Voltar ao Menu Principal
+
+PARTY_ROUND=Rodada
+PARTY_ROUND_WINNER=Vencedor
+PARTY_NOTPLAYEDYET=Não tocada
+PARTY_NOBODY=Ninguém
+NEXT_ROUND=Rodada seguinte:
+
+PARTY_DISMISSED=Dispensado!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=Ganhou!
+
+MODE_RANDOM_NAME=Modo Aleatório
+MODE_RANDOM_DESC=Será escolhido um Modo Aleatoriamente
+
+MODE_HOLDTHELINE_NAME=Manter a linha
+MODE_HOLDTHELINE_DESC=Não piorar o ponteiro que é mostrado na barra de pontuação
+
+MODE_5000POINTS_NAME=Até 5000
+MODE_5000POINTS_DESC=Quem obter primeiro 5000 pontos ganha a partida
+
+MODE_DUEL_NAME=Duelo
+MODE_DUEL_DESC=Fazer um Duelo até aos 10000 pontos.
+
+MODE_TEAMDUEL_NAME=Duelo de equipe
+MODE_TEAMDUEL_DESC=Passa o Microfone!
+
+MODE_BLIND_NAME=Modo Cego
+MODE_BLIND_DESC=Duelo sem ver as notas.
+
+STAT_MAIN=Estatísticas
+STAT_MAIN_DESC=Geral
+STAT_MAIN_WHEREAMI=Estatísticas
+
+STAT_OVERVIEW_INTRO=%0:s Estatisticas.  \n Último Reset a %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Canções(%3:d com Video), das quais %1:d já tocaram e %2:d ainda não tocaram.\n A Canção mais popular é %5:s de %4:s.
+STAT_OVERVIEW_PLAYER=Desde o último Reset houve %0:d Jogador(es) diferente(s).\n O Melhor Jogador é %1:s com a Pontuação Média de %2:d Pontos.\n %3:s teve a Pontuação mais alta com %4:d Pontos.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Estatísticas
+STAT_DETAIL_WHEREAMI=Estatísticas Detalhadas
+
+STAT_NEXT=Página Seguinte
+STAT_PREV=Página Anterior
+STAT_REVERSE=Ordem Inversa
+STAT_PAGE=%0:d de %1:d Páginas\n (%2:d de %3:d Entradas)
+
+STAT_DESC_SCORES=Pontuções Altas
+STAT_DESC_SCORES_REVERSED=Pontuações Baixas
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Melhores Cantores
+STAT_DESC_SINGERS_REVERSED=Piores Cantores
+STAT_FORMAT_SINGERS=%0:s \n Pontuação Média: %1:d
+
+STAT_DESC_SONGS=Melhores Canções
+STAT_DESC_SONGS_REVERSED=Canções Menos Populares
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx Cantaram
+
+STAT_DESC_BANDS=Melhores Bandas
+STAT_DESC_BANDS_REVERSED=Bandas Menos Populares
+STAT_FORMAT_BANDS=%0:s \n %1:dx Cantaram
+
+SCREENSHOT_SAVED=Screenshot Guardado
+SCREENSHOT_FAILED=Impossível Guardar Screenshot
+
+INFO_FILE_SAVED=Ficheiro Guardado
+ERROR_SAVE_FILE_FAILED=Impossível Guardar Ficheiro
+ERROR_FILE_NOT_FOUND=Ficheiro Não Encontrado
+
+ENCODING_ERROR_ASK_FOR_UTF8=Impossível guardar na codificação corrente. Converter pata UTF-8?
+EDITOR_ERROR_NO_TRACK_SELECTED=Nenhuma pista seleccionada
+
+MSG_ERROR_TITLE=Erro
+MSG_INFO_TITLE=Informação
+MSG_QUESTION_TITLE=Questão
+MSG_QUIT_USDX=Deseja mesmo sair do UltraStar?
+MSG_END_PARTY=Deseja mesmo terminar o Modo Festa?
+
+ERROR_NO_SONGS=Nenhuma Canção lida
+ERROR_NO_PLUGINS=Nenhum Plugin lido
+ERROR_NO_MODES_FOR_CURRENT_SETUP=Não existem modos para a corrente configuração
+ERROR_CAN_NOT_START_PARTY=Erro ao iniciar o Modo Festa!
+ERROR_CORRUPT_SONG=Canção não pôde ser lida!
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=A canção não foi encontrada!
+ERROR_CORRUPT_SONG_NO_NOTES=A canção não tem notas!
+ERROR_CORRUPT_SONG_NO_BREAKS=A canção não tem quebras de linha!
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Erro durante o parsing da linha %0:d
+ERROR_NO_EDITOR=Esta opção não está disponível no Linux/Mac
+ERROR_PLAYER_DEVICE_ASSIGNMENT=O Jogador %d está atribuído a vários microfones. Por favor verifique as opções de gravação!
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=O Jogador %d não está atribuído a nenhum microfone. Por favor verifique as opções de gravação!
diff --git a/songmanagement/game/languages/Russian.ini b/songmanagement/game/languages/Russian.ini
new file mode 100644
index 00000000..5c4e5d62
--- /dev/null
+++ b/songmanagement/game/languages/Russian.ini
@@ -0,0 +1,442 @@
+[Text]
+OPTION_VALUE_CATALAN=Каталонский
+OPTION_VALUE_CROATIAN=Хорватский
+OPTION_VALUE_CZECH=Чешский
+OPTION_VALUE_DANISH=Датский
+OPTION_VALUE_DUTCH=Голландский
+OPTION_VALUE_ENGLISH=Английский
+OPTION_VALUE_EUSKARA=Баскский
+OPTION_VALUE_FINNISH=Финский
+OPTION_VALUE_FRENCH=Французский
+OPTION_VALUE_GERMAN=Немецкий
+OPTION_VALUE_GREEK=Греческий
+OPTION_VALUE_HUNGARIAN=Венгерский
+OPTION_VALUE_ICELANDIC=Исландский
+OPTION_VALUE_ITALIAN=Итальянский
+OPTION_VALUE_JAPANESE=Японский
+OPTION_VALUE_LUXEMBOURGISH=Люксембуржский
+OPTION_VALUE_NORWEGIAN=Норвежский
+OPTION_VALUE_POLISH=Польский
+OPTION_VALUE_PORTUGUESE=Португальский
+OPTION_VALUE_RUSSIAN=Русский
+OPTION_VALUE_SERBIAN=Сербский
+OPTION_VALUE_SLOVAK=Словацкий
+OPTION_VALUE_SLOVENIAN=Словенский
+OPTION_VALUE_SPANISH=Испанский
+OPTION_VALUE_SWEDISH=Шведский
+
+OPTION_VALUE_EASY=Простой
+OPTION_VALUE_MEDIUM=Средний
+OPTION_VALUE_HARD=Сложный
+
+OPTION_VALUE_ON=Вкл
+OPTION_VALUE_OFF=Выкл
+
+OPTION_VALUE_EDITION=Редакция
+OPTION_VALUE_GENRE=Жанр
+OPTION_VALUE_LANGUAGE=Язык
+OPTION_VALUE_FOLDER=Папка
+OPTION_VALUE_TITLE=Название
+OPTION_VALUE_ARTIST=Исполнитель
+OPTION_VALUE_TITLE2=Название 2
+OPTION_VALUE_ARTIST2=Исполнитель 2
+
+OPTION_VALUE_WHENNOVIDEO=Если нет видео
+
+OPTION_VALUE_SMALL=Маленький
+OPTION_VALUE_BIG=Большой
+
+OPTION_VALUE_HALF=Половина
+OPTION_VALUE_FULL_VID=Полный (Видео)
+OPTION_VALUE_FULL_VID_BG=Полный (Фон и видео)
+
+OPTION_VALUE_AUTO=Авто
+OPTION_VALUE_SEC=Секунда
+OPTION_VALUE_SECS=Секунд(ы)
+
+OPTION_VALUE_PLAIN=Plain
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Простое
+OPTION_VALUE_ZOOM=Масштаб
+OPTION_VALUE_SLIDE=Скольжение
+OPTION_VALUE_BALL=Шар
+OPTION_VALUE_SHIFT=Сдвиг
+
+OPTION_VALUE_EURO=Европейский
+OPTION_VALUE_JAPAN=Японский
+OPTION_VALUE_AMERICAN=Американский
+
+OPTION_VALUE_BLUE=Синий
+OPTION_VALUE_GREEN=Зелёный
+OPTION_VALUE_PINK=Розовый
+OPTION_VALUE_RED=Красный
+OPTION_VALUE_VIOLET=Фиолетовый
+OPTION_VALUE_ORANGE=Оранжевый
+OPTION_VALUE_YELLOW=Жёлтый
+OPTION_VALUE_BROWN=Коричневый
+OPTION_VALUE_BLACK=Чёрный
+
+OPTION_VALUE_SING=Пение
+OPTION_VALUE_SELECT_PLAYERS=Выбор игроков
+OPTION_VALUE_OPEN_MENU=Открыть меню
+
+OPTION_VALUE_HARDWARE_CURSOR=Аппаратный курсор
+OPTION_VALUE_SOFTWARE_CURSOR=Програмный курсор
+
+SING_LOADING=Загрузка...
+
+SING_CHOOSE_MODE=Выберите режим
+SING_SING=Пение
+SING_SING_DESC=быстрая игра: пойте соло или дуэтом
+
+SING_MULTI=Вечеринка
+SING_MULTI_DESC=петь в режиме вечеринки
+
+SING_TOOLS=Инструменты
+
+SING_STATS=Статистика
+SING_STATS_DESC=смотреть статистику
+
+SING_EDITOR=Редактор
+SING_EDITOR_DESC=создать свою собственную песню
+
+SING_GAME_OPTIONS=Настройки
+SING_GAME_OPTIONS_DESC=изменить настройки игры
+
+SING_EXIT=Выход
+SING_EXIT_DESC=выйти из игры
+
+SING_OPTIONS=Настройки
+SING_OPTIONS_DESC=изменить настройки
+SING_OPTIONS_WHEREAMI=Настройки
+
+SING_OPTIONS_GAME=игра
+SING_OPTIONS_GRAPHICS=графика
+SING_OPTIONS_SOUND=звук
+SING_OPTIONS_LYRICS=текст
+SING_OPTIONS_THEMES=темы
+SING_OPTIONS_RECORD=запись
+SING_OPTIONS_ADVANCED=продвинутые
+SING_OPTIONS_EXIT=назад
+
+SING_OPTIONS_GAME_WHEREAMI=Настройки игры
+SING_OPTIONS_GAME_DESC=основные настройки игры
+SING_OPTIONS_GAME_PLAYERS=Игроки
+SING_OPTIONS_GAME_DIFFICULTY=Сложность
+SING_OPTIONS_GAME_LANGUAGE=Язык
+SING_OPTIONS_GAME_TABS=Табы
+SING_OPTIONS_GAME_SORTING=Сортировка
+SING_OPTIONS_GAME_DEBUG=Отладка
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Настройки графики
+SING_OPTIONS_GRAPHICS_DESC=настройки графики
+SING_OPTIONS_GRAPHICS_RESOLUTION=Разрешение
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Полный экран
+SING_OPTIONS_GRAPHICS_DEPTH=Глубина цвета
+SING_OPTIONS_GRAPHICS_VISUALIZER=Визуализация
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Осциллограф
+SING_OPTIONS_GRAPHICS_LINEBONUS=Бонус "в линию"
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Размер клипа
+
+SING_OPTIONS_SOUND_WHEREAMI=Настройки звука
+SING_OPTIONS_SOUND_DESC=настройки звука
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Вывод с микрофона
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Фоновая музыка
+SING_OPTIONS_SOUND_MIC_BOOST=Усиление мкрофона
+SING_OPTIONS_SOUND_CLICK_ASSIST=Метроном-помощник
+SING_OPTIONS_SOUND_BEAT_CLICK=Метроном
+SING_OPTIONS_SOUND_THRESHOLD=Погрешность
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Режим двух игроков
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Громкость превью
+SING_OPTIONS_SOUND_PREVIEWFADING=Затухание превью
+
+SING_OPTIONS_LYRICS_WHEREAMI=Настройки текстов
+SING_OPTIONS_LYRICS_DESC=настройки текстов
+SING_OPTIONS_LYRICS_FONT=Шрифт
+SING_OPTIONS_LYRICS_EFFECT=Эффект
+SING_OPTIONS_LYRICS_SOLMIZATION=сольмизация
+SING_OPTIONS_LYRICS_NOTELINES=Линии стана
+
+SING_OPTIONS_THEMES_WHEREAMI=Настройки тем
+SING_OPTIONS_THEMES_DESC=настройки тем и скинов
+SING_OPTIONS_THEMES_THEME=Тема
+SING_OPTIONS_THEMES_SKIN=Скин
+SING_OPTIONS_THEMES_COLOR=Цвет
+
+SING_OPTIONS_RECORD_WHEREAMI=Настройки записи
+SING_OPTIONS_RECORD_DESC=настройки микрофона
+SING_OPTIONS_RECORD_CARD=Звуковая карта
+SING_OPTIONS_RECORD_INPUT=Вход
+SING_OPTIONS_RECORD_CHANNEL=Канал
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Дополнительные настройки
+SING_OPTIONS_ADVANCED_DESC=дополнительные настройки
+SING_OPTIONS_ADVANCED_EFFECTSING=Эффекты пения
+SING_OPTIONS_ADVANCED_SCREENFADE=Затухание экрана
+SING_OPTIONS_ADVANCED_LOADANIMATION=Анимация загрузки
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Запросы
+SING_OPTIONS_ADVANCED_LINEBONUS=Бонус "В линию"
+SING_OPTIONS_ADVANCED_ONSONGCLICK=После выбора песни
+;TODO: SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto PartyMenu
+
+SING_EDIT=Редактор
+SING_EDIT_MENU_DESCRIPTION=создать свою собственную песню
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Импортировать текст из MIDI-файла
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=назад
+SING_EDIT_BUTTON_CONVERT=Импорт
+SING_EDIT_BUTTON_EXIT=назад
+
+SING_EDIT_NAVIGATE=перейти
+SING_EDIT_SELECT=выбрать
+SING_EDIT_EXIT=назад
+
+SING_LEGEND_SELECT=выбрать
+SING_LEGEND_NAVIGATE=перейти
+SING_LEGEND_CONTINUE=продолжить
+SING_LEGEND_ESC=назад
+
+SING_PLAYER_DESC=введите имя игрока(игроков)
+SING_PLAYER_WHEREAMI=Имена игроков
+SING_PLAYER_ENTER_NAME=введите имя
+
+SING_DIFFICULTY_DESC=уровень сложности
+SING_DIFFICULTY_WHEREAMI=Сложность
+SING_DIFFICULTY_CONTINUE=к выбору песни
+SING_EASY=Легкий
+SING_MEDIUM=Средний
+SING_HARD=Сложный
+
+SING_SONG_SELECTION_DESC=выберите песню
+SING_SONG_SELECTION_WHEREAMI=Выбор песни
+SING_SONG_SELECTION_GOTO=перейти ..
+SING_SONG_SELECTION=выбор песни
+SING_SONG_SELECTION_MENU=меню
+SING_SONG_SELECTION_PLAYLIST=плэйлист
+SING_SONGS_IN_CAT=Песни
+PLAYLIST_CATTEXT=Плэйлист: %s
+
+SING_TIME=ВРЕМЯ
+SING_TOTAL=всего
+SING_MODE=пение соло
+SING_NOTES=ноты
+SING_GOLDEN_NOTES=золотые ноты
+SING_PHRASE_BONUS=бонус "В линию"
+
+SING_MENU=Главное меню
+
+SONG_SCORE=Результаты исполнения
+SONG_SCORE_WHEREAMI=Очки
+
+SING_SCORE_TONE_DEAF=Глухой
+SING_SCORE_AMATEUR=Любитель
+SING_SCORE_WANNABE=Старается
+SING_SCORE_HOPEFUL=Подающий надежды
+SING_SCORE_RISING_STAR=Восходящая звезда
+SING_SCORE_LEAD_SINGER=Вокалист
+SING_SCORE_SUPERSTAR=Суперзвезда
+SING_SCORE_ULTRASTAR=Ультрастар!
+
+SING_TOP_5_CHARTS=5 лучших
+SING_TOP_5_CHARTS_WHEREAMI=лучшие 5
+SING_TOP_5_CHARTS_CONTINUE=к выбору песни
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=сменить сложность
+
+POPUP_PERFECT=прекрасно!
+POPUP_AWESOME=удивительно!
+POPUP_GREAT=великолепно!
+POPUP_GOOD=хорошо!
+POPUP_NOTBAD=неплохо!
+POPUP_BAD=плохо!
+POPUP_POOR=ужасно!
+POPUP_AWFUL=невыносимо!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= и
+
+SONG_MENU_NAME_MAIN=меню пения
+SONG_MENU_PLAY=Петь
+SONG_MENU_CHANGEPLAYERS=Изменить игроков
+SONG_MENU_EDIT=Изменить
+SONG_MENU_MODI=Петь
+SONG_MENU_CANCEL=Отмена
+
+SONG_MENU_NAME_PLAYLIST=Меню песен
+SONG_MENU_PLAYLIST_ADD=Добавить песню
+SONG_MENU_PLAYLIST_DEL=Удалить песню
+
+SONG_MENU_NAME_PLAYLIST_ADD=Добавить песню
+SONG_MENU_PLAYLIST_ADD_NEW=в новый плэйлист
+SONG_MENU_PLAYLIST_ADD_EXISTING=в существующий плэйлист
+SONG_MENU_PLAYLIST_NOEXISTING=Плэйлисты отсутствуют
+
+SONG_MENU_NAME_PLAYLIST_NEW=Новый плэйлист
+SONG_MENU_PLAYLIST_NEW_CREATE=Создать
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Без имени
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Вы действительно желаете удалить элемент?
+SONG_MENU_YES=Да
+SONG_MENU_NO=Нет
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Открыть список
+SONG_MENU_PLAYLIST_LOAD=открыть
+SONG_MENU_PLAYLIST_DELCURRENT=удалить текущий плэйлист
+
+SONG_MENU_NAME_PLAYLIST_DEL=Удалить плэйлист?
+
+SONG_MENU_NAME_PARTY_MAIN=Меню вечеринки
+SONG_MENU_JOKER=Джокер
+
+SONG_MENU_NAME_PARTY_JOKER=взять джокер
+
+SONG_JUMPTO_DESC=поиск песни
+SONG_JUMPTO_TYPE_DESC=Искать:
+SONG_JUMPTO_TYPE1=Всё
+SONG_JUMPTO_TYPE2=Название
+SONG_JUMPTO_TYPE3=Исполнитель
+SONG_JUMPTO_SONGSFOUND=%d Песен найдено
+SONG_JUMPTO_NOSONGSFOUND=Песен не найдено
+SONG_JUMPTO_HELP=Введите текст для поиска
+SONG_JUMPTO_CATTEXT=Искать: %s
+
+PARTY_MODE=режим вечеринки
+PARTY_DIFFICULTY=Сложность
+PARTY_PLAYLIST=Режим плэйлиста
+PARTY_PLAYLIST_ALL=Все песни
+PARTY_PLAYLIST_CATEGORY=Папка
+PARTY_PLAYLIST_PLAYLIST=Плэйлист
+PARTY_TEAMS=число команд
+PARTY_TEAMS_PLAYER1=число исполнителей
+PARTY_TEAMS_PLAYER2=число исполнителей
+PARTY_TEAMS_PLAYER3=число исполнителей
+
+PARTY_LEGEND_CONTINUE=продолжить
+
+PARTY_OPTIONS_DESC=настройки игры-вечеринки
+PARTY_OPTIONS_WHEREAMI=Настройки вечеринки
+
+PARTY_PLAYER_DESC=введите имена игроков и команд!
+PARTY_PLAYER_WHEREAMI=Имена для вечеринки
+PARTY_PLAYER_ENTER_NAME=ввести имена
+
+
+PARTY_ROUNDS_DESC=выберите режимы игры
+PARTY_ROUNDS_WHEREAMI=Раунды вечеринки
+PARTY_ROUNDS_LEGEND_CONTINUE=начать игру-вечеринку
+PARTY_ROUNDCOUNT=число раундов
+PARTY_SELECTMODE1=режим раунда 1
+PARTY_SELECTMODE2=режим раунда 2
+PARTY_SELECTMODE3=режим раунда 3
+PARTY_SELECTMODE4=режим раунда 4
+PARTY_SELECTMODE5=режим раунда 5
+PARTY_SELECTMODE6=режим раунда 6
+PARTY_SELECTMODE7=режим раунда 7
+
+PARTY_ROUND_DESC=следующие игроки к микрофонам:
+PARTY_ROUND_WHEREAMI=Следующий раунд вечеринки
+PARTY_ROUND_LEGEND_CONTINUE=начать раунд
+
+PARTY_SONG_WHEREAMI=Выбор песен для вечеринки
+PARTY_SONG_LEGEND_CONTINUE=петь
+PARTY_SONG_MENU=меню
+
+PARTY_SCORE_DESC=счёт прошедшего раунда
+PARTY_SCORE_WHEREAMI=Очки вечеринки
+
+PARTY_WIN_DESC=победитель вечеринки
+PARTY_WIN_WHEREAMI=Победитель вечеринки
+PARTY_WIN_LEGEND_CONTINUE=вернуться в главное меню
+
+PARTY_ROUND=Раунд
+PARTY_ROUND_WINNER=Победитель
+PARTY_NOTPLAYEDYET=ещё не играли
+PARTY_NOBODY=никто
+NEXT_ROUND=Следующий раунд:
+
+PARTY_DISMISSED=Отменено!
+PARTY_SCORE_WINS=Победители: %s !
+;TODO: PARTY_SCORE_WINS2=wins!
+
+MODE_RANDOM_NAME=Случайный режим
+MODE_RANDOM_DESC=Режим будет выбран случайным образом
+
+MODE_HOLDTHELINE_NAME=Оставайтесь на линии
+MODE_HOLDTHELINE_DESC=Будьте не хуже, чем вам показывает указатель рэйтинга.
+
+MODE_5000POINTS_NAME=До 5000
+MODE_5000POINTS_DESC=Матч выигрывает тот, кто первым наберёт 5000 очков.
+
+MODE_DUEL_NAME=Дуэль
+MODE_DUEL_DESC=Дуэль до 10000 очков.
+
+MODE_TEAMDUEL_NAME=Командная дуэль
+MODE_TEAMDUEL_DESC=Передавайте микрофон!
+
+MODE_BLIND_NAME=Слепой режим
+MODE_BLIND_DESC=Дуэль, в которой вы не видите нот.
+
+STAT_MAIN=Статистика
+STAT_MAIN_DESC=Главная
+STAT_MAIN_WHEREAMI=Статистика
+
+STAT_OVERVIEW_INTRO=%0:s Статистика.  \n Последний сброс в %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Песен(%3:d с видео), из них %1:d уже проигрывались и %2:d ещё не проигрывались.\n Самая популярная песня  %5:s from %4:s.
+STAT_OVERVIEW_PLAYER=С последнего сброса в игре участвовало %0:d игроков.\n Лучший игрок %1:s со средним счётом %2:d очков.\n %3:s с лучшим счётом %4:d очков.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Статистика
+STAT_DETAIL_WHEREAMI=Подробная статистика
+
+STAT_NEXT=След. страница
+STAT_PREV=Пред. страница
+STAT_REVERSE=В обр. порядке
+STAT_PAGE=страница %0:d из %1:d\n (%2:d из %3:d)
+
+STAT_DESC_SCORES=Лучшие игры
+STAT_DESC_SCORES_REVERSED=Худшие игры
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Лучшие певцы
+STAT_DESC_SINGERS_REVERSED=Худшие певцы
+STAT_FORMAT_SINGERS=%0:s \n Средний счёт: %1:d
+
+STAT_DESC_SONGS=Популярные песни
+STAT_DESC_SONGS_REVERSED=Непопулярные песни
+STAT_FORMAT_SONGS=%0:s - %1:s \n звучала %2:dx
+
+STAT_DESC_BANDS=Популярные группы
+STAT_DESC_BANDS_REVERSED=Непопулярные группы
+STAT_FORMAT_BANDS=%0:s \n звучала %1:dx
+
+SCREENSHOT_SAVED=Снимок экрана сохранён
+SCREENSHOT_FAILED=Невозможно сохранить снимок экрана
+
+INFO_FILE_SAVED=Файл сохранён
+ERROR_SAVE_FILE_FAILED=Невозможно сохранить файл
+ERROR_FILE_NOT_FOUND=Файл не найден
+
+ENCODING_ERROR_ASK_FOR_UTF8=Невозможно сохранить изменения в текущей кодировке. Преобразовать в UTF-8?
+EDITOR_ERROR_NO_TRACK_SELECTED=Ни одна дорожка не выбрана
+
+MSG_ERROR_TITLE=Ошибка
+MSG_INFO_TITLE=Информация
+MSG_QUESTION_TITLE=Вопрос
+MSG_QUIT_USDX=Вы действительно желаете покинуть UltraStar?
+MSG_END_PARTY=Действительно покинуть режим вечеринки?
+
+ERROR_NO_SONGS=Нет загруженных песен
+ERROR_NO_PLUGINS=Нет загруженных дополнений
+ERROR_NO_MODES_FOR_CURRENT_SETUP=нет доступных режимов для текущих настроек игрока/команды
+ERROR_CAN_NOT_START_PARTY=произошла ошибка запуска игры-вечеринки
+ERROR_CORRUPT_SONG=Песня не может быть загружена.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Песня не может быть загружена: Файл не найден
+ERROR_CORRUPT_SONG_NO_NOTES=Песня не может быть загружена: Невозможно найти ноты
+ERROR_CORRUPT_SONG_NO_BREAKS=Песня не может быть загружена: Невозможно найти разделители строк
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Песня не может быть загружена: Ошибка обработки строки %0:d
+ERROR_NO_EDITOR=Эта возможность недоступна в Linux/Mac
+ERROR_PLAYER_DEVICE_ASSIGNMENT=Игроку %d назначено несколько микрофонов. Пожалуйста проверьте опции записи
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Игроку %d не назначено ни одного микрофона. Пожалуйста проверьте опции записи
+;TRANSLATOR: Dmitry "Sadler" Manachkin
diff --git a/songmanagement/game/languages/Serbian.ini b/songmanagement/game/languages/Serbian.ini
new file mode 100644
index 00000000..b02ddf3c
--- /dev/null
+++ b/songmanagement/game/languages/Serbian.ini
@@ -0,0 +1,443 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Ucitava se...
+
+SING_CHOOSE_MODE=izaberi mod
+SING_SING=pevaj
+SING_SING_DESC=brza igra: pevaj solo ili u duetu
+
+SING_MULTI=tim
+SING_MULTI_DESC=pevaj u timskom modu
+
+SING_TOOLS=alati
+
+SING_STATS=statistike
+SING_STATS_DESC=pogledaj statistike
+
+SING_EDITOR=editor
+SING_EDITOR_DESC=napravi svoje pesme
+
+SING_GAME_OPTIONS=oprcije igre
+SING_GAME_OPTIONS_DESC=promeni podesavanja igre
+
+SING_EXIT=izlaz
+SING_EXIT_DESC=izadji iz igre
+
+SING_OPTIONS=opcije
+SING_OPTIONS_DESC=promeni podesavanja
+SING_OPTIONS_WHEREAMI=Opcije
+
+SING_OPTIONS_GAME=igra
+SING_OPTIONS_GRAPHICS=grafika
+SING_OPTIONS_SOUND=zvuk
+SING_OPTIONS_LYRICS=lirike
+SING_OPTIONS_THEMES=teme
+SING_OPTIONS_RECORD=snimanje
+SING_OPTIONS_ADVANCED=ostalo
+SING_OPTIONS_EXIT=nazad
+
+SING_OPTIONS_GAME_WHEREAMI=Opcije Igra
+SING_OPTIONS_GAME_DESC=opsta podesavanja igre
+SING_OPTIONS_GAME_PLAYERS=Igraci
+SING_OPTIONS_GAME_DIFFICULTY=Tezina
+SING_OPTIONS_GAME_LANGUAGE=Jezik
+SING_OPTIONS_GAME_TABS=Tabovi
+SING_OPTIONS_GAME_SORTING=Sortiranje
+SING_OPTIONS_GAME_DEBUG=Dibagiranje
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Opcije Grafika
+SING_OPTIONS_GRAPHICS_DESC=graficka podesavanja
+SING_OPTIONS_GRAPHICS_RESOLUTION=Rezolucija
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Pun Ekran
+SING_OPTIONS_GRAPHICS_DEPTH=Boje
+;TODO: SING_OPTIONS_GRAPHICS_VISUALIZER=Visualization
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Osciloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Bonus Linija
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Velicina Videa
+
+SING_OPTIONS_SOUND_WHEREAMI=Opcije Zvuk
+SING_OPTIONS_SOUND_DESC=podesavanja zvuka
+;TODO: SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Microphone Playback
+;TODO: SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Background music
+SING_OPTIONS_SOUND_MIC_BOOST=Pojacanje mikrofona
+SING_OPTIONS_SOUND_CLICK_ASSIST=Click assist
+SING_OPTIONS_SOUND_BEAT_CLICK=Beat click
+SING_OPTIONS_SOUND_THRESHOLD=Stepen Cujnosti
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Mod za dva igraca
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Provera jacine tona
+SING_OPTIONS_SOUND_PREVIEWFADING=Provera pomracenja
+
+SING_OPTIONS_LYRICS_WHEREAMI=Opcije Lirike
+SING_OPTIONS_LYRICS_DESC=Podesavanja lirika
+SING_OPTIONS_LYRICS_FONT=Font
+SING_OPTIONS_LYRICS_EFFECT=Efekti
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmizacija
+;TODO: SING_OPTIONS_LYRICS_NOTELINES=Staves
+
+SING_OPTIONS_THEMES_WHEREAMI=Opcije Teme
+SING_OPTIONS_THEMES_DESC=podesavanja teme i skina
+SING_OPTIONS_THEMES_THEME=Tema
+SING_OPTIONS_THEMES_SKIN=Skin
+SING_OPTIONS_THEMES_COLOR=Boja
+
+SING_OPTIONS_RECORD_WHEREAMI=Opcije Snimanje
+SING_OPTIONS_RECORD_DESC=podesavanja mikrofona
+SING_OPTIONS_RECORD_CARD=Zvucna Kartica
+SING_OPTIONS_RECORD_INPUT=Ulaz
+SING_OPTIONS_RECORD_CHANNEL=Kanal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Opcije Ostalo
+SING_OPTIONS_ADVANCED_DESC=ostala podesavanja
+SING_OPTIONS_ADVANCED_EFFECTSING=Efekti Pevanja
+SING_OPTIONS_ADVANCED_SCREENFADE=Pomracenje Ekrana
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animacija Ucitavanja
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Bezbednosna Pitanja
+SING_OPTIONS_ADVANCED_LINEBONUS=Linijski Bonus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Posle Odabira Pesme
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Automatski Timski Meni
+
+;TODO: SING_EDIT=Editor
+;TODO: SING_EDIT_MENU_DESCRIPTION=create your own song
+
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Import text from midi file
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_EXIT=back
+;TODO: SING_EDIT_BUTTON_CONVERT=Import
+;TODO: SING_EDIT_BUTTON_EXIT=back
+
+;TODO: SING_EDIT_NAVIGATE=navigate
+;TODO: SING_EDIT_SELECT=select
+;TODO: SING_EDIT_EXIT=back
+
+SING_LEGEND_SELECT=izaberi
+SING_LEGEND_NAVIGATE=biraj
+SING_LEGEND_CONTINUE=nastavi
+SING_LEGEND_ESC=nazad
+
+SING_PLAYER_DESC=unesi ime igraca
+SING_PLAYER_WHEREAMI=Imenaigraca
+SING_PLAYER_ENTER_NAME=unesi ime
+
+SING_DIFFICULTY_DESC=izaberi tezinu
+SING_DIFFICULTY_WHEREAMI=Tezina
+SING_DIFFICULTY_CONTINUE=do odabira pesme
+SING_EASY=Lako
+SING_MEDIUM=Normalno
+SING_HARD=Tesko
+
+SING_SONG_SELECTION_DESC=izaberi svoju pesmu
+SING_SONG_SELECTION_WHEREAMI=Izbor Pesme
+SING_SONG_SELECTION_GOTO=idi na...
+SING_SONG_SELECTION=izbor pesme
+SING_SONG_SELECTION_MENU=meni
+SING_SONG_SELECTION_PLAYLIST=lista pesama
+SING_SONGS_IN_CAT=Pesme
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=TIME
+SING_TOTAL=total
+SING_MODE=pevaj solo
+SING_NOTES=note
+SING_GOLDEN_NOTES=zlatne note
+SING_PHRASE_BONUS=linijski bonus
+
+SING_MENU=Glavni Meni
+
+SONG_SCORE=rezultat pesme
+SONG_SCORE_WHEREAMI=Rezultat
+
+SING_SCORE_TONE_DEAF=Antitalenat
+SING_SCORE_AMATEUR=Amater
+;TODO: SING_SCORE_WANNABE=Wannabe
+;TODO: SING_SCORE_HOPEFUL=Hopeful
+SING_SCORE_RISING_STAR=Zvezda U Usponu
+SING_SCORE_LEAD_SINGER=Solista
+SING_SCORE_SUPERSTAR=SuperZvezda
+SING_SCORE_ULTRASTAR=UltraZvezda
+
+SING_TOP_5_CHARTS=najboljih 5 Igraca
+SING_TOP_5_CHARTS_WHEREAMI=najboljih pet
+SING_TOP_5_CHARTS_CONTINUE=do izbora pesme
+;TODO: SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=savrseno!
+POPUP_AWESOME=odlicno!
+POPUP_GREAT=sjajno!
+POPUP_GOOD=dobro!
+POPUP_NOTBAD=nije lose!
+POPUP_BAD=lose!
+POPUP_POOR=jedno!
+POPUP_AWFUL=grozno!
+
+IMPLODE_GLUE1=, 
+IMPLODE_GLUE2= i 
+
+SONG_MENU_NAME_MAIN=meni pesme
+SONG_MENU_PLAY=Pevaj
+SONG_MENU_CHANGEPLAYERS=Promeni Igrace
+SONG_MENU_EDIT=Edituj
+SONG_MENU_MODI=Pevaj Modi
+SONG_MENU_CANCEL=Nazad
+
+SONG_MENU_NAME_PLAYLIST=Meni Pesme
+SONG_MENU_PLAYLIST_ADD=Dodaj Pesmu
+SONG_MENU_PLAYLIST_DEL=Obrisi Pesmu
+
+SONG_MENU_NAME_PLAYLIST_ADD=Dodaj Pesmu
+SONG_MENU_PLAYLIST_ADD_NEW=na novu listu
+SONG_MENU_PLAYLIST_ADD_EXISTING=na postojecu listu
+SONG_MENU_PLAYLIST_NOEXISTING=Nema dostupnih lista
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nova Lista
+SONG_MENU_PLAYLIST_NEW_CREATE=Napravi
+SONG_MENU_PLAYLIST_NEW_UNNAMED=BezNaziva
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Zaista Obrisati?
+SONG_MENU_YES=Da
+SONG_MENU_NO=Ne
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Otvori Listu
+SONG_MENU_PLAYLIST_LOAD=otvori
+SONG_MENU_PLAYLIST_DELCURRENT=obrisi Trenutnu Listu
+
+SONG_MENU_NAME_PLAYLIST_DEL=Obrisi listu?
+
+SONG_MENU_NAME_PARTY_MAIN=Timski Meni
+SONG_MENU_JOKER=Dzoker
+
+SONG_MENU_NAME_PARTY_JOKER=uzmi dzokera
+
+SONG_JUMPTO_DESC=trazi pesmu
+SONG_JUMPTO_TYPE_DESC=Trazi:
+SONG_JUMPTO_TYPE1=Sve
+SONG_JUMPTO_TYPE2=Naziv
+SONG_JUMPTO_TYPE3=Izvodjac
+SONG_JUMPTO_SONGSFOUND=%d Pesma(pesama) nadjeno
+SONG_JUMPTO_NOSONGSFOUND=Nema nadjenih pesama
+SONG_JUMPTO_HELP=Upisi tekst koji trazis
+SONG_JUMPTO_CATTEXT=Search for: %s
+
+PARTY_MODE=timski mod
+PARTY_DIFFICULTY=Tezina
+PARTY_PLAYLIST=Mod Liste Pesama
+PARTY_PLAYLIST_ALL=Sve Pesme
+PARTY_PLAYLIST_CATEGORY=Direktorijum
+PARTY_PLAYLIST_PLAYLIST=Lista Pesama
+PARTY_TEAMS=Timovi
+PARTY_TEAMS_PLAYER1=Igrac Tim1
+PARTY_TEAMS_PLAYER2=Igrac Tim2
+PARTY_TEAMS_PLAYER3=Igrac Tim3
+
+PARTY_LEGEND_CONTINUE=nastavi
+
+PARTY_OPTIONS_DESC=podesavanja za timsku igru
+PARTY_OPTIONS_WHEREAMI=Timske Opcije
+
+PARTY_PLAYER_DESC=unesi imena igraca i timova!
+PARTY_PLAYER_WHEREAMI=Imena Timova
+PARTY_PLAYER_ENTER_NAME=unesi imena
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=zapocni timsku igru
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=sledeci igraci za mikrofonom
+PARTY_ROUND_WHEREAMI=Timska Sledeca Runda
+PARTY_ROUND_LEGEND_CONTINUE=pocni rundu
+
+PARTY_SONG_WHEREAMI=Timski Izbor Pesama
+PARTY_SONG_LEGEND_CONTINUE=povaj
+PARTY_SONG_MENU=timski meni
+
+PARTY_SCORE_DESC=rezultat poslednje runde
+PARTY_SCORE_WHEREAMI=Timski Poeni
+
+PARTY_WIN_DESC=pobednik timske igre
+PARTY_WIN_WHEREAMI=Timski Pobednik
+PARTY_WIN_LEGEND_CONTINUE=nazad u glavni meni
+
+PARTY_ROUND=Runda
+PARTY_ROUND_WINNER=Pobednik
+PARTY_NOTPLAYEDYET=nije jos igrao
+PARTY_NOBODY=niko
+NEXT_ROUND=Sledeca runda:
+
+PARTY_DISMISSED=Otpusten!
+PARTY_SCORE_WINS=%s 
+PARTY_SCORE_WINS2=Pobedio!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Drzi liniju
+MODE_HOLDTHELINE_DESC=Ne budi losiji nego sto ti strelica pokazuje.
+
+MODE_5000POINTS_NAME=Do 5000
+MODE_5000POINTS_DESC=Ko stigne prvi do 5000 poena pobedjuje.
+
+MODE_DUEL_NAME=Duel
+MODE_DUEL_DESC=Pevaj duel do 10000 poena.
+
+;TODO: MODE_TEAMDUEL_NAME=Team Duell
+;TODO: MODE_TEAMDUEL_DESC=Pass The Mic!
+
+MODE_BLIND_NAME=Slepi Mod
+MODE_BLIND_DESC=Duel bez gledanja nota.
+
+STAT_MAIN=Statistike
+STAT_MAIN_DESC=Generalne
+STAT_MAIN_WHEREAMI=Statistike
+
+STAT_OVERVIEW_INTRO=%0:s Statistike.  \n Poslednji reset bio je %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Pesme(%3:d sa Videom), gde su %1:d vec igrane  i %2:d nisu jos igrane.\n Najpopularnija pesma je %5:s sa %4:s.
+STAT_OVERVIEW_PLAYER=Od poslednjeg reseta bilo je %0:d razlicitih igraca.\n Najbolji igrac je %1:s sa prosecnim rezultatom od %2:d poena.\n %3:s je imao najveci rezultat sa %4:d poena.
+
+;TODO: STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statistike
+STAT_DETAIL_WHEREAMI=Detalji Statistike
+
+STAT_NEXT=Sledeca Strana
+STAT_PREV=Prethodna Strana
+STAT_REVERSE=Obrnuti Redosled
+STAT_PAGE=Seite %0:d of %1:d strana\n (%2:d od %3:d unosa)
+
+STAT_DESC_SCORES=NajboljiRezultati
+STAT_DESC_SCORES_REVERSED=NajgoriRezultati
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s] \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Najbolji Pevaci
+STAT_DESC_SINGERS_REVERSED=Najgori Pevaci
+STAT_FORMAT_SINGERS=%0:s \n Prosecan Rezultat: %1:d
+
+STAT_DESC_SONGS=Najpopularnije Pesme
+STAT_DESC_SONGS_REVERSED=Najmanje Popularne Pesme
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx pevano
+
+STAT_DESC_BANDS=Najpopularniji Bendovi
+STAT_DESC_BANDS_REVERSED=Najmanje Popularni Bendovi
+STAT_FORMAT_BANDS=%0:s \n %1:dx Pevano
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Greska
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Pitanje
+MSG_QUIT_USDX=Stvarno napustate UltraStar?
+MSG_END_PARTY=Stvarno napustate Timski Mod?
+
+ERROR_NO_SONGS=Nema ucitanih pesama
+ERROR_NO_PLUGINS=Nema ucitanih plugin-ova
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Pesma se ne moze ucitati.
+;TODO: ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Song could not be loaded: File not found
+;TODO: ERROR_CORRUPT_SONG_NO_NOTES=Song could not be loaded: Can''t find any notes
+;TODO: ERROR_CORRUPT_SONG_NO_BREAKS=Song could not be loaded: Can''t find any linebreaks
+;TODO: ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Song could not be loaded: Error parsing line %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: SING_SCORE_HIT_ARTIST=Hit Pevac
+;UNUSED: PARTY_ROUNDS=Runde
diff --git a/songmanagement/game/languages/Slovak.ini b/songmanagement/game/languages/Slovak.ini
new file mode 100644
index 00000000..8ad15e0c
--- /dev/null
+++ b/songmanagement/game/languages/Slovak.ini
@@ -0,0 +1,443 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=... nahráva sa hra !
+
+SING_CHOOSE_MODE=vyberte si z možností
+SING_SING=Hra
+SING_SING_DESC=sólo alebo duet
+
+SING_MULTI=Párty
+SING_MULTI_DESC=párty-mód
+
+SING_TOOLS=Nástroje
+
+SING_STATS=štatistika
+SING_STATS_DESC=zobraziť štatistiku
+
+SING_EDITOR=editor
+SING_EDITOR_DESC=vytvorte si vlastnú skladbu
+
+SING_GAME_OPTIONS=nastavenia
+SING_GAME_OPTIONS_DESC=nastavenia hry
+
+SING_EXIT=Koniec
+SING_EXIT_DESC=návrat do systému
+
+SING_OPTIONS=nastavenia
+SING_OPTIONS_DESC=zmeniť nastavenia
+SING_OPTIONS_WHEREAMI=Nastavenia
+
+SING_OPTIONS_GAME=hra
+SING_OPTIONS_GRAPHICS=grafika
+SING_OPTIONS_SOUND=zvuk
+SING_OPTIONS_LYRICS=text
+SING_OPTIONS_THEMES=témy
+SING_OPTIONS_RECORD=mikrofón
+SING_OPTIONS_ADVANCED=iné
+SING_OPTIONS_EXIT=späť
+
+SING_OPTIONS_GAME_WHEREAMI=Nastavenia hry
+SING_OPTIONS_GAME_DESC=všeobecné nastavenia
+SING_OPTIONS_GAME_PLAYERS=Počet hráčov
+SING_OPTIONS_GAME_DIFFICULTY=Obtiažnosť
+SING_OPTIONS_GAME_LANGUAGE=Jazyk
+SING_OPTIONS_GAME_TABS=Kategórie
+SING_OPTIONS_GAME_SORTING=Zoradenie
+SING_OPTIONS_GAME_DEBUG=Debug mód
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Grafika
+SING_OPTIONS_GRAPHICS_DESC=nastavenie grafických detailov
+SING_OPTIONS_GRAPHICS_RESOLUTION=Rozlíšenie
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Celá obrazovka
+SING_OPTIONS_GRAPHICS_DEPTH=Far. hĺbka
+;TODO: SING_OPTIONS_GRAPHICS_VISUALIZER=Visualization
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Osciloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Čiarový Bonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Zobrazenie videa
+
+SING_OPTIONS_SOUND_WHEREAMI=Zvuk
+SING_OPTIONS_SOUND_DESC=nastavenie zvuku
+;TODO: SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Microphone Playback
+;TODO: SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Background music
+SING_OPTIONS_SOUND_MIC_BOOST=Zosilnenie mikrof.
+SING_OPTIONS_SOUND_CLICK_ASSIST=Pomocný klik
+SING_OPTIONS_SOUND_BEAT_CLICK=Rytmický klik
+SING_OPTIONS_SOUND_THRESHOLD=Prah počuteľ.
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Mód dvoch hráčov
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Náhľad(volume)
+SING_OPTIONS_SOUND_PREVIEWFADING=Prechod skladieb
+
+SING_OPTIONS_LYRICS_WHEREAMI=Text
+SING_OPTIONS_LYRICS_DESC=nastavenia zobrazovania textov piesní
+SING_OPTIONS_LYRICS_FONT=Písmo
+SING_OPTIONS_LYRICS_EFFECT=Efekt zvýraznenia
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmizácia
+;TODO: SING_OPTIONS_LYRICS_NOTELINES=Staves
+
+SING_OPTIONS_THEMES_WHEREAMI=Témy
+SING_OPTIONS_THEMES_DESC=zmena témy
+SING_OPTIONS_THEMES_THEME=Téma
+SING_OPTIONS_THEMES_SKIN=Vzhľad
+SING_OPTIONS_THEMES_COLOR=Farba
+
+SING_OPTIONS_RECORD_WHEREAMI=Mikrofón
+SING_OPTIONS_RECORD_DESC=nastavenie mikrofónu
+SING_OPTIONS_RECORD_CARD=Zvuková karta
+SING_OPTIONS_RECORD_INPUT=Vstup
+SING_OPTIONS_RECORD_CHANNEL=Kanál
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Iné
+SING_OPTIONS_ADVANCED_DESC=rozširujúce nastavenia
+SING_OPTIONS_ADVANCED_EFFECTSING=Efekty pri speve
+SING_OPTIONS_ADVANCED_SCREENFADE=Jemný prechod
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animácia loading(u)
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Potvrdzovanie
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus za riadok
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Po zvolení skladby
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto PartyMenu
+
+;TODO: SING_EDIT=Editor
+;TODO: SING_EDIT_MENU_DESCRIPTION=create your own song
+
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Import text from midi file
+;TODO: SING_EDIT_BUTTON_DESCRIPTION_EXIT=back
+;TODO: SING_EDIT_BUTTON_CONVERT=Import
+;TODO: SING_EDIT_BUTTON_EXIT=back
+
+;TODO: SING_EDIT_NAVIGATE=navigate
+;TODO: SING_EDIT_SELECT=select
+;TODO: SING_EDIT_EXIT=back
+
+SING_LEGEND_SELECT=výber
+SING_LEGEND_NAVIGATE=navigácia
+SING_LEGEND_CONTINUE=pokračovať
+SING_LEGEND_ESC=späť
+
+SING_PLAYER_DESC=zadajte meno hráča(ov)
+SING_PLAYER_WHEREAMI=Mená hráčov
+SING_PLAYER_ENTER_NAME=zadávanie mena
+
+SING_DIFFICULTY_DESC=Vyberte obtiažnosť
+SING_DIFFICULTY_WHEREAMI=Obtiažnosť
+SING_DIFFICULTY_CONTINUE=pokračovať
+SING_EASY=Ľahká
+SING_MEDIUM=Stredná
+SING_HARD=Ťažká
+
+SING_SONG_SELECTION_DESC=Vyberte skladbu
+SING_SONG_SELECTION_WHEREAMI=výber skladby
+SING_SONG_SELECTION_GOTO=choď na ..
+SING_SONG_SELECTION=výber skladby
+SING_SONG_SELECTION_MENU=menu
+SING_SONG_SELECTION_PLAYLIST=playlist
+SING_SONGS_IN_CAT=Skladba
+PLAYLIST_CATTEXT=Playlist: %s
+
+SING_TIME=Čas
+SING_TOTAL=celkovo
+SING_MODE=spievať sólo
+SING_NOTES=noty
+SING_GOLDEN_NOTES=zlaté noty
+SING_PHRASE_BONUS=bonus za riadok
+
+SING_MENU=Hlavné Menu
+
+SONG_SCORE=hodnotenie
+SONG_SCORE_WHEREAMI=Skóre
+
+SING_SCORE_TONE_DEAF=Antitalent
+SING_SCORE_AMATEUR=Amatér
+;TODO: SING_SCORE_WANNABE=Wannabe
+;TODO: SING_SCORE_HOPEFUL=Hopeful
+SING_SCORE_RISING_STAR=Vychádzajúca hviezda
+SING_SCORE_LEAD_SINGER=Spevák
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=najlepších 5
+SING_TOP_5_CHARTS_WHEREAMI=top 5
+SING_TOP_5_CHARTS_CONTINUE=pre výber skladby
+;TODO: SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=neskutočné!
+POPUP_AWESOME=paráda!
+POPUP_GREAT=super!
+POPUP_GOOD=dobré!
+POPUP_NOTBAD=nie zlé!
+POPUP_BAD=zle!
+POPUP_POOR=bieda!
+POPUP_AWFUL=otrasné!
+
+IMPLODE_GLUE1=, 
+IMPLODE_GLUE2= a 
+
+SONG_MENU_NAME_MAIN=Výber hudby
+SONG_MENU_PLAY=Štart
+SONG_MENU_CHANGEPLAYERS=Iný hráč
+SONG_MENU_EDIT=Uprav
+SONG_MENU_MODI=Sing a Modi
+SONG_MENU_CANCEL=Zrušiť
+
+SONG_MENU_NAME_PLAYLIST=Skladby
+SONG_MENU_PLAYLIST_ADD=Pridaj skladbu
+SONG_MENU_PLAYLIST_DEL=Zmaž skladbu
+
+SONG_MENU_NAME_PLAYLIST_ADD=Pridaj Skladbu
+SONG_MENU_PLAYLIST_ADD_NEW=do nového playlistu
+SONG_MENU_PLAYLIST_ADD_EXISTING=do existujúceho playlistu
+SONG_MENU_PLAYLIST_NOEXISTING=Nie je dostupný žiadny playlist
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nový Playlist
+SONG_MENU_PLAYLIST_NEW_CREATE=Vytvor
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Bez mena
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Skutočne Zmazať ?
+SONG_MENU_YES=Áno
+SONG_MENU_NO=Nie
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Načítaj Playlist
+SONG_MENU_PLAYLIST_LOAD=načítaj
+SONG_MENU_PLAYLIST_DELCURRENT=zmaž tento Playlist
+
+SONG_MENU_NAME_PLAYLIST_DEL=Zmazať Playlist?
+
+SONG_MENU_NAME_PARTY_MAIN=Party Menu
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=použi jokera
+
+SONG_JUMPTO_DESC=hľadaj skladbu
+SONG_JUMPTO_TYPE_DESC=hľadaj:
+SONG_JUMPTO_TYPE1=všade
+SONG_JUMPTO_TYPE2=v názve skladby
+SONG_JUMPTO_TYPE3=v mene autora
+SONG_JUMPTO_SONGSFOUND=%d skladieb vyhovuje filtru
+SONG_JUMPTO_NOSONGSFOUND=Žiadna skladba
+SONG_JUMPTO_HELP=Napíš kľúčové slovo pre hľadanie
+SONG_JUMPTO_CATTEXT=Hľadaj: %s
+
+PARTY_MODE=párty mód
+PARTY_DIFFICULTY=Obtiažnosť
+PARTY_PLAYLIST=Skladby z playlistu
+PARTY_PLAYLIST_ALL=Všetky skladby
+PARTY_PLAYLIST_CATEGORY=Kategória
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_TEAMS=Počet tímov
+PARTY_TEAMS_PLAYER1=Hráčov v Tíme 1
+PARTY_TEAMS_PLAYER2=Hráčov v Tíme 2
+PARTY_TEAMS_PLAYER3=Hráčov v Tíme 3
+
+PARTY_LEGEND_CONTINUE=pokračovať
+
+PARTY_OPTIONS_DESC=nastavenia pre párty-mód
+PARTY_OPTIONS_WHEREAMI=Párty nastavenia
+
+PARTY_PLAYER_DESC=Zadajte mená tímov a hráčov!
+PARTY_PLAYER_WHEREAMI=Párty mená
+PARTY_PLAYER_ENTER_NAME=zadajte mená
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=Pokračovať
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=párty pre hráčov
+PARTY_ROUND_WHEREAMI=List párty disciplín
+PARTY_ROUND_LEGEND_CONTINUE=Štart disciplíny
+
+PARTY_SONG_WHEREAMI=Párty - Výver Skladby 	 
+PARTY_SONG_LEGEND_CONTINUE=Štart 	 
+PARTY_SONG_MENU=party menu
+
+PARTY_SCORE_DESC=skóre posledného kola
+PARTY_SCORE_WHEREAMI=Párty skóre
+
+PARTY_WIN_DESC=Víťaz párty
+PARTY_WIN_WHEREAMI=Stupeň víťazov
+PARTY_WIN_LEGEND_CONTINUE=späť do hlavného menu
+
+PARTY_ROUND=Kolo
+PARTY_ROUND_WINNER=Víťaz
+PARTY_NOTPLAYEDYET=nehralo
+PARTY_NOBODY=ani jedno družstvo
+NEXT_ROUND=Ďalšie kolo:
+
+PARTY_DISMISSED=Ukončené !
+PARTY_SCORE_WINS=%s 
+PARTY_SCORE_WINS2=víťaz tohto kola
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Superstar
+MODE_HOLDTHELINE_DESC=nesmieš klesnúť pod hranicu ukazovateľa úspešnosti
+
+MODE_5000POINTS_NAME=Po 5000
+MODE_5000POINTS_DESC=kto prvý získa 5000 bodov sa stane víťazom
+
+MODE_DUEL_NAME=Duel
+MODE_DUEL_DESC=spievaj, kým nedosiahneš 10000 bodov
+
+MODE_TEAMDUEL_NAME=Duel Tímov
+MODE_TEAMDUEL_DESC=každý hráč sa vystrieda za mikrofónom
+
+MODE_BLIND_NAME=Slepý
+MODE_BLIND_DESC=neuvidíš noty pre hlas
+
+STAT_MAIN=Štatistika
+STAT_MAIN_DESC=Všeobecne
+STAT_MAIN_WHEREAMI=Štatistiky
+
+STAT_OVERVIEW_INTRO=%0:s štatistika  \n Štatistika od %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=SKLADBY \n Celkove: %0:d z toho %3:d s videom\n Počet už hraných: %1:d \n Počet nehraných: %2:d \n Najhranejšia skladba: %5:s od %4:s
+STAT_OVERVIEW_PLAYER=HRÁČI \n Celkove: %0:d rôznych hráčov.\n Najlepší hráč: %1:s (%2:d - priemer bodov)\n Najvyššie skóre: %3:s (%4:d bodov)
+
+;TODO: STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Štatistiky
+STAT_DETAIL_WHEREAMI=Podrobná štatistika
+
+STAT_NEXT=Ďalšia strana
+STAT_PREV=Predošlá strana
+STAT_REVERSE=Otoč poradie
+STAT_PAGE=%0:d. z %1:d strán\n (%2:d z %3:d položiek)
+
+STAT_DESC_SCORES=Najvyššie skóre
+STAT_DESC_SCORES_REVERSED=Najhoršie skóre
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s] \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Najlepší speváci
+STAT_DESC_SINGERS_REVERSED=Najhorší speváci
+STAT_FORMAT_SINGERS=%0:s \n Priemer skóre: %1:d
+
+STAT_DESC_SONGS=Najhranejšie skladby
+STAT_DESC_SONGS_REVERSED=Najmenej hrané skladby
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx spievaná
+
+STAT_DESC_BANDS=Najhranejšia kapela
+STAT_DESC_BANDS_REVERSED=Najmenej hraná kapela
+STAT_FORMAT_BANDS=%0:s \n %1:dx spievaná
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Chyba
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Otázka
+MSG_QUIT_USDX=Skutočne chcete skončiť UltraStar?
+MSG_END_PARTY=Skutočne chcete skončit Párty Mód ?
+
+ERROR_NO_SONGS=Žiadna skladba
+ERROR_NO_PLUGINS=Žiadny zásuvný modul
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Skladbu sa nepodarilo nahrať.
+;TODO: ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Song could not be loaded: File not found
+;TODO: ERROR_CORRUPT_SONG_NO_NOTES=Song could not be loaded: Can''t find any notes
+;TODO: ERROR_CORRUPT_SONG_NO_BREAKS=Song could not be loaded: Can''t find any linebreaks
+;TODO: ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Song could not be loaded: Error parsing line %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: SING_SCORE_HIT_ARTIST=Star 
+;UNUSED: PARTY_ROUNDS=Počet kôl
diff --git a/songmanagement/game/languages/Slovenian.ini b/songmanagement/game/languages/Slovenian.ini
new file mode 100644
index 00000000..9a299fbf
--- /dev/null
+++ b/songmanagement/game/languages/Slovenian.ini
@@ -0,0 +1,442 @@
+[Text]
+;TODO: OPTION_VALUE_CATALAN=Catalan
+;TODO: OPTION_VALUE_CROATIAN=Croatian
+;TODO: OPTION_VALUE_CZECH=Czech
+;TODO: OPTION_VALUE_DANISH=Danish
+;TODO: OPTION_VALUE_DUTCH=Dutch
+;TODO: OPTION_VALUE_ENGLISH=English
+;TODO: OPTION_VALUE_EUSKARA=Euskara
+;TODO: OPTION_VALUE_FINNISH=Finnish
+;TODO: OPTION_VALUE_FRENCH=French
+;TODO: OPTION_VALUE_GERMAN=German
+;TODO: OPTION_VALUE_GREEK=Greek
+;TODO: OPTION_VALUE_HUNGARIAN=Hungarian
+;TODO: OPTION_VALUE_ICELANDIC=Icelandic
+;TODO: OPTION_VALUE_ITALIAN=Italian
+;TODO: OPTION_VALUE_JAPANESE=Japanese
+;TODO: OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+;TODO: OPTION_VALUE_NORWEGIAN=Norwegian
+;TODO: OPTION_VALUE_POLISH=Polish
+;TODO: OPTION_VALUE_PORTUGUESE=Portuguese
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+;TODO: OPTION_VALUE_SERBIAN=Serbian
+;TODO: OPTION_VALUE_SLOVAK=Slovak
+;TODO: OPTION_VALUE_SLOVENIAN=Slovenian
+;TODO: OPTION_VALUE_SPANISH=Spanish
+;TODO: OPTION_VALUE_SWEDISH=Swedish
+
+;TODO: OPTION_VALUE_EASY=Easy
+;TODO: OPTION_VALUE_MEDIUM=Medium
+;TODO: OPTION_VALUE_HARD=Hard
+
+;TODO: OPTION_VALUE_ON=On
+;TODO: OPTION_VALUE_OFF=Off
+
+;TODO: OPTION_VALUE_EDITION=Edition
+;TODO: OPTION_VALUE_GENRE=Genre
+;TODO: OPTION_VALUE_LANGUAGE=Language
+;TODO: OPTION_VALUE_FOLDER=Folder
+;TODO: OPTION_VALUE_TITLE=Title
+;TODO: OPTION_VALUE_ARTIST=Artist
+;TODO: OPTION_VALUE_TITLE2=Title2
+;TODO: OPTION_VALUE_ARTIST2=Artist2
+
+;TODO: OPTION_VALUE_WHENNOVIDEO=When No Video
+
+;TODO: OPTION_VALUE_SMALL=Small
+;TODO: OPTION_VALUE_BIG=Big
+
+;TODO: OPTION_VALUE_HALF=Half
+;TODO: OPTION_VALUE_FULL_VID=Full (Video)
+;TODO: OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+
+;TODO: OPTION_VALUE_AUTO=Auto
+;TODO: OPTION_VALUE_SEC=Second
+;TODO: OPTION_VALUE_SECS=Seconds
+
+;TODO: OPTION_VALUE_PLAIN=Plain
+;TODO: OPTION_VALUE_OLINE1=OLine1
+;TODO: OPTION_VALUE_OLINE2=OLine2
+
+;TODO: OPTION_VALUE_SIMPLE=Simple
+;TODO: OPTION_VALUE_ZOOM=Zoom
+;TODO: OPTION_VALUE_SLIDE=Slide
+;TODO: OPTION_VALUE_BALL=Ball
+;TODO: OPTION_VALUE_SHIFT=Shift
+
+;TODO: OPTION_VALUE_EURO=Euro
+;TODO: OPTION_VALUE_JAPAN=Japan
+;TODO: OPTION_VALUE_AMERICAN=American
+
+;TODO: OPTION_VALUE_BLUE=Blue
+;TODO: OPTION_VALUE_GREEN=Green
+;TODO: OPTION_VALUE_PINK=Pink
+;TODO: OPTION_VALUE_RED=Red
+;TODO: OPTION_VALUE_VIOLET=Violet
+;TODO: OPTION_VALUE_ORANGE=Orange
+;TODO: OPTION_VALUE_YELLOW=Yellow
+;TODO: OPTION_VALUE_BROWN=Brown
+;TODO: OPTION_VALUE_BLACK=Black
+
+;TODO: OPTION_VALUE_SING=Sing
+;TODO: OPTION_VALUE_SELECT_PLAYERS=Select Players
+;TODO: OPTION_VALUE_OPEN_MENU=Open Menu
+
+;TODO: OPTION_VALUE_HARDWARE_CURSOR=Hardware Cursor
+;TODO: OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Nalaganje...
+
+SING_CHOOSE_MODE=izberi nacin
+SING_SING=poj
+SING_SING_DESC=poj sam ali v duetu
+
+SING_MULTI=zabava
+SING_MULTI_DESC=poj v nacinu zabave
+
+SING_TOOLS=orodja
+
+SING_STATS=statistika
+SING_STATS_DESC=poglej statistiko
+
+SING_EDITOR=urednik
+SING_EDITOR_DESC=izdelaj svoje pesmi
+
+SING_GAME_OPTIONS=nastavitve igre
+SING_GAME_OPTIONS_DESC=spremeni nastavitve igre
+
+SING_EXIT=izhod
+SING_EXIT_DESC=izhod iz igre
+
+SING_OPTIONS=nastavitve
+SING_OPTIONS_DESC=spremeni nastavitve
+SING_OPTIONS_WHEREAMI=Nastavitve
+
+SING_OPTIONS_GAME=igra
+SING_OPTIONS_GRAPHICS=izgled
+SING_OPTIONS_SOUND=zvok
+SING_OPTIONS_LYRICS=besedilo
+SING_OPTIONS_THEMES=tema
+SING_OPTIONS_RECORD=snemanje
+SING_OPTIONS_ADVANCED=napredno
+SING_OPTIONS_EXIT=nazaj
+
+SING_OPTIONS_GAME_WHEREAMI=Nastavitve Igre
+SING_OPTIONS_GAME_DESC=osnovne nastavitve
+SING_OPTIONS_GAME_PLAYERS=Igralci
+SING_OPTIONS_GAME_DIFFICULTY=Težavnost
+SING_OPTIONS_GAME_LANGUAGE=Jezik
+SING_OPTIONS_GAME_TABS=Mape
+SING_OPTIONS_GAME_SORTING=Sortiranje
+SING_OPTIONS_GAME_DEBUG=Odpravljanje hrošcev
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Nastavitve prikaza
+SING_OPTIONS_GRAPHICS_DESC=nastavitve prikaza
+SING_OPTIONS_GRAPHICS_RESOLUTION=Locljivost
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Celozaslonski nacin
+SING_OPTIONS_GRAPHICS_DEPTH=Globina
+SING_OPTIONS_GRAPHICS_VISUALIZER=Vizualizacija
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Osciloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Vrsticni bonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Velikost videa
+
+SING_OPTIONS_SOUND_WHEREAMI=Nastavitve zvoka
+SING_OPTIONS_SOUND_DESC=nastavitve zvoka
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Mikrofonski Playback
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Glasbena podlaga
+SING_OPTIONS_SOUND_MIC_BOOST=Ojacitev mikrofona
+SING_OPTIONS_SOUND_CLICK_ASSIST=Asistent klikanja
+SING_OPTIONS_SOUND_BEAT_CLICK=Klikanje po ritmu
+SING_OPTIONS_SOUND_THRESHOLD=Prag
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Nacin za dva igralca
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Glasnost predogleda
+SING_OPTIONS_SOUND_PREVIEWFADING=narašcanje glasnosti
+
+SING_OPTIONS_LYRICS_WHEREAMI=Nastavitve besedila
+SING_OPTIONS_LYRICS_DESC=nastavitve besedila
+SING_OPTIONS_LYRICS_FONT=Pisava
+SING_OPTIONS_LYRICS_EFFECT=Ucinek
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmizacija
+SING_OPTIONS_LYRICS_NOTELINES=Notno crtovje
+
+SING_OPTIONS_THEMES_WHEREAMI=Nastavitve tem
+SING_OPTIONS_THEMES_DESC=nastavitve teme
+SING_OPTIONS_THEMES_THEME=Tema
+SING_OPTIONS_THEMES_SKIN=Izgled
+SING_OPTIONS_THEMES_COLOR=Barva
+
+SING_OPTIONS_RECORD_WHEREAMI=Nastavitve snemanja
+SING_OPTIONS_RECORD_DESC=nastavitve mikrofona
+SING_OPTIONS_RECORD_CARD=Vir zvoka
+SING_OPTIONS_RECORD_INPUT=Vhod
+SING_OPTIONS_RECORD_CHANNEL=Kanal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Napredne nastavitve
+SING_OPTIONS_ADVANCED_DESC=Napredne nastavitve
+SING_OPTIONS_ADVANCED_EFFECTSING=Pevski efekt
+SING_OPTIONS_ADVANCED_SCREENFADE=Zamegljevanje prikaza
+SING_OPTIONS_ADVANCED_LOADANIMATION=Zacetna animacija
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Zašcitno vprašanje
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus za vrstico
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Po izboru pesmi
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Samodejni nacin Zabava
+
+SING_EDIT=Urednik
+SING_EDIT_MENU_DESCRIPTION=Izdelaj lastno pesem
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Izvozi besedilo iz midi datoteke
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Nazaj
+SING_EDIT_BUTTON_CONVERT=Uvozi
+SING_EDIT_BUTTON_EXIT=Nazaj
+
+SING_EDIT_NAVIGATE=Navigacija
+SING_EDIT_SELECT=Izberi
+SING_EDIT_EXIT=Nazaj
+
+SING_LEGEND_SELECT=izberi
+SING_LEGEND_NAVIGATE=premik
+SING_LEGEND_CONTINUE=nadaljuj
+SING_LEGEND_ESC=nazaj
+
+SING_PLAYER_DESC=vpiši imena igralcev
+SING_PLAYER_WHEREAMI=Imena igralcev
+SING_PLAYER_ENTER_NAME=vnesi ime
+
+SING_DIFFICULTY_DESC=izberi težavnost
+SING_DIFFICULTY_WHEREAMI=Težavnost
+SING_DIFFICULTY_CONTINUE=k izbiri pesmi
+SING_EASY=Enostavno
+SING_MEDIUM=Srednje
+SING_HARD=Težko
+
+SING_SONG_SELECTION_DESC=izberi svojo pesem
+SING_SONG_SELECTION_WHEREAMI=Izbira pesmi
+SING_SONG_SELECTION_GOTO=pojdi na...
+SING_SONG_SELECTION=izbira pesmi
+SING_SONG_SELECTION_MENU=meni
+SING_SONG_SELECTION_PLAYLIST=seznam predvajanja
+SING_SONGS_IN_CAT=Pesmi
+PLAYLIST_CATTEXT=Lista: %s
+
+SING_TIME=CAS
+SING_TOTAL=skupaj
+SING_MODE=Petje
+SING_NOTES=note
+SING_GOLDEN_NOTES=zlate note
+SING_PHRASE_BONUS=bonus za vrstico
+
+SING_MENU=Glavni meni
+
+SONG_SCORE=rezultat petja
+SONG_SCORE_WHEREAMI=Rezultat
+
+SING_SCORE_TONE_DEAF=Gluhonem
+SING_SCORE_AMATEUR=Amater
+SING_SCORE_WANNABE=Igralec
+SING_SCORE_HOPEFUL=Nadebudnež
+SING_SCORE_RISING_STAR=Vzhajajoca zvezda
+SING_SCORE_LEAD_SINGER=Vodilni pevec
+SING_SCORE_SUPERSTAR=Superzvezda
+SING_SCORE_ULTRASTAR=Ultrazvezda
+
+SING_TOP_5_CHARTS=najboljših 5 pevcev
+SING_TOP_5_CHARTS_WHEREAMI=najboljših 5
+SING_TOP_5_CHARTS_CONTINUE=k izbiri pesmi
+;TODO: SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=popolno!
+POPUP_AWESOME=odlicno!
+POPUP_GREAT=zelo dobro!
+POPUP_GOOD=dobro!
+POPUP_NOTBAD=ni slabo!
+POPUP_BAD=slabo!
+POPUP_POOR=zelo slabo!
+POPUP_AWFUL=obupno!
+
+IMPLODE_GLUE1=, 
+IMPLODE_GLUE2= in 
+
+SONG_MENU_NAME_MAIN=meni pesmi
+SONG_MENU_PLAY=Poj
+SONG_MENU_CHANGEPLAYERS=Spremeni igralca
+SONG_MENU_EDIT=Uredi
+SONG_MENU_MODI=Poj "a Modi"
+SONG_MENU_CANCEL=Preklici
+
+SONG_MENU_NAME_PLAYLIST=Meni Pesem
+SONG_MENU_PLAYLIST_ADD=Dodaj pesem
+SONG_MENU_PLAYLIST_DEL=Izbriši pesem
+
+SONG_MENU_NAME_PLAYLIST_ADD=Dodaj pesem
+SONG_MENU_PLAYLIST_ADD_NEW=dodaj nov seznam
+SONG_MENU_PLAYLIST_ADD_EXISTING=dodaj shranjen seznam
+SONG_MENU_PLAYLIST_NOEXISTING=Ni seznamov
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nov seznam
+SONG_MENU_PLAYLIST_NEW_CREATE=Ustvari
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Neimenovan
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Res izbrišem?
+SONG_MENU_YES=Da
+SONG_MENU_NO=Ne
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Odpri seznam
+SONG_MENU_PLAYLIST_LOAD=odpri
+SONG_MENU_PLAYLIST_DELCURRENT=izbriši trenuten seznam
+
+SONG_MENU_NAME_PLAYLIST_DEL=Izbrišem seznam?
+
+SONG_MENU_NAME_PARTY_MAIN=Meni Zabava
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=izkoristi jokerja
+
+SONG_JUMPTO_DESC=poišci pesem
+SONG_JUMPTO_TYPE_DESC=Isci po:
+SONG_JUMPTO_TYPE1=Vse
+SONG_JUMPTO_TYPE2=Naslov
+SONG_JUMPTO_TYPE3=Avtor
+SONG_JUMPTO_SONGSFOUND=%d pesmi najdenih
+SONG_JUMPTO_NOSONGSFOUND=Ne najdem
+SONG_JUMPTO_HELP=Vpiši besedilo za iskanje
+SONG_JUMPTO_CATTEXT=Išci po: %s
+
+PARTY_MODE=zabava
+PARTY_DIFFICULTY=Težavnost
+PARTY_PLAYLIST=Izbor
+PARTY_PLAYLIST_ALL=Vse pesmi
+PARTY_PLAYLIST_CATEGORY=Mapa
+PARTY_PLAYLIST_PLAYLIST=Seznam
+PARTY_TEAMS=Ekipe
+PARTY_TEAMS_PLAYER1=Igralec Ekipa1
+PARTY_TEAMS_PLAYER2=Igralec Ekipa2
+PARTY_TEAMS_PLAYER3=Igralec Ekipa3
+
+PARTY_LEGEND_CONTINUE=nadaljuj
+
+PARTY_OPTIONS_DESC=nastavitve za nacin zabave
+PARTY_OPTIONS_WHEREAMI=nastavitve zabave
+
+PARTY_PLAYER_DESC=vpiši igralce in imena ekip!
+PARTY_PLAYER_WHEREAMI=Imena
+PARTY_PLAYER_ENTER_NAME=vpiši imena
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=zacni zabavo
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=naslednji igralec k mikrofonu
+PARTY_ROUND_WHEREAMI=Naslednja runda
+PARTY_ROUND_LEGEND_CONTINUE=zacni rundo
+
+PARTY_SONG_WHEREAMI=Izbor pesmi - Zabava
+PARTY_SONG_LEGEND_CONTINUE=poj
+PARTY_SONG_MENU=meni Zabava
+
+PARTY_SCORE_DESC=tocke zadnje runde
+PARTY_SCORE_WHEREAMI=Tocke v zabavi
+
+PARTY_WIN_DESC=Zmagovalec
+PARTY_WIN_WHEREAMI=Zmagovalec
+PARTY_WIN_LEGEND_CONTINUE=nazaj k glavnemu meniju
+
+PARTY_ROUND=Runda
+PARTY_ROUND_WINNER=Zmagovalec
+PARTY_NOTPLAYEDYET=neizvedeno
+PARTY_NOBODY=nobeden
+NEXT_ROUND=Naslednja runda:
+
+PARTY_DISMISSED=Zakljucena!
+PARTY_SCORE_WINS=%s 
+PARTY_SCORE_WINS2=zmaga!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Zdrži nivo
+MODE_HOLDTHELINE_DESC=Ne poj slabše, kot kaže kazalnik na števcu za ocenjevanje.
+
+MODE_5000POINTS_NAME=Do 5000
+MODE_5000POINTS_DESC=Kdor prvi doseže 5000 tock, zmaga.
+
+MODE_DUEL_NAME=Dvoboj
+MODE_DUEL_DESC=Tekmovanje do 10000 tock.
+
+MODE_TEAMDUEL_NAME=Ekipni dvoboj
+MODE_TEAMDUEL_DESC=Podaj mikrofon!
+
+MODE_BLIND_NAME=Slepi dvoboj
+MODE_BLIND_DESC=Dvoboj brez prikaza not.
+
+STAT_MAIN=Statika
+STAT_MAIN_DESC=Splošno
+STAT_MAIN_WHEREAMI=Statistika
+
+STAT_OVERVIEW_INTRO=%0:s Statistika.  \n Nazadnje ponastavljeno %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Pesmi(%3:d z videom), od katerih je bilo %1:d že zapetih  in %2:d ne.\n Najbolj priljubljena pesem je %5:s od %4:s.
+STAT_OVERVIEW_PLAYER=Od zadnje ponastavitve statistike je igro igralo %0:d igralcev.\n Najboljši/a je %1:s s povprecnim rezultatom %2:d tock.\n %3:s je dosegel/la najboljši rezultat s %4:d tockami.
+
+;TODO: STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statistika
+STAT_DETAIL_WHEREAMI=Podrobna statistika
+
+STAT_NEXT=Naslednja stran
+STAT_PREV=Prejšnja stran
+STAT_REVERSE=Obratni vrstni red
+STAT_PAGE=Stran %0:d od %1:d strani\n (%2:d od %3:d zapisov)
+
+STAT_DESC_SCORES=Najboljši rezultati
+STAT_DESC_SCORES_REVERSED=Najslabši rezultati
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s] \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Najboljši igralec
+STAT_DESC_SINGERS_REVERSED=Najslabši igralec
+STAT_FORMAT_SINGERS=%0:s \n povprecni rezultat: %1:d
+
+STAT_DESC_SONGS=Najbolj popularne pesmi
+STAT_DESC_SONGS_REVERSED=Najmanj popularne pesmi
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx igrano
+
+STAT_DESC_BANDS=Najbolj popularen izvajalec
+STAT_DESC_BANDS_REVERSED=Najmanj popularen izvajalec
+STAT_FORMAT_BANDS=%0:s \n %1:dx igrano
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Napaka
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Vprašanje
+MSG_QUIT_USDX=Želite zapustiti Ultrastar?
+MSG_END_PARTY=Koncam zabavo?
+
+ERROR_NO_SONGS=Ni pesmi: Naloži jih v mapo Songs
+ERROR_NO_PLUGINS=Ni vkljuckov
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Ne morem naložiti pesmi.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Ne morem naložiti pesmi: Ne najdem datoteke
+ERROR_CORRUPT_SONG_NO_NOTES=Ne morem naloziti pesmi: Ne najdem not.
+ERROR_CORRUPT_SONG_NO_BREAKS=Ne morem naložiti pesmi: Ne najdem prelomov vrstic.
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Ne morem naložiti pesmi: Napaka v parsanju vrstice %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: PARTY_ROUNDS=Število rund
diff --git a/songmanagement/game/languages/Spanish.ini b/songmanagement/game/languages/Spanish.ini
new file mode 100644
index 00000000..66511230
--- /dev/null
+++ b/songmanagement/game/languages/Spanish.ini
@@ -0,0 +1,443 @@
+[Text]
+OPTION_VALUE_CATALAN=Catalán
+OPTION_VALUE_CROATIAN=Croata
+OPTION_VALUE_CZECH=Checo
+OPTION_VALUE_DANISH=Danés
+OPTION_VALUE_DUTCH=Holandés
+OPTION_VALUE_ENGLISH=Inglés
+OPTION_VALUE_EUSKARA=Euskera
+OPTION_VALUE_FINNISH=Finlandés
+OPTION_VALUE_FRENCH=Francés
+OPTION_VALUE_GERMAN=Alemán
+OPTION_VALUE_GREEK=Griego
+OPTION_VALUE_HUNGARIAN=Húngaro
+OPTION_VALUE_ICELANDIC=Islándico
+OPTION_VALUE_ITALIAN=Italiano
+OPTION_VALUE_JAPANESE=Japonés
+OPTION_VALUE_LUXEMBOURGISH=Luxemburgués
+OPTION_VALUE_NORWEGIAN=Noruego
+OPTION_VALUE_POLISH=Polaco
+OPTION_VALUE_PORTUGUESE=Portugués
+;TODO: OPTION_VALUE_RUSSIAN=Russian
+OPTION_VALUE_SERBIAN=Serbio
+OPTION_VALUE_SLOVAK=Eslovaco
+OPTION_VALUE_SLOVENIAN=Esloveno
+OPTION_VALUE_SPANISH=Español
+OPTION_VALUE_SWEDISH=Sueco
+
+OPTION_VALUE_EASY=Fácil
+OPTION_VALUE_MEDIUM=Medio
+OPTION_VALUE_HARD=Difícil
+
+OPTION_VALUE_ON=Sí
+OPTION_VALUE_OFF=No
+
+OPTION_VALUE_EDITION=Edición
+OPTION_VALUE_GENRE=Género
+OPTION_VALUE_LANGUAGE=Idioma
+OPTION_VALUE_FOLDER=Carpeta
+OPTION_VALUE_TITLE=Título
+OPTION_VALUE_ARTIST=Artista
+OPTION_VALUE_TITLE2=Título2
+OPTION_VALUE_ARTIST2=Artista2
+
+OPTION_VALUE_WHENNOVIDEO=Si no hay video
+
+OPTION_VALUE_SMALL=Pequeño
+OPTION_VALUE_BIG=Grande
+
+OPTION_VALUE_HALF=Mitad
+OPTION_VALUE_FULL_VID=Completo (video)
+OPTION_VALUE_FULL_VID_BG=Completo (fondo y video)
+
+OPTION_VALUE_AUTO=Auto
+OPTION_VALUE_SEC=Segundo
+OPTION_VALUE_SECS=Segundos
+
+OPTION_VALUE_PLAIN=Sencillo
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Simple
+OPTION_VALUE_ZOOM=Acercar
+OPTION_VALUE_SLIDE=Deslizar
+OPTION_VALUE_BALL=Pelotita
+OPTION_VALUE_SHIFT=Saltar
+
+OPTION_VALUE_EURO=Europeo
+OPTION_VALUE_JAPAN=Japón
+OPTION_VALUE_AMERICAN=Americano
+
+OPTION_VALUE_BLUE=Azul
+OPTION_VALUE_GREEN=Verde
+OPTION_VALUE_PINK=Rosado
+OPTION_VALUE_RED=Rojo
+OPTION_VALUE_VIOLET=Violeta
+OPTION_VALUE_ORANGE=Naranja
+OPTION_VALUE_YELLOW=Amarillo
+OPTION_VALUE_BROWN=Marrón
+OPTION_VALUE_BLACK=Negro
+
+OPTION_VALUE_SING=Cantar
+OPTION_VALUE_SELECT_PLAYERS=Elegir jugadores
+OPTION_VALUE_OPEN_MENU=Abrir menú
+
+OPTION_VALUE_HARDWARE_CURSOR=Cursor por hardware
+OPTION_VALUE_SOFTWARE_CURSOR=Cursor por software 
+
+SING_LOADING=Cargando...
+
+SING_CHOOSE_MODE=Elige
+SING_SING=¡Canta!
+SING_SING_DESC=Juego rápido: cantar solo o en dueto
+
+SING_MULTI=Grupo
+SING_MULTI_DESC=Cantar en grupos
+
+SING_TOOLS=Utilidades
+
+SING_STATS=Estadísticas
+SING_STATS_DESC=Ver estadísticas
+
+SING_EDITOR=Editor
+SING_EDITOR_DESC=Crea tu propia canción
+
+SING_GAME_OPTIONS=Opciones
+SING_GAME_OPTIONS_DESC=Cambia las opciones del juego
+
+SING_EXIT=Salir
+SING_EXIT_DESC=Salir del juego
+
+SING_OPTIONS=Opciones
+SING_OPTIONS_DESC=Cambia las opciones
+SING_OPTIONS_WHEREAMI=Opciones
+
+SING_OPTIONS_GAME=Juego
+SING_OPTIONS_GRAPHICS=Gráficos
+SING_OPTIONS_SOUND=Sonido
+SING_OPTIONS_LYRICS=Letras
+SING_OPTIONS_THEMES=Apariencia
+SING_OPTIONS_RECORD=Micrófonos
+SING_OPTIONS_ADVANCED=Avanzado
+SING_OPTIONS_EXIT=Atrás
+
+SING_OPTIONS_GAME_WHEREAMI=Opciones del juego
+SING_OPTIONS_GAME_DESC=Cambiar las preferencias generales del juego
+SING_OPTIONS_GAME_PLAYERS=Jugadores
+SING_OPTIONS_GAME_DIFFICULTY=Dificultad
+SING_OPTIONS_GAME_LANGUAGE=Idioma
+SING_OPTIONS_GAME_TABS=Etiquetas
+SING_OPTIONS_GAME_SORTING=Clasificar por
+SING_OPTIONS_GAME_DEBUG=Modo depuración
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Opciones gráficas
+SING_OPTIONS_GRAPHICS_DESC=Cambiar los ajustes de video
+SING_OPTIONS_GRAPHICS_RESOLUTION=Resolución
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Pantalla completa
+SING_OPTIONS_GRAPHICS_DEPTH=Profundidad de color
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualización
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Osciloscopio
+SING_OPTIONS_GRAPHICS_LINEBONUS=Bonus de línea
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Tamaño del video
+
+SING_OPTIONS_SOUND_WHEREAMI=Opciones de sonido
+SING_OPTIONS_SOUND_DESC=Cambiar los ajustes de audio
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Oír el micrófono
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Música de fondo
+SING_OPTIONS_SOUND_MIC_BOOST=Potenciar micrófono
+SING_OPTIONS_SOUND_CLICK_ASSIST=Ayuda de notas
+SING_OPTIONS_SOUND_BEAT_CLICK=Clic en compases
+SING_OPTIONS_SOUND_THRESHOLD=Umbral del micro.
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Modo 2 jugadores
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Volumen del adelanto
+SING_OPTIONS_SOUND_PREVIEWFADING=Desvanecimiento
+
+SING_OPTIONS_LYRICS_WHEREAMI=Opciones de letras
+SING_OPTIONS_LYRICS_DESC=Cambiar la forma en que se ven las canciones
+SING_OPTIONS_LYRICS_FONT=Tipografía
+SING_OPTIONS_LYRICS_EFFECT=Efecto
+SING_OPTIONS_LYRICS_SOLMIZATION=Solfeo
+SING_OPTIONS_LYRICS_NOTELINES=Pentagrama
+
+SING_OPTIONS_THEMES_WHEREAMI=Opciones de apariencia
+SING_OPTIONS_THEMES_DESC=Cambiar colores y temas
+SING_OPTIONS_THEMES_THEME=Tema
+SING_OPTIONS_THEMES_SKIN=Piel
+SING_OPTIONS_THEMES_COLOR=Color
+
+SING_OPTIONS_RECORD_WHEREAMI=Opciones de micrófonos
+SING_OPTIONS_RECORD_DESC=Cambiar entradas de sonido
+SING_OPTIONS_RECORD_CARD=Dispositivo de sonido
+SING_OPTIONS_RECORD_INPUT=Entrada
+SING_OPTIONS_RECORD_CHANNEL=Canal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Opciones avanzadas
+SING_OPTIONS_ADVANCED_DESC=Opciones avanzadas
+SING_OPTIONS_ADVANCED_EFFECTSING=Efectos al cantar
+SING_OPTIONS_ADVANCED_SCREENFADE=Desvanecimiento
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animación de carga
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Preguntar al borrar
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus de línea
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Al seleccionar canción
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto menú de grupo
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=Crear tu propia canción
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importar texto desde archivo MIDI
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Atrás
+SING_EDIT_BUTTON_CONVERT=Importar
+SING_EDIT_BUTTON_EXIT=Atrás
+
+SING_EDIT_NAVIGATE=Navegar
+SING_EDIT_SELECT=Seleccionar
+SING_EDIT_EXIT=Atrás
+
+SING_LEGEND_SELECT=Seleccionar
+SING_LEGEND_NAVIGATE=Navegar
+SING_LEGEND_CONTINUE=Continuar
+SING_LEGEND_ESC=Atrás
+
+SING_PLAYER_DESC=Nombres de jugadores
+SING_PLAYER_WHEREAMI=Nombres de jugadores
+SING_PLAYER_ENTER_NAME=Escribe el nombre
+
+SING_DIFFICULTY_DESC=Selecciona la dificultad
+SING_DIFFICULTY_WHEREAMI=Dificultad
+SING_DIFFICULTY_CONTINUE=Selección de canción
+SING_EASY=Fácil
+SING_MEDIUM=Normal
+SING_HARD=Difícil
+
+SING_SONG_SELECTION_DESC=Elige tu canción
+SING_SONG_SELECTION_WHEREAMI=Elige la canción
+SING_SONG_SELECTION_GOTO=Ir a...
+SING_SONG_SELECTION=Selección de canción
+SING_SONG_SELECTION_MENU=Menú
+SING_SONG_SELECTION_PLAYLIST=Lista
+SING_SONGS_IN_CAT=canciones
+PLAYLIST_CATTEXT=Lista: %s
+
+SING_TIME=TIEMPO
+SING_TOTAL=Total
+SING_MODE=Solo
+SING_NOTES=Notas
+SING_GOLDEN_NOTES=Notas doradas
+SING_PHRASE_BONUS=Bonus de línea
+
+SING_MENU=Menú principal
+
+SONG_SCORE=Puntajes
+SONG_SCORE_WHEREAMI=Puntajes
+
+SING_SCORE_TONE_DEAF=Desafinado
+SING_SCORE_AMATEUR=Aficionado
+SING_SCORE_WANNABE=Mejorando
+SING_SCORE_HOPEFUL=Promesa
+SING_SCORE_RISING_STAR=Cantante
+SING_SCORE_LEAD_SINGER=Gran Cantante
+SING_SCORE_SUPERSTAR=Superestrella
+SING_SCORE_ULTRASTAR=Ultraestrella
+
+SING_TOP_5_CHARTS=Los 5 mejores
+SING_TOP_5_CHARTS_WHEREAMI=Los 5 mejores
+SING_TOP_5_CHARTS_CONTINUE=A selección de canción
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=Cambiar dificultad
+
+POPUP_PERFECT=¡Perfecto!
+POPUP_AWESOME=¡Asombroso!
+POPUP_GREAT=¡Genial!
+POPUP_GOOD=¡Bien!
+POPUP_NOTBAD=¡Nada mal!
+POPUP_BAD=¡Mal!
+POPUP_POOR=¡Pésimo!
+POPUP_AWFUL=¡Horrible!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= y
+
+SONG_MENU_NAME_MAIN=Menú canciones
+SONG_MENU_PLAY=Cantar
+SONG_MENU_CHANGEPLAYERS=Elegir jugadores
+SONG_MENU_EDIT=Editar
+SONG_MENU_MODI=Cantar una Modi
+SONG_MENU_CANCEL=Cancelar
+
+SONG_MENU_NAME_PLAYLIST=Menú canciones
+SONG_MENU_PLAYLIST_ADD=Agregar canción
+SONG_MENU_PLAYLIST_DEL=Borrar canción
+
+SONG_MENU_NAME_PLAYLIST_ADD=Agregar canción
+SONG_MENU_PLAYLIST_ADD_NEW=A un listado nuevo
+SONG_MENU_PLAYLIST_ADD_EXISTING=A un listado existente
+SONG_MENU_PLAYLIST_NOEXISTING=No hay listados
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nuevo listado de canciones
+SONG_MENU_PLAYLIST_NEW_CREATE=Crear
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Sin nombre
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=¿Borrar?
+SONG_MENU_YES=Sí
+SONG_MENU_NO=No
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Abrir listado
+SONG_MENU_PLAYLIST_LOAD=Abrir
+SONG_MENU_PLAYLIST_DELCURRENT=Borrar listado actual
+
+SONG_MENU_NAME_PLAYLIST_DEL=¿Borrar listado?
+
+SONG_MENU_NAME_PARTY_MAIN=Menú grupo
+SONG_MENU_JOKER=Aleatorio
+
+SONG_MENU_NAME_PARTY_JOKER=Aleatorio
+
+SONG_JUMPTO_DESC=Buscar canción
+SONG_JUMPTO_TYPE_DESC=Buscar por:
+SONG_JUMPTO_TYPE1=Todo
+SONG_JUMPTO_TYPE2=Título
+SONG_JUMPTO_TYPE3=Artista
+SONG_JUMPTO_SONGSFOUND=%d resultados
+SONG_JUMPTO_NOSONGSFOUND=0 resultados
+SONG_JUMPTO_HELP=Escribe el texto a buscar
+SONG_JUMPTO_CATTEXT=Buscar por: %s
+
+PARTY_MODE=Modo Grupo
+PARTY_DIFFICULTY=Dificultad
+PARTY_PLAYLIST=Modo lista
+PARTY_PLAYLIST_ALL=Todo
+PARTY_PLAYLIST_CATEGORY=Carpeta
+PARTY_PLAYLIST_PLAYLIST=Listado
+PARTY_TEAMS=Equipos
+PARTY_TEAMS_PLAYER1=Integrantes eq. 1
+PARTY_TEAMS_PLAYER2=Integrantes eq. 2
+PARTY_TEAMS_PLAYER3=Integrantes eq. 3
+
+PARTY_LEGEND_CONTINUE=Continuar
+
+PARTY_OPTIONS_DESC=Opciones del modo grupo
+PARTY_OPTIONS_WHEREAMI=Opciones del modo grupo
+
+PARTY_PLAYER_DESC=¡Escribe los nombres de jugadores y equipos!
+PARTY_PLAYER_WHEREAMI=Nombre de los equipos
+PARTY_PLAYER_ENTER_NAME=Escribe los nombres
+
+
+PARTY_ROUNDS_DESC=Elige qué modos quieres jugar
+PARTY_ROUNDS_WHEREAMI=Rondas 
+PARTY_ROUNDS_LEGEND_CONTINUE=Empezar
+PARTY_ROUNDCOUNT=Cantidad de rondas
+PARTY_SELECTMODE1=Modo 1ra. ronda
+PARTY_SELECTMODE2=Modo 2da. ronda
+PARTY_SELECTMODE3=Modo 3ra. ronda
+PARTY_SELECTMODE4=Modo 4ta. ronda
+PARTY_SELECTMODE5=Modo 5ta. ronda
+PARTY_SELECTMODE6=Modo 6ta. ronda
+PARTY_SELECTMODE7=Modo 7ma. ronda
+
+PARTY_ROUND_DESC=Siguientes jugadores
+PARTY_ROUND_WHEREAMI=Siguiente ronda
+PARTY_ROUND_LEGEND_CONTINUE=Iniciar ronda
+
+PARTY_SONG_WHEREAMI=Selección de canción
+PARTY_SONG_LEGEND_CONTINUE=Cantar
+PARTY_SONG_MENU=Menú grupo
+
+PARTY_SCORE_DESC=Puntaje de la última ronda
+PARTY_SCORE_WHEREAMI=Puntaje
+
+PARTY_WIN_DESC=Equipo ganador
+PARTY_WIN_WHEREAMI=Ganador
+PARTY_WIN_LEGEND_CONTINUE=Al menú principal
+
+PARTY_ROUND=Ronda
+PARTY_ROUND_WINNER=Ganador
+PARTY_NOTPLAYEDYET=Aún no jugado
+PARTY_NOBODY=Nadie
+NEXT_ROUND=Siguiente ronda:
+
+PARTY_DISMISSED=¡Perdió!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=¡Ganó!
+
+MODE_RANDOM_NAME=Aleatorio
+MODE_RANDOM_DESC=Se elegirá el modo al azar
+
+MODE_HOLDTHELINE_NAME=Mantén la línea
+MODE_HOLDTHELINE_DESC=¡No bajes tu puntaje del mostrado en pantalla!
+
+MODE_5000POINTS_NAME=Hasta 5000
+MODE_5000POINTS_DESC=Gana quien obtenga 5000 puntos.
+
+MODE_DUEL_NAME=Duelo
+MODE_DUEL_DESC=Canta un duelo hasta 10000 puntos.
+
+MODE_TEAMDUEL_NAME=Duelo de equipos
+MODE_TEAMDUEL_DESC=¡Pasa el micro!
+
+MODE_BLIND_NAME=Modo a ciegas
+MODE_BLIND_DESC=Duelo sin ver las notas.
+
+STAT_MAIN=Estadísticas
+STAT_MAIN_DESC=General
+STAT_MAIN_WHEREAMI=Estadísticas
+
+STAT_OVERVIEW_INTRO=Estadísticas de %0:s\n Desde el %1:.2d/%2:.2d/%3:d
+STAT_OVERVIEW_SONG=Hay %0:d canciones (%3:d con vídeo),\n de las cuales %1:d han sido cantadas y %2:d aún no.\n La más popular es %5:s de %4:s.
+STAT_OVERVIEW_PLAYER=Hay registrados %0:d jugadores diferentes.\n El mejor es %1:s con un promedio de %2:d puntos.\n El puntaje más alto fue logrado por %3:s con %4:d puntos.
+
+STAT_FORMAT_DATE=%0:.2d/%1:.2d/%2:d
+
+STAT_DETAIL=Estadísticas
+STAT_DETAIL_WHEREAMI=Estadísticas detalladas
+
+STAT_NEXT=Siguiente
+STAT_PREV=Anterior
+STAT_REVERSE=Invertir el orden
+STAT_PAGE=Página %0:d de %1:d \n (%2:d ítems de un total de %3:d)
+
+STAT_DESC_SCORES=Puntajes
+STAT_DESC_SCORES_REVERSED=Peores puntajes
+STAT_FORMAT_SCORES=%1:d - %0:s\n %3:s - %4:s (%2:s) el %5:s
+
+STAT_DESC_SINGERS=Cantantes
+STAT_DESC_SINGERS_REVERSED=Peores cantantes
+STAT_FORMAT_SINGERS=%0:s \n Promedio: %1:d
+
+STAT_DESC_SONGS=Lo más cantado
+STAT_DESC_SONGS_REVERSED=Lo menos cantado
+STAT_FORMAT_SONGS=%0:s - %1:s \n cantado %2:d veces
+
+STAT_DESC_BANDS=Grupos populares
+STAT_DESC_BANDS_REVERSED=Grupos menos cantados
+STAT_FORMAT_BANDS=%0:s \n cantado %1:d veces
+
+SCREENSHOT_SAVED=Pantalla guardada
+SCREENSHOT_FAILED=No se pudo guardar
+
+INFO_FILE_SAVED=Archivo guardado
+ERROR_SAVE_FILE_FAILED=No se pudo guardar
+ERROR_FILE_NOT_FOUND=No se encontró el archivo
+
+ENCODING_ERROR_ASK_FOR_UTF8=No se pueden guardar los cambios en la codificación actual. ¿Convertir a UTF-8?
+EDITOR_ERROR_NO_TRACK_SELECTED=Sin pista seleccionada
+
+MSG_ERROR_TITLE=Error
+MSG_INFO_TITLE=Información
+MSG_QUESTION_TITLE=Pregunta
+MSG_QUIT_USDX=¿Seguro que quieres salir?
+MSG_END_PARTY=¿Seguro que quieres salir del modo grupo?
+
+ERROR_NO_SONGS=No hay canciones
+ERROR_NO_PLUGINS=No hay plugins
+ERROR_NO_MODES_FOR_CURRENT_SETUP=No hay modos disponibles para la configuración actual de equipos y jugadores
+ERROR_CAN_NOT_START_PARTY=Ocurrió un error al iniciar el juego
+ERROR_CORRUPT_SONG=Imposible cargar la canción.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Imposible cargar la canción: Archivo no encontrado
+ERROR_CORRUPT_SONG_NO_NOTES=Imposible cargar la canción: No se encuentran notas
+ERROR_CORRUPT_SONG_NO_BREAKS=Imposible cargar la canción: No se encuentran interrupciones de línea
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Imposible cargar la canción: Error durante el parsing de la línea %0:d
+ERROR_NO_EDITOR=Esta función no está disponible en Linux/Mac
+ERROR_PLAYER_DEVICE_ASSIGNMENT=Se han asignado más de 1 micrófono al jugador %d. Comprueba las opciones de micrófonos.
+ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Al jugador %d no se le ha asignado ningún micrófono. Comprueba las opciones de micrófonos
+;UNUSED: PARTY_ROUNDS=Rondas
+;TRANSLATOR: Daniela Rodríguez Careri
diff --git a/songmanagement/game/languages/Swedish.ini b/songmanagement/game/languages/Swedish.ini
new file mode 100644
index 00000000..3c99dad7
--- /dev/null
+++ b/songmanagement/game/languages/Swedish.ini
@@ -0,0 +1,442 @@
+[Text]
+OPTION_VALUE_CATALAN=Katalanska
+OPTION_VALUE_CROATIAN=Kroatiska
+OPTION_VALUE_CZECH=Tjeckiska
+OPTION_VALUE_DANISH=Danska
+OPTION_VALUE_DUTCH=Nederländska
+OPTION_VALUE_ENGLISH=Engelska
+OPTION_VALUE_EUSKARA=Euskara
+OPTION_VALUE_FINNISH=Finska
+OPTION_VALUE_FRENCH=Franska
+OPTION_VALUE_GERMAN=Tyska
+OPTION_VALUE_GREEK=Grekiska
+OPTION_VALUE_HUNGARIAN=Ungerska
+OPTION_VALUE_ICELANDIC=Isländska
+OPTION_VALUE_ITALIAN=Italienska
+OPTION_VALUE_JAPANESE=Japanska
+OPTION_VALUE_LUXEMBOURGISH=Luxemburgska
+OPTION_VALUE_NORWEGIAN=Norska
+OPTION_VALUE_POLISH=Polska
+OPTION_VALUE_PORTUGUESE=Portuguesiska
+OPTION_VALUE_RUSSIAN=Ryska
+OPTION_VALUE_SERBIAN=Serbiska
+OPTION_VALUE_SLOVAK=Slovakiska
+OPTION_VALUE_SLOVENIAN=Slovenian
+OPTION_VALUE_SPANISH=Spanska
+OPTION_VALUE_SWEDISH=Svenska
+
+OPTION_VALUE_EASY=Lätt
+OPTION_VALUE_MEDIUM=Medel
+OPTION_VALUE_HARD=Svår
+
+OPTION_VALUE_ON=På
+OPTION_VALUE_OFF=Av
+
+OPTION_VALUE_EDITION=Utgåva
+OPTION_VALUE_GENRE=Genre
+OPTION_VALUE_LANGUAGE=Språk
+OPTION_VALUE_FOLDER=Mapp
+OPTION_VALUE_TITLE=Titel
+OPTION_VALUE_ARTIST=Artist
+OPTION_VALUE_TITLE2=Titel2
+OPTION_VALUE_ARTIST2=Artist2
+
+OPTION_VALUE_WHENNOVIDEO=När video saknas
+
+OPTION_VALUE_SMALL=Liten
+OPTION_VALUE_BIG=Stor
+
+OPTION_VALUE_HALF=Halv
+OPTION_VALUE_FULL_VID=Hel (Video)
+OPTION_VALUE_FULL_VID_BG=Hel (BG & Video)
+
+OPTION_VALUE_AUTO=Auto
+OPTION_VALUE_SEC=Sekund
+OPTION_VALUE_SECS=Sekunder
+
+OPTION_VALUE_PLAIN=Slät
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Enkel
+OPTION_VALUE_ZOOM=Zoom
+OPTION_VALUE_SLIDE=Glid
+OPTION_VALUE_BALL=Boll
+OPTION_VALUE_SHIFT=Förskjutning
+
+OPTION_VALUE_EURO=Europeisk
+OPTION_VALUE_JAPAN=Japansk
+OPTION_VALUE_AMERICAN=Amerikansk
+
+OPTION_VALUE_BLUE=Blå
+OPTION_VALUE_GREEN=Grön
+OPTION_VALUE_PINK=Rosa
+OPTION_VALUE_RED=Röd
+OPTION_VALUE_VIOLET=Lila
+OPTION_VALUE_ORANGE=Orange
+OPTION_VALUE_YELLOW=Gul
+OPTION_VALUE_BROWN=Brun
+OPTION_VALUE_BLACK=Svart
+
+OPTION_VALUE_SING=Sjung
+OPTION_VALUE_SELECT_PLAYERS=Välj spelare
+OPTION_VALUE_OPEN_MENU=Öppna meny
+
+OPTION_VALUE_HARDWARE_CURSOR=Systempekare
+OPTION_VALUE_SOFTWARE_CURSOR=Programpekare
+
+SING_LOADING=Läser in...
+
+SING_CHOOSE_MODE=Välj läge
+SING_SING=Sjung
+SING_SING_DESC=Snabbspel: Sjung solo eller duett
+
+SING_MULTI=Party
+SING_MULTI_DESC=Sjung i partyläge
+
+SING_TOOLS=Verktyg
+
+SING_STATS=Statistik
+SING_STATS_DESC=Kolla statistiken
+
+SING_EDITOR=Editor
+SING_EDITOR_DESC=Skapa din egen låt
+
+SING_GAME_OPTIONS=Spelinställningar
+SING_GAME_OPTIONS_DESC=Ändra spelets inställningar
+
+SING_EXIT=Avsluta
+SING_EXIT_DESC=Sluta spela
+
+SING_OPTIONS=Inställningar
+SING_OPTIONS_DESC=Ändra inställningar
+SING_OPTIONS_WHEREAMI=Inställningar
+
+SING_OPTIONS_GAME=Spel
+SING_OPTIONS_GRAPHICS=Grafik
+SING_OPTIONS_SOUND=Ljud
+SING_OPTIONS_LYRICS=Text
+SING_OPTIONS_THEMES=Teman
+SING_OPTIONS_RECORD=Inspelning
+SING_OPTIONS_ADVANCED=Avancerat
+SING_OPTIONS_EXIT=Tillbaka
+
+SING_OPTIONS_GAME_WHEREAMI=Inställningar Spel
+SING_OPTIONS_GAME_DESC=Vanliga spelinställningar
+SING_OPTIONS_GAME_PLAYERS=Spelare
+SING_OPTIONS_GAME_DIFFICULTY=Svårighetsnivå
+SING_OPTIONS_GAME_LANGUAGE=Språk
+SING_OPTIONS_GAME_TABS=Tabbar
+SING_OPTIONS_GAME_SORTING=Sortering
+SING_OPTIONS_GAME_DEBUG=Debuggning
+
+SING_OPTIONS_GRAPHICS_WHEREAMI=Inställningar Grafik
+SING_OPTIONS_GRAPHICS_DESC=Grafikinställningar
+SING_OPTIONS_GRAPHICS_RESOLUTION=Upplösning
+SING_OPTIONS_GRAPHICS_FULLSCREEN=Helskärm
+SING_OPTIONS_GRAPHICS_DEPTH=Färgdjup
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualisering
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Radbonus
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Filmstorlek
+
+SING_OPTIONS_SOUND_WHEREAMI=Inställningar Ljud
+SING_OPTIONS_SOUND_DESC=Ljudinställningar
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Mikrofonuppspelning
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Bakgrundsmusik
+SING_OPTIONS_SOUND_MIC_BOOST=Mikrofonförstärkning
+SING_OPTIONS_SOUND_CLICK_ASSIST=Hjälpljud
+SING_OPTIONS_SOUND_BEAT_CLICK=Taktljud
+SING_OPTIONS_SOUND_THRESHOLD=Ljudtröskel
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Tvåspelarläge
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Volym i låtvalsmenyn
+SING_OPTIONS_SOUND_PREVIEWFADING=Toning i låtvalsmenyn
+
+SING_OPTIONS_LYRICS_WHEREAMI=Inställningar Text
+SING_OPTIONS_LYRICS_DESC=Sångtextinställningar
+SING_OPTIONS_LYRICS_FONT=Typsnitt
+SING_OPTIONS_LYRICS_EFFECT=Effekt
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmisation
+SING_OPTIONS_LYRICS_NOTELINES=Notlinjer
+
+SING_OPTIONS_THEMES_WHEREAMI=Inställningar Teman
+SING_OPTIONS_THEMES_DESC=Temainställningar
+SING_OPTIONS_THEMES_THEME=Tema
+SING_OPTIONS_THEMES_SKIN=Utseende
+SING_OPTIONS_THEMES_COLOR=Färg
+
+SING_OPTIONS_RECORD_WHEREAMI=Inställningar Inspelning
+SING_OPTIONS_RECORD_DESC=Mikrofoninställningar
+SING_OPTIONS_RECORD_CARD=Ljudkort
+SING_OPTIONS_RECORD_INPUT=Ingång
+SING_OPTIONS_RECORD_CHANNEL=Kanal
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Inställningar Avancerat
+SING_OPTIONS_ADVANCED_DESC=Avancerade inställningar
+SING_OPTIONS_ADVANCED_EFFECTSING=Sångeffekter
+SING_OPTIONS_ADVANCED_SCREENFADE=Skärmtoning
+SING_OPTIONS_ADVANCED_LOADANIMATION=Inläsningsanimation
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Säkerhetsfråga
+SING_OPTIONS_ADVANCED_LINEBONUS=Radbonus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Vid låtval
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Automatisk Partymeny
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=Skapa din egen låt
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importera text från MIDI-fil
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Tillbaka
+SING_EDIT_BUTTON_CONVERT=Importera
+SING_EDIT_BUTTON_EXIT=Tillbaka
+
+SING_EDIT_NAVIGATE=Navigera
+SING_EDIT_SELECT=Välj
+SING_EDIT_EXIT=Tillbaka
+
+SING_LEGEND_SELECT=Välj
+SING_LEGEND_NAVIGATE=Navigera
+SING_LEGEND_CONTINUE=Fortsätt
+SING_LEGEND_ESC=Tillbaka
+
+SING_PLAYER_DESC=Skriv in spelarnamn
+SING_PLAYER_WHEREAMI=Spelarnamn
+SING_PLAYER_ENTER_NAME=Skriv namn
+
+SING_DIFFICULTY_DESC=Välj svårighetsgrad
+SING_DIFFICULTY_WHEREAMI=Svårighetsgrad
+SING_DIFFICULTY_CONTINUE=Till låtval
+SING_EASY=Lätt
+SING_MEDIUM=Medel
+SING_HARD=Svår
+
+SING_SONG_SELECTION_DESC=Välj din låt
+SING_SONG_SELECTION_WHEREAMI=Låtval
+SING_SONG_SELECTION_GOTO=Gå till...
+SING_SONG_SELECTION=Låtval
+SING_SONG_SELECTION_MENU=Meny
+SING_SONG_SELECTION_PLAYLIST=Spellista
+SING_SONGS_IN_CAT=Låtar
+PLAYLIST_CATTEXT=Spellista: %s
+
+SING_TIME=TID
+SING_TOTAL=Totalt
+SING_MODE=Sjung solo
+SING_NOTES=Noter
+SING_GOLDEN_NOTES=Gyllene noter
+SING_PHRASE_BONUS=Radbonus
+
+SING_MENU=Huvudmeny
+
+SONG_SCORE=Låtpoäng
+SONG_SCORE_WHEREAMI=Poäng
+
+SING_SCORE_TONE_DEAF=Tondöv
+SING_SCORE_AMATEUR=Amatör
+SING_SCORE_WANNABE=Wannabe
+SING_SCORE_HOPEFUL=Potential
+SING_SCORE_RISING_STAR=Stigande stjärna
+SING_SCORE_LEAD_SINGER=Hitartist
+SING_SCORE_SUPERSTAR=Superstjärna
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=Topp 5 Spelare
+SING_TOP_5_CHARTS_WHEREAMI=Topp 5
+SING_TOP_5_CHARTS_CONTINUE=Till låtval
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=byt svårighetsgrad
+
+POPUP_PERFECT=Perfekt!
+POPUP_AWESOME=Storartat!
+POPUP_GREAT=Riktigt bra!
+POPUP_GOOD=Bra!
+POPUP_NOTBAD=Godkänt!
+POPUP_BAD=Dåligt!
+POPUP_POOR=Uselt!
+POPUP_AWFUL=Hemskt!
+
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= och
+
+SONG_MENU_NAME_MAIN=Låtmeny
+SONG_MENU_PLAY=Sjung
+SONG_MENU_CHANGEPLAYERS=Ändra spelare
+SONG_MENU_EDIT=Redigera
+SONG_MENU_MODI=Sjung på ett sätt
+SONG_MENU_CANCEL=Ångra
+
+SONG_MENU_NAME_PLAYLIST=Låtmeny
+SONG_MENU_PLAYLIST_ADD=Lägg till låt
+SONG_MENU_PLAYLIST_DEL=Ta bort låt
+
+SONG_MENU_NAME_PLAYLIST_ADD=Lägg till låt
+SONG_MENU_PLAYLIST_ADD_NEW=till ny spellista
+SONG_MENU_PLAYLIST_ADD_EXISTING=till exsisterande spellista
+SONG_MENU_PLAYLIST_NOEXISTING=Ingen spellista tillgänglig
+
+SONG_MENU_NAME_PLAYLIST_NEW=Ny spellista
+SONG_MENU_PLAYLIST_NEW_CREATE=Skapa
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Namnlös
+
+SONG_MENU_NAME_PLAYLIST_DELITEM=Vill du verkligen bort?
+SONG_MENU_YES=Ja
+SONG_MENU_NO=Nej
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Öppna spellista
+SONG_MENU_PLAYLIST_LOAD=öppna
+SONG_MENU_PLAYLIST_DELCURRENT=ta bort nuvarande spellista
+
+SONG_MENU_NAME_PLAYLIST_DEL=Ta bort spellista?
+
+SONG_MENU_NAME_PARTY_MAIN=Partymeny
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=ta joker
+
+SONG_JUMPTO_DESC=sök låt
+SONG_JUMPTO_TYPE_DESC=Sök efter:
+SONG_JUMPTO_TYPE1=Alla
+SONG_JUMPTO_TYPE2=Titel
+SONG_JUMPTO_TYPE3=Artist
+SONG_JUMPTO_SONGSFOUND=%d Låt(ar) hittade
+SONG_JUMPTO_NOSONGSFOUND=Ingen låt hittad
+SONG_JUMPTO_HELP=Skriv text att söka efter
+SONG_JUMPTO_CATTEXT=Sök efter: %s
+
+PARTY_MODE=partyläge
+PARTY_DIFFICULTY=Svårighetsnivå
+PARTY_PLAYLIST=Spellistläge
+PARTY_PLAYLIST_ALL=Alla låtar
+PARTY_PLAYLIST_CATEGORY=Mapp
+PARTY_PLAYLIST_PLAYLIST=Spellista
+PARTY_TEAMS=Lag
+PARTY_TEAMS_PLAYER1=Spelare Lag1
+PARTY_TEAMS_PLAYER2=Spelare Lag2
+PARTY_TEAMS_PLAYER3=Spelare Lag3
+
+PARTY_LEGEND_CONTINUE=fortsätt
+
+PARTY_OPTIONS_DESC=inställningar för partyspel
+PARTY_OPTIONS_WHEREAMI=Partyinställningar
+
+PARTY_PLAYER_DESC=skriv spelar- och lagnamn!
+PARTY_PLAYER_WHEREAMI=Partynamn
+PARTY_PLAYER_ENTER_NAME=skriv namn
+
+
+;TODO: PARTY_ROUNDS_DESC=select which modes you want to play
+;TODO: PARTY_ROUNDS_WHEREAMI=Party Rounds
+PARTY_ROUNDS_LEGEND_CONTINUE=starta partyspel
+;TODO: PARTY_ROUNDCOUNT=number of rounds
+;TODO: PARTY_SELECTMODE1=mode round 1
+;TODO: PARTY_SELECTMODE2=mode round 2
+;TODO: PARTY_SELECTMODE3=mode round 3
+;TODO: PARTY_SELECTMODE4=mode round 4
+;TODO: PARTY_SELECTMODE5=mode round 5
+;TODO: PARTY_SELECTMODE6=mode round 6
+;TODO: PARTY_SELECTMODE7=mode round 7
+
+PARTY_ROUND_DESC=nästa spelare till mikrofonerna
+PARTY_ROUND_WHEREAMI=Party Nästa omgång
+PARTY_ROUND_LEGEND_CONTINUE=starta omgång
+
+PARTY_SONG_WHEREAMI=Party Låtval
+PARTY_SONG_LEGEND_CONTINUE=sjung
+PARTY_SONG_MENU=partymeny
+
+PARTY_SCORE_DESC=poäng från förra omgången
+PARTY_SCORE_WHEREAMI=Partypoäng
+
+PARTY_WIN_DESC=vinnare av partyspelet
+PARTY_WIN_WHEREAMI=Partyvinnare
+PARTY_WIN_LEGEND_CONTINUE=tillbaka till huvudmenyn
+
+PARTY_ROUND=Omgång
+PARTY_ROUND_WINNER=Vinnare
+PARTY_NOTPLAYEDYET=inte spelad än
+PARTY_NOBODY=ingen
+NEXT_ROUND=Nästa runda:
+
+PARTY_DISMISSED=Avbröt!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=vann!
+
+;TODO: MODE_RANDOM_NAME=Random Mode
+;TODO: MODE_RANDOM_DESC=One mode will be choosen randomly
+
+MODE_HOLDTHELINE_NAME=Håll god ton
+MODE_HOLDTHELINE_DESC=Bli inte sämre än vad markeringen på omdömesmätaren visar.
+
+MODE_5000POINTS_NAME=Till 5000
+MODE_5000POINTS_DESC=Den som först får 5000 poäng vinner matchen.
+
+MODE_DUEL_NAME=Duell
+MODE_DUEL_DESC=Sjung en duett till 10000 poäng.
+
+MODE_TEAMDUEL_NAME=Lagduell
+MODE_TEAMDUEL_DESC=Skicka micken!
+
+MODE_BLIND_NAME=Blindläge
+MODE_BLIND_DESC=Duell utan att se tonerna.
+
+STAT_MAIN=Statistik
+STAT_MAIN_DESC=Allmänn
+STAT_MAIN_WHEREAMI=Statistik
+
+STAT_OVERVIEW_INTRO=%0:s Statistik.  \n Senast återställd %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Låtar(%3:d med Video), varav %1:d redan har spelats och %2:d inte har spelats än.\n Den mest populära låten är %5:s med %4:s.
+STAT_OVERVIEW_PLAYER=Sedan den senaste återställningen har %0:d olika spelare sjungit.\n Den bästa spelaren är %1:s med ett genomsnitt på %2:d poäng.\n %3:s har sjungit bäst med %4:d poäng.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
+
+STAT_DETAIL=Statistik
+STAT_DETAIL_WHEREAMI=Detaljerad statistik
+
+STAT_NEXT=Nästa sida
+STAT_PREV=Föregående sida
+STAT_REVERSE=Omvänd ordning
+STAT_PAGE=Sida %0:d av %1:d sidor\n (%2:d av %3:d poster)
+
+STAT_DESC_SCORES=Högsta resultat
+STAT_DESC_SCORES_REVERSED=Lägsta resultat
+STAT_FORMAT_SCORES=%0:s - %1:d  [%2:s]  %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Bästa sångare
+STAT_DESC_SINGERS_REVERSED=Sämsta sångare
+STAT_FORMAT_SINGERS=%0:s \n genomsnittlig poäng: %1:d
+
+STAT_DESC_SONGS=Populäraste låtarna
+STAT_DESC_SONGS_REVERSED=Minst populära låtarna
+STAT_FORMAT_SONGS=%0:s - %1:s \n Sjungen %2:dx gånger
+
+STAT_DESC_BANDS=Populäraste artisterna
+STAT_DESC_BANDS_REVERSED=Minst populära artisterna
+STAT_FORMAT_BANDS=%0:s \n %1:dx sjungna
+
+;TODO: SCREENSHOT_SAVED=Screenshot saved
+;TODO: SCREENSHOT_FAILED=Couldn''t save screenshot
+
+;TODO: INFO_FILE_SAVED=File saved
+;TODO: ERROR_SAVE_FILE_FAILED=Couldn''t save file 
+;TODO: ERROR_FILE_NOT_FOUND=File not found
+
+;TODO: ENCODING_ERROR_ASK_FOR_UTF8=Cannot save changes in current encoding. Convert to UTF-8?
+;TODO: EDITOR_ERROR_NO_TRACK_SELECTED=No track selected
+
+MSG_ERROR_TITLE=Fel
+;TODO: MSG_INFO_TITLE=Information
+MSG_QUESTION_TITLE=Fråga
+MSG_QUIT_USDX=Vill du verkligen avsluta UltraStar?
+MSG_END_PARTY=Vill du verkligen avsluta partyläge?
+
+ERROR_NO_SONGS=Inga låtar laddade
+ERROR_NO_PLUGINS=Inga insticksprogram laddade
+;TODO: ERROR_NO_MODES_FOR_CURRENT_SETUP=no modes available for current player/team setup
+;TODO: ERROR_CAN_NOT_START_PARTY=an error occurred starting the party game
+ERROR_CORRUPT_SONG=Låten kunde inte laddas.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Låten kunde inte laddas: Filen kunde inte hittas
+ERROR_CORRUPT_SONG_NO_NOTES=Låten kunde inte laddas: Kan inte hitta toner
+ERROR_CORRUPT_SONG_NO_BREAKS=Låten kunde inte laddas: Kan inte hitta radbrytningar
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Låten kunde inte laddas: Fel på rad %0:d
+;TODO: ERROR_NO_EDITOR=This feature is not available on Linux/Mac
+;TODO: ERROR_PLAYER_DEVICE_ASSIGNMENT=Player %d is assigned to multiple microphones. Please check your record options
+;TODO: ERROR_PLAYER_NO_DEVICE_ASSIGNMENT=Player %d is not assigned to a microphone. Please check your record options
+;UNUSED: PARTY_ROUNDS=Omgångar
diff --git a/songmanagement/game/languages/convert.sh b/songmanagement/game/languages/convert.sh
new file mode 100755
index 00000000..328efcda
--- /dev/null
+++ b/songmanagement/game/languages/convert.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# See: http://www.microsoft.com/resources/msdn/goglobal/default.mspx?OS=Windows%20Vista
+
+function convertUTF8 {
+  if [ ! -f $2.ini ]; then
+    echo "skip $2.ini: does not exist"
+    return
+  fi
+
+  # UTF-8 BOM (0xEF 0xBB 0xBF)
+  BOM=`echo -n -e "\0357\0273\0277"`
+  HEADER=`head -c3 $2.ini`
+  if [ $HEADER != $BOM ]; then
+    echo "Convert $2.ini from $1 to UTF8"
+    echo -n $BOM >$2.tmp
+    iconv -f $1 -t UTF-8 $2.ini >>$2.tmp
+    mv $2.tmp $2.ini
+  else
+    echo "skip $2.ini: already UTF8"    
+  fi
+}
+
+#convertUTF8 UTF8 Catalan
+convertUTF8 CP1252 French 
+convertUTF8 CP1252 Italian 
+convertUTF8 CP1252 Spanish 
+convertUTF8 CP1250 Croatian
+convertUTF8 CP1252 Euskara 
+convertUTF8 CP1252 German 
+#convertUTF8 UCS-2LE Japanese 
+convertUTF8 CP1252 Swedish 
+convertUTF8 CP1252 Dutch 
+convertUTF8 CP1252 Finnish 
+convertUTF8 CP1253 Greek 
+convertUTF8 CP1252 Portuguese 
+
+convertUTF8 CP1252 Danish 
+convertUTF8 CP1252 Norwegian 
+#convertUTF8 CP1251 Serbian 
+convertUTF8 CP1250 Serbian 
+convertUTF8 CP1250 Slovenian 
+convertUTF8 CP1250 Polish 
+convertUTF8 CP1250 Slovak 
diff --git a/songmanagement/game/languages/readme.txt b/songmanagement/game/languages/readme.txt
new file mode 100644
index 00000000..5628092c
--- /dev/null
+++ b/songmanagement/game/languages/readme.txt
@@ -0,0 +1,99 @@
+.o0 Ultrastar Deluxe in your language 0o.
+
+-----------------------
+   Table of Contents
+-----------------------
+1. Introduction
+2. Translate texts
+3. Wildcards
+
+-----------------------
+1. Introduction:
+-----------------------
+To translate USDX to a new language, copy the file Language.new to [Language].ini with [Language]
+replaced by the English name of your language (e.g. German.ini for German).
+Translate all texts according to section (2) of this file.
+
+-----------------------
+2. Translate texts:
+-----------------------
+1) For each target language there is a translation file named [Language].ini where [Language] is the target
+   language.
+2) All lines that have not been translated so far are prefixed with ";TODO:" like the following line
+     ;TODO: SOME_OPTION=English text here
+3) Translate the text if you are familiar with the target language
+4) After you have done so remove the ";TODO: " prefix so that it looks like in this German translation:
+     SOME_OPTION=Hier der deutsche Text
+   IMPORTANT: Do NOT remove the ";TODO: " prefix if you did not translate the text and it is still English.
+5) At the end of the file there might be some lines which start with ";INVALID: " or ";UNUSED: ". 
+   Invalid lines are not correctly formatted lines and might crash USDX. Unused lines are not used
+   anymore by USDX or they have been renamed.
+6) If you want you may add your name to the END (not the beginning) of the file:
+     ;TRANSLATOR: Mario Translatori
+   Note the ";" in front of it.
+7) Share your translation with others:
+   - Send the translated file to our Patch-Tracker at SourceForge (http://sourceforge.net/tracker/?group_id=191560&atid=937872)
+   - or contact us via our IRC channel
+
+-----------------------
+3. Wildcards:
+-----------------------
+Here are some informations about the wildcards in the language texts for the statistic screens (STAT_...):
+Information that will replace the wildcards:
+
+STAT_OVERVIEW_INTRO:
+  Format:
+    %0:d Ultrastar Version
+    %1:d Day of Reset (A1)
+    %2:d Month of Reset (A2)
+    %3:d Year of Reset (A3)
+
+STAT_OVERVIEW_SONG:
+  Format:
+    %0:d Count Songs (A1)
+    %1:d Count of Sung Songs (A2)
+    %2:d Count of UnSung Songs
+    %3:d Count of Songs with Video (A3)
+    %4:s Name of the most popular Song
+
+STAT_OVERVIEW_PLAYER:
+  Format:
+    %0:d Count Players (A1)
+    %1:s Best Player (Result)
+    %2:d Best Players Score
+    %3:s Best Score Player (Result2)
+    %4:d Best Score
+
+STAT_FORMAT_SCORES:
+  Format:
+    %0:s Singer
+    %1:d Score
+    %2:s Difficulty
+    %3:s Song Artist   
+    %4:s Song Title
+
+STAT_FORMAT_SINGERS:
+  Format:
+    %0:s Singer
+    %1:d Average Score
+
+
+STAT_FORMAT_SONGS:
+  Format:
+    %0:s Artist
+    %1:s Title
+    %2:d Times Sung
+
+STAT_FORMAT_BANDS:
+  Format:
+    %0:s Artist Name
+    %1:d Times Sung
+
+Some further explanations about the wildcards:
+%x:[.y]z
+
+Where X is the number of the wildcard,
+Y is optional, it is the number of digits for deciaml numbers (Z=d). So, if y is 2 there and the number is only 0 to 9 there will be a zero added in front of the number.
+z can be d for numbers and s for texts
+
+For the date thing in STAT_OVERVIEW_INTRO you may use %1:.2d for the day and %2:.2d for the month.
diff --git a/songmanagement/game/languages/update.py b/songmanagement/game/languages/update.py
new file mode 100755
index 00000000..7447b19e
--- /dev/null
+++ b/songmanagement/game/languages/update.py
@@ -0,0 +1,154 @@
+#!/usr/bin/python
+
+# UltraStar Deluxe - Karaoke Game
+#
+# UltraStar Deluxe is the legal property of its developers, whose names
+# are too numerous to list here. Please refer to the COPYRIGHT
+# file distributed with this source distribution.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+import re
+import sys
+import os
+import codecs
+
+# buffer english file (always open binary, handle newline uniformly as "\n")
+f = open("English.ini", "rbU")
+english = []
+for line in f:
+	english.append(line.rstrip("\n"))
+f.close
+
+transPattern = re.compile("\s*(\w+)\s*=(.+)$")
+
+def update(lang):
+	print "\nUpdate " + lang
+
+	# buffer translation file (always open binary, handle newline uniformly)
+	f = open(lang, "rbU")
+	translation = []
+	for line in f:
+		translation.append(line.rstrip("\n"))
+	f.close
+	# WORKAROUND: On windows the file does not seem to be closed by f.close
+	# as long as it is still referenced. Hence os.rename(lang, oldLang) will
+	# fail later as the file is still opened for reading.
+	f = None;
+
+	outList = []
+	# find new fields
+	for line in english:
+		# header
+		if re.search("\[Text\]", line, re.I):
+			outList.append(codecs.BOM_UTF8 + "[Text]")
+			continue
+		# ignore comments
+		elif re.match("\s*[;#]", line):
+			continue
+		# copy empty lines
+		elif re.match("\s*$", line):
+			outList.append("")
+			continue
+		m = transPattern.match(line)
+		if (not m):
+			print "Invalid line: " + line
+			sys.exit(1)
+		untranslated = True
+		for transline in translation:
+			m2 = re.match("\s*" + m.group(1) + "\s*=(.+)$", transline)
+			if (m2):
+				outList.append(m.group(1) + "=" + m2.group(1))
+				untranslated = False
+				break
+		if (untranslated):
+			print ("  +" + m.group(1))
+			outList.append(";TODO: " + line)
+
+	# find unsupported (not in English.ini) translations
+	for line in translation:
+		# ignore header
+		if re.search("\[Text\]", line, re.I):
+			continue
+		# ignore TODOs
+		if re.match(";TODO:", line):
+			continue
+		# copy comments
+		elif re.match("\s*[;#]", line):
+			outList.append(line)
+			continue
+		# ignore empty line
+		elif re.match("\s*$", line):
+			continue
+		m = transPattern.match(line)
+		if (not m):
+			print ("  -" + line)
+			outList.append(";INVALID: " + line)
+			continue
+		# check if field is in English.ini
+		unsupported = True
+		for orig in english:
+			m2 = re.match("\s*" + m.group(1) + "\s*=(.+)$", orig)
+			# ignore translated lines (already written in first pass)
+			if (m2):
+				unsupported = False
+				break
+		# unsupported translation
+		if (unsupported):
+			print ("  -" + m.group(1))
+			outList.append(";UNUSED: " + m.group(1) + "=" + m.group(2))
+
+	# check if file changed
+	changed = False
+	if (len(outList) != len(translation)):
+		changed = True
+	else:
+		# search for a changed line
+		for i in range(len(outList)):
+			if (outList[i] != translation[i]):
+				changed = True
+				break
+
+	# write changes
+	if changed:
+		# create a backup first
+		oldLang = lang + ".bak"
+		if (os.path.exists(oldLang)):
+			os.remove(oldLang)
+		os.rename(lang, oldLang)
+
+		f = open(lang, 'wb')
+		for line in outList:
+			# binary mode does not convert "\n" to the os specific line-ending.
+			# Use os.linesep instead.
+			f.write(line + os.linesep)
+		f.close()
+
+if len(sys.argv) >= 2:
+	# update specific language file passed as command-line argument
+	update(sys.argv[1])
+else:
+	# update all language (ini) files
+	iniList=os.listdir(".")
+	for ini in iniList: 
+		if not re.search(".ini$", ini):
+			continue
+		if ini == "English.ini":
+			continue
+		update(ini);
+
+	# update template (do not use an .ini prefix as USDX would load it)
+	update("Language.new");
diff --git a/songmanagement/game/plugins/5000points.usdx b/songmanagement/game/plugins/5000points.usdx
new file mode 100644
index 00000000..75dc4e03
--- /dev/null
+++ b/songmanagement/game/plugins/5000points.usdx
@@ -0,0 +1,74 @@
+--[[
+ * UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *]]
+    
+function plugin_init()
+  register('party mode: 5000points', '1.00', 'USDX Team', 'http://www.UltrastarDeluxe.org');
+
+  require('Usdx.Party')
+  require('Usdx.ScreenSing');
+
+  local Mode = {}
+
+  Mode.Name = '5000points'
+  Mode.CanNonParty = true;
+  Mode.CanParty = true;
+  Mode.OnSing = 'Sing';
+  Mode.AfterSing = 'Calculate_Winner';
+
+  Usdx.Party.Register(Mode)
+
+  return true;
+end
+
+function Sing()
+  Scores = ScreenSing.GetScores();
+
+  for i = 1, #Scores do
+    if (Scores[i] >= 5000) then
+      ScreenSing.Finish();
+      break;
+    end
+  end
+
+  return true;
+end
+
+function Calculate_Winner()
+  Scores = Scores or ScreenSing.GetScores();
+  local Ranking = {};
+  for i = 1, #Scores do
+    if Scores[i] >= 5000 then
+      Ranking[i] = 1
+    else
+      Ranking[i] = #Scores
+    end
+  end
+
+  Party.SetRoundRanking(Ranking);
+  Scores = nil;
+
+  return true;
+end
\ No newline at end of file
diff --git a/songmanagement/game/plugins/PluginDescription.odt b/songmanagement/game/plugins/PluginDescription.odt
new file mode 100644
index 00000000..476e5113
Binary files /dev/null and b/songmanagement/game/plugins/PluginDescription.odt differ
diff --git a/songmanagement/game/plugins/blind.usdx b/songmanagement/game/plugins/blind.usdx
new file mode 100644
index 00000000..73bbd98d
--- /dev/null
+++ b/songmanagement/game/plugins/blind.usdx
@@ -0,0 +1,53 @@
+--[[
+ * UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *]]
+ 
+function plugin_init()
+  register('party mode: blind', '1.00', 'USDX Team', 'http://www.UltrastarDeluxe.org');
+
+  require('Usdx.Party')
+  require('Usdx.ScreenSing')
+
+  local Mode = {}
+
+  Mode.Name = 'Blind'
+  Mode.CanNonParty = true;
+  Mode.CanParty = true;
+
+  Mode.BeforeSing = 'BeforeSing';
+
+  Usdx.Party.Register(Mode)
+
+  return true;
+end
+
+function BeforeSing()
+  local Settings = {};
+  Settings['NotesVisible'] = {}; -- notes hidden for every player
+
+  ScreenSing.SetSettings(Settings);
+
+  return true;
+end
\ No newline at end of file
diff --git a/songmanagement/game/plugins/duel.usdx b/songmanagement/game/plugins/duel.usdx
new file mode 100644
index 00000000..596aa270
--- /dev/null
+++ b/songmanagement/game/plugins/duel.usdx
@@ -0,0 +1,41 @@
+--[[
+ * UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *]]
+ 
+function plugin_init()
+  register('party mode: duel', '1.00', 'USDX Team', 'http://www.UltrastarDeluxe.org');
+
+  require('Usdx.Party')
+
+  local Mode = {}
+
+  Mode.Name = 'Duel'
+  Mode.CanNonParty = true;
+  Mode.CanParty = true;
+
+  Usdx.Party.Register(Mode)
+
+  return true;
+end
\ No newline at end of file
diff --git a/songmanagement/game/plugins/holdtheline.usdx b/songmanagement/game/plugins/holdtheline.usdx
new file mode 100644
index 00000000..85a57d21
--- /dev/null
+++ b/songmanagement/game/plugins/holdtheline.usdx
@@ -0,0 +1,219 @@
+--[[
+ * UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/game/plugins/holdtheline.usdx $
+ * $Id: holdtheline.usdx 2258 2010-06-17 17:30:16Z b_krueger $
+ *]]
+
+--Configuration
+-- limit to get
+local startRatingLimit = 0; --percentage : from 0 to 1 , eg. 0.1
+local fullRatingLimit = 1;  --percentage : from 0 to 1 , eg. 0.95
+local ratingLimit = startRatingLimit;
+
+-- percentage of the song-time, to need the full rating ( [start.beat + line.length] of the last line is the "end" of the song
+local percentageToFullRating = 0.75; --percentage : from 0 to 1 , eg. 0.75
+
+-- position of big progress bar in the center
+local Indicator = {};
+Indicator.Width  = 10; --pixles
+Indicator.Height = 10; --pixles
+
+--Do not Change a Line if ya do not know what ya doing!
+-- scoring
+local scores = {};
+local lastDissmissedNo;
+local dissmissedCount;
+
+
+function plugin_init()
+  register('party mode: holdtheline', '0.6', 'USDX Team', 'http://www.UltrastarDeluxe.org');
+
+  require('math', 'Usdx.Party', 'Usdx.ScreenSing', 'Usdx.Gl', 'Usdx.TextGl');
+  local Mode = {}
+
+  Mode.Name = 'holdtheline';
+  Mode.CanParty = true;
+  Mode.PlayerCount = {1,2,3,4,5,6};
+
+  Mode.BeforeSing = 'BeforeSing'
+  Mode.OnSing = 'Sing';
+  Mode.AfterSing = 'Finish';
+
+  Usdx.Party.Register(Mode);
+
+  return true;
+end
+
+
+function BeforeSing()
+  hSongLoaded = Usdx.Hook('ScreenSing.SongLoaded', 'Prepare');
+  hDraw = Usdx.Hook('Display.Draw', 'Draw');
+
+  return true;
+end;
+
+
+function Prepare()
+
+  -- get beat-sum of the whole song
+  local Lines = ScreenSing.GetSongLines();
+  local lastNote = Lines[#Lines].Notes[#Lines[#Lines].Notes];
+  TotalBeats = lastNote.Start + lastNote.Length;
+  
+  -- calculate OSD position for players
+  do
+    local RBRect = ScreenSing.GetRBRect();
+    OSD = {};
+
+    for i = 1, #RBRect do
+      OSD[i] = {};
+      OSD[i].Left   = RBRect[i].x;
+      OSD[i].Right  = RBRect[i].x + RBRect[i].w;
+      OSD[i].Top    = RBRect[i].y + RBRect[i].h;
+      OSD[i].Bottom = RBRect[i].y + RBRect[i].h + math.max(RBRect[i].h, 13);
+      scores[i] = false;
+    end;
+  end;
+
+  --fill some Vars with values
+  Teams = Party.GetTeams(); --team-infos
+  lastDissmissedNo = 1;     --dismissed-runner
+  dissmissedCount = 0;      --dismissed-counter
+
+  -- remove hook
+  hSongLoaded:Unhook();
+  hSongLoaded = nil;
+end;
+
+function DrawPlayerIndicator(i)
+  Gl.Disable('GL_TEXTURE_2D');
+
+ local xOffset = ratingLimit * (OSD[i].Right - OSD[i].Left)
+
+  -- background
+  Gl.Color (0, 1, 0, 1);
+  Gl.Begin('GL_QUADS');
+    Gl.Vertex(OSD[i].Left+xOffset-(Indicator.Width/2), OSD[i].Top+Indicator.Height);
+    Gl.Vertex(OSD[i].Left+xOffset, OSD[i].Top);
+    Gl.Vertex(OSD[i].Left+xOffset, OSD[i].Top);
+    Gl.Vertex(OSD[i].Left+xOffset+(Indicator.Width/2), OSD[i].Top+Indicator.Height);
+  Gl.End();
+end;
+
+function DrawOut(i)
+  Gl.Disable('GL_TEXTURE_2D');
+
+  local Text = ' OUT ';
+
+  -- text
+  Gl.Color(1, 0, 0, 1);
+  TextGl.Size(18);
+  TextGl.Style(1);
+  TextGl.Italic(false);
+  local PosX = (OSD[i].Left + OSD[i].Right) / 2;
+  PosX = PosX - TextGl.Width(Text) / 2;
+  TextGl.Pos(PosX, OSD[i].Top - 3);
+  TextGl.Print(Text);
+
+end;
+
+
+function Finish()
+
+  -- remove hook
+  hDraw:Unhook();
+  --hDraw = nil;
+
+  if dissmissedCount >= (#Teams-1) then 
+    --calculate scoring out of the dissmissed-order
+    local Ranking = {};
+    for i = 1, #Teams do
+      if (type(scores[i]) == "boolean") then 
+         Ranking[i] = 1;
+      else  
+         Ranking[i] = #Teams - scores[i] + 1;
+      end;
+    end;
+
+    Party.SetRoundRanking(Ranking);
+  end;
+
+  return (dissmissedCount < (#Teams-1));
+end;
+
+
+function Draw() 
+  for i = 1, #Teams do
+    if scores[i] == false then
+       DrawPlayerIndicator(i);
+    else 
+       --todo: draw dismissed-texture OVER the scoreing as a stamp or sth else
+       DrawOut(i);
+    end;
+  end;
+end;
+
+
+function Sing()
+  local Ratings = Usdx.ScreenSing.GetRating();
+  local finished = true;
+  local dismissedAPlayer = false;
+
+  -- calculate the x-offset of the indicator (ratingLimit)
+  local currentBeat = ScreenSing.GetBeat();
+
+  if (currentBeat<0) then
+    ratingLimit = startRatingLimit;
+  elseif (currentBeat <= (TotalBeats*percentageToFullRating)) then
+    ratingLimit = ((fullRatingLimit-startRatingLimit) / (TotalBeats*percentageToFullRating)) * currentBeat + startRatingLimit;    
+  else 
+    ratingLimit = fullRatingLimit;
+  end;
+
+  for i = 1, #Teams do
+    if scores[i] == false then
+      --player no. i is still in game
+      if Ratings[i] >= ratingLimit then
+        finished = false;
+      else 
+        --todo: play dismissed-sound
+        --todo: disable player i (bars from player i)
+        dismissedAPlayer = true;
+        dissmissedCount = dissmissedCount + 1;
+        scores[i] = lastDissmissedNo;
+      end;
+    end;
+  end;
+
+  --if more than one player is dismissed in one round,
+  --this guarantees correct scoring
+  if dismissedAPlayer == true then 
+    lastDissmissedNo = lastDissmissedNo + 1;
+  end;
+
+  --if only one player is in game, this round is finished
+  if dissmissedCount >= (#Teams-1) then 
+    ScreenSing.Finish();
+  end;
+
+end;
\ No newline at end of file
diff --git a/songmanagement/game/plugins/hooks.txt b/songmanagement/game/plugins/hooks.txt
new file mode 100644
index 00000000..7a91643d
--- /dev/null
+++ b/songmanagement/game/plugins/hooks.txt
@@ -0,0 +1,5 @@
+this document lists all hooks that are available and created by usdx
+Usdx.LoadingFinished - called when all plugins are loaded, not breakable
+Display.PreDraw - called before a frame is Drawn - not breakable
+Display.Draw - called after a frame w/ screen is drawn. you can draw above screen here
+ScreenSing.SongLoaded - called after a song is loaded to ScreenSing in OnShow, not breakable
\ No newline at end of file
diff --git a/songmanagement/game/plugins/teamduel.usdx b/songmanagement/game/plugins/teamduel.usdx
new file mode 100644
index 00000000..68e91da3
--- /dev/null
+++ b/songmanagement/game/plugins/teamduel.usdx
@@ -0,0 +1,258 @@
+--[[
+ * UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *]]
+
+-- some values to adjust the creation of PlayerChanges
+local MinPercentage = 0.06;  -- minimal amount of points between changes (in percent)
+local MaxPercentage = 0.12; -- maximal amount of points between changes (in percent)
+-- position of big progress bar in the center
+local BarPos = {};
+BarPos.Top = 30
+BarPos.Bottom = 50
+BarPos.Left = 300
+BarPos.Right = 500
+
+function plugin_init()
+  register('party mode: teamduel', '1.00', 'USDX Team', 'http://www.UltrastarDeluxe.org');
+
+  require('math', 'Usdx.Party', 'Usdx.ScreenSing', 'Usdx.Gl', 'Usdx.TextGl');
+  local Mode = {}
+
+  Mode.Name = 'teamduel';
+  Mode.CanParty = true;
+  Mode.PlayerCount = {2,3,4,5,6};
+
+  Mode.BeforeSing = 'BeforeSing'
+  Mode.OnSing = 'Sing';
+
+  Usdx.Party.Register(Mode)
+
+  ScreenSing.GetBeat();
+
+  return true;
+end
+
+-- called everytime a singing session w/ this party mode is startet
+-- we just hook ScreenSing.SongLoaded to prepare the mic changes here
+function BeforeSing()
+  hSongLoaded = Usdx.Hook('ScreenSing.SongLoaded', 'PrepareChanges');
+
+  -- execute default action (e.g. set correct singing playercount)
+  return true
+end;
+
+-- adds a new SentenceChange at Line to the PlayerChanges array
+function AddChange(Line)
+  PlayerChanges[#PlayerChanges + 1] = {};
+  PlayerChanges[#PlayerChanges].OnBeat = Lines[Line].Start;
+
+  PlayerChanges[#PlayerChanges].NextPlayer = {}
+  for i = 1, #Teams do
+    repeat
+      PlayerChanges[#PlayerChanges].NextPlayer[i] = math.random(#Teams[i].Players);
+    until (1 == #PlayerChanges) or (PlayerChanges[#PlayerChanges].NextPlayer[i] ~= PlayerChanges[#PlayerChanges-1].NextPlayer[i]) or (#Teams[i].Players == 1);
+  end;
+end;
+
+function PrepareChanges()
+  Lines = ScreenSing.GetSongLines();
+  Teams = Party.GetTeams();
+
+  -- get sum of hittable beats (per line and total)
+  local TotalBeats = 0;
+  local LineValue = {};
+  for i = 1, #Lines do
+    for j = 1, #Lines[i].Notes do
+      LineValue[i] = (LineValue[i] or 0) + Lines[i].Notes[j].Length * Lines[i].Notes[j].NoteType;
+    end;
+    TotalBeats = TotalBeats + LineValue[i];
+  end;
+
+  -- calculate changes
+  PlayerChanges = {};
+  -- fallback if there are only freestyle notes
+  -- random count of lines between changes
+  if (TotalBeats == 0) then
+    local i = 1;
+    repeat
+      if i > 1 then
+        AddChange(i);
+      end
+
+      local step = math.ceil((MinPercentage + (MaxPercentage - MinPercentage) * math.random()) * #Lines);
+      if step < 1 then
+        step = 1;
+      end;
+
+      i = i + step;
+    until i >= #Lines;
+  else -- calculate changes by amount of hittable beats
+    local i = 1;
+    local BeatsToChange = math.ceil((MinPercentage + (MaxPercentage - MinPercentage) * math.random()) * TotalBeats);
+    local Beats = 0;
+
+    repeat
+      Beats = Beats + LineValue[i];
+      if Beats >= BeatsToChange then
+        AddChange(i);
+        BeatsToChange = BeatsToChange + math.ceil((MinPercentage + (MaxPercentage - MinPercentage) * math.random()) * TotalBeats);
+      end
+      i = i + 1;
+    until i >= #Lines;
+  end;
+
+  -- free lines
+  Lines = nil;
+
+  -- init NextPlayerChange
+  NextPlayerChange = 1;
+
+  -- calculate OSD position for players
+  do
+    local RBRect = ScreenSing.GetRBRect();
+    OSD = {};
+
+    for i = 1, #RBRect do
+      OSD[i] = {};
+      OSD[i].Left   = RBRect[i].x;
+      OSD[i].Right  = RBRect[i].x + RBRect[i].w;
+      OSD[i].Top    = RBRect[i].y + RBRect[i].h;
+      OSD[i].Bottom = RBRect[i].y + RBRect[i].h + math.max(RBRect[i].h, 13);
+    end;
+  end;
+
+  -- remove hook
+  hSongLoaded:Unhook();
+  hSongLoaded = nil;
+end
+
+function DrawPlayerText(i, Text)
+  Gl.Disable('GL_TEXTURE_2D');
+
+  -- background
+  Gl.Color (0, 0, 0, 1);
+  Gl.Begin('GL_QUADS');
+    Gl.Vertex(OSD[i].Left, OSD[i].Top);
+    Gl.Vertex(OSD[i].Left, OSD[i].Bottom);
+    Gl.Vertex(OSD[i].Right, OSD[i].Bottom);
+    Gl.Vertex(OSD[i].Right, OSD[i].Top);
+  Gl.End();
+
+  -- text
+  Gl.Color(1, 0, 0, 1);
+  TextGl.Style(1);
+  TextGl.Size(18);
+  TextGl.Italic(false);
+  local PosX = (OSD[i].Left + OSD[i].Right) / 2;
+  PosX = PosX - TextGl.Width(Text) / 2;
+
+  TextGl.Pos(PosX, OSD[i].Top - 3);
+
+  TextGl.Print(Text);
+end;
+
+-- draws the progress bar for player i
+function DrawPlayerProgress(i, Progress)
+  Gl.Disable('GL_TEXTURE_2D');
+
+  -- background
+  Gl.Color (0, 0, 0, 1);
+  Gl.Begin('GL_QUADS');
+    Gl.Vertex(OSD[i].Left, OSD[i].Top);
+    Gl.Vertex(OSD[i].Left, OSD[i].Bottom);
+    Gl.Vertex(OSD[i].Right, OSD[i].Bottom);
+    Gl.Vertex(OSD[i].Right, OSD[i].Top);
+  Gl.End();
+
+  -- bar
+  Gl.Color(1, 0, 0, 1);
+  Gl.Begin('GL_QUADS');
+    Gl.Vertex(OSD[i].Left + 2, OSD[i].Top + 2);
+    Gl.Vertex(OSD[i].Left + 2, OSD[i].Bottom - 2);
+    Gl.Vertex(OSD[i].Left + 2 + (OSD[i].Right - OSD[i].Left - 4) * Progress, OSD[i].Bottom - 2);
+    Gl.Vertex(OSD[i].Left + 2 + (OSD[i].Right - OSD[i].Left - 4) * Progress, OSD[i].Top + 2);
+  Gl.End();
+end;
+
+-- draws the big progress bar in the screen center
+function DrawCenterProgress(Progress)
+  Gl.Disable('GL_TEXTURE_2D');
+
+  -- background
+  Gl.Color (0, 0, 0, 1);
+  Gl.Begin('GL_QUADS');
+    Gl.Vertex(BarPos.Left, BarPos.Top);
+    Gl.Vertex(BarPos.Left, BarPos.Bottom);
+    Gl.Vertex(BarPos.Right, BarPos.Bottom);
+    Gl.Vertex(BarPos.Right, BarPos.Top);
+  Gl.End();
+
+  -- bar
+  Gl.Color(1, 0, 0, 1);
+  Gl.Begin('GL_QUADS');
+    Gl.Vertex(BarPos.Left + 2, BarPos.Top + 2);
+    Gl.Vertex(BarPos.Left + 2, BarPos.Bottom - 2);
+    Gl.Vertex(BarPos.Left + 2 + (BarPos.Right - BarPos.Left - 4) * Progress, BarPos.Bottom - 2);
+    Gl.Vertex(BarPos.Left + 2 + (BarPos.Right - BarPos.Left - 4) * Progress, BarPos.Top + 2);
+  Gl.End();
+end;
+
+function Sing()
+  if (NextPlayerChange <= #PlayerChanges) then
+    local BeatsToNextChange = PlayerChanges[NextPlayerChange].OnBeat - ScreenSing.GetBeat();
+    local TimeToNextChange = ScreenSing.BeatsToSeconds(BeatsToNextChange);
+
+    -- draw next player text or progress bar
+    if (TimeToNextChange <= 0) then
+      --there is a change
+      NextPlayerChange = NextPlayerChange + 1;
+
+    elseif (TimeToNextChange <= 5) then
+      for i = 1, #Teams do
+        DrawPlayerProgress(i, 1 - TimeToNextChange/5);
+      end;
+    elseif (TimeToNextChange <= 6.5) then
+      for i = 1, #Teams do
+        DrawPlayerText(i, Teams[i].Players[PlayerChanges[NextPlayerChange].NextPlayer[i]].Name);
+      end;
+    elseif (TimeToNextChange <= 8) then
+      for i = 1, #Teams do
+        DrawPlayerText(i, 'Next Player');
+      end;
+    elseif (TimeToNextChange <= 9.5) then
+      for i = 1, #Teams do
+        DrawPlayerText(i, Teams[i].Players[PlayerChanges[NextPlayerChange].NextPlayer[i]].Name);
+      end;
+    elseif (TimeToNextChange <= 11) then
+      for i = 1, #Teams do
+        DrawPlayerText(i, 'Next Player');
+      end;
+    end
+
+    if (TimeToNextChange <= 11) then
+      DrawCenterProgress(1 - TimeToNextChange/11);
+    end;
+  end;
+end
\ No newline at end of file
diff --git a/songmanagement/game/resources/credits/credits_v5_bg.png b/songmanagement/game/resources/credits/credits_v5_bg.png
new file mode 100644
index 00000000..23dfedd7
Binary files /dev/null and b/songmanagement/game/resources/credits/credits_v5_bg.png differ
diff --git a/songmanagement/game/resources/credits/credits_v5_overlay.png b/songmanagement/game/resources/credits/credits_v5_overlay.png
new file mode 100644
index 00000000..6dad2a4f
Binary files /dev/null and b/songmanagement/game/resources/credits/credits_v5_overlay.png differ
diff --git a/songmanagement/game/resources/credits/intro-l-01.png b/songmanagement/game/resources/credits/intro-l-01.png
new file mode 100644
index 00000000..91561598
Binary files /dev/null and b/songmanagement/game/resources/credits/intro-l-01.png differ
diff --git a/songmanagement/game/resources/credits/intro-l-02.png b/songmanagement/game/resources/credits/intro-l-02.png
new file mode 100644
index 00000000..57a63175
Binary files /dev/null and b/songmanagement/game/resources/credits/intro-l-02.png differ
diff --git a/songmanagement/game/resources/credits/intro-l-03.png b/songmanagement/game/resources/credits/intro-l-03.png
new file mode 100644
index 00000000..d4d0757e
Binary files /dev/null and b/songmanagement/game/resources/credits/intro-l-03.png differ
diff --git a/songmanagement/game/resources/credits/intro-l-04.png b/songmanagement/game/resources/credits/intro-l-04.png
new file mode 100644
index 00000000..8c98b00a
Binary files /dev/null and b/songmanagement/game/resources/credits/intro-l-04.png differ
diff --git a/songmanagement/game/resources/credits/intro-l-05.png b/songmanagement/game/resources/credits/intro-l-05.png
new file mode 100644
index 00000000..793e27ae
Binary files /dev/null and b/songmanagement/game/resources/credits/intro-l-05.png differ
diff --git a/songmanagement/game/resources/credits/intro-l-06.png b/songmanagement/game/resources/credits/intro-l-06.png
new file mode 100644
index 00000000..c8e55c01
Binary files /dev/null and b/songmanagement/game/resources/credits/intro-l-06.png differ
diff --git a/songmanagement/game/resources/credits/intro-l-07.png b/songmanagement/game/resources/credits/intro-l-07.png
new file mode 100644
index 00000000..dd6286ae
Binary files /dev/null and b/songmanagement/game/resources/credits/intro-l-07.png differ
diff --git a/songmanagement/game/resources/credits/intro-l-08.png b/songmanagement/game/resources/credits/intro-l-08.png
new file mode 100644
index 00000000..034f9d24
Binary files /dev/null and b/songmanagement/game/resources/credits/intro-l-08.png differ
diff --git a/songmanagement/game/resources/credits/intro-l-09.png b/songmanagement/game/resources/credits/intro-l-09.png
new file mode 100644
index 00000000..7cd1f7f5
Binary files /dev/null and b/songmanagement/game/resources/credits/intro-l-09.png differ
diff --git a/songmanagement/game/resources/credits/names_alexanders.png b/songmanagement/game/resources/credits/names_alexanders.png
new file mode 100644
index 00000000..411b4b3e
Binary files /dev/null and b/songmanagement/game/resources/credits/names_alexanders.png differ
diff --git a/songmanagement/game/resources/credits/names_blindguard.png b/songmanagement/game/resources/credits/names_blindguard.png
new file mode 100644
index 00000000..a19f1b03
Binary files /dev/null and b/songmanagement/game/resources/credits/names_blindguard.png differ
diff --git a/songmanagement/game/resources/credits/names_blindy.png b/songmanagement/game/resources/credits/names_blindy.png
new file mode 100644
index 00000000..dab4a5d0
Binary files /dev/null and b/songmanagement/game/resources/credits/names_blindy.png differ
diff --git a/songmanagement/game/resources/credits/names_brunzel.png b/songmanagement/game/resources/credits/names_brunzel.png
new file mode 100644
index 00000000..f033b3bf
Binary files /dev/null and b/songmanagement/game/resources/credits/names_brunzel.png differ
diff --git a/songmanagement/game/resources/credits/names_canni.png b/songmanagement/game/resources/credits/names_canni.png
new file mode 100644
index 00000000..83294434
Binary files /dev/null and b/songmanagement/game/resources/credits/names_canni.png differ
diff --git a/songmanagement/game/resources/credits/names_commandio.png b/songmanagement/game/resources/credits/names_commandio.png
new file mode 100644
index 00000000..12214cb0
Binary files /dev/null and b/songmanagement/game/resources/credits/names_commandio.png differ
diff --git a/songmanagement/game/resources/credits/names_hennymcc.png b/songmanagement/game/resources/credits/names_hennymcc.png
new file mode 100644
index 00000000..f43f5401
Binary files /dev/null and b/songmanagement/game/resources/credits/names_hennymcc.png differ
diff --git a/songmanagement/game/resources/credits/names_jaybinks.png b/songmanagement/game/resources/credits/names_jaybinks.png
new file mode 100644
index 00000000..794943a2
Binary files /dev/null and b/songmanagement/game/resources/credits/names_jaybinks.png differ
diff --git a/songmanagement/game/resources/credits/names_krueger.png b/songmanagement/game/resources/credits/names_krueger.png
new file mode 100644
index 00000000..5f013d6b
Binary files /dev/null and b/songmanagement/game/resources/credits/names_krueger.png differ
diff --git a/songmanagement/game/resources/credits/names_lazyjoker.png b/songmanagement/game/resources/credits/names_lazyjoker.png
new file mode 100644
index 00000000..6d8a8a08
Binary files /dev/null and b/songmanagement/game/resources/credits/names_lazyjoker.png differ
diff --git a/songmanagement/game/resources/credits/names_mezzox.png b/songmanagement/game/resources/credits/names_mezzox.png
new file mode 100644
index 00000000..dd797c82
Binary files /dev/null and b/songmanagement/game/resources/credits/names_mezzox.png differ
diff --git a/songmanagement/game/resources/credits/names_mischi.png b/songmanagement/game/resources/credits/names_mischi.png
new file mode 100644
index 00000000..fffac577
Binary files /dev/null and b/songmanagement/game/resources/credits/names_mischi.png differ
diff --git a/songmanagement/game/resources/credits/names_mog.png b/songmanagement/game/resources/credits/names_mog.png
new file mode 100644
index 00000000..00da77b8
Binary files /dev/null and b/songmanagement/game/resources/credits/names_mog.png differ
diff --git a/songmanagement/game/resources/credits/names_mota.png b/songmanagement/game/resources/credits/names_mota.png
new file mode 100644
index 00000000..0263f71b
Binary files /dev/null and b/songmanagement/game/resources/credits/names_mota.png differ
diff --git a/songmanagement/game/resources/credits/names_skillmaster.png b/songmanagement/game/resources/credits/names_skillmaster.png
new file mode 100644
index 00000000..9f92cb6b
Binary files /dev/null and b/songmanagement/game/resources/credits/names_skillmaster.png differ
diff --git a/songmanagement/game/resources/credits/names_whiteshark.png b/songmanagement/game/resources/credits/names_whiteshark.png
new file mode 100644
index 00000000..a7e50a24
Binary files /dev/null and b/songmanagement/game/resources/credits/names_whiteshark.png differ
diff --git a/songmanagement/game/resources/credits/outro-bg.png b/songmanagement/game/resources/credits/outro-bg.png
new file mode 100644
index 00000000..4fbae8c9
Binary files /dev/null and b/songmanagement/game/resources/credits/outro-bg.png differ
diff --git a/songmanagement/game/resources/credits/outro-esc.png b/songmanagement/game/resources/credits/outro-esc.png
new file mode 100644
index 00000000..01ce735a
Binary files /dev/null and b/songmanagement/game/resources/credits/outro-esc.png differ
diff --git a/songmanagement/game/resources/credits/outro-exit-dark.png b/songmanagement/game/resources/credits/outro-exit-dark.png
new file mode 100644
index 00000000..dcb232f0
Binary files /dev/null and b/songmanagement/game/resources/credits/outro-exit-dark.png differ
diff --git a/songmanagement/game/resources/graphics/NoCover.jpg b/songmanagement/game/resources/graphics/NoCover.jpg
new file mode 100644
index 00000000..0a424708
Binary files /dev/null and b/songmanagement/game/resources/graphics/NoCover.jpg differ
diff --git a/songmanagement/game/resources/icons/ultrastardx-icon.png b/songmanagement/game/resources/icons/ultrastardx-icon.png
new file mode 100644
index 00000000..1b13a6ee
Binary files /dev/null and b/songmanagement/game/resources/icons/ultrastardx-icon.png differ
diff --git a/songmanagement/game/sounds/Common back.mp3 b/songmanagement/game/sounds/Common back.mp3
new file mode 100644
index 00000000..34354740
Binary files /dev/null and b/songmanagement/game/sounds/Common back.mp3 differ
diff --git a/songmanagement/game/sounds/Common start.mp3 b/songmanagement/game/sounds/Common start.mp3
new file mode 100644
index 00000000..34354740
Binary files /dev/null and b/songmanagement/game/sounds/Common start.mp3 differ
diff --git a/songmanagement/game/sounds/background track license.txt b/songmanagement/game/sounds/background track license.txt
new file mode 100755
index 00000000..7462de34
--- /dev/null
+++ b/songmanagement/game/sounds/background track license.txt	
@@ -0,0 +1,10 @@
+This work is licensed under the Creative Commons license by-sa 3.0.
+(http://creativecommons.org/licenses/by-sa/3.0/)
+
+Author:
+DJad (http://www.jamendo.com/de/artist/DJad)
+
+Distributed by:
+Site: jamendo.com
+File: DJad - Walking Alone.mp3
+URL:  http://www.jamendo.com/de/track/543970
diff --git a/songmanagement/game/sounds/background track.mp3 b/songmanagement/game/sounds/background track.mp3
new file mode 100755
index 00000000..f32135fc
Binary files /dev/null and b/songmanagement/game/sounds/background track.mp3 differ
diff --git a/songmanagement/game/sounds/credits-outro-tune.mp3 b/songmanagement/game/sounds/credits-outro-tune.mp3
new file mode 100644
index 00000000..fc23561c
Binary files /dev/null and b/songmanagement/game/sounds/credits-outro-tune.mp3 differ
diff --git a/songmanagement/game/sounds/dismissed.mp3 b/songmanagement/game/sounds/dismissed.mp3
new file mode 100644
index 00000000..f478e7a3
Binary files /dev/null and b/songmanagement/game/sounds/dismissed.mp3 differ
diff --git a/songmanagement/game/sounds/menu swoosh.mp3 b/songmanagement/game/sounds/menu swoosh.mp3
new file mode 100644
index 00000000..1025a86f
Binary files /dev/null and b/songmanagement/game/sounds/menu swoosh.mp3 differ
diff --git a/songmanagement/game/sounds/option change col.mp3 b/songmanagement/game/sounds/option change col.mp3
new file mode 100644
index 00000000..c2fcb43b
Binary files /dev/null and b/songmanagement/game/sounds/option change col.mp3 differ
diff --git a/songmanagement/game/sounds/rimshot022b.mp3 b/songmanagement/game/sounds/rimshot022b.mp3
new file mode 100644
index 00000000..9f49bab4
Binary files /dev/null and b/songmanagement/game/sounds/rimshot022b.mp3 differ
diff --git a/songmanagement/game/sounds/select music change music 50.mp3 b/songmanagement/game/sounds/select music change music 50.mp3
new file mode 100644
index 00000000..ade19a70
Binary files /dev/null and b/songmanagement/game/sounds/select music change music 50.mp3 differ
diff --git a/songmanagement/game/sounds/select music change music.mp3 b/songmanagement/game/sounds/select music change music.mp3
new file mode 100644
index 00000000..86a7218d
Binary files /dev/null and b/songmanagement/game/sounds/select music change music.mp3 differ
diff --git a/songmanagement/game/sounds/wome-credits-tune.mp3 b/songmanagement/game/sounds/wome-credits-tune.mp3
new file mode 100644
index 00000000..564e8d6f
Binary files /dev/null and b/songmanagement/game/sounds/wome-credits-tune.mp3 differ
diff --git a/songmanagement/game/themes/Candy.ini b/songmanagement/game/themes/Candy.ini
new file mode 100755
index 00000000..8bd894a4
--- /dev/null
+++ b/songmanagement/game/themes/Candy.ini
@@ -0,0 +1,7139 @@
+[Theme]
+Name = Candy
+Creator = Tamaki
+US_Version = USD 110
+
+# _______                    _    _ 
+#|__   __|                  | |  (_)
+#   | | __ _ _ __ ___   __ _| | ___ 
+#   | |/ _` | '_ ` _ \ / _` | |/ / |
+#   | | (_| | | | | | | (_| |   <| |
+#   |_|\__,_|_| |_| |_|\__,_|_|\_\_|
+#
+# Creator of Orange, Vistar and Streetlight
+# Themes for USDX 1.01
+#
+
+[Colors]
+White = 255 255 255
+Turkis = 13 186 167
+GrayLightest = 223 223 223
+GrayLight = 191 191 191
+Gray = 127 127 127
+GrayDark = 63 63 63
+Black = 0 0 0
+GrayPopup = 51 51 51
+Gold = 255 223 31
+Silver = 223 223 223
+Bronze = 205 127 50
+Red = 255 0 0
+Button = 188 77 148
+Light = 243 171 218
+
+[Loading]
+[LoadingBackground]
+Tex = LoadingBG
+
+[LoadingText1]
+X = 450
+Y = 200
+Color = Button
+Font = 0
+Align = 0
+Size = 24
+Text = SING_LOADING
+
+[LoadingText2]
+X = 790
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = US_VERSION
+
+#==================================================================== MAIN ==============
+
+[Main]
+[MainBackground]
+Tex = MainBG
+
+[MainText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = SING_MENU
+
+[MainTextDescriptionLong]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[MainButtonSolo]
+X = 18
+Y = 360
+W = 149
+H = 105
+Tex = ButtonMain
+Type = Transparent
+Color = White
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[MainButtonSoloText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_SING
+Color = Button
+
+[MainButtonMulti]
+X = 172
+Y = 360
+W = 149
+H = 105
+Tex = ButtonMain
+Type = Transparent
+Color = White
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[MainButtonMultiText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_MULTI
+Color = Button
+
+[MainButtonStats]
+X = 326
+Y = 360
+W = 149
+H = 105
+Tex = ButtonMain
+Type = Transparent
+Color = White
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[MainButtonStatsText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_STATS
+Color = Button
+
+[MainButtonOptions]
+X = 480
+Y = 360
+W = 149
+H = 105
+Tex = ButtonMain
+Type = Transparent
+Color = White
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[MainButtonOptionsText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_OPTIONS
+Color = Button
+
+[MainButtonExit]
+X = 634
+Y = 360
+W = 149
+H = 105
+Tex = ButtonMain
+Type = Transparent
+Color = White
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[MainButtonExitText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_EXIT
+Color = Button
+
+[MainStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[MainStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[MainText2]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[MainStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[MainText3]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_SELECT
+
+#================================================================== Song ======
+
+[Song]
+
+[SongBackground]
+Tex = MainBG
+
+[SongStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[SongTextCat]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_SONG_SELECTION_DESC
+
+[SongStatic2]
+X = 281
+Y = 104
+W = 240
+H = 215
+Z = 0.2
+Tex = SongSelection1
+Color = White
+Type = Transparent
+
+[SongStatic3]
+X = 281
+Y = 319
+W = 240
+H = 255
+Z = 0.97
+Tex = SongSelection2
+Color = White
+Type = Transparent
+
+[SongStatic4]
+X = 493
+Y = 522
+W = 8
+H = 10
+Z = 0.98
+Color = White
+Tex = icon_song_video
+Type = Transparent
+
+[SongCover]
+X = 300
+Y = 123
+W = 325
+H = 200
+Reflections = 1
+Style=5
+
+[SongEqualizer]
+Visible = 1
+Direction = 1
+Color = White
+Alpha = 1
+X = 300
+Y = 528
+PieceW = 5
+PieceH = 5
+Space = 1
+Bands = 6
+Length = 12
+
+[SongVideoIcon]
+X = 493
+Y = 522
+W = 8
+H = 10
+Z = 0.99
+Color = Button
+Tex = icon_song_video
+Type = Transparent
+
+[SongTextArtist]
+X = 400
+Y = 338
+W = 190
+Color = Button
+Font = 1
+Size = 24
+Align = 1
+Text =
+
+[SongTextTitle]
+X = 400
+Y = 404
+W = 190
+Color = Button
+Font = 0
+Size = 24
+Align = 1
+Text =
+
+[SongTextNumber]
+X = 488
+Y = 518
+Z = 0.95
+Color = Button
+Size = 18
+Align = 2
+
+#Variable statics and texts for song-screen in sing- and partymode
+# There can be an unlimited Number of Statics and Texts, As long
+# as the numbers are in order.
+# Statics that are shown in PartyMode Only are Named_
+#        SongStaticParty[No]
+# Texts that are shown in PartyMode Only are Named_
+#        SongTextParty[No]
+# Statics that are shown in Normal Mode Only are Named_
+#        SongStaticNonParty[No]
+# Texts that are shown in Normal Mode Only are Named_
+#        SongTextNonParty[No]
+#Here are the ones for singmode
+
+[SongTextNonParty1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = SING_SONG_SELECTION
+
+# NAVBAR #########################
+# Jump to a letter with [ALT] + [A..Z]
+[SongStaticNonParty1]
+X = 726
+Y = 35
+W = 22
+H = 22
+Tex = ButtonAlt
+Color = White
+Type = Transparent
+
+[SongTextNonParty2]
+X = 748
+Y = 33
+Color = Light
+Font = 0
+Size = 24
+Align = 0
+Text = +
+
+[SongStaticNonParty2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+
+[SongTextNonParty3]
+X = 720
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_SONG_SELECTION_GOTO
+
+# Menu opens with [M]
+[SongStaticNonParty3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonM
+Color = White
+Type = Transparent
+
+[SongTextNonParty4]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_SONG_SELECTION_MENU
+
+[SongStaticNonParty4]
+X = 759
+Y = 91
+W = 22
+H = 22
+Tex = ButtonJ
+Color = White
+Type = Transparent
+
+[SongTextNonParty5]
+X = 753
+Y = 90
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SONG_JUMPTO_DESC
+
+[SongStaticNonParty5]
+X = 759
+Y = 118
+W = 22
+H = 22
+Tex = ButtonP
+Color = White
+Type = Transparent
+
+[SongTextNonParty6]
+X = 753
+Y = 117
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_SONG_SELECTION_PLAYLIST
+
+
+
+#and these are the ones for partymode
+[SongStaticParty1]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = Button13
+Color = White
+Type = Transparent
+
+[SongTextParty1]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SONG_MENU_NAME_PARTY_JOKER
+
+# menu
+[SongStaticParty2]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonM
+Color = White
+Type = Transparent
+
+[SongTextParty2]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = PARTY_SONG_MENU
+
+[SongStaticParty3]
+X = 759
+Y = 91
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[SongTextParty3]
+X = 753
+Y = 90
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = PARTY_SONG_LEGEND_CONTINUE
+
+#Texts for Party Mode
+[SongTextParty4]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+#variable statics end
+
+# Jokers, 5 for each team, only shown in party Mode
+[SongStaticTeam1Joker1]
+Tex = Joker
+X = 100
+Y = 540
+W = 50
+H = 40
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+Z = 0.98
+
+[SongStaticTeam1Joker2]
+Tex = Joker
+X = 100
+Y = 500
+W = 50
+H = 40
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+Z = 0.98
+
+[SongStaticTeam1Joker3]
+Tex = Joker
+X = 100
+Y = 460
+W = 50
+H = 40
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+Z = 0.98
+
+[SongStaticTeam1Joker4]
+Tex = Joker
+X = 100
+Y = 420
+W = 50
+H = 40
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+Z = 0.98
+
+[SongStaticTeam1Joker5]
+Tex = Joker
+X = 100
+Y = 380
+W = 50
+H = 40
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+Z = 0.98
+
+[SongStaticTeam2Joker1]
+Tex = Joker
+X = 160
+Y = 540
+W = 50
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker2]
+Tex = Joker
+X = 160
+Y = 500
+W = 50
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker3]
+Tex = Joker
+X = 160
+Y = 460
+W = 50
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker4]
+Tex = Joker
+X = 160
+Y = 420
+W = 50
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker5]
+Tex = Joker
+X = 160
+Y = 380
+W = 50
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker1]
+Tex = Joker
+X = 220
+Y = 540
+W = 50
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker2]
+Tex = Joker
+X = 220
+Y = 500
+W = 50
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker3]
+Tex = Joker
+X = 220
+Y = 460
+W = 50
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker4]
+Tex = Joker
+X = 220
+Y = 420
+W = 50
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker5]
+Tex = Joker
+X = 220
+Y = 380
+W = 50
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+#==================================================================== Sing =============
+
+[Sing]
+Texts = 1
+Statics = 8
+
+[SingBackground]
+Type=color
+ColR=1
+ColB=1
+ColG=1
+
+[SingText1]
+Text = SING_TIME
+X = 45
+Y = 573
+Font = 1
+Size = 18
+Color = Button
+Align = 1
+
+[SingStatic1]
+Tex = LyricBar
+X = 0
+Y = 400
+W = 800
+H = 200
+Color = White
+Type = Transparent
+
+[SingTimeProgress]
+X = 80
+Y = 580
+W = 640
+H = 6
+Color = Button
+
+[SingTimeText]
+Text = SING_TIME
+X = 755
+Y = 573
+Font = 1
+Size = 18
+Color = Button
+Align = 1
+
+# O N E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#PlayerOne
+[SingP1Static]
+Tex = P
+X = 18
+Y = 296
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[SingP1Text]
+Text = P1
+X = 25
+Y = 302
+Font = 1
+Size = 18
+Color = P1Dark
+Align = 0
+
+[SingP1Static2]
+Tex = ScoreBG
+X = 676
+Y = 272
+W = 110
+H = 65
+Color = P1Dark
+Type = Colorized
+
+[SingP1TextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1SingBar]
+X = 685
+Y = 316
+W = 90
+H = 8
+
+# T W O  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1TwoPStatic]
+Tex = P
+X = 18
+Y = 115
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[SingP1TwoPText]
+Text = P1
+X = 25
+Y = 122
+Font = 1
+Size = 18
+Color = P1Dark
+Align = 0
+
+[SingP1TwoPStatic2]
+Tex = ScoreBG
+X = 676
+Y = 92
+W = 110
+H = 65
+Color = P1Dark
+Type = Colorized
+
+[SingP1TwoPTextScore]
+Text = 00000
+X = 698
+Y = 104
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1TwoPSingBar]
+X = 685
+Y = 136
+W = 90
+H = 8
+
+#Player Two
+[SingP2RStatic]
+Tex = P
+X = 18
+Y = 295
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[SingP2RText]
+Text = P2
+X = 25
+Y = 302
+Font = 1
+Size = 18
+Color = P2Dark
+Align = 0
+
+[SingP2RStatic2]
+Tex = ScoreBG
+X = 676
+Y = 272
+W = 110
+H = 65
+Color = P2Dark
+Type = Colorized
+
+[SingP2RTextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2RSingBar]
+X = 685
+Y = 316
+W = 90
+H = 8
+
+# T H R E E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1ThreePStatic]
+Tex = P
+X = 20
+Y = 61
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[SingP1ThreePText]
+Text = P1
+X = 27
+Y = 66
+Font = 1
+Size = 20
+Color = P1Dark
+Align = 0
+
+[SingP1ThreePStatic2]
+Tex = ScoreBG
+X = 66
+Y = 51
+W = 110
+H = 65
+Color = P1Dark
+Type = Colorized
+
+[SingP1ThreePTextScore]
+Text = 00000
+X = 88
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1ThreePSingBar]
+X = 75
+Y = 95
+W = 90
+H = 8
+
+#Player Two
+[SingP2MStatic]
+Tex = P
+X = 320
+Y = 61
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[SingP2MText]
+Text = P2
+X = 326
+Y = 66
+Font = 1
+Size = 20
+Color = P2Dark
+Align = 0
+
+[SingP2MStatic2]
+Tex = ScoreBG
+X = 366
+Y = 51
+W = 110
+H = 65
+Color = P2Dark
+Type = Colorized
+
+[SingP2MTextScore]
+Text = 00000
+X = 388
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2MSingBar]
+X = 375
+Y = 95
+W = 90
+H = 8
+
+#Player Three
+[SingP3RStatic]
+Tex = P
+X = 620
+Y = 61
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[SingP3RText]
+Text = P3
+X = 626
+Y = 66
+Font = 1
+Size = 20
+Color = P3Dark
+Align = 0
+
+[SingP3RStatic2]
+Tex = ScoreBG
+X = 666
+Y = 51
+W = 110
+H = 65
+Color = P3Dark
+Type = Colorized
+
+[SingP3RTextScore]
+Text = 00000
+X = 688
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP3SingBar]
+X = 675
+Y = 95
+W = 90
+H = 8
+
+#================================================================== Score ======
+
+[Score]
+[ScoreBackground]
+Tex = MainBG
+
+[ScoreText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = SONG_SCORE
+
+[ScoreTextArtistTitle]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = ArtistTitle
+
+[ScoreStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[ScoreStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[ScoreText2]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_CONTINUE
+
+# # # # # # # # # # # # # # # # # # One Player Score # # # # # # # # # # # #
+[ScoreTextName1]
+X = 197
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = Button
+Align = 0
+
+# Rating
+[ScoreStaticRatingPicture1]
+X = 385
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore1]
+X = 422
+Y = 235
+width = 100
+Color = Button
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+# Note Score
+[ScoreStaticBoxDark1]
+Tex = ScoreBar_box_dark
+X = 200
+Y = 326
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes1]
+X = 227
+Y = 322
+Color = Button
+Font = 0
+Size = 30
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore1]
+X = 487
+Y = 322
+Color = Button
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static1]
+Tex = ScoreLine
+X = 200
+Y = 351
+W = 287
+H = 1
+Color = Light
+Type = Transoarent
+
+# Line Bonus
+[ScoreStaticBoxLight1]
+Tex = ScoreBar_box_light
+X = 200
+Y = 358
+W = 22
+H = 20
+Color = P1Light
+Type = Colorized
+
+[ScoreTextLineBonus1]
+X = 227
+Y = 352
+Color = Button
+Font = 0
+Size = 30
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore1]
+X = 487
+Y = 352
+Color = Button
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static2]
+Tex = ScoreLine
+X = 200
+Y = 382
+W = 287
+H = 1
+Color = Light
+Type = Transparent
+
+# Golden Notes
+[ScoreStaticBoxLightest1]
+Tex = ScoreBar_box_lightest
+X = 200
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes1]
+X = 227
+Y = 383
+Color = Button
+Font = 0
+Size = 30
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore1]
+X = 487
+Y = 383
+Color = Button
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+#Total Score
+[ScorePlayer1Static3]
+Tex = PlayerIDBox01
+X = 200
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+
+[ScoreTextTotal1]
+X = 237
+Y = 454
+Color = Button
+Font = 1
+Size = 30
+Text = SING_TOTAL
+Align = 0
+
+[ScoreTextTotalSCore1]
+X = 487
+Y = 444
+Color = Button
+Font = 1
+Size = 42
+Align = 2
+Text = 0
+
+#ScoreBar
+[ScorePlayer1Static4]
+Tex = Scorepipe
+X = 536
+Y = 148
+W = 40
+H = 330
+Color = White
+Type = Transparent
+
+[ScoreStaticBackLevel1]
+Tex = ScoreLevel
+X = 551
+Y = 178
+W = 10
+H = 300
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound1]
+Tex = ScoreLevelRound
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel1]
+Tex = ScoreLevel
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound1]
+Tex = ScoreLevelRound
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer1Static5]
+Tex = ScoreEndCap
+X = 536
+Y = 478
+W = 40
+H = 40
+z = 0.9
+Color = P1Dark
+Type = Colorized
+
+# # # # # # # # # # # # # # # # # # Two Player Score # # # # # # # # # # # #
+# P L A Y E R   O N E
+[ScoreTextName2]
+X = 42
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = Button
+Align = 0
+
+[ScoreStaticRatingPicture2]
+X = 180
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore2]
+X = 217
+Y = 235
+Width = 100
+Color = Button
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark2]
+Tex = ScoreBar_box_dark
+X = 45
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes2]
+X = 72
+Y = 324
+Color = Button
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore2]
+X = 282
+Y = 324
+Color = Button
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLight2]
+Tex = ScoreBar_box_light
+X = 45
+Y = 358
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextLineBonus2]
+X = 72
+Y = 355
+Color = Button
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore2]
+X = 282
+Y = 355
+Color = Button
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLightest2]
+Tex = ScoreBar_box_lightest
+X = 45
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes2]
+X = 72
+Y = 387
+Color = Button
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore2]
+X = 282
+Y = 387
+Color = Button
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreTextTotal2]
+X = 82
+Y = 454
+Color = Button
+Font = 0
+Size = 30
+Text = SING_TOTAL
+
+[ScoreTextTotalSCore2]
+X = 283
+Y = 444
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+# Lines
+[ScorePlayer2Static1]
+Tex = ScoreLine
+X = 45
+Y = 351
+W = 237
+H = 1
+Type = Transparent
+Color = Light
+
+[ScorePlayer2Static2]
+Tex = ScoreLine
+X = 45
+Y = 382
+W = 237
+H = 1
+Type = Transparent
+Color = Light
+
+[ScorePlayer2Static5]
+Tex = PlayerIDBox01
+X = 45
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+
+#ScoreBar
+[ScoreStaticBackLevel2]
+Tex = ScoreLevel
+X = 309
+Y = 178
+W = 10
+H = 300
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound2]
+Tex = ScoreLevelRound
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel2]
+Tex = ScoreLevel
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound2]
+Tex = ScoreLevelRound
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer2Static3]
+Tex = ScoreEndCap
+X = 294
+Y = 478
+W = 40
+H = 40
+z = 0.9
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer2Static4]
+Tex = Scorepipe
+X = 294
+Y = 148
+W = 40
+H = 330
+z = 0.89
+Color = White
+Type = Transparent
+
+# P L A Y E R   T W O
+[ScoreTextName3]
+X = 758
+Y = 290
+Font = 0
+Size = 30
+Text = P2
+Color = Button
+Align = 2
+
+[ScoreStaticRatingPicture3]
+X = 545
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore3]
+X = 583
+Y = 235
+width = 100
+Color = Button
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark3]
+Tex = ScoreBar_box_dark
+X = 733
+Y = 327
+W = 22
+H = 20
+Color = P2Dark
+Type = Colorized
+
+[ScoreTextNotes3]
+X = 728
+Y = 324
+Color = Button
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 2
+
+[ScoreTextNotesScore3]
+X = 518
+Y = 324
+Color = Button
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLight3]
+Tex = ScoreBar_box_light
+X = 733
+Y = 358
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextLineBonus3]
+X = 728
+Y = 355
+Color = Button
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 2
+
+[ScoreTextLineBonusScore3]
+X = 518
+Y = 355
+Color = Button
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLightest3]
+Tex = ScoreBar_box_lightest
+X = 733
+Y = 390
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes3]
+X = 728
+Y = 387
+Color = Button
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 2
+
+[ScoreTextGoldenNotesScore3]
+X = 518
+Y = 387
+Color = Button
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreTextTotal3]
+X = 718
+Y = 454
+Color = Button
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 2
+
+[ScoreTextTotalScore3]
+X = 517
+Y = 444
+Color = Button
+Font = 0
+Size = 42
+Align = 0
+Text = 00000
+
+#Lines
+[ScorePlayer3Static1]
+Tex = ScoreLine
+X = 518
+Y = 351
+W = 237
+H = 1
+Type = Transparent
+Color = Light
+
+[ScorePlayer3Static2]
+Tex = ScoreLine
+X = 518
+Y = 382
+W = 237
+H = 1
+Type = Transparent
+Color = Light
+
+[ScorePlayer3Static5]
+Tex = PlayerIDBox02
+X = 729
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+
+#ScoreBar
+[ScoreStaticBackLevel3]
+Tex = ScoreLevel
+X = 475
+Y = 178
+W = 10
+H = 300
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound3]
+Tex = ScoreLevelRound
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticLevel3]
+Tex = ScoreLevel
+Color = P2Dark
+Type = Colorized
+
+[ScoreStaticLevelRound3]
+Tex = ScoreLevelRound
+Color = P2Dark
+Type = Colorized
+
+[ScorePlayer3Static3]
+Tex = ScoreEndCap
+X = 460
+Y = 478
+W = 40
+H = 40
+z = 0.9
+Color = P2Dark
+Type = Colorized
+
+[ScorePlayer3Static4]
+Tex = Scorepipe
+X = 460
+Y = 148
+W = 40
+H = 330
+z = 0.89
+Color = White
+Type = Transparent
+
+# # # # # # # # # # # # # # # # # # Three Player Score # # # # # # # # # # # #
+# P L A Y E R  O N E
+[ScoreTextName4]
+X = 20
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P1
+Color = P1Dark
+
+# Rating
+[ScoreStaticRatingPicture4]
+X = 200
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes4]
+X = 20
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = Button
+
+[ScoreTextNotesScore4]
+X = 260
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Button
+
+[ScoreTextLineBonus4]
+X = 20
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Button
+
+[ScoreTextLineBonusScore4]
+X = 260
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Button
+
+[ScoreTextGoldenNotes4]
+X = 20
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Button
+
+[ScoreTextGoldenNotesScore4]
+X = 260
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Button
+
+[ScoreTextScore4]
+X = 20
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = Button
+
+[ScoreTextTotal4]
+X = 47
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Button
+
+[ScoreTextTotalScore4]
+X = 260
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Button
+
+[ScoreStaticBoxDark4]
+Tex = P
+X = 16
+Y = 371
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[ScorePlayer4Text1]
+X = 24
+Y = 379
+W = 30
+H = 30
+Z = 1
+Color = P1Dark
+Font = 1
+Size = 15
+Align = 0
+Text = P1
+
+#lines
+[ScorePlayer4Static1]
+X = 20
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer4Static2]
+X = 20
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer4Static3]
+X = 20
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer4Static4]
+X = 20
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer4Static5]
+X = 20
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+# P L A Y E R  T W O
+[ScoreTextName5]
+X = 280
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P2
+Color = P2Dark
+
+# Rating
+[ScoreStaticRatingPicture5]
+X = 460
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes5]
+X = 280
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = Button
+
+[ScoreTextNotesScore5]
+X = 520
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Button
+
+[ScoreTextLineBonus5]
+X = 280
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Button
+
+[ScoreTextLineBonusScore5]
+X = 520
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Button
+
+[ScoreTextGoldenNotes5]
+X = 280
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Button
+
+[ScoreTextGoldenNotesScore5]
+X = 520
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Button
+
+[ScoreTextScore5]
+X = 280
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = Button
+
+[ScoreTextTotal5]
+X = 307
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Button
+
+[ScoreTextTotalScore5]
+X = 520
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Button
+
+[ScoreStaticBoxDark5]
+Tex = P
+X = 276
+Y = 371
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[ScorePlayer5Text1]
+X = 284
+Y = 379
+W = 30
+H = 30
+Z = 1
+Color = P2Dark
+Font = 1
+Size = 15
+Align = 0
+Text = P2
+
+[ScorePlayer5Static1]
+X = 280
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer5Static2]
+X = 280
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer5Static3]
+X = 280
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer5Static4]
+X = 280
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer5Static5]
+X = 280
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+# P L A Y E R  T H R E E
+[ScoreTextName6]
+X = 540
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P3
+Color = P3Dark
+
+# Rating
+[ScoreStaticRatingPicture6]
+X = 720
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes6]
+X = 540
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = Button
+
+[ScoreTextNotesScore6]
+X = 780
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Button
+
+[ScoreTextLineBonus6]
+X = 540
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Button
+
+[ScoreTextLineBonusScore6]
+X = 780
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Button
+
+[ScoreTextGoldenNotes6]
+X = 540
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Button
+
+[ScoreTextGoldenNotesScore6]
+X = 780
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Button
+
+[ScoreTextScore6]
+X = 540
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = Button
+
+[ScoreTextTotal6]
+X = 567
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Button
+
+[ScoreTextTotalScore6]
+X = 780
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Button
+
+[ScoreStaticBoxDark6]
+Tex = P
+X = 536
+Y = 371
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[ScorePlayer6Text1]
+X = 544
+Y = 379
+W = 30
+H = 30
+Z = 1
+Color = P3Dark
+Font = 1
+Size = 15
+Align = 0
+Text = P3
+
+#lines
+[ScorePlayer6Static1]
+X = 540
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer6Static2]
+X = 540
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer6Static3]
+X = 540
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer6Static4]
+X = 540
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+[ScorePlayer6Static5]
+X = 540
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Transparent
+Color = Light
+
+#================================================================== Options ======
+
+[Options]
+Fade = 2
+
+[OptionsBackground]
+Tex = MainBG
+
+[OptionsStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[OptionsText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsTextDescription]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[OptionsStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsText2]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[OptionsText3]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_SELECT
+
+[OptionsStatic4]
+X = 759
+Y = 91
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsText4]
+X = 753
+Y = 90
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[OptionsButtonGame]
+X = 95
+Y = 260
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[OptionsButtonGameText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_OPTIONS_GAME
+Color = Button
+
+[OptionsButtonGraphics]
+X = 249
+Y = 260
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[OptionsButtonGraphicsText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_OPTIONS_GRAPHICS
+Color = Button
+
+[OptionsButtonSound]
+X = 403
+Y = 260
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[OptionsButtonSoundText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_OPTIONS_SOUND
+Color = Button
+
+[OptionsButtonLyrics]
+X = 557
+Y = 260
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[OptionsButtonLyricsText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_OPTIONS_LYRICS
+Color = Button
+
+[OptionsButtonThemes]
+X = 95
+Y = 400
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[OptionsButtonThemesText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_OPTIONS_THEMES
+Color = Button
+
+[OptionsButtonRecord]
+X = 249
+Y = 400
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[OptionsButtonRecordText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_OPTIONS_RECORD
+Color = Button
+
+[OptionsButtonAdvanced]
+X = 403
+Y = 400
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[OptionsButtonAdvancedText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_OPTIONS_ADVANCED
+Color = Button
+
+[OptionsButtonExit]
+X = 557
+Y = 400
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[OptionsButtonExitText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = Button
+
+
+
+[OptionsGame]
+Texts = 5
+
+[OptionsGameBackground]
+Tex = OptionsBG
+
+[OptionsGameStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[OptionsGameText1]
+X = 80
+Y = 25
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsGameText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_GAME_DESC
+
+[OptionsGameStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsGameText3]
+X = 753
+Y = 34
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsGameStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsGameText4]
+X = 753
+Y = 62
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[OptionsGameSelectPlayers]
+Text = SING_OPTIONS_GAME_PLAYERS
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGameSelectDifficulty]
+Text = SING_OPTIONS_GAME_DIFFICULTY
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGameSelectSlideLanguage]
+Text = SING_OPTIONS_GAME_LANGUAGE
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGameSelectTabs]
+Text = SING_OPTIONS_GAME_TABS
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGameSelectSlideSorting]
+Text = SING_OPTIONS_GAME_SORTING
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGameSelectDebug]
+Text = SING_OPTIONS_GAME_DEBUG
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGameButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+
+[OptionsGraphics]
+[OptionsGraphicsBackground]
+Tex = OptionsBG
+
+[OptionsGraphicsStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[OptionsGraphicsText1]
+X = 80
+Y = 25
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsGraphicsText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_GRAPHICS_DESC
+
+[OptionsGraphicsStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsGraphicsText3]
+X = 753
+Y = 34
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsGraphicsStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsGraphicsText4]
+X = 753
+Y = 62
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[OptionsGraphicsSelectSlideResolution]
+Text = SING_OPTIONS_GRAPHICS_RESOLUTION
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGraphicsSelectFullscreen]
+Text = SING_OPTIONS_GRAPHICS_FULLSCREEN
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGraphicsSelectDepth]
+Text = SING_OPTIONS_GRAPHICS_DEPTH
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGraphicsSelectVisualizer]
+Text = SING_OPTIONS_GRAPHICS_VISUALIZER
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGraphicsSelectOscilloscope]
+Text = SING_OPTIONS_GRAPHICS_OSCILLOSCOPE
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGraphicsSelectMovieSize]
+Text = SING_OPTIONS_GRAPHICS_MOVIE_SIZE
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsGraphicsButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+
+[OptionsSound]
+[OptionsSoundBackground]
+Tex = OptionsBG
+
+[OptionsSoundStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[OptionsSoundText1]
+X = 80
+Y = 25
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsSoundText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_SOUND_DESC
+
+[OptionsSoundStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsSoundText3]
+X = 753
+Y = 34
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsSoundStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsSoundText4]
+X = 753
+Y = 62
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[OptionsSoundSelectVoicePassthrough]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_VOICEPASSTHROUGH
+X = 70
+Y = 130
+W = 250
+H = 35
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsSoundSelectBackgroundMusic]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_BACKGROUNDMUSIC
+X = 70
+Y = 170
+W = 250
+H = 35
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsSoundSelectMicBoost]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_MIC_BOOST
+X = 70
+Y = 210
+W = 250
+H = 35
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsSoundSelectClickAssist]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_CLICK_ASSIST
+X = 70
+Y = 250
+W = 250
+H = 35
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsSoundSelectBeatClick]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_BEAT_CLICK
+X = 70
+Y = 290
+W = 250
+H = 35
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsSoundSelectThreshold]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_THRESHOLD
+X = 70
+Y = 330
+W = 250
+H = 35
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsSoundSelectSlidePreviewVolume]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_PREVIEWVOLUME
+X = 70
+Y = 370
+W = 250
+H = 35
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsSoundSelectSlidePreviewFADING]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_PREVIEWFADING
+X = 70
+Y = 410
+W = 250
+H = 35
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsSoundButtonExit]
+X = 70
+Y = 460
+W = 250
+H = 40
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+
+[OptionsLyrics]
+[OptionsLyricsBackground]
+Tex = OptionsBG
+
+[OptionsLyricsStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[OptionsLyricsText1]
+X = 80
+Y = 25
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsLyricsText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_LYRICS_DESC
+
+[OptionsLyricsStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsLyricsText3]
+X = 753
+Y = 34
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsLyricsStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsLyricsText4]
+X = 753
+Y = 62
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[OptionsLyricsSelectLyricsFont]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_LYRICS_FONT
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsLyricsSelectLyricsEffect]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_LYRICS_EFFECT
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsLyricsSelectNoteLines]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = SING_OPTIONS_LYRICS_NOTELINES
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsLyricsButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+
+[OptionsThemes]
+[OptionsThemesBackground]
+Tex = MainBG
+
+[OptionsThemesStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[OptionsThemesText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsThemesText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_THEMES_DESC
+
+[OptionsThemesStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsThemesText3]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsThemesStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsThemesText4]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[OptionsThemesSelectTheme]
+Text = SING_OPTIONS_THEMES_THEME
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsThemesSelectSkin]
+Text = SING_OPTIONS_THEMES_SKIN
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsThemesSelectColor]
+Text = SING_OPTIONS_THEMES_COLOR
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsThemesButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+
+[OptionsRecord]
+[OptionsRecordBackground]
+Tex = OptionsBG
+
+[OptionsRecordStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[OptionsRecordText1]
+X = 80
+Y = 25
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsRecordText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_RECORD_DESC
+
+[OptionsRecordStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsRecordText3]
+X = 753
+Y = 34
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsRecordStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsRecordText4]
+X = 753
+Y = 62
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[OptionsRecordSelectSlideCard]
+Text = SING_OPTIONS_RECORD_CARD
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsRecordSelectSlideInput]
+Text = SING_OPTIONS_RECORD_INPUT
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsRecordSelectSlideChannel]
+Text = SING_OPTIONS_RECORD_CHANNEL
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = Button
+STDColor = White
+
+[OptionsRecordButtonExit]
+X = 70
+Y = 390
+W = 250
+H = 40
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+
+[OptionsAdvanced]
+[OptionsAdvancedBackground]
+Tex = OptionsBG
+
+[OptionsAdvancedStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[OptionsAdvancedText1]
+X = 80
+Y = 25
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsAdvancedText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_ADVANCED_DESC
+
+[OptionsAdvancedStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsAdvancedText3]
+X = 753
+Y = 34
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsAdvancedStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsAdvancedText4]
+X = 753
+Y = 62
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[OptionsAdvancedSelectScreenFade]
+Text = SING_OPTIONS_ADVANCED_SCREENFADE
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsAdvancedSelectEffectSing]
+Text = SING_OPTIONS_ADVANCED_EFFECTSING
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsAdvancedSelectLineBonus]
+Text = SING_OPTIONS_GRAPHICS_LINEBONUS
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsAdvancedSelectSlideOnSongClick]
+Text = SING_OPTIONS_ADVANCED_ONSONGCLICK
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsAdvancedSelectAskbeforeDel]
+Text = SING_OPTIONS_ADVANCED_ASKBEFOREDEL
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsAdvancedSelectPartyPopup]
+Text = SING_OPTIONS_ADVANCED_PARTYPOPUP
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[OptionsAdvancedButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+
+#================================================================== Top 5 ======
+
+[Top5]
+[Top5Background]
+Tex = MainBG
+
+[Top5Text1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = SING_TOP_5_CHARTS
+
+[Top5TextArtistTitle]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = artist - title
+
+[Top5Text2]
+X = 80
+Y = 95
+Color = Button
+Font = 1
+Size = 30
+Align = 0
+Text = SING_OPTIONS_GAME_DIFFICULTY
+
+[Top5TextLevel]
+X = 280
+Y = 95
+Color = Button
+Font = 1
+Size = 30
+Align = 1
+Text = easy
+
+[Top5Static1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[Top5Static2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[Top5Text3]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_TOP_5_CHARTS_CONTINUE
+
+[Top5Static3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[Top5Text4]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_TOP_5_CHARTS_SWITCH_DIFFICULTY
+
+[Top5TextName1]
+X = 150
+Y = 190
+Color = Button
+Font = 0
+Size = 42
+Align = 0
+Text = 1. Player1
+
+[Top5TextName2]
+X = 150
+Y = 240
+Color = Button
+Font = 0
+Size = 42
+Align = 0
+Text = 2. Player2
+
+[Top5TextName3]
+X = 150
+Y = 290
+Color = Button
+Font = 0
+Size = 42
+Align = 0
+Text = 3. Player3
+
+[Top5TextName4]
+X = 150
+Y = 340
+Color = Button
+Font = 0
+Size = 42
+Align = 0
+Text = 4. Player4
+
+[Top5TextName5]
+X = 150
+Y = 390
+Color = Button
+Font = 0
+Size = 42
+Align = 0
+Text = 5. Player5
+
+[Top5TextScore1]
+X = 560
+Y = 190
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore2]
+X = 560
+Y = 240
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore3]
+X = 560
+Y = 290
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore4]
+X = 560
+Y = 340
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore5]
+X = 560
+Y = 390
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+
+[Top5TextDate1]
+X = 760
+Y = 190
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate2]
+X = 760
+Y = 240
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate3]
+X = 760
+Y = 290
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate4]
+X = 760
+Y = 340
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate5]
+X = 760
+Y = 390
+Color = Button
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextNumber1]
+X = 120
+Y = 193
+Color = Button
+Font = 1
+Size = 27
+Align = 1
+Text = 1
+
+[Top5TextNumber2]
+X = 120
+Y = 243
+Color = Button
+Font = 1
+Size = 27
+Align = 1
+Text = 2
+
+[Top5TextNumber3]
+X = 120
+Y = 293
+Color = Button
+Font = 1
+Size = 27
+Align = 1
+Text = 3
+
+[Top5TextNumber4]
+X = 120
+Y = 343
+Color = Button
+Font = 1
+Size = 27
+Align = 1
+Text = 4
+
+[Top5TextNumber5]
+X = 120
+Y = 393
+Color = Button
+Font = 1
+Size = 27
+Align = 1
+Text = 5
+
+[Top5StaticNumber1]
+Tex = P
+X = 105
+Y = 192
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[Top5StaticNumber2]
+Tex = P
+X = 105
+Y = 242
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[Top5StaticNumber3]
+Tex = P
+X = 105
+Y = 292
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[Top5StaticNumber4]
+Tex = PlayerNumberBox
+Tex = P
+X = 105
+Y = 342
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[Top5StaticNumber5]
+Tex = PlayerNumberBox
+Tex = P
+X = 105
+Y = 392
+W = 30
+H = 40
+Color = White
+Type = Transparent
+
+[Edit]
+[EditBackground]
+Tex = EditBG
+
+# main icon
+[EditStatic1]
+X = 65
+Y = 150
+W = 25
+H = 25
+Color = White
+Tex = IconEdit
+Type = Transparent
+# Type = Colorized
+
+# main icon title
+[EditText1]
+X = 95
+Y = 135
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_EDIT
+
+# main icon subtitle
+[EditText2]
+X = 95
+Y = 175
+Color = ColorLightest
+Font = 0
+Size = 30
+Align = 0
+Text = SING_EDIT_MENU_DESCRIPTION
+
+# Navigate button text
+[EditText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+# Select button text
+[EditText4]
+X = 440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_SELECT
+Reflection=1
+ReflectionSpacing=13
+
+# Esc button text
+[EditText5]
+X = 590
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_EXIT
+Reflection=1
+ReflectionSpacing=13
+
+[EditTextDescription]
+X = 95
+Y = 195
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = SING_EDIT_TEXTDESCRIPTION
+
+[EditStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic6]
+X = 550
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditButtonConvert]
+X = 250
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[EditButtonConvertText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_CONVERT
+Color = White
+
+[EditButtonExit]
+X = 405
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[EditButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_EXIT
+Color = White
+
+================================================================== Level ======
+
+[Level]
+[LevelBackground]
+Tex = MainBG
+
+[LevelStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[LevelText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = SING_MODE
+
+[LevelText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_DIFFICULTY_DESC
+
+[LevelStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[LevelText3]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[LevelStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[LevelText4]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_DIFFICULTY_CONTINUE
+
+[LevelButtonEasy]
+X = 172
+Y = 360
+W = 149
+H = 105
+Tex = ButtonMain
+Type = Transparent
+Color = White
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[LevelButtonMedium]
+X = 326
+Y = 360
+W = 149
+H = 105
+Tex = ButtonMain
+Type = Transparent
+Color = White
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[LevelButtonHard]
+X = 480
+Y = 360
+W = 149
+H = 105
+Tex = ButtonMain
+Type = Transparent
+Color = White
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[LevelButtonEasyText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Color = Button
+Text = SING_EASY
+
+[LevelButtonMediumText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Color = Button
+Text = SING_MEDIUM
+
+[LevelButtonHardText1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Color = Button
+Text = SING_HARD
+
+#================================================================== Name ======
+
+[Name]
+[NameBackground]
+Tex  = MainBG
+
+[NameStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[NameText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = SING_MODE
+
+[NameText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = SING_PLAYER_DESC
+
+[NameStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[NameText3]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[NameStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+
+[NameText4]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_PLAYER_ENTER_NAME
+
+[NameStatic4]
+X = 759
+Y = 91
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[NameText5]
+X = 753
+Y = 90
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_CONTINUE
+
+[NameButtonPlayer1]
+X = 172
+Y = 260
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[NameButtonPlayer1Text1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = 
+Color = P1Dark
+DColor = P1Light
+
+[NameButtonPlayer2]
+X = 326
+Y = 260
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[NameButtonPlayer2Text1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = 
+Color = P2Dark
+DColor = P2Light
+
+[NameButtonPlayer3]
+X = 480
+Y = 260
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[NameButtonPlayer3Text1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = 
+Color = P3Dark
+DColor = P3Light
+
+[NameButtonPlayer4]
+X = 172
+Y = 400
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[NameButtonPlayer4Text1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = 
+Color = P4Dark
+DColor = P4Light
+
+[NameButtonPlayer5]
+X = 326
+Y = 400
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[NameButtonPlayer5Text1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = 
+Color = P5Dark
+DColor = P5Light
+
+[NameButtonPlayer6]
+X = 480
+Y = 400
+W = 149
+H = 105
+Tex = ButtonMain
+Color = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 70
+FadeTex = Transparent
+FadeTexPos = 0
+
+[NameButtonPlayer6Text1]
+X = 75
+Y = 28
+Font = 1
+Size = 32
+Align = 1
+Text = 
+Color = P6Dark
+DColor = P6Light
+
+#================================================================== Party ======
+
+[PartyNewRound]
+[PartyNewRoundBackground]
+Tex = OptionsBG
+
+[PartyNewRoundStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[PartyNewRoundText1]
+X = 80
+Y = 25
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyNewRoundText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_ROUND_DESC
+
+[PartyNewRoundText3]
+X = 753
+Y = 34
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = PARTY_ROUND_LEGEND_CONTINUE
+
+[PartyNewRoundText4]
+X = 460
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND
+Align = 0
+
+[PartyNewRoundText5]
+X = 600
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND_WINNER
+Align = 0
+
+[PartyNewRoundText6]
+X = 448
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = PARTY_ROUND
+Align = 2
+
+[PartyNewRoundTextTeam1Players]
+X = 30
+Y = 137
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam2Players]
+X = 30
+Y = 218
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam3Players]
+X = 30
+Y = 299
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundStatic2]
+Tex = PartyRoundBG1
+X = 450
+Y = 103
+W = 330
+H = 24
+Color = Button
+Type = Transparent
+
+[PartyNewRoundStatic3]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyNewRoundStatic4]
+Tex = PartyRoundBG3
+X = 250
+Y = 350
+W = 300
+H = 50
+Color = Button
+Type = Transparent
+
+[PartyNewRoundStatic5]
+Tex = PartyRoundBG4
+X = 50
+Y = 495
+W = 700
+H = 30
+Color = Button
+Type = Transparent
+
+[PartyNewRoundStaticTeam1]
+Tex = PartyTeamButton1
+X = 20
+Y = 110
+W = 400
+H = 50
+Color = P1Dark
+Type = Transparent
+
+[PartyNewRoundStaticTeam2]
+Tex = PartyTeamButton1
+X = 20
+Y = 191
+W = 400
+H = 50
+Color = P2Dark
+Type = Transparent
+
+[PartyNewRoundStaticTeam3]
+Tex = PartyTeamButton1
+X = 20
+Y = 272
+W = 400
+H = 50
+Color = P3Dark
+Type = Transparent
+
+[PartyNewRoundStaticNextPlayer1]
+Tex = PartyPlayerButton
+X = 155
+Y = 415
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Light
+Z = 0.9
+
+[PartyNewRoundStaticNextPlayer2]
+Tex = PartyPlayerButton
+X = 325
+Y = 415
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Light
+Z = 0.9
+
+[PartyNewRoundStaticNextPlayer3]
+Tex = PartyPlayerButton
+X = 495
+Y = 415
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Light
+Z = 0.9
+
+[PartyNewRoundTextRound1]
+X = 460
+Y = 133
+Color = Button
+Font = 0
+Size = 24
+Text = Round 1
+Align = 0
+
+[PartyNewRoundTextRound2]
+X = 460
+Y = 162
+Color = Button
+Font = 0
+Size = 24
+Text = Round 2
+Align = 0
+
+[PartyNewRoundTextRound3]
+X = 460
+Y = 191
+Color = Button
+Font = 0
+Size = 24
+Text = Round 3
+Align = 0
+
+[PartyNewRoundTextRound4]
+X = 460
+Y = 220
+Color = Button
+Font = 0
+Size = 24
+Text = Round 4
+Align = 0
+
+[PartyNewRoundTextRound5]
+X = 460
+Y = 249
+Color = Button
+Font = 0
+Size = 24
+Text = Round 5
+Align = 0
+
+[PartyNewRoundTextRound6]
+X = 460
+Y = 278
+Color = Button
+Font = 0
+Size = 24
+Text = Round 6
+Align = 0
+
+[PartyNewRoundTextRound7]
+X = 460
+Y = 307
+Color = Button
+Font = 0
+Size = 24
+Text = Round 7
+Align = 0
+
+[PartyNewRoundTextWinner1]
+X = 600
+Y = 133
+Color = Button
+Font = 0
+Size = 24
+Text = Winner 1
+Align = 0
+
+[PartyNewRoundTextWinner2]
+X = 600
+Y = 162
+Color = Button
+Font = 0
+Size = 24
+Text = Winner 2
+Align = 0
+
+[PartyNewRoundTextWinner3]
+X = 600
+Y = 191
+Color = Button
+Font = 0
+Size = 24
+Text = Winner 3
+Align = 0
+
+[PartyNewRoundTextWinner4]
+X = 600
+Y = 220
+Color = Button
+Font = 0
+Size = 24
+Text = Winner 4
+Align = 0
+
+[PartyNewRoundTextWinner5]
+X = 600
+Y = 249
+Color = Button
+Font = 0
+Size = 24
+Text = Winner 5
+Align = 0
+
+[PartyNewRoundTextWinner6]
+X = 600
+Y = 278
+Color = Button
+Font = 0
+Size = 24
+Text = Winner 6
+Align = 0
+
+[PartyNewRoundTextWinner7]
+X = 600
+Y = 307
+Color = Button
+Font = 0
+Size = 24
+Text = Winner 7
+Align = 0
+
+[PartyNewRoundStaticRound1]
+Tex = PartyRoundBG2
+X = 450
+Y = 135
+W = 330
+H = 20
+Color = Light
+Type = Transparent
+Z = 0.9
+
+[PartyNewRoundStaticRound2]
+Tex = PartyRoundBG2
+X = 450
+Y = 164
+W = 330
+H = 20
+Color = Light
+Type = Transparent
+Z = 0.9
+[PartyNewRoundStaticRound3]
+Tex = PartyRoundBG2
+X = 450
+Y = 193
+W = 330
+H = 20
+Color = Light
+Type = Transparent
+Z = 0.9
+
+[PartyNewRoundStaticRound4]
+Tex = PartyRoundBG2
+X = 450
+Y = 222
+W = 330
+H = 20
+Color = Light
+Type = Transparent
+Z = 0.9
+
+[PartyNewRoundStaticRound5]
+Tex = PartyRoundBG2
+X = 450
+Y = 251
+W = 330
+H = 20
+Color = Light
+Type = Transparent
+Z = 0.9
+
+[PartyNewRoundStaticRound6]
+Tex = PartyRoundBG2
+X = 450
+Y = 280
+W = 330
+H = 20
+Color = Light
+Type = Transparent
+Z = 0.9
+
+[PartyNewRoundStaticRound7]
+Tex = PartyRoundBG2
+X = 450
+Y = 309
+W = 330
+H = 20
+Color = Light
+Type = Transparent
+Z = 0.9
+
+[PartyNewRoundTextNextRound]
+X = 400
+Y = 495
+Color = White
+Font = 0
+Size = 30
+Text = Next Round
+Align = 1
+
+[PartyNewRoundTextNextRoundNo]
+X = 457
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = 99
+Align = 0
+
+[PartyNewRoundTextScoreTeam1]
+X = 390
+Y = 110
+Color = White
+Font = 0
+Size = 51
+Text = 3000
+Align = 1
+
+[PartyNewRoundTextScoreTeam2]
+X = 390
+Y = 191
+Color = White
+Font = 0
+Size = 51
+Text = 2000
+Align = 1
+
+[PartyNewRoundTextScoreTeam3]
+X = 390
+Y = 272
+Color = White
+Font = 0
+Size = 51
+Text = 1000
+Align = 1
+
+[PartyNewRoundTextNameTeam1]
+X = 30
+Y = 108
+Color = White
+Font = 0
+Size = 36
+Text = Team 1
+Align = 0
+
+[PartyNewRoundTextNameTeam2]
+X = 30
+Y = 189
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyNewRoundTextNameTeam3]
+X = 30
+Y = 270
+Color = White
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyNewRoundTextNextPlayer1]
+X = 230
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 1
+Align = 1
+
+[PartyNewRoundTextNextPlayer2]
+X = 400
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 2
+Align = 1
+
+[PartyNewRoundTextNextPlayer3]
+X = 570
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 3
+Align = 1
+
+
+[PartyScore]
+[PartyScoreBackground]
+Tex = MainBG
+
+[PartyScoreStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[PartyScoreStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyScoreText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyScoreText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_SCORE_DESC
+
+[PartyScoreText3]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = PARTY_LEGEND_CONTINUE
+
+[PartyScoreStatic3]
+Tex = StatsBox
+X = 118
+Y = 200
+W = 565
+H = 370
+Color = White
+Type = Transparent
+
+[PartyScoreText4]
+X = 400
+Y = 246
+Color = Button
+Font = 0
+Size = 45
+Text = PARTY_SCORE_WINS2
+Align = 1
+
+[PartyScoreTextWinner]
+X = 400
+Y = 208
+Color = Button
+Font = 0
+Size = 54
+Text = The Winner is...
+Align = 1
+
+[PartyScoreTextScoreTeam1]
+X = 612
+Y = 298
+Color = P1Dark
+Font = 0
+Size = 36
+Text = 3000
+Align = 2
+
+[PartyScoreTextScoreTeam2]
+X = 612
+Y = 378
+Color = P2Dark
+Font = 0
+Size = 36
+Text = 2000
+Align = 2
+
+[PartyScoreTextScoreTeam3]
+X = 612
+Y = 458
+Color = P3Dark
+Font = 0
+Size = 36
+Text = 1000
+Align = 2
+
+[PartyScoreTextNameTeam1]
+X = 188
+Y = 298
+Font = 0
+Size = 36
+Align = 0
+Text = Team 1
+Color = P1Dark
+
+[PartyScoreTextNameTeam2]
+X = 188
+Y = 378
+Color = P2Dark
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyScoreTextNameTeam3]
+X = 188
+Y = 458
+Color = P3Dark
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyWin]
+[PartyWinBackground]
+Tex = MainBG
+
+[PartyWinStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[PartyWinStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyWinText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyWinText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_WIN_DESC
+
+[PartyWinText3]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = PARTY_WIN_LEGEND_CONTINUE
+
+[PartyWinTextNameTeam1]
+X = 400
+Y = 210
+Font = 0
+Size = 36
+Align = 1
+Text = Team 1
+Color = Button
+
+[PartyWinTextNameTeam2]
+X = 240
+Y = 230
+Color = Button
+Font = 0
+Size = 36
+Text = Team 2
+Align = 1
+
+[PartyWinTextNameTeam3]
+X = 560
+Y = 250
+Color = Button
+Font = 0
+Size = 36
+Text = Team 3
+Align = 1
+
+[PartyWinTextScoreTeam1]
+X = 400
+Y = 240
+Color = Button
+Font = 0
+Size = 36
+Text = 3000
+Align = 1
+
+[PartyWinTextScoreTeam2]
+X = 240
+Y = 260
+Color = Button
+Font = 0
+Size = 36
+Text = 2000
+Align = 1
+
+[PartyWinTextScoreTeam3]
+X = 560
+Y = 280
+Color = Button
+Font = 0
+Size = 36
+Text = 1000
+Align = 1
+
+[PartyWinStaticTeam1BG]
+Tex = ButtonMain
+X = 325
+Y = 200
+W = 149
+H = 105
+Type = Transparent
+Color = White
+
+[PartyWinStaticTeam1Deco]
+Tex = PartyWinDeco1
+X = 310
+Y = 165
+W = 30
+H = 64
+Type = Colorized
+Color = Gold
+
+[PartyWinStaticTeam2BG]
+Tex = ButtonMain
+X = 165
+Y = 220
+W = 149
+H = 105
+Type = Transparent
+Color = White
+
+[PartyWinStaticTeam2Deco]
+Tex = PartyWinDeco2
+X = 150
+Y = 185
+W = 30
+H = 64
+Type = Colorized
+Color = Silver
+
+[PartyWinStaticTeam3BG]
+Tex = ButtonMain
+X = 485
+Y = 240
+W = 149
+H = 105
+Type = Transparent
+Color = White
+
+[PartyWinStaticTeam3Deco]
+Tex = PartyWinDeco3
+X = 470
+Y = 205
+W = 30
+H = 64
+Type = Colorized
+Color = Bronze
+
+#===================================================== Party site 1 ===
+
+[PartyOptions]
+[PartyOptionsBackground]
+Tex = MainBG
+
+[PartyOptionsStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[PartyOptionsText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyOptionsText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_OPTIONS_DESC
+
+[PartyOptionsStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyOptionsText3]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[PartyOptionsStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyOptionsText4]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_CONTINUE
+
+[PartyOptionsStatic4]
+X = 75
+Y = 300
+W = 650
+H = 202
+Tex = Party1BG
+Color = White
+Type = Transparent
+
+[PartyOptionsSelectLevel]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = PARTY_DIFFICULTY
+X = 95
+Y = 328
+W = 200
+H = 34
+SkipX = 10
+Fields = 1
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyOptionsSelectPlayList]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = PARTY_PLAYLIST
+X = 95
+Y = 372
+W = 200
+H = 34
+SkipX = 10
+Fields = 1
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyOptionsSelectPlayList2]
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+Text = PARTY_PLAYLIST
+X = 95
+Y = 416
+W = 200
+H = 34
+SkipX = 10
+Fields = 1
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyPlayer]
+[PartyPlayerBackground]
+Tex = OptionsBG
+
+[PartyPlayerStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic4]
+X = 759
+Y = 91
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyPlayerText1]
+X = 80
+Y = 25
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyPlayerText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_PLAYER_DESC
+
+[PartyPlayerText3]
+X = 753
+Y = 34
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[PartyPlayerText4]
+X = 753
+Y = 62
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = PARTY_PLAYER_ENTER_NAME
+
+[PartyPlayerText5]
+X = 753
+Y = 90
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_CONTINUE
+
+[PartyPlayerSelectTeams]
+Tex = MainBar
+TexSBG = SelectBG
+Type = Transparent
+TypeSBG = Transparent
+Text = PARTY_TEAMS
+X = 45
+Y = 140
+W = 220
+H = 40
+SkipX = 10
+Fields = 2
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = White
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyPlayerSelectPlayers1]
+Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+Type = Transparent
+TypeSBG = Transparent
+Text = PARTY_TEAMS_PLAYER1
+X = 365
+Y = 195
+W = 200
+SBGW = 200
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = P1Light
+DColor = P1Lightest
+TColor = White
+TDColor = White
+
+SBGColor = P1Dark
+SBGDColor = P1Lightest
+STColor = White
+STDColor = White
+
+[PartyPlayerSelectPlayers2]
+Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+Type = Transparent
+TypeSBG = Transparent
+Text = PARTY_TEAMS_PLAYER2
+X = 365
+Y = 335
+W = 200
+SBGW = 200
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = P2Light
+DColor = P2Lightest
+TColor = White
+TDColor = White
+
+SBGColor = P2Dark
+SBGDColor = P2Lightest
+STColor = White
+STDColor = White
+
+[PartyPlayerSelectPlayers3]
+Tex = MainBar
+Type = Transparent
+TypeSBG = Transparent
+TexSBG = PartyPlayerSelectBG
+Text = PARTY_TEAMS_PLAYER3
+X = 365
+Y = 475
+W = 200
+SBGW = 200
+H = 40
+SkipX = 10
+Fields = 4
+
+Color = P3Light
+DColor = P3Lightest
+TColor = White
+TDColor = White
+
+SBGColor = P3Dark
+SBGDColor = P3Lightest
+STColor = White
+STDColor = White
+
+# Thx to my girlfriend, who gives me plenty of blowjobs
+# during work for making a new theme specially for her =)
+
+[PartyPlayerTeam1Name]
+Tex = PartyTeamButton2
+X = 45
+Y = 190
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Dark
+DColor = P1Lightest
+
+[PartyPlayerTeam1NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 1
+Color = White
+
+[PartyPlayerPlayer1Name]
+Tex = Button
+X = 45
+Y = 250
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Dark
+DColor = P1Lightest
+
+[PartyPlayerPlayer1NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 1
+Color = White
+
+[PartyPlayerPlayer2Name]
+Tex = Button
+X = 205
+Y = 250
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Dark
+DColor = P1Lightest
+
+[PartyPlayerPlayer2NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 2
+Color = White
+
+[PartyPlayerPlayer3Name]
+Tex = Button
+X = 365
+Y = 250
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Dark
+DColor = P1Lightest
+
+[PartyPlayerPlayer3NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 3
+Color = White
+
+[PartyPlayerPlayer4Name]
+Tex = Button
+X = 525
+Y = 250
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Dark
+DColor = P1Lightest
+
+[PartyPlayerPlayer4NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 4
+Color = White
+
+[PartyPlayerTeam2Name]
+Tex = PartyTeamButton2
+X = 45
+Y = 330
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Dark
+DColor = P2Lightest
+
+[PartyPlayerTeam2NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 2
+Color = White
+
+[PartyPlayerPlayer5Name]
+Tex = Button
+X = 45
+Y = 390
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Dark
+DColor = P2Lightest
+
+[PartyPlayerPlayer5NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 5
+Color = White
+
+[PartyPlayerPlayer6Name]
+Tex = Button
+X = 205
+Y = 390
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Dark
+DColor = P2Lightest
+
+[PartyPlayerPlayer6NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 6
+Color = White
+
+[PartyPlayerPlayer7Name]
+Tex = Button
+X = 365
+Y = 390
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Dark
+DColor = P2Lightest
+
+[PartyPlayerPlayer7NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 7
+Color = White
+
+[PartyPlayerPlayer8Name]
+Tex = Button
+X = 525
+Y = 390
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Dark
+DColor = P2Lightest
+
+[PartyPlayerPlayer8NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 8
+Color = White
+
+[PartyPlayerTeam3Name]
+Tex = PartyTeamButton2
+X = 45
+Y = 470
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Dark
+DColor = P3Lightest
+
+[PartyPlayerTeam3NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 3
+Color = White
+
+[PartyPlayerPlayer9Name]
+Tex = Button
+X = 45
+Y = 530
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Dark
+DColor = P3Lightest
+
+[PartyPlayerPlayer9NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 9
+Color = White
+
+[PartyPlayerPlayer10Name]
+Tex = Button
+X = 205
+Y = 530
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Dark
+DColor = P3Lightest
+
+[PartyPlayerPlayer10NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 10
+Color = White
+
+[PartyPlayerPlayer11Name]
+Tex = Button
+X = 365
+Y = 530
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Dark
+DColor = P3Lightest
+
+[PartyPlayerPlayer11NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 11
+Color = White
+
+[PartyPlayerPlayer12Name]
+Tex = Button
+X = 525
+Y = 530
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Dark
+DColor = P3Lightest
+
+[PartyPlayerPlayer12NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 12
+Color = White
+
+
+
+[PartyRoundsBackground]
+Tex = OptionsBG
+
+[PartyRoundsStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[PartyRoundsStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyRoundsStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyRoundsText1]
+X = 80
+Y = 25
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyRoundsText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_ROUNDS_DESC
+
+[PartyRoundsText3]
+X = 753
+Y = 34
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[PartyRoundsText4]
+X = 753
+Y = 62
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = PARTY_ROUNDS_LEGEND_CONTINUE
+
+[PartyRoundsSelectRoundCount]
+Text = PARTY_ROUNDCOUNT
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyRoundsSelectRound1]
+Text = PARTY_SELECTMODE1
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyRoundsSelectRound2]
+Text = PARTY_SELECTMODE2
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyRoundsSelectRound3]
+Text = PARTY_SELECTMODE3
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyRoundsSelectRound4]
+Text = PARTY_SELECTMODE4
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyRoundsSelectRound5]
+Text = PARTY_SELECTMODE5
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyRoundsSelectRound6]
+Text = PARTY_SELECTMODE6
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 430
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[PartyRoundsSelectRound7]
+Text = PARTY_SELECTMODE7
+Tex = Party1Bar
+TexSBG = Party1Bar
+Type = Transparent
+TypeSBG = Transparent
+X = 70
+Y = 480
+W = 250
+H = 40
+SkipX = 10
+
+Color = Button
+DColor = Light
+TColor = White
+TDColor = Button
+
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+#================================================================== SongMenu ======
+
+[SongMenu]
+
+[SongMenuBackground]
+Type=Fade
+ColR=255
+ColG=255
+ColB=255
+Alpha=0.6
+
+[SongMenuStatic1]
+X = 518
+Y = 314
+W = 240
+H = 260
+Tex = PartyMenuBG
+Color = White
+Type = Transparent
+
+[SongMenuTextMenu]
+X = 538
+Y = 320
+Z = 0.97
+Color = Button
+Size = 36
+Text = MENU
+
+[SongMenuButton1]
+X = 528
+Y = 365
+Z = 0.97
+W = 220
+H = 25
+Tex = SongMenuButton
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[SongMenuButton1Text1]
+X = 10
+Y = 0
+Z = 0.97
+Color = White
+Size = 24
+Text = SONG_MENU_PLAY
+
+[SongMenuButton2]
+X = 528
+Y = 395
+Z = 0.97
+W = 220
+H = 25
+Tex = SongMenuButton
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[SongMenuButton2Text1]
+X = 10
+Y = 0
+Color = White
+Size = 24
+Text = SONG_MENU_EDIT
+Z = 0.97
+
+[SongMenuButton3]
+X = 528
+Y = 425
+Z = 0.97
+W = 220
+H = 25
+Tex = SongMenuButton
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[SongMenuButton3Text1]
+X = 10
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_MODI
+Align = 0
+Z = 0.97
+
+# shows up instead of Button 3
+# in some song menus
+[SongMenuSelectSlide3]
+TexSBG = SongMenuButton
+Text = 
+Type = Transparent
+ShowArrows = 1
+OneItemOnly = 1
+X = 528
+Y = 425
+W = 0
+H = 25
+Z = 0.97
+SkipX = 0
+SBGW = 220
+TextSize = 24
+Color = Button
+DColor = Light
+TColor = White
+TDColor = White
+SBGColor = Button
+SBGDColor = Light
+STColor = White
+STDColor = White
+
+[SongMenuButton4]
+X = 528
+Y = 455
+Z = 0.97
+W = 220
+H = 25
+Tex = SongMenuButton
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[SongMenuButton4Text1]
+X = 10
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_CANCEL
+Align = 0
+Z = 0.97
+
+[SongJumpto]
+[SongJumptoBackground]
+Type=Fade
+ColR=255
+ColG=255
+ColB=255
+Alpha=0.6
+
+[SongJumptoStatic1]
+X = 518
+Y = 314
+W = 240
+H = 260
+Tex = SearchBG
+Color = White
+Type = Transparent
+
+[SongJumptoText1]
+X = 538
+Y = 320
+Color = Button
+Size = 36
+Text = SONG_JUMPTO_TYPE_DESC
+Z = 0.97
+
+[SongJumptoStatic2]
+X = 526
+Y = 366
+W = 224
+H = 28
+Color = Button
+Tex = interface_selectbg_search
+Type = Colorized
+Z = 0.97
+
+[SongJumptoSelectSlideType]
+X = 516
+Y = 363
+Z = 0.97
+H = 30
+SBGW = 150
+SkipX = 4
+Size = 36
+
+TColor = Button
+STColor = Button
+
+[SongJumptoButtonSearchText]
+X = 526
+Y = 375
+Z = 0.97
+W = 160
+H = 50
+Size = 36
+Font = 1
+Align = 0
+
+[SongJumptoTextFound]
+X = 539
+Y = 425
+Color = Button
+Font = 0
+Size = 24
+Text = SONG_JUMPTO_HELP
+Align = 0
+Z = 0.97
+
+[StatMain]
+[StatMainBackground]
+Tex = MainBG
+
+[StatMainButtonScores]
+X = 589
+Y = 200
+W = 190
+H = 50
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[StatMainButtonScoresText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SCORES
+Color = White
+
+[StatMainButtonSingers]
+X = 589
+Y = 260
+W = 190
+H = 50
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[StatMainButtonSingersText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SINGERS
+Color = White
+
+[StatMainButtonSongs]
+X = 589
+Y = 320
+W = 190
+H = 50
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[StatMainButtonSongsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_SONGS
+Color = White
+
+[StatMainButtonBands]
+X = 589
+Y = 380
+W = 190
+H = 50
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[StatMainButtonBandsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_BANDS
+Color = White
+
+[StatMainButtonExit]
+X = 589
+Y = 440
+W = 190
+H = 50
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[StatMainButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatMainTextOverview]
+X = 45
+Y = 215
+W = 510
+Color = Button
+Font = 0
+Size = 27
+Align = 0
+Text =
+
+[StatMainStatic1]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[StatMainStatic2]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[StatMainStatic3]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[StatMainStatic4]
+X = 6
+Y = 181
+W = 565
+H = 370
+Tex = StatsBox
+Color = White
+Type = Transparent
+
+[StatMainText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = STAT_MAIN
+
+[StatMainText2]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text = STAT_MAIN_DESC
+
+[StatMainText3]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[StatMainText4]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[StatDetail]
+[StatDetailBackground]
+Tex = MainBG
+
+[StatDetailStatic1]
+X = 6
+Y = 181
+W = 565
+H = 370
+Tex = StatsBox
+Color = White
+Type = Transparent
+
+[StatDetailButtonNext]
+X = 589
+Y = 200
+W = 190
+H = 50
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[StatDetailButtonNextText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_NEXT
+Color = White
+
+[StatDetailButtonPrev]
+X = 589
+Y = 260
+W = 190
+H = 50
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[StatDetailButtonPrevText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_PREV
+Color = White
+
+[StatDetailButtonReverse]
+X = 589
+Y = 320
+W = 190
+H = 50
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[StatDetailButtonReverseText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_REVERSE
+Color = White
+
+[StatDetailButtonExit]
+X = 589
+Y = 380
+W = 190
+H = 50
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+
+[StatDetailButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatDetailTextDescription]
+X = 80
+Y = 70
+Color = Button
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[StatDetailTextPage]
+X = 546
+Y = 198
+Color = White
+Font = 0
+Size = 15
+Align = 2
+Text =
+
+[StatDetailTextList1]
+X = 45
+Y = 222
+Color = Button
+Font = 0
+Size = 21
+Text = Stat1
+
+[StatDetailTextList2]
+X = 45
+Y = 260
+Color = Button
+Font = 0
+Size = 21
+Text = Stat2
+
+[StatDetailTextList3]
+X = 45
+Y = 298
+Color = Button
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList4]
+X = 45
+Y = 336
+Color = Button
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList5]
+X = 45
+Y = 374
+Color = Button
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList6]
+X = 45
+Y = 412
+Color = Button
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList7]
+X = 45
+Y = 450
+Color = Button
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList8]
+X = 45
+Y = 488
+Color = Button
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList9]
+X = 45
+Y = 526
+Color = Button
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList10]
+X = 45
+Y = 564
+Color = Button
+Font = 0
+Size = 21
+Text =
+
+[StatDetailStatic2]
+X = 14
+Y = 33
+W = 62
+H = 62
+Tex = iconlogo
+Color = White
+Type = Transparent
+
+[StatDetailStatic3]
+X = 759
+Y = 35
+W = 22
+H = 22
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[StatDetailStatic4]
+X = 759
+Y = 63
+W = 22
+H = 22
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[StatDetailText1]
+X = 80
+Y = 25
+Color = Light
+Font = 0
+Size = 54
+Align = 0
+Text = STAT_DETAIL
+
+[StatDetailText2]
+X = 753
+Y = 34
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_NAVIGATE
+
+[StatDetailText3]
+X = 753
+Y = 62
+Color = Light
+Font = 0
+Size = 24
+Align = 2
+Text = SING_LEGEND_ESC
+
+[CheckPopup]
+
+[CheckPopupBackground]
+Type=Fade
+ColR=255
+ColG=255
+ColB=255
+Alpha=0.6
+
+[CheckPopupStatic1]
+X = 280
+Y = 175
+W = 240
+H = 260
+Tex = PartyMenuBG
+Color = White
+Type = Transparent
+
+[CheckPopupText1]
+X = 400
+Y = 185
+W = 400
+Color = Button
+Font = 0
+Size = 30
+Text = MSG_QUESTION_TITLE
+Align = 1
+Z = 1
+
+[CheckPopupText]
+X = 400
+Y = 230
+W = 230
+Color = Button
+Font = 0
+Size = 30
+Text = error text
+Align = 1
+Z = 1
+
+[CheckPopupButton1]
+X = 292
+Y = 360
+W = 100
+H = 25
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = YES
+Align = 1
+Z = 1
+
+[CheckPopupButton2]
+X = 408
+Y = 360
+W = 100
+H = 25
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton2Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = NO
+Align = 1
+Z = 1
+
+
+[ErrorPopup]
+[ErrorPopupBackground]
+Type=Fade
+ColR=255
+ColG=255
+ColB=255
+Alpha=0.6
+
+[ErrorPopupStatic1]
+X = 280
+Y = 175
+W = 240
+H = 260
+Tex = PartyMenuBG
+Color = White
+Type = Transparent
+
+[ErrorPopupText1]
+X = 400
+Y = 185
+W = 400
+Color = Button
+Font = 0
+Size = 30
+Text = MSG_ERROR_TITLE
+Align = 1
+Z = 1
+
+[ErrorPopupText]
+X = 400
+Y = 230
+W = 230
+Color = Button
+Font = 0
+Size = 30
+Text = error text
+Align = 1
+Z = 1
+
+[ErrorPopupButton1]
+X = 350
+Y = 365
+W = 100
+H = 25
+Tex = Party1Bar
+Color = Button
+DColor = Light
+Type = Transparent
+Texts = 1
+Z = 1
+
+[ErrorPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = OK
+Align = 1
+Z = 1
+
+[PausePopUpStatic]
+Tex = Pause
+X = 0
+Y = 0
+W = 800
+H = 600
+Z = 0.95
+Color = White
+Type = Transparent
+
+[SingLyricsUpperBar]
+X = 20
+W = 760
+Y = 490
+H = 41
+;YOffSet (+/-) for the Sing-Indicator
+IndicatorYOffset = 3
+
+[SingLyricsLowerBar]
+X = 20
+W = 760
+Y = 532
+H = 41
\ No newline at end of file
diff --git a/songmanagement/game/themes/Candy/Clouds static.ini b/songmanagement/game/themes/Candy/Clouds static.ini
new file mode 100755
index 00000000..7d48ff6b
--- /dev/null
+++ b/songmanagement/game/themes/Candy/Clouds static.ini	
@@ -0,0 +1,145 @@
+[Skin]
+Theme=Candy
+Name=Clouds [static]
+[Textures]
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+iconlogo = [icon]logo.png
+
+icon_song_video = [icon]song_video.png
+
+ButtonMain      = [button]main.png
+Transparent     = Transparent.png
+MainBar         = [main]mainBar.png
+
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+LoadingBG      = [bg-load]clouds.jpg
+MainBG         = [bg-main]clouds.jpg
+OptionsBG      = [bg-main]options.jpg
+
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+PartyMenuBG    = [main]partymenubg.png
+SearchBG    = [main]searchbg.png
+
+LyricBar       = [sing]textBar.png
+
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+TimeBar      = [sing]timeBar.jpg
+
+LineBonusBack  = [sing]scoreBg.png
+
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+ScoreBG        = [sing]scoreBg.png
+
+P              = [sing]p.png
+
+Ball           = [sing]lyricsHelpBar.png
+
+ScoreBox        = [score]box.png
+Scorepipe       = [score]pipe.png 
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelround.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_0.png
+Rating_2 = [score]rating_1.png
+Rating_3 = [score]rating_1.png
+Rating_4 = [score]rating_2.png
+Rating_5 = [score]rating_2.png
+Rating_6 = [score]rating_2.png
+Rating_7 = [score]rating_3.png
+
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+Party1BG = Party1BG.png
+Party1Bar = Party1Bar.png
+Button         = [main]button.png
+
+StatsBox = StatsBox.png
+
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+SongMenuButton = SongMenuButton.png
+
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+BGFade     = [special]bg_fade.png
+
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Candy/Clouds.ini b/songmanagement/game/themes/Candy/Clouds.ini
new file mode 100755
index 00000000..cffcfe24
--- /dev/null
+++ b/songmanagement/game/themes/Candy/Clouds.ini
@@ -0,0 +1,145 @@
+[Skin]
+Theme=Candy
+Name=Clouds
+[Textures]
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+iconlogo = [icon]logo.png
+
+icon_song_video = [icon]song_video.png
+
+ButtonMain      = [button]main.png
+Transparent     = Transparent.png
+MainBar         = [main]mainBar.png
+
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+LoadingBG      = [bg-load]clouds.jpg
+MainBG         = [bg-main]clouds.avi
+OptionsBG      = [bg-main]options.avi
+
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+PartyMenuBG    = [main]partymenubg.png
+SearchBG    = [main]searchbg.png
+
+LyricBar       = [sing]textBar.png
+
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+TimeBar      = [sing]timeBar.jpg
+
+LineBonusBack  = [sing]scoreBg.png
+
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+ScoreBG        = [sing]scoreBg.png
+
+P              = [sing]p.png
+
+Ball           = [sing]lyricsHelpBar.png
+
+ScoreBox        = [score]box.png
+Scorepipe       = [score]pipe.png 
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelround.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_0.png
+Rating_2 = [score]rating_1.png
+Rating_3 = [score]rating_1.png
+Rating_4 = [score]rating_2.png
+Rating_5 = [score]rating_2.png
+Rating_6 = [score]rating_2.png
+Rating_7 = [score]rating_3.png
+
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+Party1BG = Party1BG.png
+Party1Bar = Party1Bar.png
+Button         = [main]button.png
+
+StatsBox = StatsBox.png
+
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+SongMenuButton = SongMenuButton.png
+
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+BGFade     = [special]bg_fade.png
+
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Candy/Party1BG.png b/songmanagement/game/themes/Candy/Party1BG.png
new file mode 100755
index 00000000..50822a09
Binary files /dev/null and b/songmanagement/game/themes/Candy/Party1BG.png differ
diff --git a/songmanagement/game/themes/Candy/Party1Bar.png b/songmanagement/game/themes/Candy/Party1Bar.png
new file mode 100755
index 00000000..4ff5d707
Binary files /dev/null and b/songmanagement/game/themes/Candy/Party1Bar.png differ
diff --git a/songmanagement/game/themes/Candy/SongMenuButton.png b/songmanagement/game/themes/Candy/SongMenuButton.png
new file mode 100755
index 00000000..49e63c8c
Binary files /dev/null and b/songmanagement/game/themes/Candy/SongMenuButton.png differ
diff --git a/songmanagement/game/themes/Candy/StatsBox.png b/songmanagement/game/themes/Candy/StatsBox.png
new file mode 100755
index 00000000..4e8add8e
Binary files /dev/null and b/songmanagement/game/themes/Candy/StatsBox.png differ
diff --git a/songmanagement/game/themes/Candy/Transparent.png b/songmanagement/game/themes/Candy/Transparent.png
new file mode 100755
index 00000000..450ebb30
Binary files /dev/null and b/songmanagement/game/themes/Candy/Transparent.png differ
diff --git a/songmanagement/game/themes/Candy/[bg-load]clouds.jpg b/songmanagement/game/themes/Candy/[bg-load]clouds.jpg
new file mode 100755
index 00000000..6969612a
Binary files /dev/null and b/songmanagement/game/themes/Candy/[bg-load]clouds.jpg differ
diff --git a/songmanagement/game/themes/Candy/[bg-main]clouds.AVI b/songmanagement/game/themes/Candy/[bg-main]clouds.AVI
new file mode 100755
index 00000000..06d56f73
Binary files /dev/null and b/songmanagement/game/themes/Candy/[bg-main]clouds.AVI differ
diff --git a/songmanagement/game/themes/Candy/[bg-main]clouds.jpg b/songmanagement/game/themes/Candy/[bg-main]clouds.jpg
new file mode 100755
index 00000000..49519985
Binary files /dev/null and b/songmanagement/game/themes/Candy/[bg-main]clouds.jpg differ
diff --git a/songmanagement/game/themes/Candy/[bg-main]options.AVI b/songmanagement/game/themes/Candy/[bg-main]options.AVI
new file mode 100755
index 00000000..05e1170f
Binary files /dev/null and b/songmanagement/game/themes/Candy/[bg-main]options.AVI differ
diff --git a/songmanagement/game/themes/Candy/[bg-main]options.jpg b/songmanagement/game/themes/Candy/[bg-main]options.jpg
new file mode 100755
index 00000000..dfc24431
Binary files /dev/null and b/songmanagement/game/themes/Candy/[bg-main]options.jpg differ
diff --git a/songmanagement/game/themes/Candy/[button]13.png b/songmanagement/game/themes/Candy/[button]13.png
new file mode 100755
index 00000000..d262205f
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]13.png differ
diff --git a/songmanagement/game/themes/Candy/[button]alt.png b/songmanagement/game/themes/Candy/[button]alt.png
new file mode 100755
index 00000000..d3689fc1
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]alt.png differ
diff --git a/songmanagement/game/themes/Candy/[button]az.png b/songmanagement/game/themes/Candy/[button]az.png
new file mode 100755
index 00000000..e625ab22
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]az.png differ
diff --git a/songmanagement/game/themes/Candy/[button]enter.png b/songmanagement/game/themes/Candy/[button]enter.png
new file mode 100755
index 00000000..3c81914d
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]enter.png differ
diff --git a/songmanagement/game/themes/Candy/[button]esc.png b/songmanagement/game/themes/Candy/[button]esc.png
new file mode 100755
index 00000000..c8456e49
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]esc.png differ
diff --git a/songmanagement/game/themes/Candy/[button]j.png b/songmanagement/game/themes/Candy/[button]j.png
new file mode 100755
index 00000000..532fc87f
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]j.png differ
diff --git a/songmanagement/game/themes/Candy/[button]m.png b/songmanagement/game/themes/Candy/[button]m.png
new file mode 100755
index 00000000..849f5e49
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]m.png differ
diff --git a/songmanagement/game/themes/Candy/[button]main.png b/songmanagement/game/themes/Candy/[button]main.png
new file mode 100755
index 00000000..ea9b7a47
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]main.png differ
diff --git a/songmanagement/game/themes/Candy/[button]navi.png b/songmanagement/game/themes/Candy/[button]navi.png
new file mode 100755
index 00000000..28f99f2d
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]navi.png differ
diff --git a/songmanagement/game/themes/Candy/[button]p.png b/songmanagement/game/themes/Candy/[button]p.png
new file mode 100755
index 00000000..ecd32add
Binary files /dev/null and b/songmanagement/game/themes/Candy/[button]p.png differ
diff --git a/songmanagement/game/themes/Candy/[effect]goldenNoteStar.png b/songmanagement/game/themes/Candy/[effect]goldenNoteStar.png
new file mode 100755
index 00000000..7bd6225f
Binary files /dev/null and b/songmanagement/game/themes/Candy/[effect]goldenNoteStar.png differ
diff --git a/songmanagement/game/themes/Candy/[effect]perfectNoteStar.png b/songmanagement/game/themes/Candy/[effect]perfectNoteStar.png
new file mode 100755
index 00000000..99132c39
Binary files /dev/null and b/songmanagement/game/themes/Candy/[effect]perfectNoteStar.png differ
diff --git a/songmanagement/game/themes/Candy/[icon]logo.png b/songmanagement/game/themes/Candy/[icon]logo.png
new file mode 100755
index 00000000..f1a27a91
Binary files /dev/null and b/songmanagement/game/themes/Candy/[icon]logo.png differ
diff --git a/songmanagement/game/themes/Candy/[icon]options.png b/songmanagement/game/themes/Candy/[icon]options.png
new file mode 100755
index 00000000..34b88e6a
Binary files /dev/null and b/songmanagement/game/themes/Candy/[icon]options.png differ
diff --git a/songmanagement/game/themes/Candy/[icon]song_duett.png b/songmanagement/game/themes/Candy/[icon]song_duett.png
new file mode 100755
index 00000000..c6c873c4
Binary files /dev/null and b/songmanagement/game/themes/Candy/[icon]song_duett.png differ
diff --git a/songmanagement/game/themes/Candy/[icon]song_video.png b/songmanagement/game/themes/Candy/[icon]song_video.png
new file mode 100755
index 00000000..ed409289
Binary files /dev/null and b/songmanagement/game/themes/Candy/[icon]song_video.png differ
diff --git a/songmanagement/game/themes/Candy/[interface]cursor.png b/songmanagement/game/themes/Candy/[interface]cursor.png
new file mode 100755
index 00000000..0fe390f0
Binary files /dev/null and b/songmanagement/game/themes/Candy/[interface]cursor.png differ
diff --git a/songmanagement/game/themes/Candy/[interface]cursor_pressed.png b/songmanagement/game/themes/Candy/[interface]cursor_pressed.png
new file mode 100755
index 00000000..fa0056cc
Binary files /dev/null and b/songmanagement/game/themes/Candy/[interface]cursor_pressed.png differ
diff --git a/songmanagement/game/themes/Candy/[interface]select_arrow_left.png b/songmanagement/game/themes/Candy/[interface]select_arrow_left.png
new file mode 100755
index 00000000..e4a32d2d
Binary files /dev/null and b/songmanagement/game/themes/Candy/[interface]select_arrow_left.png differ
diff --git a/songmanagement/game/themes/Candy/[interface]select_arrow_right.png b/songmanagement/game/themes/Candy/[interface]select_arrow_right.png
new file mode 100755
index 00000000..b2a29793
Binary files /dev/null and b/songmanagement/game/themes/Candy/[interface]select_arrow_right.png differ
diff --git a/songmanagement/game/themes/Candy/[interface]selectbg_search.png b/songmanagement/game/themes/Candy/[interface]selectbg_search.png
new file mode 100755
index 00000000..57d0ca88
Binary files /dev/null and b/songmanagement/game/themes/Candy/[interface]selectbg_search.png differ
diff --git a/songmanagement/game/themes/Candy/[main]button.png b/songmanagement/game/themes/Candy/[main]button.png
new file mode 100755
index 00000000..7d05462d
Binary files /dev/null and b/songmanagement/game/themes/Candy/[main]button.png differ
diff --git a/songmanagement/game/themes/Candy/[main]mainBar.png b/songmanagement/game/themes/Candy/[main]mainBar.png
new file mode 100755
index 00000000..800d088b
Binary files /dev/null and b/songmanagement/game/themes/Candy/[main]mainBar.png differ
diff --git a/songmanagement/game/themes/Candy/[main]partymenubg.png b/songmanagement/game/themes/Candy/[main]partymenubg.png
new file mode 100755
index 00000000..e3152769
Binary files /dev/null and b/songmanagement/game/themes/Candy/[main]partymenubg.png differ
diff --git a/songmanagement/game/themes/Candy/[main]searchbg.png b/songmanagement/game/themes/Candy/[main]searchbg.png
new file mode 100755
index 00000000..66f1f975
Binary files /dev/null and b/songmanagement/game/themes/Candy/[main]searchbg.png differ
diff --git a/songmanagement/game/themes/Candy/[main]selectbg.png b/songmanagement/game/themes/Candy/[main]selectbg.png
new file mode 100755
index 00000000..d268d684
Binary files /dev/null and b/songmanagement/game/themes/Candy/[main]selectbg.png differ
diff --git a/songmanagement/game/themes/Candy/[main]songCover.jpg b/songmanagement/game/themes/Candy/[main]songCover.jpg
new file mode 100755
index 00000000..b2556118
Binary files /dev/null and b/songmanagement/game/themes/Candy/[main]songCover.jpg differ
diff --git a/songmanagement/game/themes/Candy/[main]songSelection1.png b/songmanagement/game/themes/Candy/[main]songSelection1.png
new file mode 100755
index 00000000..bb0b8bfc
Binary files /dev/null and b/songmanagement/game/themes/Candy/[main]songSelection1.png differ
diff --git a/songmanagement/game/themes/Candy/[main]songSelection2.png b/songmanagement/game/themes/Candy/[main]songSelection2.png
new file mode 100755
index 00000000..83d19c31
Binary files /dev/null and b/songmanagement/game/themes/Candy/[main]songSelection2.png differ
diff --git a/songmanagement/game/themes/Candy/[party]Joker.png b/songmanagement/game/themes/Candy/[party]Joker.png
new file mode 100755
index 00000000..12d18edf
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]Joker.png differ
diff --git a/songmanagement/game/themes/Candy/[party]playerButton.png b/songmanagement/game/themes/Candy/[party]playerButton.png
new file mode 100755
index 00000000..0c4f9b9f
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]playerButton.png differ
diff --git a/songmanagement/game/themes/Candy/[party]playerTeamButton.png b/songmanagement/game/themes/Candy/[party]playerTeamButton.png
new file mode 100755
index 00000000..fd0999ba
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]playerTeamButton.png differ
diff --git a/songmanagement/game/themes/Candy/[party]playerselectbg.png b/songmanagement/game/themes/Candy/[party]playerselectbg.png
new file mode 100755
index 00000000..464a40e9
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]playerselectbg.png differ
diff --git a/songmanagement/game/themes/Candy/[party]pointer.png b/songmanagement/game/themes/Candy/[party]pointer.png
new file mode 100755
index 00000000..2292d6c1
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]pointer.png differ
diff --git a/songmanagement/game/themes/Candy/[party]roundBG1.png b/songmanagement/game/themes/Candy/[party]roundBG1.png
new file mode 100755
index 00000000..d66e5743
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]roundBG1.png differ
diff --git a/songmanagement/game/themes/Candy/[party]roundBG2.png b/songmanagement/game/themes/Candy/[party]roundBG2.png
new file mode 100755
index 00000000..217915b8
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]roundBG2.png differ
diff --git a/songmanagement/game/themes/Candy/[party]roundBG3.png b/songmanagement/game/themes/Candy/[party]roundBG3.png
new file mode 100755
index 00000000..677d6f78
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]roundBG3.png differ
diff --git a/songmanagement/game/themes/Candy/[party]roundBG4.png b/songmanagement/game/themes/Candy/[party]roundBG4.png
new file mode 100755
index 00000000..dfd24b50
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]roundBG4.png differ
diff --git a/songmanagement/game/themes/Candy/[party]roundTeamButton.png b/songmanagement/game/themes/Candy/[party]roundTeamButton.png
new file mode 100755
index 00000000..018d4d9c
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]roundTeamButton.png differ
diff --git a/songmanagement/game/themes/Candy/[party]winDecoration.png b/songmanagement/game/themes/Candy/[party]winDecoration.png
new file mode 100755
index 00000000..7c42acdc
Binary files /dev/null and b/songmanagement/game/themes/Candy/[party]winDecoration.png differ
diff --git a/songmanagement/game/themes/Candy/[score]Line.png b/songmanagement/game/themes/Candy/[score]Line.png
new file mode 100755
index 00000000..954caf94
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]Line.png differ
diff --git a/songmanagement/game/themes/Candy/[score]bar_box_dark.png b/songmanagement/game/themes/Candy/[score]bar_box_dark.png
new file mode 100755
index 00000000..e4fbfa41
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]bar_box_dark.png differ
diff --git a/songmanagement/game/themes/Candy/[score]bar_box_light.png b/songmanagement/game/themes/Candy/[score]bar_box_light.png
new file mode 100755
index 00000000..ddc17ed8
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]bar_box_light.png differ
diff --git a/songmanagement/game/themes/Candy/[score]bar_box_lightest.png b/songmanagement/game/themes/Candy/[score]bar_box_lightest.png
new file mode 100755
index 00000000..995bb9ef
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]bar_box_lightest.png differ
diff --git a/songmanagement/game/themes/Candy/[score]box.png b/songmanagement/game/themes/Candy/[score]box.png
new file mode 100755
index 00000000..71a0cee6
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]box.png differ
diff --git a/songmanagement/game/themes/Candy/[score]endcap.png b/songmanagement/game/themes/Candy/[score]endcap.png
new file mode 100755
index 00000000..6f364b80
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]endcap.png differ
diff --git a/songmanagement/game/themes/Candy/[score]level.png b/songmanagement/game/themes/Candy/[score]level.png
new file mode 100755
index 00000000..1f627560
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]level.png differ
diff --git a/songmanagement/game/themes/Candy/[score]levelRound.png b/songmanagement/game/themes/Candy/[score]levelRound.png
new file mode 100755
index 00000000..2bc7a6b8
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]levelRound.png differ
diff --git a/songmanagement/game/themes/Candy/[score]level_dark.png b/songmanagement/game/themes/Candy/[score]level_dark.png
new file mode 100755
index 00000000..da4fd407
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]level_dark.png differ
diff --git a/songmanagement/game/themes/Candy/[score]level_dark_round.png b/songmanagement/game/themes/Candy/[score]level_dark_round.png
new file mode 100755
index 00000000..30be6368
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]level_dark_round.png differ
diff --git a/songmanagement/game/themes/Candy/[score]level_light.png b/songmanagement/game/themes/Candy/[score]level_light.png
new file mode 100755
index 00000000..1c1c8a4d
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]level_light.png differ
diff --git a/songmanagement/game/themes/Candy/[score]level_light_round.png b/songmanagement/game/themes/Candy/[score]level_light_round.png
new file mode 100755
index 00000000..88740234
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]level_light_round.png differ
diff --git a/songmanagement/game/themes/Candy/[score]level_lightest.png b/songmanagement/game/themes/Candy/[score]level_lightest.png
new file mode 100755
index 00000000..f02fdf7b
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]level_lightest.png differ
diff --git a/songmanagement/game/themes/Candy/[score]level_lightest_round.png b/songmanagement/game/themes/Candy/[score]level_lightest_round.png
new file mode 100755
index 00000000..6034cac5
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]level_lightest_round.png differ
diff --git a/songmanagement/game/themes/Candy/[score]pipe.png b/songmanagement/game/themes/Candy/[score]pipe.png
new file mode 100755
index 00000000..96aede8d
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]pipe.png differ
diff --git a/songmanagement/game/themes/Candy/[score]rating_0.png b/songmanagement/game/themes/Candy/[score]rating_0.png
new file mode 100755
index 00000000..81c305a9
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]rating_0.png differ
diff --git a/songmanagement/game/themes/Candy/[score]rating_1.png b/songmanagement/game/themes/Candy/[score]rating_1.png
new file mode 100755
index 00000000..78c64fb5
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]rating_1.png differ
diff --git a/songmanagement/game/themes/Candy/[score]rating_2.png b/songmanagement/game/themes/Candy/[score]rating_2.png
new file mode 100755
index 00000000..49aaa2f2
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]rating_2.png differ
diff --git a/songmanagement/game/themes/Candy/[score]rating_3.png b/songmanagement/game/themes/Candy/[score]rating_3.png
new file mode 100755
index 00000000..3007b5db
Binary files /dev/null and b/songmanagement/game/themes/Candy/[score]rating_3.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player1]lyric_active.png b/songmanagement/game/themes/Candy/[sing.player1]lyric_active.png
new file mode 100755
index 00000000..089c8c5e
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player1]lyric_active.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player1]lyric_inactive.png b/songmanagement/game/themes/Candy/[sing.player1]lyric_inactive.png
new file mode 100755
index 00000000..a349007d
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player1]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player2]lyric_active.png b/songmanagement/game/themes/Candy/[sing.player2]lyric_active.png
new file mode 100755
index 00000000..509767fa
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player2]lyric_active.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player2]lyric_inactive.png b/songmanagement/game/themes/Candy/[sing.player2]lyric_inactive.png
new file mode 100755
index 00000000..ac40ec61
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player2]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player3]lyric_active.png b/songmanagement/game/themes/Candy/[sing.player3]lyric_active.png
new file mode 100755
index 00000000..7b130ac5
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player3]lyric_active.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player3]lyric_inactive.png b/songmanagement/game/themes/Candy/[sing.player3]lyric_inactive.png
new file mode 100755
index 00000000..c5a00600
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player3]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player4]lyric_active.png b/songmanagement/game/themes/Candy/[sing.player4]lyric_active.png
new file mode 100755
index 00000000..993041fd
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player4]lyric_active.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player4]lyric_inactive.png b/songmanagement/game/themes/Candy/[sing.player4]lyric_inactive.png
new file mode 100755
index 00000000..f09669b2
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player4]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player5]lyric_active.png b/songmanagement/game/themes/Candy/[sing.player5]lyric_active.png
new file mode 100755
index 00000000..631dc9c3
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player5]lyric_active.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player5]lyric_inactive.png b/songmanagement/game/themes/Candy/[sing.player5]lyric_inactive.png
new file mode 100755
index 00000000..716071e8
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player5]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player6]lyric_active.png b/songmanagement/game/themes/Candy/[sing.player6]lyric_active.png
new file mode 100755
index 00000000..65133d03
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player6]lyric_active.png differ
diff --git a/songmanagement/game/themes/Candy/[sing.player6]lyric_inactive.png b/songmanagement/game/themes/Candy/[sing.player6]lyric_inactive.png
new file mode 100755
index 00000000..0c5f34d3
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing.player6]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]lyricsHelpBar.png b/songmanagement/game/themes/Candy/[sing]lyricsHelpBar.png
new file mode 100755
index 00000000..dc36d4d3
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]lyricsHelpBar.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]notesBgLeft.png b/songmanagement/game/themes/Candy/[sing]notesBgLeft.png
new file mode 100755
index 00000000..3e8efe01
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]notesBgLeft.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]notesBgMid.png b/songmanagement/game/themes/Candy/[sing]notesBgMid.png
new file mode 100755
index 00000000..48aa38ba
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]notesBgMid.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]notesBgRight.png b/songmanagement/game/themes/Candy/[sing]notesBgRight.png
new file mode 100755
index 00000000..b0d7d500
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]notesBgRight.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]notesLeft.png b/songmanagement/game/themes/Candy/[sing]notesLeft.png
new file mode 100755
index 00000000..28baff12
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]notesLeft.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]notesMid.png b/songmanagement/game/themes/Candy/[sing]notesMid.png
new file mode 100755
index 00000000..639d6011
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]notesMid.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]notesPlainLeft.png b/songmanagement/game/themes/Candy/[sing]notesPlainLeft.png
new file mode 100755
index 00000000..8080466d
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]notesPlainLeft.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]notesPlainMid.png b/songmanagement/game/themes/Candy/[sing]notesPlainMid.png
new file mode 100755
index 00000000..beaf8568
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]notesPlainMid.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]notesPlainRight.png b/songmanagement/game/themes/Candy/[sing]notesPlainRight.png
new file mode 100755
index 00000000..ca2a0c75
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]notesPlainRight.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]notesRight.png b/songmanagement/game/themes/Candy/[sing]notesRight.png
new file mode 100755
index 00000000..12724d8c
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]notesRight.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]p.png b/songmanagement/game/themes/Candy/[sing]p.png
new file mode 100755
index 00000000..22155497
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]p.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]pause.png b/songmanagement/game/themes/Candy/[sing]pause.png
new file mode 100755
index 00000000..86a57aa6
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]pause.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]scoreBg.png b/songmanagement/game/themes/Candy/[sing]scoreBg.png
new file mode 100755
index 00000000..4936401a
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]scoreBg.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]singBarBack.png b/songmanagement/game/themes/Candy/[sing]singBarBack.png
new file mode 100755
index 00000000..14d2ba42
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]singBarBack.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]singBarBar.png b/songmanagement/game/themes/Candy/[sing]singBarBar.png
new file mode 100755
index 00000000..9c57057b
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]singBarBar.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]singBarFront.png b/songmanagement/game/themes/Candy/[sing]singBarFront.png
new file mode 100755
index 00000000..42477c5a
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]singBarFront.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]textBar.png b/songmanagement/game/themes/Candy/[sing]textBar.png
new file mode 100755
index 00000000..b0325bff
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]textBar.png differ
diff --git a/songmanagement/game/themes/Candy/[sing]timeBar.jpg b/songmanagement/game/themes/Candy/[sing]timeBar.jpg
new file mode 100755
index 00000000..cc5cb552
Binary files /dev/null and b/songmanagement/game/themes/Candy/[sing]timeBar.jpg differ
diff --git a/songmanagement/game/themes/Candy/[special]bg_fade.png b/songmanagement/game/themes/Candy/[special]bg_fade.png
new file mode 100755
index 00000000..dc3248ef
Binary files /dev/null and b/songmanagement/game/themes/Candy/[special]bg_fade.png differ
diff --git a/songmanagement/game/themes/Classic.ini b/songmanagement/game/themes/Classic.ini
new file mode 100644
index 00000000..8ea3fe83
--- /dev/null
+++ b/songmanagement/game/themes/Classic.ini
@@ -0,0 +1,8012 @@
+;1.10
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Theme]
+Name = Classic
+Creator = MezzoX
+US_Version = USD 110
+DefaultSkin = Blue
+
+[Colors]
+White = 255 255 255
+LightBlue = 119 187 210
+DarkBlue = 28 126 171
+LightRed = 170 146 146
+DarkRed = 155 113 113
+LightGreen = 136 168 136
+DarkGreen = 106 152 104
+LightPurple = 155 136 168
+DarkPurple = 145 104 152
+LightOrange = 168 155 136
+DarkOrange = 151 131 76
+LightYellow = 168 168 136
+DarkYellow = 150 151 76
+Turkis = 13 186 167
+GrayLightest = 223 223 223
+GrayLight = 191 191 191
+Gray = 127 127 127
+GrayDark = 63 63 63
+Black = 0 0 0
+GrayPopup = 51 51 51
+Gold = 255 223 31
+Silver = 223 223 223
+Bronze = 205 127 50
+Red = 255 0 0
+
+[Loading]
+[LoadingBackground]
+Tex = LoadingBG
+Color = DarkRed
+Type = Colorized
+
+[LoadingText1]
+X = 350
+Y = 250
+Color = GrayDark
+Font = 1
+Align = 0
+Size = 48
+Text = SING_LOADING
+Reflection = 0
+
+
+[LoadingText2]
+X = 780
+Y = 570
+Color = GrayDark
+Font = 1
+Size = 24
+Align = 2
+Text = US_VERSION
+Reflection = 0
+
+
+[Main]
+[MainBackground]
+Tex = MainBG
+
+[MainStatic1]
+X =30
+Y =235
+W =32
+H =32
+Tex = MainIcon
+Color = ColorDark
+Type = Transparent
+
+[MainText1]
+X =30
+Y =170
+Color = GrayLight
+Font = 1
+Size = 66
+Align = 0
+Text = SING_MENU
+
+[MainTextDescription]
+X =63
+Y =233
+Color=GrayDark
+Font =1
+Size = 30
+Align=0
+Text=
+
+[MainTextDescriptionLong]
+X =63
+Y =265
+Color = Black
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[MainStatic2]
+X =30
+Y =270
+W =740
+H =283
+Tex = usdx_logo 
+Color = ColorDark
+Type = Transparent
+
+
+[MainStatic3]
+X =530
+Y = 545
+W = 32
+H = 30
+Tex = ButtonE
+Color = White
+Type = Transparent
+
+[MainText4]
+X =570
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDITOR
+
+[MainStatic4]
+X = 126
+Y = 545
+W =32
+H =30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[MainText2]
+X =166
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[MainStatic5]
+X =340
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[MainText3]
+X =380
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_SELECT
+
+[MainButtonSolo]
+X =430
+Y =195
+W = 64
+H = 64
+Tex = ButtonSolo
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[MainButtonSoloText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_SING
+Color = GrayDark
+
+[MainButtonMulti]
+X =500
+Y =195
+W = 64
+H = 64
+Tex = ButtonMulti
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[MainButtonMultiText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_MULTI
+Color = GrayDark
+
+[MainButtonStats]
+X =570
+Y =195
+W = 64
+H = 64
+Tex = ButtonStats
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[MainButtonStatsText1]
+X = 70
+Y = 3
+Font = 0
+Size = 24
+Align = 1
+Text = SING_STATS
+Color = GrayDark
+
+[MainButtonOptions]
+X =640
+Y =195
+W = 64
+H = 64
+Tex = ButtonOptions
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+
+[MainButtonOptionsText1]
+X = 70
+Y = 3
+Font = 0
+Size = 24
+Align = 1
+Text = SING_OPTIONS
+Color = GrayDark
+
+[MainButtonExit]
+X =710
+Y =195
+W = 64
+H = 64
+Tex = ButtonExit
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+
+[MainButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EXIT
+Color = GrayDark
+
+[Song]
+
+[SongBackground]
+Tex = SongBG
+
+[SongStaticNonParty1]
+X =20
+Y =500
+W =32
+H =32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[SongTextCat]
+X =50
+Y =500
+Color=GrayDark
+Font =1
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_DESC
+
+[SongStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongStatic2]
+X =0
+Y =100
+W =800
+H =350
+Z = 0.1
+Color=GrayLight
+Tex =SongFade
+Type = Colorized
+
+[SongCover]
+X=300
+Y=140
+W=300
+H=200
+Style=4
+Reflections=0
+
+[SongEqualizer]
+Visible = 1
+Direction = 1
+Color =Black
+Alpha = 1
+X=378
+Y=488
+PieceW=8
+PieceH=3
+Space=1
+Bands=5
+Length=7
+
+[SongVideoIcon]
+X=450
+Y=462
+W =32
+H =32
+Z=1
+Color=White
+Tex = icon_song_video
+Type = Transparent
+
+
+[SongStatic3]
+X =270
+Y =120
+W =260
+H =240
+Z =0.95
+Color = Gray
+Tex = SongSelection
+Type = Transparent
+
+[SongStatic4]
+X =378
+Y =463
+Z = 0.8
+W =44
+H =28
+Color =Black
+Tex =SongEqualizerBG
+Type = Colorized
+
+
+[SongTextArtist]
+X =400
+Y =360
+Color=Black
+Font =0
+Size = 27
+Align =1
+Text=
+
+[SongTextTitle]
+X =400
+Y =390
+Color=GrayDark
+Font =0
+Size = 27
+Align =1
+Text=
+
+[SongTextNumber]
+X =400
+Y =425
+Color=Gray
+Font =1
+Size = 21
+Align =1
+Text=
+
+#Variable statics and texts for song-screen in sing- and partymode
+# There can be an unlimited Number of Statics and Texts, As long
+# as the numbers are in order.
+# Statics that are shown in PartyMode Only are Named_
+#        SongStaticParty[No]
+# Texts that are shown in PartyMode Only are Named_
+#        SongTextParty[No]
+# Statics that are shown in Normal Mode Only are Named_
+#        SongStaticNonParty[No]
+# Texts that are shown in Normal Mode Only are Named_
+#        SongTextNonParty[No]
+#Here are the ones for singmode
+
+[SongTextNonParty1]
+X =30
+Y =455
+Color=GrayLight
+Font =1
+Size = 45
+Text = SING_SONG_SELECTION
+Align = 0
+
+# NAVBAR #########################
+# Jump to a letter with [ALT] + [A..Z]
+[SongStaticNonParty2]
+X =110
+Y =553
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAlt
+Color = White
+Type = Transparent
+
+
+[SongTextNonParty2]
+X = 142
+Y =553
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = +
+
+
+[SongStaticNonParty3]
+X =155
+Y =553
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+
+
+[SongTextNonParty3]
+X = 195
+Y = 555
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_GOTO
+
+
+# Menu opens with [M]
+[SongStaticNonParty4]
+X = 305
+Y =553
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonM
+Color = White
+Type = Transparent
+
+
+[SongTextNonParty4]
+X = 345
+Y = 555
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_MENU
+
+
+# The so famous search, shown with [J]
+[SongStaticNonParty5]
+X = 420
+Y = 553
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonJ
+Color = White
+Type = Transparent
+
+[SongTextNonParty5]
+X = 460
+Y = 555
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SONG_JUMPTO_DESC
+
+
+# [P]laylist
+[SongStaticNonParty6]
+X = 600
+Y = 553
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonP
+Color = White
+Type = Transparent
+
+
+[SongTextNonParty6]
+X = 640
+Y = 555
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_PLAYLIST
+
+
+#and these are the ones for partymode
+[SongStaticParty1]
+X =20
+Y =500
+W =32
+H =32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+# NAVBAR for party
+# enter a number
+[SongStaticParty2]
+X = 126
+Y = 545
+W =32
+H =30
+Tex = Button13
+Color = White
+Type = Transparent
+
+[SongTextParty2]
+X =166
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SONG_MENU_NAME_PARTY_JOKER
+
+
+# menu
+[SongStaticParty3]
+X =330
+Y = 545
+W = 32
+H = 30
+Tex = ButtonM
+Color = White
+Type = Transparent
+
+[SongTextParty3]
+X =370
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_MENU
+
+
+[SongStaticParty4]
+X =530
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[SongTextParty4]
+X =570
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_LEGEND_CONTINUE
+
+
+#Texts for Party Mode
+[SongTextParty1]
+X =30
+Y =455
+Color=GrayLight
+Font =1
+Size = 45
+Text = PARTY_MODE
+
+#variable statics end
+
+# Jokers, 5 for each team, only shown in party Mode
+[SongStaticTeam1Joker1]
+Tex = Joker
+X =20
+Y =30
+W =50
+H =50
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker2]
+Tex = Joker
+X =70
+Y =30
+W =50
+H =50
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker3]
+Tex = Joker
+X =120
+Y =30
+W =50
+H =50
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker4]
+Tex = Joker
+X =170
+Y =30
+W =50
+H =50
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker5]
+Tex = Joker
+X =220
+Y =30
+W =50
+H =50
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker1]
+Tex = Joker
+X =280
+Y =30
+W =50
+H =50
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker2]
+Tex = Joker
+X =330
+Y =30
+W =50
+H =50
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker3]
+Tex = Joker
+X =380
+Y =30
+W =50
+H =50
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker4]
+Tex = Joker
+X =430
+Y =30
+W =50
+H =50
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker5]
+Tex = Joker
+X =480
+Y =30
+W =50
+H =50
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker1]
+Tex = Joker
+X =540
+Y =30
+W =50
+H =50
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker2]
+Tex = Joker
+X =590
+Y =30
+W =50
+H =50
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker3]
+Tex = Joker
+X =640
+Y =30
+W =50
+H =50
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker4]
+Tex = Joker
+X =690
+Y =30
+W =50
+H =50
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker5]
+Tex = Joker
+X =740
+Y =30
+W =50
+H =50
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+
+[Sing]
+Texts = 1
+
+[SingBackground]
+Type=color
+ColR=1
+ColB=1
+ColG=1
+
+[SingText1]
+Text =SING_TIME
+X =43
+Y =17
+Font =1
+Size = 18
+Color =Black
+Align=1
+
+[SingStatic1]
+;TextBG
+Tex =LyricBar
+X =10
+Y =490
+W =780
+H =105
+Color =GrayLightest
+Type = Transparent
+
+[SingStatic2]
+;TimeBar
+Tex =LyricBar
+X =12
+Y =5
+W =328
+H =42
+Color =GrayLightest
+Type = Transparent
+
+[SingStatic3]
+Tex =Rectangle
+X =140
+Y =21
+W =190
+H =10
+Color=Gray
+
+[SingTimeProgress]
+X =140
+Y =21
+W =190
+H =10
+Color=GrayDark
+
+[SingTimeText]
+Text =SING_TIME
+X =100
+Y =14
+Font =1
+Size = 24
+Color =White
+Align=1
+
+# O N E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#PlayerOne
+[SingP1Static]
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P1Dark
+Type = Colorized
+
+[SingP1Text]
+Text = P1
+X = 25
+Y = 302
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP1Static2]
+Tex = ScoreBG
+X = 680
+Y = 282
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1TextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1SingBar]
+X = 680
+Y = 316
+W = 100
+H = 8
+
+# T W O  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1TwoPStatic]
+Tex = P
+X = 20
+Y = 117
+W = 30
+H = 28
+Color = P1Dark
+Type = Colorized
+
+[SingP1TwoPText]
+Text = P1
+X = 25
+Y = 122
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP1TwoPStatic2]
+Tex = ScoreBG
+X = 680
+Y = 102
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1TwoPTextScore]
+Text = 00000
+X = 698
+Y = 104
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1TwoPSingBar]
+X = 680
+Y = 136
+W = 100
+H = 8
+
+#Player Two
+[SingP2RStatic]
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P2Dark
+Type = Colorized
+
+[SingP2RText]
+Text = P2
+X = 24
+Y = 302
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP2RStatic2]
+Tex = ScoreBG
+X = 680
+Y = 282
+W = 100
+H = 36
+Color = P2Dark
+Type = Colorized
+
+[SingP2RTextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2RSingBar]
+X = 680
+Y = 316
+W = 100
+H = 8
+
+# T H R E E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1ThreePStatic]
+Tex = P
+X = 16
+Y = 59
+W = 50
+H = 44
+Color = P1Dark
+Type = Colorized
+
+[SingP1ThreePText]
+Text = P1
+X = 27
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP1ThreePStatic2]
+Tex = ScoreBG
+X = 75
+Y = 61
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1ThreePTextScore]
+Text = 00000
+X = 93
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1ThreePSingBar]
+X = 75
+Y = 95
+W = 100
+H = 8
+
+#Player Two
+[SingP2MStatic]
+Tex = P
+X = 311
+Y = 59
+W = 50
+H = 44
+Color = P2Dark
+Type = Colorized
+
+[SingP2MText]
+Text = P2
+X = 321
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP2MStatic2]
+Tex = ScoreBG
+X = 370
+Y = 61
+W = 100
+H = 36
+Color = P2Dark
+Type = Colorized
+
+[SingP2MTextScore]
+Text = 00000
+X = 388
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2MSingBar]
+X = 370
+Y = 95
+W = 100
+H = 8
+
+#Player Three
+[SingP3RStatic]
+Tex = P
+X = 611
+Y = 59
+W = 50
+H = 44
+Color = P3Dark
+Type = Colorized
+
+[SingP3RText]
+Text = P3
+X = 621
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP3RStatic2]
+Tex = ScoreBG
+X = 670
+Y = 61
+W = 100
+H = 36
+Color = P3Dark
+Type = Colorized
+
+[SingP3RTextScore]
+Text = 00000
+X = 688
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP3SingBar]
+X = 670
+Y = 95
+W = 100
+H = 8
+
+[Score]
+Texts = 1
+
+[ScoreBackground]
+Tex = ScoreScreenBG
+
+[ScoreText1]
+X = 70
+Y = 6
+Color = GrayLight
+Font =1
+Size = 60
+Text = SONG_SCORE
+Align = 0
+
+[ScoreTextArtistTitle]
+X = 105
+Y = 65
+Color = GrayDark
+Font = 0
+Size = 26
+Align = 0
+Text = ArtistTitle
+
+[ScoreStatic1]
+X = 70
+Y = 63
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+
+[ScoreStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreStatic4]
+X =350
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[ScoreText2]
+X =390
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+
+#end of main stuff
+
+# # # # # # # # # # # # # # # # # # One Player Score # # # # # # # # # # # #
+[ScoreTextName1]
+X = 197
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = Black
+Align = 0
+
+# Rating
+[ScoreStaticRatingPicture1]
+X = 385
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore1]
+X = 422
+Y = 235
+width = 100
+Color = Black
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+# Note Score
+[ScoreStaticBoxDark1]
+Tex = ScoreBar_box_dark
+X = 200
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes1]
+X = 227
+Y = 322
+Color = Black
+Font = 0
+Size = 30
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore1]
+X = 487
+Y = 322
+Color = Black
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static1]
+Tex = ScoreLine
+X = 200
+Y = 351
+W = 287
+H = 1
+Color = Gray
+Type = Transparent
+
+# Line Bonus
+[ScoreStaticBoxLight1]
+Tex = ScoreBar_box_light
+X = 200
+Y = 358
+W = 22
+H = 20
+Color = P1Light
+Type = Colorized
+
+[ScoreTextLineBonus1]
+X = 227
+Y = 352
+Color = Black
+Font = 0
+Size = 30
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore1]
+X = 487
+Y = 352
+Color = Black
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static2]
+Tex = ScoreLine
+X = 200
+Y = 382
+W = 287
+H = 1
+Color = Gray
+Type = Transparent
+
+# Golden Notes
+[ScoreStaticBoxLightest1]
+Tex = ScoreBar_box_lightest
+X = 200
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes1]
+X = 227
+Y = 383
+Color = Black
+Font = 0
+Size = 30
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore1]
+X = 487
+Y = 383
+Color = Black
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+#Total Score
+[ScoreStaticPlayerIdBox1]
+Tex = PlayerIDBox01
+X = 200
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+
+
+[ScoreTextTotal1]
+X = 237
+Y = 454
+Color = Black
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 0
+
+
+[ScoreTextTotalSCore1]
+X = 487
+Y = 444
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 0
+
+#ScoreBar
+[ScoreStaticBackLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 168
+W = 95
+H = 310
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound1]
+Tex = ScoreLevelRound
+X = 503
+Y = 138
+W = 95
+H = 8
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 400
+W = 95
+H = 10
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound1]
+Tex = ScoreLevelRound
+X = 503
+Y = 392
+W = 95
+H = 8
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer1Static3]
+Tex = ScoreEndCap
+X = 499
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P1Dark
+Type = Colorized
+
+
+[ScorePlayer1Static4]
+Tex = ScoreGlassBox
+X = 499
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# # # # # # # # # # # # # # # # # # Two Player Score # # # # # # # # # # # #
+# P L A Y E R   O N E
+[ScoreTextName2]
+X = 42
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = Black
+Align = 0
+
+[ScoreStaticRatingPicture2]
+X = 180
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore2]
+X = 217
+Y = 235
+Width = 100
+Color = Black
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark2]
+Tex = ScoreBar_box_dark
+X = 45
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes2]
+X = 72
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore2]
+X = 282
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLight2]
+Tex = ScoreBar_box_light
+X = 45
+Y = 358
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextLineBonus2]
+X = 72
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore2]
+X = 282
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLightest2]
+Tex = ScoreBar_box_lightest
+X = 45
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes2]
+X = 72
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore2]
+X = 282
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreTextTotal2]
+X = 82
+Y = 454
+Color = Black
+Font = 0
+Size = 30
+Text = SING_TOTAL
+
+
+[ScoreTextTotalSCore2]
+X = 283
+Y = 444
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+
+# Lines
+[ScorePlayer2Static1]
+Tex = ScoreLine
+X = 45
+Y = 351
+W = 237
+H = 1
+Type = Transparent
+Color = Gray
+
+[ScorePlayer2Static2]
+Tex = ScoreLine
+X = 45
+Y = 382
+W = 237
+H = 1
+Type = Transparent
+Color = Gray
+
+[ScoreStaticPlayerIdBox2]
+Tex = PlayerIDBox01
+X = 45
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+
+
+#ScoreBar
+[ScoreStaticBackLevel2]
+Tex = ScoreLevel
+X = 298
+Y = 168
+W = 95
+H = 310
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound2]
+Tex = ScoreLevelRound
+X = 298
+Y = 138
+W = 95
+H = 8
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel2]
+Tex = ScoreLevel
+X = 298
+Y = 400
+W = 95
+H = 10
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound2]
+Tex = ScoreLevelRound
+X = 298
+Y = 392
+W = 95
+H = 8
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer2Static3]
+Tex = ScoreEndCap
+X = 294
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P1Dark
+Type = Colorized
+
+
+[ScorePlayer2Static4]
+Tex = ScoreGlassBox
+X = 294
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# P L A Y E R   T W O
+[ScoreTextName3]
+X = 758
+Y = 290
+Font = 0
+Size = 30
+Text = P2
+Color = Black
+Align = 2
+
+[ScoreStaticRatingPicture3]
+X = 545
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore3]
+X = 583
+Y = 235
+width = 100
+Color = Black
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark3]
+Tex = ScoreBar_box_dark
+X = 733
+Y = 327
+W = 22
+H = 20
+Color = P2Dark
+Type = Colorized
+
+[ScoreTextNotes3]
+X = 728
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 2
+
+[ScoreTextNotesScore3]
+X = 518
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLight3]
+Tex = ScoreBar_box_light
+X = 733
+Y = 358
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextLineBonus3]
+X = 728
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 2
+
+[ScoreTextLineBonusScore3]
+X = 518
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLightest3]
+Tex = ScoreBar_box_lightest
+X = 733
+Y = 390
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes3]
+X = 728
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 2
+
+[ScoreTextGoldenNotesScore3]
+X = 518
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreTextTotal3]
+X = 718
+Y = 454
+Color = Black
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 2
+
+
+[ScoreTextTotalScore3]
+X = 517
+Y = 444
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 00000
+
+
+#Lines
+[ScorePlayer3Static1]
+Tex = ScoreLine
+X = 518
+Y = 351
+W = 237
+H = 1
+Type = Transparent
+Color = Gray
+
+[ScorePlayer3Static2]
+Tex = ScoreLine
+X = 518
+Y = 382
+W = 237
+H = 1
+Type = Transparent
+Color = Gray
+
+[ScoreStaticPlayerIdBox3]
+Tex = PlayerIDBox02
+X = 729
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+
+
+#ScoreBar
+[ScoreStaticBackLevel3]
+Tex = ScoreLevel
+X = 409
+Y = 168
+W = 95
+H = 310
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound3]
+Tex = ScoreLevelRound
+X = 409
+Y = 138
+W = 95
+H = 8
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticLevel3]
+Tex = ScoreLevel
+X = 409
+Y = 400
+W = 95
+H = 10
+Color = P2Dark
+Type = Colorized
+
+[ScoreStaticLevelRound3]
+Tex = ScoreLevelRound
+X = 409
+Y = 392
+W = 95
+H = 8
+Color = P2Dark
+Type = Colorized
+
+[ScorePlayer3Static3]
+Tex = ScoreEndCap
+X = 405
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P2Dark
+Type = Colorized
+
+
+[ScorePlayer3Static4]
+Tex = ScoreGlassBox
+X = 405
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# # # # # # # # # # # # # # # # # # Three Player Score # # # # # # # # # # # #
+# P L A Y E R  O N E
+[ScoreTextName4]
+X = 20
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P1
+Color = Black
+
+# Rating
+[ScoreStaticRatingPicture4]
+X = 200
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes4]
+X = 20
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = Black
+
+[ScoreTextNotesScore4]
+X = 260
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextLineBonus4]
+X = 20
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Black
+
+[ScoreTextLineBonusScore4]
+X = 260
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextGoldenNotes4]
+X = 20
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Black
+
+[ScoreTextGoldenNotesScore4]
+X = 260
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextScore4]
+X = 20
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = Black
+
+[ScoreTextTotal4]
+X = 47
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Black
+
+
+[ScoreTextTotalScore4]
+X = 260
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Black
+
+
+[ScoreStaticBoxDark4]
+Tex = PlayerNumberBox
+X = 20
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P1Dark
+Z = 0.9
+
+
+[ScorePlayer4Text1]
+X = 24
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = Black
+Font = 1
+Size = 15
+Align = 0
+Text = P1
+
+#lines
+[ScorePlayer4Static1]
+X = 20
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer4Static2]
+X = 20
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer4Static3]
+X = 20
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer4Static4]
+X = 20
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer4Static5]
+X = 20
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+# P L A Y E R  T W O
+[ScoreTextName5]
+X = 280
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P2
+Color = Black
+
+# Rating
+[ScoreStaticRatingPicture5]
+X = 460
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes5]
+X = 280
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = Black
+
+[ScoreTextNotesScore5]
+X = 520
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextLineBonus5]
+X = 280
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Black
+
+[ScoreTextLineBonusScore5]
+X = 520
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextGoldenNotes5]
+X = 280
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Black
+
+[ScoreTextGoldenNotesScore5]
+X = 520
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextScore5]
+X = 280
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = Black
+
+[ScoreTextTotal5]
+X = 307
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Black
+
+[ScoreTextTotalScore5]
+X = 520
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Black
+
+[ScoreStaticBoxDark5]
+Tex = PlayerNumberBox
+X = 280
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P2Dark
+Z = 0.9
+
+
+[ScorePlayer5Text1]
+X = 284
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = Black
+Font = 1
+Size = 15
+Align = 0
+Text = P2
+
+[ScorePlayer5Static1]
+X = 280
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer5Static2]
+X = 280
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer5Static3]
+X = 280
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer5Static4]
+X = 280
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer5Static5]
+X = 280
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+# P L A Y E R  T H R E E
+[ScoreTextName6]
+X = 540
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P3
+Color = Black
+
+# Rating
+[ScoreStaticRatingPicture6]
+X = 720
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes6]
+X = 540
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = Black
+
+[ScoreTextNotesScore6]
+X = 780
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextLineBonus6]
+X = 540
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Black
+
+[ScoreTextLineBonusScore6]
+X = 780
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextGoldenNotes6]
+X = 540
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Black
+
+[ScoreTextGoldenNotesScore6]
+X = 780
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextScore6]
+X = 540
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = Black
+
+[ScoreTextTotal6]
+X = 567
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Black
+
+[ScoreTextTotalScore6]
+X = 780
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Black
+
+[ScoreStaticBoxDark6]
+Tex = PlayerNumberBox
+X = 540
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P3Dark
+Z = 0.9
+
+
+[ScorePlayer6Text1]
+X = 544
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = Black
+Font = 1
+Size = 15
+Align = 0
+Text = P3
+
+#lines
+[ScorePlayer6Static1]
+X = 540
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer6Static2]
+X = 540
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer6Static3]
+X = 540
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer6Static4]
+X = 540
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[ScorePlayer6Static5]
+X = 540
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
+
+[Options]
+Texts = 6
+Fade = 2
+
+[OptionsBackground]
+Tex = OptionsBG
+
+[OptionsStatic1]
+X=40
+Y=250
+W=32
+H=32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[OptionsText1]
+X = 50
+Y = 170
+Color = GrayLight
+Font = 1
+Size = 75
+Text = SING_OPTIONS
+Align = 0
+
+
+[OptionsTextDescription]
+X = 70
+Y = 248
+Color = GrayDark
+Font = 1
+Size = 30
+Align = 0
+Text =
+
+[OptionsStatic2]
+X = 156
+Y = 545
+W =32
+H =30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+
+[OptionsText2]
+X =196
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+
+[OptionsStatic3]
+X =340
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+
+[OptionsText3]
+X =380
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_SELECT
+
+
+[OptionsStatic4]
+X =530
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+
+[OptionsText4]
+X =570
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_ESC
+
+
+[OptionsButtonGame]
+X = 40
+Y = 310
+W = 180
+H = 70
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+
+[OptionsButtonGameText1]
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_GAME
+Color = White
+
+[OptionsButtonGraphics]
+X = 220
+Y = 310
+W = 180
+H = 70
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+
+[OptionsButtonGraphicsText1]
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_GRAPHICS
+Color = White
+
+[OptionsButtonSound]
+X = 400
+Y = 310
+W = 180
+H = 70
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+[OptionsButtonSoundText1]
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_SOUND
+Color = White
+
+[OptionsButtonLyrics]
+X = 580
+Y = 310
+W = 180
+H = 70
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
+
+[OptionsButtonLyricsText1]
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_LYRICS
+Color = White
+
+[OptionsButtonThemes]
+X = 40
+Y = 380
+W = 180
+H = 70
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
+
+
+[OptionsButtonThemesText1]
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_THEMES
+Color = White
+
+[OptionsButtonRecord]
+X = 220
+Y = 380
+W = 180
+H = 70
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
+
+[OptionsButtonRecordText1]
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_RECORD
+Color = White
+Texts = 1
+
+[OptionsButtonAdvanced]
+X = 400
+Y = 380
+W = 180
+H = 70
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
+
+[OptionsButtonAdvancedText1]
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_ADVANCED
+Color = White
+Texts = 1
+
+[OptionsButtonExit]
+X = 580
+Y = 380
+W = 180
+H = 70
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
+
+
+[OptionsButtonExitText1]
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[OptionsGame]
+Texts = 5
+
+[OptionsGameBackground]
+Tex = OptionsBG
+
+[OptionsGameStatic1]
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[OptionsGameText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
+
+
+[OptionsGameText2]
+X = 105
+Y = 80
+Color = Gray
+Size = 30
+Text = SING_OPTIONS_GAME_WHEREAMI
+
+
+[OptionsGameStatic2]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+
+[OptionsGameText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsGameStatic3]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+
+[OptionsGameText4]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+
+[OptionsGameSelectPlayers]
+Text = SING_OPTIONS_GAME_PLAYERS
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectDifficulty]
+Text = SING_OPTIONS_GAME_DIFFICULTY
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectSlideLanguage]
+Text = SING_OPTIONS_GAME_LANGUAGE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectTabs]
+Text = SING_OPTIONS_GAME_TABS
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectSlideSorting]
+Text = SING_OPTIONS_GAME_SORTING
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectDebug]
+Text = SING_OPTIONS_GAME_DEBUG
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[OptionsGraphics]
+Texts = 5
+
+[OptionsGraphicsBackground]
+Tex = OptionsBG
+
+[OptionsGraphicsStatic1]
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[OptionsGraphicsText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
+
+
+[OptionsGraphicsText2]
+X = 105
+Y = 80
+Color = Gray
+Size = 30
+Text = SING_OPTIONS_GRAPHICS_WHEREAMI
+
+[OptionsGraphicsStatic2]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsGraphicsText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsGraphicsStatic3]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsGraphicsText4]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+
+[OptionsGraphicsSelectSlideResolution]
+Text = SING_OPTIONS_GRAPHICS_RESOLUTION
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectFullscreen]
+Text = SING_OPTIONS_GRAPHICS_FULLSCREEN
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectDepth]
+Text = SING_OPTIONS_GRAPHICS_DEPTH
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectVisualizer]
+Text = SING_OPTIONS_GRAPHICS_VISUALIZER
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectOscilloscope]
+Text = SING_OPTIONS_GRAPHICS_OSCILLOSCOPE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectMovieSize]
+Text = SING_OPTIONS_GRAPHICS_MOVIE_SIZE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[OptionsSound]
+Texts = 5
+
+[OptionsSoundBackground]
+Tex = OptionsBG
+
+[OptionsSoundStatic1]
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[OptionsSoundText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
+
+[OptionsSoundText2]
+X = 105
+Y = 80
+Color = Gray
+Size = 30
+Text = SING_OPTIONS_SOUND_WHEREAMI
+
+
+[OptionsSoundStatic2]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsSoundText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsSoundStatic3]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsSoundText4]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+
+[OptionsSoundSelectVoicePassthrough]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_VOICEPASSTHROUGH
+X = 70
+Y = 130
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectBackgroundMusic]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_BACKGROUNDMUSIC
+X = 70
+Y = 170
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectMicBoost]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_MIC_BOOST
+X = 70
+Y = 210
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectClickAssist]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_CLICK_ASSIST
+X = 70
+Y = 250
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectBeatClick]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_BEAT_CLICK
+X = 70
+Y = 290
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectThreshold]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_THRESHOLD
+X = 70
+Y = 330
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectSlidePreviewVolume]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_PREVIEWVOLUME
+X = 70
+Y = 370
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectSlidePreviewFADING]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_PREVIEWFADING
+X = 70
+Y = 410
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundButtonExit]
+X = 70
+Y = 460
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[OptionsLyrics]
+Texts = 1
+
+[OptionsLyricsBackground]
+Tex = OptionsBG
+
+[OptionsLyricsStatic1]
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+
+[OptionsLyricsText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
+
+[OptionsLyricsText2]
+X = 105
+Y = 80
+Color = Gray
+Size = 30
+Text = SING_OPTIONS_LYRICS_WHEREAMI
+
+[OptionsLyricsStatic2]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsLyricsText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsLyricsStatic3]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsLyricsText4]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+
+[OptionsLyricsSelectLyricsFont]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_LYRICS_FONT
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsSelectLyricsEffect]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_LYRICS_EFFECT
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsSelectNoteLines]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_LYRICS_NOTELINES
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[OptionsThemes]
+Texts = 5
+
+[OptionsThemesBackground]
+Tex = OptionsBG
+
+[OptionsThemesStatic1]
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+
+[OptionsThemesText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
+
+[OptionsThemesText2]
+X = 105
+Y = 80
+Color = Gray
+Size = 30
+Text = SING_OPTIONS_THEMES_WHEREAMI
+
+[OptionsThemesStatic2]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsThemesText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsThemesStatic3]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsThemesText4]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+
+[OptionsThemesSelectTheme]
+Text = SING_OPTIONS_THEMES_THEME
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesSelectSkin]
+Text = SING_OPTIONS_THEMES_SKIN
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesSelectColor]
+Text = SING_OPTIONS_THEMES_COLOR
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[OptionsRecord]
+Texts = 5
+
+[OptionsRecordBackground]
+Tex = OptionsBG
+
+[OptionsRecordStatic1]
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[OptionsRecordText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
+
+[OptionsRecordText2]
+X = 105
+Y = 80
+Color = Gray
+Size = 30
+Text = SING_OPTIONS_RECORD_WHEREAMI
+
+[OptionsRecordStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordStatic4]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsRecordText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsRecordStatic5]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsRecordText4]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+
+[OptionsRecordSelectSlideCard]
+Text = SING_OPTIONS_RECORD_CARD
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordSelectSlideInput]
+Text = SING_OPTIONS_RECORD_INPUT
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordSelectSlideChannel]
+Text = SING_OPTIONS_RECORD_CHANNEL
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordButtonExit]
+X = 70
+Y = 390
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[OptionsAdvanced]
+Texts = 5
+
+[OptionsAdvancedBackground]
+Tex = OptionsBG
+
+[OptionsAdvancedStatic1]
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[OptionsAdvancedText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
+
+
+[OptionsAdvancedText2]
+X = 105
+Y = 80
+Color = Gray
+Size = 30
+Text = SING_OPTIONS_ADVANCED_WHEREAMI
+
+[OptionsAdvancedStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedStatic4]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[OptionsAdvancedText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+
+
+[OptionsAdvancedStatic5]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[OptionsAdvancedText4]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+
+#########unused at the moment#########
+#[OptionsAdvancedSelectLoadAnimation]
+#Text = SING_OPTIONS_ADVANCED_LOADANIMATION
+#Tex = MainBar
+#TexSBG = SelectBG
+#X = 40
+#Y = 85
+#W = 230
+#H = 70
+#SkipX = 10
+
+#Color = ColorDark
+#DColor = ColorLight
+#TColor = White
+#TDColor = White
+
+#SBGColor = DarkBlue
+#SBGDColor = LightBlue
+#STColor = White
+#STDColor = GrayDark
+
+[OptionsAdvancedSelectScreenFade]
+Text = SING_OPTIONS_ADVANCED_SCREENFADE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectEffectSing]
+Text = SING_OPTIONS_ADVANCED_EFFECTSING
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectLineBonus]
+Text = SING_OPTIONS_GRAPHICS_LINEBONUS
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectSlideOnSongClick]
+Text = SING_OPTIONS_ADVANCED_ONSONGCLICK
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectAskbeforeDel]
+Text = SING_OPTIONS_ADVANCED_ASKBEFOREDEL
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectPartyPopup]
+Text = SING_OPTIONS_ADVANCED_PARTYPOPUP
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+
+[Top5]
+Texts = 1
+
+[Top5Background]
+Tex = Top5BG
+
+[Top5Text1]
+X = 70
+Y = 6
+Color = GrayLight
+Font =1
+Size = 60
+Text = SING_TOP_5_CHARTS
+
+[Top5TextArtistTitle]
+X = 105
+Y = 65
+Color = GrayDark
+Font = 0
+Size = 26
+Align = 0
+Text = artist - title
+
+[Top5Text4]
+X = 390
+Y = 30
+Color = Black
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_GAME_DIFFICULTY
+
+[Top5TextLevel]
+X = 600
+Y = 30
+Color = Black
+Font = 0
+Size = 30
+Align = 1
+Text = easy
+
+[Top5Static1]
+X = 70
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[Top5Static2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Static3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Static4]
+X = 200
+Y = 553
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[Top5Text2]
+X = 240
+Y = 555
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_TOP_5_CHARTS_CONTINUE
+
+[Top5Static5]
+X = 450
+Y = 553
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[Top5Text3]
+X = 490
+Y = 555
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_TOP_5_CHARTS_SWITCH_DIFFICULTY
+
+[Top5TextName1]
+X = 150
+Y = 190
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 1. Player1
+
+[Top5TextName2]
+X = 150
+Y = 240
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 2. Player2
+
+[Top5TextName3]
+X = 150
+Y = 290
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 3. Player3
+
+[Top5TextName4]
+X = 150
+Y = 340
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 4. Player4
+
+[Top5TextName5]
+X = 150
+Y = 390
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 5. Player5
+
+[Top5TextScore1]
+X = 560
+Y = 190
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore2]
+X = 560
+Y = 240
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore3]
+X = 560
+Y = 290
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore4]
+X = 560
+Y = 340
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore5]
+X = 560
+Y = 390
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+
+[Top5TextDate1]
+X = 760
+Y = 190
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate2]
+X = 760
+Y = 240
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate3]
+X = 760
+Y = 290
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate4]
+X = 760
+Y = 340
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate5]
+X = 760
+Y = 390
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextNumber1]
+X = 120
+Y = 193
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 1
+
+[Top5TextNumber2]
+X = 120
+Y = 243
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 2
+
+[Top5TextNumber3]
+X = 120
+Y = 293
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 3
+
+[Top5TextNumber4]
+X = 120
+Y = 343
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 4
+
+[Top5TextNumber5]
+X = 120
+Y = 393
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 5
+
+[Top5StaticNumber1]
+Tex = PlayerNumberBox
+X = 100
+Y = 186
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber2]
+Tex = PlayerNumberBox
+X = 100
+Y = 236
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber3]
+Tex = PlayerNumberBox
+X = 100
+Y = 286
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber4]
+Tex = PlayerNumberBox
+X = 100
+Y = 336
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber5]
+Tex = PlayerNumberBox
+X = 100
+Y = 386
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Edit]
+Texts = 5
+
+[EditBackground]
+Tex = EditBG
+
+# main icon
+[EditStatic1]
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+# Type = Colorized
+
+# main icon title
+[EditText1]
+X = 70
+Y = 5
+Color = Gray
+Font = 1
+Size = 60
+Align = 0
+Text = SING_EDIT
+
+# main icon subtitle
+[EditText2]
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = SING_EDIT_MENU_DESCRIPTION
+
+# Navigate button text
+[EditText3]
+X =166
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_EDIT_NAVIGATE
+
+
+# Select button text
+[EditText4]
+X =350
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_SELECT
+
+
+# Esc button text
+[EditText5]
+X =570
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_EXIT
+
+
+[EditTextDescription]
+X = 95
+Y = 195
+Color = Black
+Font = 0
+Size = 30
+Align = 0
+Text = SING_EDIT_TEXTDESCRIPTION
+
+[EditStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic4]
+X = 126
+Y = 545
+W =32
+H =30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+
+[EditStatic5]
+X =310
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[EditStatic6]
+X =530
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[EditButtonConvert]
+X = 250
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+[EditButtonConvertText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_CONVERT
+Color = White
+
+[EditButtonExit]
+X = 405
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+FadeTexPos = 0
+
+[EditButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_EXIT
+Color = White
+
+[Level]
+Texts = 5
+
+[LevelBackground]
+Tex = MainBG
+
+[LevelStatic1]
+X=20
+Y=250
+W=32
+H=32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[LevelText1]
+X=30
+Y=180
+Font=1
+Size = 66
+Align=0
+Text = SING_MODE
+Color=GrayLight
+
+[LevelText2]
+X=50
+Y=248
+Font=1
+Size = 30
+Align=0
+Text=SING_PLAYER_DESC
+Color=GrayDark
+
+[LevelStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic4]
+X = 216
+Y = 545
+W =32
+H =30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[LevelStatic5]
+X =400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+
+[LevelText3]
+X =256
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+
+[LevelText4]
+X =440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_DIFFICULTY_CONTINUE
+
+
+[LevelButtonEasy]
+Tex=Button
+X=25
+Y=310
+W=250
+H=70
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+[LevelButtonMedium]
+Tex=Button
+X=275
+Y=310
+W=250
+H=70
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+
+[LevelButtonHard]
+Tex=Button
+X=525
+Y=310
+W=250
+H=70
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+
+[LevelButtonEasyText1]
+X=115
+Y=20
+Font=1
+Size = 27
+Align=1
+Text=SING_EASY
+Color=White
+
+[LevelButtonMediumText1]
+X=115
+Y=20
+Font=1
+Size = 27
+Align=1
+Text=SING_MEDIUM
+Color=White
+
+[LevelButtonHardText1]
+X=115
+Y=20
+Font=1
+Size = 27
+Align=1
+Text=SING_HARD
+Color=White
+
+[Name]
+Texts = 2
+
+[NameBackground]
+Tex  = MainBG
+
+[NameStatic1]
+X=20
+Y=250
+W=32
+H=32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[NameText1]
+X=30
+Y=180
+Font=1
+Size = 66
+Align=0
+Text = SING_MODE
+Color=GrayLight
+
+[NameText2]
+X=50
+Y=248
+Font=1
+Size = 30
+Align=0
+Text=SING_PLAYER_DESC
+Color=GrayDark
+
+[NameStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameStatic4]
+X = 126
+Y = 545
+W =32
+H =30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[NameText3]
+X =166
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[NameStatic5]
+X =310
+Y = 545
+W = 32
+H = 30
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+
+
+[NameText4]
+X =350
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_PLAYER_ENTER_NAME
+
+[NameStatic6]
+X =530
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+
+[NameText5]
+X =570
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+
+
+[NameButtonPlayer1]
+X=25
+Y=310
+W=250
+H=70
+Tex = Button
+Color = P1Dark
+DColor = P1Light
+Type = Transparent
+Texts = 1
+
+
+[NameButtonPlayer1Text1]
+X=115
+Y=20
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer2]
+X = 275
+Y=310
+W=250
+H=70
+Tex = Button
+Color = P2Dark
+DColor = P2Light
+Type = Transparent
+Texts = 1
+
+
+[NameButtonPlayer2Text1]
+X=115
+Y=20
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer3]
+X = 525
+Y=310
+W=250
+H=70
+Tex = Button
+Color = P3Dark
+DColor = P3Light
+Type = Transparent
+Texts = 1
+
+
+[NameButtonPlayer3Text1]
+X=115
+Y=20
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer4]
+X=25
+Y=400
+W=250
+H=70
+Tex = Button
+Color = P4Dark
+DColor = P4Light
+Type = Transparent
+Texts = 1
+
+
+[NameButtonPlayer4Text1]
+X=115
+Y=20
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer5]
+X = 275
+Y=400
+W=250
+H=70
+Tex = Button
+Color = P5Dark
+DColor = P5Light
+Type = Transparent
+Texts = 1
+
+
+[NameButtonPlayer5Text1]
+X=115
+Y=20
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer6]
+X = 525
+Y=400
+W=250
+H=70
+Tex = Button
+Color = P6Dark
+DColor = P6Light
+Type = Transparent
+Texts = 1
+
+
+[NameButtonPlayer6Text1]
+X=115
+Y=20
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[PartyNewRound]
+Texts = 7
+
+[PartyNewRoundBackground]
+Tex = MainBG
+
+[PartyNewRoundStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStatic3]
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[PartyNewRoundText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 1
+Size = 60
+Color = GrayLight
+Text = PARTY_MODE
+
+[PartyNewRoundText2]
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_ROUND_DESC
+
+[PartyNewRoundText3]
+X = 388
+Y = 555
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = PARTY_ROUND_WHEREAMI
+
+[PartyNewRoundText4]
+X = 450
+Y = 555
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_ROUND_LEGEND_CONTINUE
+
+[PartyNewRoundText5]
+X = 460
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND
+Align = 0
+
+[PartyNewRoundText6]
+X = 600
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND_WINNER
+Align = 0
+
+[PartyNewRoundText7]
+X = 448
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = PARTY_ROUND
+Align = 2
+
+[PartyNewRoundTextTeam1Players]
+X = 30
+Y = 137
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam2Players]
+X = 30
+Y = 218
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam3Players]
+X = 30
+Y = 299
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundStatic4]
+Tex = PartyRoundBG1
+X = 450
+Y = 103
+W = 330
+H = 24
+Color = Gray
+Type = Transparent
+
+[PartyNewRoundStatic5]
+X = 410
+Y = 553
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyNewRoundStatic6]
+Tex = PartyRoundBG3
+X = 250
+Y = 350
+W = 300
+H = 50
+Color = Gray
+Type = Transparent
+
+[PartyNewRoundStatic7]
+Tex = PartyRoundBG4
+X = 50
+Y = 495
+W = 700
+H = 30
+Color = GrayLight
+Type = Transparent
+
+[PartyNewRoundStaticTeam1]
+Tex = PartyTeamButton1
+X = 20
+Y = 110
+W = 400
+H = 50
+Color = P1Dark
+Type = Transparent
+Reflection = 0
+
+[PartyNewRoundStaticTeam2]
+Tex = PartyTeamButton1
+X = 20
+Y = 191
+W = 400
+H = 50
+Color = P2Dark
+Type = Transparent
+Reflection = 0
+
+[PartyNewRoundStaticTeam3]
+Tex = PartyTeamButton1
+X = 20
+Y = 272
+W = 400
+H = 50
+Color = P3Dark
+Type = Transparent
+Reflection = 0
+
+[PartyNewRoundStaticNextPlayer1]
+Tex = PartyPlayerButton
+X = 155
+Y = 415
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Dark
+
+[PartyNewRoundStaticNextPlayer2]
+Tex = PartyPlayerButton
+X = 325
+Y = 415
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Dark
+
+
+[PartyNewRoundStaticNextPlayer3]
+Tex = PartyPlayerButton
+X = 495
+Y = 415
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Dark
+
+
+
+[PartyNewRoundTextRound1]
+X = 460
+Y = 133
+Color = White
+Font = 0
+Size = 24
+Text = Round 1
+Align = 0
+
+[PartyNewRoundTextRound2]
+X = 460
+Y = 162
+Color = White
+Font = 0
+Size = 24
+Text = Round 2
+Align = 0
+
+[PartyNewRoundTextRound3]
+X = 460
+Y = 191
+Color = White
+Font = 0
+Size = 24
+Text = Round 3
+Align = 0
+
+[PartyNewRoundTextRound4]
+X = 460
+Y = 220
+Color = White
+Font = 0
+Size = 24
+Text = Round 4
+Align = 0
+
+[PartyNewRoundTextRound5]
+X = 460
+Y = 249
+Color = White
+Font = 0
+Size = 24
+Text = Round 5
+Align = 0
+
+[PartyNewRoundTextRound6]
+X = 460
+Y = 278
+Color = White
+Font = 0
+Size = 24
+Text = Round 6
+Align = 0
+
+[PartyNewRoundTextRound7]
+X = 460
+Y = 307
+Color = White
+Font = 0
+Size = 24
+Text = Round 7
+Align = 0
+
+[PartyNewRoundTextWinner1]
+X = 600
+Y = 133
+Color = White
+Font = 0
+Size = 24
+Text = Winner 1
+Align = 0
+
+[PartyNewRoundTextWinner2]
+X = 600
+Y = 162
+Color = White
+Font = 0
+Size = 24
+Text = Winner 2
+Align = 0
+
+[PartyNewRoundTextWinner3]
+X = 600
+Y = 191
+Color = White
+Font = 0
+Size = 24
+Text = Winner 3
+Align = 0
+
+[PartyNewRoundTextWinner4]
+X = 600
+Y = 220
+Color = White
+Font = 0
+Size = 24
+Text = Winner 4
+Align = 0
+
+[PartyNewRoundTextWinner5]
+X = 600
+Y = 249
+Color = White
+Font = 0
+Size = 24
+Text = Winner 5
+Align = 0
+
+[PartyNewRoundTextWinner6]
+X = 600
+Y = 278
+Color = White
+Font = 0
+Size = 24
+Text = Winner 6
+Align = 0
+
+[PartyNewRoundTextWinner7]
+X = 600
+Y = 307
+Color = White
+Font = 0
+Size = 24
+Text = Winner 7
+Align = 0
+
+[PartyNewRoundStaticRound1]
+Tex = PartyRoundBG2
+X = 450
+Y = 135
+W = 330
+H = 20
+Color = GrayLight
+Type = Transparent
+
+[PartyNewRoundStaticRound2]
+Tex = PartyRoundBG2
+X = 450
+Y = 164
+W = 330
+H = 20
+Color = GrayLight
+Type = Transparent
+
+[PartyNewRoundStaticRound3]
+Tex = PartyRoundBG2
+X = 450
+Y = 193
+W = 330
+H = 20
+Color = GrayLight
+Type = Transparent
+[PartyNewRoundStaticRound4]
+Tex = PartyRoundBG2
+X = 450
+Y = 222
+W = 330
+H = 20
+Color = GrayLight
+Type = Transparent
+[PartyNewRoundStaticRound5]
+Tex = PartyRoundBG2
+X = 450
+Y = 251
+W = 330
+H = 20
+Color = GrayLight
+Type = Transparent
+
+[PartyNewRoundStaticRound6]
+Tex = PartyRoundBG2
+X = 450
+Y = 280
+W = 330
+H = 20
+Color = GrayLight
+Type = Transparent
+
+[PartyNewRoundStaticRound7]
+Tex = PartyRoundBG2
+X = 450
+Y = 309
+W = 330
+H = 20
+Color = GrayLight
+Type = Transparent
+
+[PartyNewRoundTextNextRound]
+X = 400
+Y = 495
+Color = White
+Font = 0
+Size = 30
+Text = Next Round
+Align = 1
+
+[PartyNewRoundTextNextRoundNo]
+X = 457
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = 99
+Align = 0
+
+[PartyNewRoundTextScoreTeam1]
+X = 390
+Y = 110
+Color = White
+Font = 0
+Size = 51
+Text = 3000
+Align = 1
+
+[PartyNewRoundTextScoreTeam2]
+X = 390
+Y = 191
+Color = White
+Font = 0
+Size = 51
+Text = 2000
+Align = 1
+
+[PartyNewRoundTextScoreTeam3]
+X = 390
+Y = 272
+Color = White
+Font = 0
+Size = 51
+Text = 1000
+Align = 1
+
+[PartyNewRoundTextNameTeam1]
+X = 30
+Y = 108
+Color = White
+Font = 0
+Size = 36
+Text = Team 1
+Align = 0
+
+[PartyNewRoundTextNameTeam2]
+X = 30
+Y = 189
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyNewRoundTextNameTeam3]
+X = 30
+Y = 270
+Color = White
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyNewRoundTextNextPlayer1]
+X = 230
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 1
+Align = 1
+
+[PartyNewRoundTextNextPlayer2]
+X = 400
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 2
+Align = 1
+
+[PartyNewRoundTextNextPlayer3]
+X = 570
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 3
+Align = 1
+
+
+[PartyScore]
+Texts = 5
+
+[PartyScoreBackground]
+Tex = PartyBG
+
+[PartyScoreDecoTextures]
+ChangeTextures = 1
+
+FirstTexture = PartyScoreDeco
+FirstTyp = Colorized
+FirstColor = Gold
+
+SecondTexture = PartyScoreDeco
+SecondTyp = Colorized
+SecondColor = Silver
+
+ThirdTexture = PartyScoreDeco
+ThirdTyp = Colorized
+ThirdColor = Bronze
+
+[PartyScoreStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStatic3]
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[PartyScoreStatic4]
+X = 330
+Y = 553
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyScoreText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 1
+Size = 60
+Color = GrayLight
+Text = PARTY_MODE
+
+[PartyScoreText2]
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_SCORE_DESC
+
+
+[PartyScoreText3]
+X = 370
+Y = 555
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_LEGEND_CONTINUE
+
+[PartyScoreStatic5]
+Tex = PartyScoreBG1
+X = 50
+Y = 100
+W = 700
+H = 80
+Color = Gray
+Type = Transparent
+
+[PartyScoreStatic6]
+Tex = PartyScoreBG2
+X = 50
+Y = 495
+W = 700
+H = 20
+Color = Gray
+Type = Transparent
+
+[PartyScoreText5]
+X = 400
+Y = 136
+Color = White
+Font = 0
+Size = 45
+Text = PARTY_SCORE_WINS2
+Align = 1
+
+[PartyScoreTextWinner]
+X = 400
+Y = 98
+Color = White
+Font = 0
+Size = 54
+Text = The Winner is...
+Align = 1
+
+[PartyScoreTextScoreTeam1]
+X = 568
+Y = 198
+Color = White
+Font = 0
+Size = 36
+Text = 3000
+Align = 2
+
+[PartyScoreTextScoreTeam2]
+X = 568
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = 2000
+Align = 2
+
+[PartyScoreTextScoreTeam3]
+X = 568
+Y = 398
+Color = White
+Font = 0
+Size = 36
+Text = 1000
+Align = 2
+
+[PartyScoreTextNameTeam1]
+X = 188
+Y = 198
+Font = 0
+Size = 36
+Align = 0
+Text = Team 1
+Color = White
+
+[PartyScoreTextNameTeam2]
+X = 188
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyScoreTextNameTeam3]
+X = 188
+Y = 398
+Color = White
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyScoreStaticTeam1]
+X = 188
+Y = 230
+W = 380
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Transparent
+
+[PartyScoreStaticTeam1BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 200
+W = 400
+H = 50
+Type = Transparent
+Color = P1Dark
+
+
+[PartyScoreStaticTeam1Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 191
+W = 64
+H = 64
+Type = Transparent
+Color = Gold
+
+
+[PartyScoreStaticTeam2]
+X = 188
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P2Dark
+Type = Transparent
+
+
+[PartyScoreStaticTeam2BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 300
+W = 400
+H = 50
+Type = Transparent
+Color = P2Dark
+
+
+[PartyScoreStaticTeam2Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 291
+W = 64
+H = 64
+Type = Transparent
+Color = Gold
+
+
+[PartyScoreStaticTeam3]
+X = 188
+Y = 430
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Transparent
+
+
+[PartyScoreStaticTeam3BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 400
+W = 400
+H = 50
+Type = Transparent
+Color = P3Dark
+
+
+[PartyScoreStaticTeam3Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 391
+W = 64
+H = 64
+Type = Transparent
+Color = Gold
+
+
+[PartyWin]
+Texts = 4
+
+[PartyWinBackground]
+Tex = PartyBG
+
+[PartyWinStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStatic3]
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[PartyWinStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = Button
+Enter
+Color = White
+Type = Transparent
+
+[PartyWinText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 1
+Size = 60
+Color = GrayLight
+Text = PARTY_MODE
+
+[PartyWinText2]
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_WIN_DESC
+
+[PartyWinText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_WIN_LEGEND_CONTINUE
+
+#[PartyWinTextWinner]
+#X = 150
+#Y = 120
+#Color = White
+#Font = 1
+#Size = 42
+#Text = The Winner is...
+#Align = 0
+
+[PartyWinTextScoreTeam1]
+X = 699
+Y = 183
+Color = White
+Font = 0
+Size = 57
+Text = 3000
+Align = 2
+
+[PartyWinTextScoreTeam2]
+X = 669
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = 2000
+Align = 2
+
+[PartyWinTextScoreTeam3]
+X = 649
+Y = 398
+Color = White
+Font = 0
+Size = 27
+Text = 1000
+Align = 2
+
+[PartyWinTextNameTeam1]
+X = 169
+Y = 183
+Font = 0
+Size = 57
+Align = 0
+Text = Team 1
+Color = White
+
+[PartyWinTextNameTeam2]
+X = 289
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyWinTextNameTeam3]
+X = 369
+Y = 398
+Color = White
+Font = 0
+Size = 27
+Text = Team 3
+Align = 0
+
+[PartyWinStaticTeam1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Transparent
+
+
+[PartyWinStaticTeam1BG]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Transparent
+Color = TeamColor
+
+
+[PartyWinStaticTeam1Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Transparent
+
+
+[PartyWinStaticTeam1BGRank1]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Transparent
+Color = P1Dark
+
+[PartyWinStaticTeam1Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Transparent
+
+[PartyWinStaticTeam1BGRank2]
+Tex = PartyTeamButton3
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Transparent
+Color = P1Dark
+
+
+[PartyWinStaticTeam1Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Transparent
+
+[PartyWinStaticTeam1BGRank3]
+Tex = PartyTeamButton3
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Transparent
+Color = P1Dark
+
+
+[PartyWinStaticTeam1Deco]
+Tex = PartyWinDeco1
+X = 91
+Y = 176
+W = 79
+H = 79
+Type = Colorized
+Color = Gold
+
+
+[PartyWinStaticTeam2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+
+
+[PartyWinStaticTeam2BG]
+Tex = PartyTeamButton4
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Transparent
+Color = TeamColor
+
+
+[PartyWinStaticTeam2Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamButton3
+Color = P2Dark
+Type = Transparent
+
+
+[PartyWinStaticTeam2BGRank1]
+Tex = PartyTeamButton4
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Transparent
+Color = P2Dark
+
+
+[PartyWinStaticTeam2Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P2Dark
+Type = Transparent
+
+
+[PartyWinStaticTeam2BGRank2]
+Tex = PartyTeamButton4
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Transparent
+Color = P2Dark
+
+
+[PartyWinStaticTeam2Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Transparent
+
+
+[PartyWinStaticTeam2BGRank3]
+Tex = PartyTeamButton4
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = TeamColor
+
+
+[PartyWinStaticTeam2Deco]
+Tex = PartyWinDeco2
+X = 226
+Y = 291
+W = 64
+H = 64
+Type = Colorized
+Color = Silver
+
+
+[PartyWinStaticTeam3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+
+
+[PartyWinStaticTeam3BG]
+Tex = PartyTeamButton5
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = TeamColor
+
+
+[PartyWinStaticTeam3Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+
+
+[PartyWinStaticTeam3BGRank1]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P3Dark
+
+
+[PartyWinStaticTeam3Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+
+
+[PartyWinStaticTeam3BGRank2]
+Tex = PartyTeamButton5
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P3Dark
+
+
+[PartyWinStaticTeam3Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+
+
+[PartyWinStaticTeam3BGRank3]
+Tex = PartyTeamButton5
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = P3Dark
+
+
+[PartyWinStaticTeam3Deco]
+Tex = PartyWinDeco3
+X = 316
+Y = 391
+W = 54
+H = 54
+Type = Colorized
+Color = Bronze
+
+
+[PartyOptions]
+Texts = 5
+
+[PartyOptionsBackground]
+Tex = PartyBG
+
+[PartyOptionsStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyOptionsStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyOptionsStatic3]
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[PartyOptionsStatic4]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyOptionsStatic5]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyOptionsText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 1
+Size = 60
+Color = GrayLight
+Text = PARTY_MODE
+
+[PartyOptionsText2]
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_OPTIONS_DESC
+
+[PartyOptionsText3]
+X = 290
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[PartyOptionsText4]
+X = 450
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+
+[PartyOptionsSelectLevel]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = PARTY_DIFFICULTY
+X = 70
+Y = 110
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+#TexSBG = SelectBG
+#W = 230
+#H = 40
+#SkipX = 10
+
+[PartyOptionsSelectPlayList]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = PARTY_PLAYLIST
+X = 70
+Y = 165
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyOptionsSelectPlayList2]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = PARTY_PLAYLIST
+X = 70
+Y = 220
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyOptionsSelectRounds]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = PARTY_ROUNDS
+X = 70
+Y = 250
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+
+
+[PartyPlayer]
+Texts = 6
+
+[PartyPlayerBackground]
+Tex = PartyBG
+
+[PartyPlayerStatic1]
+X = 0
+Y = 545
+Z = 0.7
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerStatic2]
+X = 250
+Y = 545
+Z = 0.7
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerStatic3]
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+
+[PartyPlayerStatic4]
+X = 126
+Y = 545
+W =32
+H =30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic5]
+X =310
+Y = 545
+W = 32
+H = 30
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic6]
+X =530
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyPlayerText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 1
+Size = 60
+Color = GrayLight
+Text = PARTY_MODE
+
+[PartyPlayerText2]
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_PLAYER_DESC
+
+
+[PartyPlayerText3]
+X =166
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[PartyPlayerText4]
+X =350
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_PLAYER_ENTER_NAME
+
+[PartyPlayerText5]
+X =570
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+
+[PartyPlayerSelectTeams]
+Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+Text = PARTY_TEAMS
+X = 75
+Y = 105
+W = 310
+SBGW = 150
+H = 40
+SkipX = 160
+Fields = 2
+
+Type = Transparent
+TypeSBG = Transparent
+
+
+Color = GrayLight
+DColor = Gray
+TColor = White
+TDColor = White
+SBGTex = MainBar
+SBGColor = GrayLight
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers1]
+;Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+Type = Transparent
+TypeSBG = Transparent
+;Text = PARTY_TEAMS_PLAYER1
+X = 335
+Y = 170
+W = 200
+SBGW = 150
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = P1Light
+DColor = P1Dark
+TColor = White
+TDColor = White
+
+SBGColor = P1Light
+SBGDColor = P1Dark
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers2]
+;Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+;Text = PARTY_TEAMS_PLAYER2
+X = 335
+Y = 300
+W = 200
+SBGW = 150
+H = 40
+SkipX = 10
+Fields = 1
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = P2Light
+DColor = P2Dark
+TColor = White
+TDColor = White
+
+SBGColor = P2Light
+SBGDColor = P2Dark
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers3]
+;Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+;Text = PARTY_TEAMS_PLAYER3
+X = 335
+Y = 430
+W = 200
+SBGW = 150
+H = 40
+SkipX = 10
+Fields = 4
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = P3Light
+DColor = P3Dark
+TColor = White
+TDColor = White
+
+SBGColor = P3Light
+SBGDColor = P3Dark
+STColor = White
+STDColor = GrayDark
+
+
+
+[PartyPlayerTeam1Name]
+Tex = PartyTeamButton2
+X = 75
+Y = 160
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerTeam1NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 1
+Color = White
+
+[PartyPlayerPlayer1Name]
+Tex = Button
+X = 70
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerPlayer1NameText1]
+X = 65
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 1
+Color = White
+
+[PartyPlayerPlayer2Name]
+Tex = Button
+X = 225
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerPlayer2NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 2
+Color = White
+
+[PartyPlayerPlayer3Name]
+Tex = Button
+X = 380
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerPlayer3NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 3
+Color = White
+
+[PartyPlayerPlayer4Name]
+Tex = Button
+X = 535
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerPlayer4NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 4
+Color = White
+
+[PartyPlayerTeam2Name]
+Tex = PartyTeamButton2
+X = 75
+Y = 290
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerTeam2NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 2
+Color = White
+
+[PartyPlayerPlayer5Name]
+Tex = Button
+X = 70
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerPlayer5NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 5
+Color = White
+
+[PartyPlayerPlayer6Name]
+Tex = Button
+X = 225
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerPlayer6NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 6
+Color = White
+
+[PartyPlayerPlayer7Name]
+Tex = Button
+X = 380
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerPlayer7NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 7
+Color = White
+
+[PartyPlayerPlayer8Name]
+Tex = Button
+X = 535
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerPlayer8NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 8
+Color = White
+
+[PartyPlayerTeam3Name]
+Tex = PartyTeamButton2
+X = 75
+Y = 420
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerTeam3NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 3
+Color = White
+
+[PartyPlayerPlayer9Name]
+Tex = Button
+X = 70
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerPlayer9NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 9
+Color = White
+
+[PartyPlayerPlayer10Name]
+Tex = Button
+X = 225
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerPlayer10NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 10
+Color = White
+
+[PartyPlayerPlayer11Name]
+Tex = Button
+X = 380
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerPlayer11NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 11
+Color = White
+
+[PartyPlayerPlayer12Name]
+Tex = Button
+X = 535
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerPlayer12NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 12
+Color = White
+
+
+
+[PartyRoundsBackground]
+Tex = PartyBG
+
+[PartyRoundsStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyRoundsStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyRoundsStatic3]
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[PartyRoundsStatic4]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyRoundsStatic5]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyRoundsText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 1
+Size = 60
+Color = GrayLight
+Text = PARTY_MODE
+
+[PartyRoundsText2]
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_ROUNDS_DESC
+
+
+[PartyRoundsText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[PartyRoundsText4]
+X = 450
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = PARTY_ROUNDS_LEGEND_CONTINUE
+
+[PartyRoundsSelectRoundCount]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_ROUNDCOUNT
+X = 70
+Y = 100
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound1]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE1
+X = 70
+Y = 155
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound2]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE2
+X = 70
+Y = 210
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound3]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE3
+X = 70
+Y = 265
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound4]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE4
+X = 70
+Y = 320
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound5]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE5
+X = 70
+Y = 375
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound6]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE6
+X = 70
+Y = 430
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound7]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE7
+X = 70
+Y = 485
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+
+
+
+[SongMenu]
+
+[SongMenuBackground]
+Type=Fade
+;ColR=0
+;ColG=0
+;ColB=0
+Alpha=0.0
+Tex = SongBG
+
+[SongMenuStatic1]
+Tex = interface_dialog_background
+X = 528
+Y = 140
+W = 250
+H = 200
+Z = 0.96
+Color = White
+Type = Transparent
+
+
+[SongMenuStatic2]
+X = 536
+Y = 151
+W = 24
+H = 24
+Color = White
+Tex = icon_song_menu
+Type = Transparent
+Z = 0.97
+
+[SongMenuTextMenu]
+X = 566
+Y = 145
+Z = 0.97
+Color = Graydark
+Size = 36
+Text = MENU
+
+[SongMenuButton1]
+X = 548
+Y = 195
+Z = 0.97
+W = 210
+H = 25
+Tex = Rectangle
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+[SongMenuButton1Text1]
+X = 6
+Y = 0
+Z = 0.97
+Color = White
+Size = 24
+Text = SONG_MENU_PLAY
+
+[SongMenuButton2]
+X = 548
+Y = 225
+Z = 0.97
+W = 210
+H = 25
+Tex = Rectangle
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+[SongMenuButton2Text1]
+X = 6
+Y = 0
+Color = White
+Size = 24
+Text = SONG_MENU_EDIT
+Z = 0.97
+
+[SongMenuButton3]
+X = 548
+Y = 255
+Z = 0.97
+W = 210
+H = 25
+Tex = Rectangle
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+[SongMenuButton3Text1]
+X = 6
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_MODI
+Align = 0
+Z = 0.97
+
+# shows up instead of BUtton 3
+# in some song menus
+[SongMenuSelectSlide3]
+TexSBG = Rectangle
+Text = 
+TypeSBG = Transparent
+ShowArrows = 1
+OneItemOnly = 1
+X = 548
+Y = 235
+W = 0
+H = 25
+Z = 0.97
+SkipX = 0
+SBGW = 210
+TextSize = 24
+Color = ColorDark
+DColor = Gray
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = Gray
+STColor = White
+STDColor = GrayDark
+[SongMenuButton4]
+X = 548
+Y = 285
+Z = 0.97
+W = 210
+H = 25
+Tex = Rectangle
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
+[SongMenuButton4Text1]
+X = 6
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_CANCEL
+Align = 0
+Z = 0.97
+
+[SongJumpto]
+
+[SongJumptoBackground]
+Type=Fade
+;ColR=0
+;ColG=0
+;ColB=0
+Alpha=0.0
+
+[SongJumptoStatic1]
+Tex = interface_dialog_background
+X = 500
+Y = 340
+W = 280
+H = 160
+Z = 0.965
+Color = GrayLightest
+Type = Transparent
+
+[SongJumptoStatic2]
+X = 508
+Y = 348
+W = 24
+H = 24
+Color = White
+Tex = icon_song_search
+Type = Transparent
+Z = 0.97
+
+[SongJumptoText1]
+X = 538
+Y = 343
+Color = GrayDark
+Size = 36
+Text = SONG_JUMPTO_TYPE_DESC
+Z = 0.97
+
+#arrows over the select
+#TODO: remove, add this for all in code
+[SongJumptoStatic3]
+X = 510
+Y = 383
+W = 260
+H = 30
+Color = ColorLightest
+Tex = interface_selectbg_search
+Type = Colorized
+Z = 0.97
+
+[SongJumptoSelectSlideType]
+#Text = SONG_JUMPTO_TYPE_DESC
+X = 516
+Y = 383
+Z = 0.97
+H = 30
+SBGW = 150
+SkipX = 4
+
+Size = 36
+
+#text
+TColor = Black
+TDColor = Red
+#Select0r.Text.Color
+STColor = Black
+STDColor = Red
+
+[SongJumptoButtonSearchText]
+X = 526
+Y = 395
+Z = 0.97
+W = 160
+H = 50
+Size = 36
+Font = 1
+Align = 0
+Color = Black
+
+[SongJumptoTextFound]
+X = 539
+Y = 445
+Color = Black
+Font = 0
+Size = 24
+Text = SONG_JUMPTO_HELP
+Align = 0
+Z = 0.97
+
+
+[StatMain]
+Texts = 0
+Statics = 0
+
+[StatMainBackground]
+Tex = MainBG
+
+[StatMainButtonScores]
+X = 589
+Y = 100
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonScoresText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SCORES
+Color = White
+
+[StatMainButtonSingers]
+X = 589
+Y = 160
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonSingersText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SINGERS
+Color = White
+
+[StatMainButtonSongs]
+X = 589
+Y = 220
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonSongsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_SONGS
+Color = White
+
+[StatMainButtonBands]
+X = 589
+Y = 280
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonBandsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_BANDS
+Color = White
+
+[StatMainButtonExit]
+X = 589
+Y = 340
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatMainTextOverview]
+X = 45
+Y = 125
+W = 510
+Color = White
+Font = 0
+Size = 27
+Align = 0
+Text =
+
+[StatMainStatic1]
+X = 35
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[StatMainStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic4]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[StatMainStatic5]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[StatMainStatic6]
+X = 40
+Y = 100
+W = 520
+H = 20
+Tex = StatMainBG1
+Color = ColorDark
+Type = Transparent
+
+[StatMainStatic7]
+X = 40
+Y = 120
+W = 520
+H = 300
+Tex = StatMainBG2
+Color = ColorLight
+Type = Transparent
+
+[StatMainStatic8]
+X = 40
+Y = 420
+W = 520
+H = 20
+Tex = StatMainBG3
+Color = ColorDark
+Type = Transparent
+
+[StatMainText1]
+X = 40
+Y = 5
+Font = 1
+Size = 60
+Color = GrayLight
+Text = STAT_MAIN
+Align = 0
+
+
+[StatMainText2]
+X = 70
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = STAT_MAIN_DESC
+
+[StatMainText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+
+[StatMainText4]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+
+[StatDetail]
+Texts = 0
+Statics = 0
+
+[StatDetailBackground]
+Tex = MainBG
+
+[StatDetailButtonNext]
+X = 589
+Y = 100
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonNextText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_NEXT
+Color = White
+
+[StatDetailButtonPrev]
+X = 589
+Y = 160
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonPrevText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_PREV
+Color = White
+
+[StatDetailButtonReverse]
+X = 589
+Y = 220
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonReverseText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_REVERSE
+Color = White
+
+[StatDetailButtonExit]
+X = 589
+Y = 280
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatDetailTextDescription]
+X = 70
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[StatDetailTextPage]
+X = 546
+Y = 98
+Color = Black
+Font = 0
+Size = 15
+Align = 2
+Text =
+
+[StatDetailTextList1]
+X = 45
+Y = 122
+Color = White
+Font = 0
+Size = 21
+Text = Stat1
+
+[StatDetailTextList2]
+X = 45
+Y = 160
+Color = White
+Font = 0
+Size = 21
+Text = Stat2
+
+[StatDetailTextList3]
+X = 45
+Y = 198
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList4]
+X = 45
+Y = 236
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList5]
+X = 45
+Y = 274
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList6]
+X = 45
+Y = 312
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList7]
+X = 45
+Y = 350
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList8]
+X = 45
+Y = 388
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList9]
+X = 45
+Y = 426
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList10]
+X = 45
+Y = 464
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailStatic1]
+X = 35
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+
+[StatDetailStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic4]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[StatDetailStatic5]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[StatDetailStatic6]
+X = 40
+Y = 100
+W = 520
+H = 24
+Tex = StatDetailBG1
+Color = ColorDark
+Type = Transparent
+
+[StatDetailStatic7]
+X = 40
+Y = 124
+W = 520
+H = 376
+Tex = StatMainBG2
+Color = ColorLight
+Type = Transparent
+
+[StatDetailStatic8]
+X = 40
+Y = 500
+W = 520
+H = 20
+Tex = StatMainBG3
+Color = ColorDark
+Type = Transparent
+
+[StatDetailText1]
+X = 40
+Y = 5
+Color = GrayLight
+Font = 1
+Size = 60
+Text = STAT_DETAIL
+Align = 0
+
+[StatDetailText2]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+
+[StatDetailText3]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+
+[CheckPopup]
+
+[CheckPopupBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[CheckPopupStatic1]
+Tex = interface_dialog_background
+X = 200
+Y = 150
+W = 400
+H = 200
+Z = 1
+Color = White
+Type = Transparent
+
+[CheckPopupText1]
+X = 400
+Y = 160
+W = 400
+Color = Gray
+Font = 1
+Size = 35
+Text = MSG_QUESTION_TITLE
+Align = 1
+Z = 1
+
+[CheckPopupText]
+X = 400
+Y = 210
+W = 280
+Color = GrayDark
+Font = 0
+Size = 35
+Text = error text
+Align = 1
+Z = 1
+
+[CheckPopupButton1]
+X = 285
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = YES
+Align = 1
+Z = 1
+
+[CheckPopupButton2]
+X = 415
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton2Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = NO
+Align = 1
+Z = 1
+
+
+[ErrorPopup]
+
+[ErrorPopupBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[ErrorPopupStatic1]
+Tex = interface_dialog_background
+X = 200
+Y = 150
+W = 400
+H = 200
+Z = 1
+Color = White
+Type = Transparent
+
+[ErrorPopupText1]
+X = 400
+Y = 160
+W = 400
+Color = Gray
+Font = 1
+Size = 35
+Text = MSG_ERROR_TITLE
+Align = 1
+Z = 1
+
+[ErrorPopupText]
+X = 400
+Y = 210
+W = 280
+Color = GrayDark
+Font = 0
+Size = 35
+Text = error text
+Align = 1
+Z = 1
+
+[ErrorPopupButton1]
+X = 350
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Z = 1
+
+[ErrorPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = OK
+Align = 1
+Z = 1
+
+[PausePopUpStatic]
+Tex = Pause
+X = 0
+Y = 0
+W = 800
+H = 600
+Z = 0.95
+Color = White
+Type = Colorized
+
+[SingLyricsUpperBar]
+X = 80
+W = 640
+Y = 493
+H = 41
+;YOffSet (+/-) for the Sing-Indicator
+IndicatorYOffset = 3
+
+[SingLyricsLowerBar]
+X = 80
+W = 640
+Y = 535
+H = 41
\ No newline at end of file
diff --git a/songmanagement/game/themes/Classic/Star.ini b/songmanagement/game/themes/Classic/Star.ini
new file mode 100644
index 00000000..e72bdbec
--- /dev/null
+++ b/songmanagement/game/themes/Classic/Star.ini
@@ -0,0 +1,246 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Skin]
+Theme=Classic
+Name=Star
+Color=Blue
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+ButtonSolo       = [mainbutton]Solo.png
+ButtonMulti      = [mainbutton]Multi.png
+ButtonEditor     = [mainbutton]Solo.png
+ButtonStats      = [mainbutton]Stats.png
+ButtonOptions    = [mainbutton]Options.png
+ButtonExit       = [mainbutton]Exit.png
+Button           = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+
+usdx_logo        = [main]logo.png
+SongsBG		 = [songs]bg.png	
+SongFade 	 = [song]BGFade.jpg
+SongEqualizerBG  = [song]EqualizerBG.jpg
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+#Backgrounds
+LoadingBG      = [bg-main]star.jpg
+MainBG         = [bg-main]star.jpg
+SongBG         = [bg-main]star.jpg
+ScoreScreenBG  = [bg-main]star.jpg
+Top5BG         = [bg-main]star.jpg
+OptionsBG      = [bg-main]star.jpg
+EditBG         = [bg-main]star.jpg
+PartyBG        = [bg-main]star.jpg
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]star.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection = [song]selection.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+ButtonE    = [button]e.png
+
+;Leiste1     = [special]bar1.png
+:Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.jpg
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Classic/[bg-load]star.jpg b/songmanagement/game/themes/Classic/[bg-load]star.jpg
new file mode 100644
index 00000000..c94a7f9c
Binary files /dev/null and b/songmanagement/game/themes/Classic/[bg-load]star.jpg differ
diff --git a/songmanagement/game/themes/Classic/[bg-main]star.jpg b/songmanagement/game/themes/Classic/[bg-main]star.jpg
new file mode 100644
index 00000000..0cd0a9aa
Binary files /dev/null and b/songmanagement/game/themes/Classic/[bg-main]star.jpg differ
diff --git a/songmanagement/game/themes/Classic/[button]13.png b/songmanagement/game/themes/Classic/[button]13.png
new file mode 100644
index 00000000..9b1a8761
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]13.png differ
diff --git a/songmanagement/game/themes/Classic/[button]alt.png b/songmanagement/game/themes/Classic/[button]alt.png
new file mode 100644
index 00000000..6232f783
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]alt.png differ
diff --git a/songmanagement/game/themes/Classic/[button]az.png b/songmanagement/game/themes/Classic/[button]az.png
new file mode 100644
index 00000000..ffd356bd
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]az.png differ
diff --git a/songmanagement/game/themes/Classic/[button]e.png b/songmanagement/game/themes/Classic/[button]e.png
new file mode 100644
index 00000000..948d4911
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]e.png differ
diff --git a/songmanagement/game/themes/Classic/[button]enter.png b/songmanagement/game/themes/Classic/[button]enter.png
new file mode 100644
index 00000000..51e994e1
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]enter.png differ
diff --git a/songmanagement/game/themes/Classic/[button]esc.png b/songmanagement/game/themes/Classic/[button]esc.png
new file mode 100644
index 00000000..075e4e97
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]esc.png differ
diff --git a/songmanagement/game/themes/Classic/[button]j.png b/songmanagement/game/themes/Classic/[button]j.png
new file mode 100644
index 00000000..31010a41
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]j.png differ
diff --git a/songmanagement/game/themes/Classic/[button]m.png b/songmanagement/game/themes/Classic/[button]m.png
new file mode 100644
index 00000000..2cf5f02f
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]m.png differ
diff --git a/songmanagement/game/themes/Classic/[button]navi.png b/songmanagement/game/themes/Classic/[button]navi.png
new file mode 100644
index 00000000..1b479aaf
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]navi.png differ
diff --git a/songmanagement/game/themes/Classic/[button]p.png b/songmanagement/game/themes/Classic/[button]p.png
new file mode 100644
index 00000000..d12d04c5
Binary files /dev/null and b/songmanagement/game/themes/Classic/[button]p.png differ
diff --git a/songmanagement/game/themes/Classic/[effect]goldenNoteStar.png b/songmanagement/game/themes/Classic/[effect]goldenNoteStar.png
new file mode 100644
index 00000000..7bd6225f
Binary files /dev/null and b/songmanagement/game/themes/Classic/[effect]goldenNoteStar.png differ
diff --git a/songmanagement/game/themes/Classic/[effect]perfectNoteStar.png b/songmanagement/game/themes/Classic/[effect]perfectNoteStar.png
new file mode 100644
index 00000000..99132c39
Binary files /dev/null and b/songmanagement/game/themes/Classic/[effect]perfectNoteStar.png differ
diff --git a/songmanagement/game/themes/Classic/[helper]buttonFade.png b/songmanagement/game/themes/Classic/[helper]buttonFade.png
new file mode 100644
index 00000000..27a94c44
Binary files /dev/null and b/songmanagement/game/themes/Classic/[helper]buttonFade.png differ
diff --git a/songmanagement/game/themes/Classic/[helper]rectangle.jpg b/songmanagement/game/themes/Classic/[helper]rectangle.jpg
new file mode 100644
index 00000000..9b4ba0f9
Binary files /dev/null and b/songmanagement/game/themes/Classic/[helper]rectangle.jpg differ
diff --git a/songmanagement/game/themes/Classic/[icon]Star.png b/songmanagement/game/themes/Classic/[icon]Star.png
new file mode 100644
index 00000000..409e9599
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]Star.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]cd.png b/songmanagement/game/themes/Classic/[icon]cd.png
new file mode 100644
index 00000000..2633d235
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]cd.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]error.png b/songmanagement/game/themes/Classic/[icon]error.png
new file mode 100644
index 00000000..f952f3fa
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]error.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]main.png b/songmanagement/game/themes/Classic/[icon]main.png
new file mode 100644
index 00000000..f7d50067
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]main.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]options.png b/songmanagement/game/themes/Classic/[icon]options.png
new file mode 100644
index 00000000..9fac0bfd
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]options.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]party.png b/songmanagement/game/themes/Classic/[icon]party.png
new file mode 100644
index 00000000..e23230e3
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]party.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]question.png b/songmanagement/game/themes/Classic/[icon]question.png
new file mode 100644
index 00000000..a72a5c43
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]question.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]score.png b/songmanagement/game/themes/Classic/[icon]score.png
new file mode 100644
index 00000000..ccc3d8ff
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]score.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]song_menu.png b/songmanagement/game/themes/Classic/[icon]song_menu.png
new file mode 100644
index 00000000..acf69bfb
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]song_menu.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]song_search.png b/songmanagement/game/themes/Classic/[icon]song_search.png
new file mode 100644
index 00000000..f5190315
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]song_search.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]song_video.png b/songmanagement/game/themes/Classic/[icon]song_video.png
new file mode 100644
index 00000000..4a679249
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]song_video.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]stats.png b/songmanagement/game/themes/Classic/[icon]stats.png
new file mode 100644
index 00000000..d8e5eac1
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]stats.png differ
diff --git a/songmanagement/game/themes/Classic/[icon]video.png b/songmanagement/game/themes/Classic/[icon]video.png
new file mode 100644
index 00000000..9bd65f86
Binary files /dev/null and b/songmanagement/game/themes/Classic/[icon]video.png differ
diff --git a/songmanagement/game/themes/Classic/[interface]cursor.png b/songmanagement/game/themes/Classic/[interface]cursor.png
new file mode 100644
index 00000000..0fe390f0
Binary files /dev/null and b/songmanagement/game/themes/Classic/[interface]cursor.png differ
diff --git a/songmanagement/game/themes/Classic/[interface]cursor_pressed.png b/songmanagement/game/themes/Classic/[interface]cursor_pressed.png
new file mode 100644
index 00000000..fa0056cc
Binary files /dev/null and b/songmanagement/game/themes/Classic/[interface]cursor_pressed.png differ
diff --git a/songmanagement/game/themes/Classic/[interface]dialog_background.png b/songmanagement/game/themes/Classic/[interface]dialog_background.png
new file mode 100644
index 00000000..3113cd30
Binary files /dev/null and b/songmanagement/game/themes/Classic/[interface]dialog_background.png differ
diff --git a/songmanagement/game/themes/Classic/[interface]select_arrow_left.png b/songmanagement/game/themes/Classic/[interface]select_arrow_left.png
new file mode 100644
index 00000000..e4a32d2d
Binary files /dev/null and b/songmanagement/game/themes/Classic/[interface]select_arrow_left.png differ
diff --git a/songmanagement/game/themes/Classic/[interface]select_arrow_right.png b/songmanagement/game/themes/Classic/[interface]select_arrow_right.png
new file mode 100644
index 00000000..b2a29793
Binary files /dev/null and b/songmanagement/game/themes/Classic/[interface]select_arrow_right.png differ
diff --git a/songmanagement/game/themes/Classic/[interface]selectbg_search.png b/songmanagement/game/themes/Classic/[interface]selectbg_search.png
new file mode 100644
index 00000000..57d0ca88
Binary files /dev/null and b/songmanagement/game/themes/Classic/[interface]selectbg_search.png differ
diff --git a/songmanagement/game/themes/Classic/[main]button.png b/songmanagement/game/themes/Classic/[main]button.png
new file mode 100644
index 00000000..978e04df
Binary files /dev/null and b/songmanagement/game/themes/Classic/[main]button.png differ
diff --git a/songmanagement/game/themes/Classic/[main]buttonf.jpg b/songmanagement/game/themes/Classic/[main]buttonf.jpg
new file mode 100644
index 00000000..d844add5
Binary files /dev/null and b/songmanagement/game/themes/Classic/[main]buttonf.jpg differ
diff --git a/songmanagement/game/themes/Classic/[main]logo.png b/songmanagement/game/themes/Classic/[main]logo.png
new file mode 100644
index 00000000..9b559de9
Binary files /dev/null and b/songmanagement/game/themes/Classic/[main]logo.png differ
diff --git a/songmanagement/game/themes/Classic/[main]mainBar.png b/songmanagement/game/themes/Classic/[main]mainBar.png
new file mode 100644
index 00000000..60063e63
Binary files /dev/null and b/songmanagement/game/themes/Classic/[main]mainBar.png differ
diff --git a/songmanagement/game/themes/Classic/[main]playerNumberBox.png b/songmanagement/game/themes/Classic/[main]playerNumberBox.png
new file mode 100644
index 00000000..3336ef56
Binary files /dev/null and b/songmanagement/game/themes/Classic/[main]playerNumberBox.png differ
diff --git a/songmanagement/game/themes/Classic/[main]selectbg.png b/songmanagement/game/themes/Classic/[main]selectbg.png
new file mode 100644
index 00000000..9917045d
Binary files /dev/null and b/songmanagement/game/themes/Classic/[main]selectbg.png differ
diff --git a/songmanagement/game/themes/Classic/[main]songCover.jpg b/songmanagement/game/themes/Classic/[main]songCover.jpg
new file mode 100644
index 00000000..7cf8930b
Binary files /dev/null and b/songmanagement/game/themes/Classic/[main]songCover.jpg differ
diff --git a/songmanagement/game/themes/Classic/[mainbutton]Exit.png b/songmanagement/game/themes/Classic/[mainbutton]Exit.png
new file mode 100644
index 00000000..bfd79f1e
Binary files /dev/null and b/songmanagement/game/themes/Classic/[mainbutton]Exit.png differ
diff --git a/songmanagement/game/themes/Classic/[mainbutton]Multi.png b/songmanagement/game/themes/Classic/[mainbutton]Multi.png
new file mode 100644
index 00000000..caea5c2b
Binary files /dev/null and b/songmanagement/game/themes/Classic/[mainbutton]Multi.png differ
diff --git a/songmanagement/game/themes/Classic/[mainbutton]Options.png b/songmanagement/game/themes/Classic/[mainbutton]Options.png
new file mode 100644
index 00000000..940e37a5
Binary files /dev/null and b/songmanagement/game/themes/Classic/[mainbutton]Options.png differ
diff --git a/songmanagement/game/themes/Classic/[mainbutton]Solo.png b/songmanagement/game/themes/Classic/[mainbutton]Solo.png
new file mode 100644
index 00000000..9f205872
Binary files /dev/null and b/songmanagement/game/themes/Classic/[mainbutton]Solo.png differ
diff --git a/songmanagement/game/themes/Classic/[mainbutton]Stats.png b/songmanagement/game/themes/Classic/[mainbutton]Stats.png
new file mode 100644
index 00000000..588c2ce6
Binary files /dev/null and b/songmanagement/game/themes/Classic/[mainbutton]Stats.png differ
diff --git a/songmanagement/game/themes/Classic/[menu]PopUpFg.png b/songmanagement/game/themes/Classic/[menu]PopUpFg.png
new file mode 100644
index 00000000..2c9785b4
Binary files /dev/null and b/songmanagement/game/themes/Classic/[menu]PopUpFg.png differ
diff --git a/songmanagement/game/themes/Classic/[menu]jumpToBg.png b/songmanagement/game/themes/Classic/[menu]jumpToBg.png
new file mode 100644
index 00000000..8e3a3a00
Binary files /dev/null and b/songmanagement/game/themes/Classic/[menu]jumpToBg.png differ
diff --git a/songmanagement/game/themes/Classic/[menu]songMenuBg.png b/songmanagement/game/themes/Classic/[menu]songMenuBg.png
new file mode 100644
index 00000000..92beff8e
Binary files /dev/null and b/songmanagement/game/themes/Classic/[menu]songMenuBg.png differ
diff --git a/songmanagement/game/themes/Classic/[menu]songMenuSelectBg.png b/songmanagement/game/themes/Classic/[menu]songMenuSelectBg.png
new file mode 100644
index 00000000..8ff5eef8
Binary files /dev/null and b/songmanagement/game/themes/Classic/[menu]songMenuSelectBg.png differ
diff --git a/songmanagement/game/themes/Classic/[party]Joker.png b/songmanagement/game/themes/Classic/[party]Joker.png
new file mode 100644
index 00000000..ba667a9b
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]Joker.png differ
diff --git a/songmanagement/game/themes/Classic/[party]playerButton.png b/songmanagement/game/themes/Classic/[party]playerButton.png
new file mode 100644
index 00000000..7232b25c
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]playerButton.png differ
diff --git a/songmanagement/game/themes/Classic/[party]playerTeamButton.png b/songmanagement/game/themes/Classic/[party]playerTeamButton.png
new file mode 100644
index 00000000..71aa736a
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]playerTeamButton.png differ
diff --git a/songmanagement/game/themes/Classic/[party]playerselectbg.png b/songmanagement/game/themes/Classic/[party]playerselectbg.png
new file mode 100644
index 00000000..daf44ace
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]playerselectbg.png differ
diff --git a/songmanagement/game/themes/Classic/[party]pointer.png b/songmanagement/game/themes/Classic/[party]pointer.png
new file mode 100644
index 00000000..2292d6c1
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]pointer.png differ
diff --git a/songmanagement/game/themes/Classic/[party]roundBG1.png b/songmanagement/game/themes/Classic/[party]roundBG1.png
new file mode 100644
index 00000000..5f40c7f5
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]roundBG1.png differ
diff --git a/songmanagement/game/themes/Classic/[party]roundBG2.png b/songmanagement/game/themes/Classic/[party]roundBG2.png
new file mode 100644
index 00000000..02afa063
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]roundBG2.png differ
diff --git a/songmanagement/game/themes/Classic/[party]roundBG3.png b/songmanagement/game/themes/Classic/[party]roundBG3.png
new file mode 100644
index 00000000..8c18cf73
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]roundBG3.png differ
diff --git a/songmanagement/game/themes/Classic/[party]roundBG4.png b/songmanagement/game/themes/Classic/[party]roundBG4.png
new file mode 100644
index 00000000..94a5caa7
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]roundBG4.png differ
diff --git a/songmanagement/game/themes/Classic/[party]roundTeamButton.png b/songmanagement/game/themes/Classic/[party]roundTeamButton.png
new file mode 100644
index 00000000..08c645b1
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]roundTeamButton.png differ
diff --git a/songmanagement/game/themes/Classic/[party]scoreBG1.png b/songmanagement/game/themes/Classic/[party]scoreBG1.png
new file mode 100644
index 00000000..53e68562
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]scoreBG1.png differ
diff --git a/songmanagement/game/themes/Classic/[party]scoreBG2.png b/songmanagement/game/themes/Classic/[party]scoreBG2.png
new file mode 100644
index 00000000..9b4bb52d
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]scoreBG2.png differ
diff --git a/songmanagement/game/themes/Classic/[party]scoreDecoration.png b/songmanagement/game/themes/Classic/[party]scoreDecoration.png
new file mode 100644
index 00000000..388077e6
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]scoreDecoration.png differ
diff --git a/songmanagement/game/themes/Classic/[party]teamPoints.png b/songmanagement/game/themes/Classic/[party]teamPoints.png
new file mode 100644
index 00000000..e7c3b3cc
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]teamPoints.png differ
diff --git a/songmanagement/game/themes/Classic/[party]winDecoration.png b/songmanagement/game/themes/Classic/[party]winDecoration.png
new file mode 100644
index 00000000..f84dbc8a
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]winDecoration.png differ
diff --git a/songmanagement/game/themes/Classic/[party]winTeamButton1.png b/songmanagement/game/themes/Classic/[party]winTeamButton1.png
new file mode 100644
index 00000000..a3e20695
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]winTeamButton1.png differ
diff --git a/songmanagement/game/themes/Classic/[party]winTeamButton2.png b/songmanagement/game/themes/Classic/[party]winTeamButton2.png
new file mode 100644
index 00000000..78237c12
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]winTeamButton2.png differ
diff --git a/songmanagement/game/themes/Classic/[party]winTeamButton3.png b/songmanagement/game/themes/Classic/[party]winTeamButton3.png
new file mode 100644
index 00000000..0d0d2788
Binary files /dev/null and b/songmanagement/game/themes/Classic/[party]winTeamButton3.png differ
diff --git a/songmanagement/game/themes/Classic/[score]Line.png b/songmanagement/game/themes/Classic/[score]Line.png
new file mode 100644
index 00000000..954caf94
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]Line.png differ
diff --git a/songmanagement/game/themes/Classic/[score]bar_box_dark.png b/songmanagement/game/themes/Classic/[score]bar_box_dark.png
new file mode 100644
index 00000000..e4fbfa41
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]bar_box_dark.png differ
diff --git a/songmanagement/game/themes/Classic/[score]bar_box_light.png b/songmanagement/game/themes/Classic/[score]bar_box_light.png
new file mode 100644
index 00000000..ddc17ed8
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]bar_box_light.png differ
diff --git a/songmanagement/game/themes/Classic/[score]bar_box_lightest.png b/songmanagement/game/themes/Classic/[score]bar_box_lightest.png
new file mode 100644
index 00000000..995bb9ef
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]bar_box_lightest.png differ
diff --git a/songmanagement/game/themes/Classic/[score]box.png b/songmanagement/game/themes/Classic/[score]box.png
new file mode 100644
index 00000000..71a0cee6
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]box.png differ
diff --git a/songmanagement/game/themes/Classic/[score]endcap.png b/songmanagement/game/themes/Classic/[score]endcap.png
new file mode 100644
index 00000000..3cccd2e1
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]endcap.png differ
diff --git a/songmanagement/game/themes/Classic/[score]glass_box.png b/songmanagement/game/themes/Classic/[score]glass_box.png
new file mode 100644
index 00000000..c0cf2a9c
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]glass_box.png differ
diff --git a/songmanagement/game/themes/Classic/[score]level.png b/songmanagement/game/themes/Classic/[score]level.png
new file mode 100644
index 00000000..1f627560
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]level.png differ
diff --git a/songmanagement/game/themes/Classic/[score]levelRound.png b/songmanagement/game/themes/Classic/[score]levelRound.png
new file mode 100644
index 00000000..2bc7a6b8
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]levelRound.png differ
diff --git a/songmanagement/game/themes/Classic/[score]level_dark.png b/songmanagement/game/themes/Classic/[score]level_dark.png
new file mode 100644
index 00000000..da4fd407
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]level_dark.png differ
diff --git a/songmanagement/game/themes/Classic/[score]level_dark_round.png b/songmanagement/game/themes/Classic/[score]level_dark_round.png
new file mode 100644
index 00000000..de239cb2
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]level_dark_round.png differ
diff --git a/songmanagement/game/themes/Classic/[score]level_light.png b/songmanagement/game/themes/Classic/[score]level_light.png
new file mode 100644
index 00000000..1c1c8a4d
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]level_light.png differ
diff --git a/songmanagement/game/themes/Classic/[score]level_light_round.png b/songmanagement/game/themes/Classic/[score]level_light_round.png
new file mode 100644
index 00000000..641151a5
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]level_light_round.png differ
diff --git a/songmanagement/game/themes/Classic/[score]level_lightest.png b/songmanagement/game/themes/Classic/[score]level_lightest.png
new file mode 100644
index 00000000..f02fdf7b
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]level_lightest.png differ
diff --git a/songmanagement/game/themes/Classic/[score]level_lightest_round.png b/songmanagement/game/themes/Classic/[score]level_lightest_round.png
new file mode 100644
index 00000000..9f1bb09e
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]level_lightest_round.png differ
diff --git a/songmanagement/game/themes/Classic/[score]rating_0.png b/songmanagement/game/themes/Classic/[score]rating_0.png
new file mode 100644
index 00000000..7e836b99
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]rating_0.png differ
diff --git a/songmanagement/game/themes/Classic/[score]rating_1.png b/songmanagement/game/themes/Classic/[score]rating_1.png
new file mode 100644
index 00000000..556821cb
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]rating_1.png differ
diff --git a/songmanagement/game/themes/Classic/[score]rating_2.png b/songmanagement/game/themes/Classic/[score]rating_2.png
new file mode 100644
index 00000000..ffa23fd3
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]rating_2.png differ
diff --git a/songmanagement/game/themes/Classic/[score]rating_3.png b/songmanagement/game/themes/Classic/[score]rating_3.png
new file mode 100644
index 00000000..5204dc5f
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]rating_3.png differ
diff --git a/songmanagement/game/themes/Classic/[score]rating_4.png b/songmanagement/game/themes/Classic/[score]rating_4.png
new file mode 100644
index 00000000..f5d7267c
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]rating_4.png differ
diff --git a/songmanagement/game/themes/Classic/[score]rating_5.png b/songmanagement/game/themes/Classic/[score]rating_5.png
new file mode 100644
index 00000000..0f6a553b
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]rating_5.png differ
diff --git a/songmanagement/game/themes/Classic/[score]rating_6.png b/songmanagement/game/themes/Classic/[score]rating_6.png
new file mode 100644
index 00000000..e8127c85
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]rating_6.png differ
diff --git a/songmanagement/game/themes/Classic/[score]rating_7.png b/songmanagement/game/themes/Classic/[score]rating_7.png
new file mode 100644
index 00000000..6b1d30f5
Binary files /dev/null and b/songmanagement/game/themes/Classic/[score]rating_7.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player1]lyric_active.png b/songmanagement/game/themes/Classic/[sing.player1]lyric_active.png
new file mode 100644
index 00000000..089c8c5e
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player1]lyric_active.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player1]lyric_inactive.png b/songmanagement/game/themes/Classic/[sing.player1]lyric_inactive.png
new file mode 100644
index 00000000..a349007d
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player1]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player2]lyric_active.png b/songmanagement/game/themes/Classic/[sing.player2]lyric_active.png
new file mode 100644
index 00000000..509767fa
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player2]lyric_active.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player2]lyric_inactive.png b/songmanagement/game/themes/Classic/[sing.player2]lyric_inactive.png
new file mode 100644
index 00000000..ac40ec61
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player2]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player3]lyric_active.png b/songmanagement/game/themes/Classic/[sing.player3]lyric_active.png
new file mode 100644
index 00000000..7b130ac5
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player3]lyric_active.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player3]lyric_inactive.png b/songmanagement/game/themes/Classic/[sing.player3]lyric_inactive.png
new file mode 100644
index 00000000..c5a00600
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player3]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player4]lyric_active.png b/songmanagement/game/themes/Classic/[sing.player4]lyric_active.png
new file mode 100644
index 00000000..993041fd
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player4]lyric_active.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player4]lyric_inactive.png b/songmanagement/game/themes/Classic/[sing.player4]lyric_inactive.png
new file mode 100644
index 00000000..f09669b2
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player4]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player5]lyric_active.png b/songmanagement/game/themes/Classic/[sing.player5]lyric_active.png
new file mode 100644
index 00000000..631dc9c3
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player5]lyric_active.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player5]lyric_inactive.png b/songmanagement/game/themes/Classic/[sing.player5]lyric_inactive.png
new file mode 100644
index 00000000..716071e8
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player5]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player6]lyric_active.png b/songmanagement/game/themes/Classic/[sing.player6]lyric_active.png
new file mode 100644
index 00000000..65133d03
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player6]lyric_active.png differ
diff --git a/songmanagement/game/themes/Classic/[sing.player6]lyric_inactive.png b/songmanagement/game/themes/Classic/[sing.player6]lyric_inactive.png
new file mode 100644
index 00000000..0c5f34d3
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing.player6]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]LyricsBall.png b/songmanagement/game/themes/Classic/[sing]LyricsBall.png
new file mode 100644
index 00000000..aa4401dd
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]LyricsBall.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]lineBonusPopUp.png b/songmanagement/game/themes/Classic/[sing]lineBonusPopUp.png
new file mode 100644
index 00000000..89d5e511
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]lineBonusPopUp.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]lyricsHelpBar.png b/songmanagement/game/themes/Classic/[sing]lyricsHelpBar.png
new file mode 100644
index 00000000..59707c21
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]lyricsHelpBar.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]notesBgLeft.png b/songmanagement/game/themes/Classic/[sing]notesBgLeft.png
new file mode 100644
index 00000000..9fe2621c
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]notesBgLeft.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]notesBgMid.png b/songmanagement/game/themes/Classic/[sing]notesBgMid.png
new file mode 100644
index 00000000..612da5d3
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]notesBgMid.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]notesBgRight.png b/songmanagement/game/themes/Classic/[sing]notesBgRight.png
new file mode 100644
index 00000000..a6f42c33
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]notesBgRight.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]notesLeft.png b/songmanagement/game/themes/Classic/[sing]notesLeft.png
new file mode 100644
index 00000000..3a404b9c
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]notesLeft.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]notesMid.png b/songmanagement/game/themes/Classic/[sing]notesMid.png
new file mode 100644
index 00000000..8769d01a
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]notesMid.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]notesPlainLeft.png b/songmanagement/game/themes/Classic/[sing]notesPlainLeft.png
new file mode 100644
index 00000000..1a94a9d8
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]notesPlainLeft.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]notesPlainMid.png b/songmanagement/game/themes/Classic/[sing]notesPlainMid.png
new file mode 100644
index 00000000..7fc64282
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]notesPlainMid.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]notesPlainRight.png b/songmanagement/game/themes/Classic/[sing]notesPlainRight.png
new file mode 100644
index 00000000..ff8bb502
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]notesPlainRight.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]notesRight.png b/songmanagement/game/themes/Classic/[sing]notesRight.png
new file mode 100644
index 00000000..8dc40cc8
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]notesRight.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]p.png b/songmanagement/game/themes/Classic/[sing]p.png
new file mode 100644
index 00000000..345c8959
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]p.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]pause.png b/songmanagement/game/themes/Classic/[sing]pause.png
new file mode 100644
index 00000000..f5ab158c
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]pause.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]scoreBg.jpg b/songmanagement/game/themes/Classic/[sing]scoreBg.jpg
new file mode 100644
index 00000000..26ea1e87
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]scoreBg.jpg differ
diff --git a/songmanagement/game/themes/Classic/[sing]scoreBg.png b/songmanagement/game/themes/Classic/[sing]scoreBg.png
new file mode 100644
index 00000000..4dc785e9
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]scoreBg.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]singBarBack.png b/songmanagement/game/themes/Classic/[sing]singBarBack.png
new file mode 100644
index 00000000..14d2ba42
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]singBarBack.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]singBarBar.jpg b/songmanagement/game/themes/Classic/[sing]singBarBar.jpg
new file mode 100644
index 00000000..4fd9bde9
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]singBarBar.jpg differ
diff --git a/songmanagement/game/themes/Classic/[sing]singBarBar.png b/songmanagement/game/themes/Classic/[sing]singBarBar.png
new file mode 100644
index 00000000..9c57057b
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]singBarBar.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]singBarFront.png b/songmanagement/game/themes/Classic/[sing]singBarFront.png
new file mode 100644
index 00000000..42477c5a
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]singBarFront.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]textBar.png b/songmanagement/game/themes/Classic/[sing]textBar.png
new file mode 100644
index 00000000..d2069235
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]textBar.png differ
diff --git a/songmanagement/game/themes/Classic/[sing]timeBar.jpg b/songmanagement/game/themes/Classic/[sing]timeBar.jpg
new file mode 100644
index 00000000..cc5cb552
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]timeBar.jpg differ
diff --git a/songmanagement/game/themes/Classic/[sing]timeBarBG.png b/songmanagement/game/themes/Classic/[sing]timeBarBG.png
new file mode 100644
index 00000000..6094fdf3
Binary files /dev/null and b/songmanagement/game/themes/Classic/[sing]timeBarBG.png differ
diff --git a/songmanagement/game/themes/Classic/[song]BGFade.jpg b/songmanagement/game/themes/Classic/[song]BGFade.jpg
new file mode 100644
index 00000000..1d6b80ff
Binary files /dev/null and b/songmanagement/game/themes/Classic/[song]BGFade.jpg differ
diff --git a/songmanagement/game/themes/Classic/[song]EqualizerBG.jpg b/songmanagement/game/themes/Classic/[song]EqualizerBG.jpg
new file mode 100644
index 00000000..54ff27f2
Binary files /dev/null and b/songmanagement/game/themes/Classic/[song]EqualizerBG.jpg differ
diff --git a/songmanagement/game/themes/Classic/[song]selection.png b/songmanagement/game/themes/Classic/[song]selection.png
new file mode 100644
index 00000000..70022ca0
Binary files /dev/null and b/songmanagement/game/themes/Classic/[song]selection.png differ
diff --git a/songmanagement/game/themes/Classic/[songs]bg.png b/songmanagement/game/themes/Classic/[songs]bg.png
new file mode 100644
index 00000000..0ff36589
Binary files /dev/null and b/songmanagement/game/themes/Classic/[songs]bg.png differ
diff --git a/songmanagement/game/themes/Classic/[special]bar1.png b/songmanagement/game/themes/Classic/[special]bar1.png
new file mode 100644
index 00000000..00afb41d
Binary files /dev/null and b/songmanagement/game/themes/Classic/[special]bar1.png differ
diff --git a/songmanagement/game/themes/Classic/[special]bar2.png b/songmanagement/game/themes/Classic/[special]bar2.png
new file mode 100644
index 00000000..c828a8e1
Binary files /dev/null and b/songmanagement/game/themes/Classic/[special]bar2.png differ
diff --git a/songmanagement/game/themes/Classic/[special]bg_fade.png b/songmanagement/game/themes/Classic/[special]bg_fade.png
new file mode 100644
index 00000000..dc3248ef
Binary files /dev/null and b/songmanagement/game/themes/Classic/[special]bg_fade.png differ
diff --git a/songmanagement/game/themes/Classic/[stat]detailBG1.png b/songmanagement/game/themes/Classic/[stat]detailBG1.png
new file mode 100644
index 00000000..212baf74
Binary files /dev/null and b/songmanagement/game/themes/Classic/[stat]detailBG1.png differ
diff --git a/songmanagement/game/themes/Classic/[stat]mainBG1.png b/songmanagement/game/themes/Classic/[stat]mainBG1.png
new file mode 100644
index 00000000..9eadc579
Binary files /dev/null and b/songmanagement/game/themes/Classic/[stat]mainBG1.png differ
diff --git a/songmanagement/game/themes/Classic/[stat]mainBG2.png b/songmanagement/game/themes/Classic/[stat]mainBG2.png
new file mode 100644
index 00000000..f883c7d5
Binary files /dev/null and b/songmanagement/game/themes/Classic/[stat]mainBG2.png differ
diff --git a/songmanagement/game/themes/Classic/[stat]mainBG3.png b/songmanagement/game/themes/Classic/[stat]mainBG3.png
new file mode 100644
index 00000000..d5bcd98e
Binary files /dev/null and b/songmanagement/game/themes/Classic/[stat]mainBG3.png differ
diff --git a/songmanagement/game/themes/Deluxe.ini b/songmanagement/game/themes/Deluxe.ini
new file mode 100644
index 00000000..30a1a198
--- /dev/null
+++ b/songmanagement/game/themes/Deluxe.ini
@@ -0,0 +1,8681 @@
+;1.10
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Theme]
+Name = Deluxe
+Creator = Ultrastar Deluxe Team
+US_Version = USD 110
+DefaultSkin = Blue
+
+[Colors]
+White = 255 255 255
+LightBlue = 119 187 210
+DarkBlue = 28 126 171
+LightRed = 170 146 146
+DarkRed = 155 113 113
+LightGreen = 136 168 136
+DarkGreen = 106 152 104
+LightPurple = 155 136 168
+DarkPurple = 145 104 152
+LightOrange = 168 155 136
+DarkOrange = 151 131 76
+LightYellow = 168 168 136
+DarkYellow = 150 151 76
+Turkis = 13 186 167
+GrayLightest = 223 223 223
+GrayLight = 191 191 191
+Gray = 127 127 127
+GrayDark = 63 63 63
+Black = 0 0 0
+GrayPopup = 51 51 51
+Gold = 255 223 31
+Silver = 223 223 223
+Bronze = 205 127 50
+Red = 255 0 0
+
+[Loading]
+[LoadingBackground]
+Tex = LoadingBG
+Color = DarkRed
+Type = Colorized
+
+[LoadingStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[LoadingStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Z = 0.4
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LoadingText1]
+X = 30
+Y = 548
+Color = White
+Font = 0
+Align = 0
+Size = 24
+Text = SING_LOADING
+Reflection = 1
+ReflectionSpacing = 13
+
+[LoadingText2]
+X = 790
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = US_VERSION
+Reflection = 1
+ReflectionSpacing = 13
+
+[Main]
+[MainBackground]
+Tex = MainBG
+
+[MainStatic1]
+X = 65
+Y = 205
+W = 25
+H = 23
+Tex = MainIcon
+Color = White
+Type = Transparent
+
+[MainText1]
+X = 95
+Y = 186
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_MENU
+
+[MainTextDescriptionLong]
+X = 95
+Y = 233
+Color = ColorLightest
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[MainStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Z = 0.4
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Z = 0.5
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainText2]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[MainStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Z = 0.5
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainText3]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_SELECT
+Reflection = 1
+ReflectionSpacing = 13
+
+[MainButtonSolo]
+X = 95
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[MainButtonSoloText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_SING
+Color = White
+
+[MainButtonMulti]
+X = 250
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[MainButtonMultiText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_MULTI
+Color = White
+
+[MainButtonCollection1]
+X = 405
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 0
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+FirstChild = 3
+
+[MainButtonCollection1Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_TOOLS
+Color = White
+
+[MainButtonStats]
+X = 410
+Y = 310
+W = 140
+H = 30
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+Parent = 1
+
+[MainButtonStatsText1]
+X = 70
+Y = 3
+Font = 0
+Size = 24
+Align = 1
+Text = SING_STATS
+Color = White
+
+[MainButtonEditor]
+X = 410
+Y = 345
+W = 140
+H = 30
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+Parent = 1
+
+[MainButtonEditorText1]
+X = 70
+Y = 3
+Font = 0
+Size = 24
+Align = 1
+Text = SING_EDITOR
+Color = White
+
+[MainButtonOptions]
+X = 410
+Y = 380
+W = 140
+H = 30
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+Parent = 1
+
+[MainButtonOptionsText1]
+X = 70
+Y = 3
+Font = 0
+Size = 24
+Align = 1
+Text = SING_OPTIONS
+Color = White
+
+[MainButtonExit]
+X = 560
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[MainButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EXIT
+Color = White
+
+[Song]
+
+[SongBackground]
+Tex = SongBG
+
+[SongStaticNonParty1]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = SongCD
+Type = Colorized
+
+[SongTextCat]
+X = 72
+Y = 58
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = SING_SONG_SELECTION_DESC
+
+[SongStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Z = 0.951
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongCover]
+X = 300
+Y = 120
+W = 325
+H = 200
+Reflections = 1
+Style=5
+
+[SongEqualizer]
+Visible = 1
+Direction = 1
+Color = White
+Alpha = 1
+X = 265
+Y = 476
+PieceW = 4
+PieceH = 4
+Space = 1
+Bands = 5
+Length = 15
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongVideoIcon]
+X = 310
+Y = 445
+W = 24
+H = 24
+Z = 0.95
+Color = White
+Tex = icon_song_video
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 22
+
+[SongStatic3]
+X = 278
+Y = 120
+W = 244
+H = 200
+Z = 0.95
+Color = ColorLight
+Tex = SongSelection1
+Type = Colorized
+
+[SongStatic4]
+X = 300
+Y = 320
+W = 200
+H = 160
+Z = 0.95
+Color = ColorLight
+Tex = SongSelection2
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextArtist]
+X = 400
+Y = 328
+W = 190
+Color = White
+Font = 1
+Size = 24
+Align = 1
+Text =
+
+[SongTextTitle]
+X = 400
+Y = 394
+W = 190
+Color = White
+Font = 0
+Size = 24
+Align = 1
+Text =
+
+[SongTextNumber]
+X = 492
+Y = 457
+Z = 0.95
+Color = White
+Size = 18
+Align = 2
+Reflection = 1
+ReflectionSpacing = 21
+
+#Variable statics and texts for song-screen in sing- and partymode
+# There can be an unlimited Number of Statics and Texts, As long
+# as the numbers are in order.
+# Statics that are shown in PartyMode Only are Named_
+#        SongStaticParty[No]
+# Texts that are shown in PartyMode Only are Named_
+#        SongTextParty[No]
+# Statics that are shown in Normal Mode Only are Named_
+#        SongStaticNonParty[No]
+# Texts that are shown in Normal Mode Only are Named_
+#        SongTextNonParty[No]
+#Here are the ones for singmode
+
+[SongTextNonParty1]
+X = 70
+Y = 6
+Color = White
+Font = 0
+Size = 60
+Text = SING_SONG_SELECTION
+Align = 0
+
+# NAVBAR #########################
+# Jump to a letter with [ALT] + [A..Z]
+[SongStaticNonParty2]
+X = 260
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAlt
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty2]
+X = 292
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = +
+Reflection = 1
+ReflectionSpacing = 13
+
+[SongStaticNonParty3]
+X = 300
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty3]
+X = 340
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_GOTO
+Reflection = 1
+ReflectionSpacing = 13
+
+# Menu opens with [M]
+[SongStaticNonParty4]
+X = 425
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonM
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty4]
+X = 465
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_MENU
+Reflection = 1
+ReflectionSpacing = 13
+
+# The so famous search, shown with [J]
+[SongStaticNonParty5]
+X = 515
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonJ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty5]
+X = 555
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SONG_JUMPTO_DESC
+Reflection = 1
+ReflectionSpacing = 13
+
+# [P]laylist
+[SongStaticNonParty6]
+X = 680
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonP
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty6]
+X = 720
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_PLAYLIST
+Reflection = 1
+ReflectionSpacing = 13
+
+#and these are the ones for partymode
+[SongStaticParty1]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+# NAVBAR for party
+# enter a number
+[SongStaticParty2]
+X = 260
+Y = 545
+Z = 0.952
+W = 32
+H = 30
+Tex = Button13
+Color = White
+Type = Transparent
+
+[SongTextParty3]
+X = 288
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SONG_MENU_NAME_PARTY_JOKER
+Reflection = 1
+ReflectionSpacing = 13
+
+# menu
+[SongStaticParty3]
+X = 400
+Y = 552
+Z = 0.952
+W = 24
+H = 23
+Tex = ButtonM
+Color = White
+Type = Transparent
+
+[SongTextParty4]
+X = 426
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_MENU
+Reflection = 1
+ReflectionSpacing = 13
+
+[SongStaticParty4]
+X = 540
+Y = 552
+Z = 0.952
+W = 24
+H = 24
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[SongTextParty5]
+X = 570
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+#Texts for Party Mode
+[SongTextParty1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = White
+Text = PARTY_MODE
+
+[SongTextParty2]
+X = 238
+Y = 548
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_SONG_WHEREAMI
+#variable statics end
+
+# Jokers, 5 for each team, only shown in party Mode
+[SongStaticTeam1Joker1]
+Tex = Joker
+X = 505
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker2]
+Tex = Joker
+X = 555
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker3]
+Tex = Joker
+X = 605
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker4]
+Tex = Joker
+X = 655
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker5]
+Tex = Joker
+X = 705
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker1]
+Tex = Joker
+X = 505
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker2]
+Tex = Joker
+X = 555
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker3]
+Tex = Joker
+X = 605
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker4]
+Tex = Joker
+X = 655
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker5]
+Tex = Joker
+X = 705
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker1]
+Tex = Joker
+X = 505
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker2]
+Tex = Joker
+X = 555
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker3]
+Tex = Joker
+X = 605
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker4]
+Tex = Joker
+X = 655
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker5]
+Tex = Joker
+X = 705
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+
+[Sing]
+Texts = 1
+
+[SingBackground]
+Type=color
+ColR=1
+ColB=1
+ColG=1
+
+[SingText1]
+Text = SING_TIME
+X = 43
+Y = 577
+Font = 1
+Size = 18
+Color = White
+Align = 1
+
+[SingStatic1]
+;TextBG
+Tex = LyricBar
+X = 10
+Y = 492
+W = 780
+H = 85
+Color = White
+Type = Transparent
+
+[SingStatic2]
+;TimeBar
+Tex = TimeBar1
+X = 10
+Y = 577
+W = 780
+H = 20
+Color = White
+Type = Transparent
+
+[SingTimeProgress]
+X = 87
+Y = 584
+W = 633
+H = 6
+Color = White
+
+[SingTimeText]
+Text = SING_TIME
+X = 761
+Y = 577
+Font = 1
+Size = 18
+Color = White
+Align = 1
+
+# O N E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#PlayerOne
+[SingP1Static]
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P1Dark
+Type = Colorized
+
+[SingP1Text]
+Text = P1
+X = 25
+Y = 302
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP1Static2]
+Tex = ScoreBG
+X = 680
+Y = 282
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1TextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1SingBar]
+X = 680
+Y = 316
+W = 100
+H = 8
+
+# T W O  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1TwoPStatic]
+Tex = P
+X = 20
+Y = 117
+W = 30
+H = 28
+Color = P1Dark
+Type = Colorized
+
+[SingP1TwoPText]
+Text = P1
+X = 25
+Y = 122
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP1TwoPStatic2]
+Tex = ScoreBG
+X = 680
+Y = 102
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1TwoPTextScore]
+Text = 00000
+X = 698
+Y = 104
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1TwoPSingBar]
+X = 680
+Y = 136
+W = 100
+H = 8
+
+#Player Two
+[SingP2RStatic]
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P2Dark
+Type = Colorized
+
+[SingP2RText]
+Text = P2
+X = 24
+Y = 302
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP2RStatic2]
+Tex = ScoreBG
+X = 680
+Y = 282
+W = 100
+H = 36
+Color = P2Dark
+Type = Colorized
+
+[SingP2RTextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2RSingBar]
+X = 680
+Y = 316
+W = 100
+H = 8
+
+# T H R E E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1ThreePStatic]
+Tex = P
+X = 16
+Y = 59
+W = 50
+H = 44
+Color = P1Dark
+Type = Colorized
+
+[SingP1ThreePText]
+Text = P1
+X = 27
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP1ThreePStatic2]
+Tex = ScoreBG
+X = 75
+Y = 61
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1ThreePTextScore]
+Text = 00000
+X = 93
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1ThreePSingBar]
+X = 75
+Y = 95
+W = 100
+H = 8
+
+#Player Two
+[SingP2MStatic]
+Tex = P
+X = 311
+Y = 59
+W = 50
+H = 44
+Color = P2Dark
+Type = Colorized
+
+[SingP2MText]
+Text = P2
+X = 321
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP2MStatic2]
+Tex = ScoreBG
+X = 370
+Y = 61
+W = 100
+H = 36
+Color = P2Dark
+Type = Colorized
+
+[SingP2MTextScore]
+Text = 00000
+X = 388
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2MSingBar]
+X = 370
+Y = 95
+W = 100
+H = 8
+
+#Player Three
+[SingP3RStatic]
+Tex = P
+X = 611
+Y = 59
+W = 50
+H = 44
+Color = P3Dark
+Type = Colorized
+
+[SingP3RText]
+Text = P3
+X = 621
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP3RStatic2]
+Tex = ScoreBG
+X = 670
+Y = 61
+W = 100
+H = 36
+Color = P3Dark
+Type = Colorized
+
+[SingP3RTextScore]
+Text = 00000
+X = 688
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP3SingBar]
+X = 670
+Y = 95
+W = 100
+H = 8
+
+[Score]
+Texts = 1
+
+[ScoreBackground]
+Tex = ScoreScreenBG
+
+[ScoreText1]
+X = 70
+Y = 6
+Color = White
+Font = 0
+Size = 60
+Text = SONG_SCORE
+Align = 0
+
+[ScoreTextArtistTitle]
+X = 70
+Y = 59
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = ArtistTitle
+
+[ScoreStatic1]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = ScoreIcon
+Type = Colorized
+
+[ScoreStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreText2]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+#end of main stuff
+
+# # # # # # # # # # # # # # # # # # One Player Score # # # # # # # # # # # #
+[ScoreTextName1]
+X = 197
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = White
+Align = 0
+
+# Rating
+[ScoreStaticRatingPicture1]
+X = 385
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore1]
+X = 422
+Y = 235
+width = 100
+Color = White
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+# Note Score
+[ScoreStaticBoxDark1]
+Tex = ScoreBar_box_dark
+X = 200
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes1]
+X = 227
+Y = 322
+Color = White
+Font = 0
+Size = 30
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore1]
+X = 487
+Y = 322
+Color = White
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static1]
+Tex = ScoreLine
+X = 200
+Y = 351
+W = 287
+H = 1
+Color = White
+Type = Colorized
+
+# Line Bonus
+[ScoreStaticBoxLight1]
+Tex = ScoreBar_box_light
+X = 200
+Y = 358
+W = 22
+H = 20
+Color = P1Light
+Type = Colorized
+
+[ScoreTextLineBonus1]
+X = 227
+Y = 352
+Color = White
+Font = 0
+Size = 30
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore1]
+X = 487
+Y = 352
+Color = White
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static2]
+Tex = ScoreLine
+X = 200
+Y = 382
+W = 287
+H = 1
+Color = White
+Type = Colorized
+
+# Golden Notes
+[ScoreStaticBoxLightest1]
+Tex = ScoreBar_box_lightest
+X = 200
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes1]
+X = 227
+Y = 383
+Color = White
+Font = 0
+Size = 30
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore1]
+X = 487
+Y = 383
+Color = White
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+#Total Score
+[ScoreStaticPlayerIdBox1]
+Tex = PlayerIDBox01
+X = 200
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+Reflection = 1
+ReflectionSpacing = 31
+
+[ScoreTextTotal1]
+X = 237
+Y = 454
+Color = White
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 0
+Reflection = 1
+ReflectionSpacing = 26
+
+[ScoreTextTotalSCore1]
+X = 487
+Y = 444
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 0
+Reflection = 1
+ReflectionSpacing = 24
+
+#ScoreBar
+[ScoreStaticBackLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 168
+W = 95
+H = 310
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound1]
+Tex = ScoreLevelRound
+X = 503
+Y = 138
+W = 95
+H = 8
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 400
+W = 95
+H = 10
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound1]
+Tex = ScoreLevelRound
+X = 503
+Y = 392
+W = 95
+H = 8
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer1Static3]
+Tex = ScoreEndCap
+X = 499
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 0
+
+[ScorePlayer1Static4]
+Tex = ScoreGlassBox
+X = 499
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# # # # # # # # # # # # # # # # # # Two Player Score # # # # # # # # # # # #
+# P L A Y E R   O N E
+[ScoreTextName2]
+X = 42
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = White
+Align = 0
+
+[ScoreStaticRatingPicture2]
+X = 180
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore2]
+X = 217
+Y = 235
+Width = 100
+Color = White
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark2]
+Tex = ScoreBar_box_dark
+X = 45
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes2]
+X = 72
+Y = 324
+Color = White
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore2]
+X = 282
+Y = 324
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLight2]
+Tex = ScoreBar_box_light
+X = 45
+Y = 358
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextLineBonus2]
+X = 72
+Y = 355
+Color = White
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore2]
+X = 282
+Y = 355
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLightest2]
+Tex = ScoreBar_box_lightest
+X = 45
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes2]
+X = 72
+Y = 387
+Color = White
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore2]
+X = 282
+Y = 387
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreTextTotal2]
+X = 82
+Y = 454
+Color = White
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Reflection = 1
+ReflectionSpacing = 24
+
+[ScoreTextTotalSCore2]
+X = 283
+Y = 444
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Reflection = 1
+ReflectionSpacing = 24
+
+# Lines
+[ScorePlayer2Static1]
+Tex = ScoreLine
+X = 45
+Y = 351
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScorePlayer2Static2]
+Tex = ScoreLine
+X = 45
+Y = 382
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScoreStaticPlayerIdBox2]
+Tex = PlayerIDBox01
+X = 45
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+Reflection = 1
+ReflectionSpacing = 31
+
+#ScoreBar
+[ScoreStaticBackLevel2]
+Tex = ScoreLevel
+X = 298
+Y = 168
+W = 95
+H = 310
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound2]
+Tex = ScoreLevelRound
+X = 298
+Y = 138
+W = 95
+H = 8
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel2]
+Tex = ScoreLevel
+X = 298
+Y = 400
+W = 95
+H = 10
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound2]
+Tex = ScoreLevelRound
+X = 298
+Y = 392
+W = 95
+H = 8
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer2Static3]
+Tex = ScoreEndCap
+X = 294
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 0
+
+[ScorePlayer2Static4]
+Tex = ScoreGlassBox
+X = 294
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# P L A Y E R   T W O
+[ScoreTextName3]
+X = 758
+Y = 290
+Font = 0
+Size = 30
+Text = P2
+Color = White
+Align = 2
+
+[ScoreStaticRatingPicture3]
+X = 545
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore3]
+X = 583
+Y = 235
+width = 100
+Color = White
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark3]
+Tex = ScoreBar_box_dark
+X = 733
+Y = 327
+W = 22
+H = 20
+Color = P2Dark
+Type = Colorized
+
+[ScoreTextNotes3]
+X = 728
+Y = 324
+Color = White
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 2
+
+[ScoreTextNotesScore3]
+X = 518
+Y = 324
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLight3]
+Tex = ScoreBar_box_light
+X = 733
+Y = 358
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextLineBonus3]
+X = 728
+Y = 355
+Color = White
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 2
+
+[ScoreTextLineBonusScore3]
+X = 518
+Y = 355
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLightest3]
+Tex = ScoreBar_box_lightest
+X = 733
+Y = 390
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes3]
+X = 728
+Y = 387
+Color = White
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 2
+
+[ScoreTextGoldenNotesScore3]
+X = 518
+Y = 387
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreTextTotal3]
+X = 718
+Y = 454
+Color = White
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 2
+Reflection = 1
+ReflectionSpacing = 24
+
+[ScoreTextTotalScore3]
+X = 517
+Y = 444
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 00000
+Reflection = 1
+ReflectionSpacing = 24
+
+#Lines
+[ScorePlayer3Static1]
+Tex = ScoreLine
+X = 518
+Y = 351
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScorePlayer3Static2]
+Tex = ScoreLine
+X = 518
+Y = 382
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScoreStaticPlayerIdBox3]
+Tex = PlayerIDBox02
+X = 729
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+Reflection = 1
+ReflectionSpacing = 31
+
+#ScoreBar
+[ScoreStaticBackLevel3]
+Tex = ScoreLevel
+X = 409
+Y = 168
+W = 95
+H = 310
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound3]
+Tex = ScoreLevelRound
+X = 409
+Y = 138
+W = 95
+H = 8
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticLevel3]
+Tex = ScoreLevel
+X = 409
+Y = 400
+W = 95
+H = 10
+Color = P2Dark
+Type = Colorized
+
+[ScoreStaticLevelRound3]
+Tex = ScoreLevelRound
+X = 409
+Y = 392
+W = 95
+H = 8
+Color = P2Dark
+Type = Colorized
+
+[ScorePlayer3Static3]
+Tex = ScoreEndCap
+X = 405
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 0
+
+[ScorePlayer3Static4]
+Tex = ScoreGlassBox
+X = 405
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# # # # # # # # # # # # # # # # # # Three Player Score # # # # # # # # # # # #
+# P L A Y E R  O N E
+[ScoreTextName4]
+X = 20
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P1
+Color = White
+
+# Rating
+[ScoreStaticRatingPicture4]
+X = 200
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes4]
+X = 20
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = White
+
+[ScoreTextNotesScore4]
+X = 260
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextLineBonus4]
+X = 20
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = White
+
+[ScoreTextLineBonusScore4]
+X = 260
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextGoldenNotes4]
+X = 20
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = White
+
+[ScoreTextGoldenNotesScore4]
+X = 260
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextScore4]
+X = 20
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = White
+
+[ScoreTextTotal4]
+X = 47
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = White
+Reflection = 1
+ReflectionSpacing = -1
+
+[ScoreTextTotalScore4]
+X = 260
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = White
+Reflection = 1
+ReflectionSpacing = -3
+
+[ScoreStaticBoxDark4]
+Tex = PlayerNumberBox
+X = 20
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P1Dark
+Z = 0.9
+Reflection = 1
+ReflectionSpacing = 4
+
+[ScorePlayer4Text1]
+X = 24
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = White
+Font = 1
+Size = 15
+Align = 0
+Text = P1
+
+#lines
+[ScorePlayer4Static1]
+X = 20
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer4Static2]
+X = 20
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer4Static3]
+X = 20
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer4Static4]
+X = 20
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer4Static5]
+X = 20
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+# P L A Y E R  T W O
+[ScoreTextName5]
+X = 280
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P2
+Color = White
+
+# Rating
+[ScoreStaticRatingPicture5]
+X = 460
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes5]
+X = 280
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = White
+
+[ScoreTextNotesScore5]
+X = 520
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextLineBonus5]
+X = 280
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = White
+
+[ScoreTextLineBonusScore5]
+X = 520
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextGoldenNotes5]
+X = 280
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = White
+
+[ScoreTextGoldenNotesScore5]
+X = 520
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextScore5]
+X = 280
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = White
+
+[ScoreTextTotal5]
+X = 307
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = White
+Reflection = 1
+ReflectionSpacing = -1
+
+[ScoreTextTotalScore5]
+X = 520
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = White
+Reflection = 1
+ReflectionSpacing = -3
+
+[ScoreStaticBoxDark5]
+Tex = PlayerNumberBox
+X = 280
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P2Dark
+Z = 0.9
+Reflection = 1
+ReflectionSpacing = 4
+
+[ScorePlayer5Text1]
+X = 284
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = White
+Font = 1
+Size = 15
+Align = 0
+Text = P2
+
+[ScorePlayer5Static1]
+X = 280
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer5Static2]
+X = 280
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer5Static3]
+X = 280
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer5Static4]
+X = 280
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer5Static5]
+X = 280
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+# P L A Y E R  T H R E E
+[ScoreTextName6]
+X = 540
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P3
+Color = White
+
+# Rating
+[ScoreStaticRatingPicture6]
+X = 720
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes6]
+X = 540
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = White
+
+[ScoreTextNotesScore6]
+X = 780
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextLineBonus6]
+X = 540
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = White
+
+[ScoreTextLineBonusScore6]
+X = 780
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextGoldenNotes6]
+X = 540
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = White
+
+[ScoreTextGoldenNotesScore6]
+X = 780
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextScore6]
+X = 540
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = White
+
+[ScoreTextTotal6]
+X = 567
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = White
+Reflection = 1
+ReflectionSpacing = -1
+
+[ScoreTextTotalScore6]
+X = 780
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = White
+Reflection = 1
+ReflectionSpacing = -3
+
+[ScoreStaticBoxDark6]
+Tex = PlayerNumberBox
+X = 540
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P3Dark
+Z = 0.9
+Reflection = 1
+ReflectionSpacing = 4
+
+[ScorePlayer6Text1]
+X = 544
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = White
+Font = 1
+Size = 15
+Align = 0
+Text = P3
+
+#lines
+[ScorePlayer6Static1]
+X = 540
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer6Static2]
+X = 540
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer6Static3]
+X = 540
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer6Static4]
+X = 540
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer6Static5]
+X = 540
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[Options]
+Texts = 6
+Fade = 2
+
+[OptionsBackground]
+Tex = OptionsBG
+
+[OptionsStatic1]
+X = 65
+Y = 130
+W = 25
+H = 25
+Color = White
+Tex = IconOption
+Type = Colorized
+
+[OptionsText1]
+X = 95
+Y = 115
+Color = White
+Font = 0
+Size = 54
+Text = SING_OPTIONS
+Align = 0
+
+[OptionsText2]
+X = 95
+Y = 165
+Color = ColorLightest
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_DESC
+
+[OptionsTextDescription]
+X = 95
+Y = 195
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[OptionsStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection=1
+ReflectionSpacing=13
+
+[OptionsStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsText4]
+X = 440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_SELECT
+Reflection=1
+ReflectionSpacing=13
+
+[OptionsStatic6]
+X = 550
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsText5]
+X = 590
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_ESC
+Reflection=1
+ReflectionSpacing=13
+
+[OptionsButtonGame]
+X = 95
+Y = 235
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonGameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_GAME
+Color = White
+
+[OptionsButtonGraphics]
+X = 250
+Y = 235
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonGraphicsText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_GRAPHICS
+Color = White
+
+[OptionsButtonSound]
+X = 405
+Y = 235
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonSoundText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_SOUND
+Color = White
+
+[OptionsButtonLyrics]
+X = 560
+Y = 235
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonLyricsText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_LYRICS
+Color = White
+
+[OptionsButtonThemes]
+X = 95
+Y = 345
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonThemesText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_THEMES
+Color = White
+
+[OptionsButtonRecord]
+X = 250
+Y = 345
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonRecordText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_RECORD
+Color = White
+Texts = 1
+
+[OptionsButtonAdvanced]
+X = 405
+Y = 345
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonAdvancedText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_ADVANCED
+Color = White
+Texts = 1
+
+[OptionsButtonExit]
+X = 560
+Y = 345
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[OptionsGame]
+Texts = 5
+
+[OptionsGameBackground]
+Tex = OptionsBG
+
+[OptionsGameStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsGameText1]
+X = 70
+Y = 5
+Color = White
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsGameText2]
+X = 70
+Y = 55
+Color = ColorLightest
+Size = 30
+Text = SING_OPTIONS_GAME_DESC
+
+[OptionsGameText3]
+X = 70
+Y = 85
+Color = White
+Size = 30
+Text = SING_OPTIONS_GAME_WHEREAMI
+
+[OptionsGameStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsGameStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[OptionsGameSelectPlayers]
+Text = SING_OPTIONS_GAME_PLAYERS
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectDifficulty]
+Text = SING_OPTIONS_GAME_DIFFICULTY
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectSlideLanguage]
+Text = SING_OPTIONS_GAME_LANGUAGE
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectTabs]
+Text = SING_OPTIONS_GAME_TABS
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectSlideSorting]
+Text = SING_OPTIONS_GAME_SORTING
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectDebug]
+Text = SING_OPTIONS_GAME_DEBUG
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphics]
+Texts = 5
+
+[OptionsGraphicsBackground]
+Tex = OptionsBG
+
+[OptionsGraphicsStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsGraphicsText1]
+X = 70
+Y = 5
+Color = White
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsGraphicsText2]
+X = 70
+Y = 55
+Color = ColorLightest
+Size = 30
+Text = SING_OPTIONS_GRAPHICS_DESC
+
+[OptionsGraphicsText3]
+X = 70
+Y = 85
+Color = White
+Size = 30
+Text = SING_OPTIONS_GRAPHICS_WHEREAMI
+
+[OptionsGraphicsStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsGraphicsStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Z = 0.5
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsGraphicsSelectSlideResolution]
+Text = SING_OPTIONS_GRAPHICS_RESOLUTION
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectFullscreen]
+Text = SING_OPTIONS_GRAPHICS_FULLSCREEN
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectDepth]
+Text = SING_OPTIONS_GRAPHICS_DEPTH
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectVisualizer]
+Text = SING_OPTIONS_GRAPHICS_VISUALIZER
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectOscilloscope]
+Text = SING_OPTIONS_GRAPHICS_OSCILLOSCOPE
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectMovieSize]
+Text = SING_OPTIONS_GRAPHICS_MOVIE_SIZE
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSound]
+Texts = 5
+
+[OptionsSoundBackground]
+Tex = OptionsBG
+
+[OptionsSoundStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsSoundText1]
+X = 70
+Y = 5
+Color = White
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsSoundText2]
+X = 70
+Y = 55
+Color = ColorLightest
+Size = 30
+Text = SING_OPTIONS_SOUND_DESC
+
+[OptionsSoundText3]
+X = 70
+Y = 85
+Color = White
+Size = 30
+Text = SING_OPTIONS_SOUND_WHEREAMI
+
+[OptionsSoundStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsSoundStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsSoundSelectVoicePassthrough]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_VOICEPASSTHROUGH
+X = 70
+Y = 130
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectBackgroundMusic]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_BACKGROUNDMUSIC
+X = 70
+Y = 170
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectMicBoost]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_MIC_BOOST
+X = 70
+Y = 210
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectClickAssist]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_CLICK_ASSIST
+X = 70
+Y = 250
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectBeatClick]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_BEAT_CLICK
+X = 70
+Y = 290
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectThreshold]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_THRESHOLD
+X = 70
+Y = 330
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectSlidePreviewVolume]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_PREVIEWVOLUME
+X = 70
+Y = 370
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectSlidePreviewFADING]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_PREVIEWFADING
+X = 70
+Y = 410
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundButtonExit]
+X = 70
+Y = 460
+W = 250
+H = 35
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyrics]
+Texts = 1
+
+[OptionsLyricsBackground]
+Tex = OptionsBG
+
+[OptionsLyricsStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsLyricsText1]
+X = 70
+Y = 5
+Color = White
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsLyricsText2]
+X = 70
+Y = 55
+Color = ColorLightest
+Size = 30
+Text = SING_OPTIONS_LYRICS_DESC
+
+[OptionsLyricsText3]
+X = 70
+Y = 85
+Color = White
+Size = 30
+Text = SING_OPTIONS_LYRICS_WHEREAMI
+
+[OptionsLyricsStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsLyricsStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsLyricsSelectLyricsFont]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_LYRICS_FONT
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsSelectLyricsEffect]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_LYRICS_EFFECT
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsSelectNoteLines]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_LYRICS_NOTELINES
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemes]
+Texts = 5
+
+[OptionsThemesBackground]
+Tex = OptionsBG
+
+[OptionsThemesStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsThemesText1]
+X = 70
+Y = 5
+Color = White
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsThemesText2]
+X = 70
+Y = 55
+Color = ColorLightest
+Size = 30
+Text = SING_OPTIONS_THEMES_DESC
+
+[OptionsThemesText3]
+X = 70
+Y = 85
+Color = White
+Size = 30
+Text = SING_OPTIONS_THEMES_WHEREAMI
+
+[OptionsThemesStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsThemesStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[OptionsThemesSelectTheme]
+Text = SING_OPTIONS_THEMES_THEME
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesSelectSkin]
+Text = SING_OPTIONS_THEMES_SKIN
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesSelectColor]
+Text = SING_OPTIONS_THEMES_COLOR
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecord]
+Texts = 5
+
+[OptionsRecordBackground]
+Tex = OptionsBG
+
+[OptionsRecordStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsRecordText1]
+X = 70
+Y = 5
+Color = White
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsRecordText2]
+X = 70
+Y = 55
+Color = ColorLightest
+Size = 30
+Text = SING_OPTIONS_RECORD_DESC
+
+[OptionsRecordText3]
+X = 70
+Y = 85
+Color = White
+Size = 30
+Text = SING_OPTIONS_RECORD_WHEREAMI
+
+[OptionsRecordStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsRecordStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[OptionsRecordSelectSlideCard]
+Text = SING_OPTIONS_RECORD_CARD
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordSelectSlideInput]
+Text = SING_OPTIONS_RECORD_INPUT
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordSelectSlideChannel]
+Text = SING_OPTIONS_RECORD_CHANNEL
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordButtonExit]
+X = 70
+Y = 390
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvanced]
+Texts = 5
+
+[OptionsAdvancedBackground]
+Tex = OptionsBG
+
+[OptionsAdvancedStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsAdvancedText1]
+X = 70
+Y = 5
+Color = White
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsAdvancedText3]
+X = 70
+Y = 55
+Color = ColorLightest
+Size = 30
+Text = SING_OPTIONS_ADVANCED_DESC
+
+[OptionsAdvancedText2]
+X = 70
+Y = 85
+Color = White
+Size = 30
+Text = SING_OPTIONS_ADVANCED_WHEREAMI
+
+[OptionsAdvancedStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsAdvancedStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+#########unused at the moment#########
+#[OptionsAdvancedSelectLoadAnimation]
+#Text = SING_OPTIONS_ADVANCED_LOADANIMATION
+#Tex = MainBar
+#TexSBG = SelectBG
+#X = 40
+#Y = 85
+#W = 230
+#H = 70
+#SkipX = 10
+
+#Color = ColorDark
+#DColor = ColorLight
+#TColor = White
+#TDColor = White
+
+#SBGColor = ColorDark
+#SBGDColor = ColorLight
+#STColor = White
+#STDColor = GrayDark
+
+[OptionsAdvancedSelectScreenFade]
+Text = SING_OPTIONS_ADVANCED_SCREENFADE
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectEffectSing]
+Text = SING_OPTIONS_ADVANCED_EFFECTSING
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectLineBonus]
+Text = SING_OPTIONS_GRAPHICS_LINEBONUS
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectSlideOnSongClick]
+Text = SING_OPTIONS_ADVANCED_ONSONGCLICK
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectAskbeforeDel]
+Text = SING_OPTIONS_ADVANCED_ASKBEFOREDEL
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectPartyPopup]
+Text = SING_OPTIONS_ADVANCED_PARTYPOPUP
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5]
+Texts = 1
+
+[Top5Background]
+Tex = Top5BG
+
+[Top5Text1]
+X = 70
+Y = 6
+Color = White
+Font = 0
+Size = 60
+Align = 0
+Text = SING_TOP_5_CHARTS
+
+[Top5TextArtistTitle]
+X = 70
+Y = 59
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = artist - title
+
+[Top5Text4]
+X = 70
+Y = 83
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_GAME_DIFFICULTY
+
+[Top5TextLevel]
+X = 270
+Y = 83
+Color = White
+Font = 0
+Size = 30
+Align = 1
+Text = easy
+
+[Top5Static1]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = ScoreIcon
+Type = Colorized
+
+[Top5Static2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Static3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Text2]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = SING_TOP_5_CHARTS_WHEREAMI
+
+[Top5Static4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[Top5Text3]
+X = 290
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_TOP_5_CHARTS_CONTINUE
+
+[Top5Static5]
+X = 530
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[Top5Text5]
+X = 560
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_TOP_5_CHARTS_SWITCH_DIFFICULTY
+
+[Top5TextName1]
+X = 150
+Y = 190
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 1. Player1
+
+[Top5TextName2]
+X = 150
+Y = 240
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 2. Player2
+
+[Top5TextName3]
+X = 150
+Y = 290
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 3. Player3
+
+[Top5TextName4]
+X = 150
+Y = 340
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 4. Player4
+
+[Top5TextName5]
+X = 150
+Y = 390
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 5. Player5
+
+[Top5TextScore1]
+X = 560
+Y = 190
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore2]
+X = 560
+Y = 240
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore3]
+X = 560
+Y = 290
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore4]
+X = 560
+Y = 340
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore5]
+X = 560
+Y = 390
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+
+[Top5TextDate1]
+X = 760
+Y = 190
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate2]
+X = 760
+Y = 240
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate3]
+X = 760
+Y = 290
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate4]
+X = 760
+Y = 340
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate5]
+X = 760
+Y = 390
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextNumber1]
+X = 120
+Y = 193
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 1
+
+[Top5TextNumber2]
+X = 120
+Y = 243
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 2
+
+[Top5TextNumber3]
+X = 120
+Y = 293
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 3
+
+[Top5TextNumber4]
+X = 120
+Y = 343
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 4
+
+[Top5TextNumber5]
+X = 120
+Y = 393
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 5
+
+[Top5StaticNumber1]
+Tex = PlayerNumberBox
+X = 100
+Y = 186
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber2]
+Tex = PlayerNumberBox
+X = 100
+Y = 236
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber3]
+Tex = PlayerNumberBox
+X = 100
+Y = 286
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber4]
+Tex = PlayerNumberBox
+X = 100
+Y = 336
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber5]
+Tex = PlayerNumberBox
+X = 100
+Y = 386
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Edit]
+Texts = 5
+
+[EditBackground]
+Tex = EditBG
+
+# main icon
+[EditStatic1]
+X = 65
+Y = 150
+W = 25
+H = 25
+Color = White
+Tex = IconEdit
+Type = Transparent
+# Type = Colorized
+
+# main icon title
+[EditText1]
+X = 95
+Y = 135
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_EDIT
+
+# main icon subtitle
+[EditText2]
+X = 95
+Y = 175
+Color = ColorLightest
+Font = 0
+Size = 30
+Align = 0
+Text = SING_EDIT_MENU_DESCRIPTION
+
+# Navigate button text
+[EditText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+# Select button text
+[EditText4]
+X = 440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_SELECT
+Reflection=1
+ReflectionSpacing=13
+
+# Esc button text
+[EditText5]
+X = 590
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_EXIT
+Reflection=1
+ReflectionSpacing=13
+
+[EditTextDescription]
+X = 95
+Y = 195
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = SING_EDIT_TEXTDESCRIPTION
+
+[EditStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic6]
+X = 550
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditButtonConvert]
+X = 250
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[EditButtonConvertText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_CONVERT
+Color = White
+
+[EditButtonExit]
+X = 405
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[EditButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_EXIT
+Color = White
+
+[Level]
+Texts = 5
+
+[LevelBackground]
+Tex = MainBG
+
+[LevelStatic1]
+X = 65
+Y = 205
+W = 25
+H = 23
+Tex = MainIcon
+Color = White
+Type = Transparent
+
+[LevelText1]
+X = 95
+Y = 186
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_MODE
+
+[LevelText2]
+X = 95
+Y = 233
+Color = ColorLightest
+Font = 0
+Size = 30
+Align = 0
+Text = SING_DIFFICULTY_DESC
+
+[LevelStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[LevelText4]
+X = 440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_DIFFICULTY_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[LevelButtonEasy]
+X = 180
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[LevelButtonMedium]
+X = 335
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[LevelButtonHard]
+X = 490
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[LevelButtonEasyText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text = SING_EASY
+
+[LevelButtonMediumText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text = SING_MEDIUM
+
+[LevelButtonHardText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text = SING_HARD
+
+[Name]
+Texts = 2
+
+[NameBackground]
+Tex  = MainBG
+
+[NameStatic1]
+X = 65
+Y = 205
+W = 25
+H = 23
+Tex = MainIcon
+Color = White
+Type = Transparent
+
+[NameText1]
+X = 95
+Y = 186
+Color = White
+Font = 0
+Size = 54
+Text = SING_MODE
+
+[NameText2]
+X = 95
+Y = 233
+Color = ColorLightest
+Font = 0
+Size = 30
+Align = 0
+Text = SING_PLAYER_DESC
+
+[NameStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[NameStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameText4]
+X = 440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_PLAYER_ENTER_NAME
+Reflection = 1
+ReflectionSpacing = 13
+
+[NameStatic6]
+X = 590
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameText5]
+X = 630
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[NameButtonPlayer1]
+X = 180
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = P1Dark
+DColor = P1Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer1Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer2]
+X = 335
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = P2Dark
+DColor = P2Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer2Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer3]
+X = 490
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = P3Dark
+DColor = P3Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer3Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer4]
+X = 180
+Y = 400
+W = 150
+H = 50
+Tex = Button
+Color = P4Dark
+DColor = P4Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer4Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer5]
+X = 335
+Y = 400
+W = 150
+H = 50
+Tex = Button
+Color = P5Dark
+DColor = P5Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer5Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer6]
+X = 490
+Y = 400
+W = 150
+H = 50
+Tex = Button
+Color = P6Dark
+DColor = P6Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer6Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[PartyNewRound]
+Texts = 7
+
+[PartyNewRoundBackground]
+Tex = MainBG
+
+[PartyNewRoundStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStatic3]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyNewRoundText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = White
+Text = PARTY_MODE
+
+[PartyNewRoundText2]
+X = 70
+Y = 65
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_ROUND_DESC
+
+[PartyNewRoundText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_ROUND_WHEREAMI
+
+[PartyNewRoundText4]
+X = 290
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = PARTY_ROUND_LEGEND_CONTINUE
+
+[PartyNewRoundText5]
+X = 460
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND
+Align = 0
+
+[PartyNewRoundText6]
+X = 600
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND_WINNER
+Align = 0
+
+[PartyNewRoundText7]
+X = 448
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = PARTY_ROUND
+Align = 2
+
+[PartyNewRoundTextTeam1Players]
+X = 30
+Y = 137
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam2Players]
+X = 30
+Y = 218
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam3Players]
+X = 30
+Y = 299
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundStatic4]
+Tex = PartyRoundBG1
+X = 450
+Y = 103
+W = 330
+H = 24
+Color = DarkBlue
+Type = Colorized
+
+[PartyNewRoundStatic5]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyNewRoundStatic6]
+Tex = PartyRoundBG3
+X = 250
+Y = 350
+W = 300
+H = 50
+Color = DarkBlue
+Type = Colorized
+
+[PartyNewRoundStatic7]
+Tex = PartyRoundBG4
+X = 50
+Y = 495
+W = 700
+H = 30
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticTeam1]
+Tex = PartyTeamButton1
+X = 20
+Y = 110
+W = 400
+H = 50
+Color = P1Dark
+Type = Colorized
+Reflection = 0
+
+[PartyNewRoundStaticTeam2]
+Tex = PartyTeamButton1
+X = 20
+Y = 191
+W = 400
+H = 50
+Color = P2Dark
+Type = Colorized
+Reflection = 0
+
+[PartyNewRoundStaticTeam3]
+Tex = PartyTeamButton1
+X = 20
+Y = 272
+W = 400
+H = 50
+Color = P3Dark
+Type = Colorized
+Reflection = 0
+
+[PartyNewRoundStaticNextPlayer1]
+Tex = PartyPlayerButton
+X = 155
+Y = 415
+W = 150
+H = 50
+Type = Colorized
+Texts = 1
+Color = P1Light
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStaticNextPlayer2]
+Tex = PartyPlayerButton
+X = 325
+Y = 415
+W = 150
+H = 50
+Type = Colorized
+Texts = 1
+Color = P2Light
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStaticNextPlayer3]
+Tex = PartyPlayerButton
+X = 495
+Y = 415
+W = 150
+H = 50
+Type = Colorized
+Texts = 1
+Color = P3Light
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyNewRoundTextRound1]
+X = 460
+Y = 133
+Color = White
+Font = 0
+Size = 24
+Text = Round 1
+Align = 0
+
+[PartyNewRoundTextRound2]
+X = 460
+Y = 162
+Color = White
+Font = 0
+Size = 24
+Text = Round 2
+Align = 0
+
+[PartyNewRoundTextRound3]
+X = 460
+Y = 191
+Color = White
+Font = 0
+Size = 24
+Text = Round 3
+Align = 0
+
+[PartyNewRoundTextRound4]
+X = 460
+Y = 220
+Color = White
+Font = 0
+Size = 24
+Text = Round 4
+Align = 0
+
+[PartyNewRoundTextRound5]
+X = 460
+Y = 249
+Color = White
+Font = 0
+Size = 24
+Text = Round 5
+Align = 0
+
+[PartyNewRoundTextRound6]
+X = 460
+Y = 278
+Color = White
+Font = 0
+Size = 24
+Text = Round 6
+Align = 0
+
+[PartyNewRoundTextRound7]
+X = 460
+Y = 307
+Color = White
+Font = 0
+Size = 24
+Text = Round 7
+Align = 0
+
+[PartyNewRoundTextWinner1]
+X = 600
+Y = 133
+Color = White
+Font = 0
+Size = 24
+Text = Winner 1
+Align = 0
+
+[PartyNewRoundTextWinner2]
+X = 600
+Y = 162
+Color = White
+Font = 0
+Size = 24
+Text = Winner 2
+Align = 0
+
+[PartyNewRoundTextWinner3]
+X = 600
+Y = 191
+Color = White
+Font = 0
+Size = 24
+Text = Winner 3
+Align = 0
+
+[PartyNewRoundTextWinner4]
+X = 600
+Y = 220
+Color = White
+Font = 0
+Size = 24
+Text = Winner 4
+Align = 0
+
+[PartyNewRoundTextWinner5]
+X = 600
+Y = 249
+Color = White
+Font = 0
+Size = 24
+Text = Winner 5
+Align = 0
+
+[PartyNewRoundTextWinner6]
+X = 600
+Y = 278
+Color = White
+Font = 0
+Size = 24
+Text = Winner 6
+Align = 0
+
+[PartyNewRoundTextWinner7]
+X = 600
+Y = 307
+Color = White
+Font = 0
+Size = 24
+Text = Winner 7
+Align = 0
+
+[PartyNewRoundStaticRound1]
+Tex = PartyRoundBG2
+X = 450
+Y = 135
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound2]
+Tex = PartyRoundBG2
+X = 450
+Y = 164
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound3]
+Tex = PartyRoundBG2
+X = 450
+Y = 193
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound4]
+Tex = PartyRoundBG2
+X = 450
+Y = 222
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound5]
+Tex = PartyRoundBG2
+X = 450
+Y = 251
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound6]
+Tex = PartyRoundBG2
+X = 450
+Y = 280
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound7]
+Tex = PartyRoundBG2
+X = 450
+Y = 309
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundTextNextRound]
+X = 400
+Y = 495
+Color = White
+Font = 0
+Size = 30
+Text = Next Round
+Align = 1
+
+[PartyNewRoundTextNextRoundNo]
+X = 457
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = 99
+Align = 0
+
+[PartyNewRoundTextScoreTeam1]
+X = 390
+Y = 110
+Color = White
+Font = 0
+Size = 51
+Text = 3000
+Align = 1
+
+[PartyNewRoundTextScoreTeam2]
+X = 390
+Y = 191
+Color = White
+Font = 0
+Size = 51
+Text = 2000
+Align = 1
+
+[PartyNewRoundTextScoreTeam3]
+X = 390
+Y = 272
+Color = White
+Font = 0
+Size = 51
+Text = 1000
+Align = 1
+
+[PartyNewRoundTextNameTeam1]
+X = 30
+Y = 108
+Color = White
+Font = 0
+Size = 36
+Text = Team 1
+Align = 0
+
+[PartyNewRoundTextNameTeam2]
+X = 30
+Y = 189
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyNewRoundTextNameTeam3]
+X = 30
+Y = 270
+Color = White
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyNewRoundTextNextPlayer1]
+X = 230
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 1
+Align = 1
+
+[PartyNewRoundTextNextPlayer2]
+X = 400
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 2
+Align = 1
+
+[PartyNewRoundTextNextPlayer3]
+X = 570
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 3
+Align = 1
+
+
+[PartyScore]
+Texts = 5
+
+[PartyScoreBackground]
+Tex = PartyBG
+
+[PartyScoreDecoTextures]
+ChangeTextures = 1
+
+FirstTexture = PartyScoreDeco
+FirstTyp = Colorized
+FirstColor = Gold
+
+SecondTexture = PartyScoreDeco
+SecondTyp = Colorized
+SecondColor = Silver
+
+ThirdTexture = PartyScoreDeco
+ThirdTyp = Colorized
+ThirdColor = Bronze
+
+[PartyScoreStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStatic3]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyScoreStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyScoreText1]
+X = 70
+Y = 6
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = White
+Text = PARTY_MODE
+
+[PartyScoreText2]
+X = 70
+Y = 53
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_SCORE_DESC
+
+[PartyScoreText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_SCORE_WHEREAMI
+
+[PartyScoreText4]
+X = 290
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = PARTY_LEGEND_CONTINUE
+
+[PartyScoreStatic5]
+Tex = PartyScoreBG1
+X = 50
+Y = 100
+W = 700
+H = 80
+Color = DarkBlue
+Type = Colorized
+
+[PartyScoreStatic6]
+Tex = PartyScoreBG2
+X = 50
+Y = 495
+W = 700
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyScoreText5]
+X = 400
+Y = 136
+Color = White
+Font = 0
+Size = 45
+Text = PARTY_SCORE_WINS2
+Align = 1
+
+[PartyScoreTextWinner]
+X = 400
+Y = 98
+Color = White
+Font = 0
+Size = 54
+Text = The Winner is...
+Align = 1
+
+[PartyScoreTextScoreTeam1]
+X = 568
+Y = 198
+Color = White
+Font = 0
+Size = 36
+Text = 3000
+Align = 2
+
+[PartyScoreTextScoreTeam2]
+X = 568
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = 2000
+Align = 2
+
+[PartyScoreTextScoreTeam3]
+X = 568
+Y = 398
+Color = White
+Font = 0
+Size = 36
+Text = 1000
+Align = 2
+
+[PartyScoreTextNameTeam1]
+X = 188
+Y = 198
+Font = 0
+Size = 36
+Align = 0
+Text = Team 1
+Color = White
+
+[PartyScoreTextNameTeam2]
+X = 188
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyScoreTextNameTeam3]
+X = 188
+Y = 398
+Color = White
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyScoreStaticTeam1]
+X = 188
+Y = 230
+W = 380
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyScoreStaticTeam1BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 200
+W = 400
+H = 50
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStaticTeam1Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 191
+W = 64
+H = 64
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = -5
+
+[PartyScoreStaticTeam2]
+X = 188
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyScoreStaticTeam2BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStaticTeam2Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 291
+W = 64
+H = 64
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = -5
+
+[PartyScoreStaticTeam3]
+X = 188
+Y = 430
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyScoreStaticTeam3BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 400
+W = 400
+H = 50
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStaticTeam3Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 391
+W = 64
+H = 64
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = -5
+
+[PartyWin]
+Texts = 4
+
+[PartyWinBackground]
+Tex = PartyBG
+
+[PartyWinStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStatic3]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyWinStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyWinText1]
+X = 70
+Y = 6
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = White
+Text = PARTY_MODE
+
+[PartyWinText2]
+X = 70
+Y = 53
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_WIN_DESC
+
+[PartyWinText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_WIN_WHEREAMI
+
+[PartyWinText4]
+X = 290
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = PARTY_WIN_LEGEND_CONTINUE
+
+#[PartyWinTextWinner]
+#X = 150
+#Y = 120
+#Color = White
+#Font = 1
+#Size = 42
+#Text = The Winner is...
+#Align = 0
+
+[PartyWinTextScoreTeam1]
+X = 699
+Y = 183
+Color = White
+Font = 0
+Size = 57
+Text = 3000
+Align = 2
+
+[PartyWinTextScoreTeam2]
+X = 669
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = 2000
+Align = 2
+
+[PartyWinTextScoreTeam3]
+X = 649
+Y = 398
+Color = White
+Font = 0
+Size = 27
+Text = 1000
+Align = 2
+
+[PartyWinTextNameTeam1]
+X = 169
+Y = 183
+Font = 0
+Size = 57
+Align = 0
+Text = Team 1
+Color = White
+
+[PartyWinTextNameTeam2]
+X = 289
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyWinTextNameTeam3]
+X = 369
+Y = 398
+Color = White
+Font = 0
+Size = 27
+Text = Team 3
+Align = 0
+
+[PartyWinStaticTeam1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BG]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam1Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BGRank1]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam1Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BGRank2]
+Tex = PartyTeamButton3
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam1Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BGRank3]
+Tex = PartyTeamButton3
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyWinStaticTeam1Deco]
+Tex = PartyWinDeco1
+X = 91
+Y = 176
+W = 79
+H = 79
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = 3
+
+[PartyWinStaticTeam2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BG]
+Tex = PartyTeamButton4
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamButton3
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BGRank1]
+Tex = PartyTeamButton4
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BGRank2]
+Tex = PartyTeamButton4
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BGRank3]
+Tex = PartyTeamButton4
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Deco]
+Tex = PartyWinDeco2
+X = 226
+Y = 291
+W = 64
+H = 64
+Type = Colorized
+Color = Silver
+Reflection = 1
+ReflectionSpacing = 3
+
+[PartyWinStaticTeam3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BG]
+Tex = PartyTeamButton5
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BGRank1]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BGRank2]
+Tex = PartyTeamButton5
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BGRank3]
+Tex = PartyTeamButton5
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Deco]
+Tex = PartyWinDeco3
+X = 316
+Y = 391
+W = 54
+H = 54
+Type = Colorized
+Color = Bronze
+Reflection = 1
+ReflectionSpacing = 3
+
+[PartyOptions]
+Texts = 5
+
+[PartyOptionsBackground]
+Tex = PartyBG
+
+[PartyOptionsStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyOptionsStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyOptionsStatic3]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyOptionsStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyOptionsStatic5]
+X = 388
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyOptionsText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = White
+Text = PARTY_MODE
+
+[PartyOptionsText2]
+X = 70
+Y = 65
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_OPTIONS_DESC
+
+[PartyOptionsText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_OPTIONS_WHEREAMI
+
+[PartyOptionsText4]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[PartyOptionsText5]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_CONTINUE
+
+[PartyOptionsSelectLevel]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_DIFFICULTY
+X = 70
+Y = 110
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+#TexSBG = SelectBG
+#W = 230
+#H = 40
+#SkipX = 10
+
+[PartyOptionsSelectPlayList]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_PLAYLIST
+X = 70
+Y = 165
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyOptionsSelectPlayList2]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_PLAYLIST
+X = 70
+Y = 220
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyOptionsSelectRounds]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_ROUNDS
+X = 70
+Y = 250
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+
+
+[PartyPlayer]
+Texts = 6
+
+[PartyPlayerBackground]
+Tex = PartyBG
+
+[PartyPlayerStatic1]
+X = 0
+Y = 545
+Z = 0.7
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerStatic2]
+X = 250
+Y = 545
+Z = 0.7
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerStatic3]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyPlayerStatic4]
+X = 260
+Y = 552
+Z = 0.75
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic5]
+X = 388
+Y = 552
+Z = 0.75
+W = 32
+H = 23
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic6]
+X = 556
+Y = 552
+Z = 0.75
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyPlayerText1]
+X = 70
+Y = 6
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = White
+Text = PARTY_MODE
+
+[PartyPlayerText2]
+X = 70
+Y = 53
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_PLAYER_DESC
+
+[PartyPlayerText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_PLAYER_WHEREAMI
+
+[PartyPlayerText4]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[PartyPlayerText5]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = PARTY_PLAYER_ENTER_NAME
+
+[PartyPlayerText6]
+X = 586
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_CONTINUE
+
+[PartyPlayerSelectTeams]
+Tex = MainBar
+TexSBG = SelectBG
+Type = Colorized
+TypeSBG = Colorized
+Text = PARTY_TEAMS
+X = 45
+Y = 90
+W = 220
+H = 40
+SkipX = 10
+Fields = 2
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers1]
+Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+Type = Colorized
+TypeSBG = Colorized
+Text = PARTY_TEAMS_PLAYER1
+X = 365
+Y = 145
+W = 200
+SBGW = 200
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = P1Lightest
+DColor = P1Light
+TColor = White
+TDColor = White
+
+SBGColor = P1Lightest
+SBGDColor = P1Light
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers2]
+Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+Type = Colorized
+TypeSBG = Colorized
+Text = PARTY_TEAMS_PLAYER2
+X = 365
+Y = 285
+W = 200
+SBGW = 200
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = P2Lightest
+DColor = P2Light
+TColor = White
+TDColor = White
+
+SBGColor = P2Lightest
+SBGDColor = P2Light
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers3]
+Tex = MainBar
+Type = Colorized
+TypeSBG = Colorized
+TexSBG = PartyPlayerSelectBG
+Text = PARTY_TEAMS_PLAYER3
+X = 365
+Y = 425
+W = 200
+SBGW = 200
+H = 40
+SkipX = 10
+Fields = 4
+
+Color = P3Lightest
+DColor = P3Light
+TColor = White
+TDColor = White
+
+SBGColor = P3Lightest
+SBGDColor = P3Light
+STColor = White
+STDColor = GrayDark
+
+
+[PartyPlayerTeam1Name]
+Tex = PartyTeamButton2
+X = 45
+Y = 140
+W = 310
+H = 50
+Type = Colorized
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerTeam1NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 1
+Color = White
+
+[PartyPlayerPlayer1Name]
+Tex = Button
+X = 45
+Y = 200
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer1NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 1
+Color = White
+
+[PartyPlayerPlayer2Name]
+Tex = Button
+X = 205
+Y = 200
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer2NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 2
+Color = White
+
+[PartyPlayerPlayer3Name]
+Tex = Button
+X = 365
+Y = 200
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer3NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 3
+Color = White
+
+[PartyPlayerPlayer4Name]
+Tex = Button
+X = 525
+Y = 200
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer4NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 4
+Color = White
+
+[PartyPlayerTeam2Name]
+Tex = PartyTeamButton2
+X = 45
+Y = 280
+W = 310
+H = 50
+Type = Colorized
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerTeam2NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 2
+Color = White
+
+[PartyPlayerPlayer5Name]
+Tex = Button
+X = 45
+Y = 340
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer5NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 5
+Color = White
+
+[PartyPlayerPlayer6Name]
+Tex = Button
+X = 205
+Y = 340
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer6NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 6
+Color = White
+
+[PartyPlayerPlayer7Name]
+Tex = Button
+X = 365
+Y = 340
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer7NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 7
+Color = White
+
+[PartyPlayerPlayer8Name]
+Tex = Button
+X = 525
+Y = 340
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer8NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 8
+Color = White
+
+[PartyPlayerTeam3Name]
+Tex = PartyTeamButton2
+X = 45
+Y = 420
+W = 310
+H = 50
+Type = Colorized
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerTeam3NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 3
+Color = White
+
+[PartyPlayerPlayer9Name]
+Tex = Button
+X = 45
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer9NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 9
+Color = White
+
+[PartyPlayerPlayer10Name]
+Tex = Button
+X = 205
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer10NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 10
+Color = White
+
+[PartyPlayerPlayer11Name]
+Tex = Button
+X = 365
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer11NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 11
+Color = White
+
+[PartyPlayerPlayer12Name]
+Tex = Button
+X = 525
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Light
+Reflection = 1
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer12NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 12
+Color = White
+
+
+
+[PartyRoundsBackground]
+Tex = PartyBG
+
+[PartyRoundsStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyRoundsStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyRoundsStatic3]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyRoundsStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyRoundsStatic5]
+X = 388
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyRoundsText1]
+X = 70
+Y = 6
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = White
+Text = PARTY_MODE
+
+[PartyRoundsText2]
+X = 70
+Y = 53
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_ROUNDS_DESC
+
+[PartyRoundsText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_ROUNDS_WHEREAMI
+
+[PartyRoundsText4]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[PartyRoundsText5]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = PARTY_ROUNDS_LEGEND_CONTINUE
+
+[PartyRoundsSelectRoundCount]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_ROUNDCOUNT
+X = 70
+Y = 100
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound1]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE1
+X = 70
+Y = 155
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound2]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE2
+X = 70
+Y = 210
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound3]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE3
+X = 70
+Y = 265
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound4]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE4
+X = 70
+Y = 320
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound5]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE5
+X = 70
+Y = 375
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound6]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE6
+X = 70
+Y = 430
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound7]
+Tex = MainBar
+Type = Colorized
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE7
+X = 70
+Y = 485
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+
+
+[SongMenu]
+
+[SongMenuBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[SongMenuStatic1]
+Tex = interface_dialog_background
+X = 500
+Y = 120
+W = 280
+H = 200
+Z = 0.96
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 0
+
+[SongMenuStatic2]
+X = 508
+Y = 131
+W = 24
+H = 24
+Color = White
+Tex = icon_song_menu
+Type = Colorized
+Z = 0.97
+
+[SongMenuTextMenu]
+X = 538
+Y = 125
+Z = 0.97
+Color = ColorLight
+Size = 36
+Text = MENU
+
+[SongMenuButton1]
+X = 530
+Y = 175
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = LightBlue
+DColor = DarkBlue
+Type = Colorized
+Texts = 1
+
+[SongMenuButton1Text1]
+X = 6
+Y = 0
+Z = 0.97
+Color = White
+Size = 24
+Text = SONG_MENU_PLAY
+
+[SongMenuButton2]
+X = 530
+Y = 205
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = LightBlue
+DColor = DarkBlue
+Type = Colorized
+Texts = 1
+
+[SongMenuButton2Text1]
+X = 6
+Y = 0
+Color = White
+Size = 24
+Text = SONG_MENU_EDIT
+Z = 0.97
+
+[SongMenuButton3]
+X = 530
+Y = 235
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = LightBlue
+DColor = DarkBlue
+Type = Colorized
+Texts = 1
+
+[SongMenuButton3Text1]
+X = 6
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_MODI
+Align = 0
+Z = 0.97
+
+# shows up instead of BUtton 3
+# in some song menus
+[SongMenuSelectSlide3]
+TexSBG = Rectangle
+Text = 
+TypeSBG = Colorized
+ShowArrows = 1
+OneItemOnly = 1
+X = 530
+Y = 235
+W = 0
+H = 25
+Z = 0.97
+SkipX = 0
+SBGW = 220
+TextSize = 24
+Color = LightBlue
+DColor = DarkBlue
+TColor = White
+TDColor = White
+SBGColor = LightBlue
+SBGDColor = DarkBlue
+STColor = White
+STDColor = White
+
+[SongMenuButton4]
+X = 530
+Y = 265
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = ColorLight
+DColor = ColorDark
+Type = Colorized
+Texts = 1
+
+[SongMenuButton4Text1]
+X = 6
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_CANCEL
+Align = 0
+Z = 0.97
+
+[SongJumpto]
+
+[SongJumptoBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.5
+
+[SongJumptoStatic1]
+Tex = interface_dialog_background
+X = 500
+Y = 320
+W = 280
+H = 160
+Z = 0.965
+Color = White
+Type = Transparent
+
+[SongJumptoStatic2]
+X = 508
+Y = 328
+W = 24
+H = 24
+Color = White
+Tex = icon_song_search
+Type = Colorized
+Z = 0.97
+
+[SongJumptoText1]
+X = 538
+Y = 323
+Color = ColorLight
+Size = 36
+Text = SONG_JUMPTO_TYPE_DESC
+Z = 0.97
+
+#arrows over the select
+#TODO: remove, add this for all in code
+[SongJumptoStatic3]
+X = 510
+Y = 363
+W = 260
+H = 30
+Color = ColorLightest
+Tex = interface_selectbg_search
+Type = Colorized
+Z = 0.97
+
+[SongJumptoSelectSlideType]
+#Text = SONG_JUMPTO_TYPE_DESC
+X = 516
+Y = 363
+Z = 0.97
+H = 30
+SBGW = 150
+SkipX = 4
+
+Size = 36
+
+#text
+TColor = White
+TDColor = Red
+#Select0r.Text.Color
+STColor = White
+STDColor = Red
+
+[SongJumptoButtonSearchText]
+X = 526
+Y = 375
+Z = 0.97
+W = 160
+H = 50
+Size = 36
+Font = 1
+Align = 0
+
+[SongJumptoTextFound]
+X = 539
+Y = 425
+Color = White
+Font = 0
+Size = 24
+Text = SONG_JUMPTO_HELP
+Align = 0
+Z = 0.97
+
+
+[StatMain]
+Texts = 0
+Statics = 0
+
+[StatMainBackground]
+Tex = MainBG
+
+[StatMainButtonScores]
+X = 589
+Y = 100
+W = 190
+H = 50
+Tex = Button
+Color = DarkBlue
+DColor = LightBlue
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonScoresText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SCORES
+Color = White
+
+[StatMainButtonSingers]
+X = 589
+Y = 160
+W = 190
+H = 50
+Tex = Button
+Color = DarkBlue
+DColor = LightBlue
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonSingersText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SINGERS
+Color = White
+
+[StatMainButtonSongs]
+X = 589
+Y = 220
+W = 190
+H = 50
+Tex = Button
+Color = DarkBlue
+DColor = LightBlue
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonSongsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_SONGS
+Color = White
+
+[StatMainButtonBands]
+X = 589
+Y = 280
+W = 190
+H = 50
+Tex = Button
+Color = DarkBlue
+DColor = LightBlue
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonBandsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_BANDS
+Color = White
+
+[StatMainButtonExit]
+X = 589
+Y = 340
+W = 190
+H = 50
+Tex = Button
+Color = DarkBlue
+DColor = LightBlue
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatMainTextOverview]
+X = 45
+Y = 125
+W = 510
+Color = White
+Font = 0
+Size = 27
+Align = 0
+Text =
+
+[StatMainStatic1]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = StatIcon
+Type = Colorized
+
+[StatMainStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[StatMainStatic5]
+X = 388
+Y = 552
+W = 32
+H = 23
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[StatMainStatic6]
+X = 40
+Y = 100
+W = 520
+H = 20
+Tex = StatMainBG1
+Color = ColorLight
+Type = Colorized
+
+[StatMainStatic7]
+X = 40
+Y = 120
+W = 520
+H = 300
+Tex = StatMainBG2
+Color = ColorDark
+Type = Colorized
+
+[StatMainStatic8]
+X = 40
+Y = 420
+W = 520
+H = 20
+Tex = StatMainBG3
+Color = ColorLight
+Type = Colorized
+
+[StatMainText1]
+X = 70
+Y = 6
+Color = White
+Font = 0
+Size = 60
+Text = STAT_MAIN
+Align = 0
+
+[StatMainText2]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = STAT_MAIN_WHEREAMI
+
+[StatMainText3]
+X = 70
+Y = 53
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = STAT_MAIN_DESC
+
+[StatMainText4]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[StatMainText5]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_ESC
+
+[StatDetail]
+Texts = 0
+Statics = 0
+
+[StatDetailBackground]
+Tex = MainBG
+
+[StatDetailButtonNext]
+X = 589
+Y = 100
+W = 190
+H = 50
+Tex = Button
+Color = DarkBlue
+DColor = LightBlue
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonNextText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_NEXT
+Color = White
+
+[StatDetailButtonPrev]
+X = 589
+Y = 160
+W = 190
+H = 50
+Tex = Button
+Color = DarkBlue
+DColor = LightBlue
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonPrevText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_PREV
+Color = White
+
+[StatDetailButtonReverse]
+X = 589
+Y = 220
+W = 190
+H = 50
+Tex = Button
+Color = DarkBlue
+DColor = LightBlue
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonReverseText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_REVERSE
+Color = White
+
+[StatDetailButtonExit]
+X = 589
+Y = 280
+W = 190
+H = 50
+Tex = Button
+Color = DarkBlue
+DColor = LightBlue
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatDetailTextDescription]
+X = 70
+Y = 53
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[StatDetailTextPage]
+X = 546
+Y = 98
+Color = Black
+Font = 0
+Size = 15
+Align = 2
+Text =
+
+[StatDetailTextList1]
+X = 45
+Y = 122
+Color = White
+Font = 0
+Size = 21
+Text = Stat1
+
+[StatDetailTextList2]
+X = 45
+Y = 160
+Color = White
+Font = 0
+Size = 21
+Text = Stat2
+
+[StatDetailTextList3]
+X = 45
+Y = 198
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList4]
+X = 45
+Y = 236
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList5]
+X = 45
+Y = 274
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList6]
+X = 45
+Y = 312
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList7]
+X = 45
+Y = 350
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList8]
+X = 45
+Y = 388
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList9]
+X = 45
+Y = 426
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList10]
+X = 45
+Y = 464
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailStatic1]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = StatIcon
+Type = Colorized
+
+[StatDetailStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[StatDetailStatic5]
+X = 388
+Y = 552
+W = 32
+H = 23
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[StatDetailStatic6]
+X = 40
+Y = 100
+W = 520
+H = 24
+Tex = StatDetailBG1
+Color = ColorLight
+Type = Colorized
+
+[StatDetailStatic7]
+X = 40
+Y = 124
+W = 520
+H = 376
+Tex = StatMainBG2
+Color = ColorDark
+Type = Colorized
+
+[StatDetailStatic8]
+X = 40
+Y = 500
+W = 520
+H = 20
+Tex = StatMainBG3
+Color = ColorLight
+Type = Colorized
+
+[StatDetailText1]
+X = 70
+Y = 6
+Color = White
+Font = 0
+Size = 60
+Text = STAT_DETAIL
+Align = 0
+
+[StatDetailText2]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = STAT_DETAIL_WHEREAMI
+
+[StatDetailText3]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[StatDetailText4]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_ESC
+
+[CheckPopup]
+
+[CheckPopupBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[CheckPopupStatic1]
+Tex = interface_dialog_background
+X = 200
+Y = 150
+W = 400
+H = 200
+Z = 1
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 15
+
+[CheckPopupText1]
+X = 400
+Y = 160
+W = 400
+Color = ColorLight
+Font = 0
+Size = 30
+Text = MSG_QUESTION_TITLE
+Align = 1
+Z = 1
+
+[CheckPopupText]
+X = 400
+Y = 210
+W = 280
+Color = White
+Font = 0
+Size = 30
+Text = error text
+Align = 1
+Z = 1
+
+[CheckPopupButton1]
+X = 285
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = YES
+Align = 1
+Z = 1
+
+[CheckPopupButton2]
+X = 415
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton2Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = NO
+Align = 1
+Z = 1
+
+
+[ErrorPopup]
+
+[ErrorPopupBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[ErrorPopupStatic1]
+Tex = interface_dialog_background
+X = 200
+Y = 150
+W = 400
+H = 200
+Z = 0.98
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 15
+
+[ErrorPopupText1]
+X = 400
+Y = 160
+W = 400
+Color = ColorLight
+Font = 0
+Size = 30
+Text = MSG_ERROR_TITLE
+Align = 1
+Z = 1
+
+[ErrorPopupText]
+X = 400
+Y = 210
+W = 280
+Color = White
+Font = 0
+Size = 30
+Text = error text
+Align = 1
+Z = 1
+
+[ErrorPopupButton1]
+X = 350
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Z = 1
+
+[ErrorPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = OK
+Align = 1
+Z = 1
+
+[PausePopUpStatic]
+Tex = Pause
+X = 0
+Y = 0
+W = 800
+H = 600
+Z = 0.95
+Color = White
+Type = Colorized
+
+[SingLyricsUpperBar]
+X = 80
+W = 640
+Y = 493
+H = 41
+;YOffSet (+/-) for the Sing-Indicator
+IndicatorYOffset = 3
+
+[SingLyricsLowerBar]
+X = 80
+W = 640
+Y = 535
+H = 41
\ No newline at end of file
diff --git a/songmanagement/game/themes/Deluxe/Blue.ini b/songmanagement/game/themes/Deluxe/Blue.ini
new file mode 100644
index 00000000..3ebc04ff
--- /dev/null
+++ b/songmanagement/game/themes/Deluxe/Blue.ini
@@ -0,0 +1,235 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Skin]
+Theme=Deluxe
+Name=Blue
+Color=Blue
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+#Backgrounds
+LoadingBG      = [bg-load]blue.jpg
+MainBG         = [bg-main]blue.jpg
+SongBG         = [bg-main]blue.jpg
+ScoreScreenBG  = [bg-main]blue.jpg
+Top5BG         = [bg-main]blue.jpg
+OptionsBG      = [bg-main]blue.jpg
+EditBG         = [bg-main]blue.jpg
+PartyBG        = [bg-main]blue.jpg
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.jpg
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Deluxe/Fall.ini b/songmanagement/game/themes/Deluxe/Fall.ini
new file mode 100644
index 00000000..4502be61
--- /dev/null
+++ b/songmanagement/game/themes/Deluxe/Fall.ini
@@ -0,0 +1,235 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Skin]
+Theme=Deluxe
+Name=Fall
+Color=Orange
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+#Backgrounds
+LoadingBG      = [bg-load]fall.jpg
+MainBG         = [bg-main]fall.jpg
+SongBG         = [bg-main]fall.jpg
+ScoreScreenBG  = [bg-main]fall.jpg
+Top5BG         = [bg-main]fall.jpg
+OptionsBG      = [bg-main]fall.jpg
+EditBG         = [bg-main]fall.jpg
+PartyBG        = [bg-main]fall.jpg
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.jpg
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Deluxe/Ocean.ini b/songmanagement/game/themes/Deluxe/Ocean.ini
new file mode 100644
index 00000000..8af41f20
--- /dev/null
+++ b/songmanagement/game/themes/Deluxe/Ocean.ini
@@ -0,0 +1,235 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Skin]
+Theme=Deluxe
+Name=Ocean
+Color=Blue
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+#Backgrounds
+LoadingBG      = [bg-load]blue.jpg
+MainBG         = [bg-video]_ocean.avi
+SongBG         = [bg-video]_ocean.avi
+ScoreScreenBG  = [bg-video]_ocean.avi
+Top5BG         = [bg-video]_ocean.avi
+OptionsBG      = [bg-video]_ocean.avi
+EditBG         = [bg-video]_ocean.avi
+PartyBG        = [bg-video]_ocean.avi
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png 
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelround.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.jpg
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Deluxe/Ribbon.ini b/songmanagement/game/themes/Deluxe/Ribbon.ini
new file mode 100644
index 00000000..06a4dd41
--- /dev/null
+++ b/songmanagement/game/themes/Deluxe/Ribbon.ini
@@ -0,0 +1,234 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Skin]
+Theme=Deluxe
+Name=Ribbon
+Color=Any
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+#Backgrounds
+LoadingBG      = [bg-video]ribbon.mov
+MainBG         = [bg-video]ribbon.mov
+SongBG         = [bg-video]ribbon.mov
+ScoreScreenBG  = [bg-video]ribbon.mov
+Top5BG         = [bg-video]ribbon.mov
+OptionsBG      = [bg-video]ribbon.mov
+EditBG         = [bg-video]ribbon.mov
+PartyBG        = [bg-video]ribbon.mov
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.jpg
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Deluxe/Summer.ini b/songmanagement/game/themes/Deluxe/Summer.ini
new file mode 100644
index 00000000..660a5ec7
--- /dev/null
+++ b/songmanagement/game/themes/Deluxe/Summer.ini
@@ -0,0 +1,235 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Skin]
+Theme=Deluxe
+Name=Summer
+Color=Red
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+#Backgrounds
+LoadingBG      = [bg-load]summer.jpg
+MainBG         = [bg-main]summer.jpg
+SongBG         = [bg-main]summer.jpg
+ScoreScreenBG  = [bg-main]summer.jpg
+Top5BG         = [bg-main]summer.jpg
+OptionsBG      = [bg-main]summer.jpg
+EditBG         = [bg-main]summer.jpg
+PartyBG        = [bg-main]summer.jpg
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.jpg
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Deluxe/Winter.ini b/songmanagement/game/themes/Deluxe/Winter.ini
new file mode 100644
index 00000000..71b4dfaa
--- /dev/null
+++ b/songmanagement/game/themes/Deluxe/Winter.ini
@@ -0,0 +1,235 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Skin]
+Theme=Deluxe
+Name=Winter
+Color=Blue
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+#Backgrounds
+LoadingBG      = [bg-load]winter.jpg
+MainBG         = [bg-main]winter.jpg
+SongBG         = [bg-main]winter.jpg
+ScoreScreenBG  = [bg-main]winter.jpg
+Top5BG         = [bg-main]winter.jpg
+OptionsBG      = [bg-main]winter.jpg
+EditBG         = [bg-main]winter.jpg
+PartyBG        = [bg-main]winter.jpg
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.jpg
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Deluxe/[bg-load]blue.jpg b/songmanagement/game/themes/Deluxe/[bg-load]blue.jpg
new file mode 100644
index 00000000..f2e2c27e
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-load]blue.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[bg-load]fall.jpg b/songmanagement/game/themes/Deluxe/[bg-load]fall.jpg
new file mode 100644
index 00000000..d205a4e4
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-load]fall.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[bg-load]summer.jpg b/songmanagement/game/themes/Deluxe/[bg-load]summer.jpg
new file mode 100644
index 00000000..af7fdaa7
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-load]summer.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[bg-load]winter.jpg b/songmanagement/game/themes/Deluxe/[bg-load]winter.jpg
new file mode 100644
index 00000000..826c22a7
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-load]winter.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[bg-main]blue.jpg b/songmanagement/game/themes/Deluxe/[bg-main]blue.jpg
new file mode 100644
index 00000000..376251a2
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-main]blue.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[bg-main]fall.jpg b/songmanagement/game/themes/Deluxe/[bg-main]fall.jpg
new file mode 100644
index 00000000..e4736d99
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-main]fall.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[bg-main]summer.jpg b/songmanagement/game/themes/Deluxe/[bg-main]summer.jpg
new file mode 100644
index 00000000..9939dfcd
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-main]summer.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[bg-main]winter.jpg b/songmanagement/game/themes/Deluxe/[bg-main]winter.jpg
new file mode 100644
index 00000000..75cefa82
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-main]winter.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[bg-video]_ocean.avi b/songmanagement/game/themes/Deluxe/[bg-video]_ocean.avi
new file mode 100644
index 00000000..357ddb21
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-video]_ocean.avi differ
diff --git a/songmanagement/game/themes/Deluxe/[bg-video]ribbon.mov b/songmanagement/game/themes/Deluxe/[bg-video]ribbon.mov
new file mode 100644
index 00000000..077ac35b
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[bg-video]ribbon.mov differ
diff --git a/songmanagement/game/themes/Deluxe/[button]13.png b/songmanagement/game/themes/Deluxe/[button]13.png
new file mode 100644
index 00000000..8e4694c4
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[button]13.png differ
diff --git a/songmanagement/game/themes/Deluxe/[button]alt.png b/songmanagement/game/themes/Deluxe/[button]alt.png
new file mode 100644
index 00000000..b3db5380
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[button]alt.png differ
diff --git a/songmanagement/game/themes/Deluxe/[button]az.png b/songmanagement/game/themes/Deluxe/[button]az.png
new file mode 100644
index 00000000..fe070495
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[button]az.png differ
diff --git a/songmanagement/game/themes/Deluxe/[button]enter.png b/songmanagement/game/themes/Deluxe/[button]enter.png
new file mode 100644
index 00000000..fcdb95ec
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[button]enter.png differ
diff --git a/songmanagement/game/themes/Deluxe/[button]esc.png b/songmanagement/game/themes/Deluxe/[button]esc.png
new file mode 100644
index 00000000..fdf025eb
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[button]esc.png differ
diff --git a/songmanagement/game/themes/Deluxe/[button]j.png b/songmanagement/game/themes/Deluxe/[button]j.png
new file mode 100644
index 00000000..5a2f2087
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[button]j.png differ
diff --git a/songmanagement/game/themes/Deluxe/[button]m.png b/songmanagement/game/themes/Deluxe/[button]m.png
new file mode 100644
index 00000000..97070b5f
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[button]m.png differ
diff --git a/songmanagement/game/themes/Deluxe/[button]navi.png b/songmanagement/game/themes/Deluxe/[button]navi.png
new file mode 100644
index 00000000..96f46860
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[button]navi.png differ
diff --git a/songmanagement/game/themes/Deluxe/[button]p.png b/songmanagement/game/themes/Deluxe/[button]p.png
new file mode 100644
index 00000000..e597ddda
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[button]p.png differ
diff --git a/songmanagement/game/themes/Deluxe/[effect]goldenNoteStar.png b/songmanagement/game/themes/Deluxe/[effect]goldenNoteStar.png
new file mode 100644
index 00000000..7bd6225f
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[effect]goldenNoteStar.png differ
diff --git a/songmanagement/game/themes/Deluxe/[effect]perfectNoteStar.png b/songmanagement/game/themes/Deluxe/[effect]perfectNoteStar.png
new file mode 100644
index 00000000..99132c39
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[effect]perfectNoteStar.png differ
diff --git a/songmanagement/game/themes/Deluxe/[helper]buttonFade.png b/songmanagement/game/themes/Deluxe/[helper]buttonFade.png
new file mode 100644
index 00000000..27a94c44
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[helper]buttonFade.png differ
diff --git a/songmanagement/game/themes/Deluxe/[helper]rectangle.jpg b/songmanagement/game/themes/Deluxe/[helper]rectangle.jpg
new file mode 100644
index 00000000..1521bdea
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[helper]rectangle.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]cd.png b/songmanagement/game/themes/Deluxe/[icon]cd.png
new file mode 100644
index 00000000..2633d235
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]cd.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]error.png b/songmanagement/game/themes/Deluxe/[icon]error.png
new file mode 100644
index 00000000..f952f3fa
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]error.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]main.png b/songmanagement/game/themes/Deluxe/[icon]main.png
new file mode 100644
index 00000000..f7d50067
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]main.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]options.png b/songmanagement/game/themes/Deluxe/[icon]options.png
new file mode 100644
index 00000000..9fac0bfd
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]options.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]party.png b/songmanagement/game/themes/Deluxe/[icon]party.png
new file mode 100644
index 00000000..e23230e3
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]party.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]question.png b/songmanagement/game/themes/Deluxe/[icon]question.png
new file mode 100644
index 00000000..a72a5c43
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]question.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]score.png b/songmanagement/game/themes/Deluxe/[icon]score.png
new file mode 100644
index 00000000..ccc3d8ff
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]score.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]song_menu.png b/songmanagement/game/themes/Deluxe/[icon]song_menu.png
new file mode 100644
index 00000000..acf69bfb
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]song_menu.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]song_search.png b/songmanagement/game/themes/Deluxe/[icon]song_search.png
new file mode 100644
index 00000000..f5190315
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]song_search.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]song_video.png b/songmanagement/game/themes/Deluxe/[icon]song_video.png
new file mode 100644
index 00000000..20170d5f
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]song_video.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]stats.png b/songmanagement/game/themes/Deluxe/[icon]stats.png
new file mode 100644
index 00000000..d8e5eac1
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]stats.png differ
diff --git a/songmanagement/game/themes/Deluxe/[icon]video.png b/songmanagement/game/themes/Deluxe/[icon]video.png
new file mode 100644
index 00000000..9bd65f86
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[icon]video.png differ
diff --git a/songmanagement/game/themes/Deluxe/[interface]cursor.png b/songmanagement/game/themes/Deluxe/[interface]cursor.png
new file mode 100644
index 00000000..0fe390f0
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[interface]cursor.png differ
diff --git a/songmanagement/game/themes/Deluxe/[interface]cursor_pressed.png b/songmanagement/game/themes/Deluxe/[interface]cursor_pressed.png
new file mode 100644
index 00000000..fa0056cc
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[interface]cursor_pressed.png differ
diff --git a/songmanagement/game/themes/Deluxe/[interface]dialog_background.png b/songmanagement/game/themes/Deluxe/[interface]dialog_background.png
new file mode 100644
index 00000000..ed032349
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[interface]dialog_background.png differ
diff --git a/songmanagement/game/themes/Deluxe/[interface]select_arrow_left.png b/songmanagement/game/themes/Deluxe/[interface]select_arrow_left.png
new file mode 100644
index 00000000..e4a32d2d
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[interface]select_arrow_left.png differ
diff --git a/songmanagement/game/themes/Deluxe/[interface]select_arrow_right.png b/songmanagement/game/themes/Deluxe/[interface]select_arrow_right.png
new file mode 100644
index 00000000..b2a29793
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[interface]select_arrow_right.png differ
diff --git a/songmanagement/game/themes/Deluxe/[interface]selectbg_search.png b/songmanagement/game/themes/Deluxe/[interface]selectbg_search.png
new file mode 100644
index 00000000..57d0ca88
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[interface]selectbg_search.png differ
diff --git a/songmanagement/game/themes/Deluxe/[main]button.png b/songmanagement/game/themes/Deluxe/[main]button.png
new file mode 100644
index 00000000..7d05462d
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[main]button.png differ
diff --git a/songmanagement/game/themes/Deluxe/[main]buttonf.jpg b/songmanagement/game/themes/Deluxe/[main]buttonf.jpg
new file mode 100644
index 00000000..d844add5
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[main]buttonf.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[main]mainBar.png b/songmanagement/game/themes/Deluxe/[main]mainBar.png
new file mode 100644
index 00000000..29239cb2
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[main]mainBar.png differ
diff --git a/songmanagement/game/themes/Deluxe/[main]playerNumberBox.png b/songmanagement/game/themes/Deluxe/[main]playerNumberBox.png
new file mode 100644
index 00000000..3336ef56
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[main]playerNumberBox.png differ
diff --git a/songmanagement/game/themes/Deluxe/[main]selectbg.png b/songmanagement/game/themes/Deluxe/[main]selectbg.png
new file mode 100644
index 00000000..f1b69eca
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[main]selectbg.png differ
diff --git a/songmanagement/game/themes/Deluxe/[main]songCover.jpg b/songmanagement/game/themes/Deluxe/[main]songCover.jpg
new file mode 100644
index 00000000..7cf8930b
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[main]songCover.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[main]songSelection1.png b/songmanagement/game/themes/Deluxe/[main]songSelection1.png
new file mode 100644
index 00000000..0dfd41e1
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[main]songSelection1.png differ
diff --git a/songmanagement/game/themes/Deluxe/[main]songSelection2.png b/songmanagement/game/themes/Deluxe/[main]songSelection2.png
new file mode 100644
index 00000000..bba4a451
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[main]songSelection2.png differ
diff --git a/songmanagement/game/themes/Deluxe/[menu]PopUpFg.png b/songmanagement/game/themes/Deluxe/[menu]PopUpFg.png
new file mode 100644
index 00000000..2c9785b4
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[menu]PopUpFg.png differ
diff --git a/songmanagement/game/themes/Deluxe/[menu]jumpToBg.png b/songmanagement/game/themes/Deluxe/[menu]jumpToBg.png
new file mode 100644
index 00000000..8e3a3a00
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[menu]jumpToBg.png differ
diff --git a/songmanagement/game/themes/Deluxe/[menu]songMenuBg.png b/songmanagement/game/themes/Deluxe/[menu]songMenuBg.png
new file mode 100644
index 00000000..92beff8e
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[menu]songMenuBg.png differ
diff --git a/songmanagement/game/themes/Deluxe/[menu]songMenuSelectBg.png b/songmanagement/game/themes/Deluxe/[menu]songMenuSelectBg.png
new file mode 100644
index 00000000..8ff5eef8
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[menu]songMenuSelectBg.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]Joker.png b/songmanagement/game/themes/Deluxe/[party]Joker.png
new file mode 100644
index 00000000..6f7c1208
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]Joker.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]playerButton.png b/songmanagement/game/themes/Deluxe/[party]playerButton.png
new file mode 100644
index 00000000..e1247e50
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]playerButton.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]playerTeamButton.png b/songmanagement/game/themes/Deluxe/[party]playerTeamButton.png
new file mode 100644
index 00000000..add685d0
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]playerTeamButton.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]playerselectbg.png b/songmanagement/game/themes/Deluxe/[party]playerselectbg.png
new file mode 100644
index 00000000..cc608229
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]playerselectbg.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]pointer.png b/songmanagement/game/themes/Deluxe/[party]pointer.png
new file mode 100644
index 00000000..2292d6c1
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]pointer.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]roundBG1.png b/songmanagement/game/themes/Deluxe/[party]roundBG1.png
new file mode 100644
index 00000000..64df6329
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]roundBG1.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]roundBG2.png b/songmanagement/game/themes/Deluxe/[party]roundBG2.png
new file mode 100644
index 00000000..a2780e2f
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]roundBG2.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]roundBG3.png b/songmanagement/game/themes/Deluxe/[party]roundBG3.png
new file mode 100644
index 00000000..7a1d02d9
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]roundBG3.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]roundBG4.png b/songmanagement/game/themes/Deluxe/[party]roundBG4.png
new file mode 100644
index 00000000..81ccfd8e
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]roundBG4.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]roundTeamButton.png b/songmanagement/game/themes/Deluxe/[party]roundTeamButton.png
new file mode 100644
index 00000000..f31d4296
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]roundTeamButton.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]scoreBG1.png b/songmanagement/game/themes/Deluxe/[party]scoreBG1.png
new file mode 100644
index 00000000..28496bcf
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]scoreBG1.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]scoreBG2.png b/songmanagement/game/themes/Deluxe/[party]scoreBG2.png
new file mode 100644
index 00000000..e6417915
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]scoreBG2.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]scoreDecoration.png b/songmanagement/game/themes/Deluxe/[party]scoreDecoration.png
new file mode 100644
index 00000000..388077e6
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]scoreDecoration.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]teamPoints.png b/songmanagement/game/themes/Deluxe/[party]teamPoints.png
new file mode 100644
index 00000000..83c4f7a8
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]teamPoints.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]winDecoration.png b/songmanagement/game/themes/Deluxe/[party]winDecoration.png
new file mode 100644
index 00000000..f84dbc8a
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]winDecoration.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]winTeamButton1.png b/songmanagement/game/themes/Deluxe/[party]winTeamButton1.png
new file mode 100644
index 00000000..9e7dba31
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]winTeamButton1.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]winTeamButton2.png b/songmanagement/game/themes/Deluxe/[party]winTeamButton2.png
new file mode 100644
index 00000000..229dbbd3
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]winTeamButton2.png differ
diff --git a/songmanagement/game/themes/Deluxe/[party]winTeamButton3.png b/songmanagement/game/themes/Deluxe/[party]winTeamButton3.png
new file mode 100644
index 00000000..53bc487a
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[party]winTeamButton3.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]Line.png b/songmanagement/game/themes/Deluxe/[score]Line.png
new file mode 100644
index 00000000..954caf94
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]Line.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]bar_box_dark.png b/songmanagement/game/themes/Deluxe/[score]bar_box_dark.png
new file mode 100644
index 00000000..e4fbfa41
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]bar_box_dark.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]bar_box_light.png b/songmanagement/game/themes/Deluxe/[score]bar_box_light.png
new file mode 100644
index 00000000..ddc17ed8
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]bar_box_light.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]bar_box_lightest.png b/songmanagement/game/themes/Deluxe/[score]bar_box_lightest.png
new file mode 100644
index 00000000..995bb9ef
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]bar_box_lightest.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]box.png b/songmanagement/game/themes/Deluxe/[score]box.png
new file mode 100644
index 00000000..71a0cee6
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]box.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]endcap.png b/songmanagement/game/themes/Deluxe/[score]endcap.png
new file mode 100644
index 00000000..3cccd2e1
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]endcap.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]glass_box.png b/songmanagement/game/themes/Deluxe/[score]glass_box.png
new file mode 100644
index 00000000..c0cf2a9c
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]glass_box.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]level.png b/songmanagement/game/themes/Deluxe/[score]level.png
new file mode 100644
index 00000000..1f627560
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]level.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]levelRound.png b/songmanagement/game/themes/Deluxe/[score]levelRound.png
new file mode 100644
index 00000000..2bc7a6b8
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]levelRound.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]level_dark.png b/songmanagement/game/themes/Deluxe/[score]level_dark.png
new file mode 100644
index 00000000..da4fd407
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]level_dark.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]level_dark_round.png b/songmanagement/game/themes/Deluxe/[score]level_dark_round.png
new file mode 100644
index 00000000..de239cb2
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]level_dark_round.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]level_light.png b/songmanagement/game/themes/Deluxe/[score]level_light.png
new file mode 100644
index 00000000..1c1c8a4d
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]level_light.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]level_light_round.png b/songmanagement/game/themes/Deluxe/[score]level_light_round.png
new file mode 100644
index 00000000..641151a5
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]level_light_round.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]level_lightest.png b/songmanagement/game/themes/Deluxe/[score]level_lightest.png
new file mode 100644
index 00000000..f02fdf7b
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]level_lightest.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]level_lightest_round.png b/songmanagement/game/themes/Deluxe/[score]level_lightest_round.png
new file mode 100644
index 00000000..9f1bb09e
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]level_lightest_round.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]rating_0.png b/songmanagement/game/themes/Deluxe/[score]rating_0.png
new file mode 100644
index 00000000..7e836b99
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]rating_0.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]rating_1.png b/songmanagement/game/themes/Deluxe/[score]rating_1.png
new file mode 100644
index 00000000..556821cb
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]rating_1.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]rating_2.png b/songmanagement/game/themes/Deluxe/[score]rating_2.png
new file mode 100644
index 00000000..ffa23fd3
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]rating_2.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]rating_3.png b/songmanagement/game/themes/Deluxe/[score]rating_3.png
new file mode 100644
index 00000000..5204dc5f
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]rating_3.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]rating_4.png b/songmanagement/game/themes/Deluxe/[score]rating_4.png
new file mode 100644
index 00000000..f5d7267c
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]rating_4.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]rating_5.png b/songmanagement/game/themes/Deluxe/[score]rating_5.png
new file mode 100644
index 00000000..0f6a553b
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]rating_5.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]rating_6.png b/songmanagement/game/themes/Deluxe/[score]rating_6.png
new file mode 100644
index 00000000..e8127c85
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]rating_6.png differ
diff --git a/songmanagement/game/themes/Deluxe/[score]rating_7.png b/songmanagement/game/themes/Deluxe/[score]rating_7.png
new file mode 100644
index 00000000..6b1d30f5
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[score]rating_7.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player1]lyric_active.png b/songmanagement/game/themes/Deluxe/[sing.player1]lyric_active.png
new file mode 100644
index 00000000..089c8c5e
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player1]lyric_active.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player1]lyric_inactive.png b/songmanagement/game/themes/Deluxe/[sing.player1]lyric_inactive.png
new file mode 100644
index 00000000..a349007d
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player1]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player2]lyric_active.png b/songmanagement/game/themes/Deluxe/[sing.player2]lyric_active.png
new file mode 100644
index 00000000..509767fa
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player2]lyric_active.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player2]lyric_inactive.png b/songmanagement/game/themes/Deluxe/[sing.player2]lyric_inactive.png
new file mode 100644
index 00000000..ac40ec61
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player2]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player3]lyric_active.png b/songmanagement/game/themes/Deluxe/[sing.player3]lyric_active.png
new file mode 100644
index 00000000..7b130ac5
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player3]lyric_active.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player3]lyric_inactive.png b/songmanagement/game/themes/Deluxe/[sing.player3]lyric_inactive.png
new file mode 100644
index 00000000..c5a00600
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player3]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player4]lyric_active.png b/songmanagement/game/themes/Deluxe/[sing.player4]lyric_active.png
new file mode 100644
index 00000000..993041fd
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player4]lyric_active.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player4]lyric_inactive.png b/songmanagement/game/themes/Deluxe/[sing.player4]lyric_inactive.png
new file mode 100644
index 00000000..f09669b2
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player4]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player5]lyric_active.png b/songmanagement/game/themes/Deluxe/[sing.player5]lyric_active.png
new file mode 100644
index 00000000..631dc9c3
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player5]lyric_active.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player5]lyric_inactive.png b/songmanagement/game/themes/Deluxe/[sing.player5]lyric_inactive.png
new file mode 100644
index 00000000..716071e8
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player5]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player6]lyric_active.png b/songmanagement/game/themes/Deluxe/[sing.player6]lyric_active.png
new file mode 100644
index 00000000..65133d03
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player6]lyric_active.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing.player6]lyric_inactive.png b/songmanagement/game/themes/Deluxe/[sing.player6]lyric_inactive.png
new file mode 100644
index 00000000..0c5f34d3
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing.player6]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]LyricsBall.png b/songmanagement/game/themes/Deluxe/[sing]LyricsBall.png
new file mode 100644
index 00000000..aa4401dd
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]LyricsBall.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]lineBonusPopUp.png b/songmanagement/game/themes/Deluxe/[sing]lineBonusPopUp.png
new file mode 100644
index 00000000..c7bd0a41
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]lineBonusPopUp.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]lyricsHelpBar.png b/songmanagement/game/themes/Deluxe/[sing]lyricsHelpBar.png
new file mode 100644
index 00000000..59707c21
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]lyricsHelpBar.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]notesBgLeft.png b/songmanagement/game/themes/Deluxe/[sing]notesBgLeft.png
new file mode 100644
index 00000000..9fe2621c
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]notesBgLeft.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]notesBgMid.png b/songmanagement/game/themes/Deluxe/[sing]notesBgMid.png
new file mode 100644
index 00000000..612da5d3
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]notesBgMid.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]notesBgRight.png b/songmanagement/game/themes/Deluxe/[sing]notesBgRight.png
new file mode 100644
index 00000000..a6f42c33
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]notesBgRight.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]notesLeft.png b/songmanagement/game/themes/Deluxe/[sing]notesLeft.png
new file mode 100644
index 00000000..3a404b9c
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]notesLeft.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]notesMid.png b/songmanagement/game/themes/Deluxe/[sing]notesMid.png
new file mode 100644
index 00000000..8769d01a
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]notesMid.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]notesPlainLeft.png b/songmanagement/game/themes/Deluxe/[sing]notesPlainLeft.png
new file mode 100644
index 00000000..1a94a9d8
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]notesPlainLeft.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]notesPlainMid.png b/songmanagement/game/themes/Deluxe/[sing]notesPlainMid.png
new file mode 100644
index 00000000..7fc64282
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]notesPlainMid.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]notesPlainRight.png b/songmanagement/game/themes/Deluxe/[sing]notesPlainRight.png
new file mode 100644
index 00000000..ff8bb502
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]notesPlainRight.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]notesRight.png b/songmanagement/game/themes/Deluxe/[sing]notesRight.png
new file mode 100644
index 00000000..8dc40cc8
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]notesRight.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]p.png b/songmanagement/game/themes/Deluxe/[sing]p.png
new file mode 100644
index 00000000..7458d8e5
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]p.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]pause.png b/songmanagement/game/themes/Deluxe/[sing]pause.png
new file mode 100644
index 00000000..f5ab158c
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]pause.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]scoreBg.jpg b/songmanagement/game/themes/Deluxe/[sing]scoreBg.jpg
new file mode 100644
index 00000000..4a4459f6
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]scoreBg.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]scoreBg.png b/songmanagement/game/themes/Deluxe/[sing]scoreBg.png
new file mode 100644
index 00000000..db6ba67f
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]scoreBg.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]singBarBack.png b/songmanagement/game/themes/Deluxe/[sing]singBarBack.png
new file mode 100644
index 00000000..14d2ba42
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]singBarBack.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]singBarBar.jpg b/songmanagement/game/themes/Deluxe/[sing]singBarBar.jpg
new file mode 100644
index 00000000..4fd9bde9
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]singBarBar.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]singBarBar.png b/songmanagement/game/themes/Deluxe/[sing]singBarBar.png
new file mode 100644
index 00000000..9c57057b
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]singBarBar.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]singBarFront.png b/songmanagement/game/themes/Deluxe/[sing]singBarFront.png
new file mode 100644
index 00000000..42477c5a
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]singBarFront.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]textBar.png b/songmanagement/game/themes/Deluxe/[sing]textBar.png
new file mode 100644
index 00000000..d2069235
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]textBar.png differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]timeBar.jpg b/songmanagement/game/themes/Deluxe/[sing]timeBar.jpg
new file mode 100644
index 00000000..cc5cb552
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]timeBar.jpg differ
diff --git a/songmanagement/game/themes/Deluxe/[sing]timeBarBG.png b/songmanagement/game/themes/Deluxe/[sing]timeBarBG.png
new file mode 100644
index 00000000..6094fdf3
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[sing]timeBarBG.png differ
diff --git a/songmanagement/game/themes/Deluxe/[special]bar1.png b/songmanagement/game/themes/Deluxe/[special]bar1.png
new file mode 100644
index 00000000..00afb41d
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[special]bar1.png differ
diff --git a/songmanagement/game/themes/Deluxe/[special]bar2.png b/songmanagement/game/themes/Deluxe/[special]bar2.png
new file mode 100644
index 00000000..c828a8e1
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[special]bar2.png differ
diff --git a/songmanagement/game/themes/Deluxe/[special]bg_fade.png b/songmanagement/game/themes/Deluxe/[special]bg_fade.png
new file mode 100644
index 00000000..dc3248ef
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[special]bg_fade.png differ
diff --git a/songmanagement/game/themes/Deluxe/[stat]detailBG1.png b/songmanagement/game/themes/Deluxe/[stat]detailBG1.png
new file mode 100644
index 00000000..8abdcfec
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[stat]detailBG1.png differ
diff --git a/songmanagement/game/themes/Deluxe/[stat]mainBG1.png b/songmanagement/game/themes/Deluxe/[stat]mainBG1.png
new file mode 100644
index 00000000..3f5a4190
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[stat]mainBG1.png differ
diff --git a/songmanagement/game/themes/Deluxe/[stat]mainBG2.png b/songmanagement/game/themes/Deluxe/[stat]mainBG2.png
new file mode 100644
index 00000000..b88ecaf8
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[stat]mainBG2.png differ
diff --git a/songmanagement/game/themes/Deluxe/[stat]mainBG3.png b/songmanagement/game/themes/Deluxe/[stat]mainBG3.png
new file mode 100644
index 00000000..28c39392
Binary files /dev/null and b/songmanagement/game/themes/Deluxe/[stat]mainBG3.png differ
diff --git a/songmanagement/game/themes/Temptation.ini b/songmanagement/game/themes/Temptation.ini
new file mode 100755
index 00000000..663ac299
--- /dev/null
+++ b/songmanagement/game/themes/Temptation.ini
@@ -0,0 +1,8815 @@
+;1.10
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Theme]
+Name = Temptation
+Creator = Charis
+US_Version = USD 110
+DefaultSkin = Temptation (16-9)
+
+[Colors]
+White = 255 255 255
+LightBlue = 119 187 210
+DarkBlue = 28 126 171
+LightRed = 170 146 146
+DarkRed = 155 113 113
+LightGreen = 136 168 136
+DarkGreen = 106 152 104
+LightPurple = 155 136 168
+DarkPurple = 145 104 152
+LightOrange = 168 155 136
+DarkOrange = 151 131 76
+LightYellow = 168 168 136
+DarkYellow = 150 151 76
+Turkis = 13 186 167
+GrayLightest = 223 223 223
+GrayLight = 191 191 191
+Gray = 127 127 127
+GrayDark = 63 63 63
+Black = 0 0 0
+GrayPopup = 51 51 51
+Gold = 255 223 31
+Silver = 223 223 223
+Bronze = 205 127 50
+Red = 255 0 0
+
+[Loading]
+[LoadingBackground]
+Tex = LoadingBG
+Color = DarkRed
+Type = Colorized
+
+[LoadingStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[LoadingStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Z = 0.4
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LoadingText1]
+X = 200
+Y = 455
+Color = White
+Font = 0
+Align = 0
+Size = 24
+Text = SING_LOADING
+Reflection = 0
+ReflectionSpacing = 13
+
+[LoadingText2]
+X = 575
+Y = 455
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = US_VERSION
+Reflection = 0
+ReflectionSpacing = 13
+
+[Main]
+[MainBackground]
+Tex = TitleBG
+
+[MainStatic1]
+X = 65
+Y = 601
+W = 1
+H = 1
+Tex = MainIcon
+Color = White
+Type = Transparent
+
+[MainText1]
+X = 95
+Y = 186
+Color = White
+Font = 0
+Size = 0
+Align = 0
+Text = SING_MENU
+
+[MainTextDescriptionLong]
+X = 400
+Y = 445
+Color = White
+Font = 0
+Size = 30
+Align = 1
+Text =
+
+[MainStatic2]
+X = 0
+Y = 601
+W = 250
+H = 1
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 0
+ReflectionSpacing = 0
+
+[MainStatic3]
+X = 250
+Y = 601
+W = 550
+H = 1
+Z = 0.4
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainStatic4]
+X = 260
+Y = 601
+W = 32
+H = 1
+Z = 0.5
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainText2]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Font = 0
+Size = 0
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[MainStatic5]
+X = 406010
+Y = 545
+W = 32
+H = 1
+Z = 0.5
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainText3]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Font = 0
+Size = 0
+Align = 0
+Text = SING_LEGEND_SELECT
+Reflection = 1
+ReflectionSpacing = 13
+
+[MainButtonSolo]
+X = 145
+Y = 510
+W = 64
+H = 64
+Tex = ButtonSolo
+Color = White
+DColor = White
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 0
+Fade = 1
+FadeText = 1
+SelectH = 48
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[MainButtonSoloText1]
+X = 75
+Y = 10
+Font = 0
+Size = 0
+Align = 1
+Text = SING_SING
+Color = White
+
+[MainButtonMulti]
+X = 240
+Y = 505
+W = 64
+H = 64
+Tex = ButtonParty
+Color = White
+DColor = White
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 0
+Fade = 1
+FadeText = 1
+SelectH = 48
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[MainButtonMultiText1]
+X = 75
+Y = 10
+Font = 0
+Size = 0
+Align = 1
+Text = SING_MULTI
+Color = White
+
+[MainButtonStats]
+X = 335
+Y = 500
+W = 64
+H = 64
+Tex = ButtonStats
+Color = White
+DColor = White
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 0
+Fade = 1
+FadeText = 1
+SelectH = 48
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[MainButtonStatsText1]
+X = 70
+Y = 3
+Font = 0
+Size = 0
+Align = 1
+Text = SING_STATS
+Color = White
+
+[MainButtonEditor]
+X = 430
+Y = 500
+W = 64
+H = 64
+Tex = ButtonEdit
+Color = White
+DColor = White
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 0
+Fade = 1
+FadeText = 1
+SelectH = 48
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[MainButtonEditorText1]
+X = 70
+Y = 3
+Font = 0
+Size = 0
+Align = 1
+Text = SING_EDITOR
+Color = White
+
+[MainButtonOptions]
+X = 515
+Y = 505
+W = 64
+H = 64
+Tex = ButtonOption
+Color = White
+DColor = White
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 0
+Fade = 1
+FadeText = 1
+SelectH = 48
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[MainButtonOptionsText1]
+X = 70
+Y = 3
+Font = 0
+Size = 0
+Align = 1
+Text = SING_OPTIONS
+Color = White
+
+[MainButtonExit]
+X = 610
+Y = 510
+W = 64
+H = 64
+Tex = ButtonExit
+Color = White
+DColor = White
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 0
+Fade = 1
+FadeText = 1
+SelectH = 48
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[MainButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 0
+Align = 1
+Text = SING_EXIT
+Color = White
+
+[Song]
+
+[SongBackground]
+Tex = SongBG
+
+[SongStaticNonParty1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = SongCD
+Type = Colorized
+
+[SongTextCat]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_SONG_SELECTION_DESC
+
+[SongStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Z = 0.951
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongCover]
+X = 300
+Y = 170
+W = 325
+H = 200
+Reflections = 1
+Style=5
+
+[SongEqualizer]
+Visible = 1
+Direction = 1
+Color = White
+Alpha = 1
+X = 50
+Y = 502
+PieceW = 4
+PieceH = 4
+Space = 1
+Bands = 20
+Length = 18
+Reflection = 1
+ReflectionSpacing = 1
+
+[SongVideoIcon]
+X = 715
+Y = 425
+W = 32
+H = 32
+Z = 0.95
+Color = White
+Tex = icon_song_video
+Type = Transparent
+Reflection = 0
+ReflectionSpacing = 1
+
+[SongStatic3]
+X = 247
+Y = 158
+W = 306
+H = 224
+Z = 0.95
+Color = ColorLight
+Tex = SongSelection1
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 1
+
+[SongStatic4]
+X = 300
+Y = 320
+W = 200
+H = 160
+Z = 0.95
+Color = ColorLight
+Tex = SongSelection2
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextArtist]
+X = 400
+Y = 420
+W = 500
+Color = White
+Font = 1
+Size = 40
+Align = 1
+Text =
+
+[SongTextTitle]
+X = 400
+Y = 472
+W = 500
+Color = White
+Font = 0
+Size = 40
+Align = 1
+Text =
+Reflection = 0
+ReflectionSpacing = 1
+[SongTextNumber]
+X = 750
+Y = 477
+Z = 0.95
+Color = White
+Size = 40
+Align = 2
+Reflection = 1
+ReflectionSpacing = 0
+
+#Variable statics and texts for song-screen in sing- and partymode
+# There can be an unlimited Number of Statics and Texts, As long
+# as the numbers are in order.
+# Statics that are shown in PartyMode Only are Named_
+#        SongStaticParty[No]
+# Texts that are shown in PartyMode Only are Named_
+#        SongTextParty[No]
+# Statics that are shown in Normal Mode Only are Named_
+#        SongStaticNonParty[No]
+# Texts that are shown in Normal Mode Only are Named_
+#        SongTextNonParty[No]
+#Here are the ones for singmode
+
+[SongTextNonParty1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_SONG_SELECTION
+
+# NAVBAR #########################
+# Jump to a letter with [ALT] + [A..Z]
+[SongStaticNonParty2]
+X = 260
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAlt
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty2]
+X = 292
+Y = 548
+Z = 0.952
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = +
+Reflection = 1
+ReflectionSpacing = 13
+
+[SongStaticNonParty3]
+X = 300
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty3]
+X = 340
+Y = 548
+Z = 0.952
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_GOTO
+Reflection = 1
+ReflectionSpacing = 13
+
+# Menu opens with [M]
+[SongStaticNonParty4]
+X = 425
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonM
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty4]
+X = 465
+Y = 548
+Z = 0.952
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_MENU
+Reflection = 1
+ReflectionSpacing = 13
+
+# The so famous search, shown with [J]
+[SongStaticNonParty5]
+X = 515
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonJ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty5]
+X = 555
+Y = 548
+Z = 0.952
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SONG_JUMPTO_DESC
+Reflection = 1
+ReflectionSpacing = 13
+
+# [P]laylist
+[SongStaticNonParty6]
+X = 680
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonP
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty6]
+X = 720
+Y = 548
+Z = 0.952
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_PLAYLIST
+Reflection = 1
+ReflectionSpacing = 13
+
+#and these are the ones for partymode
+[SongStaticParty1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+# NAVBAR for party
+# enter a number
+[SongStaticParty2]
+X = 252
+Y = 544
+Z = 0.952
+W = 32
+H = 30
+Tex = Button13
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextParty3]
+X = 288
+Y = 548
+Z = 0.952
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SONG_MENU_NAME_PARTY_JOKER
+Reflection = 1
+ReflectionSpacing = 13
+
+# menu
+[SongStaticParty3]
+X = 442
+Y = 544
+Z = 0.952
+W = 32
+H = 32
+Tex = ButtonM
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextParty4]
+X = 482
+Y = 548
+Z = 0.952
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_MENU
+Reflection = 1
+ReflectionSpacing = 13
+
+[SongStaticParty4]
+X = 632
+Y = 544
+Z = 0.952
+W = 32
+H = 32
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextParty5]
+X = 670
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+#Texts for Party Mode
+[SongTextParty1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[SongTextParty2]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_WHEREAMI
+#variable statics end
+
+# Jokers, 5 for each team, only shown in party Mode
+[SongStaticTeam1Joker1]
+Tex = Joker
+X = 55
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker2]
+Tex = Joker
+X = 70
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker3]
+Tex = Joker
+X = 85
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker4]
+Tex = Joker
+X = 100
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker5]
+Tex = Joker
+X = 115
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P1Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker1]
+Tex = Joker
+X = 145
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker2]
+Tex = Joker
+X = 160
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker3]
+Tex = Joker
+X = 175
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker4]
+Tex = Joker
+X = 190
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker5]
+Tex = Joker
+X = 205
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P2Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker1]
+Tex = Joker
+X = 235
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker2]
+Tex = Joker
+X = 250
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker3]
+Tex = Joker
+X = 265
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker4]
+Tex = Joker
+X = 280
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker5]
+Tex = Joker
+X = 295
+Y = 110
+W = 10
+H = 10
+Z = 0.98
+Color = P3Dark
+Type = Colorized
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+
+[Sing]
+Texts = 1
+
+[SingBackground]
+Type=color
+ColR=1
+ColB=1
+ColG=1
+
+[SingText1]
+Text = SING_TIME
+X = 43
+Y = 577
+Font = 1
+Size = 18
+Color = White
+Align = 1
+
+[SingStatic1]
+;TextBG
+Tex = LyricBar
+X = 10
+Y = 492
+W = 780
+H = 85
+Color = White
+Type = Transparent
+
+[SingStatic2]
+;TimeBar
+Tex = TimeBar1
+X = 10
+Y = 577
+W = 780
+H = 20
+Color = White
+Type = Transparent
+
+[SingTimeProgress]
+X = 87
+Y = 584
+W = 633
+H = 6
+Color = White
+
+[SingTimeText]
+Text = SING_TIME
+X = 761
+Y = 577
+Font = 1
+Size = 18
+Color = White
+Align = 1
+
+# O N E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#PlayerOne
+[SingP1Static]
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P1Dark
+Type = Colorized
+
+[SingP1Text]
+Text = P1
+X = 25
+Y = 302
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP1Static2]
+Tex = ScoreBG
+X = 680
+Y = 282
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1TextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1SingBar]
+X = 680
+Y = 316
+W = 100
+H = 8
+
+# T W O  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1TwoPStatic]
+Tex = P
+X = 20
+Y = 117
+W = 30
+H = 28
+Color = P1Dark
+Type = Colorized
+
+[SingP1TwoPText]
+Text = P1
+X = 25
+Y = 122
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP1TwoPStatic2]
+Tex = ScoreBG
+X = 680
+Y = 102
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1TwoPTextScore]
+Text = 00000
+X = 698
+Y = 104
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1TwoPSingBar]
+X = 680
+Y = 136
+W = 100
+H = 8
+
+#Player Two
+[SingP2RStatic]
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P2Dark
+Type = Colorized
+
+[SingP2RText]
+Text = P2
+X = 24
+Y = 302
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP2RStatic2]
+Tex = ScoreBG
+X = 680
+Y = 282
+W = 100
+H = 36
+Color = P2Dark
+Type = Colorized
+
+[SingP2RTextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2RSingBar]
+X = 680
+Y = 316
+W = 100
+H = 8
+
+# T H R E E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1ThreePStatic]
+Tex = P
+X = 16
+Y = 59
+W = 50
+H = 44
+Color = P1Dark
+Type = Colorized
+
+[SingP1ThreePText]
+Text = P1
+X = 27
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP1ThreePStatic2]
+Tex = ScoreBG
+X = 75
+Y = 61
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1ThreePTextScore]
+Text = 00000
+X = 93
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1ThreePSingBar]
+X = 75
+Y = 95
+W = 100
+H = 8
+
+#Player Two
+[SingP2MStatic]
+Tex = P
+X = 311
+Y = 59
+W = 50
+H = 44
+Color = P2Dark
+Type = Colorized
+
+[SingP2MText]
+Text = P2
+X = 321
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP2MStatic2]
+Tex = ScoreBG
+X = 370
+Y = 61
+W = 100
+H = 36
+Color = P2Dark
+Type = Colorized
+
+[SingP2MTextScore]
+Text = 00000
+X = 388
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2MSingBar]
+X = 370
+Y = 95
+W = 100
+H = 8
+
+#Player Three
+[SingP3RStatic]
+Tex = P
+X = 611
+Y = 59
+W = 50
+H = 44
+Color = P3Dark
+Type = Colorized
+
+[SingP3RText]
+Text = P3
+X = 621
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP3RStatic2]
+Tex = ScoreBG
+X = 670
+Y = 61
+W = 100
+H = 36
+Color = P3Dark
+Type = Colorized
+
+[SingP3RTextScore]
+Text = 00000
+X = 688
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP3SingBar]
+X = 670
+Y = 95
+W = 100
+H = 8
+
+[Score]
+Texts = 1
+
+[ScoreBackground]
+Tex = ScoreScreenBG
+
+[ScoreText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SONG_SCORE
+
+[ScoreTextArtistTitle]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = ArtistTitle
+
+[ScoreStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = ScoreIcon
+Type = Colorized
+
+[ScoreStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreText2]
+X = 300
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+#end of main stuff
+
+# # # # # # # # # # # # # # # # # # One Player Score # # # # # # # # # # # #
+[ScoreTextName1]
+X = 197
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = White
+Align = 0
+
+# Rating
+[ScoreStaticRatingPicture1]
+X = 385
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore1]
+X = 422
+Y = 235
+width = 100
+Color = White
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+# Note Score
+[ScoreStaticBoxDark1]
+Tex = ScoreBar_box_dark
+X = 200
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes1]
+X = 227
+Y = 322
+Color = White
+Font = 0
+Size = 30
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore1]
+X = 487
+Y = 322
+Color = White
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static1]
+Tex = ScoreLine
+X = 200
+Y = 351
+W = 287
+H = 1
+Color = White
+Type = Colorized
+
+# Line Bonus
+[ScoreStaticBoxLight1]
+Tex = ScoreBar_box_light
+X = 200
+Y = 358
+W = 22
+H = 20
+Color = P1Light
+Type = Colorized
+
+[ScoreTextLineBonus1]
+X = 227
+Y = 352
+Color = White
+Font = 0
+Size = 30
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore1]
+X = 487
+Y = 352
+Color = White
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static2]
+Tex = ScoreLine
+X = 200
+Y = 382
+W = 287
+H = 1
+Color = White
+Type = Colorized
+
+# Golden Notes
+[ScoreStaticBoxLightest1]
+Tex = ScoreBar_box_lightest
+X = 200
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes1]
+X = 227
+Y = 383
+Color = White
+Font = 0
+Size = 30
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore1]
+X = 487
+Y = 383
+Color = White
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+#Total Score
+[ScoreStaticPlayerIdBox1]
+Tex = PlayerIDBox01
+X = 200
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+Reflection = 1
+ReflectionSpacing = 31
+
+[ScoreTextTotal1]
+X = 237
+Y = 454
+Color = White
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 0
+Reflection = 1
+ReflectionSpacing = 26
+
+[ScoreTextTotalSCore1]
+X = 487
+Y = 444
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 0
+Reflection = 1
+ReflectionSpacing = 24
+
+#ScoreBar
+[ScoreStaticBackLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 168
+W = 95
+H = 310
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound1]
+Tex = ScoreLevelRound
+X = 503
+Y = 138
+W = 95
+H = 8
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 400
+W = 95
+H = 10
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound1]
+Tex = ScoreLevelRound
+X = 503
+Y = 392
+W = 95
+H = 8
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer1Static3]
+Tex = ScoreEndCap
+X = 499
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 0
+
+[ScorePlayer1Static4]
+Tex = ScoreGlassBox
+X = 499
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# # # # # # # # # # # # # # # # # # Two Player Score # # # # # # # # # # # #
+# P L A Y E R   O N E
+[ScoreTextName2]
+X = 42
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = White
+Align = 0
+
+[ScoreStaticRatingPicture2]
+X = 180
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore2]
+X = 217
+Y = 235
+Width = 100
+Color = White
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark2]
+Tex = ScoreBar_box_dark
+X = 45
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes2]
+X = 72
+Y = 324
+Color = White
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore2]
+X = 282
+Y = 324
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLight2]
+Tex = ScoreBar_box_light
+X = 45
+Y = 358
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextLineBonus2]
+X = 72
+Y = 355
+Color = White
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore2]
+X = 282
+Y = 355
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLightest2]
+Tex = ScoreBar_box_lightest
+X = 45
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes2]
+X = 72
+Y = 387
+Color = White
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore2]
+X = 282
+Y = 387
+Color = White
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreTextTotal2]
+X = 82
+Y = 454
+Color = White
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Reflection = 1
+ReflectionSpacing = 24
+
+[ScoreTextTotalSCore2]
+X = 283
+Y = 444
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Reflection = 1
+ReflectionSpacing = 24
+
+# Lines
+[ScorePlayer2Static1]
+Tex = ScoreLine
+X = 45
+Y = 351
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScorePlayer2Static2]
+Tex = ScoreLine
+X = 45
+Y = 382
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScoreStaticPlayerIdBox2]
+Tex = PlayerIDBox01
+X = 45
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+Reflection = 1
+ReflectionSpacing = 31
+
+#ScoreBar
+[ScoreStaticBackLevel2]
+Tex = ScoreLevel
+X = 298
+Y = 168
+W = 95
+H = 310
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound2]
+Tex = ScoreLevelRound
+X = 298
+Y = 138
+W = 95
+H = 8
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel2]
+Tex = ScoreLevel
+X = 298
+Y = 400
+W = 95
+H = 10
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound2]
+Tex = ScoreLevelRound
+X = 298
+Y = 392
+W = 95
+H = 8
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer2Static3]
+Tex = ScoreEndCap
+X = 294
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 0
+
+[ScorePlayer2Static4]
+Tex = ScoreGlassBox
+X = 294
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# P L A Y E R   T W O
+[ScoreTextName3]
+X = 758
+Y = 290
+Font = 0
+Size = 30
+Text = P2
+Color = White
+Align = 2
+
+[ScoreStaticRatingPicture3]
+X = 545
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore3]
+X = 583
+Y = 235
+width = 100
+Color = White
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark3]
+Tex = ScoreBar_box_dark
+X = 733
+Y = 327
+W = 22
+H = 20
+Color = P2Dark
+Type = Colorized
+
+[ScoreTextNotes3]
+X = 728
+Y = 324
+Color = White
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 2
+
+[ScoreTextNotesScore3]
+X = 518
+Y = 324
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLight3]
+Tex = ScoreBar_box_light
+X = 733
+Y = 358
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextLineBonus3]
+X = 728
+Y = 355
+Color = White
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 2
+
+[ScoreTextLineBonusScore3]
+X = 518
+Y = 355
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLightest3]
+Tex = ScoreBar_box_lightest
+X = 733
+Y = 390
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes3]
+X = 728
+Y = 387
+Color = White
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 2
+
+[ScoreTextGoldenNotesScore3]
+X = 518
+Y = 387
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreTextTotal3]
+X = 718
+Y = 454
+Color = White
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 2
+Reflection = 1
+ReflectionSpacing = 24
+
+[ScoreTextTotalScore3]
+X = 517
+Y = 444
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 00000
+Reflection = 1
+ReflectionSpacing = 24
+
+#Lines
+[ScorePlayer3Static1]
+Tex = ScoreLine
+X = 518
+Y = 351
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScorePlayer3Static2]
+Tex = ScoreLine
+X = 518
+Y = 382
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScoreStaticPlayerIdBox3]
+Tex = PlayerIDBox02
+X = 729
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+Reflection = 1
+ReflectionSpacing = 31
+
+#ScoreBar
+[ScoreStaticBackLevel3]
+Tex = ScoreLevel
+X = 409
+Y = 168
+W = 95
+H = 310
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound3]
+Tex = ScoreLevelRound
+X = 409
+Y = 138
+W = 95
+H = 8
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticLevel3]
+Tex = ScoreLevel
+X = 409
+Y = 400
+W = 95
+H = 10
+Color = P2Dark
+Type = Colorized
+
+[ScoreStaticLevelRound3]
+Tex = ScoreLevelRound
+X = 409
+Y = 392
+W = 95
+H = 8
+Color = P2Dark
+Type = Colorized
+
+[ScorePlayer3Static3]
+Tex = ScoreEndCap
+X = 405
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 0
+
+[ScorePlayer3Static4]
+Tex = ScoreGlassBox
+X = 405
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# # # # # # # # # # # # # # # # # # Three Player Score # # # # # # # # # # # #
+# P L A Y E R  O N E
+[ScoreTextName4]
+X = 20
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P1
+Color = White
+
+# Rating
+[ScoreStaticRatingPicture4]
+X = 200
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes4]
+X = 20
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = White
+
+[ScoreTextNotesScore4]
+X = 260
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextLineBonus4]
+X = 20
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = White
+
+[ScoreTextLineBonusScore4]
+X = 260
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextGoldenNotes4]
+X = 20
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = White
+
+[ScoreTextGoldenNotesScore4]
+X = 260
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextScore4]
+X = 20
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = White
+
+[ScoreTextTotal4]
+X = 47
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = White
+Reflection = 1
+ReflectionSpacing = -1
+
+[ScoreTextTotalScore4]
+X = 260
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = White
+Reflection = 1
+ReflectionSpacing = -3
+
+[ScoreStaticBoxDark4]
+Tex = PlayerNumberBox
+X = 20
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P1Dark
+Z = 0.9
+Reflection = 1
+ReflectionSpacing = 4
+
+[ScorePlayer4Text1]
+X = 24
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = White
+Font = 1
+Size = 15
+Align = 0
+Text = P1
+
+#lines
+[ScorePlayer4Static1]
+X = 20
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer4Static2]
+X = 20
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer4Static3]
+X = 20
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer4Static4]
+X = 20
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer4Static5]
+X = 20
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+# P L A Y E R  T W O
+[ScoreTextName5]
+X = 280
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P2
+Color = White
+
+# Rating
+[ScoreStaticRatingPicture5]
+X = 460
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes5]
+X = 280
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = White
+
+[ScoreTextNotesScore5]
+X = 520
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextLineBonus5]
+X = 280
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = White
+
+[ScoreTextLineBonusScore5]
+X = 520
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextGoldenNotes5]
+X = 280
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = White
+
+[ScoreTextGoldenNotesScore5]
+X = 520
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextScore5]
+X = 280
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = White
+
+[ScoreTextTotal5]
+X = 307
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = White
+Reflection = 1
+ReflectionSpacing = -1
+
+[ScoreTextTotalScore5]
+X = 520
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = White
+Reflection = 1
+ReflectionSpacing = -3
+
+[ScoreStaticBoxDark5]
+Tex = PlayerNumberBox
+X = 280
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P2Dark
+Z = 0.9
+Reflection = 1
+ReflectionSpacing = 4
+
+[ScorePlayer5Text1]
+X = 284
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = White
+Font = 1
+Size = 15
+Align = 0
+Text = P2
+
+[ScorePlayer5Static1]
+X = 280
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer5Static2]
+X = 280
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer5Static3]
+X = 280
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer5Static4]
+X = 280
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer5Static5]
+X = 280
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+# P L A Y E R  T H R E E
+[ScoreTextName6]
+X = 540
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P3
+Color = White
+
+# Rating
+[ScoreStaticRatingPicture6]
+X = 720
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes6]
+X = 540
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = White
+
+[ScoreTextNotesScore6]
+X = 780
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextLineBonus6]
+X = 540
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = White
+
+[ScoreTextLineBonusScore6]
+X = 780
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextGoldenNotes6]
+X = 540
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = White
+
+[ScoreTextGoldenNotesScore6]
+X = 780
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = White
+
+[ScoreTextScore6]
+X = 540
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = White
+
+[ScoreTextTotal6]
+X = 567
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = White
+Reflection = 1
+ReflectionSpacing = -1
+
+[ScoreTextTotalScore6]
+X = 780
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = White
+Reflection = 1
+ReflectionSpacing = -3
+
+[ScoreStaticBoxDark6]
+Tex = PlayerNumberBox
+X = 540
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P3Dark
+Z = 0.9
+Reflection = 1
+ReflectionSpacing = 4
+
+[ScorePlayer6Text1]
+X = 544
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = White
+Font = 1
+Size = 15
+Align = 0
+Text = P3
+
+#lines
+[ScorePlayer6Static1]
+X = 540
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer6Static2]
+X = 540
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer6Static3]
+X = 540
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer6Static4]
+X = 540
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[ScorePlayer6Static5]
+X = 540
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Colorized
+Color = White
+
+[Options]
+Texts = 6
+Fade = 2
+
+[OptionsBackground]
+Tex = OptionsBG
+
+[OptionsStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = IconOption
+Type = Colorized
+
+[OptionsText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Text = SING_OPTIONS
+Align = 0
+
+[OptionsText2]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = SING_OPTIONS_DESC
+
+[OptionsTextDescription]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text =
+
+[OptionsStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsText3]
+X = 300
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection=1
+ReflectionSpacing=13
+
+[OptionsStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsText4]
+X = 440
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_SELECT
+Reflection=1
+ReflectionSpacing=13
+
+[OptionsStatic6]
+X = 550
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsText5]
+X = 590
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_ESC
+Reflection=1
+ReflectionSpacing=13
+
+[OptionsButtonGame]
+X = 95
+Y = 185
+W = 150
+H = 150
+Tex = Optionsbuttongame
+Color = White
+DColor = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonGameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_GAME
+Color = White
+
+[OptionsButtonGraphics]
+X = 250
+Y = 185
+W = 150
+H = 150
+Tex = Optionsbuttongraphics
+Color = White
+DColor = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonGraphicsText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_GRAPHICS
+Color = White
+
+[OptionsButtonSound]
+X = 405
+Y = 185
+W = 150
+H = 150
+Tex = Optionsbuttonsound
+Color = White
+DColor = White
+Type = Transparent
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonSoundText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_SOUND
+Color = White
+
+[OptionsButtonLyrics]
+X = 560
+Y = 185
+W = 150
+H = 150
+Tex = Optionsbuttonlyrics
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[OptionsButtonLyricsText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_LYRICS
+Color = White
+
+[OptionsButtonThemes]
+X = 95
+Y = 295
+W = 150
+H = 150
+Tex = Optionsbuttondesign
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[OptionsButtonThemesText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_THEMES
+Color = White
+
+[OptionsButtonRecord]
+X = 250
+Y = 295
+W = 150
+H = 150
+Tex = Optionsbuttonrecord
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[OptionsButtonRecordText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_RECORD
+Color = White
+Texts = 1
+
+[OptionsButtonAdvanced]
+X = 405
+Y = 295
+W = 150
+H = 150
+Tex = Optionsbuttonadvanced
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[OptionsButtonAdvancedText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_ADVANCED
+Color = White
+Texts = 1
+
+[OptionsButtonExit]
+X = 560
+Y = 295
+W = 150
+H = 150
+Tex = Optionsbuttonback
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[OptionsButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[OptionsGame]
+Texts = 5
+
+[OptionsGameBackground]
+Tex = OptionsBG
+
+[OptionsGameStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsGameText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsGameText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_GAME_DESC
+
+[OptionsGameText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = SING_OPTIONS_GAME_WHEREAMI
+
+[OptionsGameStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsGameStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[OptionsGameSelectPlayers]
+Text = SING_OPTIONS_GAME_PLAYERS
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectDifficulty]
+Text = SING_OPTIONS_GAME_DIFFICULTY
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectSlideLanguage]
+Text = SING_OPTIONS_GAME_LANGUAGE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectTabs]
+Text = SING_OPTIONS_GAME_TABS
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectSlideSorting]
+Text = SING_OPTIONS_GAME_SORTING
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectDebug]
+Text = SING_OPTIONS_GAME_DEBUG
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphics]
+Texts = 5
+
+[OptionsGraphicsBackground]
+Tex = OptionsBG
+
+[OptionsGraphicsStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsGraphicsText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsGraphicsText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_GRAPHICS_DESC
+
+[OptionsGraphicsText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = SING_OPTIONS_GRAPHICS_WHEREAMI
+
+[OptionsGraphicsStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsGraphicsStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Z = 0.5
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Text = SING_LEGEND_ESC
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsGraphicsSelectSlideResolution]
+Text = SING_OPTIONS_GRAPHICS_RESOLUTION
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectFullscreen]
+Text = SING_OPTIONS_GRAPHICS_FULLSCREEN
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectDepth]
+Text = SING_OPTIONS_GRAPHICS_DEPTH
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectVisualizer]
+Text = SING_OPTIONS_GRAPHICS_VISUALIZER
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectOscilloscope]
+Text = SING_OPTIONS_GRAPHICS_OSCILLOSCOPE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectMovieSize]
+Text = SING_OPTIONS_GRAPHICS_MOVIE_SIZE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSound]
+Texts = 5
+
+[OptionsSoundBackground]
+Tex = OptionsBG
+
+[OptionsSoundStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsSoundText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsSoundText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_SOUND_DESC
+
+[OptionsSoundText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = SING_OPTIONS_SOUND_WHEREAMI
+
+[OptionsSoundStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsSoundStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Text = SING_LEGEND_ESC
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsSoundSelectVoicePassthrough]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_VOICEPASSTHROUGH
+X = 70
+Y = 130
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectBackgroundMusic]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_BACKGROUNDMUSIC
+X = 70
+Y = 170
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectMicBoost]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_MIC_BOOST
+X = 70
+Y = 210
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectClickAssist]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_CLICK_ASSIST
+X = 70
+Y = 250
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectBeatClick]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_BEAT_CLICK
+X = 70
+Y = 290
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectThreshold]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_THRESHOLD
+X = 70
+Y = 330
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectSlidePreviewVolume]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_PREVIEWVOLUME
+X = 70
+Y = 370
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectSlidePreviewFADING]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_SOUND_PREVIEWFADING
+X = 70
+Y = 410
+W = 250
+H = 35
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundButtonExit]
+X = 70
+Y = 460
+W = 250
+H = 35
+Tex = MainBar
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyrics]
+Texts = 1
+
+[OptionsLyricsBackground]
+Tex = OptionsBG
+
+[OptionsLyricsStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsLyricsText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsLyricsText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_LYRICS_DESC
+
+[OptionsLyricsText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = SING_OPTIONS_LYRICS_WHEREAMI
+
+[OptionsLyricsStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsLyricsStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Text = SING_LEGEND_ESC
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsLyricsSelectLyricsFont]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_LYRICS_FONT
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsSelectLyricsEffect]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_LYRICS_EFFECT
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsSelectNoteLines]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = SING_OPTIONS_LYRICS_NOTELINES
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemes]
+Texts = 5
+
+[OptionsThemesBackground]
+Tex = OptionsBG
+
+[OptionsThemesStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsThemesText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsThemesText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_THEMES_DESC
+
+[OptionsThemesText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = SING_OPTIONS_THEMES_WHEREAMI
+
+[OptionsThemesStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsThemesStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[OptionsThemesSelectTheme]
+Text = SING_OPTIONS_THEMES_THEME
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesSelectSkin]
+Text = SING_OPTIONS_THEMES_SKIN
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesSelectColor]
+Text = SING_OPTIONS_THEMES_COLOR
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecord]
+Texts = 5
+
+[OptionsRecordBackground]
+Tex = OptionsBG
+
+[OptionsRecordStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsRecordText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsRecordText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_RECORD_DESC
+
+[OptionsRecordText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = SING_OPTIONS_RECORD_WHEREAMI
+
+[OptionsRecordStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsRecordStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[OptionsRecordSelectSlideCard]
+Text = SING_OPTIONS_RECORD_CARD
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordSelectSlideInput]
+Text = SING_OPTIONS_RECORD_INPUT
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordSelectSlideChannel]
+Text = SING_OPTIONS_RECORD_CHANNEL
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordButtonExit]
+X = 70
+Y = 390
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvanced]
+Texts = 5
+
+[OptionsAdvancedBackground]
+Tex = OptionsBG
+
+[OptionsAdvancedStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = IconOption
+Type = Transparent
+
+[OptionsAdvancedText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_OPTIONS
+
+[OptionsAdvancedText3]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_ADVANCED_DESC
+
+[OptionsAdvancedText2]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = SING_OPTIONS_ADVANCED_WHEREAMI
+
+[OptionsAdvancedStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsAdvancedStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+#########unused at the moment#########
+#[OptionsAdvancedSelectLoadAnimation]
+#Text = SING_OPTIONS_ADVANCED_LOADANIMATION
+#Tex = MainBar
+#TexSBG = SelectBG
+#X = 40
+#Y = 85
+#W = 230
+#H = 70
+#SkipX = 10
+
+#Color = ColorDark
+#DColor = ColorLight
+#TColor = White
+#TDColor = White
+
+#SBGColor = ColorDark
+#SBGDColor = ColorLight
+#STColor = White
+#STDColor = GrayDark
+
+[OptionsAdvancedSelectScreenFade]
+Text = SING_OPTIONS_ADVANCED_SCREENFADE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectEffectSing]
+Text = SING_OPTIONS_ADVANCED_EFFECTSING
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectLineBonus]
+Text = SING_OPTIONS_GRAPHICS_LINEBONUS
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectSlideOnSongClick]
+Text = SING_OPTIONS_ADVANCED_ONSONGCLICK
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectAskbeforeDel]
+Text = SING_OPTIONS_ADVANCED_ASKBEFOREDEL
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectPartyPopup]
+Text = SING_OPTIONS_ADVANCED_PARTYPOPUP
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = MainBar
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5]
+Texts = 1
+
+[Top5Background]
+Tex = Top5BG
+
+[Top5Text1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_TOP_5_CHARTS
+
+[Top5TextArtistTitle]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = artist - title
+
+[Top5Text4]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = SING_OPTIONS_GAME_DIFFICULTY
+
+[Top5TextLevel]
+X = 155
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 1
+Text = easy
+
+[Top5Static1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = ScoreIcon
+Type = Colorized
+
+[Top5Static2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Static3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Text2]
+X = 238
+Y = 552
+Color = White
+Font = 0
+Size = 0
+Align = 2
+Text = SING_TOP_5_CHARTS_WHEREAMI
+
+[Top5Static4]
+X = 252
+Y = 544
+W = 32
+H = 32
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Text3]
+X = 282
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_TOP_5_CHARTS_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[Top5Static5]
+X = 522
+Y = 544
+W = 32
+H = 32
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Text5]
+X = 552
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_TOP_5_CHARTS_SWITCH_DIFFICULTY
+Reflection = 1
+ReflectionSpacing = 13
+
+[Top5TextName1]
+X = 150
+Y = 190
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 1. Player1
+
+[Top5TextName2]
+X = 150
+Y = 240
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 2. Player2
+
+[Top5TextName3]
+X = 150
+Y = 290
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 3. Player3
+
+[Top5TextName4]
+X = 150
+Y = 340
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 4. Player4
+
+[Top5TextName5]
+X = 150
+Y = 390
+Color = White
+Font = 0
+Size = 42
+Align = 0
+Text = 5. Player5
+
+[Top5TextScore1]
+X = 560
+Y = 190
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore2]
+X = 560
+Y = 240
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore3]
+X = 560
+Y = 290
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore4]
+X = 560
+Y = 340
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore5]
+X = 560
+Y = 390
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+
+[Top5TextDate1]
+X = 760
+Y = 190
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate2]
+X = 760
+Y = 240
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate3]
+X = 760
+Y = 290
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate4]
+X = 760
+Y = 340
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate5]
+X = 760
+Y = 390
+Color = White
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextNumber1]
+X = 120
+Y = 193
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 1
+
+[Top5TextNumber2]
+X = 120
+Y = 243
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 2
+
+[Top5TextNumber3]
+X = 120
+Y = 293
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 3
+
+[Top5TextNumber4]
+X = 120
+Y = 343
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 4
+
+[Top5TextNumber5]
+X = 120
+Y = 393
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 5
+
+[Top5StaticNumber1]
+Tex = PlayerNumberBox
+X = 100
+Y = 186
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber2]
+Tex = PlayerNumberBox
+X = 100
+Y = 236
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber3]
+Tex = PlayerNumberBox
+X = 100
+Y = 286
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber4]
+Tex = PlayerNumberBox
+X = 100
+Y = 336
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Top5StaticNumber5]
+Tex = PlayerNumberBox
+X = 100
+Y = 386
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
+
+[Edit]
+Texts = 5
+
+[EditBackground]
+Tex = EditBG
+
+# main icon
+[EditStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = IconEdit
+Type = Transparent
+# Type = Colorized
+
+# main icon title
+[EditText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_EDIT
+
+# main icon subtitle
+[EditText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_MENU_DESCRIPTION
+
+# Navigate button text
+[EditText3]
+X = 300
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+# Select button text
+[EditText4]
+X = 440
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_SELECT
+Reflection=1
+ReflectionSpacing=13
+
+# Esc button text
+[EditText5]
+X = 590
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_EXIT
+Reflection=1
+ReflectionSpacing=13
+
+[EditTextDescription]
+X = 5
+Y = 549
+Color = GrayDark
+Font = 0
+Size = 18
+Align = 0
+Text = SING_EDIT_TEXTDESCRIPTION
+
+[EditStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic6]
+X = 550
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditButtonConvert]
+X = 250
+Y = 270
+W = 150
+H = 150
+Tex = Editbuttonconvert
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[EditButtonConvertText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_CONVERT
+Color = White
+
+[EditButtonExit]
+X = 405
+Y = 270
+W = 150
+H = 150
+Tex = Optionsbuttonback
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[EditButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_EXIT
+Color = White
+
+[Level]
+Texts = 5
+
+[LevelBackground]
+Tex = MainBG
+
+[LevelStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Tex = MainIcon
+Color = White
+Type = Transparent
+
+[LevelText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_MODE
+
+[LevelText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_DIFFICULTY_DESC
+
+[LevelStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelText3]
+X = 300
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[LevelText4]
+X = 440
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_DIFFICULTY_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[LevelButtonEasy]
+X = 180
+Y = 270
+W = 150
+H = 150
+Tex = Levelbuttoneasy
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[LevelButtonMedium]
+X = 335
+Y = 270
+W = 150
+H = 150
+Tex = Levelbuttonmedium
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[LevelButtonHard]
+X = 490
+Y = 270
+W = 150
+H = 150
+Tex = Levelbuttonhard
+Color = White
+DColor = White
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[LevelButtonEasyText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text = SING_EASY
+
+[LevelButtonMediumText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text = SING_MEDIUM
+
+[LevelButtonHardText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text = SING_HARD
+
+[Name]
+Texts = 2
+
+[NameBackground]
+Tex  = MainBG
+
+[NameStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Tex = MainIcon
+Color = White
+Type = Transparent
+
+[NameText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_MODE
+
+[NameText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = SING_PLAYER_DESC
+
+[NameStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameText3]
+X = 300
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[NameStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameText4]
+X = 440
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_PLAYER_ENTER_NAME
+Reflection = 1
+ReflectionSpacing = 13
+
+[NameStatic6]
+X = 590
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameText5]
+X = 630
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[NameButtonPlayer1]
+X = 180
+Y = 270
+W = 150
+H = 150
+Tex = Namebutton
+Color = P1Dark
+DColor = P1Light
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[NameButtonPlayer1Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer2]
+X = 335
+Y = 270
+W = 150
+H = 150
+Tex = Namebutton
+Color = P2Dark
+DColor = P2Light
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[NameButtonPlayer2Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer3]
+X = 490
+Y = 270
+W = 150
+H = 150
+Tex = Namebutton
+Color = P3Dark
+DColor = P3Light
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[NameButtonPlayer3Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer4]
+X = 180
+Y = 350
+W = 150
+H = 150
+Tex = Namebutton
+Color = P4Dark
+DColor = P4Light
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[NameButtonPlayer4Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer5]
+X = 335
+Y = 350
+W = 150
+H = 150
+Tex = Namebutton
+Color = P5Dark
+DColor = P5Light
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[NameButtonPlayer5Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer6]
+X = 490
+Y = 350
+W = 150
+H = 150
+Tex = Namebutton
+Color = P6Dark
+DColor = P6Light
+Type = Transparent
+Align = 0
+Texts = 1
+Fade = 1
+FadeText = 1
+SelectH = 100
+FadeTex = ButtonFade
+FadeTexPos = 0
+Reflection = 1
+ReflectionSpacing = 0
+
+[NameButtonPlayer6Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[PartyNewRound]
+Texts = 7
+
+[PartyNewRoundBackground]
+Tex = MainBG
+
+[PartyNewRoundStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStatic3]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyNewRoundText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyNewRoundText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = PARTY_ROUND_DESC
+
+[PartyNewRoundText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_ROUND_WHEREAMI
+
+[PartyNewRoundText4]
+X = 282
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_ROUND_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[PartyNewRoundText5]
+X = 460
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND
+Align = 0
+
+[PartyNewRoundText6]
+X = 600
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND_WINNER
+Align = 0
+
+[PartyNewRoundText7]
+X = 448
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = PARTY_ROUND
+Align = 2
+
+[PartyNewRoundTextTeam1Players]
+X = 30
+Y = 137
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam2Players]
+X = 30
+Y = 218
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam3Players]
+X = 30
+Y = 299
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundStatic4]
+Tex = PartyRoundBG1
+X = 450
+Y = 103
+W = 330
+H = 24
+Color = DarkBlue
+Type = Colorized
+
+[PartyNewRoundStatic5]
+X = 252
+Y = 544
+W = 32
+H = 32
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStatic6]
+Tex = PartyRoundBG3
+X = 250
+Y = 350
+W = 300
+H = 50
+Color = DarkBlue
+Type = Colorized
+
+[PartyNewRoundStatic7]
+Tex = PartyRoundBG4
+X = 50
+Y = 495
+W = 700
+H = 30
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticTeam1]
+Tex = PartyTeamButton1
+X = 20
+Y = 110
+W = 400
+H = 50
+Color = P1Dark
+Type = Colorized
+Reflection = 0
+
+[PartyNewRoundStaticTeam2]
+Tex = PartyTeamButton1
+X = 20
+Y = 191
+W = 400
+H = 50
+Color = P2Dark
+Type = Colorized
+Reflection = 0
+
+[PartyNewRoundStaticTeam3]
+Tex = PartyTeamButton1
+X = 20
+Y = 272
+W = 400
+H = 50
+Color = P3Dark
+Type = Colorized
+Reflection = 0
+
+[PartyNewRoundStaticNextPlayer1]
+Tex = PartyPlayerButton
+X = 155
+Y = 415
+W = 150
+H = 50
+Type = Colorized
+Texts = 1
+Color = P1Light
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStaticNextPlayer2]
+Tex = PartyPlayerButton
+X = 325
+Y = 415
+W = 150
+H = 50
+Type = Colorized
+Texts = 1
+Color = P2Light
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStaticNextPlayer3]
+Tex = PartyPlayerButton
+X = 495
+Y = 415
+W = 150
+H = 50
+Type = Colorized
+Texts = 1
+Color = P3Light
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyNewRoundTextRound1]
+X = 460
+Y = 133
+Color = White
+Font = 0
+Size = 24
+Text = Round 1
+Align = 0
+
+[PartyNewRoundTextRound2]
+X = 460
+Y = 162
+Color = White
+Font = 0
+Size = 24
+Text = Round 2
+Align = 0
+
+[PartyNewRoundTextRound3]
+X = 460
+Y = 191
+Color = White
+Font = 0
+Size = 24
+Text = Round 3
+Align = 0
+
+[PartyNewRoundTextRound4]
+X = 460
+Y = 220
+Color = White
+Font = 0
+Size = 24
+Text = Round 4
+Align = 0
+
+[PartyNewRoundTextRound5]
+X = 460
+Y = 249
+Color = White
+Font = 0
+Size = 24
+Text = Round 5
+Align = 0
+
+[PartyNewRoundTextRound6]
+X = 460
+Y = 278
+Color = White
+Font = 0
+Size = 24
+Text = Round 6
+Align = 0
+
+[PartyNewRoundTextRound7]
+X = 460
+Y = 307
+Color = White
+Font = 0
+Size = 24
+Text = Round 7
+Align = 0
+
+[PartyNewRoundTextWinner1]
+X = 600
+Y = 133
+Color = White
+Font = 0
+Size = 24
+Text = Winner 1
+Align = 0
+
+[PartyNewRoundTextWinner2]
+X = 600
+Y = 162
+Color = White
+Font = 0
+Size = 24
+Text = Winner 2
+Align = 0
+
+[PartyNewRoundTextWinner3]
+X = 600
+Y = 191
+Color = White
+Font = 0
+Size = 24
+Text = Winner 3
+Align = 0
+
+[PartyNewRoundTextWinner4]
+X = 600
+Y = 220
+Color = White
+Font = 0
+Size = 24
+Text = Winner 4
+Align = 0
+
+[PartyNewRoundTextWinner5]
+X = 600
+Y = 249
+Color = White
+Font = 0
+Size = 24
+Text = Winner 5
+Align = 0
+
+[PartyNewRoundTextWinner6]
+X = 600
+Y = 278
+Color = White
+Font = 0
+Size = 24
+Text = Winner 6
+Align = 0
+
+[PartyNewRoundTextWinner7]
+X = 600
+Y = 307
+Color = White
+Font = 0
+Size = 24
+Text = Winner 7
+Align = 0
+
+[PartyNewRoundStaticRound1]
+Tex = PartyRoundBG2
+X = 450
+Y = 135
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound2]
+Tex = PartyRoundBG2
+X = 450
+Y = 164
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound3]
+Tex = PartyRoundBG2
+X = 450
+Y = 193
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound4]
+Tex = PartyRoundBG2
+X = 450
+Y = 222
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound5]
+Tex = PartyRoundBG2
+X = 450
+Y = 251
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound6]
+Tex = PartyRoundBG2
+X = 450
+Y = 280
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundStaticRound7]
+Tex = PartyRoundBG2
+X = 450
+Y = 309
+W = 330
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyNewRoundTextNextRound]
+X = 400
+Y = 495
+Color = White
+Font = 0
+Size = 30
+Text = Next Round
+Align = 1
+
+[PartyNewRoundTextNextRoundNo]
+X = 457
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = 99
+Align = 0
+
+[PartyNewRoundTextScoreTeam1]
+X = 390
+Y = 110
+Color = White
+Font = 0
+Size = 51
+Text = 3000
+Align = 1
+
+[PartyNewRoundTextScoreTeam2]
+X = 390
+Y = 191
+Color = White
+Font = 0
+Size = 51
+Text = 2000
+Align = 1
+
+[PartyNewRoundTextScoreTeam3]
+X = 390
+Y = 272
+Color = White
+Font = 0
+Size = 51
+Text = 1000
+Align = 1
+
+[PartyNewRoundTextNameTeam1]
+X = 30
+Y = 108
+Color = White
+Font = 0
+Size = 36
+Text = Team 1
+Align = 0
+
+[PartyNewRoundTextNameTeam2]
+X = 30
+Y = 189
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyNewRoundTextNameTeam3]
+X = 30
+Y = 270
+Color = White
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyNewRoundTextNextPlayer1]
+X = 230
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 1
+Align = 1
+
+[PartyNewRoundTextNextPlayer2]
+X = 400
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 2
+Align = 1
+
+[PartyNewRoundTextNextPlayer3]
+X = 570
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 3
+Align = 1
+
+
+[PartyScore]
+Texts = 5
+
+[PartyScoreBackground]
+Tex = PartyBG
+
+[PartyScoreDecoTextures]
+ChangeTextures = 1
+
+FirstTexture = PartyScoreDeco
+FirstTyp = Colorized
+FirstColor = Gold
+
+SecondTexture = PartyScoreDeco
+SecondTyp = Colorized
+SecondColor = Silver
+
+ThirdTexture = PartyScoreDeco
+ThirdTyp = Colorized
+ThirdColor = Bronze
+
+[PartyScoreStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStatic3]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyScoreStatic4]
+X = 252
+Y = 544
+W = 32
+H = 32
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyScoreText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = PARTY_SCORE_DESC
+
+[PartyScoreText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SCORE_WHEREAMI
+
+[PartyScoreText4]
+X = 282
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+
+[PartyScoreStatic5]
+Tex = PartyScoreBG1
+X = 50
+Y = 100
+W = 700
+H = 80
+Color = DarkBlue
+Type = Colorized
+
+[PartyScoreStatic6]
+Tex = PartyScoreBG2
+X = 50
+Y = 495
+W = 700
+H = 20
+Color = LightBlue
+Type = Colorized
+
+[PartyScoreText5]
+X = 400
+Y = 136
+Color = White
+Font = 0
+Size = 45
+Text = PARTY_SCORE_WINS2
+Align = 1
+
+[PartyScoreTextWinner]
+X = 400
+Y = 98
+Color = White
+Font = 0
+Size = 54
+Text = The Winner is...
+Align = 1
+
+[PartyScoreTextScoreTeam1]
+X = 568
+Y = 198
+Color = White
+Font = 0
+Size = 36
+Text = 3000
+Align = 2
+
+[PartyScoreTextScoreTeam2]
+X = 568
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = 2000
+Align = 2
+
+[PartyScoreTextScoreTeam3]
+X = 568
+Y = 398
+Color = White
+Font = 0
+Size = 36
+Text = 1000
+Align = 2
+
+[PartyScoreTextNameTeam1]
+X = 188
+Y = 198
+Font = 0
+Size = 36
+Align = 0
+Text = Team 1
+Color = White
+
+[PartyScoreTextNameTeam2]
+X = 188
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyScoreTextNameTeam3]
+X = 188
+Y = 398
+Color = White
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyScoreStaticTeam1]
+X = 188
+Y = 230
+W = 380
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyScoreStaticTeam1BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 200
+W = 400
+H = 50
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStaticTeam1Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 191
+W = 64
+H = 64
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = -5
+
+[PartyScoreStaticTeam2]
+X = 188
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyScoreStaticTeam2BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStaticTeam2Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 291
+W = 64
+H = 64
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = -5
+
+[PartyScoreStaticTeam3]
+X = 188
+Y = 430
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyScoreStaticTeam3BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 400
+W = 400
+H = 50
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStaticTeam3Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 391
+W = 64
+H = 64
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = -5
+
+[PartyWin]
+Texts = 4
+
+[PartyWinBackground]
+Tex = PartyBG
+
+[PartyWinStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStatic3]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyWinStatic4]
+X = 252
+Y = 544
+W = 32
+H = 32
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyWinText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyWinText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = PARTY_WIN_DESC
+
+[PartyWinText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_WIN_WHEREAMI
+
+[PartyWinText4]
+X = 282
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_WIN_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing =13
+
+
+#[PartyWinTextWinner]
+#X = 150
+#Y = 120
+#Color = White
+#Font = 1
+#Size = 42
+#Text = The Winner is...
+#Align = 0
+
+[PartyWinTextScoreTeam1]
+X = 699
+Y = 183
+Color = White
+Font = 0
+Size = 57
+Text = 3000
+Align = 2
+
+[PartyWinTextScoreTeam2]
+X = 669
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = 2000
+Align = 2
+
+[PartyWinTextScoreTeam3]
+X = 649
+Y = 398
+Color = White
+Font = 0
+Size = 27
+Text = 1000
+Align = 2
+
+[PartyWinTextNameTeam1]
+X = 169
+Y = 183
+Font = 0
+Size = 57
+Align = 0
+Text = Team 1
+Color = White
+
+[PartyWinTextNameTeam2]
+X = 289
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyWinTextNameTeam3]
+X = 369
+Y = 398
+Color = White
+Font = 0
+Size = 27
+Text = Team 3
+Align = 0
+
+[PartyWinStaticTeam1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BG]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam1Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BGRank1]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam1Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BGRank2]
+Tex = PartyTeamButton3
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam1Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BGRank3]
+Tex = PartyTeamButton3
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyWinStaticTeam1Deco]
+Tex = PartyWinDeco1
+X = 91
+Y = 176
+W = 79
+H = 79
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = 3
+
+[PartyWinStaticTeam2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BG]
+Tex = PartyTeamButton4
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamButton3
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BGRank1]
+Tex = PartyTeamButton4
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BGRank2]
+Tex = PartyTeamButton4
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BGRank3]
+Tex = PartyTeamButton4
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Deco]
+Tex = PartyWinDeco2
+X = 226
+Y = 291
+W = 64
+H = 64
+Type = Colorized
+Color = Silver
+Reflection = 1
+ReflectionSpacing = 3
+
+[PartyWinStaticTeam3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BG]
+Tex = PartyTeamButton5
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BGRank1]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BGRank2]
+Tex = PartyTeamButton5
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BGRank3]
+Tex = PartyTeamButton5
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Deco]
+Tex = PartyWinDeco3
+X = 316
+Y = 391
+W = 54
+H = 54
+Type = Colorized
+Color = Bronze
+Reflection = 1
+ReflectionSpacing = 3
+
+[PartyOptions]
+Texts = 5
+
+[PartyOptionsBackground]
+Tex = PartyBG
+
+[PartyOptionsStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyOptionsStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyOptionsStatic3]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyOptionsStatic4]
+X = 252
+Y = 544
+W = 32
+H = 32
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyOptionsStatic5]
+X = 380
+Y = 544
+W = 32
+H = 32
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyOptionsText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyOptionsText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = PARTY_OPTIONS_DESC
+
+[PartyOptionsText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_OPTIONS_WHEREAMI
+
+[PartyOptionsText4]
+X = 286
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+
+[PartyOptionsText5]
+X = 410
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+
+[PartyOptionsSelectLevel]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_DIFFICULTY
+X = 70
+Y = 110
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+#TexSBG = SelectBG
+#W = 230
+#H = 40
+#SkipX = 10
+
+[PartyOptionsSelectPlayList]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_PLAYLIST
+X = 70
+Y = 165
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyOptionsSelectPlayList2]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_PLAYLIST
+X = 70
+Y = 220
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyOptionsSelectRounds]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_ROUNDS
+X = 70
+Y = 250
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+
+
+[PartyPlayer]
+Texts = 6
+
+[PartyPlayerBackground]
+Tex = PartyBG
+
+[PartyPlayerStatic1]
+X = 0
+Y = 545
+Z = 0.7
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerStatic2]
+X = 250
+Y = 545
+Z = 0.7
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerStatic3]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyPlayerStatic4]
+X = 252
+Y = 544
+Z = 0.75
+W = 32
+H = 32
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerStatic5]
+X = 380
+Y = 544
+Z = 0.75
+W = 32
+H = 32
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyPlayerStatic6]
+X = 548
+Y = 544
+Z = 0.75
+W = 32
+H = 32
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyPlayerText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = PARTY_PLAYER_DESC
+
+[PartyPlayerText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_PLAYER_WHEREAMI
+
+[PartyPlayerText4]
+X = 286
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+
+[PartyPlayerText5]
+X = 410
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_PLAYER_ENTER_NAME
+Reflection = 1
+ReflectionSpacing = 13
+
+[PartyPlayerText6]
+X = 578
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[PartyPlayerSelectTeams]
+Tex = MainBar
+TexSBG = SelectBG
+Type = Transparent
+TypeSBG = Transparent
+Text = PARTY_TEAMS
+X = 78
+Y = 135
+W = 310
+H = 30
+SBGW = 310
+SkipX = 10
+Fields = 2
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers1]
+Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+Type = Colorized
+TypeSBG = Colorized
+Text = 
+X = 388
+Y = 180
+W = 0
+SBGW = 310
+H = 30
+SkipX = 10
+Fields = 1
+
+Color = P1Lightest
+DColor = P1Dark
+TColor = White
+TDColor = White
+
+SBGColor = P1Lightest
+SBGDColor = P1Dark
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers2]
+Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+Type = Colorized
+TypeSBG = Colorized
+Text = 
+X = 388
+Y = 280
+W = 0
+SBGW = 310
+H = 30
+SkipX = 10
+Fields = 1
+
+Color = P2Lightest
+DColor = P2Dark
+TColor = White
+TDColor = White
+
+SBGColor = P2Lightest
+SBGDColor = P2Dark
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers3]
+Tex = MainBar
+Type = Colorized
+TypeSBG = Colorized
+TexSBG = PartyPlayerSelectBG
+Text = 
+X = 388
+Y = 380
+W = 0
+SBGW = 310
+H = 30
+SkipX = 10
+Fields = 4
+
+Color = P3Lightest
+DColor = P3Dark
+TColor = White
+TDColor = White
+
+SBGColor = P3Lightest
+SBGDColor = P3Dark
+STColor = White
+STDColor = GrayDark
+
+
+[PartyPlayerTeam1Name]
+Tex = PartyTeamButton2
+X = 78
+Y = 180
+W = 310
+H = 30
+Type = Colorized
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerTeam1NameText1]
+X = 60
+Y = 0
+Font = 0
+Size = 32
+Align = 1
+Text = Team 1
+Color = White
+
+[PartyPlayerPlayer1Name]
+Tex = Button
+X = 78
+Y = 225
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer1NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 1
+Color = White
+
+[PartyPlayerPlayer2Name]
+Tex = Button
+X = 238
+Y = 225
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer2NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 2
+Color = White
+
+[PartyPlayerPlayer3Name]
+Tex = Button
+X = 398
+Y = 225
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer3NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 3
+Color = White
+
+[PartyPlayerPlayer4Name]
+Tex = Button
+X = 558
+Y = 225
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer4NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 4
+Color = White
+
+[PartyPlayerTeam2Name]
+Tex = PartyTeamButton2
+X = 78
+Y = 280
+W = 310
+H = 30
+Type = Colorized
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerTeam2NameText1]
+X = 60
+Y = 0
+Font = 0
+Size = 32
+Align = 1
+Text = Team 2
+Color = White
+
+[PartyPlayerPlayer5Name]
+Tex = Button
+X = 78
+Y = 325
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer5NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 5
+Color = White
+
+[PartyPlayerPlayer6Name]
+Tex = Button
+X = 238
+Y = 325
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer6NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 6
+Color = White
+
+[PartyPlayerPlayer7Name]
+Tex = Button
+X = 398
+Y = 325
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer7NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 7
+Color = White
+
+[PartyPlayerPlayer8Name]
+Tex = Button
+X = 558
+Y = 325
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer8NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 8
+Color = White
+
+[PartyPlayerTeam3Name]
+Tex = PartyTeamButton2
+X = 78
+Y = 380
+W = 310
+H = 30
+Type = Colorized
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerTeam3NameText1]
+X = 60
+Y = 0
+Font = 0
+Size = 32
+Align = 1
+Text = Team 3
+Color = White
+
+[PartyPlayerPlayer9Name]
+Tex = Button
+X = 78
+Y = 425
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer9NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 9
+Color = White
+
+[PartyPlayerPlayer10Name]
+Tex = Button
+X = 238
+Y = 425
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer10NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 10
+Color = White
+
+[PartyPlayerPlayer11Name]
+Tex = Button
+X = 398
+Y = 425
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer11NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 11
+Color = White
+
+[PartyPlayerPlayer12Name]
+Tex = Button
+X = 558
+Y = 425
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Light
+Reflection = 0
+ReflectionSpacing = 1
+
+[PartyPlayerPlayer12NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 12
+Color = White
+
+
+
+[PartyRoundsBackground]
+Tex = PartyBG
+
+[PartyRoundsStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyRoundsStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyRoundsStatic3]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyRoundsStatic4]
+X = 252
+Y = 544
+W = 32
+H = 32
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyRoundsStatic5]
+X = 380
+Y = 544
+W = 32
+H = 32
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyRoundsText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = PARTY_MODE
+
+[PartyRoundsText2]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = PARTY_ROUNDS_DESC
+
+[PartyRoundsText3]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_ROUNDS_WHEREAMI
+
+[PartyRoundsText4]
+X = 286
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[PartyRoundsText5]
+X = 410
+Y = 548
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_ROUNDS_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[PartyRoundsSelectRoundCount]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_ROUNDCOUNT
+X = 70
+Y = 100
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound1]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE1
+X = 70
+Y = 155
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound2]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE2
+X = 70
+Y = 210
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound3]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE3
+X = 70
+Y = 265
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound4]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE4
+X = 70
+Y = 320
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound5]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE5
+X = 70
+Y = 375
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound6]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE6
+X = 70
+Y = 430
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound7]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Colorized
+Text = PARTY_SELECTMODE7
+X = 70
+Y = 485
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Color = ColorDark
+DColor = ColorLight
+TColor = White
+TDColor = White
+
+SBGColor = ColorDark
+SBGDColor = ColorLight
+STColor = White
+STDColor = GrayDark
+
+
+
+[SongMenu]
+
+[SongMenuBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[SongMenuStatic1]
+Tex = interface_dialog_background
+X = 500
+Y = 170
+W = 280
+H = 200
+Z = 0.96
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 0
+
+[SongMenuStatic2]
+X = 508
+Y = 181
+W = 24
+H = 24
+Color = White
+Tex = icon_song_menu
+Type = Colorized
+Z = 0.97
+
+[SongMenuTextMenu]
+X = 538
+Y = 175
+Z = 0.97
+Color = White
+Size = 36
+Text = MENU
+
+[SongMenuButton1]
+X = 530
+Y = 225
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = LightBlue
+DColor = DarkBlue
+Type = Colorized
+Texts = 1
+
+[SongMenuButton1Text1]
+X = 6
+Y = 0
+Z = 0.97
+Color = White
+Size = 24
+Text = SONG_MENU_PLAY
+
+[SongMenuButton2]
+X = 530
+Y = 255
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = LightBlue
+DColor = DarkBlue
+Type = Colorized
+Texts = 1
+
+[SongMenuButton2Text1]
+X = 6
+Y = 0
+Color = White
+Size = 24
+Text = SONG_MENU_EDIT
+Z = 0.97
+
+[SongMenuButton3]
+X = 530
+Y = 285
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = LightBlue
+DColor = DarkBlue
+Type = Colorized
+Texts = 1
+
+[SongMenuButton3Text1]
+X = 6
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_MODI
+Align = 0
+Z = 0.97
+
+# shows up instead of BUtton 3
+# in some song menus
+[SongMenuSelectSlide3]
+TexSBG = Rectangle
+Text = 
+TypeSBG = Colorized
+ShowArrows = 1
+OneItemOnly = 1
+X = 530
+Y = 235
+W = 0
+H = 25
+Z = 0.97
+SkipX = 0
+SBGW = 220
+TextSize = 24
+Color = LightBlue
+DColor = DarkBlue
+TColor = White
+TDColor = White
+SBGColor = LightBlue
+SBGDColor = DarkBlue
+STColor = White
+STDColor = White
+
+[SongMenuButton4]
+X = 530
+Y = 315
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = ColorLight
+DColor = ColorDark
+Type = Colorized
+Texts = 1
+
+[SongMenuButton4Text1]
+X = 6
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_CANCEL
+Align = 0
+Z = 0.97
+
+[SongJumpto]
+
+[SongJumptoBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.5
+
+[SongJumptoStatic1]
+Tex = interface_dialog_background
+X = 500
+Y = 370
+W = 280
+H = 160
+Z = 0.965
+Color = White
+Type = Transparent
+
+[SongJumptoStatic2]
+X = 508
+Y = 378
+W = 24
+H = 24
+Color = White
+Tex = icon_song_search
+Type = Colorized
+Z = 0.97
+
+[SongJumptoText1]
+X = 538
+Y = 373
+Color = White
+Size = 36
+Text = SONG_JUMPTO_TYPE_DESC
+Z = 0.97
+
+#arrows over the select
+#TODO: remove, add this for all in code
+[SongJumptoStatic3]
+X = 510
+Y = 413
+W = 260
+H = 30
+Color = White
+Tex = interface_selectbg_search
+Type = Colorized
+Z = 0.97
+
+[SongJumptoSelectSlideType]
+#Text = SONG_JUMPTO_TYPE_DESC
+X = 516
+Y = 413
+Z = 0.97
+H = 30
+SBGW = 150
+SkipX = 4
+
+Size = 36
+
+#text
+TColor = White
+TDColor = Red
+#Select0r.Text.Color
+STColor = White
+STDColor = Red
+
+[SongJumptoButtonSearchText]
+X = 526
+Y = 425
+Z = 0.97
+W = 160
+H = 50
+Size = 36
+Font = 1
+Align = 0
+
+[SongJumptoTextFound]
+X = 539
+Y = 475
+Color = White
+Font = 0
+Size = 24
+Text = SONG_JUMPTO_HELP
+Align = 0
+Z = 0.97
+
+
+[StatMain]
+Texts = 0
+Statics = 0
+
+[StatMainBackground]
+Tex = MainBG
+
+[StatMainButtonScores]
+X = 539
+Y = 150
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonScoresText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SCORES
+Color = White
+
+[StatMainButtonSingers]
+X = 539
+Y = 210
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonSingersText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SINGERS
+Color = White
+
+[StatMainButtonSongs]
+X = 539
+Y = 270
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonSongsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_SONGS
+Color = White
+
+[StatMainButtonBands]
+X = 539
+Y = 330
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonBandsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_BANDS
+Color = White
+
+[StatMainButtonExit]
+X = 539
+Y = 390
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatMainTextOverview]
+X = 45
+Y = 125
+W = 510
+Color = White
+Font = 0
+Size = 24
+Align = 0
+Text =
+
+[StatMainStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = StatIcon
+Type = Colorized
+
+[StatMainStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic6]
+X = 40
+Y = 100
+W = 520
+H = 20
+Tex = StatMainBG1
+Color = ColorLight
+Type = Colorized
+
+[StatMainStatic7]
+X = 40
+Y = 120
+W = 702
+H = 392
+Tex = StatMainBG2
+Color = ColorDark
+Type = Colorized
+
+[StatMainStatic8]
+X = 40
+Y = 420
+W = 520
+H = 20
+Tex = StatMainBG3
+Color = ColorLight
+Type = Colorized
+
+[StatMainText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = STAT_MAIN
+
+[StatMainText2]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = STAT_MAIN_WHEREAMI
+
+[StatMainText3]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_MAIN_DESC
+
+[StatMainText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[StatMainText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[StatDetail]
+Texts = 0
+Statics = 0
+
+[StatDetailBackground]
+Tex = MainBG
+
+[StatDetailButtonNext]
+X = 539
+Y = 200
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonNextText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_NEXT
+Color = White
+
+[StatDetailButtonPrev]
+X = 539
+Y = 260
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonPrevText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_PREV
+Color = White
+
+[StatDetailButtonReverse]
+X = 539
+Y = 320
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonReverseText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_REVERSE
+Color = White
+
+[StatDetailButtonExit]
+X = 539
+Y = 380
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatDetailTextDescription]
+X = 580
+Y = 40
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 1
+Text =
+
+[StatDetailTextPage]
+X = 546
+Y = 98
+Color = White
+Font = 0
+Size = 15
+Align = 2
+Text =
+
+[StatDetailTextList1]
+X = 45
+Y = 122
+Color = White
+Font = 0
+Size = 21
+Text = Stat1
+
+[StatDetailTextList2]
+X = 45
+Y = 160
+Color = White
+Font = 0
+Size = 21
+Text = Stat2
+
+[StatDetailTextList3]
+X = 45
+Y = 198
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList4]
+X = 45
+Y = 236
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList5]
+X = 45
+Y = 274
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList6]
+X = 45
+Y = 312
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList7]
+X = 45
+Y = 350
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList8]
+X = 45
+Y = 388
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList9]
+X = 45
+Y = 426
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList10]
+X = 45
+Y = 464
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailStatic1]
+X = 5
+Y = 30
+W = 48
+H = 48
+Color = White
+Tex = StatIcon
+Type = Colorized
+
+[StatDetailStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic6]
+X = 40
+Y = 100
+W = 520
+H = 24
+Tex = StatDetailBG1
+Color = ColorLight
+Type = Colorized
+
+[StatDetailStatic7]
+X = 40
+Y = 124
+W = 702
+H = 392
+Tex = StatMainBG2
+Color = ColorDark
+Type = Colorized
+
+[StatDetailStatic8]
+X = 40
+Y = 500
+W = 520
+H = 20
+Tex = StatMainBG3
+Color = ColorLight
+Type = Colorized
+
+[StatDetailText1]
+X = 55
+Y = 28
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = STAT_DETAIL
+
+[StatDetailText2]
+X = 5
+Y = 547
+Color = GrayDark
+Font = 0
+Size = 24
+Align = 0
+Text = STAT_DETAIL_WHEREAMI
+
+[StatDetailText3]
+X = 300
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[StatDetailText4]
+X = 440
+Y = 548
+Z = 0.5
+Color = White
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[CheckPopup]
+
+[CheckPopupBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[CheckPopupStatic1]
+Tex = interface_dialog_background
+X = 200
+Y = 150
+W = 400
+H = 200
+Z = 1
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 15
+
+[CheckPopupText1]
+X = 400
+Y = 160
+W = 400
+Color = White
+Font = 0
+Size = 30
+Text = MSG_QUESTION_TITLE
+Align = 1
+Z = 1
+
+[CheckPopupText]
+X = 400
+Y = 210
+W = 280
+Color = White
+Font = 0
+Size = 30
+Text = error text
+Align = 1
+Z = 1
+
+[CheckPopupButton1]
+X = 285
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = YES
+Align = 1
+Z = 1
+
+[CheckPopupButton2]
+X = 415
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton2Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = NO
+Align = 1
+Z = 1
+
+
+[ErrorPopup]
+
+[ErrorPopupBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[ErrorPopupStatic1]
+Tex = interface_dialog_background
+X = 200
+Y = 150
+W = 400
+H = 200
+Z = 0.98
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 15
+
+[ErrorPopupText1]
+X = 400
+Y = 160
+W = 400
+Color = White
+Font = 0
+Size = 30
+Text = MSG_ERROR_TITLE
+Align = 1
+Z = 1
+
+[ErrorPopupText]
+X = 400
+Y = 210
+W = 280
+Color = White
+Font = 0
+Size = 30
+Text = error text
+Align = 1
+Z = 1
+
+[ErrorPopupButton1]
+X = 350
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Z = 1
+
+[ErrorPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = OK
+Align = 1
+Z = 1
+
+[PausePopUpStatic]
+Tex = Pause
+X = 0
+Y = 0
+W = 800
+H = 600
+Z = 0.95
+Color = White
+Type = Colorized
+
+[SingLyricsUpperBar]
+X = 80
+W = 640
+Y = 493
+H = 41
+;YOffSet (+/-) for the Sing-Indicator
+IndicatorYOffset = 3
+
+[SingLyricsLowerBar]
+X = 80
+W = 640
+Y = 535
+H = 41
\ No newline at end of file
diff --git a/songmanagement/game/themes/Temptation/Temptation (16-9).ini b/songmanagement/game/themes/Temptation/Temptation (16-9).ini
new file mode 100755
index 00000000..0567b074
--- /dev/null
+++ b/songmanagement/game/themes/Temptation/Temptation (16-9).ini	
@@ -0,0 +1,264 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Skin]
+Theme=Temptation
+Name=Temptation (16-9)
+Color=Green
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+ButtonSolo     = [main]buttonsolo.png
+ButtonParty    = [main]buttonparty.png
+ButtonStats    = [main]buttonstats.png
+ButtonEdit     = [main]buttonedit.png
+ButtonOption   = [main]buttonoption.png
+ButtonExit     = [main]buttonexit.png
+Button2        = [main]button2.png
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+#Backgrounds
+LoadingBG      = [bg-load]16-9.png
+TitleBG        = [bg-title]16-9.png
+MainBG         = [bg-main]16-9.png
+SongBG         = [bg-main]16-9.png
+ScoreScreenBG  = [bg-main]16-9.png
+Top5BG         = [bg-main]16-9.png
+OptionsBG      = [bg-main]16-9.png
+EditBG         = [bg-main]16-9.png
+PartyBG        = [bg-main]16-9.png
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+# # # O P T I O N S # # #
+Optionsbuttongame = [Options]buttongame.png
+Optionsbuttongraphics = [Options]buttongraphics.png
+Optionsbuttonsound = [Options]buttonsound.png
+Optionsbuttonlyrics = [Options]buttonlyrics.png
+Optionsbuttondesign = [Options]buttondesign.png
+Optionsbuttonrecord = [Options]buttonrecord.png
+Optionsbuttonadvanced = [Options]buttonadvanced.png
+Optionsbuttonback = [Options]buttonback.png
+
+# # # L E V E L # # #
+Levelbuttoneasy = [Level]buttoneasy.png
+Levelbuttonmedium = [Level]buttonmedium.png
+Levelbuttonhard = [Level]buttonhard.png
+
+# # # E D I T # # #
+Editbuttonconvert = [edit]buttonconvert.png
+
+# # # N A M E # # # 
+Namebutton = [Name]button.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.png
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Temptation/Temptation (4-3).ini b/songmanagement/game/themes/Temptation/Temptation (4-3).ini
new file mode 100755
index 00000000..a0f72731
--- /dev/null
+++ b/songmanagement/game/themes/Temptation/Temptation (4-3).ini	
@@ -0,0 +1,264 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Skin]
+Theme=Temptation
+Name=Temptation (4-3)
+Color=Green
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+ButtonSolo     = [main]buttonsolo.png
+ButtonParty    = [main]buttonparty.png
+ButtonStats    = [main]buttonstats.png
+ButtonEdit     = [main]buttonedit.png
+ButtonOption   = [main]buttonoption.png
+ButtonExit     = [main]buttonexit.png
+Button2        = [main]button2.png
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+#Backgrounds
+LoadingBG      = [bg-load]4-3.png
+TitleBG        = [bg-title]4-3.png
+MainBG         = [bg-main]4-3.png
+SongBG         = [bg-main]4-3.png
+ScoreScreenBG  = [bg-main]4-3.png
+Top5BG         = [bg-main]4-3.png
+OptionsBG      = [bg-main]4-3.png
+EditBG         = [bg-main]4-3.png
+PartyBG        = [bg-main]4-3.png
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+# # # O P T I O N S # # #
+Optionsbuttongame = [Options]buttongame.png
+Optionsbuttongraphics = [Options]buttongraphics.png
+Optionsbuttonsound = [Options]buttonsound.png
+Optionsbuttonlyrics = [Options]buttonlyrics.png
+Optionsbuttondesign = [Options]buttondesign.png
+Optionsbuttonrecord = [Options]buttonrecord.png
+Optionsbuttonadvanced = [Options]buttonadvanced.png
+Optionsbuttonback = [Options]buttonback.png
+
+# # # L E V E L # # #
+Levelbuttoneasy = [Level]buttoneasy.png
+Levelbuttonmedium = [Level]buttonmedium.png
+Levelbuttonhard = [Level]buttonhard.png
+
+# # # E D I T # # #
+Editbuttonconvert = [edit]buttonconvert.png
+
+# # # N A M E # # # 
+Namebutton = [Name]button.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.png
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Temptation/[Level]buttoneasy.png b/songmanagement/game/themes/Temptation/[Level]buttoneasy.png
new file mode 100755
index 00000000..c7c91898
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Level]buttoneasy.png differ
diff --git a/songmanagement/game/themes/Temptation/[Level]buttonhard.png b/songmanagement/game/themes/Temptation/[Level]buttonhard.png
new file mode 100755
index 00000000..9d4ffafe
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Level]buttonhard.png differ
diff --git a/songmanagement/game/themes/Temptation/[Level]buttonmedium.png b/songmanagement/game/themes/Temptation/[Level]buttonmedium.png
new file mode 100755
index 00000000..58986bb8
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Level]buttonmedium.png differ
diff --git a/songmanagement/game/themes/Temptation/[Name]button.png b/songmanagement/game/themes/Temptation/[Name]button.png
new file mode 100755
index 00000000..e5083213
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Name]button.png differ
diff --git a/songmanagement/game/themes/Temptation/[Options]buttonadvanced.png b/songmanagement/game/themes/Temptation/[Options]buttonadvanced.png
new file mode 100755
index 00000000..459fadde
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Options]buttonadvanced.png differ
diff --git a/songmanagement/game/themes/Temptation/[Options]buttonback.png b/songmanagement/game/themes/Temptation/[Options]buttonback.png
new file mode 100755
index 00000000..aea00e61
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Options]buttonback.png differ
diff --git a/songmanagement/game/themes/Temptation/[Options]buttondesign.png b/songmanagement/game/themes/Temptation/[Options]buttondesign.png
new file mode 100755
index 00000000..d57828f3
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Options]buttondesign.png differ
diff --git a/songmanagement/game/themes/Temptation/[Options]buttongame.png b/songmanagement/game/themes/Temptation/[Options]buttongame.png
new file mode 100755
index 00000000..16f7900e
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Options]buttongame.png differ
diff --git a/songmanagement/game/themes/Temptation/[Options]buttongraphics.png b/songmanagement/game/themes/Temptation/[Options]buttongraphics.png
new file mode 100755
index 00000000..efe8c773
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Options]buttongraphics.png differ
diff --git a/songmanagement/game/themes/Temptation/[Options]buttonlyrics.png b/songmanagement/game/themes/Temptation/[Options]buttonlyrics.png
new file mode 100755
index 00000000..0392ab33
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Options]buttonlyrics.png differ
diff --git a/songmanagement/game/themes/Temptation/[Options]buttonrecord.png b/songmanagement/game/themes/Temptation/[Options]buttonrecord.png
new file mode 100755
index 00000000..7ab2c165
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Options]buttonrecord.png differ
diff --git a/songmanagement/game/themes/Temptation/[Options]buttonsound.png b/songmanagement/game/themes/Temptation/[Options]buttonsound.png
new file mode 100755
index 00000000..21a47500
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[Options]buttonsound.png differ
diff --git a/songmanagement/game/themes/Temptation/[bg-load]16-9.png b/songmanagement/game/themes/Temptation/[bg-load]16-9.png
new file mode 100755
index 00000000..1de5d1b9
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[bg-load]16-9.png differ
diff --git a/songmanagement/game/themes/Temptation/[bg-load]4-3.png b/songmanagement/game/themes/Temptation/[bg-load]4-3.png
new file mode 100755
index 00000000..95a8b4df
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[bg-load]4-3.png differ
diff --git a/songmanagement/game/themes/Temptation/[bg-main]16-9.png b/songmanagement/game/themes/Temptation/[bg-main]16-9.png
new file mode 100755
index 00000000..3a7ff375
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[bg-main]16-9.png differ
diff --git a/songmanagement/game/themes/Temptation/[bg-main]4-3.png b/songmanagement/game/themes/Temptation/[bg-main]4-3.png
new file mode 100755
index 00000000..b8e912b1
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[bg-main]4-3.png differ
diff --git a/songmanagement/game/themes/Temptation/[bg-title]16-9.png b/songmanagement/game/themes/Temptation/[bg-title]16-9.png
new file mode 100755
index 00000000..e522c08c
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[bg-title]16-9.png differ
diff --git a/songmanagement/game/themes/Temptation/[bg-title]4-3.png b/songmanagement/game/themes/Temptation/[bg-title]4-3.png
new file mode 100755
index 00000000..e3a3c6ce
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[bg-title]4-3.png differ
diff --git a/songmanagement/game/themes/Temptation/[button]13.png b/songmanagement/game/themes/Temptation/[button]13.png
new file mode 100755
index 00000000..05afe08d
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[button]13.png differ
diff --git a/songmanagement/game/themes/Temptation/[button]alt.png b/songmanagement/game/themes/Temptation/[button]alt.png
new file mode 100755
index 00000000..55fc61e7
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[button]alt.png differ
diff --git a/songmanagement/game/themes/Temptation/[button]az.png b/songmanagement/game/themes/Temptation/[button]az.png
new file mode 100755
index 00000000..b87bf871
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[button]az.png differ
diff --git a/songmanagement/game/themes/Temptation/[button]enter.png b/songmanagement/game/themes/Temptation/[button]enter.png
new file mode 100755
index 00000000..35c13242
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[button]enter.png differ
diff --git a/songmanagement/game/themes/Temptation/[button]esc.png b/songmanagement/game/themes/Temptation/[button]esc.png
new file mode 100755
index 00000000..13843b5a
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[button]esc.png differ
diff --git a/songmanagement/game/themes/Temptation/[button]j.png b/songmanagement/game/themes/Temptation/[button]j.png
new file mode 100755
index 00000000..e9e49ecb
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[button]j.png differ
diff --git a/songmanagement/game/themes/Temptation/[button]m.png b/songmanagement/game/themes/Temptation/[button]m.png
new file mode 100755
index 00000000..f20687da
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[button]m.png differ
diff --git a/songmanagement/game/themes/Temptation/[button]navi.png b/songmanagement/game/themes/Temptation/[button]navi.png
new file mode 100755
index 00000000..8c242314
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[button]navi.png differ
diff --git a/songmanagement/game/themes/Temptation/[button]p.png b/songmanagement/game/themes/Temptation/[button]p.png
new file mode 100755
index 00000000..6b0ac29f
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[button]p.png differ
diff --git a/songmanagement/game/themes/Temptation/[edit]buttonconvert.png b/songmanagement/game/themes/Temptation/[edit]buttonconvert.png
new file mode 100755
index 00000000..672de317
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[edit]buttonconvert.png differ
diff --git a/songmanagement/game/themes/Temptation/[effect]goldenNoteStar.png b/songmanagement/game/themes/Temptation/[effect]goldenNoteStar.png
new file mode 100755
index 00000000..7bd6225f
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[effect]goldenNoteStar.png differ
diff --git a/songmanagement/game/themes/Temptation/[effect]perfectNoteStar.png b/songmanagement/game/themes/Temptation/[effect]perfectNoteStar.png
new file mode 100755
index 00000000..99132c39
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[effect]perfectNoteStar.png differ
diff --git a/songmanagement/game/themes/Temptation/[helper]buttonFade.png b/songmanagement/game/themes/Temptation/[helper]buttonFade.png
new file mode 100755
index 00000000..c51465db
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[helper]buttonFade.png differ
diff --git a/songmanagement/game/themes/Temptation/[helper]rectangle.png b/songmanagement/game/themes/Temptation/[helper]rectangle.png
new file mode 100755
index 00000000..8c607396
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[helper]rectangle.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]cd.png b/songmanagement/game/themes/Temptation/[icon]cd.png
new file mode 100755
index 00000000..6c1157c9
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]cd.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]error.png b/songmanagement/game/themes/Temptation/[icon]error.png
new file mode 100755
index 00000000..6431ddec
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]error.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]main.png b/songmanagement/game/themes/Temptation/[icon]main.png
new file mode 100755
index 00000000..516ca7f5
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]main.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]options.png b/songmanagement/game/themes/Temptation/[icon]options.png
new file mode 100755
index 00000000..628b8aca
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]options.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]party.png b/songmanagement/game/themes/Temptation/[icon]party.png
new file mode 100755
index 00000000..a555d928
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]party.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]question.png b/songmanagement/game/themes/Temptation/[icon]question.png
new file mode 100755
index 00000000..49223ad2
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]question.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]score.png b/songmanagement/game/themes/Temptation/[icon]score.png
new file mode 100755
index 00000000..b9ec2aa5
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]score.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]song_menu.png b/songmanagement/game/themes/Temptation/[icon]song_menu.png
new file mode 100755
index 00000000..3ef99d0a
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]song_menu.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]song_search.png b/songmanagement/game/themes/Temptation/[icon]song_search.png
new file mode 100755
index 00000000..365bdac6
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]song_search.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]song_video.png b/songmanagement/game/themes/Temptation/[icon]song_video.png
new file mode 100755
index 00000000..7ae7110a
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]song_video.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]stats.png b/songmanagement/game/themes/Temptation/[icon]stats.png
new file mode 100755
index 00000000..7b888f4f
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]stats.png differ
diff --git a/songmanagement/game/themes/Temptation/[icon]video.png b/songmanagement/game/themes/Temptation/[icon]video.png
new file mode 100755
index 00000000..7ae7110a
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[icon]video.png differ
diff --git a/songmanagement/game/themes/Temptation/[interface]cursor.png b/songmanagement/game/themes/Temptation/[interface]cursor.png
new file mode 100755
index 00000000..0fe390f0
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[interface]cursor.png differ
diff --git a/songmanagement/game/themes/Temptation/[interface]cursor_pressed.png b/songmanagement/game/themes/Temptation/[interface]cursor_pressed.png
new file mode 100755
index 00000000..fa0056cc
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[interface]cursor_pressed.png differ
diff --git a/songmanagement/game/themes/Temptation/[interface]dialog_background.png b/songmanagement/game/themes/Temptation/[interface]dialog_background.png
new file mode 100755
index 00000000..ed032349
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[interface]dialog_background.png differ
diff --git a/songmanagement/game/themes/Temptation/[interface]select_arrow_left.png b/songmanagement/game/themes/Temptation/[interface]select_arrow_left.png
new file mode 100755
index 00000000..e4a32d2d
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[interface]select_arrow_left.png differ
diff --git a/songmanagement/game/themes/Temptation/[interface]select_arrow_right.png b/songmanagement/game/themes/Temptation/[interface]select_arrow_right.png
new file mode 100755
index 00000000..b2a29793
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[interface]select_arrow_right.png differ
diff --git a/songmanagement/game/themes/Temptation/[interface]selectbg_search.png b/songmanagement/game/themes/Temptation/[interface]selectbg_search.png
new file mode 100755
index 00000000..57d0ca88
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[interface]selectbg_search.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]button.png b/songmanagement/game/themes/Temptation/[main]button.png
new file mode 100755
index 00000000..bb69fd52
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]button.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]button2.png b/songmanagement/game/themes/Temptation/[main]button2.png
new file mode 100755
index 00000000..64c165e1
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]button2.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]buttonedit.png b/songmanagement/game/themes/Temptation/[main]buttonedit.png
new file mode 100755
index 00000000..79bd3767
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]buttonedit.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]buttonexit.png b/songmanagement/game/themes/Temptation/[main]buttonexit.png
new file mode 100755
index 00000000..6ee46df6
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]buttonexit.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]buttonf.jpg b/songmanagement/game/themes/Temptation/[main]buttonf.jpg
new file mode 100755
index 00000000..d844add5
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]buttonf.jpg differ
diff --git a/songmanagement/game/themes/Temptation/[main]buttonoption.png b/songmanagement/game/themes/Temptation/[main]buttonoption.png
new file mode 100755
index 00000000..f7aa2e95
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]buttonoption.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]buttonparty.png b/songmanagement/game/themes/Temptation/[main]buttonparty.png
new file mode 100755
index 00000000..3c6939a3
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]buttonparty.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]buttonsolo.png b/songmanagement/game/themes/Temptation/[main]buttonsolo.png
new file mode 100755
index 00000000..f436c957
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]buttonsolo.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]buttonstats.png b/songmanagement/game/themes/Temptation/[main]buttonstats.png
new file mode 100755
index 00000000..8159086b
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]buttonstats.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]mainBar.png b/songmanagement/game/themes/Temptation/[main]mainBar.png
new file mode 100755
index 00000000..d10b32de
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]mainBar.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]playerNumberBox.png b/songmanagement/game/themes/Temptation/[main]playerNumberBox.png
new file mode 100755
index 00000000..3336ef56
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]playerNumberBox.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]selectbg.png b/songmanagement/game/themes/Temptation/[main]selectbg.png
new file mode 100755
index 00000000..f482d083
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]selectbg.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]songCover.jpg b/songmanagement/game/themes/Temptation/[main]songCover.jpg
new file mode 100755
index 00000000..7cf8930b
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]songCover.jpg differ
diff --git a/songmanagement/game/themes/Temptation/[main]songSelection1.png b/songmanagement/game/themes/Temptation/[main]songSelection1.png
new file mode 100755
index 00000000..6a15daec
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]songSelection1.png differ
diff --git a/songmanagement/game/themes/Temptation/[main]songSelection2.png b/songmanagement/game/themes/Temptation/[main]songSelection2.png
new file mode 100755
index 00000000..17c76e29
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[main]songSelection2.png differ
diff --git a/songmanagement/game/themes/Temptation/[menu]PopUpFg.png b/songmanagement/game/themes/Temptation/[menu]PopUpFg.png
new file mode 100755
index 00000000..2c9785b4
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[menu]PopUpFg.png differ
diff --git a/songmanagement/game/themes/Temptation/[menu]jumpToBg.png b/songmanagement/game/themes/Temptation/[menu]jumpToBg.png
new file mode 100755
index 00000000..8e3a3a00
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[menu]jumpToBg.png differ
diff --git a/songmanagement/game/themes/Temptation/[menu]songMenuBg.png b/songmanagement/game/themes/Temptation/[menu]songMenuBg.png
new file mode 100755
index 00000000..92beff8e
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[menu]songMenuBg.png differ
diff --git a/songmanagement/game/themes/Temptation/[menu]songMenuSelectBg.png b/songmanagement/game/themes/Temptation/[menu]songMenuSelectBg.png
new file mode 100755
index 00000000..8ff5eef8
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[menu]songMenuSelectBg.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]Joker.png b/songmanagement/game/themes/Temptation/[party]Joker.png
new file mode 100755
index 00000000..b44489e0
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]Joker.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]playerButton.png b/songmanagement/game/themes/Temptation/[party]playerButton.png
new file mode 100755
index 00000000..9126b031
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]playerButton.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]playerTeamButton.png b/songmanagement/game/themes/Temptation/[party]playerTeamButton.png
new file mode 100755
index 00000000..b8be88eb
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]playerTeamButton.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]playerselectbg.png b/songmanagement/game/themes/Temptation/[party]playerselectbg.png
new file mode 100755
index 00000000..48815fb6
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]playerselectbg.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]pointer.png b/songmanagement/game/themes/Temptation/[party]pointer.png
new file mode 100755
index 00000000..2292d6c1
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]pointer.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]roundBG1.png b/songmanagement/game/themes/Temptation/[party]roundBG1.png
new file mode 100755
index 00000000..96197c40
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]roundBG1.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]roundBG2.png b/songmanagement/game/themes/Temptation/[party]roundBG2.png
new file mode 100755
index 00000000..af55fcf3
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]roundBG2.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]roundBG3.png b/songmanagement/game/themes/Temptation/[party]roundBG3.png
new file mode 100755
index 00000000..70981f39
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]roundBG3.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]roundBG4.png b/songmanagement/game/themes/Temptation/[party]roundBG4.png
new file mode 100755
index 00000000..5d1c50d7
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]roundBG4.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]roundTeamButton.png b/songmanagement/game/themes/Temptation/[party]roundTeamButton.png
new file mode 100755
index 00000000..4cb40817
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]roundTeamButton.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]scoreBG1.png b/songmanagement/game/themes/Temptation/[party]scoreBG1.png
new file mode 100755
index 00000000..044c1d7b
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]scoreBG1.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]scoreBG2.png b/songmanagement/game/themes/Temptation/[party]scoreBG2.png
new file mode 100755
index 00000000..fe720320
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]scoreBG2.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]scoreDecoration.png b/songmanagement/game/themes/Temptation/[party]scoreDecoration.png
new file mode 100755
index 00000000..388077e6
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]scoreDecoration.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]teamPoints.png b/songmanagement/game/themes/Temptation/[party]teamPoints.png
new file mode 100755
index 00000000..83c4f7a8
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]teamPoints.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]winDecoration.png b/songmanagement/game/themes/Temptation/[party]winDecoration.png
new file mode 100755
index 00000000..f84dbc8a
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]winDecoration.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]winTeamButton1.png b/songmanagement/game/themes/Temptation/[party]winTeamButton1.png
new file mode 100755
index 00000000..ab2cc37e
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]winTeamButton1.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]winTeamButton2.png b/songmanagement/game/themes/Temptation/[party]winTeamButton2.png
new file mode 100755
index 00000000..adf07767
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]winTeamButton2.png differ
diff --git a/songmanagement/game/themes/Temptation/[party]winTeamButton3.png b/songmanagement/game/themes/Temptation/[party]winTeamButton3.png
new file mode 100755
index 00000000..d57ec2f3
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[party]winTeamButton3.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]Line.png b/songmanagement/game/themes/Temptation/[score]Line.png
new file mode 100755
index 00000000..954caf94
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]Line.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]bar_box_dark.png b/songmanagement/game/themes/Temptation/[score]bar_box_dark.png
new file mode 100755
index 00000000..e4fbfa41
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]bar_box_dark.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]bar_box_light.png b/songmanagement/game/themes/Temptation/[score]bar_box_light.png
new file mode 100755
index 00000000..ddc17ed8
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]bar_box_light.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]bar_box_lightest.png b/songmanagement/game/themes/Temptation/[score]bar_box_lightest.png
new file mode 100755
index 00000000..995bb9ef
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]bar_box_lightest.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]box.png b/songmanagement/game/themes/Temptation/[score]box.png
new file mode 100755
index 00000000..71a0cee6
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]box.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]endcap.png b/songmanagement/game/themes/Temptation/[score]endcap.png
new file mode 100755
index 00000000..3cccd2e1
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]endcap.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]glass_box.png b/songmanagement/game/themes/Temptation/[score]glass_box.png
new file mode 100755
index 00000000..c0cf2a9c
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]glass_box.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]level.png b/songmanagement/game/themes/Temptation/[score]level.png
new file mode 100755
index 00000000..1f627560
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]level.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]levelRound.png b/songmanagement/game/themes/Temptation/[score]levelRound.png
new file mode 100755
index 00000000..2bc7a6b8
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]levelRound.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]level_dark.png b/songmanagement/game/themes/Temptation/[score]level_dark.png
new file mode 100755
index 00000000..da4fd407
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]level_dark.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]level_dark_round.png b/songmanagement/game/themes/Temptation/[score]level_dark_round.png
new file mode 100755
index 00000000..de239cb2
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]level_dark_round.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]level_light.png b/songmanagement/game/themes/Temptation/[score]level_light.png
new file mode 100755
index 00000000..1c1c8a4d
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]level_light.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]level_light_round.png b/songmanagement/game/themes/Temptation/[score]level_light_round.png
new file mode 100755
index 00000000..641151a5
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]level_light_round.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]level_lightest.png b/songmanagement/game/themes/Temptation/[score]level_lightest.png
new file mode 100755
index 00000000..f02fdf7b
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]level_lightest.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]level_lightest_round.png b/songmanagement/game/themes/Temptation/[score]level_lightest_round.png
new file mode 100755
index 00000000..9f1bb09e
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]level_lightest_round.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]rating_0.png b/songmanagement/game/themes/Temptation/[score]rating_0.png
new file mode 100755
index 00000000..7e836b99
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]rating_0.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]rating_1.png b/songmanagement/game/themes/Temptation/[score]rating_1.png
new file mode 100755
index 00000000..556821cb
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]rating_1.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]rating_2.png b/songmanagement/game/themes/Temptation/[score]rating_2.png
new file mode 100755
index 00000000..ffa23fd3
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]rating_2.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]rating_3.png b/songmanagement/game/themes/Temptation/[score]rating_3.png
new file mode 100755
index 00000000..5204dc5f
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]rating_3.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]rating_4.png b/songmanagement/game/themes/Temptation/[score]rating_4.png
new file mode 100755
index 00000000..f5d7267c
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]rating_4.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]rating_5.png b/songmanagement/game/themes/Temptation/[score]rating_5.png
new file mode 100755
index 00000000..0f6a553b
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]rating_5.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]rating_6.png b/songmanagement/game/themes/Temptation/[score]rating_6.png
new file mode 100755
index 00000000..e8127c85
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]rating_6.png differ
diff --git a/songmanagement/game/themes/Temptation/[score]rating_7.png b/songmanagement/game/themes/Temptation/[score]rating_7.png
new file mode 100755
index 00000000..6b1d30f5
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[score]rating_7.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player1]lyric_active.png b/songmanagement/game/themes/Temptation/[sing.player1]lyric_active.png
new file mode 100755
index 00000000..089c8c5e
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player1]lyric_active.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player1]lyric_inactive.png b/songmanagement/game/themes/Temptation/[sing.player1]lyric_inactive.png
new file mode 100755
index 00000000..a349007d
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player1]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player2]lyric_active.png b/songmanagement/game/themes/Temptation/[sing.player2]lyric_active.png
new file mode 100755
index 00000000..509767fa
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player2]lyric_active.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player2]lyric_inactive.png b/songmanagement/game/themes/Temptation/[sing.player2]lyric_inactive.png
new file mode 100755
index 00000000..ac40ec61
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player2]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player3]lyric_active.png b/songmanagement/game/themes/Temptation/[sing.player3]lyric_active.png
new file mode 100755
index 00000000..7b130ac5
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player3]lyric_active.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player3]lyric_inactive.png b/songmanagement/game/themes/Temptation/[sing.player3]lyric_inactive.png
new file mode 100755
index 00000000..c5a00600
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player3]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player4]lyric_active.png b/songmanagement/game/themes/Temptation/[sing.player4]lyric_active.png
new file mode 100755
index 00000000..993041fd
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player4]lyric_active.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player4]lyric_inactive.png b/songmanagement/game/themes/Temptation/[sing.player4]lyric_inactive.png
new file mode 100755
index 00000000..f09669b2
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player4]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player5]lyric_active.png b/songmanagement/game/themes/Temptation/[sing.player5]lyric_active.png
new file mode 100755
index 00000000..631dc9c3
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player5]lyric_active.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player5]lyric_inactive.png b/songmanagement/game/themes/Temptation/[sing.player5]lyric_inactive.png
new file mode 100755
index 00000000..716071e8
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player5]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player6]lyric_active.png b/songmanagement/game/themes/Temptation/[sing.player6]lyric_active.png
new file mode 100755
index 00000000..65133d03
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player6]lyric_active.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing.player6]lyric_inactive.png b/songmanagement/game/themes/Temptation/[sing.player6]lyric_inactive.png
new file mode 100755
index 00000000..0c5f34d3
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing.player6]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]LyricsBall.png b/songmanagement/game/themes/Temptation/[sing]LyricsBall.png
new file mode 100755
index 00000000..4297b31a
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]LyricsBall.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]lineBonusPopUp.png b/songmanagement/game/themes/Temptation/[sing]lineBonusPopUp.png
new file mode 100755
index 00000000..c7bd0a41
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]lineBonusPopUp.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]lyricsHelpBar.png b/songmanagement/game/themes/Temptation/[sing]lyricsHelpBar.png
new file mode 100755
index 00000000..59707c21
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]lyricsHelpBar.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]notesBgLeft.png b/songmanagement/game/themes/Temptation/[sing]notesBgLeft.png
new file mode 100755
index 00000000..9fe2621c
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]notesBgLeft.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]notesBgMid.png b/songmanagement/game/themes/Temptation/[sing]notesBgMid.png
new file mode 100755
index 00000000..612da5d3
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]notesBgMid.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]notesBgRight.png b/songmanagement/game/themes/Temptation/[sing]notesBgRight.png
new file mode 100755
index 00000000..a6f42c33
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]notesBgRight.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]notesLeft.png b/songmanagement/game/themes/Temptation/[sing]notesLeft.png
new file mode 100755
index 00000000..8feb2364
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]notesLeft.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]notesMid.png b/songmanagement/game/themes/Temptation/[sing]notesMid.png
new file mode 100755
index 00000000..15eb1915
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]notesMid.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]notesPlainLeft.png b/songmanagement/game/themes/Temptation/[sing]notesPlainLeft.png
new file mode 100755
index 00000000..37a46c17
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]notesPlainLeft.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]notesPlainMid.png b/songmanagement/game/themes/Temptation/[sing]notesPlainMid.png
new file mode 100755
index 00000000..46fd0518
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]notesPlainMid.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]notesPlainRight.png b/songmanagement/game/themes/Temptation/[sing]notesPlainRight.png
new file mode 100755
index 00000000..7b3854f0
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]notesPlainRight.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]notesRight.png b/songmanagement/game/themes/Temptation/[sing]notesRight.png
new file mode 100755
index 00000000..2c0536da
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]notesRight.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]p.png b/songmanagement/game/themes/Temptation/[sing]p.png
new file mode 100755
index 00000000..7458d8e5
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]p.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]pause.png b/songmanagement/game/themes/Temptation/[sing]pause.png
new file mode 100755
index 00000000..f5ab158c
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]pause.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]scoreBg.jpg b/songmanagement/game/themes/Temptation/[sing]scoreBg.jpg
new file mode 100755
index 00000000..4a4459f6
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]scoreBg.jpg differ
diff --git a/songmanagement/game/themes/Temptation/[sing]scoreBg.png b/songmanagement/game/themes/Temptation/[sing]scoreBg.png
new file mode 100755
index 00000000..db6ba67f
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]scoreBg.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]singBarBack.png b/songmanagement/game/themes/Temptation/[sing]singBarBack.png
new file mode 100755
index 00000000..14d2ba42
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]singBarBack.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]singBarBar.jpg b/songmanagement/game/themes/Temptation/[sing]singBarBar.jpg
new file mode 100755
index 00000000..4fd9bde9
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]singBarBar.jpg differ
diff --git a/songmanagement/game/themes/Temptation/[sing]singBarBar.png b/songmanagement/game/themes/Temptation/[sing]singBarBar.png
new file mode 100755
index 00000000..9c57057b
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]singBarBar.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]singBarFront.png b/songmanagement/game/themes/Temptation/[sing]singBarFront.png
new file mode 100755
index 00000000..42477c5a
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]singBarFront.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]textBar.png b/songmanagement/game/themes/Temptation/[sing]textBar.png
new file mode 100755
index 00000000..d2069235
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]textBar.png differ
diff --git a/songmanagement/game/themes/Temptation/[sing]timeBar.jpg b/songmanagement/game/themes/Temptation/[sing]timeBar.jpg
new file mode 100755
index 00000000..cc5cb552
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]timeBar.jpg differ
diff --git a/songmanagement/game/themes/Temptation/[sing]timeBarBG.png b/songmanagement/game/themes/Temptation/[sing]timeBarBG.png
new file mode 100755
index 00000000..0457d387
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[sing]timeBarBG.png differ
diff --git a/songmanagement/game/themes/Temptation/[special]bar1.png b/songmanagement/game/themes/Temptation/[special]bar1.png
new file mode 100755
index 00000000..5c0b2310
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[special]bar1.png differ
diff --git a/songmanagement/game/themes/Temptation/[special]bar2.png b/songmanagement/game/themes/Temptation/[special]bar2.png
new file mode 100755
index 00000000..05287fa6
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[special]bar2.png differ
diff --git a/songmanagement/game/themes/Temptation/[special]bg_fade.png b/songmanagement/game/themes/Temptation/[special]bg_fade.png
new file mode 100755
index 00000000..dc3248ef
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[special]bg_fade.png differ
diff --git a/songmanagement/game/themes/Temptation/[stat]detailBG1.png b/songmanagement/game/themes/Temptation/[stat]detailBG1.png
new file mode 100755
index 00000000..8e589bf3
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[stat]detailBG1.png differ
diff --git a/songmanagement/game/themes/Temptation/[stat]mainBG1.png b/songmanagement/game/themes/Temptation/[stat]mainBG1.png
new file mode 100755
index 00000000..60918a27
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[stat]mainBG1.png differ
diff --git a/songmanagement/game/themes/Temptation/[stat]mainBG2.png b/songmanagement/game/themes/Temptation/[stat]mainBG2.png
new file mode 100755
index 00000000..be1e1be8
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[stat]mainBG2.png differ
diff --git a/songmanagement/game/themes/Temptation/[stat]mainBG3.png b/songmanagement/game/themes/Temptation/[stat]mainBG3.png
new file mode 100755
index 00000000..fa5053aa
Binary files /dev/null and b/songmanagement/game/themes/Temptation/[stat]mainBG3.png differ
diff --git a/songmanagement/game/themes/Verdure.ini b/songmanagement/game/themes/Verdure.ini
new file mode 100644
index 00000000..126e0134
--- /dev/null
+++ b/songmanagement/game/themes/Verdure.ini
@@ -0,0 +1,8994 @@
+;1.10
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+
+[Theme]
+Name = Verdure
+Creator = MezzoX
+US_Version = USD 110
+
+[Colors]
+White = 255 255 255
+LightBlue = 119 187 210
+DarkBlue = 28 126 171
+LightRed = 170 146 146
+DarkRed = 155 113 113
+LightGreen = 136 168 136
+DarkGreen = 106 152 104
+LightPurple = 155 136 168
+DarkPurple = 145 104 152
+LightOrange = 168 155 136
+DarkOrange = 151 131 76
+LightYellow = 168 168 136
+DarkYellow = 150 151 76
+Turkis = 13 186 167
+GrayLightest = 223 223 223
+GrayLight = 191 191 191
+Gray = 127 127 127
+GrayDark = 63 63 63
+Black = 0 0 0
+GrayPopup = 51 51 51
+Gold = 255 223 31
+Silver = 223 223 223
+Bronze = 205 127 50
+Red = 255 0 0
+
+[Loading]
+[LoadingBackground]
+Tex = LoadingBG
+Color = DarkRed
+Type = Colorized
+
+[LoadingStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[LoadingStatic3]
+X = 150
+Y = 180
+W = 500
+H = 180
+Z = 0.4
+Tex = LoadLogo
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LoadingStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Z = 0.4
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LoadingText1]
+X = 30
+Y = 548
+Color = White
+Font = 0
+Align = 0
+Size = 24
+Text = SING_LOADING
+Reflection = 1
+ReflectionSpacing = 13
+
+[LoadingText2]
+X = 790
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = US_VERSION
+Reflection = 1
+ReflectionSpacing = 13
+
+[Main]
+[MainBackground]
+Tex = MainBG
+
+[MainStatic1]
+X = 110
+Y = 190
+W = 25
+H = 23
+Tex = MainIcon
+Color = Black
+Type = Transparent
+
+[MainStatic6]
+X = 95
+Y = 180
+W = 500
+H = 75
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[MainText1]
+X = 140
+Y = 176
+Color = Black
+Font = 0
+Size = 54
+Align = 0
+Text = SING_MENU
+
+[MainTextDescriptionLong]
+X = 140
+Y = 223
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[MainStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Z = 0.4
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Z = 0.5
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainText2]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[MainStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Z = 0.5
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[MainText3]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_SELECT
+Reflection = 1
+ReflectionSpacing = 13
+
+[MainButtonSolo]
+X = 95
+Y = 270
+W = 150
+H = 50
+Tex = ButtonLeft
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+;DeSelectReflectionSpacing = 280
+;Fade = 1
+;FadeText = 1
+;SelectH = 150
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+
+[MainButtonSoloText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_SING
+Color = White
+
+[MainButtonMulti]
+X = 250
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+;DeSelectReflectionSpacing = 280
+;Fade = 1
+;FadeText = 1
+;SelectH = 150
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[MainButtonMultiText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_MULTI
+Color = White
+
+[MainButtonCollection1]
+X = 405
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+;DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 0
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+FirstChild = 3
+
+[MainButtonCollection1Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_TOOLS
+Color = White
+
+[MainButtonStats]
+X = 410
+Y = 310
+W = 140
+H = 30
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+Parent = 1
+
+[MainButtonStatsText1]
+X = 70
+Y = 3
+Font = 0
+Size = 24
+Align = 1
+Text = SING_STATS
+Color = White
+
+[MainButtonEditor]
+X = 410
+Y = 345
+W = 140
+H = 30
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+Parent = 1
+
+[MainButtonEditorText1]
+X = 70
+Y = 3
+Font = 0
+Size = 24
+Align = 1
+Text = SING_EDITOR
+Color = White
+
+[MainButtonOptions]
+X = 410
+Y = 380
+W = 140
+H = 30
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+Parent = 1
+
+[MainButtonOptionsText1]
+X = 70
+Y = 3
+Font = 0
+Size = 24
+Align = 1
+Text = SING_OPTIONS
+Color = White
+
+[MainButtonExit]
+X = 560
+Y = 270
+W = 150
+H = 50
+Tex = ButtonRight
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+;DeSelectReflectionSpacing = 280
+;Fade = 1
+;FadeText = 1
+;SelectH = 150
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[MainButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EXIT
+Color = White
+
+#######
+###############
+########
+
+[Song]
+
+[SongBackground]
+Tex = SongBG
+
+[SongStaticNonParty1]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = SongCD
+Type = Transparent
+
+[SongTextCat]
+X = 70
+Y = 60
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = SING_SONG_SELECTION_DESC
+
+[SongStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Z = 0.4
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Z = 0.951
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongCover]
+X = 300
+Y = 120
+W = 325
+H = 200
+Reflections = 1
+Style=5
+
+[SongEqualizer]
+Visible = 1
+Direction = 1
+Color = ColorDark
+Alpha = 1
+X = 255
+Y = 476
+PieceW = 4
+PieceH = 4
+Space = 1
+Bands = 5
+Length = 15
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongVideoIcon]
+X = 310
+Y = 445
+W = 24
+H = 24
+Z = 0.95
+Color = White
+Tex = icon_song_video
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 22
+
+:[SongStatic3]
+:X = 278
+;Y = 120
+;W = 244
+;H = 200
+;Z = 0.95
+;Color = ColorLight
+;Tex = SongSelection1
+;Type = Transparent
+
+[SongStatic3]
+X = 283
+Y = 110
+W = 230
+H = 210
+Tex = SongSelection1
+Color = White
+Type = Transparent
+
+[SongStatic4]
+X = 283
+Y = 320
+W = 230
+H = 160
+Z = 0.95
+Color = White
+Tex = SongSelection2
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongStatic5]
+X = 20
+Y = 10
+W = 500
+H = 85
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[SongTextArtist]
+X = 400
+Y = 328
+W = 200
+Color = Black
+Font = 1
+Size = 24
+Align = 1
+Text =
+
+[SongTextTitle]
+X = 400
+Y = 394
+W = 200
+Color = ColorDark
+Font = 0
+Size = 25
+Align = 1
+Text =
+
+[SongTextNumber]
+X = 492
+Y = 457
+Z = 0.95
+Color = Black
+Size = 18
+Align = 2
+Reflection = 1
+ReflectionSpacing = 21
+
+#Variable statics and texts for song-screen in sing- and partymode
+# There can be an unlimited Number of Statics and Texts, As long
+# as the numbers are in order.
+# Statics that are shown in PartyMode Only are Named_
+#        SongStaticParty[No]
+# Texts that are shown in PartyMode Only are Named_
+#        SongTextParty[No]
+# Statics that are shown in Normal Mode Only are Named_
+#        SongStaticNonParty[No]
+# Texts that are shown in Normal Mode Only are Named_
+#        SongTextNonParty[No]
+#Here are the ones for singmode
+
+[SongTextNonParty1]
+X = 70
+Y = 6
+Color = Black
+Font = 0
+Size = 60
+Text = SING_SONG_SELECTION
+Align = 0
+
+# NAVBAR #########################
+# Jump to a letter with [ALT] + [A..Z]
+[SongStaticNonParty2]
+X = 260
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAlt
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty2]
+X = 292
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = +
+Reflection = 1
+ReflectionSpacing = 13
+
+[SongStaticNonParty3]
+X = 300
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty3]
+X = 340
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_GOTO
+Reflection = 1
+ReflectionSpacing = 13
+
+# Menu opens with [M]
+[SongStaticNonParty4]
+X = 425
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonM
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty4]
+X = 465
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_MENU
+Reflection = 1
+ReflectionSpacing = 13
+
+# The so famous search, shown with [J]
+[SongStaticNonParty5]
+X = 515
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonJ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty5]
+X = 555
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SONG_JUMPTO_DESC
+Reflection = 1
+ReflectionSpacing = 13
+
+# [P]laylist
+[SongStaticNonParty6]
+X = 680
+Y = 545
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonP
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[SongTextNonParty6]
+X = 720
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_SONG_SELECTION_PLAYLIST
+Reflection = 1
+ReflectionSpacing = 13
+
+#and these are the ones for partymode
+[SongStaticParty1]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = PartyIcon
+Type = Transparent
+
+# NAVBAR for party
+# enter a number
+[SongStaticParty2]
+X = 260
+Y = 547
+Z = 0.952
+W = 32
+H = 30
+Tex = Button13
+Color = White
+Type = Transparent
+
+[SongTextParty3]
+X = 300
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SONG_MENU_NAME_PARTY_JOKER
+Reflection = 1
+ReflectionSpacing = 13
+
+# menu
+[SongStaticParty3]
+X = 435
+Y = 547
+Z = 0.952
+W = 32
+H = 30
+Tex = ButtonM
+Color = White
+Type = Transparent
+
+[SongTextParty4]
+X = 475
+Y = 548
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_MENU
+Reflection = 1
+ReflectionSpacing = 13
+
+[SongStaticParty4]
+X = 575
+Y = 547
+Z = 0.952
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[SongTextParty5]
+X = 615
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+#Texts for Party Mode
+[SongTextParty1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = Black
+Text = PARTY_MODE
+
+[SongTextParty2]
+X = 238
+Y = 548
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_SONG_WHEREAMI
+#variable statics end
+
+# Jokers, 5 for each team, only shown in party Mode
+[SongStaticTeam1Joker1]
+Tex = Joker
+X = 520
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker2]
+Tex = Joker
+X = 570
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker3]
+Tex = Joker
+X = 620
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker4]
+Tex = Joker
+X = 670
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam1Joker5]
+Tex = Joker
+X = 720
+Y = 400
+W = 40
+H = 40
+Z = 0.98
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker1]
+Tex = Joker
+X = 520
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker2]
+Tex = Joker
+X = 570
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker3]
+Tex = Joker
+X = 620
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker4]
+Tex = Joker
+X = 670
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam2Joker5]
+Tex = Joker
+X = 720
+Y = 450
+W = 40
+H = 40
+Z = 0.98
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker1]
+Tex = Joker
+X = 520
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker2]
+Tex = Joker
+X = 570
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker3]
+Tex = Joker
+X = 620
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker4]
+Tex = Joker
+X = 670
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+[SongStaticTeam3Joker5]
+Tex = Joker
+X = 720
+Y = 500
+W = 40
+H = 40
+Z = 0.98
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
+
+
+[Sing]
+Texts = 1
+
+[SingBackground]
+Type=color
+ColR=1
+ColB=1
+ColG=1
+
+[SingText1]
+Text = SING_TIME
+X = 43
+Y = 577
+Font = 1
+Size = 18
+Color = White
+Align = 1
+
+[SingStatic1]
+;TextBG
+Tex = LyricBar
+X = 10
+Y = 492
+W = 780
+H = 85
+Color = White
+Type = Transparent
+
+[SingStatic2]
+;TimeBar
+Tex = TimeBar1
+X = 10
+Y = 577
+W = 780
+H = 20
+Color = White
+Type = Transparent
+
+[SingTimeProgress]
+X = 87
+Y = 584
+W = 633
+H = 6
+Color = White
+
+[SingTimeText]
+Text = SING_TIME
+X = 761
+Y = 577
+Font = 1
+Size = 18
+Color = White
+Align = 1
+
+# O N E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#PlayerOne
+[SingP1Static]
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P1Dark
+Type = Colorized
+
+[SingP1Text]
+Text = P1
+X = 25
+Y = 302
+Font = 1
+Size = 18
+Color = DarkGreen
+Align = 0
+
+[SingP1Static2]
+Tex = ScoreBG
+X = 680
+Y = 282
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1TextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1SingBar]
+X = 680
+Y = 316
+W = 100
+H = 8
+
+# T W O  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1TwoPStatic]
+Tex = P
+X = 20
+Y = 117
+W = 30
+H = 28
+Color = P1Dark
+Type = Colorized
+
+[SingP1TwoPText]
+Text = P1
+X = 25
+Y = 122
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP1TwoPStatic2]
+Tex = ScoreBG
+X = 680
+Y = 102
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1TwoPTextScore]
+Text = 00000
+X = 698
+Y = 104
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1TwoPSingBar]
+X = 680
+Y = 136
+W = 100
+H = 8
+
+#Player Two
+[SingP2RStatic]
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P2Dark
+Type = Colorized
+
+[SingP2RText]
+Text = P2
+X = 24
+Y = 302
+Font = 1
+Size = 18
+Color = White
+Align = 0
+
+[SingP2RStatic2]
+Tex = ScoreBG
+X = 680
+Y = 282
+W = 100
+H = 36
+Color = P2Dark
+Type = Colorized
+
+[SingP2RTextScore]
+Text = 00000
+X = 698
+Y = 284
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2RSingBar]
+X = 680
+Y = 316
+W = 100
+H = 8
+
+# T H R E E  P L A Y E R   M O D E # # # # # # # # # # # # # # # # # # # #
+#Player One
+[SingP1ThreePStatic]
+Tex = P
+X = 16
+Y = 59
+W = 50
+H = 44
+Color = P1Dark
+Type = Colorized
+
+[SingP1ThreePText]
+Text = P1
+X = 27
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP1ThreePStatic2]
+Tex = ScoreBG
+X = 75
+Y = 61
+W = 100
+H = 36
+Color = P1Dark
+Type = Colorized
+
+[SingP1ThreePTextScore]
+Text = 00000
+X = 93
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP1ThreePSingBar]
+X = 75
+Y = 95
+W = 100
+H = 8
+
+#Player Two
+[SingP2MStatic]
+Tex = P
+X = 311
+Y = 59
+W = 50
+H = 44
+Color = P2Dark
+Type = Colorized
+
+[SingP2MText]
+Text = P2
+X = 321
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP2MStatic2]
+Tex = ScoreBG
+X = 370
+Y = 61
+W = 100
+H = 36
+Color = P2Dark
+Type = Colorized
+
+[SingP2MTextScore]
+Text = 00000
+X = 388
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP2MSingBar]
+X = 370
+Y = 95
+W = 100
+H = 8
+
+#Player Three
+[SingP3RStatic]
+Tex = P
+X = 611
+Y = 59
+W = 50
+H = 44
+Color = P3Dark
+Type = Colorized
+
+[SingP3RText]
+Text = P3
+X = 621
+Y = 66
+Font = 1
+Size = 24
+Color = White
+Align = 0
+
+[SingP3RStatic2]
+Tex = ScoreBG
+X = 670
+Y = 61
+W = 100
+H = 36
+Color = P3Dark
+Type = Colorized
+
+[SingP3RTextScore]
+Text = 00000
+X = 688
+Y = 63
+Font = 0
+Size = 30
+Color = White
+Align = 0
+
+[SingP3SingBar]
+X = 670
+Y = 95
+W = 100
+H = 8
+
+[Score]
+Texts = 1
+
+[ScoreBackground]
+Tex = ScoreScreenBG
+
+[ScoreText1]
+X = 60
+Y = 6
+Color = Black
+Font = 0
+Size = 60
+Text = SONG_SCORE
+Align = 0
+
+[ScoreTextArtistTitle]
+X = 60
+Y = 59
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = ArtistTitle
+
+[ScoreStatic1]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = ScoreIcon
+Type = Transparent
+
+[ScoreStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[ScoreStatic5]
+X = 20
+Y = 10
+W = 700
+H = 80
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+;[ScoreStatic6]
+;X = 20
+;Y = 110
+;W = 755
+;H = 420
+;z = 0.1
+;Tex = ScoreGlassBG
+;Color = White
+;Type = Transparent
+
+[ScoreText2]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+#end of main stuff
+
+# # # # # # # # # # # # # # # # # # One Player Score # # # # # # # # # # # #
+[ScoreTextName1]
+X = 197
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = Black
+Align = 0
+
+# Rating
+[ScoreStaticRatingPicture1]
+X = 385
+Y = 165
+H = 75
+W = 75
+z = 0.95
+
+[ScoreTextScore1]
+X = 422
+Y = 235
+width = 100
+Color = Black
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+# Note Score
+[ScoreStaticBoxDark1]
+Tex = ScoreBar_box_dark
+X = 200
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes1]
+X = 227
+Y = 322
+Color = Black
+Font = 0
+Size = 30
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore1]
+X = 487
+Y = 322
+Color = Black
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static1]
+Tex = ScoreLine
+X = 200
+Y = 351
+W = 287
+H = 1
+Color = White
+Type = Colorized
+
+# Line Bonus
+[ScoreStaticBoxLight1]
+Tex = ScoreBar_box_light
+X = 200
+Y = 358
+W = 22
+H = 20
+Color = P1Light
+Type = Colorized
+
+[ScoreTextLineBonus1]
+X = 227
+Y = 352
+Color = Black
+Font = 0
+Size = 30
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore1]
+X = 487
+Y = 352
+Color = Black
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+# A simple line
+[ScorePlayer1Static2]
+Tex = ScoreLine
+X = 200
+Y = 382
+W = 287
+H = 1
+Color = White
+Type = Colorized
+
+# Golden Notes
+[ScoreStaticBoxLightest1]
+Tex = ScoreBar_box_lightest
+X = 200
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes1]
+X = 227
+Y = 383
+Color = Black
+Font = 0
+Size = 30
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore1]
+X = 487
+Y = 383
+Color = Black
+Font = 0
+Size = 30
+Align = 2
+Text = 0
+
+#Total Score
+[ScoreStaticPlayerIdBox1]
+Tex = PlayerIDBox01
+X = 200
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+Reflection = 1
+ReflectionSpacing = 31
+
+[ScoreTextTotal1]
+X = 237
+Y = 454
+Color = Black
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 0
+Reflection = 1
+ReflectionSpacing = 26
+
+[ScoreTextTotalSCore1]
+X = 487
+Y = 444
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 0
+Reflection = 1
+ReflectionSpacing = 24
+
+#ScoreBar
+[ScoreStaticBackLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 168
+W = 95
+H = 310
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound1]
+Tex = ScoreLevelRound
+X = 503
+Y = 138
+W = 95
+H = 8
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 400
+W = 95
+H = 10
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound1]
+Tex = ScoreLevelRound
+X = 503
+Y = 392
+W = 95
+H = 8
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer1Static3]
+Tex = ScoreEndCap
+X = 499
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 0
+
+[ScorePlayer1Static4]
+Tex = ScoreGlassBox
+X = 499
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# # # # # # # # # # # # # # # # # # Two Player Score # # # # # # # # # # # #
+# P L A Y E R   O N E
+[ScoreTextName2]
+X = 42
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = Black
+Align = 0
+
+[ScoreStaticRatingPicture2]
+X = 180
+Y = 165
+H = 75
+W = 75
+z = 1.0
+
+[ScoreTextScore2]
+X = 217
+Y = 235
+Width = 100
+Color = Black
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark2]
+Tex = ScoreBar_box_dark
+X = 45
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
+
+[ScoreTextNotes2]
+X = 72
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 0
+
+[ScoreTextNotesScore2]
+X = 282
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLight2]
+Tex = ScoreBar_box_light
+X = 45
+Y = 358
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextLineBonus2]
+X = 72
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 0
+
+[ScoreTextLineBonusScore2]
+X = 282
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreStaticBoxLightest2]
+Tex = ScoreBar_box_lightest
+X = 45
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes2]
+X = 72
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 0
+
+[ScoreTextGoldenNotesScore2]
+X = 282
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
+
+[ScoreTextTotal2]
+X = 82
+Y = 454
+Color = Black
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Reflection = 1
+ReflectionSpacing = 24
+
+[ScoreTextTotalSCore2]
+X = 283
+Y = 444
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Reflection = 1
+ReflectionSpacing = 24
+
+# Lines
+[ScorePlayer2Static1]
+Tex = ScoreLine
+X = 45
+Y = 351
+W = 237
+H = 1
+Type = Colorized
+Color = ColorDark
+
+[ScorePlayer2Static2]
+Tex = ScoreLine
+X = 45
+Y = 382
+W = 237
+H = 1
+Type = Colorized
+Color = ColorDark
+
+[ScoreStaticPlayerIdBox2]
+Tex = PlayerIDBox01
+X = 45
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+Reflection = 1
+ReflectionSpacing = 31
+
+#ScoreBar
+[ScoreStaticBackLevel2]
+Tex = ScoreLevel
+X = 298
+Y = 168
+W = 95
+H = 310
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound2]
+Tex = ScoreLevelRound
+X = 298
+Y = 138
+W = 95
+H = 8
+Color = P1Lightest
+Type = Colorized
+
+[ScoreStaticLevel2]
+Tex = ScoreLevel
+X = 298
+Y = 400
+W = 95
+H = 10
+Color = P1Dark
+Type = Colorized
+
+[ScoreStaticLevelRound2]
+Tex = ScoreLevelRound
+X = 298
+Y = 392
+W = 95
+H = 8
+Color = P1Dark
+Type = Colorized
+
+[ScorePlayer2Static3]
+Tex = ScoreEndCap
+X = 294
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 0
+
+[ScorePlayer2Static4]
+Tex = ScoreGlassBox
+X = 294
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# P L A Y E R   T W O
+[ScoreTextName3]
+X = 758
+Y = 290
+Font = 0
+Size = 30
+Text = P2
+Color = Black
+Align = 2
+
+[ScoreStaticRatingPicture3]
+X = 545
+Y = 165
+H = 75
+W = 75
+
+[ScoreTextScore3]
+X = 583
+Y = 235
+width = 100
+Color = Black
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
+
+[ScoreStaticBoxDark3]
+Tex = ScoreBar_box_dark
+X = 733
+Y = 327
+W = 22
+H = 20
+Color = P2Dark
+Type = Colorized
+
+[ScoreTextNotes3]
+X = 728
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 2
+
+[ScoreTextNotesScore3]
+X = 518
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLight3]
+Tex = ScoreBar_box_light
+X = 733
+Y = 358
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextLineBonus3]
+X = 728
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 2
+
+[ScoreTextLineBonusScore3]
+X = 518
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreStaticBoxLightest3]
+Tex = ScoreBar_box_lightest
+X = 733
+Y = 390
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
+
+[ScoreTextGoldenNotes3]
+X = 728
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 2
+
+[ScoreTextGoldenNotesScore3]
+X = 518
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
+
+[ScoreTextTotal3]
+X = 718
+Y = 454
+Color = Black
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 2
+Reflection = 1
+ReflectionSpacing = 24
+
+[ScoreTextTotalScore3]
+X = 517
+Y = 444
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 00000
+Reflection = 1
+ReflectionSpacing = 24
+
+#Lines
+[ScorePlayer3Static1]
+Tex = ScoreLine
+X = 518
+Y = 351
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScorePlayer3Static2]
+Tex = ScoreLine
+X = 518
+Y = 382
+W = 237
+H = 1
+Type = Colorized
+Color = White
+
+[ScoreStaticPlayerIdBox3]
+Tex = PlayerIDBox02
+X = 729
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+Reflection = 1
+ReflectionSpacing = 31
+
+#ScoreBar
+[ScoreStaticBackLevel3]
+Tex = ScoreLevel
+X = 409
+Y = 168
+W = 95
+H = 310
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticBackLevelRound3]
+Tex = ScoreLevelRound
+X = 409
+Y = 138
+W = 95
+H = 8
+Color = P2Lightest
+Type = Colorized
+
+[ScoreStaticLevel3]
+Tex = ScoreLevel
+X = 409
+Y = 400
+W = 95
+H = 10
+Color = P2Dark
+Type = Colorized
+
+[ScoreStaticLevelRound3]
+Tex = ScoreLevelRound
+X = 409
+Y = 392
+W = 95
+H = 8
+Color = P2Dark
+Type = Colorized
+
+[ScorePlayer3Static3]
+Tex = ScoreEndCap
+X = 405
+Y = 478
+W = 110
+H = 30
+z = 0.9
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 0
+
+[ScorePlayer3Static4]
+Tex = ScoreGlassBox
+X = 405
+Y = 148
+W = 113
+H = 331
+z = 0.89
+Color = White
+Type = Transparent
+
+# # # # # # # # # # # # # # # # # # Three Player Score # # # # # # # # # # # #
+# P L A Y E R  O N E
+[ScoreTextName4]
+X = 20
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P1
+Color = Black
+
+# Rating
+[ScoreStaticRatingPicture4]
+X = 200
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes4]
+X = 20
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = Black
+
+[ScoreTextNotesScore4]
+X = 260
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextLineBonus4]
+X = 20
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Black
+
+[ScoreTextLineBonusScore4]
+X = 260
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextGoldenNotes4]
+X = 20
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Black
+
+[ScoreTextGoldenNotesScore4]
+X = 260
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextScore4]
+X = 20
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = Black
+
+[ScoreTextTotal4]
+X = 47
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Black
+Reflection = 1
+ReflectionSpacing = -1
+
+[ScoreTextTotalScore4]
+X = 260
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Black
+Reflection = 1
+ReflectionSpacing = -3
+
+[ScoreStaticBoxDark4]
+Tex = PlayerNumberBox
+X = 20
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P1Dark
+Z = 0.9
+Reflection = 1
+ReflectionSpacing = 4
+
+[ScorePlayer4Text1]
+X = 24
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = White
+Font = 1
+Size = 15
+Align = 0
+Text = P1
+
+#lines
+[ScorePlayer4Static1]
+X = 20
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer4Static2]
+X = 20
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer4Static3]
+X = 20
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer4Static4]
+X = 20
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer4Static5]
+X = 20
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+# P L A Y E R  T W O
+[ScoreTextName5]
+X = 280
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P2
+Color = Black
+
+# Rating
+[ScoreStaticRatingPicture5]
+X = 460
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes5]
+X = 280
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = Black
+
+[ScoreTextNotesScore5]
+X = 520
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextLineBonus5]
+X = 280
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Black
+
+[ScoreTextLineBonusScore5]
+X = 520
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextGoldenNotes5]
+X = 280
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Black
+
+[ScoreTextGoldenNotesScore5]
+X = 520
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextScore5]
+X = 280
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = Black
+
+[ScoreTextTotal5]
+X = 307
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Black
+Reflection = 1
+ReflectionSpacing = -1
+
+[ScoreTextTotalScore5]
+X = 520
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Black
+Reflection = 1
+ReflectionSpacing = -3
+
+[ScoreStaticBoxDark5]
+Tex = PlayerNumberBox
+X = 280
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P2Dark
+Z = 0.9
+Reflection = 1
+ReflectionSpacing = 4
+
+[ScorePlayer5Text1]
+X = 284
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = Black
+Font = 1
+Size = 15
+Align = 0
+Text = P2
+
+[ScorePlayer5Static1]
+X = 280
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer5Static2]
+X = 280
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer5Static3]
+X = 280
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer5Static4]
+X = 280
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer5Static5]
+X = 280
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+# P L A Y E R  T H R E E
+[ScoreTextName6]
+X = 540
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P3
+Color = Black
+
+# Rating
+[ScoreStaticRatingPicture6]
+X = 720
+Y = 150
+H = 60
+W = 60
+
+[ScoreTextNotes6]
+X = 540
+Y = 220
+Font = 0
+Size = 27
+Align = 0
+Text = SING_NOTES
+Color = Black
+
+[ScoreTextNotesScore6]
+X = 780
+Y = 220
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextLineBonus6]
+X = 540
+Y = 250
+Font = 0
+Size = 27
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Black
+
+[ScoreTextLineBonusScore6]
+X = 780
+Y = 250
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextGoldenNotes6]
+X = 540
+Y = 280
+Font = 0
+Size = 27
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Black
+
+[ScoreTextGoldenNotesScore6]
+X = 780
+Y = 280
+Font = 0
+Size = 30
+Align = 2
+Text = 0000
+Color = Black
+
+[ScoreTextScore6]
+X = 540
+Y = 310
+Font = 1
+Size = 27
+Align = 0
+Text = Tone Deaf
+Color = Black
+
+[ScoreTextTotal6]
+X = 567
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Black
+Reflection = 1
+ReflectionSpacing = -1
+
+[ScoreTextTotalScore6]
+X = 780
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Black
+Reflection = 1
+ReflectionSpacing = -3
+
+[ScoreStaticBoxDark6]
+Tex = PlayerNumberBox
+X = 540
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P3Dark
+Z = 0.9
+Reflection = 1
+ReflectionSpacing = 4
+
+[ScorePlayer6Text1]
+X = 544
+Y = 376
+W = 30
+H = 30
+Z = 1
+Color = Black
+Font = 1
+Size = 15
+Align = 0
+Text = P3
+
+#lines
+[ScorePlayer6Static1]
+X = 540
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer6Static2]
+X = 540
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer6Static3]
+X = 540
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer6Static4]
+X = 540
+Y = 308
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+[ScorePlayer6Static5]
+X = 540
+Y = 338
+W = 240
+H = 4
+Tex = ScoreLine
+Type = Colorized
+Color = Black
+
+##################
+#################################
+#################
+
+[Options]
+Texts = 6
+Fade = 2
+
+[OptionsBackground]
+Tex = OptionsBG
+
+[OptionsStatic1]
+X = 110
+Y = 130
+W = 25
+H = 25
+Color = Black
+Tex = IconOption
+Type = Transparent
+
+[OptionsStatic7]
+X = 95
+Y = 115
+W = 500
+H = 115
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[OptionsText1]
+X = 140
+Y = 115
+Color = Black
+Font = 0
+Size = 54
+Text = SING_OPTIONS
+Align = 0
+
+[OptionsText2]
+X = 140
+Y = 165
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_DESC
+
+[OptionsTextDescription]
+X = 140
+Y = 195
+Color = Color
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[OptionsStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection=1
+ReflectionSpacing=13
+
+[OptionsStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsText4]
+X = 440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_SELECT
+Reflection=1
+ReflectionSpacing=13
+
+[OptionsStatic6]
+X = 550
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsText5]
+X = 590
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_ESC
+Reflection=1
+ReflectionSpacing=13
+
+[OptionsButtonGame]
+X = 95
+Y = 245
+W = 150
+H = 50
+Tex = ButtonLeft
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+;Fade = 1
+;FadeText = 1
+;SelectH = 100
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[OptionsButtonGameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_GAME
+Color = White
+
+[OptionsButtonGraphics]
+X = 250
+Y = 245
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+;Fade = 1
+;FadeText = 1
+;SelectH = 100
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[OptionsButtonGraphicsText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_GRAPHICS
+Color = White
+
+[OptionsButtonSound]
+X = 405
+Y = 245
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+;Fade = 1
+;FadeText = 1
+;SelectH = 100
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[OptionsButtonSoundText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_SOUND
+Color = White
+
+[OptionsButtonLyrics]
+X = 560
+Y = 245
+W = 150
+H = 50
+Tex = ButtonRight
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+;Fade = 1
+;FadeText = 1
+;SelectH = 100
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[OptionsButtonLyricsText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_LYRICS
+Color = White
+
+[OptionsButtonThemes]
+X = 95
+Y = 335
+W = 150
+H = 50
+Tex = ButtonLeft
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+;Fade = 1
+;FadeText = 1
+;SelectH = 100
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[OptionsButtonThemesText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_THEMES
+Color = White
+
+[OptionsButtonRecord]
+X = 250
+Y = 335
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+;Fade = 1
+;FadeText = 1
+;SelectH = 100
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[OptionsButtonRecordText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_RECORD
+Color = White
+Texts = 1
+
+[OptionsButtonAdvanced]
+X = 405
+Y = 335
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+;Fade = 1
+;FadeText = 1
+;SelectH = 100
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[OptionsButtonAdvancedText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_ADVANCED
+Color = White
+Texts = 1
+
+[OptionsButtonExit]
+X = 560
+Y = 335
+W = 150
+H = 50
+Tex = ButtonRight
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Align = 0
+Texts = 1
+;Fade = 1
+;FadeText = 1
+;SelectH = 100
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[OptionsButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+#################
+###########################################################################################
+################
+
+[OptionsGame]
+Texts = 5
+
+[OptionsGameBackground]
+Tex = OptionsBG
+
+[OptionsGameStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = Black
+Tex = IconOption
+Type = Transparent
+
+[OptionsGameStatic6]
+X = 20
+Y = 10
+W = 500
+H = 110
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[OptionsGameText1]
+X = 70
+Y = 5
+Color = Black
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsGameText2]
+X = 70
+Y = 55
+Color = ColorDark
+Size = 30
+Text = SING_OPTIONS_GAME_DESC
+
+[OptionsGameText3]
+X = 70
+Y = 85
+Color = Black
+Size = 30
+Text = SING_OPTIONS_GAME_WHEREAMI
+
+[OptionsGameStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsGameStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGameText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[OptionsGameSelectPlayers]
+Text = SING_OPTIONS_GAME_PLAYERS
+Tex = MainBar
+TexSBG = SelectBG
+Type = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectDifficulty]
+Text = SING_OPTIONS_GAME_DIFFICULTY
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectSlideLanguage]
+Text = SING_OPTIONS_GAME_LANGUAGE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectTabs]
+Text = SING_OPTIONS_GAME_TABS
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectSlideSorting]
+Text = SING_OPTIONS_GAME_SORTING
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameSelectDebug]
+Text = SING_OPTIONS_GAME_DEBUG
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGameButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+Align = 0
+Texts = 1
+
+[OptionsGameButtonExitText1]
+X = 60		
+Y = 5
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+################################
+
+[OptionsGraphics]
+Texts = 5
+
+[OptionsGraphicsBackground]
+Tex = OptionsBG
+
+[OptionsGraphicsStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = Black
+Tex = IconOption
+Type = Transparent
+
+[OptionsGraphicsStatic6]
+X = 20
+Y = 10
+W = 500
+H = 110
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[OptionsGraphicsText1]
+X = 70
+Y = 5
+Color = Black
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsGraphicsText2]
+X = 70
+Y = 55
+Color = ColorDark
+Size = 30
+Text = SING_OPTIONS_GRAPHICS_DESC
+
+[OptionsGraphicsText3]
+X = 70
+Y = 85
+Color = Black
+Size = 30
+Text = SING_OPTIONS_GRAPHICS_WHEREAMI
+
+
+[OptionsGraphicsStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsGraphicsStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Z = 0.5
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsGraphicsText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsGraphicsSelectSlideResolution]
+Text = SING_OPTIONS_GRAPHICS_RESOLUTION
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectFullscreen]
+Text = SING_OPTIONS_GRAPHICS_FULLSCREEN
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectDepth]
+Text = SING_OPTIONS_GRAPHICS_DEPTH
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectVisualizer]
+Text = SING_OPTIONS_GRAPHICS_VISUALIZER
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectOscilloscope]
+Text = SING_OPTIONS_GRAPHICS_OSCILLOSCOPE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsSelectMovieSize]
+Text = SING_OPTIONS_GRAPHICS_MOVIE_SIZE
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsGraphicsButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+Align = 0
+Texts = 1
+
+[OptionsGraphicsButtonExitText1]
+X = 60		
+Y = 5
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[OptionsSound]
+Texts = 5
+
+[OptionsSoundBackground]
+Tex = OptionsBG
+
+[OptionsSoundStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = Black
+Tex = IconOption
+Type = Transparent
+
+[OptionsSoundText1]
+X = 70
+Y = 5
+Color = Black
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsSoundText2]
+X = 70
+Y = 55
+Color = ColorDark
+Size = 30
+Text = SING_OPTIONS_SOUND_DESC
+
+[OptionsSoundText3]
+X = 70
+Y = 85
+Color = Black
+Size = 30
+Text = SING_OPTIONS_SOUND_WHEREAMI
+
+[OptionsSoundStatic6]
+X = 20
+Y = 10
+W = 500
+H = 110
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[OptionsSoundStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsSoundStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsSoundText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsSoundSelectVoicePassthrough]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_SOUND_VOICEPASSTHROUGH
+X = 70
+Y = 130
+W = 250
+H = 35
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectBackgroundMusic]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_SOUND_BACKGROUNDMUSIC
+X = 70
+Y = 170
+W = 250
+H = 35
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectMicBoost]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_SOUND_MIC_BOOST
+X = 70
+Y = 210
+W = 250
+H = 35
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectClickAssist]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_SOUND_CLICK_ASSIST
+X = 70
+Y = 250
+W = 250
+H = 35
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectBeatClick]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_SOUND_BEAT_CLICK
+X = 70
+Y = 290
+W = 250
+H = 35
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectThreshold]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_SOUND_THRESHOLD
+X = 70
+Y = 330
+W = 250
+H = 35
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectSlidePreviewVolume]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_SOUND_PREVIEWVOLUME
+X = 70
+Y = 370
+W = 250
+H = 35
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundSelectSlidePreviewFADING]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_SOUND_PREVIEWFADING
+X = 70
+Y = 410
+W = 250
+H = 35
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsSoundButtonExit]
+X = 70
+Y = 460
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+Align = 0
+Texts = 1
+
+[OptionsSoundButtonExitText1]
+X = 60		
+Y = 5
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[OptionsLyrics]
+Texts = 1
+
+[OptionsLyricsBackground]
+Tex = OptionsBG
+
+[OptionsLyricsStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = Black
+Tex = IconOption
+Type = Transparent
+
+[OptionsLyricsText1]
+X = 70
+Y = 5
+Color = Black
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsLyricsText2]
+X = 70
+Y = 55
+Color = ColorDark
+Size = 30
+Text = SING_OPTIONS_LYRICS_DESC
+
+[OptionsLyricsText3]
+X = 70
+Y = 85
+Color = Black
+Size = 30
+Text = SING_OPTIONS_LYRICS_WHEREAMI
+
+[OptionsLyricsStatic6]
+X = 20
+Y = 10
+W = 500
+H = 110
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[OptionsLyricsStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsLyricsStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsLyricsText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
+Reflection = 1
+ReflectionSpacing = 20
+
+[OptionsLyricsSelectLyricsFont]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_LYRICS_FONT
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsSelectLyricsEffect]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_LYRICS_EFFECT
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsSelectNoteLines]
+Tex = MainBar
+TexSBG = SelectBG
+Text = SING_OPTIONS_LYRICS_NOTELINES
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsLyricsButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+Align = 0
+Texts = 1
+
+[OptionsLyricsButtonExitText1]
+X = 60		
+Y = 5
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[OptionsThemes]
+Texts = 5
+
+[OptionsThemesBackground]
+Tex = OptionsBG
+
+[OptionsThemesStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = Black
+Tex = IconOption
+Type = Transparent
+
+[OptionsThemesText1]
+X = 70
+Y = 5
+Color = Black
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsThemesText2]
+X = 70
+Y = 55
+Color = ColorDark
+Size = 30
+Text = SING_OPTIONS_THEMES_DESC
+
+[OptionsThemesText3]
+X = 70
+Y = 85
+Color = Black
+Size = 30
+Text = SING_OPTIONS_THEMES_WHEREAMI
+
+[OptionsThemesStatic6]
+X = 20
+Y = 10
+W = 500
+H = 110
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[OptionsThemesStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsThemesStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsThemesText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[OptionsThemesSelectTheme]
+Text = SING_OPTIONS_THEMES_THEME
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesSelectSkin]
+Text = SING_OPTIONS_THEMES_SKIN
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesSelectColor]
+Text = SING_OPTIONS_THEMES_COLOR
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsThemesButtonExit]
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+Align = 0
+Texts = 1
+
+[OptionsThemesButtonExitText1]
+X = 60		
+Y = 5
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[OptionsRecord]
+Texts = 5
+
+[OptionsRecordBackground]
+Tex = OptionsBG
+
+[OptionsRecordStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = Black
+Tex = IconOption
+Type = Transparent
+
+[OptionsRecordText1]
+X = 70
+Y = 5
+Color = Black
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsRecordText2]
+X = 70
+Y = 55
+Color = ColorDark
+Size = 30
+Text = SING_OPTIONS_RECORD_DESC
+
+[OptionsRecordText3]
+X = 70
+Y = 85
+Color = Black
+Size = 30
+Text = SING_OPTIONS_RECORD_WHEREAMI
+
+[OptionsRecordStatic6]
+X = 20
+Y = 10
+W = 500
+H = 110
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[OptionsRecordStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsRecordStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsRecordText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+[OptionsRecordSelectSlideCard]
+Text = SING_OPTIONS_RECORD_CARD
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordSelectSlideInput]
+Text = SING_OPTIONS_RECORD_INPUT
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordSelectSlideChannel]
+Text = SING_OPTIONS_RECORD_CHANNEL
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsRecordButtonExit]
+X = 70
+Y = 390
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+Align = 0
+Texts = 1
+
+[OptionsRecordButtonExitText1]
+X = 60		
+Y = 5
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[OptionsAdvanced]
+Texts = 5
+
+[OptionsAdvancedBackground]
+Tex = OptionsBG
+
+[OptionsAdvancedStatic1]
+X = 40
+Y = 22
+W = 25
+H = 23
+Color = Black
+Tex = IconOption
+Type = Transparent
+
+[OptionsAdvancedText1]
+X = 70
+Y = 5
+Color = Black
+Size = 54
+Text = SING_OPTIONS
+
+[OptionsAdvancedText3]
+X = 70
+Y = 55
+Color = ColorDark
+Size = 30
+Text = SING_OPTIONS_ADVANCED_DESC
+
+[OptionsAdvancedText2]
+X = 70
+Y = 85
+Color = Black
+Size = 30
+Text = SING_OPTIONS_ADVANCED_WHEREAMI
+
+[OptionsAdvancedStatic6]
+X = 20
+Y = 10
+W = 500
+H = 110
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[OptionsAdvancedStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedText4]
+X = 300
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_NAVIGATE
+
+[OptionsAdvancedStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[OptionsAdvancedText5]
+X = 440
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Reflection = 1
+ReflectionSpacing = 20
+Text = SING_LEGEND_ESC
+
+#########unused at the moment#########
+#[OptionsAdvancedSelectLoadAnimation]
+#Text = SING_OPTIONS_ADVANCED_LOADANIMATION
+#Tex = MainBar
+#TexSBG = SelectBG
+#X = 40
+#Y = 85
+#W = 230
+#H = 70
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectScreenFade]
+Text = SING_OPTIONS_ADVANCED_SCREENFADE
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectEffectSing]
+Text = SING_OPTIONS_ADVANCED_EFFECTSING
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectLineBonus]
+Text = SING_OPTIONS_GRAPHICS_LINEBONUS
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectSlideOnSongClick]
+Text = SING_OPTIONS_ADVANCED_ONSONGCLICK
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 280
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectAskbeforeDel]
+Text = SING_OPTIONS_ADVANCED_ASKBEFOREDEL
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 330
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedSelectPartyPopup]
+Text = SING_OPTIONS_ADVANCED_PARTYPOPUP
+Tex = MainBar
+TexSBG = SelectBG
+X = 70
+Y = 380
+W = 250
+H = 40
+SkipX = 10
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[OptionsAdvancedButtonExit]
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+Align = 0
+Texts = 1
+
+[OptionsAdvancedButtonExitText1]
+X = 60		
+Y = 5
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[Top5]
+Texts = 1
+
+[Top5Background]
+Tex = Top5BG
+
+[Top5Text1]
+X = 60
+Y = 6
+Color = Black
+Font = 0
+Size = 60
+Align = 0
+Text = SING_TOP_5_CHARTS
+
+[Top5TextArtistTitle]
+X = 60
+Y = 60
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = artist - title
+
+[Top5Text4]
+X = 370
+Y = 30
+Color = Black
+Font = 0
+Size = 30
+Align = 0
+Text = SING_OPTIONS_GAME_DIFFICULTY
+
+[Top5Static6]
+X = 20
+Y = 10
+W = 700
+H = 85
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[Top5TextLevel]
+X = 580
+Y = 30
+Color = Black
+Font = 0
+Size = 30
+Align = 1
+Text = easy
+
+[Top5Static1]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = ScoreIcon
+Type = Transparent
+
+[Top5Static2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Static3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[Top5Text2]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = SING_TOP_5_CHARTS_WHEREAMI
+
+[Top5Static4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[Top5Text3]
+X = 290
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_TOP_5_CHARTS_CONTINUE
+
+[Top5Static5]
+X = 530
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[Top5Text5]
+X = 560
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_TOP_5_CHARTS_SWITCH_DIFFICULTY
+
+[Top5TextName1]
+X = 150
+Y = 190
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 1. Player1
+
+[Top5TextName2]
+X = 150
+Y = 240
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 2. Player2
+
+[Top5TextName3]
+X = 150
+Y = 290
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 3. Player3
+
+[Top5TextName4]
+X = 150
+Y = 340
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 4. Player4
+
+[Top5TextName5]
+X = 150
+Y = 390
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 5. Player5
+
+[Top5TextScore1]
+X = 560
+Y = 190
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore2]
+X = 560
+Y = 240
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore3]
+X = 560
+Y = 290
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore4]
+X = 560
+Y = 340
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextScore5]
+X = 560
+Y = 390
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+
+[Top5TextDate1]
+X = 760
+Y = 190
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate2]
+X = 760
+Y = 240
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate3]
+X = 760
+Y = 290
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate4]
+X = 760
+Y = 340
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextDate5]
+X = 760
+Y = 390
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+[Top5TextNumber1]
+X = 120
+Y = 193
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 1
+
+[Top5TextNumber2]
+X = 120
+Y = 243
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 2
+
+[Top5TextNumber3]
+X = 120
+Y = 293
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 3
+
+[Top5TextNumber4]
+X = 120
+Y = 343
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 4
+
+[Top5TextNumber5]
+X = 120
+Y = 393
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 5
+
+[Top5StaticNumber1]
+Tex = PlayerNumberBox
+X = 100
+Y = 186
+W = 40
+H = 40
+Color = ColorDark
+Type = Transparent
+
+[Top5StaticNumber2]
+Tex = PlayerNumberBox
+X = 100
+Y = 236
+W = 40
+H = 40
+Color = ColorDark
+Type = Transparent
+
+[Top5StaticNumber3]
+Tex = PlayerNumberBox
+X = 100
+Y = 286
+W = 40
+H = 40
+Color = ColorDark
+Type = Transparent
+
+[Top5StaticNumber4]
+Tex = PlayerNumberBox
+X = 100
+Y = 336
+W = 40
+H = 40
+Color = ColorDark
+Type = Transparent
+
+[Top5StaticNumber5]
+Tex = PlayerNumberBox
+X = 100
+Y = 386
+W = 40
+H = 40
+Color = ColorDark
+Type = Transparent
+
+[Edit]
+Texts = 5
+
+[EditBackground]
+Tex = EditBG
+
+# main icon
+[EditStatic1]
+X = 65
+Y = 150
+W = 25
+H = 25
+Color = White
+Tex = IconEdit
+Type = Transparent
+# Type = Colorized
+
+# main icon title
+[EditText1]
+X = 95
+Y = 135
+Color = White
+Font = 0
+Size = 54
+Align = 0
+Text = SING_EDIT
+
+# main icon subtitle
+[EditText2]
+X = 95
+Y = 175
+Color = ColorLightest
+Font = 0
+Size = 30
+Align = 0
+Text = SING_EDIT_MENU_DESCRIPTION
+
+# Navigate button text
+[EditText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+# Select button text
+[EditText4]
+X = 440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_SELECT
+Reflection=1
+ReflectionSpacing=13
+
+# Esc button text
+[EditText5]
+X = 590
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_EDIT_EXIT
+Reflection=1
+ReflectionSpacing=13
+
+[EditTextDescription]
+X = 95
+Y = 195
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = SING_EDIT_TEXTDESCRIPTION
+
+[EditStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditStatic6]
+X = 550
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[EditButtonConvert]
+X = 250
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[EditButtonConvertText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_CONVERT
+Color = White
+
+[EditButtonExit]
+X = 405
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+DeSelectReflectionSpacing = 280
+Fade = 1
+FadeText = 1
+SelectH = 150
+FadeTex = ButtonFade
+FadeTexPos = 0
+
+[EditButtonExitText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_EDIT_BUTTON_EXIT
+Color = White
+
+[Level]
+Texts = 5
+
+[LevelBackground]
+Tex = MainBG
+
+[LevelStatic1]
+X = 110
+Y = 195
+W = 25
+H = 23
+Tex = MainIcon
+Color = Black
+Type = Transparent
+
+[LevelText1]
+X = 140
+Y = 176
+Color = Black
+Font = 0
+Size = 54
+Align = 0
+Text = SING_MODE
+
+[LevelText2]
+X = 140
+Y = 223
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = SING_DIFFICULTY_DESC
+
+[LevelStatic6]
+X = 95
+Y = 180
+W = 500
+H = 80
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[LevelStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[LevelText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[LevelText4]
+X = 440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_DIFFICULTY_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[LevelButtonEasy]
+X = 180
+Y = 270
+W = 150
+H = 50
+Tex = ButtonLeft
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+;DeSelectReflectionSpacing = 280
+;Fade = 1
+;FadeText = 1
+;SelectH = 150
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[LevelButtonMedium]
+X = 335
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+;DeSelectReflectionSpacing = 280
+;Fade = 1
+;FadeText = 1
+;SelectH = 150
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[LevelButtonHard]
+X = 490
+Y = 270
+W = 150
+H = 50
+Tex = ButtonRight
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 15
+;DeSelectReflectionSpacing = 280
+;Fade = 1
+;FadeText = 1
+;SelectH = 150
+;FadeTex = ButtonFade
+;FadeTexPos = 0
+
+[LevelButtonEasyText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text = SING_EASY
+
+[LevelButtonMediumText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text = SING_MEDIUM
+
+[LevelButtonHardText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text = SING_HARD
+
+[Name]
+Texts = 2
+
+[NameBackground]
+Tex  = MainBG
+
+[NameStatic1]
+X = 110
+Y = 195
+W = 25
+H = 23
+Tex = MainIcon
+Color = Black
+Type = Transparent
+
+[NameText1]
+X = 140
+Y = 176
+Color = Black
+Font = 0
+Size = 54
+Text = SING_MODE
+
+[NameText2]
+X = 140
+Y = 223
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = SING_PLAYER_DESC
+
+[NameStatic7]
+X = 95
+Y = 180
+W = 500
+H = 80
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[NameStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameStatic4]
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameText3]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+Reflection = 1
+ReflectionSpacing = 13
+
+[NameStatic5]
+X = 400
+Y = 545
+W = 32
+H = 30
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameText4]
+X = 440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_PLAYER_ENTER_NAME
+Reflection = 1
+ReflectionSpacing = 13
+
+[NameStatic6]
+X = 590
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameText5]
+X = 630
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
+
+[NameButtonPlayer1]
+X = 180
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = P1Dark
+DColor = P1Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer1Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer2]
+X = 335
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = P2Dark
+DColor = P2Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer2Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer3]
+X = 490
+Y = 270
+W = 150
+H = 50
+Tex = Button
+Color = P3Dark
+DColor = P3Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer3Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer4]
+X = 180
+Y = 400
+W = 150
+H = 50
+Tex = Button
+Color = P4Dark
+DColor = P4Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer4Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer5]
+X = 335
+Y = 400
+W = 150
+H = 50
+Tex = Button
+Color = P5Dark
+DColor = P5Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer5Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[NameButtonPlayer6]
+X = 490
+Y = 400
+W = 150
+H = 50
+Tex = Button
+Color = P6Dark
+DColor = P6Light
+Type = Transparent
+Texts = 1
+Reflection = 1
+ReflectionSpacing = 2
+
+[NameButtonPlayer6Text1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
+
+[PartyNewRound]
+Texts = 7
+
+[PartyNewRoundBackground]
+Tex = MainBG
+
+[PartyNewRoundStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStatic8]
+X = 20
+Y = 10
+W = 500
+H = 80
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[PartyNewRoundStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStatic3]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = PartyIcon
+Type = Transparent
+
+[PartyNewRoundText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = Black
+Text = PARTY_MODE
+
+[PartyNewRoundText2]
+X = 70
+Y = 55
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_ROUND_DESC
+
+[PartyNewRoundText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_ROUND_WHEREAMI
+
+[PartyNewRoundText4]
+X = 290
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = PARTY_ROUND_LEGEND_CONTINUE
+
+[PartyNewRoundText5]
+X = 460
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND
+Align = 0
+
+[PartyNewRoundText6]
+X = 600
+Y = 100
+Color = White
+Font = 0
+Size = 30
+Text = PARTY_ROUND_WINNER
+Align = 0
+
+[PartyNewRoundText7]
+X = 448
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = PARTY_ROUND
+Align = 2
+
+[PartyNewRoundTextTeam1Players]
+X = 30
+Y = 137
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam2Players]
+X = 30
+Y = 218
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundTextTeam3Players]
+X = 30
+Y = 299
+Color = White
+Font = 0
+Size = 21
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
+
+[PartyNewRoundStatic4]
+Tex = PartyRoundBG1
+X = 450
+Y = 103
+W = 330
+H = 24
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundStatic5]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyNewRoundStatic6]
+Tex = PartyRoundBG3
+X = 250
+Y = 350
+W = 300
+H = 50
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundStatic7]
+Tex = PartyRoundBG4
+X = 50
+Y = 495
+W = 700
+H = 30
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundStaticTeam1]
+Tex = PartyTeamButton1
+X = 20
+Y = 110
+W = 400
+H = 50
+Color = P1Dark
+Type = Transparent
+Reflection = 0
+
+[PartyNewRoundStaticTeam2]
+Tex = PartyTeamButton1
+X = 20
+Y = 191
+W = 400
+H = 50
+Color = P2Dark
+Type = Transparent
+Reflection = 0
+
+[PartyNewRoundStaticTeam3]
+Tex = PartyTeamButton1
+X = 20
+Y = 272
+W = 400
+H = 50
+Color = P3Dark
+Type = Transparent
+Reflection = 0
+
+[PartyNewRoundStaticNextPlayer1]
+Tex = PartyPlayerButton
+X = 155
+Y = 415
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStaticNextPlayer2]
+Tex = PartyPlayerButton
+X = 325
+Y = 415
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyNewRoundStaticNextPlayer3]
+Tex = PartyPlayerButton
+X = 495
+Y = 415
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyNewRoundTextRound1]
+X = 460
+Y = 133
+Color = White
+Font = 0
+Size = 24
+Text = Round 1
+Align = 0
+
+[PartyNewRoundTextRound2]
+X = 460
+Y = 162
+Color = White
+Font = 0
+Size = 24
+Text = Round 2
+Align = 0
+
+[PartyNewRoundTextRound3]
+X = 460
+Y = 191
+Color = White
+Font = 0
+Size = 24
+Text = Round 3
+Align = 0
+
+[PartyNewRoundTextRound4]
+X = 460
+Y = 220
+Color = White
+Font = 0
+Size = 24
+Text = Round 4
+Align = 0
+
+[PartyNewRoundTextRound5]
+X = 460
+Y = 249
+Color = White
+Font = 0
+Size = 24
+Text = Round 5
+Align = 0
+
+[PartyNewRoundTextRound6]
+X = 460
+Y = 278
+Color = White
+Font = 0
+Size = 24
+Text = Round 6
+Align = 0
+
+[PartyNewRoundTextRound7]
+X = 460
+Y = 307
+Color = White
+Font = 0
+Size = 24
+Text = Round 7
+Align = 0
+
+[PartyNewRoundTextWinner1]
+X = 600
+Y = 133
+Color = White
+Font = 0
+Size = 24
+Text = Winner 1
+Align = 0
+
+[PartyNewRoundTextWinner2]
+X = 600
+Y = 162
+Color = White
+Font = 0
+Size = 24
+Text = Winner 2
+Align = 0
+
+[PartyNewRoundTextWinner3]
+X = 600
+Y = 191
+Color = White
+Font = 0
+Size = 24
+Text = Winner 3
+Align = 0
+
+[PartyNewRoundTextWinner4]
+X = 600
+Y = 220
+Color = White
+Font = 0
+Size = 24
+Text = Winner 4
+Align = 0
+
+[PartyNewRoundTextWinner5]
+X = 600
+Y = 249
+Color = White
+Font = 0
+Size = 24
+Text = Winner 5
+Align = 0
+
+[PartyNewRoundTextWinner6]
+X = 600
+Y = 278
+Color = White
+Font = 0
+Size = 24
+Text = Winner 6
+Align = 0
+
+[PartyNewRoundTextWinner7]
+X = 600
+Y = 307
+Color = White
+Font = 0
+Size = 24
+Text = Winner 7
+Align = 0
+
+[PartyNewRoundStaticRound1]
+Tex = PartyRoundBG2
+X = 450
+Y = 135
+W = 330
+H = 20
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundStaticRound2]
+Tex = PartyRoundBG2
+X = 450
+Y = 164
+W = 330
+H = 20
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundStaticRound3]
+Tex = PartyRoundBG2
+X = 450
+Y = 193
+W = 330
+H = 20
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundStaticRound4]
+Tex = PartyRoundBG2
+X = 450
+Y = 222
+W = 330
+H = 20
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundStaticRound5]
+Tex = PartyRoundBG2
+X = 450
+Y = 251
+W = 330
+H = 20
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundStaticRound6]
+Tex = PartyRoundBG2
+X = 450
+Y = 280
+W = 330
+H = 20
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundStaticRound7]
+Tex = PartyRoundBG2
+X = 450
+Y = 309
+W = 330
+H = 20
+Color = ColorDark
+Type = Transparent
+
+[PartyNewRoundTextNextRound]
+X = 400
+Y = 495
+Color = White
+Font = 0
+Size = 30
+Text = Next Round
+Align = 1
+
+[PartyNewRoundTextNextRoundNo]
+X = 457
+Y = 350
+Color = White
+Font = 0
+Size = 54
+Text = 99
+Align = 0
+
+[PartyNewRoundTextScoreTeam1]
+X = 390
+Y = 110
+Color = White
+Font = 0
+Size = 51
+Text = 3000
+Align = 1
+
+[PartyNewRoundTextScoreTeam2]
+X = 390
+Y = 191
+Color = White
+Font = 0
+Size = 51
+Text = 2000
+Align = 1
+
+[PartyNewRoundTextScoreTeam3]
+X = 390
+Y = 272
+Color = White
+Font = 0
+Size = 51
+Text = 1000
+Align = 1
+
+[PartyNewRoundTextNameTeam1]
+X = 30
+Y = 108
+Color = White
+Font = 0
+Size = 36
+Text = Team 1
+Align = 0
+
+[PartyNewRoundTextNameTeam2]
+X = 30
+Y = 189
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyNewRoundTextNameTeam3]
+X = 30
+Y = 270
+Color = White
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyNewRoundTextNextPlayer1]
+X = 230
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 1
+Align = 1
+
+[PartyNewRoundTextNextPlayer2]
+X = 400
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 2
+Align = 1
+
+[PartyNewRoundTextNextPlayer3]
+X = 570
+Y = 425
+Color = White
+Font = 0
+Size = 30
+Text = Player 3
+Align = 1
+
+
+[PartyScore]
+Texts = 5
+
+[PartyScoreBackground]
+Tex = PartyBG
+
+[PartyScoreDecoTextures]
+ChangeTextures = 1
+
+FirstTexture = PartyScoreDeco
+FirstTyp = Colorized
+FirstColor = Gold
+
+SecondTexture = PartyScoreDeco
+SecondTyp = Colorized
+SecondColor = Silver
+
+ThirdTexture = PartyScoreDeco
+ThirdTyp = Colorized
+ThirdColor = Bronze
+
+[PartyScoreStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStatic3]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = PartyIcon
+Type = Transparent
+
+[PartyScoreStatic7]
+X = 20
+Y = 10
+W = 500
+H = 80
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[PartyScoreStatic4]
+X = 260
+Y = 547
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyScoreText1]
+X = 70
+Y = 6
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = Black
+Text = PARTY_MODE
+
+[PartyScoreText2]
+X = 70
+Y = 58
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_SCORE_DESC
+
+[PartyScoreText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_SCORE_WHEREAMI
+
+[PartyScoreText4]
+X = 300
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_LEGEND_CONTINUE
+
+[PartyScoreStatic5]
+Tex = PartyScoreBG1
+X = 50
+Y = 100
+W = 700
+H = 80
+Color = ColorDark
+Type = Transparent
+
+[PartyScoreStatic6]
+Tex = PartyScoreBG2
+X = 50
+Y = 495
+W = 700
+H = 20
+Color = ColorDark
+Type = Transparent
+
+[PartyScoreText5]
+X = 400
+Y = 136
+Color = White
+Font = 0
+Size = 45
+Text = PARTY_SCORE_WINS2
+Align = 1
+
+[PartyScoreTextWinner]
+X = 400
+Y = 98
+Color = White
+Font = 0
+Size = 54
+Text = The Winner is...
+Align = 1
+
+[PartyScoreTextScoreTeam1]
+X = 568
+Y = 198
+Color = White
+Font = 0
+Size = 36
+Text = 3000
+Align = 2
+
+[PartyScoreTextScoreTeam2]
+X = 568
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = 2000
+Align = 2
+
+[PartyScoreTextScoreTeam3]
+X = 568
+Y = 398
+Color = White
+Font = 0
+Size = 36
+Text = 1000
+Align = 2
+
+[PartyScoreTextNameTeam1]
+X = 188
+Y = 198
+Font = 0
+Size = 36
+Align = 0
+Text = Team 1
+Color = White
+
+[PartyScoreTextNameTeam2]
+X = 188
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyScoreTextNameTeam3]
+X = 188
+Y = 398
+Color = White
+Font = 0
+Size = 36
+Text = Team 3
+Align = 0
+
+[PartyScoreStaticTeam1]
+X = 188
+Y = 230
+W = 380
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyScoreStaticTeam1BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 200
+W = 400
+H = 50
+Type = Transparent
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStaticTeam1Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 191
+W = 64
+H = 64
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = -5
+
+[PartyScoreStaticTeam2]
+X = 188
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyScoreStaticTeam2BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 300
+W = 400
+H = 50
+Type = Transparent
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStaticTeam2Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 291
+W = 64
+H = 64
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = -5
+
+[PartyScoreStaticTeam3]
+X = 188
+Y = 430
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyScoreStaticTeam3BG]
+Tex = PartyTeamButton2
+X = 178
+Y = 400
+W = 400
+H = 50
+Type = Transparent
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyScoreStaticTeam3Deco]
+Tex = PartyScoreDeco
+X = 563
+Y = 391
+W = 64
+H = 64
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = -5
+
+[PartyWin]
+Texts = 4
+
+[PartyWinBackground]
+Tex = PartyBG
+
+[PartyWinStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStatic3]
+X = 40
+Y = 22
+W = 27
+H = 27
+Color = White
+Tex = PartyIcon
+Type = Colorized
+
+[PartyWinStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyWinText1]
+X = 70
+Y = 6
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = White
+Text = PARTY_MODE
+
+[PartyWinText2]
+X = 70
+Y = 53
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_WIN_DESC
+
+[PartyWinText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_WIN_WHEREAMI
+
+[PartyWinText4]
+X = 290
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = PARTY_WIN_LEGEND_CONTINUE
+
+#[PartyWinTextWinner]
+#X = 150
+#Y = 120
+#Color = White
+#Font = 1
+#Size = 42
+#Text = The Winner is...
+#Align = 0
+
+[PartyWinTextScoreTeam1]
+X = 699
+Y = 183
+Color = White
+Font = 0
+Size = 57
+Text = 3000
+Align = 2
+
+[PartyWinTextScoreTeam2]
+X = 669
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = 2000
+Align = 2
+
+[PartyWinTextScoreTeam3]
+X = 649
+Y = 398
+Color = White
+Font = 0
+Size = 27
+Text = 1000
+Align = 2
+
+[PartyWinTextNameTeam1]
+X = 169
+Y = 183
+Font = 0
+Size = 57
+Align = 0
+Text = Team 1
+Color = White
+
+[PartyWinTextNameTeam2]
+X = 289
+Y = 298
+Color = White
+Font = 0
+Size = 36
+Text = Team 2
+Align = 0
+
+[PartyWinTextNameTeam3]
+X = 369
+Y = 398
+Color = White
+Font = 0
+Size = 27
+Text = Team 3
+Align = 0
+
+[PartyWinStaticTeam1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BG]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam1Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BGRank1]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam1Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BGRank2]
+Tex = PartyTeamButton3
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam1Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P1Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam1BGRank3]
+Tex = PartyTeamButton3
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = P1Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+
+[PartyWinStaticTeam1Deco]
+Tex = PartyWinDeco1
+X = 91
+Y = 176
+W = 79
+H = 79
+Type = Colorized
+Color = Gold
+Reflection = 1
+ReflectionSpacing = 3
+
+[PartyWinStaticTeam2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BG]
+Tex = PartyTeamButton4
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamButton3
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BGRank1]
+Tex = PartyTeamButton4
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P2Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BGRank2]
+Tex = PartyTeamButton4
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P2Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam2BGRank3]
+Tex = PartyTeamButton4
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam2Deco]
+Tex = PartyWinDeco2
+X = 226
+Y = 291
+W = 64
+H = 64
+Type = Colorized
+Color = Silver
+Reflection = 1
+ReflectionSpacing = 3
+
+[PartyWinStaticTeam3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = TeamColor
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BG]
+Tex = PartyTeamButton5
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = TeamColor
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Rank1]
+X = 169
+Y = 230
+W = 530
+H = 16
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BGRank1]
+Tex = PartyTeamButton3
+X = 159
+Y = 185
+W = 550
+H = 65
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Rank2]
+X = 289
+Y = 330
+W = 380
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BGRank2]
+Tex = PartyTeamButton5
+X = 279
+Y = 300
+W = 400
+H = 50
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Rank3]
+X = 369
+Y = 420
+W = 280
+H = 15
+Z = 1
+Tex = PartyTeamPoints
+Color = P3Dark
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 12
+
+[PartyWinStaticTeam3BGRank3]
+Tex = PartyTeamButton5
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = P3Dark
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyWinStaticTeam3Deco]
+Tex = PartyWinDeco3
+X = 316
+Y = 391
+W = 54
+H = 54
+Type = Colorized
+Color = Bronze
+Reflection = 1
+ReflectionSpacing = 3
+
+[PartyOptions]
+Texts = 5
+
+[PartyOptionsBackground]
+Tex = PartyBG
+
+[PartyOptionsStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyOptionsStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyOptionsStatic3]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = PartyIcon
+Type = Transparent
+
+[PartyOptionsStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyOptionsStatic5]
+X = 388
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyOptionsStatic6]
+X = 20
+Y = 10
+W = 500
+H = 80
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[PartyOptionsText1]
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = Black
+Text = PARTY_MODE
+
+[PartyOptionsText2]
+X = 70
+Y = 55
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_OPTIONS_DESC
+
+[PartyOptionsText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_OPTIONS_WHEREAMI
+
+[PartyOptionsText4]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[PartyOptionsText5]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_CONTINUE
+
+[PartyOptionsSelectLevel]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_DIFFICULTY
+X = 70
+Y = 110
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+#TexSBG = SelectBG
+#W = 230
+#H = 40
+#SkipX = 10
+
+[PartyOptionsSelectPlayList]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_PLAYLIST
+X = 70
+Y = 165
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyOptionsSelectPlayList2]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_PLAYLIST
+X = 70
+Y = 220
+W = 230
+H = 40
+SkipX = 10
+Fields = 1
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyOptionsSelectRounds]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_ROUNDS
+X = 70
+Y = 275
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayer]
+Texts = 6
+
+[PartyPlayerBackground]
+Tex = PartyBG
+
+[PartyPlayerStatic1]
+X = 0
+Y = 545
+Z = 0.7
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerStatic2]
+X = 250
+Y = 545
+Z = 0.7
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyPlayerStatic3]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = PartyIcon
+Type = Transparent
+
+[PartyPlayerStatic4]
+X = 260
+Y = 552
+Z = 0.75
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic5]
+X = 388
+Y = 552
+Z = 0.75
+W = 24
+H = 23
+Tex = ButtonAZ
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic6]
+X = 556
+Y = 552
+Z = 0.75
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyPlayerStatic7]
+X = 20
+Y = 10
+W = 500
+H = 80
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[PartyPlayerText1]
+X = 70
+Y = 6
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = Black
+Text = PARTY_MODE
+
+[PartyPlayerText2]
+X = 70
+Y = 58
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_PLAYER_DESC
+
+[PartyPlayerText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_PLAYER_WHEREAMI
+
+[PartyPlayerText4]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[PartyPlayerText5]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = PARTY_PLAYER_ENTER_NAME
+
+[PartyPlayerText6]
+X = 586
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_CONTINUE
+
+[PartyPlayerSelectTeams]
+Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+Text = PARTY_TEAMS
+X = 45
+Y = 105
+W = 310
+SBGW = 150
+H = 40
+SkipX = 170
+Fields = 2
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers1]
+;Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+;Text = PARTY_TEAMS_PLAYER1
+X = 315
+Y = 170
+W = 200
+SBGW = 150
+H = 40
+SkipX = 10
+Fields = 1
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = P1Light
+DColor = P1Dark
+TColor = White
+TDColor = White
+
+SBGColor = P1Light
+SBGDColor = P1Dark
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers2]
+;Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+;Text = PARTY_TEAMS_PLAYER2
+X = 315
+Y = 300
+W = 200
+SBGW = 150
+H = 40
+SkipX = 10
+Fields = 1
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = P2Light
+DColor = P2Dark
+TColor = White
+TDColor = White
+
+SBGColor = P2Light
+SBGDColor = P2Dark
+STColor = White
+STDColor = GrayDark
+
+[PartyPlayerSelectPlayers3]
+;Tex = MainBar
+TexSBG = PartyPlayerSelectBG
+;Text = PARTY_TEAMS_PLAYER3
+X = 315
+Y = 430
+W = 200
+SBGW = 150
+H = 40
+SkipX = 10
+Fields = 4
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = P3Light
+DColor = P3Dark
+TColor = White
+TDColor = White
+
+SBGColor = P3Light
+SBGDColor = P3Dark
+STColor = White
+STDColor = GrayDark
+
+
+
+[PartyPlayerTeam1Name]
+Tex = PartyTeamButton2
+X = 45
+Y = 160
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerTeam1NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 1
+Color = White
+
+[PartyPlayerPlayer1Name]
+Tex = Button
+X = 45
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerPlayer1NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 1
+Color = White
+
+[PartyPlayerPlayer2Name]
+Tex = Button
+X = 205
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerPlayer2NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 2
+Color = White
+
+[PartyPlayerPlayer3Name]
+Tex = Button
+X = 365
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerPlayer3NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 3
+Color = White
+
+[PartyPlayerPlayer4Name]
+Tex = Button
+X = 525
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
+
+[PartyPlayerPlayer4NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 4
+Color = White
+
+[PartyPlayerTeam2Name]
+Tex = PartyTeamButton2
+X = 45
+Y = 290
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerTeam2NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 2
+Color = White
+
+[PartyPlayerPlayer5Name]
+Tex = Button
+X = 45
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerPlayer5NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 5
+Color = White
+
+[PartyPlayerPlayer6Name]
+Tex = Button
+X = 205
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerPlayer6NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 6
+Color = White
+
+[PartyPlayerPlayer7Name]
+Tex = Button
+X = 365
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerPlayer7NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 7
+Color = White
+
+[PartyPlayerPlayer8Name]
+Tex = Button
+X = 525
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
+
+[PartyPlayerPlayer8NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 8
+Color = White
+
+[PartyPlayerTeam3Name]
+Tex = PartyTeamButton2
+X = 45
+Y = 420
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerTeam3NameText1]
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 3
+Color = White
+
+[PartyPlayerPlayer9Name]
+Tex = Button
+X = 45
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerPlayer9NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 9
+Color = White
+
+[PartyPlayerPlayer10Name]
+Tex = Button
+X = 205
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerPlayer10NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 10
+Color = White
+
+[PartyPlayerPlayer11Name]
+Tex = Button
+X = 365
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerPlayer11NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 11
+Color = White
+
+[PartyPlayerPlayer12Name]
+Tex = Button
+X = 525
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
+
+[PartyPlayerPlayer12NameText1]
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 12
+Color = White
+
+
+
+[PartyRoundsBackground]
+Tex = PartyBG
+
+[PartyRoundsStatic1]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyRoundsStatic2]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[PartyRoundsStatic3]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = PartyIcon
+Type = Transparent
+
+[PartyRoundsStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[PartyRoundsStatic5]
+X = 388
+Y = 552
+W = 24
+H = 23
+Tex = ButtonEnter
+Color = White
+Type = Transparent
+
+[PartyRoundsStatic6]
+X = 20
+Y = 10
+W = 500
+H = 75
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[PartyRoundsText1]
+X = 70
+Y = 6
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
+Font = 0
+Size = 60
+Color = Black
+Text = PARTY_MODE
+
+[PartyRoundsText2]
+X = 70
+Y = 53
+Color = ColorDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_ROUNDS_DESC
+
+[PartyRoundsText3]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = PARTY_ROUNDS_WHEREAMI
+
+[PartyRoundsText4]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[PartyRoundsText5]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = PARTY_ROUNDS_LEGEND_CONTINUE
+
+[PartyRoundsSelectRoundCount]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_ROUNDCOUNT
+X = 70
+Y = 100
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound1]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE1
+X = 70
+Y = 155
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound2]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE2
+X = 70
+Y = 210
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound3]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE3
+X = 70
+Y = 265
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound4]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE4
+X = 70
+Y = 320
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound5]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE5
+X = 70
+Y = 375
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound6]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE6
+X = 70
+Y = 430
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+[PartyRoundsSelectRound7]
+Tex = MainBar
+TexSBG = SelectBG
+Text = PARTY_SELECTMODE7
+X = 70
+Y = 485
+W = 230
+H = 40
+SkipX = 10
+Fields = 7
+
+Type = Transparent
+TypeSBG = Transparent
+
+Color = ColorLight
+DColor = ColorDark
+TColor = White
+TDColor = White
+
+SBGColor = ColorLight
+SBGDColor = ColorDark
+STColor = White
+STDColor = GrayDark
+
+
+
+[SongMenu]
+
+[SongMenuBackground]
+Type=Fade
+;ColR=0
+;ColG=0
+;ColB=0
+Alpha=0.0
+Tex = SongBG
+
+
+[SongMenuStatic1]
+Tex = interface_dialog_background
+X = 520
+Y = 120
+W = 270
+H = 200
+Z = 0.96
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 0
+
+[SongMenuStatic2]
+X = 528
+Y = 131
+W = 24
+H = 24
+Color = White
+Tex = icon_song_menu
+Type = Colorized
+Z = 0.97
+
+[SongMenuTextMenu]
+X = 558
+Y = 125
+Z = 0.97
+Color = ColorDark
+Size = 36
+Text = MENU
+
+[SongMenuButton1]
+X = 540
+Y = 175
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+
+[SongMenuButton1Text1]
+X = 6
+Y = 0
+Z = 0.97
+Color = White
+Size = 24
+Text = SONG_MENU_PLAY
+
+[SongMenuButton2]
+X = 540
+Y = 205
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+
+[SongMenuButton2Text1]
+X = 6
+Y = 0
+Color = White
+Size = 24
+Text = SONG_MENU_EDIT
+Z = 0.97
+
+[SongMenuButton3]
+X = 540
+Y = 235
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+
+[SongMenuButton3Text1]
+X = 6
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_MODI
+Align = 0
+Z = 0.97
+
+# shows up instead of BUtton 3
+# in some song menus
+[SongMenuSelectSlide3]
+TexSBG = Rectangle
+Text = 
+Type = Colorized
+ShowArrows = 1
+OneItemOnly = 1
+X = 540
+Y = 235
+W = 0
+H = 25
+Z = 0.97
+SkipX = 0
+SBGW = 220
+TextSize = 24
+Color = LightBlue
+DColor = DarkBlue
+TColor = White
+TDColor = White
+SBGColor = LightBlue
+SBGDColor = DarkBlue
+STColor = White
+STDColor = White
+
+[SongMenuButton4]
+X = 540
+Y = 265
+Z = 0.97
+W = 220
+H = 25
+Tex = Rectangle
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+
+[SongMenuButton4Text1]
+X = 6
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_CANCEL
+Align = 0
+Z = 0.97
+
+[SongJumpto]
+
+[SongJumptoBackground]
+Type=Fade
+;ColR=0
+;ColG=0
+;ColB=0
+Alpha=0.0
+Tex = SongBG
+
+[SongJumptoStatic1]
+Tex = interface_dialog_background
+X = 520
+Y = 320
+W = 270
+H = 160
+Z = 0.965
+Color = White
+Type = Transparent
+
+[SongJumptoStatic2]
+X = 528
+Y = 328
+W = 24
+H = 24
+Color = Black
+Tex = icon_song_search
+Type = Colorized
+Z = 0.97
+
+[SongJumptoText1]
+X = 558
+Y = 323
+Color = ColorDark
+Size = 36
+Text = SONG_JUMPTO_TYPE_DESC
+Z = 0.97
+
+#arrows over the select
+#TODO: remove, add this for all in code
+[SongJumptoStatic3]
+X = 520
+Y = 363
+W = 260
+H = 30
+Color = ColorDark
+Tex = interface_selectbg_search
+Type = Colorized
+Z = 0.97
+
+[SongJumptoSelectSlideType]
+#Text = SONG_JUMPTO_TYPE_DESC
+X = 526
+Y = 363
+Z = 0.97
+H = 30
+SBGW = 150
+SkipX = 4
+Color = Black
+Size = 36
+
+#text
+TColor = Black
+TDColor = Black
+#Select0r.Text.Color
+STColor = Black
+STDColor = Black
+
+[SongJumptoButtonSearchText]
+X = 536
+Y = 375
+Z = 0.97
+W = 160
+H = 50
+Size = 36
+Font = 1
+Align = 0
+Color = Black
+
+[SongJumptoTextFound]
+X = 549
+Y = 425
+Color = Black
+Font = 0
+Size = 24
+Text = SONG_JUMPTO_HELP
+Align = 0
+Z = 0.97
+
+##### STATISTIKEN ######
+
+[StatMain]
+Texts = 0
+Statics = 0
+
+[StatMainBackground]
+Tex = MainBG
+
+[StatMainButtonScores]
+X = 589
+Y = 100
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonScoresText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SCORES
+Color = White
+
+[StatMainButtonSingers]
+X = 589
+Y = 160
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonSingersText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_DESC_SINGERS
+Color = White
+
+[StatMainButtonSongs]
+X = 589
+Y = 220
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonSongsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_SONGS
+Color = White
+
+[StatMainButtonBands]
+X = 589
+Y = 280
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonBandsText1]
+X = 95
+Y = 13
+Font = 0
+Size = 24
+Align = 1
+Text = STAT_DESC_BANDS
+Color = White
+
+[StatMainButtonExit]
+X = 589
+Y = 340
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatMainButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatMainTextOverview]
+X = 45
+Y = 125
+W = 510
+Color = White
+Font = 0
+Size = 27
+Align = 0
+Text =
+
+[StatMainStatic9]
+X = 20
+Y = 10
+W = 500
+H = 80
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[StatMainStatic1]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = StatIcon
+Type = Transparent
+
+[StatMainStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatMainStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[StatMainStatic5]
+X = 388
+Y = 552
+W = 32
+H = 23
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[StatMainStatic6]
+X = 40
+Y = 100
+W = 520
+H = 20
+Tex = StatMainBG1
+Color = ColorLight
+Type = Transparent
+
+[StatMainStatic7]
+X = 40
+Y = 120
+W = 520
+H = 300
+Tex = StatMainBG2
+Color = ColorLight
+Type = Transparent
+
+[StatMainStatic8]
+X = 40
+Y = 420
+W = 520
+H = 20
+Tex = StatMainBG3
+Color = ColorLight
+Type = Transparent
+
+[StatMainText1]
+X = 70
+Y = 6
+Color = Black
+Font = 0
+Size = 60
+Text = STAT_MAIN
+Align = 0
+
+[StatMainText2]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = STAT_MAIN_WHEREAMI
+
+[StatMainText3]
+X = 70
+Y = 53
+Color = Black
+Font = 0
+Size = 30
+Align = 0
+Text = STAT_MAIN_DESC
+
+[StatMainText4]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[StatMainText5]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_ESC
+
+[StatDetail]
+Texts = 0
+Statics = 0
+
+[StatDetailBackground]
+Tex = MainBG
+
+[StatDetailButtonNext]
+X = 589
+Y = 100
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonNextText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_NEXT
+Color = White
+
+[StatDetailButtonPrev]
+X = 589
+Y = 160
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonPrevText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_PREV
+Color = White
+
+[StatDetailButtonReverse]
+X = 589
+Y = 220
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonReverseText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = STAT_REVERSE
+Color = White
+
+[StatDetailButtonExit]
+X = 589
+Y = 280
+W = 190
+H = 50
+Tex = Button
+Color = ColorDark
+DColor = ColorLight
+Type = Transparent
+Texts = 1
+Reflection = 0
+
+[StatDetailButtonExitText1]
+X = 95
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
+
+[StatDetailTextDescription]
+X = 70
+Y = 53
+Color = White
+Font = 0
+Size = 30
+Align = 0
+Text =
+
+[StatDetailTextPage]
+X = 546
+Y = 98
+Color = Black
+Font = 0
+Size = 15
+Align = 2
+Text =
+
+[StatDetailTextList1]
+X = 45
+Y = 122
+Color = White
+Font = 0
+Size = 21
+Text = Stat1
+
+[StatDetailTextList2]
+X = 45
+Y = 160
+Color = White
+Font = 0
+Size = 21
+Text = Stat2
+
+[StatDetailTextList3]
+X = 45
+Y = 198
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList4]
+X = 45
+Y = 236
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList5]
+X = 45
+Y = 274
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList6]
+X = 45
+Y = 312
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList7]
+X = 45
+Y = 350
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList8]
+X = 45
+Y = 388
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList9]
+X = 45
+Y = 426
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailTextList10]
+X = 45
+Y = 464
+Color = White
+Font = 0
+Size = 21
+Text =
+
+[StatDetailStatic1]
+X = 30
+Y = 22
+W = 27
+H = 27
+Color = Black
+Tex = StatIcon
+Type = Transparent
+
+[StatDetailStatic9]
+X = 20
+Y = 10
+W = 500
+H = 80
+Tex = MainTextBG
+Color = White
+Type = Transparent
+
+[StatDetailStatic2]
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic3]
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
+
+[StatDetailStatic4]
+X = 260
+Y = 552
+W = 24
+H = 23
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+[StatDetailStatic5]
+X = 388
+Y = 552
+W = 32
+H = 23
+Tex = ButtonEsc
+Color = White
+Type = Transparent
+
+[StatDetailStatic6]
+X = 40
+Y = 100
+W = 520
+H = 24
+Tex = StatDetailBG1
+Color = ColorLight
+Type = Transparent
+
+[StatDetailStatic7]
+X = 40
+Y = 124
+W = 520
+H = 376
+Tex = StatMainBG2
+Color = ColorLight
+Type = Transparent
+
+[StatDetailStatic8]
+X = 40
+Y = 500
+W = 520
+H = 20
+Tex = StatMainBG3
+Color = ColorLight
+Type = Transparent
+
+[StatDetailText1]
+X = 70
+Y = 6
+Color = Black
+Font = 0
+Size = 60
+Text = STAT_DETAIL
+Align = 0
+
+[StatDetailText2]
+X = 238
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 2
+Text = STAT_DETAIL_WHEREAMI
+
+[StatDetailText3]
+X = 294
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_NAVIGATE
+
+[StatDetailText4]
+X = 418
+Y = 552
+Color = Black
+Font = 0
+Size = 21
+Align = 0
+Text = SING_LEGEND_ESC
+
+[CheckPopup]
+
+[CheckPopupBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[CheckPopupStatic1]
+Tex = interface_dialog_background
+X = 200
+Y = 150
+W = 400
+H = 200
+Z = 1
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 15
+
+[CheckPopupText1]
+X = 400
+Y = 160
+W = 400
+Color = ColorDark
+Font = 0
+Size = 30
+Text = MSG_QUESTION_TITLE
+Align = 1
+Z = 1
+
+[CheckPopupText]
+X = 400
+Y = 210
+W = 280
+Color = Black
+Font = 0
+Size = 30
+Text = error text
+Align = 1
+Z = 1
+
+[CheckPopupButton1]
+X = 285
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = YES
+Align = 1
+Z = 1
+
+[CheckPopupButton2]
+X = 415
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Z = 1
+
+[CheckPopupButton2Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = NO
+Align = 1
+Z = 1
+
+
+[ErrorPopup]
+
+[ErrorPopupBackground]
+Type=Fade
+ColR=0
+ColG=0
+ColB=0
+Alpha=0.4
+
+[ErrorPopupStatic1]
+Tex = interface_dialog_background
+X = 200
+Y = 150
+W = 400
+H = 200
+Z = 0.98
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 15
+
+[ErrorPopupText1]
+X = 400
+Y = 160
+W = 400
+Color = ColorDark
+Font = 0
+Size = 30
+Text = MSG_ERROR_TITLE
+Align = 1
+Z = 1
+
+[ErrorPopupText]
+X = 400
+Y = 210
+W = 280
+Color = Black
+Font = 0
+Size = 30
+Text = error text
+Align = 1
+Z = 1
+
+[ErrorPopupButton1]
+X = 350
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorLight
+DColor = ColorDark
+Type = Transparent
+Texts = 1
+Z = 1
+
+[ErrorPopupButton1Text1]
+X = 50
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = OK
+Align = 1
+Z = 1
+
+[PausePopUpStatic]
+Tex = Pause
+X = 0
+Y = 0
+W = 800
+H = 600
+Z = 0.95
+Color = White
+Type = Colorized
+
+[SingLyricsUpperBar]
+X = 80
+W = 640
+Y = 493
+H = 41
+;YOffSet (+/-) for the Sing-Indicator
+IndicatorYOffset = 3
+
+[SingLyricsLowerBar]
+X = 80
+W = 640
+Y = 535
+H = 41
\ No newline at end of file
diff --git a/songmanagement/game/themes/Verdure/Drippin.ini b/songmanagement/game/themes/Verdure/Drippin.ini
new file mode 100644
index 00000000..bda3141f
--- /dev/null
+++ b/songmanagement/game/themes/Verdure/Drippin.ini
@@ -0,0 +1,241 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+;
+;The video is free for private / non-commercial use. 
+;� Copyright dreamscene.org - All rights reserved. 
+
+[Skin]
+Theme=Verdure
+Name=Drippin
+Color=Green
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+LoadLogo       = [main]logo.png
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+MainTextBG     = [main]textbg.png
+ButtonLeft     = [main]button_left.png
+ButtonRight    = [main]button_right.png
+
+#Backgrounds
+LoadingBG      = [bg]drippin.jpg
+MainBG         = [bg-video]drippin.avi
+SongBG         = [bg-video]drippin.avi
+ScoreScreenBG  = [bg-video]drippin.avi
+Top5BG         = [bg-video]drippin.avi
+OptionsBG      = [bg-video]drippin.avi
+EditBG         = [bg-video]drippin.avi
+PartyBG        = [bg-video]drippin.avi
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.png
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Verdure/Drippin_Low.ini b/songmanagement/game/themes/Verdure/Drippin_Low.ini
new file mode 100644
index 00000000..183e7405
--- /dev/null
+++ b/songmanagement/game/themes/Verdure/Drippin_Low.ini
@@ -0,0 +1,241 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+;
+;The video is free for private / non-commercial use. 
+;� Copyright dreamscene.org - All rights reserved. 
+
+[Skin]
+Theme=Verdure
+Name=Drippin (Low)
+Color=Green
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+LoadLogo       = [main]logo.png
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+MainTextBG     = [main]textbg.png
+ButtonLeft     = [main]button_left.png
+ButtonRight    = [main]button_right.png
+
+#Backgrounds
+LoadingBG      = [bg]drippin.jpg
+MainBG         = [bg-video]drippin_low.avi
+SongBG         = [bg-video]drippin_low.avi
+ScoreScreenBG  = [bg-video]drippin_low.avi
+Top5BG         = [bg-video]drippin_low.avi
+OptionsBG      = [bg-video]drippin_low.avi
+EditBG         = [bg-video]drippin_low.avi
+PartyBG        = [bg-video]drippin_low.avi
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.png
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Verdure/Drippin_Static.ini b/songmanagement/game/themes/Verdure/Drippin_Static.ini
new file mode 100644
index 00000000..c9b0fc10
--- /dev/null
+++ b/songmanagement/game/themes/Verdure/Drippin_Static.ini
@@ -0,0 +1,241 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+;
+;The video is free for private / non-commercial use. 
+;� Copyright dreamscene.org - All rights reserved. 
+
+[Skin]
+Theme=Verdure
+Name=Drippin (Static)
+Color=Green
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+LoadLogo       = [main]logo.png
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+MainTextBG     = [main]textbg.png
+ButtonLeft     = [main]button_left.png
+ButtonRight    = [main]button_right.png
+
+#Backgrounds
+LoadingBG      = [bg]drippin.jpg
+MainBG         = [bg]drippin.jpg
+SongBG         = [bg]drippin.jpg
+ScoreScreenBG  = [bg]drippin.jpg
+Top5BG         = [bg]drippin.jpg
+OptionsBG      = [bg]drippin.jpg
+EditBG         = [bg]drippin.jpg
+PartyBG        = [bg]drippin.jpg
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.png
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Verdure/Springtime.ini b/songmanagement/game/themes/Verdure/Springtime.ini
new file mode 100644
index 00000000..52e69d18
--- /dev/null
+++ b/songmanagement/game/themes/Verdure/Springtime.ini
@@ -0,0 +1,241 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+;
+;The video is free for private / non-commercial use. 
+;� Copyright dreamscene.org - All rights reserved. 
+
+[Skin]
+Theme=Verdure
+Name=Springtime
+Color=Green
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+LoadLogo       = [main]logo.png
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+MainTextBG     = [main]textbg.png
+ButtonLeft     = [main]button_left.png
+ButtonRight    = [main]button_right.png
+
+#Backgrounds
+LoadingBG      = [bg]springtime.jpg
+MainBG         = [bg-video]springtime.avi
+SongBG         = [bg-video]springtime.avi
+ScoreScreenBG  = [bg-video]springtime.avi
+Top5BG         = [bg-video]springtime.avi
+OptionsBG      = [bg-video]springtime.avi
+EditBG         = [bg-video]springtime.avi
+PartyBG        = [bg-video]springtime.avi
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.png
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Verdure/Springtime_Low.ini b/songmanagement/game/themes/Verdure/Springtime_Low.ini
new file mode 100644
index 00000000..93e91ac4
--- /dev/null
+++ b/songmanagement/game/themes/Verdure/Springtime_Low.ini
@@ -0,0 +1,241 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+;
+;The video is free for private / non-commercial use. 
+;� Copyright dreamscene.org - All rights reserved. 
+
+[Skin]
+Theme=Verdure
+Name=Springtime (Low)
+Color=Green
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+LoadLogo       = [main]logo.png
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+MainTextBG     = [main]textbg.png
+ButtonLeft     = [main]button_left.png
+ButtonRight    = [main]button_right.png
+
+#Backgrounds
+LoadingBG      = [bg]springtime.jpg
+MainBG         = [bg-video]springtime_low.avi
+SongBG         = [bg-video]springtime_low.avi
+ScoreScreenBG  = [bg-video]springtime_low.avi
+Top5BG         = [bg-video]springtime_low.avi
+OptionsBG      = [bg-video]springtime_low.avi
+EditBG         = [bg-video]springtime_low.avi
+PartyBG        = [bg-video]springtime_low.avi
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.png
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Verdure/Springtime_Static.ini b/songmanagement/game/themes/Verdure/Springtime_Static.ini
new file mode 100644
index 00000000..999c1b02
--- /dev/null
+++ b/songmanagement/game/themes/Verdure/Springtime_Static.ini
@@ -0,0 +1,241 @@
+;0.5.1
+;experimental version
+;if you are using this as a sample for your theme
+;don't be suprised it doesn't work good with newer releases
+;
+;The video is free for private / non-commercial use. 
+;� Copyright dreamscene.org - All rights reserved. 
+
+[Skin]
+Theme=Verdure
+Name=Springtime (Static)
+Color=Green
+
+[Textures]
+/**
+ * Interface
+ */
+interface_selectbg_search   = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
+
+Cursor = [interface]cursor.png
+Cursor_Pressed = [interface]cursor_pressed.png
+
+/**
+ * Icons
+ */
+icon_song_menu   = [icon]song_menu.png
+icon_song_search = [icon]song_search.png
+icon_song_video  = [icon]song_video.png
+
+
+# # # M A I N # # #
+LoadLogo       = [main]logo.png
+Button         = [main]button.png
+ButtonF        = [main]buttonf.jpg
+MainBar        = [main]mainBar.png
+SelectBG       = [main]selectbg.png
+MainTextBG     = [main]textbg.png
+ButtonLeft     = [main]button_left.png
+ButtonRight    = [main]button_right.png
+
+#Backgrounds
+LoadingBG      = [bg]springtime.jpg
+MainBG         = [bg]springtime.jpg
+SongBG         = [bg]springtime.jpg
+ScoreScreenBG  = [bg]springtime.jpg
+Top5BG         = [bg]springtime.jpg
+OptionsBG      = [bg]springtime.jpg
+EditBG         = [bg]springtime.jpg
+PartyBG        = [bg]springtime.jpg
+
+#Icons on screen
+SongCD         = [icon]cd.png
+MainIcon       = [icon]main.png
+MainSearch     = [icon]search.png
+IconOption     = [icon]options.png
+IconEdit       = [icon]options.png
+IconSongMenu   = [icon]songmenu.png
+ScoreIcon      = [icon]score.png
+PartyIcon      = [icon]party.png
+StatIcon       = [icon]stats.png
+VideoIcon      = [icon]video.png
+
+IconError      = [icon]error.png
+IconQuestion   = [icon]question.png
+
+
+# # # S O N G S E L E C E T # # #
+SongSelection1 = [main]songSelection1.png
+SongSelection2 = [main]songSelection2.png
+SongCover      = [main]songCover.jpg
+
+
+# # # S I N G # # #
+#the bar where the lyrics reside
+LyricBar       = [sing]textBar.png
+
+#this one slides in, to tell you that singing starts immediately
+LyricHelpBar   = [sing]lyricsHelpBar.png
+
+#the bar behind the timestuff
+TimeBar1      = [sing]timeBarBG.png
+
+#the time progress bar  (not skinned in this theme :P )
+TimeBar      = [sing]timeBar.jpg
+
+#linebonus, the thing that pop ups at the score
+LineBonusBack  = [sing]lineBonusPopUp.png
+
+#Singbar (the thing beneath the scores)
+SingBarBack    = [sing]singBarBack.png
+SingBarBar     = [sing]singBarBar.png
+SingBarFront   = [sing]singBarFront.png
+
+#Background for scores
+ScoreBG        = [sing]scoreBg.png
+
+#Background for the P1, P2 and so on
+P              = [sing]p.png
+
+#Pointer for lyrics
+Ball           = [sing]LyricsBall.png
+
+
+# # # S C O R E / T O P 5 # # #
+ScoreBox        = [score]box.png
+ScoreGlassBox   = [score]glass_box.png
+ScoreLevel      = [score]level.png
+ScoreLevelRound = [score]levelRound.png
+
+ScoreLevel_Dark           = [score]level_dark.png
+ScoreLevel_Dark_Round     = [score]level_dark_round.png
+
+ScoreLevel_Light          = [score]level_light.png
+ScoreLevel_Light_Round    = [score]level_light_round.png
+
+ScoreLevel_Lightest       = [score]level_lightest.png
+ScoreLevel_Lightest_Round = [score]level_lightest_round.png
+
+# Boxes near the text, that show what color is for which bar
+ScoreBar_box_lightest = [score]bar_box_lightest.png
+ScoreBar_box_light    = [score]bar_box_light.png
+ScoreBar_box_dark     = [score]bar_box_dark.png
+
+ScoreEndCap     = [score]endcap.png
+ScoreLine       = [score]line.png
+PlayerNumberBox = [main]playerNumberBox.png
+
+PlayerIDBox01 = [sing.player1]lyric_active.png
+PlayerIDBox02 = [sing.player2]lyric_active.png
+PlayerIDBox03 = [sing.player3]lyric_active.png
+PlayerIDBox04 = [sing.player4]lyric_active.png
+PlayerIDBox05 = [sing.player5]lyric_active.png
+PlayerIDBox06 = [sing.player6]lyric_active.png
+
+# these icons are part of the tango icon set
+# licensed under Creative Commons Attribution Share-Alike license
+# http://tango.freedesktop.org
+Rating_0 = [score]rating_0.png
+Rating_1 = [score]rating_1.png
+Rating_2 = [score]rating_2.png
+Rating_3 = [score]rating_3.png
+Rating_4 = [score]rating_4.png
+Rating_5 = [score]rating_5.png
+Rating_6 = [score]rating_6.png
+Rating_7 = [score]rating_7.png
+# thank you girls and guys!!!
+
+
+# # # P A R T Y # # #
+Joker             =[party]Joker.png
+PartyPlayerButton =[party]playerButton.png
+PartyTeamButton1  =[party]roundTeamButton.png
+PartyTeamButton2  =[party]playerTeamButton.png
+PartyTeamButton3  =[party]winTeamButton1.png
+PartyTeamButton4  =[party]winTeamButton2.png
+PartyTeamButton5  =[party]winTeamButton3.png
+PartyRoundBG1     =[party]roundBG1.png
+PartyRoundBG2     =[party]roundBG2.png
+PartyRoundBG3     =[party]roundBG3.png
+PartyRoundBG4     =[party]roundBG4.png
+HDL_Pointer       =[party]pointer.png
+PartyTeamPoints   =[party]teamPoints.png
+PartyScoreDeco    =[party]scoreDecoration.png
+PartyScoreBG1     =[party]scoreBG1.png
+PartyScoreBG2     =[party]scoreBG2.png
+PartyWinDeco1     =[party]winDecoration.png
+PartyWinDeco2     =[party]winDecoration.png
+PartyWinDeco3     =[party]winDecoration.png
+PartyPlayerSelectBG = [party]playerselectbg.png
+
+
+# # # S T A T S # # #
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
+
+
+# # # N A V I # # #
+ButtonP     = [button]p.png
+ButtonM     = [button]m.png
+ButtonJ     = [button]j.png
+ButtonAlt   = [button]alt.png
+ButtonAZ    = [button]az.png
+ButtonEnter = [button]enter.png
+ButtonNavi  = [button]navi.png
+ButtonEsc   = [button]esc.png
+Button13    = [button]13.png
+
+Leiste1     = [special]bar1.png
+Leiste2     = [special]bar2.png
+
+JumpToBG    = [menu]jumpToBg.png
+SongMenuBG  = [menu]songMenuBg.png
+SongMenuSelectBG  = [menu]songMenuSelectBg.png
+PopUpBG     = [menu]popUpBG.png
+
+
+# # # N O T E S # # #
+# sung notes - colorized with playercolors
+GrayLeft       = [sing]notesLeft.png
+GrayMid        = [sing]notesMid.png
+GrayRight      = [sing]notesRight.png
+# unsung notes - colorized with playercolors
+NotePlainLeft  = [sing]notesPlainLeft.png
+NotePlainMid   = [sing]notesPlainMid.png
+NotePlainRight = [sing]notesPlainRight.png
+# the glow around unsung/sung notes - colorized with playercolors
+NoteBGLeft     = [sing]notesBgLeft.png
+NoteBGMid      = [sing]notesBgMid.png
+NoteBGRight    = [sing]notesBgRight.png
+Pause          = [sing]pause.png
+
+
+# # # E F F E C T S # # #
+NoteStar        = [effect]goldenNoteStar.png
+NotePerfectStar = [effect]perfectNoteStar.png
+
+
+# # # dirty helpers # # #
+Rectangle  = [helper]rectangle.png
+ButtonFade = [helper]buttonFade.png
+BGFade     = [special]bg_fade.png
+
+
+# # # D U E T # # #
+LyricIcon_P1  = [sing.player1]lyric_active.png
+LyricIconD_P1 = [sing.player1]lyric_inactive.png
+LyricIcon_P2  = [sing.player2]lyric_active.png
+LyricIconD_P2 = [sing.player2]lyric_inactive.png
+LyricIcon_P3  = [sing.player3]lyric_active.png
+LyricIconD_P3 = [sing.player3]lyric_inactive.png
+LyricIcon_P4  = [sing.player4]lyric_active.png
+LyricIconD_P4 = [sing.player4]lyric_inactive.png
+LyricIcon_P5  = [sing.player5]lyric_active.png
+LyricIconD_P5 = [sing.player5]lyric_inactive.png
+LyricIcon_P6  = [sing.player6]lyric_active.png
+LyricIconD_P6 = [sing.player6]lyric_inactive.png
\ No newline at end of file
diff --git a/songmanagement/game/themes/Verdure/[bg-video]drippin.avi b/songmanagement/game/themes/Verdure/[bg-video]drippin.avi
new file mode 100644
index 00000000..5da1dc7f
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[bg-video]drippin.avi differ
diff --git a/songmanagement/game/themes/Verdure/[bg-video]drippin_low.avi b/songmanagement/game/themes/Verdure/[bg-video]drippin_low.avi
new file mode 100644
index 00000000..286bc12b
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[bg-video]drippin_low.avi differ
diff --git a/songmanagement/game/themes/Verdure/[bg-video]springtime.avi b/songmanagement/game/themes/Verdure/[bg-video]springtime.avi
new file mode 100644
index 00000000..778a45f7
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[bg-video]springtime.avi differ
diff --git a/songmanagement/game/themes/Verdure/[bg-video]springtime_low.avi b/songmanagement/game/themes/Verdure/[bg-video]springtime_low.avi
new file mode 100644
index 00000000..2cdf57b8
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[bg-video]springtime_low.avi differ
diff --git a/songmanagement/game/themes/Verdure/[bg]drippin.jpg b/songmanagement/game/themes/Verdure/[bg]drippin.jpg
new file mode 100644
index 00000000..183d076e
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[bg]drippin.jpg differ
diff --git a/songmanagement/game/themes/Verdure/[bg]springtime.jpg b/songmanagement/game/themes/Verdure/[bg]springtime.jpg
new file mode 100644
index 00000000..52aa04f5
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[bg]springtime.jpg differ
diff --git a/songmanagement/game/themes/Verdure/[button]13.png b/songmanagement/game/themes/Verdure/[button]13.png
new file mode 100644
index 00000000..8e4694c4
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[button]13.png differ
diff --git a/songmanagement/game/themes/Verdure/[button]alt.png b/songmanagement/game/themes/Verdure/[button]alt.png
new file mode 100644
index 00000000..b3db5380
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[button]alt.png differ
diff --git a/songmanagement/game/themes/Verdure/[button]az.png b/songmanagement/game/themes/Verdure/[button]az.png
new file mode 100644
index 00000000..fe070495
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[button]az.png differ
diff --git a/songmanagement/game/themes/Verdure/[button]enter.png b/songmanagement/game/themes/Verdure/[button]enter.png
new file mode 100644
index 00000000..fcdb95ec
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[button]enter.png differ
diff --git a/songmanagement/game/themes/Verdure/[button]esc.png b/songmanagement/game/themes/Verdure/[button]esc.png
new file mode 100644
index 00000000..fdf025eb
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[button]esc.png differ
diff --git a/songmanagement/game/themes/Verdure/[button]j.png b/songmanagement/game/themes/Verdure/[button]j.png
new file mode 100644
index 00000000..5a2f2087
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[button]j.png differ
diff --git a/songmanagement/game/themes/Verdure/[button]m.png b/songmanagement/game/themes/Verdure/[button]m.png
new file mode 100644
index 00000000..97070b5f
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[button]m.png differ
diff --git a/songmanagement/game/themes/Verdure/[button]navi.png b/songmanagement/game/themes/Verdure/[button]navi.png
new file mode 100644
index 00000000..96f46860
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[button]navi.png differ
diff --git a/songmanagement/game/themes/Verdure/[button]p.png b/songmanagement/game/themes/Verdure/[button]p.png
new file mode 100644
index 00000000..e597ddda
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[button]p.png differ
diff --git a/songmanagement/game/themes/Verdure/[effect]goldenNoteStar.png b/songmanagement/game/themes/Verdure/[effect]goldenNoteStar.png
new file mode 100644
index 00000000..7bd6225f
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[effect]goldenNoteStar.png differ
diff --git a/songmanagement/game/themes/Verdure/[effect]perfectNoteStar.png b/songmanagement/game/themes/Verdure/[effect]perfectNoteStar.png
new file mode 100644
index 00000000..99132c39
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[effect]perfectNoteStar.png differ
diff --git a/songmanagement/game/themes/Verdure/[helper]buttonFade.png b/songmanagement/game/themes/Verdure/[helper]buttonFade.png
new file mode 100644
index 00000000..27a94c44
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[helper]buttonFade.png differ
diff --git a/songmanagement/game/themes/Verdure/[helper]rectangle.png b/songmanagement/game/themes/Verdure/[helper]rectangle.png
new file mode 100644
index 00000000..57c77385
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[helper]rectangle.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]cd.png b/songmanagement/game/themes/Verdure/[icon]cd.png
new file mode 100644
index 00000000..2633d235
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]cd.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]error.png b/songmanagement/game/themes/Verdure/[icon]error.png
new file mode 100644
index 00000000..f952f3fa
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]error.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]main.png b/songmanagement/game/themes/Verdure/[icon]main.png
new file mode 100644
index 00000000..f7d50067
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]main.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]options.png b/songmanagement/game/themes/Verdure/[icon]options.png
new file mode 100644
index 00000000..9fac0bfd
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]options.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]party.png b/songmanagement/game/themes/Verdure/[icon]party.png
new file mode 100644
index 00000000..e23230e3
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]party.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]question.png b/songmanagement/game/themes/Verdure/[icon]question.png
new file mode 100644
index 00000000..a72a5c43
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]question.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]score.png b/songmanagement/game/themes/Verdure/[icon]score.png
new file mode 100644
index 00000000..ccc3d8ff
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]score.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]song_menu.png b/songmanagement/game/themes/Verdure/[icon]song_menu.png
new file mode 100644
index 00000000..acf69bfb
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]song_menu.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]song_search.png b/songmanagement/game/themes/Verdure/[icon]song_search.png
new file mode 100644
index 00000000..f5190315
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]song_search.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]song_video.png b/songmanagement/game/themes/Verdure/[icon]song_video.png
new file mode 100644
index 00000000..4a679249
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]song_video.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]stats.png b/songmanagement/game/themes/Verdure/[icon]stats.png
new file mode 100644
index 00000000..d8e5eac1
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]stats.png differ
diff --git a/songmanagement/game/themes/Verdure/[icon]video.png b/songmanagement/game/themes/Verdure/[icon]video.png
new file mode 100644
index 00000000..9bd65f86
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[icon]video.png differ
diff --git a/songmanagement/game/themes/Verdure/[interface]cursor.png b/songmanagement/game/themes/Verdure/[interface]cursor.png
new file mode 100644
index 00000000..0fe390f0
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[interface]cursor.png differ
diff --git a/songmanagement/game/themes/Verdure/[interface]cursor_pressed.png b/songmanagement/game/themes/Verdure/[interface]cursor_pressed.png
new file mode 100644
index 00000000..fa0056cc
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[interface]cursor_pressed.png differ
diff --git a/songmanagement/game/themes/Verdure/[interface]dialog_background.png b/songmanagement/game/themes/Verdure/[interface]dialog_background.png
new file mode 100644
index 00000000..a66837cc
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[interface]dialog_background.png differ
diff --git a/songmanagement/game/themes/Verdure/[interface]select_arrow_left.png b/songmanagement/game/themes/Verdure/[interface]select_arrow_left.png
new file mode 100644
index 00000000..e4a32d2d
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[interface]select_arrow_left.png differ
diff --git a/songmanagement/game/themes/Verdure/[interface]select_arrow_right.png b/songmanagement/game/themes/Verdure/[interface]select_arrow_right.png
new file mode 100644
index 00000000..b2a29793
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[interface]select_arrow_right.png differ
diff --git a/songmanagement/game/themes/Verdure/[interface]selectbg_search.png b/songmanagement/game/themes/Verdure/[interface]selectbg_search.png
new file mode 100644
index 00000000..57d0ca88
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[interface]selectbg_search.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]button.png b/songmanagement/game/themes/Verdure/[main]button.png
new file mode 100644
index 00000000..1d5ccaed
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]button.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]button_left.png b/songmanagement/game/themes/Verdure/[main]button_left.png
new file mode 100644
index 00000000..7dc9f6aa
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]button_left.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]button_right.png b/songmanagement/game/themes/Verdure/[main]button_right.png
new file mode 100644
index 00000000..10a5c490
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]button_right.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]buttonf.jpg b/songmanagement/game/themes/Verdure/[main]buttonf.jpg
new file mode 100644
index 00000000..d844add5
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]buttonf.jpg differ
diff --git a/songmanagement/game/themes/Verdure/[main]logo.png b/songmanagement/game/themes/Verdure/[main]logo.png
new file mode 100644
index 00000000..b7810fab
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]logo.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]mainBar.png b/songmanagement/game/themes/Verdure/[main]mainBar.png
new file mode 100644
index 00000000..a9797e15
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]mainBar.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]playerNumberBox.png b/songmanagement/game/themes/Verdure/[main]playerNumberBox.png
new file mode 100644
index 00000000..2035c4cc
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]playerNumberBox.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]selectbg.png b/songmanagement/game/themes/Verdure/[main]selectbg.png
new file mode 100644
index 00000000..9a9e89ac
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]selectbg.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]songCover.jpg b/songmanagement/game/themes/Verdure/[main]songCover.jpg
new file mode 100644
index 00000000..7cf8930b
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]songCover.jpg differ
diff --git a/songmanagement/game/themes/Verdure/[main]songSelection1.png b/songmanagement/game/themes/Verdure/[main]songSelection1.png
new file mode 100644
index 00000000..c9f2ba22
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]songSelection1.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]songSelection2.png b/songmanagement/game/themes/Verdure/[main]songSelection2.png
new file mode 100644
index 00000000..73fe2652
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]songSelection2.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]songSelection3.png b/songmanagement/game/themes/Verdure/[main]songSelection3.png
new file mode 100644
index 00000000..f4704ef2
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]songSelection3.png differ
diff --git a/songmanagement/game/themes/Verdure/[main]textbg.png b/songmanagement/game/themes/Verdure/[main]textbg.png
new file mode 100644
index 00000000..f355bb57
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[main]textbg.png differ
diff --git a/songmanagement/game/themes/Verdure/[menu]PopUpFg.png b/songmanagement/game/themes/Verdure/[menu]PopUpFg.png
new file mode 100644
index 00000000..2c9785b4
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[menu]PopUpFg.png differ
diff --git a/songmanagement/game/themes/Verdure/[menu]jumpToBg.png b/songmanagement/game/themes/Verdure/[menu]jumpToBg.png
new file mode 100644
index 00000000..8e3a3a00
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[menu]jumpToBg.png differ
diff --git a/songmanagement/game/themes/Verdure/[menu]songMenuBg.png b/songmanagement/game/themes/Verdure/[menu]songMenuBg.png
new file mode 100644
index 00000000..92beff8e
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[menu]songMenuBg.png differ
diff --git a/songmanagement/game/themes/Verdure/[menu]songMenuSelectBg.png b/songmanagement/game/themes/Verdure/[menu]songMenuSelectBg.png
new file mode 100644
index 00000000..8ff5eef8
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[menu]songMenuSelectBg.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]Joker.png b/songmanagement/game/themes/Verdure/[party]Joker.png
new file mode 100644
index 00000000..59093432
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]Joker.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]playerButton.png b/songmanagement/game/themes/Verdure/[party]playerButton.png
new file mode 100644
index 00000000..d66b195d
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]playerButton.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]playerTeamButton.png b/songmanagement/game/themes/Verdure/[party]playerTeamButton.png
new file mode 100644
index 00000000..1d645717
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]playerTeamButton.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]playerselectbg.png b/songmanagement/game/themes/Verdure/[party]playerselectbg.png
new file mode 100644
index 00000000..79a449e7
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]playerselectbg.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]pointer.png b/songmanagement/game/themes/Verdure/[party]pointer.png
new file mode 100644
index 00000000..2292d6c1
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]pointer.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]roundBG1.png b/songmanagement/game/themes/Verdure/[party]roundBG1.png
new file mode 100644
index 00000000..9cd6397e
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]roundBG1.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]roundBG2.png b/songmanagement/game/themes/Verdure/[party]roundBG2.png
new file mode 100644
index 00000000..03a52fb5
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]roundBG2.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]roundBG3.png b/songmanagement/game/themes/Verdure/[party]roundBG3.png
new file mode 100644
index 00000000..1e758ede
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]roundBG3.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]roundBG4.png b/songmanagement/game/themes/Verdure/[party]roundBG4.png
new file mode 100644
index 00000000..45e81d6b
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]roundBG4.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]roundTeamButton.png b/songmanagement/game/themes/Verdure/[party]roundTeamButton.png
new file mode 100644
index 00000000..9bdfe994
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]roundTeamButton.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]scoreBG1.png b/songmanagement/game/themes/Verdure/[party]scoreBG1.png
new file mode 100644
index 00000000..42d4464b
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]scoreBG1.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]scoreBG2.png b/songmanagement/game/themes/Verdure/[party]scoreBG2.png
new file mode 100644
index 00000000..90aa5cce
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]scoreBG2.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]scoreDecoration.png b/songmanagement/game/themes/Verdure/[party]scoreDecoration.png
new file mode 100644
index 00000000..388077e6
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]scoreDecoration.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]teamPoints.png b/songmanagement/game/themes/Verdure/[party]teamPoints.png
new file mode 100644
index 00000000..a6d2f42d
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]teamPoints.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]winDecoration.png b/songmanagement/game/themes/Verdure/[party]winDecoration.png
new file mode 100644
index 00000000..f84dbc8a
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]winDecoration.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]winTeamButton1.png b/songmanagement/game/themes/Verdure/[party]winTeamButton1.png
new file mode 100644
index 00000000..d080b6fe
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]winTeamButton1.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]winTeamButton2.png b/songmanagement/game/themes/Verdure/[party]winTeamButton2.png
new file mode 100644
index 00000000..9bdfe994
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]winTeamButton2.png differ
diff --git a/songmanagement/game/themes/Verdure/[party]winTeamButton3.png b/songmanagement/game/themes/Verdure/[party]winTeamButton3.png
new file mode 100644
index 00000000..c2b2e730
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[party]winTeamButton3.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]Line.png b/songmanagement/game/themes/Verdure/[score]Line.png
new file mode 100644
index 00000000..954caf94
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]Line.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]bar_box_dark.png b/songmanagement/game/themes/Verdure/[score]bar_box_dark.png
new file mode 100644
index 00000000..e4fbfa41
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]bar_box_dark.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]bar_box_light.png b/songmanagement/game/themes/Verdure/[score]bar_box_light.png
new file mode 100644
index 00000000..ddc17ed8
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]bar_box_light.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]bar_box_lightest.png b/songmanagement/game/themes/Verdure/[score]bar_box_lightest.png
new file mode 100644
index 00000000..995bb9ef
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]bar_box_lightest.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]box.png b/songmanagement/game/themes/Verdure/[score]box.png
new file mode 100644
index 00000000..71a0cee6
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]box.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]endcap.png b/songmanagement/game/themes/Verdure/[score]endcap.png
new file mode 100644
index 00000000..3cccd2e1
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]endcap.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]glass_box.png b/songmanagement/game/themes/Verdure/[score]glass_box.png
new file mode 100644
index 00000000..c0cf2a9c
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]glass_box.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]glassbackground.png b/songmanagement/game/themes/Verdure/[score]glassbackground.png
new file mode 100644
index 00000000..6bc60500
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]glassbackground.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]level.png b/songmanagement/game/themes/Verdure/[score]level.png
new file mode 100644
index 00000000..1f627560
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]level.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]levelRound.png b/songmanagement/game/themes/Verdure/[score]levelRound.png
new file mode 100644
index 00000000..2bc7a6b8
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]levelRound.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]level_dark.png b/songmanagement/game/themes/Verdure/[score]level_dark.png
new file mode 100644
index 00000000..da4fd407
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]level_dark.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]level_dark_round.png b/songmanagement/game/themes/Verdure/[score]level_dark_round.png
new file mode 100644
index 00000000..de239cb2
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]level_dark_round.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]level_light.png b/songmanagement/game/themes/Verdure/[score]level_light.png
new file mode 100644
index 00000000..1c1c8a4d
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]level_light.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]level_light_round.png b/songmanagement/game/themes/Verdure/[score]level_light_round.png
new file mode 100644
index 00000000..641151a5
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]level_light_round.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]level_lightest.png b/songmanagement/game/themes/Verdure/[score]level_lightest.png
new file mode 100644
index 00000000..f02fdf7b
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]level_lightest.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]level_lightest_round.png b/songmanagement/game/themes/Verdure/[score]level_lightest_round.png
new file mode 100644
index 00000000..9f1bb09e
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]level_lightest_round.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]rating_0.png b/songmanagement/game/themes/Verdure/[score]rating_0.png
new file mode 100644
index 00000000..7e836b99
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]rating_0.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]rating_1.png b/songmanagement/game/themes/Verdure/[score]rating_1.png
new file mode 100644
index 00000000..556821cb
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]rating_1.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]rating_2.png b/songmanagement/game/themes/Verdure/[score]rating_2.png
new file mode 100644
index 00000000..ffa23fd3
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]rating_2.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]rating_3.png b/songmanagement/game/themes/Verdure/[score]rating_3.png
new file mode 100644
index 00000000..5204dc5f
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]rating_3.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]rating_4.png b/songmanagement/game/themes/Verdure/[score]rating_4.png
new file mode 100644
index 00000000..f5d7267c
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]rating_4.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]rating_5.png b/songmanagement/game/themes/Verdure/[score]rating_5.png
new file mode 100644
index 00000000..0f6a553b
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]rating_5.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]rating_6.png b/songmanagement/game/themes/Verdure/[score]rating_6.png
new file mode 100644
index 00000000..e8127c85
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]rating_6.png differ
diff --git a/songmanagement/game/themes/Verdure/[score]rating_7.png b/songmanagement/game/themes/Verdure/[score]rating_7.png
new file mode 100644
index 00000000..6b1d30f5
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[score]rating_7.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player1]lyric_active.png b/songmanagement/game/themes/Verdure/[sing.player1]lyric_active.png
new file mode 100644
index 00000000..089c8c5e
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player1]lyric_active.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player1]lyric_inactive.png b/songmanagement/game/themes/Verdure/[sing.player1]lyric_inactive.png
new file mode 100644
index 00000000..a349007d
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player1]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player2]lyric_active.png b/songmanagement/game/themes/Verdure/[sing.player2]lyric_active.png
new file mode 100644
index 00000000..509767fa
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player2]lyric_active.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player2]lyric_inactive.png b/songmanagement/game/themes/Verdure/[sing.player2]lyric_inactive.png
new file mode 100644
index 00000000..ac40ec61
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player2]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player3]lyric_active.png b/songmanagement/game/themes/Verdure/[sing.player3]lyric_active.png
new file mode 100644
index 00000000..7b130ac5
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player3]lyric_active.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player3]lyric_inactive.png b/songmanagement/game/themes/Verdure/[sing.player3]lyric_inactive.png
new file mode 100644
index 00000000..c5a00600
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player3]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player4]lyric_active.png b/songmanagement/game/themes/Verdure/[sing.player4]lyric_active.png
new file mode 100644
index 00000000..993041fd
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player4]lyric_active.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player4]lyric_inactive.png b/songmanagement/game/themes/Verdure/[sing.player4]lyric_inactive.png
new file mode 100644
index 00000000..f09669b2
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player4]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player5]lyric_active.png b/songmanagement/game/themes/Verdure/[sing.player5]lyric_active.png
new file mode 100644
index 00000000..631dc9c3
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player5]lyric_active.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player5]lyric_inactive.png b/songmanagement/game/themes/Verdure/[sing.player5]lyric_inactive.png
new file mode 100644
index 00000000..716071e8
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player5]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player6]lyric_active.png b/songmanagement/game/themes/Verdure/[sing.player6]lyric_active.png
new file mode 100644
index 00000000..65133d03
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player6]lyric_active.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing.player6]lyric_inactive.png b/songmanagement/game/themes/Verdure/[sing.player6]lyric_inactive.png
new file mode 100644
index 00000000..0c5f34d3
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing.player6]lyric_inactive.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]LyricsBall.png b/songmanagement/game/themes/Verdure/[sing]LyricsBall.png
new file mode 100644
index 00000000..aa4401dd
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]LyricsBall.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]lineBonusPopUp.png b/songmanagement/game/themes/Verdure/[sing]lineBonusPopUp.png
new file mode 100644
index 00000000..c7bd0a41
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]lineBonusPopUp.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]lyricsHelpBar.png b/songmanagement/game/themes/Verdure/[sing]lyricsHelpBar.png
new file mode 100644
index 00000000..33ea8ddf
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]lyricsHelpBar.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]notesBgLeft.png b/songmanagement/game/themes/Verdure/[sing]notesBgLeft.png
new file mode 100644
index 00000000..9fe2621c
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]notesBgLeft.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]notesBgMid.png b/songmanagement/game/themes/Verdure/[sing]notesBgMid.png
new file mode 100644
index 00000000..612da5d3
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]notesBgMid.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]notesBgRight.png b/songmanagement/game/themes/Verdure/[sing]notesBgRight.png
new file mode 100644
index 00000000..a6f42c33
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]notesBgRight.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]notesLeft.png b/songmanagement/game/themes/Verdure/[sing]notesLeft.png
new file mode 100644
index 00000000..3a404b9c
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]notesLeft.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]notesMid.png b/songmanagement/game/themes/Verdure/[sing]notesMid.png
new file mode 100644
index 00000000..8769d01a
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]notesMid.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]notesPlainLeft.png b/songmanagement/game/themes/Verdure/[sing]notesPlainLeft.png
new file mode 100644
index 00000000..1a94a9d8
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]notesPlainLeft.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]notesPlainMid.png b/songmanagement/game/themes/Verdure/[sing]notesPlainMid.png
new file mode 100644
index 00000000..7fc64282
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]notesPlainMid.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]notesPlainRight.png b/songmanagement/game/themes/Verdure/[sing]notesPlainRight.png
new file mode 100644
index 00000000..ff8bb502
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]notesPlainRight.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]notesRight.png b/songmanagement/game/themes/Verdure/[sing]notesRight.png
new file mode 100644
index 00000000..8dc40cc8
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]notesRight.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]p.png b/songmanagement/game/themes/Verdure/[sing]p.png
new file mode 100644
index 00000000..7458d8e5
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]p.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]pause.png b/songmanagement/game/themes/Verdure/[sing]pause.png
new file mode 100644
index 00000000..f5ab158c
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]pause.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]scoreBg.jpg b/songmanagement/game/themes/Verdure/[sing]scoreBg.jpg
new file mode 100644
index 00000000..4a4459f6
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]scoreBg.jpg differ
diff --git a/songmanagement/game/themes/Verdure/[sing]scoreBg.png b/songmanagement/game/themes/Verdure/[sing]scoreBg.png
new file mode 100644
index 00000000..db6ba67f
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]scoreBg.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]singBarBack.png b/songmanagement/game/themes/Verdure/[sing]singBarBack.png
new file mode 100644
index 00000000..14d2ba42
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]singBarBack.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]singBarBar.jpg b/songmanagement/game/themes/Verdure/[sing]singBarBar.jpg
new file mode 100644
index 00000000..4fd9bde9
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]singBarBar.jpg differ
diff --git a/songmanagement/game/themes/Verdure/[sing]singBarBar.png b/songmanagement/game/themes/Verdure/[sing]singBarBar.png
new file mode 100644
index 00000000..9c57057b
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]singBarBar.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]singBarFront.png b/songmanagement/game/themes/Verdure/[sing]singBarFront.png
new file mode 100644
index 00000000..42477c5a
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]singBarFront.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]textBar.png b/songmanagement/game/themes/Verdure/[sing]textBar.png
new file mode 100644
index 00000000..d2069235
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]textBar.png differ
diff --git a/songmanagement/game/themes/Verdure/[sing]timeBar.jpg b/songmanagement/game/themes/Verdure/[sing]timeBar.jpg
new file mode 100644
index 00000000..cc5cb552
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]timeBar.jpg differ
diff --git a/songmanagement/game/themes/Verdure/[sing]timeBarBG.png b/songmanagement/game/themes/Verdure/[sing]timeBarBG.png
new file mode 100644
index 00000000..6094fdf3
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[sing]timeBarBG.png differ
diff --git a/songmanagement/game/themes/Verdure/[special]bar1.png b/songmanagement/game/themes/Verdure/[special]bar1.png
new file mode 100644
index 00000000..a6da49e3
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[special]bar1.png differ
diff --git a/songmanagement/game/themes/Verdure/[special]bar12.png b/songmanagement/game/themes/Verdure/[special]bar12.png
new file mode 100644
index 00000000..00afb41d
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[special]bar12.png differ
diff --git a/songmanagement/game/themes/Verdure/[special]bar2.png b/songmanagement/game/themes/Verdure/[special]bar2.png
new file mode 100644
index 00000000..e42a3217
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[special]bar2.png differ
diff --git a/songmanagement/game/themes/Verdure/[special]bar22.png b/songmanagement/game/themes/Verdure/[special]bar22.png
new file mode 100644
index 00000000..c828a8e1
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[special]bar22.png differ
diff --git a/songmanagement/game/themes/Verdure/[special]bg_fade.png b/songmanagement/game/themes/Verdure/[special]bg_fade.png
new file mode 100644
index 00000000..dc3248ef
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[special]bg_fade.png differ
diff --git a/songmanagement/game/themes/Verdure/[stat]detailBG1.png b/songmanagement/game/themes/Verdure/[stat]detailBG1.png
new file mode 100644
index 00000000..e89394cb
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[stat]detailBG1.png differ
diff --git a/songmanagement/game/themes/Verdure/[stat]mainBG1.png b/songmanagement/game/themes/Verdure/[stat]mainBG1.png
new file mode 100644
index 00000000..440791df
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[stat]mainBG1.png differ
diff --git a/songmanagement/game/themes/Verdure/[stat]mainBG2.png b/songmanagement/game/themes/Verdure/[stat]mainBG2.png
new file mode 100644
index 00000000..bd7f6146
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[stat]mainBG2.png differ
diff --git a/songmanagement/game/themes/Verdure/[stat]mainBG3.png b/songmanagement/game/themes/Verdure/[stat]mainBG3.png
new file mode 100644
index 00000000..ab956992
Binary files /dev/null and b/songmanagement/game/themes/Verdure/[stat]mainBG3.png differ
diff --git a/songmanagement/game/visuals/.gitignore b/songmanagement/game/visuals/.gitignore
new file mode 100644
index 00000000..39ea0e37
--- /dev/null
+++ b/songmanagement/game/visuals/.gitignore
@@ -0,0 +1,2 @@
+# don't delete this file as it prevents git from removing this directory
+projectM
diff --git a/songmanagement/icons/readme.txt b/songmanagement/icons/readme.txt
new file mode 100644
index 00000000..f75a99f4
--- /dev/null
+++ b/songmanagement/icons/readme.txt
@@ -0,0 +1,20 @@
+Resource files (.rc/.res) are needed for MS Windows builds only.
+
+The .res file is the compiled version of .rc and appended to the
+executable. It is just used to provide an icon for the executable
+that is shown in the explorer.
+
+Delphi does the compilation of the .rc to .res file automatically.
+FPC needs windres (delivered with FPC) for ths purpose but windres
+must be started separately.
+
+You can manually run the compilation process with either
+	rccompile-delphi.bat or
+	rccompile-fpc.bat
+depending on the available compiler (delphi/windres files are compatible).
+
+If FPC is used, the path to the FPC bin-dir might have to be adjusted,
+the default is "PATH=C:\Programme\lazarus\fpc\2.2.0\bin\i386-win32\".
+
+To avoid the need to run the resource-compiler, a pre-compiled .res-file
+was added to SVN. Please commit the res-file if the rc-file was changed.
\ No newline at end of file
diff --git a/songmanagement/icons/ultrastardx-icon.svg b/songmanagement/icons/ultrastardx-icon.svg
new file mode 100644
index 00000000..49719bba
--- /dev/null
+++ b/songmanagement/icons/ultrastardx-icon.svg
@@ -0,0 +1,4001 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48px"
+   height="48px"
+   id="svg1288"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   sodipodi:docbase="C:\Documents and Settings\mog\Desktop"
+   sodipodi:docname="usdx_icon_main.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="C:\Documents and Settings\mog\Desktop\usdx_icon.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs3">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6190">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop6192" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop6194" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Dot_s"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Dot_s"
+       style="overflow:visible">
+      <path
+         id="path8362"
+         d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+         transform="scale(0.2) translate(7.4, 1)" />
+    </marker>
+    <marker
+       inkscape:stockid="SemiCircleIn"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="SemiCircleIn"
+       style="overflow:visible">
+      <path
+         id="path8410"
+         d="M -0.37450702,-0.045692580 C -0.37450702,2.7143074 1.8654930,4.9543074 4.6254930,4.9543074 L 4.6254930,-5.0456926 C 1.8654930,-5.0456926 -0.37450702,-2.8056926 -0.37450702,-0.045692580 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+         transform="scale(0.6)" />
+    </marker>
+    <marker
+       inkscape:stockid="DiamondM"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="DiamondM"
+       style="overflow:visible">
+      <path
+         id="path8377"
+         d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="Scissors"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Scissors"
+       style="overflow:visible">
+      <path
+         id="schere"
+         style="marker-start:none"
+         d="M 9.0898857,-3.6061018 C 8.1198849,-4.7769976 6.3697607,-4.7358294 5.0623558,-4.2327734 L -3.1500488,-1.1548705 C -5.5383421,-2.4615840 -7.8983361,-2.0874077 -7.8983361,-2.7236578 C -7.8983361,-3.2209742 -7.4416699,-3.1119800 -7.5100293,-4.4068519 C -7.5756648,-5.6501286 -8.8736064,-6.5699315 -10.100428,-6.4884954 C -11.327699,-6.4958500 -12.599867,-5.5553341 -12.610769,-4.2584343 C -12.702194,-2.9520479 -11.603560,-1.7387447 -10.304005,-1.6532027 C -8.7816644,-1.4265411 -6.0857470,-2.3487593 -4.8210600,-0.082342643 C -5.7633447,1.6559151 -7.4350844,1.6607341 -8.9465707,1.5737277 C -10.201445,1.5014928 -11.708664,1.8611256 -12.307219,3.0945882 C -12.885586,4.2766744 -12.318421,5.9591904 -10.990470,6.3210002 C -9.6502788,6.8128279 -7.8098011,6.1912892 -7.4910978,4.6502760 C -7.2454393,3.4624530 -8.0864637,2.9043186 -7.7636052,2.4731223 C -7.5199917,2.1477623 -5.9728246,2.3362771 -3.2164999,1.0982979 L 5.6763468,4.2330688 C 6.8000164,4.5467672 8.1730685,4.5362646 9.1684433,3.4313614 L -0.051640930,-0.053722219 L 9.0898857,-3.6061018 z M -9.2179159,-5.5066058 C -7.9233569,-4.7838060 -8.0290767,-2.8230356 -9.3743431,-2.4433169 C -10.590861,-2.0196559 -12.145370,-3.2022863 -11.757521,-4.5207817 C -11.530373,-5.6026336 -10.104134,-6.0014137 -9.2179159,-5.5066058 z M -9.1616516,2.5107591 C -7.8108215,3.0096239 -8.0402087,5.2951947 -9.4138723,5.6023681 C -10.324932,5.9187072 -11.627422,5.4635705 -11.719569,4.3902287 C -11.897178,3.0851737 -10.363484,1.9060805 -9.1616516,2.5107591 z " />
+    </marker>
+    <marker
+       inkscape:stockid="Dot_l"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Dot_l"
+       style="overflow:visible">
+      <path
+         id="path8356"
+         d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+         transform="scale(0.8) translate(7.4, 1)" />
+    </marker>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient12868">
+      <stop
+         style="stop-color:#888a85;stop-opacity:1;"
+         offset="0"
+         id="stop12870" />
+      <stop
+         style="stop-color:#888a85;stop-opacity:0;"
+         offset="1"
+         id="stop12872" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient12860">
+      <stop
+         style="stop-color:#d3d7cf;stop-opacity:1;"
+         offset="0"
+         id="stop12862" />
+      <stop
+         style="stop-color:#d3d7cf;stop-opacity:0;"
+         offset="1"
+         id="stop12864" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient9508">
+      <stop
+         style="stop-color:#cfd7d2;stop-opacity:1;"
+         offset="0"
+         id="stop9510" />
+      <stop
+         style="stop-color:#b6bdba;stop-opacity:1;"
+         offset="1"
+         id="stop9512" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient9498">
+      <stop
+         style="stop-color:#fcaf3e;stop-opacity:1;"
+         offset="0"
+         id="stop9500" />
+      <stop
+         id="stop6206"
+         offset="0.5"
+         style="stop-color:#f89426;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ce5c00;stop-opacity:1;"
+         offset="1"
+         id="stop9502" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient9486">
+      <stop
+         style="stop-color:#f57900;stop-opacity:1;"
+         offset="0"
+         id="stop9488" />
+      <stop
+         style="stop-color:#f57900;stop-opacity:1;"
+         offset="1"
+         id="stop9490" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Lstart"
+       style="overflow:visible">
+      <path
+         id="path8294"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.8) translate(12.5,0)" />
+    </marker>
+    <linearGradient
+       id="linearGradient5060">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop5062" />
+      <stop
+         style="stop-color:#d3d7cf;stop-opacity:1;"
+         offset="1"
+         id="stop5064" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5048">
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="0"
+         id="stop5050" />
+      <stop
+         id="stop5056"
+         offset="0.5"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5052" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3085">
+      <stop
+         id="stop3087"
+         offset="0"
+         style="stop-color:#b47002;stop-opacity:1;" />
+      <stop
+         id="stop3089"
+         offset="1.0000000"
+         style="stop-color:#6b4301;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2182">
+      <stop
+         style="stop-color:#555753;stop-opacity:1;"
+         offset="0"
+         id="stop2184" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop2186" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2182"
+       id="radialGradient2188"
+       cx="25.357143"
+       cy="36.500000"
+       fx="25.357143"
+       fy="36.500000"
+       r="14.714286"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.500000,-3.881442e-16,18.25000)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient9498"
+       id="linearGradient10785"
+       x1="19.831461"
+       y1="17.279234"
+       x2="27.983488"
+       y2="23.122595"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.9214033,0,0,0.9699814,0.9487224,6.31005e-2)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2182"
+       id="linearGradient12835"
+       x1="23.023905"
+       y1="28.715317"
+       x2="33.638981"
+       y2="30.077406"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient12868"
+       id="linearGradient12874"
+       x1="18.649262"
+       y1="29.037402"
+       x2="26.027897"
+       y2="31.271891"
+       gradientUnits="userSpaceOnUse" />
+    <pattern
+       patternUnits="userSpaceOnUse"
+       width="3.2648874"
+       height="3.1963946"
+       patternTransform="translate(-30.919022,6.1467707)"
+       id="pattern12879">
+      <path
+         d="M -29.43362,7.7791886 C -29.383398,7.8525901 -29.507786,7.8831005 -29.555619,7.8626608 C -29.685241,7.8072705 -29.6745,7.6299519 -29.600565,7.5351925 C -29.468312,7.3656903 -29.212148,7.3909591 -29.067626,7.528772 C -28.855535,7.731018 -28.89685,8.0751688 -29.099732,8.2671809 C -29.370141,8.5231028 -29.804935,8.4650332 -30.043611,8.1965497 C -30.34396,7.8586906 -30.268821,7.3321406 -29.934454,7.0472003 C -29.52949,6.7020993 -28.910613,6.7944684 -28.579634,7.1948832 C -28.189587,7.6667582 -28.299277,8.3782965 -28.765843,8.7551731 C -29.304511,9.1902921 -30.108923,9.0632236 -30.531603,8.5304385 C -31.011879,7.9250542 -30.867395,7.0276257 -30.268343,6.559208 C -29.596296,6.0337142 -28.605749,6.1956393 -28.091642,6.8609944 C -27.520886,7.5996646 -27.70027,8.6834052 -28.431954,9.2431653"
+         sodipodi:t0="0"
+         sodipodi:argument="-17.878809"
+         sodipodi:radius="1.7738556"
+         sodipodi:revolution="3"
+         sodipodi:expansion="1"
+         sodipodi:cy="7.7791886"
+         sodipodi:cx="-29.43362"
+         id="path12877"
+         style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+         sodipodi:type="spiral"
+         transform="translate(30.919022,-6.1467707)" />
+    </pattern>
+    <pattern
+       patternUnits="userSpaceOnUse"
+       width="2.2471589"
+       height="2.2471589"
+       patternTransform="translate(-28.221284,1.5945946)"
+       id="pattern13897">
+      <path
+         d="M -26.274515,3.5413633 L -26.959798,3.3089773 L -27.539729,3.7417535 L -27.530481,3.0181998 L -28.121284,2.6003876 L -27.430285,2.3855929 L -27.215491,1.6945946 L -26.797679,2.2853978 L -26.074125,2.2761495 L -26.506901,2.8560807 L -26.274515,3.5413633 z "
+         inkscape:randomized="0"
+         inkscape:rounded="0"
+         inkscape:flatsided="false"
+         sodipodi:arg2="1.4137167"
+         sodipodi:arg1="0.78539816"
+         sodipodi:r2="0.54483539"
+         sodipodi:r1="1.0896708"
+         sodipodi:cy="2.7708497"
+         sodipodi:cx="-27.045029"
+         sodipodi:sides="5"
+         id="path13895"
+         style="opacity:0.61499999;fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         sodipodi:type="star"
+         transform="translate(28.221284,-1.5945946)" />
+    </pattern>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient13910"
+       cx="-5.3587475"
+       cy="9.5075159"
+       fx="-5.3587475"
+       fy="9.5075159"
+       r="8.8359814"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient13912"
+       x1="-12.268445"
+       y1="12.204313"
+       x2="3.4772339"
+       y2="9.5075159"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       y2="248.6311"
+       x2="153.0005"
+       y1="15.4238"
+       x1="99.7773"
+       gradientUnits="userSpaceOnUse"
+       id="aigrd1">
+      <stop
+         id="stop53300"
+         style="stop-color:#184375"
+         offset="0" />
+      <stop
+         id="stop53302"
+         style="stop-color:#C8BDDC"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2300">
+      <stop
+         style="stop-color:#000000;stop-opacity:0.32673267;"
+         offset="0.0000000"
+         id="stop2302" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop2304" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2300"
+       id="radialGradient13964"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.399258,-2.234445e-7,8.196178e-8,0.513264,4.365074,4.839285)"
+       cx="14.287618"
+       cy="68.872971"
+       fx="14.287618"
+       fy="72.568001"
+       r="11.689870" />
+    <linearGradient
+       id="linearGradient2219">
+      <stop
+         id="stop2221"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop2223"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2227"
+       inkscape:collect="always">
+      <stop
+         id="stop2229"
+         offset="0"
+         style="stop-color:#8f5402;stop-opacity:1;" />
+      <stop
+         id="stop2231"
+         offset="1"
+         style="stop-color:#6e4001;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2251">
+      <stop
+         style="stop-color:#f6e1cf;stop-opacity:1;"
+         offset="0"
+         id="stop2253" />
+      <stop
+         id="stop3682"
+         offset="0.5"
+         style="stop-color:#e19d56;stop-opacity:1;" />
+      <stop
+         style="stop-color:#f4dcb7;stop-opacity:1"
+         offset="1"
+         id="stop2255" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2227"
+       id="linearGradient14122"
+       gradientUnits="userSpaceOnUse"
+       x1="-10.153608"
+       y1="10.91142"
+       x2="-7.9586563"
+       y2="18.145666" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15542"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-3.1872875,0.6538025)"
+       spreadMethod="pad"
+       x1="-11.696355"
+       y1="9.7079487"
+       x2="-12.762947"
+       y2="9.7079487" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15750"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.7071068,0.7071068,0.7071068,0.7071068,8.1660931,11.76696)"
+       spreadMethod="pad"
+       x1="-11.98508"
+       y1="9.7079487"
+       x2="-13.032627"
+       y2="9.7079487" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15752"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.7071068,0.7071068,0.7071068,0.7071068,34.196829,-14.053784)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15754"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.6222568,0.6222568,0.6222568,0.6222568,34.989233,-13.266883)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15756"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.4101318,-0.4101318,0.4101318,-0.4101318,34.089425,27.06224)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15758"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,0.6071472,19.535899)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15760"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.6853552,-0.6853552,0.6853552,0.6853552,0.4907678,20.356798)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15762"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.5374068,-0.5374068,0.5374068,-0.5374068,34.821364,30.163136)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15764"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.6853552,0.6853552,0.6853552,0.6853552,35.017728,-14.170163)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15766"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.5374068,0.5374068,0.5374068,0.5374068,34.821364,-11.519707)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15768"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.4101318,0.4101318,0.4101318,0.4101318,34.089425,-8.4188108)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15770"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.7071068,-0.7071068,-0.7071068,-0.7071068,39.929933,7.0365706)"
+       spreadMethod="pad"
+       x1="-11.696355"
+       y1="9.7079487"
+       x2="-12.762947"
+       y2="9.7079487" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15772"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.6222568,-0.6222568,0.6222568,0.6222568,1.3940485,20.328302)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15774"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.4101318,-0.4101318,0.4101318,0.4101318,6.2421202,19.428494)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15776"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.5374068,-0.5374068,0.5374068,0.5374068,3.1412237,20.160433)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15778"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,1,47.734136,1.5261303e-2)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15780"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.9692386,0,0,0.9692386,48.396892,0.513432)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15782"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.880004,0,0,0.880004,47.738027,1.1319987)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15784"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.760008,0,0,0.760008,46.383886,2.2487366)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15786"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.5800139,0,0,0.5800139,43.673662,3.9238423)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15788"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.7071068,-0.7071068,0.7071068,-0.7071068,34.19683,32.697213)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15790"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.6853552,-0.6853552,0.6853552,-0.6853552,35.017729,32.813592)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15792"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.6222568,-0.6222568,0.6222568,-0.6222568,34.989233,31.910312)"
+       x1="21.217932"
+       y1="9.3064537"
+       x2="22.702164"
+       y2="9.3064537" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15794"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.7071068,-0.7071068,0.7071068,-0.7071068,8.1679014,7.0365706)"
+       spreadMethod="pad"
+       x1="-11.696355"
+       y1="9.7079487"
+       x2="-12.762947"
+       y2="9.7079487" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient15796"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.7071068,0.7071068,-0.7071068,0.7071068,39.931741,11.76696)"
+       spreadMethod="pad"
+       x1="-11.98508"
+       y1="9.7079487"
+       x2="-13.032627"
+       y2="9.7079487" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient15802"
+       gradientUnits="userSpaceOnUse"
+       x1="-12.268445"
+       y1="12.204313"
+       x2="3.4772339"
+       y2="9.5075159" />
+    <pattern
+       patternUnits="userSpaceOnUse"
+       width="1.8172532"
+       height="1.8262007"
+       patternTransform="translate(-13.085598,37.674324)"
+       id="pattern15818">
+      <g
+         id="g15812"
+         transform="translate(13.085598,-37.674324)">
+        <path
+           sodipodi:type="arc"
+           style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="path15804"
+           sodipodi:cx="-12.61294"
+           sodipodi:cy="38.438137"
+           sodipodi:rx="0.40862656"
+           sodipodi:ry="0.40862656"
+           d="M -12.204313 38.438137 A 0.40862656 0.40862656 0 1 1  -13.021566,38.438137 A 0.40862656 0.40862656 0 1 1  -12.204313 38.438137 z"
+           transform="translate(-6.4031681e-2,-0.3463392)" />
+        <path
+           d="M -12.204313 38.438137 A 0.40862656 0.40862656 0 1 1  -13.021566,38.438137 A 0.40862656 0.40862656 0 1 1  -12.204313 38.438137 z"
+           sodipodi:ry="0.40862656"
+           sodipodi:rx="0.40862656"
+           sodipodi:cy="38.438137"
+           sodipodi:cx="-12.61294"
+           id="path15806"
+           style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           sodipodi:type="arc"
+           transform="translate(0.9359684,-0.3551868)" />
+        <path
+           transform="translate(0.9359683,0.6449132)"
+           sodipodi:type="arc"
+           style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="path15808"
+           sodipodi:cx="-12.61294"
+           sodipodi:cy="38.438137"
+           sodipodi:rx="0.40862656"
+           sodipodi:ry="0.40862656"
+           d="M -12.204313 38.438137 A 0.40862656 0.40862656 0 1 1  -13.021566,38.438137 A 0.40862656 0.40862656 0 1 1  -12.204313 38.438137 z" />
+        <path
+           d="M -12.204313 38.438137 A 0.40862656 0.40862656 0 1 1  -13.021566,38.438137 A 0.40862656 0.40862656 0 1 1  -12.204313 38.438137 z"
+           sodipodi:ry="0.40862656"
+           sodipodi:rx="0.40862656"
+           sodipodi:cy="38.438137"
+           sodipodi:cx="-12.61294"
+           id="path15810"
+           style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           sodipodi:type="arc"
+           transform="translate(-6.4031681e-2,0.6537608)" />
+      </g>
+    </pattern>
+    <pattern
+       patternUnits="userSpaceOnUse"
+       width="2.1373415"
+       height="2.1373415"
+       patternTransform="translate(-17.104986,37.964479)"
+       id="pattern15841">
+      <path
+         transform="matrix(2.1794872,0,0,2.1794872,36.985226,-83.037965)"
+         d="M -16.103735 38.590103 A 0.3756254 0.3756254 0 1 1  -16.854986,38.590103 A 0.3756254 0.3756254 0 1 1  -16.103735 38.590103 z"
+         sodipodi:ry="0.3756254"
+         sodipodi:rx="0.3756254"
+         sodipodi:cy="38.590103"
+         sodipodi:cx="-16.479361"
+         id="path15839"
+         style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:#eeeeec;stroke-width:0.22941177;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         sodipodi:type="arc" />
+    </pattern>
+    <pattern
+       patternUnits="userSpaceOnUse"
+       width="3.0039061"
+       height="2.0165261"
+       patternTransform="translate(38.630058,-14.644896)"
+       id="pattern18812">
+      <g
+         inkscape:label="#g18807"
+         id="microdots"
+         transform="translate(-38.630058,14.644896)">
+        <path
+           sodipodi:type="arc"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           id="path18801"
+           sodipodi:cx="33.03125"
+           sodipodi:cy="-1.7812501"
+           sodipodi:rx="1.90625"
+           sodipodi:ry="1.90625"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           transform="matrix(0.2622951,0,0,0.2622951,32.470029,-13.677683)" />
+        <path
+           transform="matrix(0.2622951,0,0,0.2622951,31.468108,-12.661157)"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           sodipodi:ry="1.90625"
+           sodipodi:rx="1.90625"
+           sodipodi:cy="-1.7812501"
+           sodipodi:cx="33.03125"
+           id="path18803"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           sodipodi:type="arc" />
+        <path
+           transform="matrix(0.2622951,0,0,0.2622951,30.466123,-13.646433)"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           sodipodi:ry="1.90625"
+           sodipodi:rx="1.90625"
+           sodipodi:cy="-1.7812501"
+           sodipodi:cx="33.03125"
+           id="path18805"
+           style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           sodipodi:type="arc" />
+      </g>
+    </pattern>
+    <pattern
+       patternUnits="userSpaceOnUse"
+       width="2.0019851"
+       height="1.9852765"
+       patternTransform="translate(31.912544,-2.0625013)"
+       id="pattern18851">
+      <g
+         id="g18847"
+         transform="translate(-31.912544,2.0625013)">
+        <path
+           sodipodi:type="arc"
+           style="opacity:0.25;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           id="path18797"
+           sodipodi:cx="33.03125"
+           sodipodi:cy="-1.7812501"
+           sodipodi:rx="1.90625"
+           sodipodi:ry="1.90625"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           transform="matrix(0.2622951,0,0,0.2622951,24.750594,-0.1100117)" />
+        <path
+           sodipodi:type="arc"
+           style="opacity:0.25;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           id="path18799"
+           sodipodi:cx="33.03125"
+           sodipodi:cy="-1.7812501"
+           sodipodi:rx="1.90625"
+           sodipodi:ry="1.90625"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           transform="matrix(0.2622951,0,0,0.2622951,23.748609,-1.0952881)" />
+      </g>
+    </pattern>
+    <pattern
+       patternUnits="userSpaceOnUse"
+       width="2.0019851"
+       height="1.9852771"
+       patternTransform="translate(27.53732,-9.9290644)"
+       id="pattern18879">
+      <g
+         id="g18875"
+         transform="translate(-27.53732,9.9290644)">
+        <path
+           transform="matrix(0.2622951,0,0,0.2622951,20.37537,-7.9765742)"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           sodipodi:ry="1.90625"
+           sodipodi:rx="1.90625"
+           sodipodi:cy="-1.7812501"
+           sodipodi:cx="33.03125"
+           id="path18871"
+           style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           sodipodi:type="arc" />
+        <path
+           transform="matrix(0.2622951,0,0,0.2622951,19.373385,-8.9618512)"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           sodipodi:ry="1.90625"
+           sodipodi:rx="1.90625"
+           sodipodi:cy="-1.7812501"
+           sodipodi:cx="33.03125"
+           id="path18873"
+           style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           sodipodi:type="arc" />
+      </g>
+    </pattern>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4878"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4905"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4907"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4909"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4911"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4913"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4915"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4917"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4919"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4921"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4923"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4925"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4927"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4929"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4931"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4933"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4935"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4937"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4939"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4941"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4943"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4945"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4947"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4949"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4951"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4953"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4955"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4957"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4959"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4961"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4963"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4965"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4967"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4969"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4971"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4973"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4975"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4977"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4979"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4981"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4983"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4985"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4987"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4989"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4991"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4993"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4995"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4997"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient4999"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5001"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5003"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5005"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5007"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5009"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5011"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5013"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5015"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5017"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5019"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5021"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5023"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5025"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5027"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5029"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5031"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5033"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5035"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5037"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5039"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5041"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5043"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5045"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5047"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5049"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5051"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5053"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5055"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5057"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5059"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5061"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5063"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5065"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5067"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5069"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5071"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5073"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5075"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5077"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5079"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5081"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5083"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5085"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5087"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5089"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5091"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5093"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5095"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5097"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5099"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5101"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5103"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5105"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5107"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5109"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5111"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5113"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5115"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5117"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5119"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5121"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5123"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5125"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5127"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5129"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5131"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5133"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5135"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5137"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5139"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5141"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5143"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5145"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5147"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5149"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5151"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5153"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5155"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5157"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5159"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5161"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5163"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5165"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5167"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5169"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5171"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5173"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5175"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5177"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5179"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5181"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5183"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5185"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5187"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5189"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5191"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5193"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5195"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5197"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5199"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5201"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5203"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5205"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5207"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5209"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5211"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5213"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5215"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2219"
+       id="linearGradient5217"
+       gradientUnits="userSpaceOnUse"
+       x1="24.839689"
+       y1="11.097245"
+       x2="19.109165"
+       y2="4.0261784" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6190"
+       id="radialGradient6196"
+       cx="-8.7209244"
+       cy="9.7599792"
+       fx="-8.7209244"
+       fy="9.7599792"
+       r="8.3359814"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.118641,1.1769587,-0.9949577,-0.1002948,0.9126152,17.083396)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient9498"
+       id="linearGradient6204"
+       x1="18.650481"
+       y1="18.897921"
+       x2="29.34952"
+       y2="18.897921"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6228"
+       gradientUnits="userSpaceOnUse"
+       x1="34.082512"
+       y1="34.742275"
+       x2="32.531906"
+       y2="32.223206" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6230"
+       gradientUnits="userSpaceOnUse"
+       x1="37.706436"
+       y1="31.083729"
+       x2="34.752117"
+       y2="28.96241" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6232"
+       gradientUnits="userSpaceOnUse"
+       x1="39.562592"
+       y1="26.992363"
+       x2="34.941113"
+       y2="24.252325" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6234"
+       gradientUnits="userSpaceOnUse"
+       x1="39.120647"
+       y1="21.375841"
+       x2="34.785271"
+       y2="19.475491" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6236"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,1,48.493297,0)"
+       x1="8.785944"
+       y1="6.9265218"
+       x2="20.608435"
+       y2="22.508814" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6260"
+       gradientUnits="userSpaceOnUse"
+       x1="34.082512"
+       y1="34.742275"
+       x2="32.531906"
+       y2="32.223206" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6262"
+       gradientUnits="userSpaceOnUse"
+       x1="37.706436"
+       y1="31.083729"
+       x2="34.752117"
+       y2="28.96241" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6264"
+       gradientUnits="userSpaceOnUse"
+       x1="39.562592"
+       y1="26.992363"
+       x2="34.941113"
+       y2="24.252325" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6266"
+       gradientUnits="userSpaceOnUse"
+       x1="39.120647"
+       y1="21.375841"
+       x2="34.785271"
+       y2="19.475491" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="linearGradient6268"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,1,48.493297,0)"
+       x1="8.785944"
+       y1="6.9265218"
+       x2="20.608435"
+       y2="22.508814" />
+  </defs>
+  <sodipodi:namedview
+     stroke="#e9b96e"
+     fill="#e9b96e"
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.14117647"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="16"
+     inkscape:cx="-1.9529842"
+     inkscape:cy="24.488241"
+     inkscape:current-layer="layer6"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:window-width="1600"
+     inkscape:window-height="1075"
+     inkscape:window-x="20"
+     inkscape:window-y="17"
+     showguides="true"
+     inkscape:guide-bbox="true">
+    <sodipodi:guide
+       orientation="horizontal"
+       position="66.291261"
+       id="guide2588" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>File Manager</dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>file</rdf:li>
+            <rdf:li>manager</rdf:li>
+            <rdf:li>copy</rdf:li>
+            <rdf:li>move</rdf:li>
+            <rdf:li>filesystem</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by/2.0/" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Attribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="redraw"
+     sodipodi:insensitive="true"
+     style="display:none">
+    <image
+       style="opacity:0.61499999;display:inline"
+       y="-6.3348417"
+       x="-3.4472263"
+       id="image10799"
+       height="54.839954"
+       width="54.839954"
+       sodipodi:absref="C:\DOCUME~1\mog\LOCALS~1\Temp\v12finallj1.jpg"
+       xlink:href="C:\DOCUME~1\mog\LOCALS~1\Temp\v12finallj1.jpg" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer5"
+     inkscape:label="wings"
+     style="display:inline">
+    <g
+       id="g6216">
+      <path
+         style="fill:url(#linearGradient6228);fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 24.462047,28.5 L 36.274547,33.125 C 36.274547,33.125 34.737364,37.091205 24.462047,33.40625 L 24.462047,28.5 z "
+         id="path13987" />
+      <path
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 35.418539,33.412478 C 35.418539,33.412478 34.724386,33.599892 33.985706,34.139928 L 21.964135,28.771824 L 22.41585,27.525323 L 35.418539,33.412478 z "
+         id="path6214"
+         sodipodi:nodetypes="ccccc" />
+      <path
+         style="fill:url(#linearGradient6230);fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 25.993297,26.34375 L 40.837047,28.0625 C 40.837047,28.0625 40.49275,34.283482 24.462047,31.46875 L 24.462047,26.46875 C 25.015589,26.426108 25.988622,26.347435 25.993297,26.34375 z "
+         id="path13989" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         id="path6212"
+         d="M 40.195754,28.519004 C 40.195754,28.519004 39.813326,29.020009 39.253932,29.744141 L 25.981569,27.802359 L 26.068881,26.479412 L 40.195754,28.519004 z "
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+      <path
+         style="fill:url(#linearGradient6232);fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 43.993297,21.4375 C 43.993297,21.437499 45.628594,28.747665 27.430797,29.625 C 26.30527,29.679263 25.30967,29.72042 24.462047,29.71875 L 24.462047,25.46875 C 26.808644,24.435229 29.171474,23.607908 29.180797,23.59375 L 43.993297,21.4375 z "
+         id="path13991" />
+      <path
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 43.462892,22.001537 C 43.462892,22.001537 43.476033,22.519583 43.141756,23.371373 L 29.616553,25.293276 L 29.329971,23.998794 L 43.462892,22.001537 z "
+         id="path6210"
+         sodipodi:nodetypes="ccccc" />
+      <path
+         style="fill:url(#linearGradient6234);fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 43.618297,13.59375 C 43.618297,13.59375 46.735124,21.336074 29.118297,26.125 C 27.130318,26.665409 25.618721,26.966252 24.462047,27.125 L 24.462047,22.84375 C 26.782455,20.91245 29.579948,19.082733 29.587047,19.0625 L 43.618297,13.59375 z "
+         id="path13993" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         id="path6208"
+         d="M 43.212385,14.274928 C 43.212385,14.274928 43.352117,14.773946 43.236844,15.68169 L 30.595441,20.860469 L 30.000278,19.675736 L 43.212385,14.274928 z "
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+      <path
+         style="fill:url(#linearGradient6236);fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 39.149547,6.6875 C 39.149547,6.6875 44.655755,12.960627 29.618297,23.3125 C 27.268694,24.92998 25.593801,25.897272 24.462047,26.34375 L 24.462047,21.21875 C 25.952449,18.819541 27.712047,16.519886 27.712047,16.5 L 39.149547,6.6875 z "
+         id="path13995" />
+      <path
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 39.04058,7.4343786 C 39.04058,7.4343786 39.330135,7.8641495 39.506137,8.7620957 L 29.13433,17.653128 L 28.19683,16.715628 L 39.04058,7.4343786 z "
+         id="path13997"
+         sodipodi:nodetypes="ccccc" />
+    </g>
+    <g
+       id="g6238"
+       transform="matrix(-1,0,0,1,48.495385,0)">
+      <path
+         id="path6240"
+         d="M 24.462047,28.5 L 36.274547,33.125 C 36.274547,33.125 34.737364,37.091205 24.462047,33.40625 L 24.462047,28.5 z "
+         style="fill:url(#linearGradient6260);fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         id="path6242"
+         d="M 35.418539,33.412478 C 35.418539,33.412478 34.724386,33.599892 33.985706,34.139928 L 21.964135,28.771824 L 22.41585,27.525323 L 35.418539,33.412478 z "
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+      <path
+         id="path6244"
+         d="M 25.993297,26.34375 L 40.837047,28.0625 C 40.837047,28.0625 40.49275,34.283482 24.462047,31.46875 L 24.462047,26.46875 C 25.015589,26.426108 25.988622,26.347435 25.993297,26.34375 z "
+         style="fill:url(#linearGradient6262);fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+      <path
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 40.195754,28.519004 C 40.195754,28.519004 39.813326,29.020009 39.253932,29.744141 L 25.981569,27.802359 L 26.068881,26.479412 L 40.195754,28.519004 z "
+         id="path6246"
+         sodipodi:nodetypes="ccccc" />
+      <path
+         id="path6248"
+         d="M 43.993297,21.4375 C 43.993297,21.437499 45.628594,28.747665 27.430797,29.625 C 26.30527,29.679263 25.30967,29.72042 24.462047,29.71875 L 24.462047,25.46875 C 26.808644,24.435229 29.171474,23.607908 29.180797,23.59375 L 43.993297,21.4375 z "
+         style="fill:url(#linearGradient6264);fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         id="path6250"
+         d="M 43.462892,22.001537 C 43.462892,22.001537 43.476033,22.519583 43.141756,23.371373 L 29.616553,25.293276 L 29.329971,23.998794 L 43.462892,22.001537 z "
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+      <path
+         id="path6252"
+         d="M 43.618297,13.59375 C 43.618297,13.59375 46.735124,21.336074 29.118297,26.125 C 27.130318,26.665409 25.618721,26.966252 24.462047,27.125 L 24.462047,22.84375 C 26.782455,20.91245 29.579948,19.082733 29.587047,19.0625 L 43.618297,13.59375 z "
+         style="fill:url(#linearGradient6266);fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+      <path
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         d="M 43.212385,14.274928 C 43.212385,14.274928 43.352117,14.773946 43.236844,15.68169 L 30.595441,20.860469 L 30.000278,19.675736 L 43.212385,14.274928 z "
+         id="path6254"
+         sodipodi:nodetypes="ccccc" />
+      <path
+         id="path6256"
+         d="M 39.149547,6.6875 C 39.149547,6.6875 44.655755,12.960627 29.618297,23.3125 C 27.268694,24.92998 25.593801,25.897272 24.462047,26.34375 L 24.462047,21.21875 C 25.952449,18.819541 27.712047,16.519886 27.712047,16.5 L 39.149547,6.6875 z "
+         style="fill:url(#linearGradient6268);fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         id="path6258"
+         d="M 39.04058,7.4343786 C 39.04058,7.4343786 39.330135,7.8641495 39.506137,8.7620957 L 29.13433,17.653128 L 28.19683,16.715628 L 39.04058,7.4343786 z "
+         style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="main"
+     style="display:inline">
+    <path
+       style="fill:url(#linearGradient12835);fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-mid:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 18.130032,15.704157 L 19.130032,41.662825 C 19.129093,41.668442 19.130032,41.678918 19.130032,41.684566 C 19.130032,42.068599 21.311777,42.804059 24,42.804059 C 26.688222,42.804059 28.869966,42.068599 28.869968,41.684566 C 28.869968,41.679766 28.870646,41.667603 28.869968,41.662825 L 29.869968,15.704157 L 18.130032,15.704157 z "
+       id="handle"
+       sodipodi:nodetypes="ccsssccc" />
+    <path
+       style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient12874);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-mid:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 19.149262,16.684861 L 20.084146,41.15011 C 20.616446,41.459648 21.770533,41.744086 24.009631,41.744086 C 26.248728,41.744086 27.906409,41.125857 27.90719,41.105453 L 28.841107,16.694493 L 19.149262,16.684861 z "
+       id="path12857"
+       sodipodi:nodetypes="ccsscc" />
+    <path
+       style="fill:url(#linearGradient6204);fill-opacity:1.0;fill-rule:evenodd;stroke:url(#linearGradient10785);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-mid:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 19.150481,15.295842 C 19.281912,17.620392 19.355179,20.756688 19.368976,21.441103 C 21.195694,22.229425 22.132819,22.354668 23.982251,22.5 C 25.806131,22.391411 26.756919,22.225505 28.631025,21.448742 L 28.849519,15.295842 L 19.150481,15.295842 z "
+       id="path9535"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       transform="matrix(0.8821489,0,0,0.8821489,27.027944,-1.3222195)"
+       d="M 4.9035182 12.204313 A 8.3359814 8.3359814 0 1 1  -11.768445,12.204313 A 8.3359814 8.3359814 0 1 1  4.9035182 12.204313 z"
+       sodipodi:ry="8.3359814"
+       sodipodi:rx="8.3359814"
+       sodipodi:cy="12.204313"
+       sodipodi:cx="-3.4324632"
+       id="path13902"
+       style="opacity:1;fill:url(#radialGradient13910);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient13912);stroke-width:1.13359559;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc" />
+    <a
+       id="micro_dots"
+       inkscape:label="#a4718"
+       style="opacity:0.85">
+      <g
+         style="fill:url(#linearGradient4878)"
+         id="g4559">
+        <path
+           transform="matrix(0.2622951,0,0,0.2622951,10.33805,3.37772)"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           sodipodi:ry="1.90625"
+           sodipodi:rx="1.90625"
+           sodipodi:cy="-1.7812501"
+           sodipodi:cx="33.03125"
+           id="path2562"
+           style="fill:url(#linearGradient4905);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           sodipodi:type="arc" />
+        <path
+           sodipodi:type="arc"
+           style="fill:url(#linearGradient4907);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           id="path2568"
+           sodipodi:cx="33.03125"
+           sodipodi:cy="-1.7812501"
+           sodipodi:rx="1.90625"
+           sodipodi:ry="1.90625"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           transform="matrix(0.2622951,0,0,0.2622951,12.33805,3.37772)" />
+        <g
+           style="fill:url(#linearGradient4909)"
+           id="g2572"
+           transform="translate(-19.472349,25.540624)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4911);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2574"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4913);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2576"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4915)"
+           id="g2578"
+           transform="translate(-17.472349,25.540624)">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2580"
+             style="opacity:1;fill:url(#linearGradient4917);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2582"
+             style="opacity:1;fill:url(#linearGradient4919);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4921)"
+           id="g2592"
+           transform="translate(-15.472349,25.540624)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4923);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2594"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4925);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2596"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <path
+           sodipodi:type="arc"
+           style="fill:url(#linearGradient4927);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           id="path2600"
+           sodipodi:cx="33.03125"
+           sodipodi:cy="-1.7812501"
+           sodipodi:rx="1.90625"
+           sodipodi:ry="1.90625"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           transform="matrix(0.2622951,0,0,0.2622951,20.33805,3.37772)" />
+        <g
+           style="fill:url(#linearGradient4929)"
+           transform="translate(-23.472349,27.540624)"
+           id="g2665">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2667"
+             style="opacity:1;fill:url(#linearGradient4931);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2669"
+             style="opacity:1;fill:url(#linearGradient4933);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4935)"
+           transform="translate(-21.472349,27.540624)"
+           id="g2671">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4937);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2673"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4939);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2675"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4941)"
+           transform="translate(-19.472349,27.540624)"
+           id="g2677">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2679"
+             style="opacity:1;fill:url(#linearGradient4943);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2681"
+             style="opacity:1;fill:url(#linearGradient4945);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4947)"
+           id="g2683"
+           transform="translate(-17.472349,27.540624)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4949);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2685"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4951);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2687"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4953)"
+           transform="translate(-15.472349,27.540624)"
+           id="g2689">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2691"
+             style="opacity:1;fill:url(#linearGradient4955);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2693"
+             style="opacity:1;fill:url(#linearGradient4957);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4959)"
+           id="g2695"
+           transform="translate(-13.472349,27.540624)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4961);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2697"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4963);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2699"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <path
+           sodipodi:type="arc"
+           style="fill:url(#linearGradient4965);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           id="path2705"
+           sodipodi:cx="33.03125"
+           sodipodi:cy="-1.7812501"
+           sodipodi:rx="1.90625"
+           sodipodi:ry="1.90625"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           transform="matrix(0.2622951,0,0,0.2622951,21.336065,4.392443)" />
+        <path
+           sodipodi:type="arc"
+           style="fill:url(#linearGradient4967);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           id="path2717"
+           sodipodi:cx="33.03125"
+           sodipodi:cy="-1.7812501"
+           sodipodi:rx="1.90625"
+           sodipodi:ry="1.90625"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           transform="matrix(0.2622951,0,0,0.2622951,8.33805,7.37772)" />
+        <g
+           style="fill:url(#linearGradient4969)"
+           id="g2721"
+           transform="translate(-23.472349,29.540624)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4971);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2723"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4973);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2725"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4975)"
+           id="g2727"
+           transform="translate(-21.472349,29.540624)">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2729"
+             style="opacity:1;fill:url(#linearGradient4977);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2731"
+             style="opacity:1;fill:url(#linearGradient4979);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4981)"
+           id="g2733"
+           transform="translate(-19.472349,29.540624)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4983);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2735"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4985);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2737"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4987)"
+           id="g2739"
+           transform="translate(-17.472349,29.540624)">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2741"
+             style="opacity:1;fill:url(#linearGradient4989);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2743"
+             style="opacity:1;fill:url(#linearGradient4991);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4993)"
+           id="g2745"
+           transform="translate(-15.472349,29.540624)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4995);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2747"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient4997);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2749"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient4999)"
+           transform="translate(-13.472349,29.540624)"
+           id="g2751">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2753"
+             style="opacity:1;fill:url(#linearGradient5001);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2755"
+             style="opacity:1;fill:url(#linearGradient5003);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5005)"
+           id="g2757"
+           transform="translate(-11.472349,29.540624)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5007);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2759"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5009);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2761"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5011)"
+           transform="translate(-25.472349,31.540623)"
+           id="g2771">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5013);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2773"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5015);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2775"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5017)"
+           transform="translate(-23.472349,31.540623)"
+           id="g2777">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2779"
+             style="opacity:1;fill:url(#linearGradient5019);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2781"
+             style="opacity:1;fill:url(#linearGradient5021);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5023)"
+           transform="translate(-21.472349,31.540623)"
+           id="g2783">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5025);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2785"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2787"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5029)"
+           transform="translate(-19.472349,31.540623)"
+           id="g2789">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2791"
+             style="opacity:1;fill:url(#linearGradient5031);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2793"
+             style="opacity:1;fill:url(#linearGradient5033);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5035)"
+           id="g2795"
+           transform="translate(-17.472349,31.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5037);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2797"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5039);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2799"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5041)"
+           transform="translate(-15.472349,31.540623)"
+           id="g2801">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2803"
+             style="opacity:1;fill:url(#linearGradient5043);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2805"
+             style="opacity:1;fill:url(#linearGradient5045);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5047)"
+           id="g2807"
+           transform="translate(-13.472349,31.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5049);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2809"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5051);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2811"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5053)"
+           transform="translate(-11.472349,31.540623)"
+           id="g2813">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2815"
+             style="opacity:1;fill:url(#linearGradient5055);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2817"
+             style="opacity:1;fill:url(#linearGradient5057);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <path
+           transform="matrix(0.2622951,0,0,0.2622951,23.336065,8.392442)"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           sodipodi:ry="1.90625"
+           sodipodi:rx="1.90625"
+           sodipodi:cy="-1.7812501"
+           sodipodi:cx="33.03125"
+           id="path2823"
+           style="fill:url(#linearGradient5059);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           sodipodi:type="arc" />
+        <g
+           style="fill:url(#linearGradient5061)"
+           id="g2827"
+           transform="translate(-25.472349,33.540623)">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2829"
+             style="opacity:1;fill:url(#linearGradient5063);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2831"
+             style="opacity:1;fill:url(#linearGradient5065);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5067)"
+           id="g2833"
+           transform="translate(-23.472349,33.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5069);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2835"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5071);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2837"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5073)"
+           id="g2839"
+           transform="translate(-21.472349,33.540623)">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2841"
+             style="opacity:1;fill:url(#linearGradient5075);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2843"
+             style="opacity:1;fill:url(#linearGradient5077);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5079)"
+           id="g2845"
+           transform="translate(-19.472349,33.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5081);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2847"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5083);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2849"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5085)"
+           id="g2851"
+           transform="translate(-17.472349,33.540623)">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2853"
+             style="opacity:1;fill:url(#linearGradient5087);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2855"
+             style="opacity:1;fill:url(#linearGradient5089);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5091)"
+           id="g2857"
+           transform="translate(-15.472349,33.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5093);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2859"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5095);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2861"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5097)"
+           transform="translate(-13.472349,33.540623)"
+           id="g2863">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2865"
+             style="opacity:1;fill:url(#linearGradient5099);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2867"
+             style="opacity:1;fill:url(#linearGradient5101);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5103)"
+           id="g2869"
+           transform="translate(-11.472349,33.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5105);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2871"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5107);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2873"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <path
+           sodipodi:type="arc"
+           style="fill:url(#linearGradient5109);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           id="path2879"
+           sodipodi:cx="33.03125"
+           sodipodi:cy="-1.7812501"
+           sodipodi:rx="1.90625"
+           sodipodi:ry="1.90625"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           transform="matrix(0.2622951,0,0,0.2622951,23.336065,10.392442)" />
+        <path
+           transform="matrix(0.2622951,0,0,0.2622951,8.33805,13.377719)"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           sodipodi:ry="1.90625"
+           sodipodi:rx="1.90625"
+           sodipodi:cy="-1.7812501"
+           sodipodi:cx="33.03125"
+           id="path2885"
+           style="fill:url(#linearGradient5111);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           sodipodi:type="arc" />
+        <g
+           style="fill:url(#linearGradient5113)"
+           transform="translate(-23.472349,35.540623)"
+           id="g2889">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2891"
+             style="opacity:1;fill:url(#linearGradient5115);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2893"
+             style="opacity:1;fill:url(#linearGradient5117);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5119)"
+           transform="translate(-21.472349,35.540623)"
+           id="g2895">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5121);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2897"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5123);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2899"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5125)"
+           transform="translate(-19.472349,35.540623)"
+           id="g2901">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2903"
+             style="opacity:1;fill:url(#linearGradient5127);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2905"
+             style="opacity:1;fill:url(#linearGradient5129);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5131)"
+           id="g2907"
+           transform="translate(-17.472349,35.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5133);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2909"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5135);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2911"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5137)"
+           transform="translate(-15.472349,35.540623)"
+           id="g2913">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2915"
+             style="opacity:1;fill:url(#linearGradient5139);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2917"
+             style="opacity:1;fill:url(#linearGradient5141);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5143)"
+           id="g2919"
+           transform="translate(-13.472349,35.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5145);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2921"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5147);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2923"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5149)"
+           transform="translate(-11.472349,35.540623)"
+           id="g2925">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2927"
+             style="opacity:1;fill:url(#linearGradient5151);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2929"
+             style="opacity:1;fill:url(#linearGradient5153);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5155)"
+           id="g2945"
+           transform="translate(-23.472349,37.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5157);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2947"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5159);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2949"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5161)"
+           id="g2951"
+           transform="translate(-21.472349,37.540623)">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2953"
+             style="opacity:1;fill:url(#linearGradient5163);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2955"
+             style="opacity:1;fill:url(#linearGradient5165);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5167)"
+           id="g2957"
+           transform="translate(-19.472349,37.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5169);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2959"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5171);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2961"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5173)"
+           id="g2963"
+           transform="translate(-17.472349,37.540623)">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2965"
+             style="opacity:1;fill:url(#linearGradient5175);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2967"
+             style="opacity:1;fill:url(#linearGradient5177);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5179)"
+           id="g2969"
+           transform="translate(-15.472349,37.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5181);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2971"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5183);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path2973"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5185)"
+           transform="translate(-13.472349,37.540623)"
+           id="g2975">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2977"
+             style="opacity:1;fill:url(#linearGradient5187);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path2979"
+             style="opacity:1;fill:url(#linearGradient5189);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <path
+           transform="matrix(0.2622951,0,0,0.2622951,21.336065,14.392442)"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           sodipodi:ry="1.90625"
+           sodipodi:rx="1.90625"
+           sodipodi:cy="-1.7812501"
+           sodipodi:cx="33.03125"
+           id="path2985"
+           style="fill:url(#linearGradient5191);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           sodipodi:type="arc" />
+        <g
+           style="fill:url(#linearGradient5193)"
+           transform="translate(-21.472349,39.540623)"
+           id="g3007">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5195);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path3009"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5197);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path3011"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5199)"
+           transform="translate(-19.472349,39.540623)"
+           id="g3013">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path3015"
+             style="opacity:1;fill:url(#linearGradient5201);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path3017"
+             style="opacity:1;fill:url(#linearGradient5203);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5205)"
+           id="g3019"
+           transform="translate(-17.472349,39.540623)">
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5207);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path3021"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)" />
+          <path
+             sodipodi:type="arc"
+             style="opacity:1;fill:url(#linearGradient5209);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             id="path3023"
+             sodipodi:cx="33.03125"
+             sodipodi:cy="-1.7812501"
+             sodipodi:rx="1.90625"
+             sodipodi:ry="1.90625"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)" />
+        </g>
+        <g
+           style="fill:url(#linearGradient5211)"
+           transform="translate(-15.472349,39.540623)"
+           id="g3025">
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,33.810399,-22.162904)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path3027"
+             style="opacity:1;fill:url(#linearGradient5213);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+          <path
+             transform="matrix(0.2622951,0,0,0.2622951,32.808414,-23.148181)"
+             d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+             sodipodi:ry="1.90625"
+             sodipodi:rx="1.90625"
+             sodipodi:cy="-1.7812501"
+             sodipodi:cx="33.03125"
+             id="path3029"
+             style="opacity:1;fill:url(#linearGradient5215);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+             sodipodi:type="arc" />
+        </g>
+        <path
+           transform="matrix(0.2622951,0,0,0.2622951,19.336065,16.392442)"
+           d="M 34.9375 -1.7812501 A 1.90625 1.90625 0 1 1  31.125,-1.7812501 A 1.90625 1.90625 0 1 1  34.9375 -1.7812501 z"
+           sodipodi:ry="1.90625"
+           sodipodi:rx="1.90625"
+           sodipodi:cy="-1.7812501"
+           sodipodi:cx="33.03125"
+           id="path3035"
+           style="fill:url(#linearGradient5217);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:2.70000005;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.52156863"
+           sodipodi:type="arc" />
+      </g>
+    </a>
+    <path
+       transform="translate(27.432463,-2.7864454)"
+       d="M 4.9035182 12.204313 A 8.3359814 8.3359814 0 1 1  -11.768445,12.204313 A 8.3359814 8.3359814 0 1 1  4.9035182 12.204313 z"
+       sodipodi:ry="8.3359814"
+       sodipodi:rx="8.3359814"
+       sodipodi:cy="12.204313"
+       sodipodi:cx="-3.4324632"
+       id="path5219"
+       style="opacity:1;fill:url(#radialGradient6196);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#444329;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path9466"
+       sodipodi:cx="-3.4324632"
+       sodipodi:cy="12.204313"
+       sodipodi:rx="8.3359814"
+       sodipodi:ry="8.3359814"
+       d="M 4.9035182 12.204313 A 8.3359814 8.3359814 0 1 1  -11.768445,12.204313 A 8.3359814 8.3359814 0 1 1  4.9035182 12.204313 z"
+       transform="translate(27.432463,-2.7864454)" />
+    <g
+       inkscape:label="shadow"
+       id="layer2"
+       transform="matrix(0.634441,0,0,0.5906689,8.5468312,17.929513)">
+      <path
+         transform="matrix(1.18638,0,0,1.18638,-4.539687,-7.794678)"
+         d="M 44.285715 38.714287 A 19.928572 9.837245 0 1 1  4.4285717,38.714287 A 19.928572 9.837245 0 1 1  44.285715 38.714287 z"
+         sodipodi:ry="9.837245"
+         sodipodi:rx="19.928572"
+         sodipodi:cy="38.714287"
+         sodipodi:cx="24.357143"
+         id="path1538"
+         style="color:#000000;fill:url(#radialGradient13964);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.50000042;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+         sodipodi:type="arc" />
+    </g>
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.59444444;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient13912);stroke-width:1.13359559;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path6270"
+       sodipodi:cx="-3.4324632"
+       sodipodi:cy="12.204313"
+       sodipodi:rx="8.3359814"
+       sodipodi:ry="8.3359814"
+       d="M 4.9035182 12.204313 A 8.3359814 8.3359814 0 1 1  -11.768445,12.204313 A 8.3359814 8.3359814 0 1 1  4.9035182 12.204313 z"
+       transform="matrix(0.8821489,0,0,0.8821489,27.027944,-1.3222195)" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer7"
+     inkscape:label="monkey"
+     style="display:none" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer6"
+     inkscape:label="mic mesh"
+     style="display:inline">
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M -2.9664775,3.1561066 C -2.9664775,3.1561066 0.80903931,5.5832246 6.9731484,3.1561066"
+       id="path14185" />
+  </g>
+</svg>
diff --git a/songmanagement/icons/ultrastardx-icon_32.png b/songmanagement/icons/ultrastardx-icon_32.png
new file mode 100644
index 00000000..1b13a6ee
Binary files /dev/null and b/songmanagement/icons/ultrastardx-icon_32.png differ
diff --git a/songmanagement/icons/ultrastardx-icon_512.png b/songmanagement/icons/ultrastardx-icon_512.png
new file mode 100644
index 00000000..d02ec89c
Binary files /dev/null and b/songmanagement/icons/ultrastardx-icon_512.png differ
diff --git a/songmanagement/icons/ultrastardx.icns b/songmanagement/icons/ultrastardx.icns
new file mode 100644
index 00000000..86b128b0
Binary files /dev/null and b/songmanagement/icons/ultrastardx.icns differ
diff --git a/songmanagement/icons/ultrastardx.ico b/songmanagement/icons/ultrastardx.ico
new file mode 100644
index 00000000..e5b21364
Binary files /dev/null and b/songmanagement/icons/ultrastardx.ico differ
diff --git a/songmanagement/installer/UAC.nsh b/songmanagement/installer/UAC.nsh
new file mode 100644
index 00000000..b21e72ff
--- /dev/null
+++ b/songmanagement/installer/UAC.nsh
@@ -0,0 +1,191 @@
+/*
+=======================
+UAC helper include file
+.......................
+
+Macros starting with UAC.I should only be called from the installer and vice versa for UAC.U macros.
+
+*/
+!ifndef UAC_HDR__INC
+!define UAC_HDR__INC
+!include LogicLib.nsh
+
+!define UAC.RunElevatedAndProcessMessages 'UAC::RunElevated '
+!define UAC.Unload 'UAC::Unload '
+!define UAC.StackPush 'UAC::StackPush '
+
+/*!macro _UAC.BuildOnInitElevationFunc _funcprefix
+Function ${_funcprefix}onInit
+!ifmacrodef
+FunctionEnd
+!macroend*/
+
+!macro _UAC.GenerateSimpleFunction _funcprefix _funcName _funcCode
+Function ${_funcprefix}${_funcName}
+${_funcCode}
+#messagebox mb_ok "${_funcprefix}${_funcName}"
+FunctionEnd
+!macroend
+
+!macro _UAC.TryDef _d _v
+!ifndef ${_d}
+!define ${_d} "${_v}"
+!endif
+!macroend
+
+!macro _UAC.InitStrings _modeprefix
+!insertmacro _UAC.TryDef UACSTR.UnDataFile "UAC.dat"
+!insertmacro _UAC.TryDef UACSTR.${_modeprefix}ElvWinErr "Unable to elevate , error $0"
+!ifNdef __UNINSTALL__
+	!insertmacro _UAC.TryDef UACSTR.${_modeprefix}ElvAbortReqAdmin "This installer requires admin access, aborting!"
+	!insertmacro _UAC.TryDef UACSTR.${_modeprefix}ElvMustTryAgain "This installer requires admin access, try again"
+	!else
+	!insertmacro _UAC.TryDef UACSTR.${_modeprefix}ElvAbortReqAdmin "This uninstaller requires admin access, aborting!"
+	!insertmacro _UAC.TryDef UACSTR.${_modeprefix}ElvMustTryAgain "This uninstaller requires admin access, try again"
+	!endif
+!macroend
+
+!ifmacroNdef _UAC.GenerateUninstallerTango
+!macro _UAC.GenerateUninstallerTango UninstallerFileName
+!ifdef __GLOBAL__
+	!error "UAC: Needs to be called inside a function"
+	!endif
+!ifNdef __UNINSTALL__
+	!error "UAC: _UAC.GenerateUninstallerTango should only be called by uninstaller, see http://forums.winamp.com/showthread.php?threadid=280330"
+	!endif
+!ifNdef UAC_UNINSTALLERTANGOFORALLPLATFORMS
+	!include WinVer.nsh
+	!endif
+!insertmacro _UAC.InitStrings 'U.'
+ReadIniStr $0 "$ExeDir\${UACSTR.UnDataFile}" UAC "Un.Ready"
+${IF} $0 != 1
+!ifNdef UAC_UNINSTALLERTANGOFORALLPLATFORMS
+${AndIf} ${AtLeastWinVista}
+!endif
+	InitPluginsDir
+	WriteIniStr "$PluginsDir\${UACSTR.UnDataFile}" UAC "Un.Ready" 1
+	CopyFiles /SILENT "$EXEPATH" "$PluginsDir\${UninstallerFileName}"
+	StrCpy $0 ""
+	${IfThen} ${Silent} ${|} StrCpy $0 "/S " ${|}
+	ExecWait '"$PluginsDir\${UninstallerFileName}" $0/NCRC _?=$INSTDIR' $0
+	SetErrorLevel $0
+	Quit
+	${EndIf}
+!macroend
+!endif
+
+!ifmacroNdef _UAC.GenerateOnInitElevationCode
+!macro _UAC.GenerateOnInitElevationCode _modeprefix
+!ifndef __FUNCTION__
+	!error "UAC: Needs to be called inside a function"
+	!endif
+!insertmacro _UAC.InitStrings ${_modeprefix}
+!define _UAC.GOIECUniq L${__LINE__}
+UAC_Elevate_${_UAC.GOIECUniq}:
+UAC::RunElevated 
+StrCmp 1223 $0 UAC_ElevationAborted_${_UAC.GOIECUniq} ; UAC dialog aborted by user?
+StrCmp 0 $0 0 UAC_Err_${_UAC.GOIECUniq} ; Error?
+StrCmp 1 $1 0 UAC_Success_${_UAC.GOIECUniq} ;Are we the real deal or just the wrapper?
+Quit
+UAC_Err_${_UAC.GOIECUniq}:
+MessageBox mb_iconstop "${UACSTR.${_modeprefix}ElvWinErr}"
+Abort
+UAC_ElevationAborted_${_UAC.GOIECUniq}:
+MessageBox mb_iconstop "${UACSTR.${_modeprefix}ElvAbortReqAdmin}"
+Abort
+UAC_Success_${_UAC.GOIECUniq}:
+# if $0==0 && $3==1, we are a member of the admin group (Any OS)
+# if $0==0 && $1==0, UAC not supported (Probably <NT6), run as normal?
+# if $0==0 && $1==3, we can try to elevate again
+StrCmp 1 $3 /*+4*/ UAC_Done_${_UAC.GOIECUniq} ;Admin?
+StrCmp 3 $1 0 UAC_ElevationAborted_${_UAC.GOIECUniq} ;Try again or abort?
+MessageBox mb_iconexclamation "${UACSTR.${_modeprefix}ElvMustTryAgain}" ;Inform user...
+goto UAC_Elevate_${_UAC.GOIECUniq} ;...lets try again
+UAC_Done_${_UAC.GOIECUniq}:
+!undef _UAC.GOIECUniq
+!macroend
+!endif
+
+!define UAC.I.Elevate.AdminOnly '!insertmacro UAC.I.Elevate.AdminOnly '
+!macro UAC.I.Elevate.AdminOnly
+!insertmacro _UAC.GenerateOnInitElevationCode 'I.'
+!macroend
+
+!define UAC.U.Elevate.AdminOnly '!insertmacro UAC.U.Elevate.AdminOnly '
+!macro UAC.U.Elevate.AdminOnly _UninstallerName
+!ifNdef UAC_DISABLEUNINSTALLERTANGO
+	!insertmacro _UAC.GenerateUninstallerTango "${_UninstallerName}"
+	!endif
+!insertmacro _UAC.GenerateOnInitElevationCode 'U.'
+!macroend
+
+!define UAC.AutoCodeUnload '!insertmacro UAC.AutoCodeUnload '
+!macro UAC.AutoCodeUnload _HasUninstaller
+!insertmacro _UAC.GenerateSimpleFunction "" .OnInstFailed '${UAC.Unload}'
+!insertmacro _UAC.GenerateSimpleFunction "" .OnInstSuccess '${UAC.Unload}'
+!ifNdef MUI_INCLUDED
+	!insertmacro _UAC.GenerateSimpleFunction "" .onUserAbort '${UAC.Unload}'
+	!else
+	!ifNdef MUI_CUSTOMFUNCTION_ABORT
+		!error "UAC: must call $$ {UAC.Unload} in MUI_CUSTOMFUNCTION_ABORT!"
+		!endif
+	!endif
+!if "${_HasUninstaller}" != ""
+	!insertmacro _UAC.GenerateSimpleFunction "un" .onUninstFailed '${UAC.Unload}'
+	!insertmacro _UAC.GenerateSimpleFunction "un" .onUninstSuccess '${UAC.Unload}'
+	!ifNdef MUI_INCLUDED
+		!insertmacro _UAC.GenerateSimpleFunction "un" .onUserAbort '${UAC.Unload}'
+		!else
+		!ifNdef MUI_CUSTOMFUNCTION_ABORT
+			!error "UAC: must call $$ {UAC.Unload} in MUI_CUSTOMFUNCTION_(UN)ABORT!"
+			!endif
+		!endif
+	!endif
+!macroend
+
+!define UAC.FastCallFunctionAsUser '!insertmacro UAC.FastCallFunctionAsUser '
+!macro UAC.FastCallFunctionAsUser _func _var
+GetFunctionAddress ${_var} ${_func}
+UAC::ExecCodeSegment ${_var}
+!macroend
+!define UAC.CallFunctionAsUser '!insertmacro UAC.CallFunctionAsUser '
+!macro UAC.CallFunctionAsUser _func
+push $R9
+!insertmacro UAC.FastCallFunctionAsUser ${_func} $R9
+pop $R9
+!macroend
+
+!define UAC.FastCallGetOuterInstanceHwndParent UAC::GetOuterHwnd
+!define UAC.GetOuterInstanceHwndParent '!insertmacro UAC.GetOuterInstanceHwndParent '
+!macro UAC.GetOuterInstanceHwndParent _var
+push $0
+${UAC.FastCallGetOuterInstanceHwndParent}
+Exch $0
+Pop ${_var}
+!macroend
+
+
+
+!macro _UAC.DumpEx _disp _f _fp _v
+${_f} ${_fp}
+DetailPrint "${_disp}=${_v}"
+!macroend
+!macro _UAC.Dump _f _fp _v
+!insertmacro _UAC.DumpEx `${_f}` `${_f}` `${_fp}` `${_v}`
+!macroend
+!macro _UAC.DbgDetailPrint
+push $0
+push $1
+System::Call /NoUnload "advapi32::GetUserName(t.r0,*i${NSIS_MAX_STRLEN})"
+System::Call "Kernel32::GetComputerName(t.r1,*i${NSIS_MAX_STRLEN})"
+DetailPrint "$1\$0"
+;!insertmacro _UAC.DumpEx "User" System::Call "advapi32::GetUserName(t.r0,*i${NSIS_MAX_STRLEN})" $0
+!insertmacro _UAC.DumpEx "CmdLine" "" "" "$CmdLine"
+!insertmacro _UAC.Dump UAC::IsAdmin "" $0
+!insertmacro _UAC.Dump UAC::SupportsUAC "" $0
+!insertmacro _UAC.Dump UAC::GetElevationType "" $0
+pop $1
+pop $0
+!macroend
+
+!endif /* ifndef UAC_HDR__INC */
\ No newline at end of file
diff --git a/songmanagement/installer/UltraStar Deluxe.nsi b/songmanagement/installer/UltraStar Deluxe.nsi
new file mode 100644
index 00000000..e98edc54
--- /dev/null
+++ b/songmanagement/installer/UltraStar Deluxe.nsi	
@@ -0,0 +1,614 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Installer: Main
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+!include MUI2.nsh
+!include WinVer.nsh
+!include LogicLib.nsh
+!include InstallOptions.nsh
+!include nsDialogs.nsh
+!include UAC.nsh
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Variables
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+; Installer Paths:
+
+!define path_settings ".\settings"
+!define path_languages ".\languages"
+!define path_dependencies ".\dependencies"
+!define path_images ".\dependencies\images"
+!define path_plugins ".\dependencies\plugins"
+
+; MultiLanguage - Show all languages:
+!define MUI_LANGDLL_ALLLANGUAGES
+
+!addPluginDir "${path_plugins}\"
+
+!include "${path_settings}\variables.nsh"
+!include "${path_settings}\functions.nsh"
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Export Settings
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+SetCompress Auto
+SetCompressor lzma
+SetCompressorDictSize 32
+SetDatablockOptimize On
+
+CRCCheck on
+
+XPStyle on
+
+Name "${name} v.${version}"
+Brandingtext "${name} v.${version} Installation"
+OutFile "ultrastardx-${version}-installer-full.exe"
+
+InstallDir "$PROGRAMFILES\${name}"
+InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\UltraStar Deluxe" "InstallDir"
+
+; Windows Vista / Windows 7:
+; must be "user" for UAC plugin 
+RequestExecutionLevel user
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Interface Settings
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+; Icons:
+
+!define MUI_ICON "${img_install}"
+!define MUI_UNICON "${img_uninstall}"
+
+; Header and Side Images:
+
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_BITMAP "${path_images}\${img_header}"
+!define MUI_HEADERIMAGE_UNBITMAP "${path_images}\${img_header}"
+
+!define MUI_WELCOMEFINISHPAGE_BITMAP "${path_images}\${img_side}"
+!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${path_images}\${img_side}"
+
+; Abort Warnings:
+
+!define MUI_ABORTWARNING
+!define MUI_ABORTWARNING_TEXT "$(abort_install)"
+!define MUI_ABORTWARNING_CANCEL_DEFAULT
+
+!define MUI_UNABORTWARNING
+!define MUI_UNABORTWARNING_TEXT "$(abort_uninstall)"
+!define MUI_UNABORTWARNING_CANCEL_DEFAULT
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Pages Installation Routine Settings
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+!define MUI_CUSTOMFUNCTION_GUIINIT bgmusic
+
+; Welcome Page:
+
+!define MUI_WELCOMEPAGE_TITLE_3LINES
+!define MUI_WELCOMEPAGE_TITLE "$(page_welcome_title)"
+
+!define MUI_WELCOMEPAGE_TEXT "$(page_welcome_txt)"
+
+; License Page:
+
+!define MUI_LICENSEPAGE_RADIOBUTTONS
+
+; Components Page:
+
+!define MUI_COMPONENTSPAGE_SMALLDESC
+!define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO $(page_components_info)
+
+; Finish Pages:
+
+!define MUI_FINISHPAGE_TITLE_3LINES
+
+!define MUI_FINISHPAGE_TEXT_LARGE
+!define MUI_FINISHPAGE_TEXT "$(page_finish_txt)"
+
+; MUI_FINISHPAGE_RUN is executed as admin by default.
+; To get the config.ini location right it must be executed with user 
+; rights instead.
+!define MUI_FINISHPAGE_RUN
+!define MUI_FINISHPAGE_RUN_NOTCHECKED
+!define MUI_FINISHPAGE_RUN_FUNCTION RunAppAsUser 
+
+Function RunAppAsUser 
+    UAC::ShellExec 'open' '' '$INSTDIR\${exe}.exe' '' '$INSTDIR'
+FunctionEnd
+
+!define MUI_FINISHPAGE_LINK "$(page_finish_linktxt)"
+!define MUI_FINISHPAGE_LINK_LOCATION "${homepage}"
+
+!define MUI_FINISHPAGE_SHOWREADME
+!define MUI_FINISHPAGE_SHOWREADME_TEXT $(page_finish_desktop)
+!define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateDesktopShortCuts
+
+!define MUI_FINISHPAGE_NOAUTOCLOSE
+!define MUI_UNFINISHPAGE_NOAUTOCLOSE
+
+!define MUI_FINISHPAGE_NOREBOOTSUPPORT
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Pages Installation Routine
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro MUI_PAGE_LICENSE "${license}"
+!insertmacro MUI_PAGE_COMPONENTS
+!insertmacro MUI_PAGE_DIRECTORY
+
+; Start menu page
+
+Var ICONS_GROUP
+!define MUI_STARTMENUPAGE_NODISABLE
+!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${name}"
+!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
+!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
+!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${name}"
+!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
+
+!insertmacro MUI_PAGE_INSTFILES
+
+; USDX Settings Page
+
+Page custom Settings
+
+
+; User data info
+
+Var UseAppData    ; true if APPDATA is used for user data, false for INSTDIR
+Var UserDataPath  ; Path to user data dir (e.g. $INSTDIR)
+Var ConfigIniPath ; Path to config.ini (e.g. "$INSTDIR\config.ini")
+
+; Checks for write permissions on $INSTDIR\config.ini.
+; This function creates $INSTDIR\config.use as a marker file if
+; the user has write permissions.
+; Note: Must be run with user privileges
+Function CheckInstDirUserPermissions
+	ClearErrors
+	; try to open the ini file.
+	; Use "append" mode so an existing config.ini is not destroyed.
+	FileOpen $0 "$INSTDIR\config.ini" a
+	IfErrors end
+	; we have write permissions -> create a marker file
+	FileOpen $1 "$INSTDIR\config.use" a	
+	FileClose $1
+end:
+	FileClose $0
+FunctionEnd
+
+; Determines the directory used for config.ini and other user
+; settings and data.
+; Sets $UseAppData, $UserDataPath and $ConfigIniPath
+Function DetermineUserDataDir
+	Delete "$INSTDIR\config.use"
+	!insertmacro UAC.CallFunctionAsUser CheckInstDirUserPermissions
+	IfFileExists "$INSTDIR\config.use" 0 notexists
+	StrCpy $UseAppData false
+	StrCpy $UserDataPath "$INSTDIR"
+	Goto end
+notexists:
+	StrCpy $UseAppData true
+	SetShellVarContext current
+	StrCpy $UserDataPath "$APPDATA\ultrastardx"
+	SetShellVarContext all
+end:
+	Delete "$INSTDIR\config.use"	
+	StrCpy $ConfigIniPath "$UserDataPath\config.ini"
+FunctionEnd
+
+Function Settings
+
+	!insertmacro INSTALLOPTIONS_WRITE "Settings-$LANGUAGE" "Field 18" "State" "$INSTDIR\songs"
+
+	!insertmacro MUI_HEADER_TEXT " " "$(page_settings_subtitle)"   
+	!insertmacro INSTALLOPTIONS_DISPLAY "Settings-$LANGUAGE"
+
+	; Get all the variables:
+
+	Var /GLOBAL LABEL_COMPONENTS
+
+	Var /GLOBAL CHECKBOX_COVERS
+	Var /GLOBAL CB_COVERS_State
+	Var /GLOBAL CHECKBOX_SCORES
+	Var /GLOBAL CB_SCORES_State
+	Var /GLOBAL CHECKBOX_CONFIG
+	Var /GLOBAL CB_CONFIG_State
+	Var /GLOBAL CHECKBOX_SCREENSHOTS
+	Var /GLOBAL CB_SCREENSHOTS_State
+	Var /GLOBAL CHECKBOX_PLAYLISTS
+	Var /GLOBAL CB_PLAYLISTS_State
+	Var /GLOBAL CHECKBOX_SONGS 
+	Var /GLOBAL CB_SONGS_State
+
+	Var /GLOBAL fullscreen
+	Var /GLOBAL language2
+	Var /GLOBAL resolution
+	Var /GLOBAL tabs
+	Var /GLOBAL sorting
+	Var /GLOBAL songdir
+
+	!insertmacro INSTALLOPTIONS_READ $fullscreen "Settings-$LANGUAGE" "Field 5" "State"
+	!insertmacro INSTALLOPTIONS_READ $language2 "Settings-$LANGUAGE" "Field 6" "State"
+	!insertmacro INSTALLOPTIONS_READ $resolution "Settings-$LANGUAGE" "Field 7" "State"
+	!insertmacro INSTALLOPTIONS_READ $tabs "Settings-$LANGUAGE" "Field 8" "State"
+	!insertmacro INSTALLOPTIONS_READ $sorting "Settings-$LANGUAGE" "Field 15" "State"
+	!insertmacro INSTALLOPTIONS_READ $songdir "Settings-$LANGUAGE" "Field 18" "State"
+
+	WriteINIStr "$ConfigIniPath" "Game" "Language" "$language2"
+	WriteINIStr "$ConfigIniPath" "Game" "Tabs" "$tabs"
+	WriteINIStr "$ConfigIniPath" "Game" "Sorting" "$sorting"
+
+	WriteINIStr "$ConfigIniPath" "Graphics" "FullScreen" "$fullscreen"
+	WriteINIStr "$ConfigIniPath" "Graphics" "Resolution" "$resolution"
+
+	${If} $songdir != "$INSTDIR\songs"
+	WriteINIStr "$ConfigIniPath" "Directories" "SongDir1" "$songdir"
+	${EndIf}
+		
+FunctionEnd ; Settings page End
+
+!insertmacro MUI_PAGE_FINISH
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Pages UnInstallation Routine
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+!define MUI_WELCOMEPAGE_TITLE "$(page_un_welcome_title)"
+!insertmacro MUI_UNPAGE_WELCOME
+!insertmacro MUI_UNPAGE_CONFIRM
+
+UninstPage custom un.AskDelete un.DeleteAll
+
+Function un.AskDelete
+
+	nsDialogs::Create /NOUNLOAD 1018
+
+	${NSD_CreateLabel} 0 -195 100% 12u "$(delete_components)"
+	Pop $LABEL_COMPONENTS
+
+	${NSD_CreateCheckbox} 0 -175 100% 8u "$(delete_covers)"
+	Pop $CHECKBOX_COVERS
+	nsDialogs::OnClick /NOUNLOAD $CHECKBOX_COVERS $1
+
+	${NSD_CreateCheckbox} 0 -155 100% 8u "$(delete_config)"
+	Pop $CHECKBOX_CONFIG
+	nsDialogs::OnClick /NOUNLOAD $CHECKBOX_CONFIG $2
+
+	${NSD_CreateCheckbox} 0 -135 100% 8u "$(delete_highscores)"
+	Pop $CHECKBOX_SCORES 
+	nsDialogs::OnClick /NOUNLOAD $CHECKBOX_SCORES $3
+
+	${NSD_CreateCheckbox} 0 -115 100% 8u "$(delete_screenshots)"
+	Pop $CHECKBOX_SCREENSHOTS 
+	nsDialogs::OnClick /NOUNLOAD $CHECKBOX_SCREENSHOTS $4
+
+	${NSD_CreateCheckbox} 0 -95 100% 8u "$(delete_playlists)"
+	Pop $CHECKBOX_PLAYLISTS
+	nsDialogs::OnClick /NOUNLOAD $CHECKBOX_PLAYLISTS $5
+
+	${NSD_CreateCheckbox} 0 -65 100% 18u "$(delete_songs)"
+	Pop $CHECKBOX_SONGS 
+	nsDialogs::OnClick /NOUNLOAD $CHECKBOX_SONGS $6
+
+
+	nsDialogs::Show
+
+FunctionEnd
+
+Function un.DeleteAll
+
+${NSD_GetState} $CHECKBOX_COVERS $CB_COVERS_State
+${NSD_GetState} $CHECKBOX_CONFIG $CB_CONFIG_State
+${NSD_GetState} $CHECKBOX_SCORES $CB_SCORES_State
+${NSD_GetState} $CHECKBOX_SCORES $CB_SCREENSHOTS_State
+${NSD_GetState} $CHECKBOX_SCORES $CB_PLAYLISTS_State
+${NSD_GetState} $CHECKBOX_SONGS  $CB_SONGS_State
+
+${If} $CB_COVERS_State == "1" ; Remove covers
+	RMDir /r "$INSTDIR\covers"
+	SetShellVarContext current	
+	RMDir /r "$APPDATA\ultrastardx\covers"
+	SetShellVarContext all
+${EndIf}
+
+${If} $CB_CONFIG_State == "1" ; Remove config
+	SetShellVarContext current
+	Delete "$APPDATA\ultrastardx\config.ini" 
+	SetShellVarContext all
+	Delete "$INSTDIR\config.ini"
+${EndIf}
+
+${If} $CB_SCORES_State == "1" ; Remove highscores
+	SetShellVarContext current
+	Delete "$APPDATA\ultrastardx\Ultrastar.db" 
+	SetShellVarContext all
+	Delete "$INSTDIR\Ultrastar.db"
+${EndIf}
+
+${If} $CB_SCREENSHOTS_State == "1" ; Remove screenshots
+	RMDir /r "$INSTDIR\sreenshots"
+	SetShellVarContext current
+	RMDir /r "$APPDATA\ultrastardx\screenshots"
+	SetShellVarContext all
+${EndIf}
+
+${If} $CB_SCREENSHOTS_State == "1" ; Remove playlists
+	RMDir /r "$INSTDIR\playlists"
+	SetShellVarContext current
+	RMDir /r "$APPDATA\ultrastardx\playlists"
+	SetShellVarContext all
+${EndIf}
+
+${If} $CB_SONGS_State == "1" ; Remove songs
+	RMDir /r "$INSTDIR\songs"
+	SetShellVarContext current
+	RMDir /r "$APPDATA\ultrastardx\songs"
+	SetShellVarContext all
+${EndIf}
+
+
+FunctionEnd
+
+!insertmacro MUI_UNPAGE_INSTFILES
+!insertmacro MUI_UNPAGE_FINISH
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Sections Installation Routine
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+;------------------------------------
+; MAIN COMPONENTS (Section 1)
+;------------------------------------
+
+Section $(name_section1) Section1
+	SectionIn RO
+	SetOutPath $INSTDIR
+	SetOverwrite try
+
+	Call DetermineUserDataDir
+	
+	!include "${path_settings}\files_main_install.nsh"
+
+	; Create Shortcuts:
+	SetOutPath "$INSTDIR"
+
+!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+	SetShellVarContext all
+	SetOutPath "$INSTDIR"
+
+	CreateDirectory "${name}"
+	CreateDirectory "$SMPROGRAMS\$ICONS_GROUP"
+	CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\$(sm_shortcut).lnk" "$INSTDIR\${exe}.exe"
+	CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\$(sm_website).lnk" "http://www.ultrastardeluxe.org/"
+	CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\$(sm_songs).lnk" "$INSTDIR\songs"
+	CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\$(sm_uninstall).lnk" "$INSTDIR\Uninstall.exe"
+!insertmacro MUI_STARTMENU_WRITE_END
+
+	; Vista Game Explorer:
+	; (removed due to incompatibility with Windows 7, needs rewrite)
+
+	; Create Uninstaller:
+
+	WriteUninstaller "$INSTDIR\Uninstall.exe"
+
+	WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${name}"
+	WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\ultrastardx.exe"
+	WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "InstallDir" "$INSTDIR"
+	WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe"
+	WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+	WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
+	WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+
+	SetOutPath "$INSTDIR"
+
+SectionEnd
+
+;------------------------------------
+; OPTIONAL SONGS (Section 2)
+;------------------------------------
+
+ !include "${path_settings}\files_opt_songs.nsh"
+
+;------------------------------------
+; OPTIONAL THEMES (Section 3)
+;------------------------------------
+
+; No additional themes available 
+; for current version of ultrastardx
+
+;------------------------------------
+; UNINSTALL (Section 4)
+;------------------------------------
+
+Section Uninstall
+
+	!insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
+
+	!include "${path_settings}\files_main_uninstall.nsh"
+
+	DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+
+	; Unregister from Windows Vista Game Explorer
+	; (removed due to incompatibility with Windows 7)
+
+SectionEnd
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Section Descriptions
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+
+	!insertmacro MUI_DESCRIPTION_TEXT ${Section1} $(DESC_Section1)
+	!insertmacro MUI_DESCRIPTION_TEXT ${Section2} $(DESC_Section2)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1} $(DESC_Section2_sub1)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2} $(DESC_Section2_sub2)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub3} $(DESC_Section2_sub3)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub4} $(DESC_Section2_sub4)
+;	!insertmacro MUI_DESCRIPTION_TEXT ${Section3} $(DESC_Section3) THEMES
+
+	!insertmacro MUI_DESCRIPTION_TEXT ${g2Section1} $(DESC_g2Section1)
+	!insertmacro MUI_DESCRIPTION_TEXT ${g2Section2} $(DESC_g2Section2)
+	!insertmacro MUI_DESCRIPTION_TEXT ${g2Section3} $(DESC_g2Section3)
+	!insertmacro MUI_DESCRIPTION_TEXT ${g2Section4} $(DESC_g2Section4)
+	!insertmacro MUI_DESCRIPTION_TEXT ${g2Section5} $(DESC_g2Section5)
+	!insertmacro MUI_DESCRIPTION_TEXT ${g2Section6} $(DESC_g2Section6)
+
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section1} $(DESC_s2_sub1_Section1)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section2} $(DESC_s2_sub1_Section2)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section3} $(DESC_s2_sub1_Section3)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section4} $(DESC_s2_sub1_Section4)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section5} $(DESC_s2_sub1_Section5)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section6} $(DESC_s2_sub1_Section6)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section7} $(DESC_s2_sub1_Section7)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section8} $(DESC_s2_sub1_Section8)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section9} $(DESC_s2_sub1_Section9)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section10} $(DESC_s2_sub1_Section10)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section11} $(DESC_s2_sub1_Section11)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section12} $(DESC_s2_sub1_Section12)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section13} $(DESC_s2_sub1_Section13)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section14} $(DESC_s2_sub1_Section14)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section15} $(DESC_s2_sub1_Section15)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section16} $(DESC_s2_sub1_Section16)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section17} $(DESC_s2_sub1_Section17)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section18} $(DESC_s2_sub1_Section18)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section19} $(DESC_s2_sub1_Section19)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section20} $(DESC_s2_sub1_Section20)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section21} $(DESC_s2_sub1_Section21)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section22} $(DESC_s2_sub1_Section22)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section23} $(DESC_s2_sub1_Section23)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub1_Section24} $(DESC_s2_sub1_Section24)
+
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2_Section1} $(DESC_s2_sub2_Section1)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2_Section2} $(DESC_s2_sub2_Section2)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2_Section3} $(DESC_s2_sub2_Section3)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2_Section4} $(DESC_s2_sub2_Section4)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2_Section5} $(DESC_s2_sub2_Section5)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2_Section6} $(DESC_s2_sub2_Section6)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2_Section7} $(DESC_s2_sub2_Section7)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2_Section8} $(DESC_s2_sub2_Section8)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub2_Section9} $(DESC_s2_sub2_Section9)
+
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub3_Section1} $(DESC_s2_sub3_Section1)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub3_Section2} $(DESC_s2_sub3_Section2)
+	!insertmacro MUI_DESCRIPTION_TEXT ${s2_sub3_Section3} $(DESC_s2_sub3_Section3)
+
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Language Support
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+!insertmacro MUI_LANGUAGE "English"
+!insertmacro MUI_LANGUAGE "German"
+!insertmacro MUI_LANGUAGE "Hungarian"
+!insertmacro MUI_LANGUAGE "Polish"
+
+!insertmacro MUI_RESERVEFILE_LANGDLL
+
+!include "${path_languages}\*.nsh"
+
+;!addPluginDir "${path_plugins}\"
+ 
+Function bgmusic
+	File /oname=$PLUGINSDIR\loop.wav .\dependencies\loop.wav
+	BGImage::Sound /NOUNLOAD /LOOP $PLUGINSDIR\loop.wav
+FunctionEnd
+
+Function .onGUIEnd
+	BGImage::Sound /STOP
+FunctionEnd
+
+Function .onInit
+
+	${UAC.I.Elevate.AdminOnly}
+
+	var /GLOBAL version
+	StrCpy $version "1.1"
+
+
+	System::Call 'kernel32::CreateMutexA(i 0, i 0, t "USdx Installer.exe") ?e'
+
+	Pop $R0
+
+	StrCmp $R0 0 +3
+	MessageBox MB_OK|MB_ICONEXCLAMATION $(oninit_running)
+	Abort
+
+	ReadRegStr $R0  HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${name}" 'DisplayVersion'
+
+	${If} $R0 == $version
+		MessageBox MB_YESNO|MB_ICONEXCLAMATION \
+			"${name} v.$R0 $(oninit_alreadyinstalled). $\n$\n $(oninit_installagain)" \
+			IDYES continue
+		Abort
+	${EndIf}
+
+	ReadRegStr $R1 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${name}" 'UninstallString'
+	StrCmp $R1 "" done
+  
+
+	${If} $R0 != $version
+		MessageBox MB_YESNO|MB_ICONEXCLAMATION \
+			"${name} v.$R0 $(oninit_alreadyinstalled). $\n$\n $(oninit_updateusdx) v.$R0 -> v.${version}" \
+			IDYES continue
+			Abort
+	${EndIf}
+
+
+continue:
+	ReadRegStr $R2 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${name}" 'UninstallString'
+	MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(oninit_uninstall)" IDNO done
+	ExecWait '"$R2" _?=$INSTDIR'
+
+done:
+	!insertmacro MUI_LANGDLL_DISPLAY
+
+	!insertmacro INSTALLOPTIONS_EXTRACT_AS ".\settings\settings-1031.ini" "Settings-1031"
+	!insertmacro INSTALLOPTIONS_EXTRACT_AS ".\settings\settings-1033.ini" "Settings-1033"
+	!insertmacro INSTALLOPTIONS_EXTRACT_AS ".\settings\settings-1038.ini" "Settings-1038"
+	!insertmacro INSTALLOPTIONS_EXTRACT_AS ".\settings\settings-1045.ini" "Settings-1045"
+
+FunctionEnd
+
+Function un.onInit
+
+	${nsProcess::FindProcess} "USdx.exe" $R0
+	StrCmp $R0 0 0 +2
+	MessageBox MB_YESNO|MB_ICONEXCLAMATION '$(oninit_closeusdx)' IDYES closeit IDNO end
+
+closeit:
+	${nsProcess::KillProcess} "USdx.exe" $R0
+	goto continue
+
+	${nsProcess::FindProcess} "ultrastardx.exe" $R0
+	StrCmp $R0 0 0 +2
+	MessageBox MB_YESNO|MB_ICONEXCLAMATION '$(oninit_closeusdx)' IDYES closeusdx IDNO end
+
+closeusdx:
+	${nsProcess::KillProcess} "ultrastardx.exe" $R0
+	goto continue
+
+end:
+	${nsProcess::Unload}
+	Abort
+
+continue:
+	!insertmacro MUI_LANGDLL_DISPLAY
+
+FunctionEnd
+
+Function .onInstFailed
+	${UAC.Unload}
+FunctionEnd
+ 
+Function .onInstSuccess
+	${UAC.Unload}
+FunctionEnd
diff --git a/songmanagement/installer/Update.nsi b/songmanagement/installer/Update.nsi
new file mode 100644
index 00000000..e916d3e9
--- /dev/null
+++ b/songmanagement/installer/Update.nsi
@@ -0,0 +1,215 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Installer: Update
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+!include MUI2.nsh
+!include WinVer.nsh
+!include LogicLib.nsh
+!include nsDialogs.nsh
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Variables
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+; Installer Paths:
+
+!define path_settings ".\settings"
+!define path_languages ".\languages"
+!define path_images "..\installerdependencies\images"
+!define path_plugins "..\installerdependencies\plugins"
+!define path_gdf "$WINDIR\gdf.dll"
+
+!addPluginDir "${path_plugins}\"
+
+!include "${path_settings}\variables.nsh"
+!include "${path_settings}\GameExplorer.nsh"
+!include "${path_settings}\functions.nsh"
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Export Settings
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+SetCompress Auto
+SetCompressor /SOLID lzma
+SetCompressorDictSize 32
+SetDatablockOptimize On
+
+Var /GLOBAL CHECKBOX
+Var /GLOBAL label_update_information
+Var /GLOBAL checkbox_state
+
+XPStyle on
+
+Name "${name} - Update"
+Brandingtext "${name} Update"
+OutFile "ultrastardx-update.exe"
+
+InstallDir "$PROGRAMFILES\${name}"
+
+; Windows Vista / Windows 7:
+
+RequestExecutionLevel admin
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Interface Settings
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+; Icons:
+
+!define MUI_ICON "${path_images}\${img_install}"
+!define MUI_UNICON "${path_images}\${img_uninstall}"
+
+; Header and Side Images:
+
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_BITMAP "${path_images}\${img_header}"
+!define MUI_HEADERIMAGE_UNBITMAP "${path_images}\${img_header}"
+
+!define MUI_WELCOMEFINISHPAGE_BITMAP "${path_images}\${img_side}"
+!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${path_images}\${img_side}"
+
+; Abort Warnings:
+
+!define MUI_ABORTWARNING
+!define MUI_ABORTWARNING_TEXT "$(abort_install)"
+!define MUI_ABORTWARNING_CANCEL_DEFAULT
+
+!define MUI_UNABORTWARNING
+!define MUI_UNABORTWARNING_TEXT "$(abort_uninstall)"
+!define MUI_UNABORTWARNING_CANCEL_DEFAULT
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Pages Installation Routine Settings
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+; Welcome Page:
+
+!define MUI_WELCOMEPAGE_TITLE_3LINES
+!define MUI_WELCOMEPAGE_TITLE "$(page_welcome_title_update)"
+!define MUI_WELCOMEPAGE_TEXT "$(page_welcome_txt_update)"
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Pages Installation Routine
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+!insertmacro MUI_PAGE_WELCOME
+
+; USDX Update Page
+
+Page custom Update Download
+
+Function Update
+
+nsDialogs::Create /NOUNLOAD 1018
+
+	Pop $0
+	
+	${NSD_CreateCheckbox} 0 -150 100% 8u "$(update_connect)"
+	Pop $CHECKBOX
+	GetFunctionAddress $0 OnCheckbox
+	nsDialogs::OnClick /NOUNLOAD $CHECKBOX $0
+
+	${NSD_CreateLabel} 0 0 100% 30u "$(update_information)"
+	Pop $label_update_information
+
+nsDialogs::Show
+
+
+FunctionEnd ; Update page End
+
+Function Download
+
+${NSD_GetState} $CHECKBOX $checkbox_state
+
+${If} $checkbox_state == "1"
+
+NSISdl::download /TIMEOUT=50000 http://ultrastardeluxe.xtremeweb-hosting.net/version.txt $TEMP\version.txt
+
+Push 1
+Push "$TEMP\version.txt"
+ Call ReadFileLine
+Pop $1
+
+ReadRegStr $R0  HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${name}" 'DisplayVersion'
+
+${VersionCompare} "$R0" "$1" $R1
+
+${If} $R1 == "0"
+
+messageBox MB_OK|MB_ICONINFORMATION "$(update_check_equal)"
+
+${Else}
+	${If} $R1 == "1"
+
+        IfFileExists $TEMP\version.txt FileExists
+           SetErrors
+           Goto Failed
+
+        FileExists:
+	messageBox MB_OK|MB_ICONINFORMATION "$(update_check_newer)"
+
+	${Else}
+
+		${If} $R1 == "2"
+		messageBox MB_YESNO|MB_ICONQUESTION \
+ 		"$(update_check_older)" IDNO +6
+
+		Push 2
+		Push "$TEMP\version.txt"
+ 		Call ReadFileLine
+		Pop $2
+
+		ExecShell Open $2
+
+		${Else}
+
+		Failed:
+		messageBox MB_YESNO|MB_ICONQUESTION \
+ 		"$(update_check_failed)" IDNO +2
+
+		ExecShell Open http://www.ultrastardeluxe.org
+
+		${EndIf}
+	${EndIf}
+${EndIf}
+${Else}
+
+; If checkbox_state = 0
+
+
+${EndIf}
+
+Delete "$TEMP\version.txt"
+
+
+FunctionEnd
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UPDATE (Section 1)
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+Section $(name_section1) Section1
+	SectionIn RO
+	SetOutPath $INSTDIR
+	SetOverwrite try
+
+SectionEnd
+
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Language Support
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+!insertmacro MUI_LANGUAGE "English"
+!insertmacro MUI_LANGUAGE "German"
+
+!insertmacro MUI_RESERVEFILE_LANGDLL
+
+!include "${path_languages}\*.nsh"
+
+Function .onInit
+
+  !insertmacro MUI_LANGDLL_DISPLAY
+
+
+
+FunctionEnd
diff --git a/songmanagement/installer/dependencies/dll/put game dlls here b/songmanagement/installer/dependencies/dll/put game dlls here
new file mode 100644
index 00000000..e69de29b
diff --git a/songmanagement/installer/dependencies/documents/documentation.pdf b/songmanagement/installer/dependencies/documents/documentation.pdf
new file mode 100644
index 00000000..ae99a860
Binary files /dev/null and b/songmanagement/installer/dependencies/documents/documentation.pdf differ
diff --git a/songmanagement/installer/dependencies/documents/license.txt b/songmanagement/installer/dependencies/documents/license.txt
new file mode 100644
index 00000000..66f35b98
--- /dev/null
+++ b/songmanagement/installer/dependencies/documents/license.txt
@@ -0,0 +1,125 @@
+The GNU General Public License (GPL)
+Version 2, June 1991
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
+
+one line to give the program's name and a brief idea of what it does.
+Copyright (C) 
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You 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
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
+
+Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
+
+Yoyodyne, Inc., hereby disclaims all copyright interest 
+in the program `Gnomovision' (which makes passes at compilers)
+written by James Hacker.
+
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.
diff --git a/songmanagement/installer/dependencies/images/header.bmp b/songmanagement/installer/dependencies/images/header.bmp
new file mode 100644
index 00000000..058eafd3
Binary files /dev/null and b/songmanagement/installer/dependencies/images/header.bmp differ
diff --git a/songmanagement/installer/dependencies/images/side.bmp b/songmanagement/installer/dependencies/images/side.bmp
new file mode 100644
index 00000000..3883fa09
Binary files /dev/null and b/songmanagement/installer/dependencies/images/side.bmp differ
diff --git a/songmanagement/installer/dependencies/loop.wav b/songmanagement/installer/dependencies/loop.wav
new file mode 100644
index 00000000..8a252921
Binary files /dev/null and b/songmanagement/installer/dependencies/loop.wav differ
diff --git a/songmanagement/installer/dependencies/plugins/NSISdl.dll b/songmanagement/installer/dependencies/plugins/NSISdl.dll
new file mode 100644
index 00000000..a3675054
Binary files /dev/null and b/songmanagement/installer/dependencies/plugins/NSISdl.dll differ
diff --git a/songmanagement/installer/dependencies/plugins/UAC.dll b/songmanagement/installer/dependencies/plugins/UAC.dll
new file mode 100644
index 00000000..edf21305
Binary files /dev/null and b/songmanagement/installer/dependencies/plugins/UAC.dll differ
diff --git a/songmanagement/installer/dependencies/plugins/ZipDLL.dll b/songmanagement/installer/dependencies/plugins/ZipDLL.dll
new file mode 100644
index 00000000..5925d591
Binary files /dev/null and b/songmanagement/installer/dependencies/plugins/ZipDLL.dll differ
diff --git a/songmanagement/installer/dependencies/plugins/nsProcess.dll b/songmanagement/installer/dependencies/plugins/nsProcess.dll
new file mode 100644
index 00000000..064097a3
Binary files /dev/null and b/songmanagement/installer/dependencies/plugins/nsProcess.dll differ
diff --git a/songmanagement/installer/install.ico b/songmanagement/installer/install.ico
new file mode 100644
index 00000000..fc1d0797
Binary files /dev/null and b/songmanagement/installer/install.ico differ
diff --git a/songmanagement/installer/languages/English.nsh b/songmanagement/installer/languages/English.nsh
new file mode 100644
index 00000000..a3325d5b
--- /dev/null
+++ b/songmanagement/installer/languages/English.nsh
@@ -0,0 +1,131 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Installer - Language file: English
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+LangString abort_install ${LANG_ENGLISH} "Are you sure to abort Installation?"
+LangString abort_uninstall ${LANG_ENGLISH} "Are you sure to abort UnInstallation?"
+LangString oninit_running ${LANG_ENGLISH} "The installer is already running."
+LangString oninit_installagain ${LANG_ENGLISH} "Are you sure you want to install it again?"
+LangString oninit_alreadyinstalled ${LANG_ENGLISH} "is already installed"
+LangString oninit_closeusdx ${LANG_ENGLISH} "cannot be uninstalled while its running! Do you want to close it?"
+LangString oninit_updateusdx ${LANG_ENGLISH} "Do you want to update the installation from:"
+LangString oninit_uninstall ${LANG_ENGLISH} "Do you want to uninstall the old version? (recommended)"
+
+LangString update_connect ${LANG_ENGLISH} "Establish internet connection and check for new version"
+LangString button_next ${LANG_ENGLISH} "Next >"
+LangString button_close ${LANG_ENGLISH} "Close"
+LangString update_information ${LANG_ENGLISH} "You can check if a new version of 'UltraStar Deluxe' is available. Thereto an internet connection will be established. If a new version is found, it can be installed afterwards."
+
+LangString delete_components ${LANG_ENGLISH} "Also delete the following components:"
+LangString delete_covers ${LANG_ENGLISH} "Cover?"
+LangString delete_highscores ${LANG_ENGLISH} "Highscores?"
+LangString delete_config ${LANG_ENGLISH} "Config?"
+LangString delete_screenshots ${LANG_ENGLISH} "Screenshots?"
+LangString delete_playlists ${LANG_ENGLISH} "Playlists?"
+LangString delete_songs ${LANG_ENGLISH} "Remove songs? WARNING: ALL files within the InstallationDir\songs folder will be removed(!)"
+
+LangString update_check_older ${LANG_ENGLISH} "Your version $R0 is outdated. The new version $1 of UltraStar Deluxe is available. Do you want to update?"
+LangString update_check_equal ${LANG_ENGLISH} "Your currently installed version $R0 is up-to-date. No update needed."
+LangString update_check_newer ${LANG_ENGLISH} "Your installed version $R0 is newer than the $\n$\rcurrent release version $1 of UltraStar Deluxe. No update needed."
+LangString update_check_failed ${LANG_ENGLISH} "The check for a new version failed. Do you want to visit website to check manually ?"
+
+; Welcome Page:
+
+LangString page_welcome_title_update ${LANG_ENGLISH} "Welcome to the UltraStar Deluxe Update Wizard"
+LangString page_welcome_txt_update ${LANG_ENGLISH} "This wizard will guide you through the Update process of UltraStar Deluxe. UltraStar Deluxe is a free open source Karaoke game, which can be compared with Singstar.$\n$\r$\n$\rThe UltraStar Deluxe Team wishes you fun.$\n$\rProject website: http://www.ultrastardeluxe.org$\n$\rSupport Forum: http://forum.ultrastardeluxe.org"
+LangString page_welcome_title ${LANG_ENGLISH} "Welcome to the UltraStar Deluxe Setup Wizard"
+LangString page_welcome_txt ${LANG_ENGLISH} "This wizard will guide you through the Installation of UltraStar Deluxe. UltraStar Deluxe is a free open source Karaoke game, which can be compared with Singstar.$\n$\r$\n$\rThe UltraStar Deluxe Team wishes you fun.$\n$\rProject website: http://www.ultrastardeluxe.org$\n$\rSupport Forum: http://forum.ultrastardeluxe.org"
+LangString page_un_welcome_title ${LANG_ENGLISH} "Welcome to the UltraStar Deluxe uninstall wizard"
+
+; Components Page:
+
+LangString page_components_info ${LANG_ENGLISH} "Hover the component to get details"
+
+; Custom Page
+
+LangString page_settings_fullscreen ${LANG_ENGLISH} "Fullscreen Mode"
+LangString page_settings_subtitle ${LANG_ENGLISH} "Specify your favorite settings for UltraStar Deluxe."
+
+; Finish Page:
+
+LangString page_finish_txt ${LANG_ENGLISH} "UltraStar Deluxe was installed successfully on you system.$\n$\r$\n$\rVisit out project website to get latest news and updates."
+LangString page_finish_linktxt ${LANG_ENGLISH} "Project website"
+LangString page_finish_desktop ${LANG_ENGLISH} "Create Desktop Shortcut?"
+
+; Start Menu and Shortcuts
+
+LangString sm_shortcut ${LANG_ENGLISH} "Play UltraStar Deluxe"
+LangString sm_uninstall ${LANG_ENGLISH} "Uninstall"
+LangString sm_website ${LANG_ENGLISH} "Website"
+LangString sm_license ${LANG_ENGLISH} "License"
+LangString sm_readme ${LANG_ENGLISH} "Readme"
+LangString sm_songs ${LANG_ENGLISH} "Songs"
+LangString sm_documentation ${LANG_ENGLISH} "Documentation"
+
+LangString sc_play ${LANG_ENGLISH} "Play"
+LangString sc_desktop ${LANG_ENGLISH} "Create Desktop Shortcut?"
+
+; Sections and SectionGroups
+
+LangString name_section1 ${LANG_ENGLISH} "Main components"
+LangString name_section2 ${LANG_ENGLISH} "Songs"
+LangString name_s2_sub1 ${LANG_ENGLISH} "Jonathan Coulton"
+LangString name_s2_sub2 ${LANG_ENGLISH} "Shearer"
+LangString name_s2_sub3 ${LANG_ENGLISH} "Wise Guys"
+LangString name_s2_sub4 ${LANG_ENGLISH} "Pornophonique"
+
+LangString DESC_Section1 ${LANG_ENGLISH} "These are the basic files needed by UltraStar Deluxe"
+LangString DESC_Section2 ${LANG_ENGLISH} "You can choose which songs should be downloaded (Requires Internet Connection!)"
+LangString DESC_Section2_sub1 ${LANG_ENGLISH} "You can choose which Jonathan Coulton songs (CC by-nc 3.0) should be installed."
+LangString DESC_Section2_sub2 ${LANG_ENGLISH} "You can choose which Shearer songs (CC by-nc-sa 2.0 / 3.0) should be installed."
+LangString DESC_Section2_sub3 ${LANG_ENGLISH} "You can choose which Wise Guys songs should be installed."
+LangString DESC_Section2_sub4 ${LANG_ENGLISH} "You can choose which Pornophonique songs should be installed."
+
+LangString DESC_g2Section2 ${LANG_ENGLISH} "Download the song 'Dead Smiling Pirates - I 18' (CC by-nc-nd 2.5)."
+LangString DESC_g2Section3 ${LANG_ENGLISH} "Download the song 'Joshua Morin - On The Run' (CC by-sa 2.5)."
+LangString DESC_g2Section4 ${LANG_ENGLISH} "Download the song 'Pornophonique - Space Invaders' (CC by-nc-nd 2.0)."
+LangString DESC_g2Section5 ${LANG_ENGLISH} "Download the song 'Steven Dunston - Northern Star' (CC by-nc-sa 2.5)."
+LangString DESC_g2Section1 ${LANG_ENGLISH} "Download the song 'Bodo Wartke - Liebeslied (Love Song)'."
+LangString DESC_g2Section6 ${LANG_ENGLISH} "Download the song 'Pornophonique - Space Invaders (Karaoke)' (CC by-nc-nd 2.0)."
+
+LangString DESC_s2_sub1_Section1 ${LANG_ENGLISH} "Download the song 'Monkey Shines'."
+LangString DESC_s2_sub1_Section2 ${LANG_ENGLISH} "Download the song 'I Crush Everything'."
+LangString DESC_s2_sub1_Section3 ${LANG_ENGLISH} "Download the song 'Not About You'."
+LangString DESC_s2_sub1_Section4 ${LANG_ENGLISH} "Download the song 'Mr. Fancy Pants'."
+LangString DESC_s2_sub1_Section5 ${LANG_ENGLISH} "Download the song 'Big Bad World One'."
+LangString DESC_s2_sub1_Section6 ${LANG_ENGLISH} "Download the song 'Flickr [incl. video]'."
+LangString DESC_s2_sub1_Section7 ${LANG_ENGLISH} "Download the song 'My Beige Bear'."
+LangString DESC_s2_sub1_Section8 ${LANG_ENGLISH} "Download the song 'The Future Soon'."
+LangString DESC_s2_sub1_Section9 ${LANG_ENGLISH} "Download the song 'Ikea'."
+LangString DESC_s2_sub1_Section10 ${LANG_ENGLISH} "Download the song 'Furry Old Lobster'."
+LangString DESC_s2_sub1_Section11 ${LANG_ENGLISH} "Download the song 'Code Monkey [incl. video]'."
+LangString DESC_s2_sub1_Section12 ${LANG_ENGLISH} "Download the song 'I�m Your Moon'."
+LangString DESC_s2_sub1_Section13 ${LANG_ENGLISH} "Download the song 'First Of May'."
+LangString DESC_s2_sub1_Section14 ${LANG_ENGLISH} "Download the song 'Dance, Soterios Johnson, Dance'."
+LangString DESC_s2_sub1_Section15 ${LANG_ENGLISH} "Download the song 'A Talk With George'."
+LangString DESC_s2_sub1_Section16 ${LANG_ENGLISH} "Download the song 'Creepy Doll [incl. video]'."
+LangString DESC_s2_sub1_Section17 ${LANG_ENGLISH} "Download the song 'That Spells DNA'."
+LangString DESC_s2_sub1_Section18 ${LANG_ENGLISH} "Download the song 'When You Go'."
+LangString DESC_s2_sub1_Section19 ${LANG_ENGLISH} "Download the song 'Better'."
+LangString DESC_s2_sub1_Section20 ${LANG_ENGLISH} "Download the song 'Shop Vac'."
+LangString DESC_s2_sub1_Section21 ${LANG_ENGLISH} "Download the song 'I Feel Fantastic'."
+LangString DESC_s2_sub1_Section22 ${LANG_ENGLISH} "Download the song 'Re: Your Brains'."
+LangString DESC_s2_sub1_Section23 ${LANG_ENGLISH} "Download the song 'Skullcrusher Mountain'."
+LangString DESC_s2_sub1_Section24 ${LANG_ENGLISH} "Download the song 'Chiron Beta Prime [incl. video]'."
+
+LangString DESC_s2_sub2_Section1 ${LANG_ENGLISH} "Download the song '69'."
+LangString DESC_s2_sub2_Section2 ${LANG_ENGLISH} "Download the song '69 (Karaoke)'."
+LangString DESC_s2_sub2_Section3 ${LANG_ENGLISH} "Download the song 'Can't stop it'."
+LangString DESC_s2_sub2_Section4 ${LANG_ENGLISH} "Download the song 'Can't stop it (Karaoke)'."
+LangString DESC_s2_sub2_Section5 ${LANG_ENGLISH} "Download the song 'In My Hand'."
+LangString DESC_s2_sub2_Section6 ${LANG_ENGLISH} "Download the song 'Man Song'."
+LangString DESC_s2_sub2_Section7 ${LANG_ENGLISH} "Download the song 'Man Song (Karaoke)'."
+LangString DESC_s2_sub2_Section8 ${LANG_ENGLISH} "Download the song 'Stay with me'."
+LangString DESC_s2_sub2_Section9 ${LANG_ENGLISH} "Download the song 'Stay with me (Karaoke)'."
+
+LangString DESC_s2_sub3_Section1 ${LANG_ENGLISH} "Download the song 'Lebendig und kr�ftig und sch�rfer'."
+LangString DESC_s2_sub3_Section2 ${LANG_ENGLISH} "Download the song 'Mensch, wo bist du?'."
+LangString DESC_s2_sub3_Section3 ${LANG_ENGLISH} "Download the song 'Mensch, wo bist du? (Karaoke)'."
+
+; Optional Themes
+; (not available)
\ No newline at end of file
diff --git a/songmanagement/installer/languages/German.nsh b/songmanagement/installer/languages/German.nsh
new file mode 100644
index 00000000..56507ec5
--- /dev/null
+++ b/songmanagement/installer/languages/German.nsh
@@ -0,0 +1,130 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Installer - Language file: German
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+LangString abort_install ${LANG_GERMAN} "Willst du die Installation wirklich abbrechen?"
+LangString abort_uninstall ${LANG_GERMAN} "Willst du die Deinstallation wirklich abbrechen?"
+LangString oninit_running ${LANG_GERMAN} "Die Installation wird bereits ausgef�hrt."
+LangString oninit_installagain ${LANG_GERMAN} "Bist du sicher, dass du es erneut installieren m�chtest?"
+LangString oninit_alreadyinstalled ${LANG_GERMAN} "ist bereits installiert"
+LangString oninit_closeusdx ${LANG_GERMAN} "kann nicht w�hrend der Laufzeit deinstalliert werden. Soll es geschlossen werden?"
+LangString oninit_updateusdx ${LANG_GERMAN} "M�chtest du das Programm aktualisieren von"
+LangString oninit_uninstall ${LANG_GERMAN} "M�chtest du die alte Version entfernen? (empfohlen)"
+
+LangString update_connect ${LANG_GERMAN} "Mit dem Internet verbinden und nach aktueller Version suchen"
+LangString button_next ${LANG_GERMAN} "Weiter >"
+LangString button_close ${LANG_GERMAN} "Beenden"
+LangString update_information ${LANG_GERMAN} "Du kannst nach einer aktuelleren Version von 'UltraStar Deluxe' suchen. Dazu wird eine Verbindung mit dem Internet hergestellt. Wurde eine aktuellere Version gefunden, kann diese anschlie�end installiert werden."
+
+LangString delete_components ${LANG_GERMAN} "Folgende Komponenten ebenfalls entfernen:"
+LangString delete_covers ${LANG_GERMAN} "Cover?"
+LangString delete_highscores ${LANG_GERMAN} "Statistiken?"
+LangString delete_config ${LANG_GERMAN} "Konfiguration?"
+LangString delete_screenshots ${LANG_GERMAN} "Screenshots?"
+LangString delete_playlists ${LANG_GERMAN} "Playlisten?"
+LangString delete_songs ${LANG_GERMAN} "Lieder l�schen? WARNUNG: ALLE Dateien im Unterordner 'songs' des Installationsverzeichnisses werden gel�scht(!)"
+
+LangString update_check_older ${LANG_GERMAN} "Deine aktuelle Version $R0 ist veraltet. Die neue Version $1 von UltraStar Deluxe ist verf�gbar. M�chtest du sie runterladen?"
+LangString update_check_equal ${LANG_GERMAN} "Deine aktuelle Version $R0 ist auf dem neusten Stand.$\n$\rKein Update ben�tigt."
+LangString update_check_newer ${LANG_GERMAN} "Deine aktuelle Version $R0 ist neuer als die zurzeit ver�ffentlichte$\n$\rVersion $1 von UltraStar Deluxe. Kein Update ben�tigt."
+LangString update_check_failed ${LANG_GERMAN} "Die Aktualisierungspr�fung ist fehlgeschlagen. Willst du manuell nach Updates suchen?"
+
+; Welcome Page:
+
+LangString page_welcome_title_update ${LANG_GERMAN} "Willkommen beim Aktualisierungsassistenten von UltraStar Deluxe" 
+LangString page_welcome_txt_update ${LANG_GERMAN} "Dieser Assistent wird dich durch die Aktualisierung von UltraStar Deluxe begleiten. UltraStar Deluxe ist ein kostenloses quelloffenes Karaokespiel, welches Singstar �hnelt. $\n$\r$\n$\rDas UltraStar Deluxe Team w�nscht viel Spa�.$\n$\rProjekthomepage: http://www.ultrastardeluxe.org$\n$\rSupport Forum: http://forum.ultrastardeluxe.org"
+
+LangString page_welcome_title ${LANG_GERMAN} "Willkommen zur Installationsroutine von UltraStar Deluxe"
+LangString page_welcome_txt ${LANG_GERMAN} "Dieser Assistent wird dich durch die Installation von UltraStar Deluxe begleiten. UltraStar Deluxe ist ein kostenloses quelloffenes Karaokespiel, welches Singstar �hnelt. $\n$\r$\n$\rDas UltraStar Deluxe Team w�nscht viel Spa�.$\n$\rProjekthomepage: http://www.ultrastardeluxe.org$\n$\rSupport Forum: http://forum.ultrastardeluxe.org"
+
+LangString page_un_welcome_title ${LANG_GERMAN} "Willkommen zur Deinstallation von UltraStar Deluxe"
+
+; Components Page:
+
+LangString page_components_info ${LANG_GERMAN} "Schiebe den Mauszeiger �ber die Komponente um Details einzusehen"
+
+; Custom Page
+
+LangString page_settings_fullscreen ${LANG_GERMAN} "Vollbild Modus:"
+LangString page_settings_subtitle ${LANG_GERMAN} "Lege deine favorisierten Einstellungen f�r UltraStar Deluxe fest."
+
+; Finish Page:
+
+LangString page_finish_txt ${LANG_GERMAN} "UltraStar Deluxe wurde erfolgreich auf Ihrem System installiert.$\n$\r$\n$\rBesuche unsere Projektwebseite um die neusten Updates und News zu erhalten."
+LangString page_finish_linktxt ${LANG_GERMAN} "Projektwebseite"
+LangString page_finish_desktop ${LANG_GERMAN} "Verkn�pfung auf dem Desktop erstellen?"
+
+; Start Menu and Shortcuts
+
+LangString sm_website ${LANG_GERMAN} "Webseite"
+LangString sm_uninstall ${LANG_GERMAN} "Deinstallieren"		  
+LangString sm_shortcut ${LANG_GERMAN} "UltraStar Deluxe spielen"  
+LangString sm_license ${LANG_GERMAN} "Lizenz"
+LangString sm_readme ${LANG_GERMAN} "Lies mich"
+LangString sm_songs ${LANG_GERMAN} "Songs"
+LangString sm_documentation ${LANG_GERMAN} "Dokumentation"
+
+LangString sc_play ${LANG_GERMAN} "Spielen" 
+LangString sc_desktop ${LANG_GERMAN} "Verkn�pfung auf dem Desktop erstellen?" 
+
+; Sections and SectionGroups
+
+LangString name_section1 ${LANG_GERMAN} "Hauptkomponenten"
+LangString name_section2 ${LANG_GERMAN} "Songs"
+LangString name_s2_sub1 ${LANG_GERMAN} "Jonathan Coulton"
+LangString name_s2_sub2 ${LANG_GERMAN} "Shearer"
+LangString name_s2_sub3 ${LANG_GERMAN} "Wise Guys"
+LangString name_s2_sub4 ${LANG_GERMAN} "Pornophonique"
+
+LangString DESC_Section1 ${LANG_GERMAN} "Dies sind die von UltraStar Deluxe ben�tigten Grunddateien"
+LangString DESC_Section2 ${LANG_GERMAN} "Hier k�nnen Songs zum Herunterladen gew�hlt werden. (Ben�tigt aktive Internetverbindung!)"
+LangString DESC_Section2_sub1 ${LANG_GERMAN} "Hier k�nnen Jonathan Coulton Songs (CC by-nc 3.0) zum Herunterladen gew�hlt werden."
+LangString DESC_Section2_sub2 ${LANG_GERMAN} "Hier k�nnen Shearer Songs (CC by-nc-sa 2.0 / 3.0) zum Herunterladen gew�hlt werden."
+LangString DESC_Section2_sub3 ${LANG_GERMAN} "Hier k�nnen Wise Guys Songs zum Herunterladen gew�hlt werden."
+LangString DESC_Section2_sub4 ${LANG_GERMAN} "Hier k�nnen Pornophonique Songs zum Herunterladen gew�hlt werden."
+
+LangString DESC_g2Section2 ${LANG_GERMAN} "L�dt das Lied 'Dead Smiling Pirates - I 18' (CC by-nc-nd 2.5) herunter."
+LangString DESC_g2Section3 ${LANG_GERMAN} "L�dt das Lied 'Joshua Morin - On The Run' (CC by-sa 2.5) herunter."
+LangString DESC_g2Section4 ${LANG_GERMAN} "L�dt das Lied 'Pornophonique - Space Invaders' (CC by-nc-nd 2.0) herunter."
+LangString DESC_g2Section5 ${LANG_GERMAN} "L�dt das Lied 'Steven Dunston - Northern Star' (CC by-nc-sa 2.5) herunter."
+LangString DESC_g2Section1 ${LANG_GERMAN} "L�dt das Lied 'Bodo Wartke - Liebeslied (Love Song)' herunter."
+LangString DESC_g2Section6 ${LANG_GERMAN} "L�dt das Lied 'Pornophonique - Space Invaders (Karaoke)' (CC by-nc-nd 2.0) herunter."
+
+LangString DESC_s2_sub1_Section1 ${LANG_GERMAN} "L�dt das Lied 'Monkey Shines' herunter."
+LangString DESC_s2_sub1_Section2 ${LANG_GERMAN} "L�dt das Lied 'I Crush Everything' herunter."
+LangString DESC_s2_sub1_Section3 ${LANG_GERMAN} "L�dt das Lied 'Not About You' herunter."
+LangString DESC_s2_sub1_Section4 ${LANG_GERMAN} "L�dt das Lied 'Mr. Fancy Pants' herunter."
+LangString DESC_s2_sub1_Section5 ${LANG_GERMAN} "L�dt das Lied 'Big Bad World One' herunter."
+LangString DESC_s2_sub1_Section6 ${LANG_GERMAN} "L�dt das Lied 'Flickr [inkl. Video]' herunter."
+LangString DESC_s2_sub1_Section7 ${LANG_GERMAN} "L�dt das Lied 'My Beige Bear' herunter."
+LangString DESC_s2_sub1_Section8 ${LANG_GERMAN} "L�dt das Lied 'The Future Soon' herunter."
+LangString DESC_s2_sub1_Section9 ${LANG_GERMAN} "L�dt das Lied 'Ikea' herunter."
+LangString DESC_s2_sub1_Section10 ${LANG_GERMAN} "L�dt das Lied 'Furry Old Lobster' herunter."
+LangString DESC_s2_sub1_Section11 ${LANG_GERMAN} "L�dt das Lied 'Code Monkey [inkl. Video]' herunter."
+LangString DESC_s2_sub1_Section12 ${LANG_GERMAN} "L�dt das Lied 'I�m Your Moon' herunter."
+LangString DESC_s2_sub1_Section13 ${LANG_GERMAN} "L�dt das Lied 'First Of May' herunter."
+LangString DESC_s2_sub1_Section14 ${LANG_GERMAN} "L�dt das Lied 'Dance, Soterios Johnson, Dance' herunter."
+LangString DESC_s2_sub1_Section15 ${LANG_GERMAN} "L�dt das Lied 'A Talk With George' herunter."
+LangString DESC_s2_sub1_Section16 ${LANG_GERMAN} "L�dt das Lied 'Creepy Doll [inkl. Video]' herunter."
+LangString DESC_s2_sub1_Section17 ${LANG_GERMAN} "L�dt das Lied 'That Spells DNA' herunter."
+LangString DESC_s2_sub1_Section18 ${LANG_GERMAN} "L�dt das Lied 'When You Go' herunter."
+LangString DESC_s2_sub1_Section19 ${LANG_GERMAN} "L�dt das Lied 'Better' herunter."
+LangString DESC_s2_sub1_Section20 ${LANG_GERMAN} "L�dt das Lied 'Shop Vac' herunter."
+LangString DESC_s2_sub1_Section21 ${LANG_GERMAN} "L�dt das Lied 'I Feel Fantastic' herunter."
+LangString DESC_s2_sub1_Section22 ${LANG_GERMAN} "L�dt das Lied 'Re: Your Brains' herunter."
+LangString DESC_s2_sub1_Section23 ${LANG_GERMAN} "L�dt das Lied 'Skullcrusher Mountain' herunter."
+LangString DESC_s2_sub1_Section24 ${LANG_GERMAN} "L�dt das Lied 'Chiron Beta Prime [inkl. Video]' herunter."
+
+LangString DESC_s2_sub2_Section1 ${LANG_GERMAN} "L�dt das Lied '69' herunter."
+LangString DESC_s2_sub2_Section2 ${LANG_GERMAN} "L�dt das Lied '69 (Karaoke)' herunter."
+LangString DESC_s2_sub2_Section3 ${LANG_GERMAN} "L�dt das Lied 'Can't stop it' herunter."
+LangString DESC_s2_sub2_Section4 ${LANG_GERMAN} "L�dt das Lied 'Can't stop it (Karaoke)' herunter."
+LangString DESC_s2_sub2_Section5 ${LANG_GERMAN} "L�dt das Lied 'In My Hand' herunter."
+LangString DESC_s2_sub2_Section6 ${LANG_GERMAN} "L�dt das Lied 'Man Song' herunter."
+LangString DESC_s2_sub2_Section7 ${LANG_GERMAN} "L�dt das Lied 'Man Song (Karaoke)' herunter."
+LangString DESC_s2_sub2_Section8 ${LANG_GERMAN} "L�dt das Lied 'Stay with me' herunter."
+LangString DESC_s2_sub2_Section9 ${LANG_GERMAN} "L�dt das Lied 'Stay with me (Karaoke)' herunter."
+
+LangString DESC_s2_sub3_Section1 ${LANG_GERMAN} "L�dt das Lied 'Lebendig und kr�ftig und sch�rfer' herunter."
+LangString DESC_s2_sub3_Section2 ${LANG_GERMAN} "L�dt das Lied 'Mensch, wo bist du?' herunter."
+LangString DESC_s2_sub3_Section3 ${LANG_GERMAN} "L�dt das Lied 'Mensch, wo bist du? (Karaoke)' herunter."
\ No newline at end of file
diff --git a/songmanagement/installer/languages/Hungarian.nsh b/songmanagement/installer/languages/Hungarian.nsh
new file mode 100644
index 00000000..198251f6
--- /dev/null
+++ b/songmanagement/installer/languages/Hungarian.nsh
@@ -0,0 +1,133 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Installer - Language file: Hungarian
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; Translation by Gergely BOR <borg42+ultrastardx at gmail.com>.
+
+LangString abort_install ${LANG_HUNGARIAN} "Biztosan megszak�tja a telep�t�st?"
+LangString abort_uninstall ${LANG_HUNGARIAN} "Biztosan megszak�tja a program elt�vol�t�s�t?"
+LangString oninit_running ${LANG_HUNGARIAN} "A telep�t�s m�r folyamatban van."
+LangString oninit_installagain ${LANG_HUNGARIAN} "Biztos abban, hogy m�g egyszer telep�teni szeretn�?"
+LangString oninit_alreadyinstalled ${LANG_HUNGARIAN} "m�r telep�tve van"
+LangString oninit_closeusdx ${LANG_HUNGARIAN} "nem elt�vol�that�, ha m�g fut! K�v�nja a program bez�r�s�t?"
+LangString oninit_updateusdx ${LANG_HUNGARIAN} "K�v�nja-e a programot friss�teni err�l a helyr�l:"
+LangString oninit_uninstall ${LANG_HUNGARIAN} "Do you want to uninstall the old version? (recommended)"
+
+LangString update_connect ${LANG_HUNGARIAN} "�j verzi� keres�se az interneten"
+LangString button_next ${LANG_HUNGARIAN} "Tov�bb >"
+LangString button_close ${LANG_HUNGARIAN} "Bez�r�s"
+LangString update_information ${LANG_HUNGARIAN} "Ellen�rizheti, hogy van-e �j 'UltraStar Deluxe'-verzi�. Ehhez internetkapcsolat sz�ks�ges. Ha van �j verzi�, az ezt k�vet�en telep�thet�."
+
+LangString delete_components ${LANG_HUNGARIAN} "Also delete the following components:"
+LangString delete_covers ${LANG_HUNGARIAN} "T�r�lj�k a bor�t�kat?"
+LangString delete_highscores ${LANG_HUNGARIAN} "T�r�lj�k a pontsz�mokat?"
+LangString delete_config ${LANG_HUNGARIAN} "Config?"
+LangString delete_screenshots ${LANG_HUNGARIAN} "Screenshots?"
+LangString delete_playlists ${LANG_HUNGARIAN} "Playlists?"
+LangString delete_songs ${LANG_HUNGARIAN} "T�r�lj�k a dalokat is? WARNING: ALL files within the InstallationDir\songs folder will be removed(!)"
+
+LangString update_check_older ${LANG_HUNGARIAN} "Az �n g�p�n telep�tett verzi�n�l ($R0) van m�r �jabb ($1). K�v�nja friss�teni?"
+LangString update_check_equal ${LANG_HUNGARIAN} "Az �n g�p�n a legfrissebb verzi� ($R0) van telep�tve. Friss�t�s nem sz�ks�ges."
+LangString update_check_newer ${LANG_HUNGARIAN} "Az �n g�p�n telep�tett verzi� ($R0) frissebb, mint a jelenlegi kiad�s ($1). Friss�t�s nem sz�ks�ges."
+LangString update_check_failed ${LANG_HUNGARIAN} "Az ellen�rz�s sikertelen. K�v�nja bet�lteni a program weboldal�t, hogy ellen�rizhesse hogy van-e friss�t�s?"
+
+; Welcome Page:
+
+LangString page_welcome_title_update ${LANG_HUNGARIAN} "�dv�zli �nt az UltraStar Deluxe friss�t�si var�zsl�ja!"
+LangString page_welcome_txt_update ${LANG_HUNGARIAN} "Ez a var�zsl� v�gigvezeti �nt az UltraStar Deluxe friss�t�si folyamat�n. Az UltraStar Deluxe egy ingyenes �s szabad karaokeprogram, olyan mint a Singstar.$\n$\r$\n$\rAz UltraStar Deluxe csapata j� sz�rakoz�st k�v�n!$\n$\rA projekt weboldala: http://www.ultrastardeluxe.org/$\n$\rT�mogat�s a f�rumunkon: http://forum.ultrastardeluxe.org/"
+LangString page_welcome_title ${LANG_HUNGARIAN} "�dv�zli �nt az UltraStar Deluxe telep�t�si var�zsl�ja!"
+LangString page_welcome_txt ${LANG_HUNGARIAN} "Ez a var�zsl� v�gigvezeti �nt az UltraStar Deluxe telep�t�si folyamat�n. Az UltraStar Deluxe egy ingyenes �s szabad karaokeprogram, olyan mint a Singstar.$\n$\r$\n$\rAz UltraStar Deluxe csapata j� sz�rakoz�st k�v�n!$\n$\rA projekt weboldala: http://www.ultrastardeluxe.org/$\n$\rT�mogat�s a f�rumunkon: http://forum.ultrastardeluxe.org/"
+LangString page_un_welcome_title ${LANG_HUNGARIAN} "�dv�zli �nt az UltraStar Deluxe elt�vol�t�si var�zsl�ja!"
+
+; Components Page:
+
+LangString page_components_info ${LANG_HUNGARIAN} "R�szletes inform�ci��rt vigye az egeret a komponens f�l�"
+
+; Custom Page
+
+LangString page_settings_fullscreen ${LANG_HUNGARIAN} "Teljes k�perny�s �zemm�d"
+LangString page_settings_subtitle ${LANG_HUNGARIAN} "Adja meg a kedvenc UltraStar Deluxe-be�ll�t�s�t."
+
+; Finish Page:
+
+LangString page_finish_txt ${LANG_HUNGARIAN} "Az UltraStar Deluxe telep�t�se sikeresen befejez�d�tt.$\n$\r$\n$\rHa k�v�ncsi a legfrissebb h�rekre �s friss�t�sekre, k�rj�k l�togassa meg projekt�nk weboldal�t."
+LangString page_finish_linktxt ${LANG_HUNGARIAN} "A projekt weboldala"
+LangString page_finish_desktop ${LANG_HUNGARIAN} "Tegy�nk egy parancsikont az asztalra?"
+
+; Start Menu and Shortcuts
+
+LangString sm_shortcut ${LANG_HUNGARIAN} "UltraStar Deluxe karaoke"
+LangString sm_uninstall ${LANG_HUNGARIAN} "Elt�vol�t�s"
+LangString sm_website ${LANG_HUNGARIAN} "Weboldal"
+LangString sm_license ${LANG_HUNGARIAN} "Licensz"
+LangString sm_readme ${LANG_HUNGARIAN} "OlvassEl"
+LangString sm_songs ${LANG_HUNGARIAN} "Dalok"
+LangString sm_documentation ${LANG_HUNGARIAN} "Dokument�ci�"
+
+LangString sc_play ${LANG_HUNGARIAN} "J�t�k"
+LangString sc_desktop ${LANG_HUNGARIAN} "Tegy�nk egy parancsikont az asztalra?"
+
+; Sections and SectionGroups
+
+LangString name_section1 ${LANG_HUNGARIAN} "F� komponensek"
+LangString name_section2 ${LANG_HUNGARIAN} "Dalok"
+LangString name_s2_sub1 ${LANG_HUNGARIAN} "Jonathan Coulton"
+LangString name_s2_sub2 ${LANG_HUNGARIAN} "Shearer"
+LangString name_s2_sub3 ${LANG_HUNGARIAN} "Wise Guys"
+LangString name_s2_sub4 ${LANG_HUNGARIAN} "Pornophonique"
+
+LangString DESC_Section1 ${LANG_HUNGARIAN} "Azok a f�jlok, melyek mindenk�ppen sz�ks�gesek az UltraStar Deluxe futtat�s�hoz."
+LangString DESC_Section2 ${LANG_HUNGARIAN} "Kiv�laszthatja, hogy milyen dalok legyenek telep�tve."
+LangString DESC_Section2_sub1 ${LANG_HUNGARIAN} "Kiv�laszthatja, hogy mely Jonathan Coulton-dalok (CC by-nc 3.0) legyenek telep�tve."
+LangString DESC_Section2_sub2 ${LANG_HUNGARIAN} "Kiv�laszthatja, hogy mely Shearer-dalok (CC by-nc-sa 2.0 / 3.0) legyenek telep�tve."
+LangString DESC_Section2_sub3 ${LANG_HUNGARIAN} "Kiv�laszthatja, hogy mely Wise Guys-dalok legyenek telep�tve."
+LangString DESC_Section2_sub4 ${LANG_HUNGARIAN} "Kiv�laszthatja, hogy mely Pornophonique-dalok legyenek telep�tve."
+LangString DESC_Section3 ${LANG_HUNGARIAN} "Kiv�laszthatja, hogy milyen t�m�k legyenek telep�tve. A t�m�k haszn�lat�val a program grafikai megjelen�se v�ltozik meg. A t�m�k telep�t�se nem k�telez�."
+
+LangString DESC_g2Section2 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Dead Smiling Pirates - I 18' (CC by-nc-nd 2.5) c�mu dal."
+LangString DESC_g2Section3 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Joshua Morin - On The Run' (CC by-sa 2.5) c�mu dal."
+LangString DESC_g2Section4 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Pornophonique - Space Invaders' (CC by-nc-nd 2.0) c�mu dal."
+LangString DESC_g2Section5 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Steven Dunston - Northern Star' (CC by-nc-sa 2.5) c�mu dal."
+LangString DESC_g2Section6 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Pornophonique - Space Invaders (Karaoke)' (CC by-nc-nd 2.0) c�mu dal."
+LangString DESC_g2Section1 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Bodo Wartke - Liebeslied (Love Song)' c�mu dal."
+
+LangString DESC_s2_sub1_Section1 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Monkey Shines' c�mu dal."
+LangString DESC_s2_sub1_Section2 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'I Crush Everything' c�mu dal."
+LangString DESC_s2_sub1_Section3 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Not About You'."
+LangString DESC_s2_sub1_Section4 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Mr. Fancy Pants' c�mu dal."
+LangString DESC_s2_sub1_Section5 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Big Bad World One' c�mu dal."
+LangString DESC_s2_sub1_Section6 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Flickr' c�mu dal (vide�val)."
+LangString DESC_s2_sub1_Section7 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'My Beige Bear' c�mu dal."
+LangString DESC_s2_sub1_Section8 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'The Future Soon' c�mu dal."
+LangString DESC_s2_sub1_Section9 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Ikea' c�mu dal."
+LangString DESC_s2_sub1_Section10 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Furry Old Lobster' c�mu dal."
+LangString DESC_s2_sub1_Section11 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Code Monkey' c�mu dal (vide�val)."
+LangString DESC_s2_sub1_Section12 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'I'm Your Moon' c�mu dal."
+LangString DESC_s2_sub1_Section13 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'First Of May' c�mu dal."
+LangString DESC_s2_sub1_Section14 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Dance, Soterios Johnson, Dance' c�mu dal."
+LangString DESC_s2_sub1_Section15 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'A Talk With George' c�mu dal."
+LangString DESC_s2_sub1_Section16 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Creepy Doll' c�mu dal (vide�val)."
+LangString DESC_s2_sub1_Section17 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'That Spells DNA' c�mu dal."
+LangString DESC_s2_sub1_Section18 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'When You Go' c�mu dal."
+LangString DESC_s2_sub1_Section19 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Better' c�mu dal."
+LangString DESC_s2_sub1_Section20 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Shop Vac' c�mu dal."
+LangString DESC_s2_sub1_Section21 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'I Feel Fantastic' c�mu dal."
+LangString DESC_s2_sub1_Section22 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Re: Your Brains' c�mu dal."
+LangString DESC_s2_sub1_Section23 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Skullcrusher Mountain' c�mu dal."
+LangString DESC_s2_sub1_Section24 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Chiron Beta Prime' c�mu dal (vide�val)."
+
+LangString DESC_s2_sub2_Section1 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a '69' c�mu dal."
+LangString DESC_s2_sub2_Section2 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a '69 (Karaoke)' c�mu dal."
+LangString DESC_s2_sub2_Section3 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Can't stop it' c�mu dal."
+LangString DESC_s2_sub2_Section4 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Can't stop it (Karaoke)' c�mu dal."
+LangString DESC_s2_sub2_Section5 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'In My Hand' c�mu dal."
+LangString DESC_s2_sub2_Section6 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Man Song' c�mu dal."
+LangString DESC_s2_sub2_Section7 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Man Song (Karaoke)' c�mu dal."
+LangString DESC_s2_sub2_Section8 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Stay with me' c�mu dal."
+LangString DESC_s2_sub2_Section9 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Stay with me (Karaoke)' c�mu dal."
+
+LangString DESC_s2_sub3_Section1 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Lebendig und kr�ftig und sch�rfer' c�mu dal."
+LangString DESC_s2_sub3_Section2 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Mensch, wo bist du?' c�mu dal."
+LangString DESC_s2_sub3_Section3 ${LANG_HUNGARIAN} "Telep�t�sre ker�l a 'Mensch, wo bist du? (Karaoke)' c�mu dal."
+
+; Optional Themes
+; (not available)
\ No newline at end of file
diff --git a/songmanagement/installer/languages/Polish.nsh b/songmanagement/installer/languages/Polish.nsh
new file mode 100644
index 00000000..00d04d8e
--- /dev/null
+++ b/songmanagement/installer/languages/Polish.nsh
@@ -0,0 +1,131 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Installer - Language file: Polish
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+LangString abort_install ${LANG_POLISH} "Czy jeste� pewien �e chcesz zatrzyma� instalacj� ?"
+LangString abort_uninstall ${LANG_POLISH} "Czy jeste� pewien �e chcesz zatrzyma� odinstalowywanie ?"
+LangString oninit_running ${LANG_POLISH} "Instajacja jest ju� uruchomiona."
+LangString oninit_installagain ${LANG_POLISH} "Jeste� pewien �e chcesz zainstalowa� jeszcze raz ?"
+LangString oninit_alreadyinstalled ${LANG_POLISH} "Jest obecnie zainstalowany"
+LangString oninit_closeusdx ${LANG_POLISH} "nie mo�e by� odinstalowany dop�ki jest uruchomiony! Czy chcesz zamkn�� go ?"
+LangString oninit_updateusdx ${LANG_POLISH} "Do you want to update the installation from:"
+LangString oninit_uninstall ${LANG_POLISH} "Czy chcesz odinstalowa� star� wersj� ? (rekomendowane)"
+
+LangString update_connect ${LANG_POLISH} "Sprawd� po��czenie z insternetm i sprawd� nowe wersje"
+LangString button_next ${LANG_POLISH} "Dalej >"
+LangString button_close ${LANG_POLISH} "Zamknij"
+LangString update_information ${LANG_POLISH} "Mo�esz sprawdzi� czy jest nowsza wersja 'UltraStar Deluxe'. Aby to zrobi� po��cz si� z internetm. Je�li nowa wersja zostanie znaleziona, b�dzie mo�na j� zainstalowa�."
+
+LangString delete_components ${LANG_POLISH} "Tak�� usun�� nast�puj�ce sk�adniki:"
+LangString delete_covers ${LANG_POLISH} "Ok�adka?"
+LangString delete_highscores ${LANG_POLISH} "Wyniki?"
+LangString delete_config ${LANG_POLISH} "Koniguracja?"
+LangString delete_screenshots ${LANG_POLISH} "Zrzuty ekran�w?"
+LangString delete_playlists ${LANG_POLISH} "Playlisty?"
+LangString delete_songs ${LANG_POLISH} "Usun�� piosenki? UWAGA: Wszystkie pliki w katalogu InstallationDir\songs b�d� usuni�te(!)"
+
+LangString update_check_older ${LANG_POLISH} "Twoja werjsa $R0 jest przestarza�a. Nowa wersja $1 UltraStar'a Deluxe jest ju� dost�pna. Czy chcesz dokona� aktualizacji ?"
+LangString update_check_equal ${LANG_POLISH} "Obecnie zainstalowana wersja $R0 jest najbardziej aktualna. Nie ma nowszych wersji."
+LangString update_check_newer ${LANG_POLISH} "Twoja obecnie zainstalowana wersja $R0 jest nowsza ni� $\n$\robecnie wydana wersja $1 UltraStar'a Deluxe. Nie ma nowszych aktualizacji."
+LangString update_check_failed ${LANG_POLISH} "Poszukiwanie nowyszch wersji zako�czy�o si� b��dem. Czy chcesz odwiedzi� stron� g��wn� i sprawdzi� r�cznie ?"
+
+; Welcome Page:
+
+LangString page_welcome_title_update ${LANG_POLISH} "Witamy w kreatorze aktualizacji programu UltraStar Deluxe"
+LangString page_welcome_txt_update ${LANG_POLISH} "Ten kreator przeprowadzi ci� przez proces aktualizacji gry UltraStar Deluxe. UltraStar Deluxe jest bezp�atn� i Otwart� gr� Karaoke, kt�r� mo�na por�wna� z SingStar'em.$\n$\r$\n$\rZesp� UltraStar Deluxe �yczy mi�ej zabawy.$\n$\rStrona projektu: http://www.ultrastardeluxe.org$\n$\rForum wsparcia: http://forum.ultrastardeluxe.org"
+LangString page_welcome_title ${LANG_POLISH} "Witamy w kreatorze instalacji programu UltraStar Deluxe"
+LangString page_welcome_txt ${LANG_POLISH} "Ten kreator przeprowadzi ci� przez proces instalacji gry UltraStar Deluxe. UltraStar Deluxe jest bezp�atn� i Otwart� gr� Karaoke, kt�r� mo�na por�wna� z SingStar'em.$\n$\r$\n$\rZesp� UltraStar Deluxe �yczy mi�ej zabawy.$\n$\rStrona projektu: http://www.ultrastardeluxe.org$\n$\rForum wsparcia: http://forum.ultrastardeluxe.org"
+LangString page_un_welcome_title ${LANG_POLISH} "Witamy w kreatorze deinstalacji gry UltraStar Deluxe"
+
+; Components Page:
+
+LangString page_components_info ${LANG_POLISH} "Najed� myszk� na komponent, aby zobaczy� szczeg�y"
+
+; Custom Page
+
+LangString page_settings_fullscreen ${LANG_POLISH} "Tryb Pe�noekranowy"
+LangString page_settings_subtitle ${LANG_POLISH} "Wybierz ustawienia dogodne dla Ciebie."
+
+; Finish Page:
+
+LangString page_finish_txt ${LANG_POLISH} "UltraStar Deluxe zosta� poprawnie zainstalowany na twoim komputerze.$\n$\r$\n$\rOdwied� Nasz� stron� aby otrzyma� najnowsze wiadomo�ci i aktualizacj�."
+LangString page_finish_linktxt ${LANG_POLISH} "Strona Projektu"
+LangString page_finish_desktop ${LANG_POLISH} "Czy stw�rzy� skr�t na Pulpicie ?"
+
+; Start Menu and Shortcuts
+
+LangString sm_shortcut ${LANG_POLISH} "Graj w UltraStar Deluxe"
+LangString sm_uninstall ${LANG_POLISH} "Odinstaluj"
+LangString sm_website ${LANG_POLISH} "Strona Projektu"
+LangString sm_license ${LANG_POLISH} "Licencja"
+LangString sm_readme ${LANG_POLISH} "Readme"
+LangString sm_songs ${LANG_POLISH} "Piosenki"
+LangString sm_documentation ${LANG_POLISH} "Dokumentacja"
+
+LangString sc_play ${LANG_POLISH} "Graj"
+LangString sc_desktop ${LANG_POLISH} "Czy stw�rzy� skr�t na Pulpicie ?"
+
+; Sections and SectionGroups
+
+LangString name_section1 ${LANG_POLISH} "G��wne komponenty"
+LangString name_section2 ${LANG_POLISH} "Piosenki"
+LangString name_s2_sub1 ${LANG_POLISH} "Jonathan Coulton"
+LangString name_s2_sub2 ${LANG_POLISH} "Shearer"
+LangString name_s2_sub3 ${LANG_POLISH} "Wise Guys"
+LangString name_s2_sub4 ${LANG_POLISH} "Pornophonique"
+
+LangString DESC_Section1 ${LANG_POLISH} "To s� podstawowe pliki potrzebe przez UltraStar Deluxe"
+LangString DESC_Section2 ${LANG_POLISH} "Mo�esz wybra� kt�re piosenki chcesz �ci�gn�� (Wymagane po��czenie z internetem!)"
+LangString DESC_Section2_sub1 ${LANG_POLISH} "Mo�esz wybra� kt�re piosenki Jonathan Coulton (CC by-nc 3.0) chcesz zainstalowa�."
+LangString DESC_Section2_sub2 ${LANG_POLISH} "Mo�esz wybra� kt�re piosenki Shearer (CC by-nc-sa 2.0 / 3.0) chcesz zainstalowa�."
+LangString DESC_Section2_sub3 ${LANG_POLISH} "Mo�esz wybra� kt�re piosenki Wise Guys chcesz zainstalowa�."
+LangString DESC_Section2_sub4 ${LANG_POLISH} "Mo�esz wybra� kt�re piosenki Pornophonique chcesz zainstalowa�."
+
+LangString DESC_g2Section2 ${LANG_POLISH} "�ci�gnij piosenk� 'Dead Smiling Pirates - I 18' (CC by-nc-nd 2.5)."
+LangString DESC_g2Section3 ${LANG_POLISH} "�ci�gnij piosenk� 'Joshua Morin - On The Run' (CC by-sa 2.5)."
+LangString DESC_g2Section4 ${LANG_POLISH} "�ci�gnij piosenk� 'Pornophonique - Space Invaders' (CC by-nc-nd 2.0)."
+LangString DESC_g2Section5 ${LANG_POLISH} "�ci�gnij piosenk� 'Steven Dunston - Northern Star' (CC by-nc-sa 2.5)."
+LangString DESC_g2Section1 ${LANG_POLISH} "�ci�gnij piosenk� 'Bodo Wartke - Liebeslied (Love Song)'."
+LangString DESC_g2Section6 ${LANG_POLISH} "�ci�gnij piosenk� 'Pornophonique - Space Invaders (Karaoke)' (CC by-nc-nd 2.0)."
+
+LangString DESC_s2_sub1_Section1 ${LANG_POLISH} "�ci�gnij piosenk� 'Monkey Shines'."
+LangString DESC_s2_sub1_Section2 ${LANG_POLISH} "�ci�gnij piosenk� 'I Crush Everything'."
+LangString DESC_s2_sub1_Section3 ${LANG_POLISH} "�ci�gnij piosenk� 'Not About You'."
+LangString DESC_s2_sub1_Section4 ${LANG_POLISH} "�ci�gnij piosenk� 'Mr. Fancy Pants'."
+LangString DESC_s2_sub1_Section5 ${LANG_POLISH} "�ci�gnij piosenk� 'Big Bad World One'."
+LangString DESC_s2_sub1_Section6 ${LANG_POLISH} "�ci�gnij piosenk� 'Flickr [incl. video]'."
+LangString DESC_s2_sub1_Section7 ${LANG_POLISH} "�ci�gnij piosenk� 'My Beige Bear'."
+LangString DESC_s2_sub1_Section8 ${LANG_POLISH} "�ci�gnij piosenk� 'The Future Soon'."
+LangString DESC_s2_sub1_Section9 ${LANG_POLISH} "�ci�gnij piosenk� 'Ikea'."
+LangString DESC_s2_sub1_Section10 ${LANG_POLISH} "�ci�gnij piosenk� 'Furry Old Lobster'."
+LangString DESC_s2_sub1_Section11 ${LANG_POLISH} "�ci�gnij piosenk� 'Code Monkey [incl. video]'."
+LangString DESC_s2_sub1_Section12 ${LANG_POLISH} "�ci�gnij piosenk� 'I�m Your Moon'."
+LangString DESC_s2_sub1_Section13 ${LANG_POLISH} "�ci�gnij piosenk� 'First Of May'."
+LangString DESC_s2_sub1_Section14 ${LANG_POLISH} "�ci�gnij piosenk� 'Dance, Soterios Johnson, Dance'."
+LangString DESC_s2_sub1_Section15 ${LANG_POLISH} "�ci�gnij piosenk� 'A Talk With George'."
+LangString DESC_s2_sub1_Section16 ${LANG_POLISH} "�ci�gnij piosenk� 'Creepy Doll [incl. video]'."
+LangString DESC_s2_sub1_Section17 ${LANG_POLISH} "�ci�gnij piosenk� 'That Spells DNA'."
+LangString DESC_s2_sub1_Section18 ${LANG_POLISH} "�ci�gnij piosenk� 'When You Go'."
+LangString DESC_s2_sub1_Section19 ${LANG_POLISH} "�ci�gnij piosenk� 'Better'."
+LangString DESC_s2_sub1_Section20 ${LANG_POLISH} "�ci�gnij piosenk� 'Shop Vac'."
+LangString DESC_s2_sub1_Section21 ${LANG_POLISH} "�ci�gnij piosenk� 'I Feel Fantastic'."
+LangString DESC_s2_sub1_Section22 ${LANG_POLISH} "�ci�gnij piosenk� 'Re: Your Brains'."
+LangString DESC_s2_sub1_Section23 ${LANG_POLISH} "�ci�gnij piosenk� 'Skullcrusher Mountain'."
+LangString DESC_s2_sub1_Section24 ${LANG_POLISH} "�ci�gnij piosenk� 'Chiron Beta Prime [incl. video]'."
+
+LangString DESC_s2_sub2_Section1 ${LANG_POLISH} "�ci�gnij piosenk� '69'."
+LangString DESC_s2_sub2_Section2 ${LANG_POLISH} "�ci�gnij piosenk� '69 (Karaoke)'."
+LangString DESC_s2_sub2_Section3 ${LANG_POLISH} "�ci�gnij piosenk� 'Can't stop it'."
+LangString DESC_s2_sub2_Section4 ${LANG_POLISH} "�ci�gnij piosenk� 'Can't stop it (Karaoke)'."
+LangString DESC_s2_sub2_Section5 ${LANG_POLISH} "�ci�gnij piosenk� 'In My Hand'."
+LangString DESC_s2_sub2_Section6 ${LANG_POLISH} "�ci�gnij piosenk� 'Man Song'."
+LangString DESC_s2_sub2_Section7 ${LANG_POLISH} "�ci�gnij piosenk� 'Man Song (Karaoke)'."
+LangString DESC_s2_sub2_Section8 ${LANG_POLISH} "�ci�gnij piosenk� 'Stay with me'."
+LangString DESC_s2_sub2_Section9 ${LANG_POLISH} "�ci�gnij piosenk� 'Stay with me (Karaoke)'."
+
+LangString DESC_s2_sub3_Section1 ${LANG_POLISH} "�ci�gnij piosenk� 'Lebendig und kr�ftig und sch�rfer'."
+LangString DESC_s2_sub3_Section2 ${LANG_POLISH} "�ci�gnij piosenk� 'Mensch, wo bist du?'."
+LangString DESC_s2_sub3_Section3 ${LANG_POLISH} "�ci�gnij piosenk� 'Mensch, wo bist du? (Karaoke)'."
+
+; Optional Themes
+; (not available)
\ No newline at end of file
diff --git a/songmanagement/installer/languages/translations.txt b/songmanagement/installer/languages/translations.txt
new file mode 100644
index 00000000..9d5946e8
--- /dev/null
+++ b/songmanagement/installer/languages/translations.txt
@@ -0,0 +1,16 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; How to translate the installer into your own language?
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+If you want to translate the installer, just:
+
+- Take English.nsh and edit each variabe within the "" 
+
+- Replace LANG_ENGLISH with the name of your language (in english).
+
+Please also edit the following file
+for translating the settings screen:
+
+..\settings\settings-1033.ini
+
+Thanks for your help in advance!
\ No newline at end of file
diff --git a/songmanagement/installer/settings/files_main_install.nsh b/songmanagement/installer/settings/files_main_install.nsh
new file mode 100644
index 00000000..10afc6f6
--- /dev/null
+++ b/songmanagement/installer/settings/files_main_install.nsh
@@ -0,0 +1,90 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Installer: Main components
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+; Remove old files from previous versions
+IfFileExists $INSTDIR\ScoreConverter.exe 0 +2
+Delete "$INSTDIR\ScoreConverter.exe"
+IfFileExists $INSTDIR\USdx.exe 0 +2
+Delete "$INSTDIR\USdx.exe"
+IfFileExists $INSTDIR\covers.cache 0 +2
+Delete "$INSTDIR\covers.cache"
+IfFileExists $INSTDIR\avcodec-51.dll 0 +2
+Delete "$INSTDIR\avcodec-51.dll"
+IfFileExists $INSTDIR\avformat-50.dll 0 +2
+Delete "$INSTDIR\avformat-50.dll"
+IfFileExists $INSTDIR\avutil-49.dll 0 +2
+Delete "$INSTDIR\avutil-49.dll"
+IfFileExists $INSTDIR\bass.dll 0 +2
+Delete "$INSTDIR\bass.dll"
+IfFileExists $INSTDIR\SDL.dll 0 +2
+Delete "$INSTDIR\SDL.dll"
+IfFileExists $INSTDIR\sqlite3.dll 0 +2
+Delete "$INSTDIR\sqlite3.dll"
+
+RMDir /r "$INSTDIR\Themes"
+RMDir /r "$INSTDIR\Skins"
+RMDir /r "$INSTDIR\Plugins"
+RMDir /r "$INSTDIR\Languages"
+
+; Create Directories:
+
+CreateDirectory $INSTDIR\plugins
+CreateDirectory $INSTDIR\covers
+CreateDirectory $INSTDIR\songs
+
+${If} $UseAppData == true
+
+  ; Create folders in appdata for current user
+  SetShellVarContext current		
+  CreateDirectory $UserDataPath
+  CreateDirectory $UserDataPath\screenshots
+  CreateDirectory $UserDataPath\playlists
+
+  SetOutPath "$INSTDIR"
+
+  CreateShortCut "screenshots.lnk" "$UserDataPath\screenshots"
+  CreateShortCut "playlists.lnk" "$UserDataPath\playlists"
+  CreateShortCut "config.ini.lnk" "$ConfigIniPath"
+
+  SetShellVarContext all
+${EndIf}
+
+; themes, languages, sounds, fonts, visuals dir
+
+SetOutPath "$INSTDIR"
+
+File /r /x .svn /x .gitignore ..\game\themes
+File /r /x .svn /x .gitignore ..\game\languages
+File /r /x .svn /x .gitignore ..\game\sounds
+File /r /x .svn /x .gitignore ..\game\fonts
+File /r /x .svn /x .gitignore ..\game\resources
+File /r /x .svn /x .gitignore ..\game\visuals
+
+; Root dir:
+
+File .\dependencies\dll\*.dll
+
+File ..\ChangeLog.txt
+File ..\ChangeLog.GERMAN.txt
+File ..\game\LuaCommands.odt
+File ..\README.txt
+File .\dependencies\documents\license.txt
+File .\dependencies\documents\documentation.pdf
+
+File "..\${exe}.exe"
+
+; Covers dir:
+
+SetOutPath "$INSTDIR\covers"
+
+IfFileExists $INSTDIR\covers\covers.ini +2 0
+File ..\game\covers\covers.ini
+File ..\game\covers\NoCover.jpg
+
+; Plugins dir:
+
+SetOutPath "$INSTDIR\plugins\"
+File "..\game\plugins\*.*"
+
+SetOutPath "$INSTDIR"
\ No newline at end of file
diff --git a/songmanagement/installer/settings/files_main_uninstall.nsh b/songmanagement/installer/settings/files_main_uninstall.nsh
new file mode 100644
index 00000000..ed2259bf
--- /dev/null
+++ b/songmanagement/installer/settings/files_main_uninstall.nsh
@@ -0,0 +1,110 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Uninstaller: Main components
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+; Delete created Icons in startmenu
+
+ SetShellVarContext all
+ RMDir /r "$SMPROGRAMS\$ICONS_GROUP\"
+
+; Delete created Icon on Desktop
+
+ Delete "$Desktop\Play UltraStar Deluxe.lnk"
+ Delete "$Desktop\UltraStar Deluxe spielen.lnk"
+ Delete "$Desktop\UltraStar Deluxe karaoke.lnk"
+
+; Remove dirs
+
+ RMDir /r "$INSTDIR\plugins"
+ RMDir /r "$INSTDIR\themes"
+ RMDir /r "$INSTDIR\fonts"
+ RMDir /r "$INSTDIR\languages"
+ RMDir /r "$INSTDIR\visuals"
+ RMDir /r "$INSTDIR\resources"
+ RMDir /r "$INSTDIR\sounds"
+
+; Delete remaining files
+ Delete "$INSTDIR\ScoreConverter.exe"
+ Delete "$INSTDIR\${exe}.exe"
+ Delete "$INSTDIR\ChangeLog.GERMAN.txt"
+ Delete "$INSTDIR\ChangeLog.txt"
+ Delete "$INSTDIR\LuaCommands.odt"
+ Delete "$INSTDIR\documentation.pdf"
+ Delete "$INSTDIR\license.txt"
+ Delete "$INSTDIR\README.txt"
+ Delete "$INSTDIR\screenshots.lnk"
+ Delete "$INSTDIR\playlists.lnk"
+ Delete "$INSTDIR\config.ini.lnk"
+
+ Delete "$INSTDIR\Error.log"
+ Delete "$INSTDIR\Benchmark.log"
+ Delete "$INSTDIR\cover.db"
+
+ Delete "$INSTDIR\avcodec-52.dll"
+ Delete "$INSTDIR\avformat-52.dll"
+ Delete "$INSTDIR\avfilter-1.dll"
+ Delete "$INSTDIR\avdevice-52.dll"
+ Delete "$INSTDIR\avutil-50.dll"
+ Delete "$INSTDIR\bass.dll"
+ Delete "$INSTDIR\freetype6.dll"
+ Delete "$INSTDIR\glew32.dll"
+ Delete "$INSTDIR\jpeg.dll"
+ Delete "$INSTDIR\libpng12-0.dll"
+ Delete "$INSTDIR\libprojectM.dll"
+ Delete "$INSTDIR\libtiff-3.dll"
+ Delete "$INSTDIR\lua5.1.dll"
+ Delete "$INSTDIR\lua51.dll"
+ Delete "$INSTDIR\pcre3.dll"
+ Delete "$INSTDIR\portaudio_x86.dll"
+ Delete "$INSTDIR\portmixer.dll"
+ Delete "$INSTDIR\projectM-cwrapper.dll"
+ Delete "$INSTDIR\SDL.dll"
+ Delete "$INSTDIR\SDL_image.dll"
+ Delete "$INSTDIR\SDL_ttf.dll"
+ Delete "$INSTDIR\sqlite3.dll"
+ Delete "$INSTDIR\swscale-0.dll"
+ Delete "$INSTDIR\zlib1.dll"
+
+ StrCpy $0 "$INSTDIR\songs"
+ Call un.DeleteIfEmpty 
+
+ StrCpy $0 "$INSTDIR\covers"
+ Call un.DeleteIfEmpty
+
+ StrCpy $0 "$INSTDIR\screenshots"
+ Call un.DeleteIfEmpty
+
+ StrCpy $0 "$INSTDIR\playlists"
+ Call un.DeleteIfEmpty
+
+ ; Clean up AppData
+
+ SetShellVarContext current
+
+ Delete "$APPDATA\ultrastardx\Error.log"
+ Delete "$APPDATA\ultrastardx\Benchmark.log"
+ Delete "$APPDATA\ultrastardx\cover.db"
+
+ StrCpy $0 "$APPDATA\ultrastardx\covers"
+ Call un.DeleteIfEmpty
+
+ StrCpy $0 "$APPDATA\ultrastardx\songs"
+ Call un.DeleteIfEmpty
+
+ StrCpy $0 "$APPDATA\ultrastardx\screenshots"
+ Call un.DeleteIfEmpty
+
+ StrCpy $0 "$APPDATA\ultrastardx\playlists"
+ Call un.DeleteIfEmpty
+
+ StrCpy $0 "$APPDATA\ultrastardx"
+ Call un.DeleteIfEmpty
+
+ SetShellVarContext all
+
+; Self delete:
+
+ Delete "$INSTDIR\Uninstall.exe"
+
+ StrCpy $0 "$INSTDIR"
+ Call un.DeleteIfEmpty
\ No newline at end of file
diff --git a/songmanagement/installer/settings/files_opt_songs.nsh b/songmanagement/installer/settings/files_opt_songs.nsh
new file mode 100644
index 00000000..d8d4ef28
--- /dev/null
+++ b/songmanagement/installer/settings/files_opt_songs.nsh
@@ -0,0 +1,931 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Installer: Download optional songs
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+SectionGroup $(name_section2) Section2
+
+;-----------------------------------------------------------------------
+; BODO WARTKE
+;-----------------------------------------------------------------------
+Section /o "Bodo Wartke - Liebeslied (Love Song)" g2Section1
+
+   AddSize 10343
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_song1} $LOCALAPPDATA\Temp\Song-BodoWartke-LoveSong.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-BodoWartke-LoveSong.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-BodoWartke-LoveSong.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+
+;-----------------------------------------------------------------------
+; Dead Smiling Pirates - I 18
+;-----------------------------------------------------------------------
+
+Section /o "Dead Smiling Pirates - I 18" g2Section2
+   AddSize 2816
+   SetOverwrite try
+   SetOutPath "$INSTDIR"
+   CreateDirectory "$INSTDIR\songs\Dead Smiling Pirates - I 18"
+   SetOutPath "$INSTDIR\songs\Dead Smiling Pirates - I 18\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_song2} $LOCALAPPDATA\Temp\Song-I-18.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-I-18.zip" "$INSTDIR\songs\Dead Smiling Pirates - I 18\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-I-18.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+
+;-----------------------------------------------------------------------
+; Jonathan Coulton Songs
+;-----------------------------------------------------------------------
+
+SectionGroup $(name_s2_sub1) s2_sub1
+
+Section /o "A Talk With George" s2_sub1_Section15
+
+   AddSize 4076
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song15} $LOCALAPPDATA\Temp\Song-JC-ATWG.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-ATWG.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-ATWG.zip"
+
+  SetOutPath "$INSTDIR"
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Better" s2_sub1_Section19
+
+   AddSize 4199
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song19} $LOCALAPPDATA\Temp\Song-JC-Better.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-Better.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-Better.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Monkey Shines" s2_sub1_Section1
+
+   AddSize 1455
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song1} $LOCALAPPDATA\Temp\Song-JC-MS.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-MS.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-MS.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "I Crush Everything" s2_sub1_Section2
+
+   AddSize 7127
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song2} $LOCALAPPDATA\Temp\Song-JC-ICE.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-ICE.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-ICE.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Not About You" s2_sub1_Section3
+
+   AddSize 3492
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song3} $LOCALAPPDATA\Temp\Song-JC-NAY.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-NAY.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-NAY.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Mr. Fancy Pants" s2_sub1_Section4
+
+   AddSize 2427
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song4} $LOCALAPPDATA\Temp\Song-JC-MFP.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-MFP.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-MFP.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Big Bad World One" s2_sub1_Section5
+
+   AddSize 4424
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song5} $LOCALAPPDATA\Temp\Song-JC-BBWO.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-BBWO.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-BBWO.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Flickr" s2_sub1_Section6
+
+   AddSize 21607
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song6} $LOCALAPPDATA\Temp\Song-JC-Flickr.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-Flickr.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-Flickr.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "My Beige Bear" s2_sub1_Section7
+
+   AddSize 4926
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song7} $LOCALAPPDATA\Temp\Song-JC-MBB.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-MBB.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-MBB.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "The Future Soon" s2_sub1_Section8
+
+   AddSize 5612
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song8} $LOCALAPPDATA\Temp\Song-JC-TFS.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-TFS.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-TFS.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Ikea" s2_sub1_Section9
+
+   AddSize 4608
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song9} $LOCALAPPDATA\Temp\Song-JC-Ikea.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-Ikea.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-Ikea.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Furry Old Lobster" s2_sub1_Section10
+
+   AddSize 3288
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song10} $LOCALAPPDATA\Temp\Song-JC-FOL.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-FOL.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-FOL.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Code Monkey" s2_sub1_Section11
+
+   AddSize 21402
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song11} $LOCALAPPDATA\Temp\Song-JC-CM.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-CM.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-CM.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "I�m Your Moon" s2_sub1_Section12
+
+   AddSize 4916
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song12} $LOCALAPPDATA\Temp\Song-JC-IYM.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-IYM.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-IYM.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "First Of May" s2_sub1_Section13
+
+   AddSize 6257
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song13} $LOCALAPPDATA\Temp\Song-JC-FOM.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-FOM.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-FOM.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Dance, Soterious Johnson, Dance" s2_sub1_Section14
+
+   AddSize 5929
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song14} $LOCALAPPDATA\Temp\Song-JC-DSJD.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-DSJD.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-DSJD.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Creepy Doll" s2_sub1_Section16
+
+   AddSize 66560
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song16} $LOCALAPPDATA\Temp\Song-JC-CD.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-CD.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-CD.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "That Spells DNA" s2_sub1_Section17
+
+   AddSize 4158
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song17} $LOCALAPPDATA\Temp\Song-JC-TSDNA.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-TSDNA.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-TSDNA.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "When You Go" s2_sub1_Section18
+
+   AddSize 5755
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song18} $LOCALAPPDATA\Temp\Song-JC-WYG.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-WYG.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-WYG.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Shop Vac" s2_sub1_Section20
+
+   AddSize 5448
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song20} $LOCALAPPDATA\Temp\Song-JC-SV.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-SV.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-SV.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "I Feel Fantastic" s2_sub1_Section21
+
+   AddSize 3851
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song21} $LOCALAPPDATA\Temp\Song-JC-IFF.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-IFF.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-IFF.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Re: Your Brains" s2_sub1_Section22
+
+   AddSize 7087
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song22} $LOCALAPPDATA\Temp\Song-JC-ReYB.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-ReYB.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-ReYB.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Skullcrusher Mountain" s2_sub1_Section23
+
+   AddSize 6298
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song23} $LOCALAPPDATA\Temp\Song-JC-SCM.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-SCM.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-SCM.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Chiron Beta Prime" s2_sub1_Section24
+
+   AddSize 38298
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub1_song24} $LOCALAPPDATA\Temp\Song-JC-CBP.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-JC-CBP.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-JC-CBP.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+
+SectionGroupEnd
+;-----------------------------------------------------------------------
+; Joshua Morin - On The Run
+;-----------------------------------------------------------------------
+Section /o "Joshua Morin - On The Run" g2Section3
+   AddSize 3881
+   SetOverwrite try
+   SetOutPath "$INSTDIR"
+   CreateDirectory "$INSTDIR\songs\Joshua Morin - On The Run"
+   SetOutPath "$INSTDIR\songs\Joshua Morin - On The Run\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_song3} $LOCALAPPDATA\Temp\Song-On-the-run.zip
+
+  Pop $R0 ;Get the return value
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-On-the-run.zip" "$INSTDIR\songs\Joshua Morin - On The Run\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-On-the-run.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+; Pornophonique
+;-----------------------------------------------------------------------
+SectionGroup $(name_s2_sub4) s2_sub4
+
+Section /o "Pornophonique - Space Invaders" g2Section4
+   AddSize 3646
+   SetOverwrite try
+   SetOutPath "$INSTDIR"
+   CreateDirectory "$INSTDIR\songs\Pornophonique - Space Invaders"
+   SetOutPath "$INSTDIR\songs\Pornophonique - Space Invaders\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_song4} $LOCALAPPDATA\Temp\Song-Space-Invaders.zip
+
+  Pop $R0 ;Get the return value
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Space-Invaders.zip" "$INSTDIR\songs\Pornophonique - Space Invaders\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Space-Invaders.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Pornophonique - Space Invaders (Karaoke)" g2Section6
+   AddSize 3779
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_song6} $LOCALAPPDATA\Temp\Song-SpaceInvadersKAR.zip
+
+  Pop $R0 ;Get the return value
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-SpaceInvadersKAR.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-SpaceInvadersKAR.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+
+SectionGroupEnd
+;-----------------------------------------------------------------------
+; Shearer
+;-----------------------------------------------------------------------
+SectionGroup $(name_s2_sub2) s2_sub2
+
+Section /o "Shearer - 69" s2_sub2_Section1
+
+   AddSize 4557
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub2_song1} $LOCALAPPDATA\Temp\Song-Shearer-69.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Shearer-69.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Shearer-69.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Shearer - 69 (Karaoke)" s2_sub2_Section2
+
+   AddSize 4772
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub2_song2} $LOCALAPPDATA\Temp\Song-Shearer-69-Kar.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Shearer-69-Kar.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Shearer-69-Kar.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Shearer - Can't stop it" s2_sub2_Section3
+
+   AddSize 5510
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub2_song3} $LOCALAPPDATA\Temp\Song-Shearer-CSI.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Shearer-CSI.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Shearer-CSI.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Shearer - Can't stop it (Karaoke)" s2_sub2_Section4
+
+   AddSize 4178
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub2_song4} $LOCALAPPDATA\Temp\Song-Shearer-CSI-Kar.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Shearer-CSI-Kar.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Shearer-CSI-Kar.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Shearer - In My Hand" s2_sub2_Section5
+
+   AddSize 5960
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub2_song5} $LOCALAPPDATA\Temp\Song-Shearer-IMH.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Shearer-IMH.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Shearer-IMH.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Shearer - Man Song" s2_sub2_Section6
+
+   AddSize 7270
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub2_song6} $LOCALAPPDATA\Temp\Song-Shearer-MS.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Shearer-MS.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Shearer-MS.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Shearer - Man Song (Karaoke)" s2_sub2_Section7
+
+   AddSize 5807
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub2_song7} $LOCALAPPDATA\Temp\Song-Shearer-MS-Kar.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Shearer-MS-Kar.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Shearer-MS-Kar.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Shearer - Stay With Me" s2_sub2_Section8
+
+   AddSize 6400
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub2_song8} $LOCALAPPDATA\Temp\Song-Shearer-SWM.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Shearer-SWM.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Shearer-SWM.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Shearer - Stay With Me (Karaoke)" s2_sub2_Section9
+
+   AddSize 5417
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub2_song9} $LOCALAPPDATA\Temp\Song-Shearer-SWM-Kar.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Shearer-SWM-Kar.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Shearer-SWM-Kar.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+SectionGroupEnd
+
+Section /o "Steven Dunston - Northern Star" g2Section5
+   AddSize 2427
+   SetOverwrite try
+   SetOutPath "$INSTDIR"
+   CreateDirectory "$INSTDIR\songs\Steven Dunston - Northern Star"
+   SetOutPath "$INSTDIR\songs\Steven Dunston - Northern Star\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_song5} $LOCALAPPDATA\Temp\Song-Northern-Star.zip
+
+  Pop $R0 ;Get the return value
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-Northern-Star.zip" "$INSTDIR\songs\Steven Dunston - Northern Star\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-Northern-Star.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+; Wise Guys
+;-----------------------------------------------------------------------
+SectionGroup $(name_s2_sub3) s2_sub3
+
+Section /o "Wise Guys - Lebendig und kr�ftig und sch�rfer" s2_sub3_Section1
+
+   AddSize 4015
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub3_song1} $LOCALAPPDATA\Temp\Song-WiseGuys-LUKUS.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-WiseGuys-LUKUS.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-WiseGuys-LUKUS.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Wise Guys - Mensch, wo bist du?" s2_sub3_Section2
+
+   AddSize 5335
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub3_song2} $LOCALAPPDATA\Temp\Song-WiseGuys-MWBD.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-WiseGuys-MWBD.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-WiseGuys-MWBD.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+;-----------------------------------------------------------------------
+Section /o "Wise Guys - Mensch, wo bist du? (Karaoke)" s2_sub3_Section3
+
+   AddSize 5335
+   SetOverwrite try
+   SetOutPath "$INSTDIR\songs\"
+
+; Download song:
+  NSISdl::download /TIMEOUT=50000 ${download_sub3_song3} $LOCALAPPDATA\Temp\Song-WiseGuys-MWBDKar.zip
+ 
+  Pop $R0
+    StrCmp $R0 "success" dlok
+      MessageBox MB_OK|MB_ICONEXCLAMATION "Download Error, click OK to Continue" /SD IDOK
+  dlok:
+
+  ZipDLL::extractall "$LOCALAPPDATA\Temp\Song-WiseGuys-MWBDKar.zip" "$INSTDIR\songs\"
+
+  Delete "$LOCALAPPDATA\Temp\Song-WiseGuys-MWBDKar.zip"
+
+  SetOutPath "$INSTDIR"
+
+SectionEnd
+
+SectionGroupEnd
+
+SectionGroupEnd
\ No newline at end of file
diff --git a/songmanagement/installer/settings/functions.nsh b/songmanagement/installer/settings/functions.nsh
new file mode 100644
index 00000000..d437c9e1
--- /dev/null
+++ b/songmanagement/installer/settings/functions.nsh
@@ -0,0 +1,50 @@
+; Creates Desktop Shortcut(s) if 
+; checked on Finish Page
+
+Function CreateDesktopShortCuts
+SetOutPath "$INSTDIR"
+CreateShortcut "$Desktop\$(sm_shortcut).lnk" "$INSTDIR\ultrastardx.exe"
+FunctionEnd
+
+; Deletes only empty dirs which are
+; at the top of the stack.
+
+Function un.DeleteIfEmpty
+  FindFirst $R0 $R1 "$0\*.*"
+  strcmp $R1 "." 0 NoDelete
+   FindNext $R0 $R1
+   strcmp $R1 ".." 0 NoDelete
+    ClearErrors
+    FindNext $R0 $R1
+    IfErrors 0 NoDelete
+     FindClose $R0
+     Sleep 1000
+     RMDir "$0"
+  NoDelete:
+   FindClose $R0
+FunctionEnd
+
+; Finds UltraStar Deluxe process
+;
+
+!define nsProcess::FindProcess `!insertmacro nsProcess::FindProcess`
+
+!macro nsProcess::FindProcess _FILE _ERR
+	nsProcess::_FindProcess /NOUNLOAD `${_FILE}`
+	Pop ${_ERR}
+!macroend
+
+
+!define nsProcess::KillProcess `!insertmacro nsProcess::KillProcess`
+
+!macro nsProcess::KillProcess _FILE _ERR
+	nsProcess::_KillProcess /NOUNLOAD `${_FILE}`
+	Pop ${_ERR}
+!macroend
+
+
+!define nsProcess::Unload `!insertmacro nsProcess::Unload`
+
+!macro nsProcess::Unload
+	nsProcess::_Unload
+!macroend
\ No newline at end of file
diff --git a/songmanagement/installer/settings/settings-1031.ini b/songmanagement/installer/settings/settings-1031.ini
new file mode 100644
index 00000000..9a6b4b71
--- /dev/null
+++ b/songmanagement/installer/settings/settings-1031.ini
@@ -0,0 +1,161 @@
+[Settings]
+NumFields=19
+
+; Background Group of Settings Box
+[Field 17]
+Type=GroupBox
+Left=0
+Top=0
+Right=300
+Bottom=140
+Text=UltraStar Deluxe Konfiguration (Optional) 
+
+[Field 1]
+Type=Label
+Text="Vollbild Modus:"
+Left=5
+Right=58
+Top=30
+Bottom=38
+
+[Field 2]
+Type=Label
+Text="Sprache:"
+Left=5
+Right=58
+Top=47
+Bottom=55
+
+[Field 3]
+Type=Label
+Text="Aufl�sung:"
+Left=5
+Right=58
+Top=64
+Bottom=72
+
+[Field 4]
+Type=Label
+Text="Ordnerstruktur:"
+Left=5
+Right=58
+Top=82
+Bottom=90
+
+[Field 5]
+Type=DropList
+ListItems=On|Off
+State=On
+Left=62
+Right=152
+Top=28
+Bottom=39
+
+[Field 6]
+Type=DropList
+ListItems=Catalan|Croatian|Czech|Danish|Dutch|English|Euskara|Finnish|French|German|Greek|Hungarian|Icelandic|Italian|Japanese|Luxembourgish|Norwegian|Polish|Portuguese|Serbian|Slovak|Slovenian|Spanish|Swedish
+State=German
+Left=62
+Right=152
+Top=45
+Bottom=56
+
+[Field 7]
+Type=DropList
+ListItems=320x200|640x480|800x600|1024x768|1280x1024|1440x900|1680x1050|1920x1200
+State=800x600
+Left=62
+Right=152
+Top=62
+Bottom=73
+
+[Field 8]
+Type=DropList
+ListItems=On|Off
+State=Off
+Left=62
+Right=152
+Top=81
+Bottom=91
+
+[Field 9]
+Type=Label
+Text=Spiel im Fenster oder Vollbild starten?
+Left=157
+Right=300
+Top=30
+Bottom=38
+
+[Field 10]
+Type=Label
+Text=Alle Einstellungen k�nnen nachtr�glich im Spielmen� ge�ndert werden.
+Left=5
+Right=246
+Top=14
+Bottom=23
+
+[Field 11]
+Type=Label
+Text=Passe die Sprache des Men�s an.
+Left=158
+Right=300
+Top=46
+Bottom=55
+
+[Field 12]
+Type=Label
+Text=W�hle die Aufl�sung/Fenstergr��e aus.
+Left=157
+Right=300
+Top=64
+Bottom=72
+
+[Field 13]
+Type=Label
+Text=Eine virtuelle Ordnerstruktur zum Anzeigen der Lieder verwenden?
+Left=158
+Right=300
+Top=78
+Bottom=94
+
+[Field 14]
+Type=Label
+Left=5
+Top=100
+Right=58
+Bottom=109
+Text=Sortierung:
+
+[Field 15]
+Type=DropList
+Left=62
+Top=100
+Right=152
+Bottom=111
+State=Artist
+ListItems=Edition|Genre|Language|Folder|Title|Artist
+
+[Field 16]
+Type=Label
+Left=157
+Top=101
+Right=300
+Bottom=110
+Text=Kriterium zum Sortieren der Lieder w�hlen.
+
+[Field 18]
+Type=DirRequest
+Left=5
+Top=121
+Right=152
+Bottom=132
+Text=SongDir
+State=
+
+[Field 19]
+Type=Label
+Left=158
+Top=119
+Right=295
+Bottom=134
+Text=Hier kann ein weiterer Ordner mit Songs f�r UltraStar Deluxe angegeben werden.
diff --git a/songmanagement/installer/settings/settings-1033.ini b/songmanagement/installer/settings/settings-1033.ini
new file mode 100644
index 00000000..7176d229
--- /dev/null
+++ b/songmanagement/installer/settings/settings-1033.ini
@@ -0,0 +1,161 @@
+[Settings]
+NumFields=19
+
+; Background Group of Settings Box
+[Field 17]
+Type=GroupBox
+Left=1
+Top=1
+Right=300
+Bottom=140
+Text=UltraStar Deluxe Configuration (optional) 
+
+[Field 1]
+Type=Label
+Text="Fullscreen Mode:"
+Left=5
+Right=58
+Top=30
+Bottom=38
+
+[Field 2]
+Type=Label
+Text="Language:"
+Left=5
+Right=58
+Top=47
+Bottom=55
+
+[Field 3]
+Type=Label
+Text="Resolution:"
+Left=5
+Right=58
+Top=64
+Bottom=72
+
+[Field 4]
+Type=Label
+Text="Tabs:"
+Left=5
+Right=58
+Top=82
+Bottom=90
+
+[Field 5]
+Type=DropList
+ListItems=On|Off
+State=On
+Left=62
+Right=152
+Top=28
+Bottom=39
+
+[Field 6]
+Type=DropList
+ListItems=Catalan|Croatian|Czech|Danish|Dutch|English|Euskara|Finnish|French|German|Greek|Hungarian|Icelandic|Italian|Japanese|Luxembourgish|Norwegian|Polish|Portuguese|Serbian|Slovak|Slovenian|Spanish|Swedish
+State=English
+Left=62
+Right=152
+Top=45
+Bottom=56
+
+[Field 7]
+Type=DropList
+ListItems=320x200|640x480|800x600|1024x768|1280x1024|1440x900|1680x1050|1920x1200
+State=800x600
+Left=62
+Right=152
+Top=62
+Bottom=73
+
+[Field 8]
+Type=DropList
+ListItems=On|Off
+State=Off
+Left=62
+Right=152
+Top=81
+Bottom=91
+
+[Field 9]
+Type=Label
+Text=Start game in window or fullscreen?
+Left=157
+Right=300
+Top=30
+Bottom=38
+
+[Field 10]
+Type=Label
+Text=All settings can also be changed in the GUI later.
+Left=5
+Right=246
+Top=14
+Bottom=23
+
+[Field 11]
+Type=Label
+Text=Adjust the GUI language.
+Left=158
+Right=300
+Top=46
+Bottom=55
+
+[Field 12]
+Type=Label
+Text=Choose screen resolution/window size.
+Left=157
+Right=300
+Top=64
+Bottom=72
+
+[Field 13]
+Type=Label
+Text=Employ a virtual folder structure to show songs?
+Left=158
+Right=300
+Top=78
+Bottom=94
+
+[Field 14]
+Type=Label
+Left=5
+Top=100
+Right=58
+Bottom=109
+Text=Sorting:
+
+[Field 15]
+Type=DropList
+Left=62
+Top=100
+Right=152
+Bottom=111
+State=Artist
+ListItems=Edition|Genre|Language|Folder|Title|Artist
+
+[Field 16]
+Type=Label
+Left=157
+Top=101
+Right=300
+Bottom=110
+Text=Select criterion to sort songs.
+
+[Field 18]
+Type=DirRequest
+Left=5
+Top=121
+Right=152
+Bottom=132
+Text=SongDir
+State=
+
+[Field 19]
+Type=Label
+Left=158
+Top=119
+Right=295
+Bottom=134
+Text=Choose additional song directory for UltraStar Deluxe.
\ No newline at end of file
diff --git a/songmanagement/installer/settings/settings-1038.ini b/songmanagement/installer/settings/settings-1038.ini
new file mode 100644
index 00000000..f2ef973a
--- /dev/null
+++ b/songmanagement/installer/settings/settings-1038.ini
@@ -0,0 +1,161 @@
+[Settings]
+NumFields=19
+
+; Background Group of Settings Box
+[Field 17]
+Type=GroupBox
+Left=1
+Top=1
+Right=300
+Bottom=140
+Text=UltraStar Deluxe Configuration (optional) 
+
+[Field 1]
+Type=Label
+Text="Teljes k�perny�s m�d:"
+Left=5
+Right=58
+Top=30
+Bottom=38
+
+[Field 2]
+Type=Label
+Text="Nyelv:"
+Left=5
+Right=58
+Top=47
+Bottom=55
+
+[Field 3]
+Type=Label
+Text="Felbont�s:"
+Left=5
+Right=58
+Top=64
+Bottom=72
+
+[Field 4]
+Type=Label
+Text="Tabs:"
+Left=5
+Right=58
+Top=82
+Bottom=90
+
+[Field 5]
+Type=DropList
+ListItems=On|Off
+State=On
+Left=62
+Right=152
+Top=28
+Bottom=39
+
+[Field 6]
+Type=DropList
+ListItems=Catalan|Croatian|Czech|Danish|Dutch|English|Euskara|Finnish|French|German|Greek|Hungarian|Icelandic|Italian|Japanese|Luxembourgish|Norwegian|Polish|Portuguese|Serbian|Slovak|Slovenian|Spanish|Swedish
+State=Hungarian
+Left=62
+Right=152
+Top=45
+Bottom=56
+
+[Field 7]
+Type=DropList
+ListItems=320x200|640x480|800x600|1024x768|1280x1024|1440x900|1680x1050|1920x1200
+State=800x600
+Left=62
+Right=152
+Top=62
+Bottom=73
+
+[Field 8]
+Type=DropList
+ListItems=On|Off
+State=Off
+Left=62
+Right=152
+Top=81
+Bottom=91
+
+[Field 9]
+Type=Label
+Text=Start game in window or fullscreen?
+Left=157
+Right=300
+Top=30
+Bottom=38
+
+[Field 10]
+Type=Label
+Text=All settings can also be changed in the GUI later.
+Left=5
+Right=246
+Top=14
+Bottom=23
+
+[Field 11]
+Type=Label
+Text=Adjust the GUI language.
+Left=158
+Right=300
+Top=46
+Bottom=55
+
+[Field 12]
+Type=Label
+Text=Choose screen resolution/window size.
+Left=157
+Right=300
+Top=64
+Bottom=72
+
+[Field 13]
+Type=Label
+Text=Employ a virtual folder structure to show songs?
+Left=158
+Right=300
+Top=78
+Bottom=94
+
+[Field 14]
+Type=Label
+Left=5
+Top=100
+Right=58
+Bottom=109
+Text=Sorting:
+
+[Field 15]
+Type=DropList
+Left=62
+Top=100
+Right=152
+Bottom=111
+State=Artist
+ListItems=Edition|Genre|Language|Folder|Title|Artist
+
+[Field 16]
+Type=Label
+Left=157
+Top=101
+Right=300
+Bottom=110
+Text=Select criterion to sort songs.
+
+[Field 18]
+Type=DirRequest
+Left=5
+Top=121
+Right=152
+Bottom=132
+Text=SongDir
+State=
+
+[Field 19]
+Type=Label
+Left=158
+Top=119
+Right=295
+Bottom=134
+Text=Choose additional song directory for UltraStar Deluxe.
diff --git a/songmanagement/installer/settings/settings-1045.ini b/songmanagement/installer/settings/settings-1045.ini
new file mode 100644
index 00000000..e59f0227
--- /dev/null
+++ b/songmanagement/installer/settings/settings-1045.ini
@@ -0,0 +1,161 @@
+[Settings]
+NumFields=19
+
+; Background Group of Settings Box
+[Field 17]
+Type=GroupBox
+Left=1
+Top=1
+Right=300
+Bottom=140
+Text=Konfiguracja UltraStar Deluxe (opcjonalnie) 
+
+[Field 1]
+Type=Label
+Text="Tryb Pe�noekranowy:"
+Left=5
+Right=58
+Top=30
+Bottom=38
+
+[Field 2]
+Type=Label
+Text="J�zyk:"
+Left=5
+Right=58
+Top=47
+Bottom=55
+
+[Field 3]
+Type=Label
+Text="Rozdzielczo��:"
+Left=5
+Right=58
+Top=64
+Bottom=72
+
+[Field 4]
+Type=Label
+Text="Zak�adki:"
+Left=5
+Right=58
+Top=82
+Bottom=90
+
+[Field 5]
+Type=DropList
+ListItems=On|Off
+State=On
+Left=62
+Right=152
+Top=28
+Bottom=39
+
+[Field 6]
+Type=DropList
+ListItems=Catalan|Croatian|Czech|Danish|Dutch|English|Euskara|Finnish|French|German|Greek|Hungarian|Icelandic|Italian|Japanese|Luxembourgish|Norwegian|Polish|Portuguese|Serbian|Slovak|Slovenian|Spanish|Swedish
+State=Polish
+Left=62
+Right=152
+Top=45
+Bottom=56
+
+[Field 7]
+Type=DropList
+ListItems=320x200|640x480|800x600|1024x768|1280x1024|1440x900|1680x1050|1920x1200
+State=800x600
+Left=62
+Right=152
+Top=62
+Bottom=73
+
+[Field 8]
+Type=DropList
+ListItems=On|Off
+State=Off
+Left=62
+Right=152
+Top=81
+Bottom=91
+
+[Field 9]
+Type=Label
+Text=Czy uruchamia� gr� w oknie czy na pe�nym ekranie?
+Left=157
+Right=300
+Top=30
+Bottom=38
+
+[Field 10]
+Type=Label
+Text=Wszystkie ustawienia mo�na p�niej zmieni� w grze.
+Left=5
+Right=246
+Top=14
+Bottom=23
+
+[Field 11]
+Type=Label
+Text=Dostosuj j�zyk GUI.
+Left=158
+Right=300
+Top=46
+Bottom=55
+
+[Field 12]
+Type=Label
+Text=Wybierz rozdzieczo�� ekrany/okna.
+Left=157
+Right=300
+Top=64
+Bottom=72
+
+[Field 13]
+Type=Label
+Text=Czy chcesz aby piosenki zosta�y pogrupowane na zak�adki ?
+Left=158
+Right=300
+Top=78
+Bottom=94
+
+[Field 14]
+Type=Label
+Left=5
+Top=100
+Right=58
+Bottom=109
+Text=Sortowanie:
+
+[Field 15]
+Type=DropList
+Left=62
+Top=100
+Right=152
+Bottom=111
+State=Artist
+ListItems=Edition|Genre|Language|Folder|Title|Artist
+
+[Field 16]
+Type=Label
+Left=157
+Top=101
+Right=300
+Bottom=110
+Text=Wybierz kryteria sortowania piosenek.
+
+[Field 18]
+Type=DirRequest
+Left=5
+Top=121
+Right=152
+Bottom=132
+Text=SongDir
+State=
+
+[Field 19]
+Type=Label
+Left=158
+Top=119
+Right=295
+Bottom=134
+Text=Wybierz katalog w kt�rym znajduj� si� piosenki?
\ No newline at end of file
diff --git a/songmanagement/installer/settings/variables.nsh b/songmanagement/installer/settings/variables.nsh
new file mode 100644
index 00000000..331df7e3
--- /dev/null
+++ b/songmanagement/installer/settings/variables.nsh
@@ -0,0 +1,89 @@
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+; UltraStar Deluxe Un/Installer: Variables
+; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+
+; Product Information:
+
+!define version "1.1" ; Make sure version is also set in onInit
+
+
+!define name "UltraStar Deluxe"
+!define publisher "USDX Team"
+!define homepage "http://www.ultrastardeluxe.org"
+!define forum "http://forum.ultrastardeluxe.org"
+!define wiki "http://wiki.ultrastardeluxe.org"
+
+!define exe "ultrastardx"
+
+!define license ".\dependencies\documents\license.txt"
+
+; Icons
+
+!define img_install "install.ico"
+!define img_uninstall "uninstall.ico"
+
+; Header Images
+
+!define img_header "header.bmp" ; Header image (150x57)
+!define img_side "side.bmp" ; Side image (162x314)
+
+; Registry for Start menu entries:
+
+!define PRODUCT_NAME "${name}"
+!define PRODUCT_VERSION "${version}"
+!define PRODUCT_PUBLISHER "${publisher}"
+!define PRODUCT_WEB_SITE "${homepage}"
+!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${name}"
+!define PRODUCT_UNINST_ROOT_KEY "HKLM"
+
+; Download URLs for Songs and Themes:
+
+; SONGS
+!define download_song1 "http://downloads.sourceforge.net/ultrastardx/usdx_song-bodo_wartke_-_liebeslied.zip"
+!define download_song2 "http://downloads.sourceforge.net/ultrastardx/usdx_song-dead_smiling_pirates_-_i_18.zip"
+!define download_song3 "http://downloads.sourceforge.net/ultrastardx/usdx_song-joshua_morin_-_on_the_run.zip"
+!define download_song4 "http://downloads.sourceforge.net/ultrastardx/usdx_song-pornophonique_-_space_-_invaders.zip"
+!define download_song5 "http://downloads.sourceforge.net/ultrastardx/usdx_song-steven_dunston_-_northern_star.zip"
+!define download_song6 "http://downloads.sourceforge.net/ultrastardx/usdx_song-pornophonique_-_space_invaders_kar.zip"
+
+!define download_sub1_song1 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_monkey_shines.zip"
+!define download_sub1_song2 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_i_crush_everything.zip"
+!define download_sub1_song3 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_not_about_you.zip"
+!define download_sub1_song4 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_mr_fancy_pants.zip"
+!define download_sub1_song5 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_big_bad_world_one.zip"
+!define download_sub1_song6 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_flickr.zip"
+!define download_sub1_song7 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_my_beige_bear.zip"
+!define download_sub1_song8 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_the_future_soon.zip"
+!define download_sub1_song9 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_ikea.zip"
+!define download_sub1_song10 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_furry_old_lobster.zip"
+!define download_sub1_song11 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_code_monkey.zip"
+!define download_sub1_song12 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_im_your_moon.zip"
+!define download_sub1_song13 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_first_of_may.zip"
+!define download_sub1_song14 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_dance_soterios_johnson_dance.zip"
+!define download_sub1_song15 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_a_talk_with_george.zip"
+!define download_sub1_song16 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_creepy_doll.zip"
+!define download_sub1_song17 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_that_spells_dna.zip"
+!define download_sub1_song18 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_when_you_go.zip"
+!define download_sub1_song19 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_better.zip"
+!define download_sub1_song20 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_shop_vac.zip"
+!define download_sub1_song21 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_i_feel_fantastic.zip"
+!define download_sub1_song22 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_re-_your_brains.zip"
+!define download_sub1_song23 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_skullcrusher_mountain.zip"
+!define download_sub1_song24 "http://downloads.sourceforge.net/ultrastardx/usdx_song-jonathan_coulton_-_chiron_beta_prime.zip"
+
+!define download_sub2_song1 "http://downloads.sourceforge.net/ultrastardx/usdx_song-shearer_-_69.zip"
+!define download_sub2_song2 "http://downloads.sourceforge.net/ultrastardx/usdx_song-shearer_-_69_kar.zip"
+!define download_sub2_song3 "http://downloads.sourceforge.net/ultrastardx/usdx_song-shearer_-_cant_stop_it.zip"
+!define download_sub2_song4 "http://downloads.sourceforge.net/ultrastardx/usdx_song-shearer_-_cant_stop_it_kar.zip"
+!define download_sub2_song5 "http://downloads.sourceforge.net/ultrastardx/usdx_song-shearer_-_in_my_hand.zip"
+!define download_sub2_song6 "http://downloads.sourceforge.net/ultrastardx/usdx_song-shearer_-_man_song.zip"
+!define download_sub2_song7 "http://downloads.sourceforge.net/ultrastardx/usdx_song-shearer_-_man_song_kar.zip"
+!define download_sub2_song8 "http://downloads.sourceforge.net/ultrastardx/usdx_song-shearer_-_stay_with_me.zip"
+!define download_sub2_song9 "http://downloads.sourceforge.net/ultrastardx/usdx_song-shearer_-_stay_with_me_kar.zip"
+
+!define download_sub3_song1 "http://downloads.sourceforge.net/ultrastardx/usdx_song-wise_guys_-_lebendig_und_kraeftig_und_schaerfer.zip"
+!define download_sub3_song2 "http://downloads.sourceforge.net/ultrastardx/usdx_song-wise_guys_-_mensch_wo_bist_du.zip"
+!define download_sub3_song3 "http://downloads.sourceforge.net/ultrastardx/usdx_song-wise_guys_-_mensch_wo_bist_du_kar.zip"
+
+; THEMES
+; (removed theme section - currently no additional skins available for this usdx version)
diff --git a/songmanagement/installer/uninstall.ico b/songmanagement/installer/uninstall.ico
new file mode 100644
index 00000000..1c72432a
Binary files /dev/null and b/songmanagement/installer/uninstall.ico differ
diff --git a/songmanagement/res/rccompile-delphi.bat b/songmanagement/res/rccompile-delphi.bat
new file mode 100644
index 00000000..cb429f86
--- /dev/null
+++ b/songmanagement/res/rccompile-delphi.bat
@@ -0,0 +1,2 @@
+@set RES_NAME=ultrastardx
+BRC32 -r -fo%RES_NAME%.res %RES_NAME%.rc
diff --git a/songmanagement/res/rccompile-fpc.bat b/songmanagement/res/rccompile-fpc.bat
new file mode 100644
index 00000000..fc31fd4d
--- /dev/null
+++ b/songmanagement/res/rccompile-fpc.bat
@@ -0,0 +1,4 @@
+@set PATH=C:\Programme\lazarus\fpc\2.2.4\bin\i386-win32\;%PATH%
+@set RES_NAME=ultrastardx
+windres.exe -i %RES_NAME%.rc -o %RES_NAME%.res
+
diff --git a/songmanagement/res/ultrastardx.exe.manifest b/songmanagement/res/ultrastardx.exe.manifest
new file mode 100644
index 00000000..a6481875
--- /dev/null
+++ b/songmanagement/res/ultrastardx.exe.manifest
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="ultrastardx" type="win32"></assemblyIdentity>
+<description>UltraStar Deluxe</description>
+<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+    <security>
+        <requestedPrivileges>
+            <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
+        </requestedPrivileges>
+    </security>
+</trustInfo>
+</assembly>
\ No newline at end of file
diff --git a/songmanagement/res/ultrastardx.rc b/songmanagement/res/ultrastardx.rc
new file mode 100644
index 00000000..7c3dea60
--- /dev/null
+++ b/songmanagement/res/ultrastardx.rc
@@ -0,0 +1,4 @@
+#define MANIFEST_RESOURCE_ID   1
+#define RT_MANIFEST           24
+MANIFEST_RESOURCE_ID    RT_MANIFEST  "..\\res\\ultrastardx.exe.manifest"
+MAINICON                ICON         "..\\icons\\ultrastardx.ico"
diff --git a/songmanagement/res/ultrastardx.res b/songmanagement/res/ultrastardx.res
new file mode 100644
index 00000000..813282ba
Binary files /dev/null and b/songmanagement/res/ultrastardx.res differ
diff --git a/songmanagement/src/.gitignore b/songmanagement/src/.gitignore
new file mode 100644
index 00000000..1c20f512
--- /dev/null
+++ b/songmanagement/src/.gitignore
@@ -0,0 +1,8 @@
+*.cfg
+*.local
+*.bdsproj
+*.identcache
+clean.bat
+config-linux.inc
+paths.inc
+ultrastardx-*.lp[i|s]
diff --git a/songmanagement/src/Makefile.in b/songmanagement/src/Makefile.in
new file mode 100644
index 00000000..6e221af9
--- /dev/null
+++ b/songmanagement/src/Makefile.in
@@ -0,0 +1,252 @@
+#################################################
+# @PACKAGE_STRING@
+# @configure_input@
+#################################################
+
+@SET_MAKE@
+SHELL = /bin/sh
+
+#################################################
+# Standard definitions
+#################################################
+
+prefix      ?= @prefix@
+exec_prefix ?= @exec_prefix@
+datarootdir ?= @datarootdir@
+datadir     ?= @datadir@
+# project root-dir (directory of configure script)
+top_srcdir  ?= @top_srcdir@
+# project src-dir (directory of the current Makefile)
+srcdir      ?= @srcdir@
+
+# file-type suffix of executables (e.g. ".exe" in windows)
+EXEEXT ?= @EXEEXT@
+
+#################################################
+# Tools
+#################################################
+
+# recursive dir creation tool (mkdir -p)
+MKDIR     ?= @MKDIR_P@
+RM        ?= rm -f
+RM_REC    ?= $(RM) -r
+
+#################################################
+# General package configuration
+#################################################
+
+USDX_PACKAGE_NAME := @PACKAGE_NAME@
+USDX_VERSION := @PACKAGE_VERSION@
+USDX_TARNAME := @PACKAGE_TARNAME@
+
+#################################################
+# USDX Paths
+#################################################
+
+USDX_SRC_DIR   := $(top_srcdir)/src
+USDX_GAME_DIR  := $(top_srcdir)/game
+USDX_TOOLS_DIR := $(top_srcdir)/tools
+USDX_BUILD_DIR := $(top_srcdir)/build
+USDX_LIB_DIR   := $(USDX_SRC_DIR)/lib
+
+INSTALL_DATADIR := $(datadir)/$(USDX_PACKAGE_NAME)
+
+#################################################
+# FPC config
+#################################################
+
+# Free Pascal compiler binary
+PPC := @PPC@
+# FPC target platform and processor
+PPLATFORM  := @FPC_PLATFORM@
+PPROCESSOR := @FPC_PROCESSOR@
+
+# Directories added to the unit path
+PUNIT_FLAGS := -Fu.
+
+# Directory where compiled units (.ppu and .o files) are stored
+PCUNIT_DIR   := $(USDX_BUILD_DIR)/fpc-$(PPROCESSOR)-$(PPLATFORM)
+PCUNIT_FLAGS := -FU$(PCUNIT_DIR)
+
+# Directories added to the includes path
+PINC_FLAGS := -Fi$(USDX_LIB_DIR)/JEDI-SDL/SDL/Pas
+
+##
+# PFLAGS
+##
+
+# Defined on debug mode
+ENABLE_DEBUG := @ENABLE_DEBUG@
+
+# Note: 
+#   - PFLAGS/PFLAGS_* defaults to $(PFLAGS_XYZ_DEFAULT) if not set by the user
+#   - if PFLAGS is defined, PFLAGS_* will be ignored on "make all"
+PFLAGS         ?= @PFLAGS@
+PFLAGS_BASE    ?= @PFLAGS_BASE@
+PFLAGS_DEBUG   ?= @PFLAGS_DEBUG@
+PFLAGS_RELEASE ?= @PFLAGS_RELEASE@
+
+# Do not overwrite, just add extra flags
+PFLAGS_EXTRA   += @PFLAGS_EXTRA@
+
+# Default PFLAGS, used if PFLAGS/PFLAGS_* was not set by the user 
+# - Do not use -dDEBUG because it will enable unwanted features
+# - Do not strip executable (-Xs, set by fpc.cfg) to be GNU make conformant
+# - Use DEBUG_MODE instead of DEBUG to avoid enabling the fpc.cfg DEBUG preset
+# - The flag -vB appends the full path to filenames
+# - Note that fpc.cfg already defines -vinw, so add -v0 first
+# - The stack check (-Ct) might not work with enabled threading
+# - Do we need -Coi?
+PFLAGS_BASE_DEFAULT    := -Si -Sg- -Sc- -v0Binwe
+PFLAGS_DEBUG_DEFAULT   := -Xs- -g -gl -dDEBUG_MODE
+PFLAGS_RELEASE_DEFAULT := -Xs- -O2
+PFLAGS_EXTRA_DEFAULT   :=
+
+# Debug/Release mode flags
+# Note that flags will overwrite previously specified flags,
+# e.g. "-vinwe -vi-" is the same as "-vnwe"
+PFLAGS_DEBUG_ALL   := $(PFLAGS_BASE) $(PFLAGS_DEBUG) $(PFLAGS_EXTRA)
+PFLAGS_RELEASE_ALL := $(PFLAGS_BASE) $(PFLAGS_RELEASE) $(PFLAGS_EXTRA)
+
+# Choose default PFLAGS, depending on debug mode.
+# Only used if PFLAGS was not set by the user.
+ifdef ENABLE_DEBUG
+PFLAGS_DEFAULT := $(PFLAGS_DEBUG_ALL)
+else
+PFLAGS_DEFAULT := $(PFLAGS_RELEASE_ALL)
+endif
+
+###
+# linker and library settings
+###
+
+LIBS       ?= @LIBS@
+LDFLAGS    ?= @LDFLAGS@
+linkflags  := -L/usr/lib $(LDFLAGS) $(sort $(LIBS))
+ifneq ($(linkflags),)
+PLINKFLAGS := -k"$(linkflags)"
+endif
+
+PFLAGS_ALL = $(PFLAGS) $(PDEFINES) $(PLINKFLAGS) $(PINC_FLAGS) $(PUNIT_FLAGS) $(PCUNIT_FLAGS)
+
+#################################################
+# USDX project config
+#################################################
+
+# dpr project file used as input
+USDX_PROJ := ultrastardx.dpr
+# name of executable
+USDX_BIN_NAME ?= ultrastardx$(EXEEXT)
+USDX_BIN := $(USDX_GAME_DIR)/$(USDX_BIN_NAME)
+
+#################################################
+# ProjectM
+#################################################
+
+PROJECTM_CWRAPPER_DIR := $(USDX_LIB_DIR)/projectM/cwrapper
+PROJECTM_CWRAPPER_LIB := $(PROJECTM_CWRAPPER_DIR)/libprojectM-cwrapper.a
+USE_PROJECTM_CWRAPPER := @USE_PROJECTM_CWRAPPER@
+
+#################################################
+# Static libs
+#################################################
+
+STATIC_LIBS := 
+ifeq ($(USE_PROJECTM_CWRAPPER), yes)
+STATIC_LIBS += $(PROJECTM_CWRAPPER_LIB)
+endif
+
+#################################################
+# general targets
+#################################################
+
+.PHONY: all
+all: build
+
+# One shot debug build (always rebuild)
+# Note: we cannot set PFLAGS and call build directly, 
+#  as target specific flags are not passed at recursive
+#  make calls. So call debug-build first.
+.PHONY: debug debug-build
+debug: clean_obj
+	$(MAKE) debug-build
+
+debug-build: PFLAGS := $(PFLAGS_DEBUG_ALL)
+debug-build: build
+
+# One shot release build (always rebuild)
+# Note: we cannot set PFLAGS and call build directly, 
+#  as target specific flags are not passed at recursive
+#  make calls. So call release-build first.
+.PHONY: release release-build
+release: clean_obj
+	$(MAKE) release-build
+
+release-build: PFLAGS := $(PFLAGS_RELEASE_ALL)
+release-build: build
+
+# Always rebuild, even if no file changed.
+.PHONY: rebuild
+rebuild: clean_obj
+	$(MAKE) build
+
+# Build if files changed. Always clean old data before compiling.
+# FPC does not reliably recognize changes, neither in .pas, 
+# .inc-files nor static libs (.a/.o). This might result in corrupted 
+# builds and renders debugging difficult (because FPC uses outdated
+# .ppu/.o data of files that have been changed).
+.PHONY: build
+build: $(USDX_BIN)
+
+#################################################
+# build
+#################################################
+
+SRC_FILES = $(shell find $(srcdir) -name "*.inc" -o -name "*.pas" -o -name "*.pp")
+
+# To conform to the GNU Coding Standards, INSTALL_DATADIR is
+# not hardcoded so $prefix and $datadir can be changed at any
+# execution of this Makefile. 
+# Paths cannot be passed to fpc via -d as with gcc's -D parameter.
+# We use an intermediate file instead.
+#
+# See [info autoconf], "19.5 How Do I `#define' Installation Directories?"
+#
+# Do NOT use paths.inc as target name as it is in the requisite list
+# of $(USDX_BIN).
+.PHONY: create-pathinfo
+create-pathinfo:
+	echo "INSTALL_DATADIR = '$(INSTALL_DATADIR)';" > paths.inc
+
+# check if any src-file changed and rebuild
+$(USDX_BIN): $(USDX_PROJ) $(STATIC_LIBS) $(SRC_FILES)
+	@echo "==================================="
+	@echo "Changed files:"
+	@echo "$?"
+	@echo "==================================="
+	@echo "-----------------------------------"
+	@echo "Clean old object data..."
+
+	$(MAKE) clean_obj
+
+	@echo "-----------------------------------"
+
+	$(MKDIR) "$(PCUNIT_DIR)"
+	$(MAKE) create-pathinfo
+	$(PPC) $(strip $(PFLAGS_ALL)) -o$@ $(USDX_PROJ)
+
+#################################################
+# clean-up
+#################################################
+
+.PHONY: clean
+clean: clean_obj
+	$(RM) paths.inc
+
+.PHONY: clean_obj
+clean_obj: clean_bin
+	$(RM_REC) "$(PCUNIT_DIR)"
+
+.PHONY: clean_bin
+clean_bin:
+	$(RM) "$(USDX_BIN)"
diff --git a/songmanagement/src/base/TextGL.pas b/songmanagement/src/base/TextGL.pas
new file mode 100644
index 00000000..feca0974
--- /dev/null
+++ b/songmanagement/src/base/TextGL.pas
@@ -0,0 +1,267 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit TextGL;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  gl,
+  glext,
+  SDL,
+  Classes,
+  UTexture,
+  UFont,
+  UPath,
+  ULog;
+
+type
+  PGLFont = ^TGLFont;
+  TGLFont = record
+    Font:     TScalableFont;
+    Outlined: boolean;
+    X, Y, Z:  real;
+  end;
+
+const
+  ftNormal   = 0;
+  ftBold     = 1;
+  ftOutline1 = 2;
+  ftOutline2 = 3;
+
+var
+  Fonts:   array of TGLFont;
+  ActFont: integer;
+
+procedure BuildFonts;                         // builds all fonts
+procedure KillFonts;                          // deletes all font
+function  glTextWidth(const text: UTF8String): real; // returns text width
+procedure glPrint(const text: UTF8String);    // custom GL "Print" routine
+procedure ResetFont();                        // reset font settings of active font
+procedure SetFontPos(X, Y: real);             // sets X and Y
+procedure SetFontZ(Z: real);                  // sets Z
+procedure SetFontSize(Size: real);
+procedure SetFontStyle(Style: integer);       // sets active font style (normal, bold, etc)
+procedure SetFontItalic(Enable: boolean);     // sets italic type letter (works for all fonts)
+procedure SetFontReflection(Enable:boolean;Spacing: real); // enables/disables text reflection
+
+implementation
+
+uses
+  UTextEncoding,
+  SysUtils,
+  IniFiles,
+  UCommon,
+  UMain,
+  UPathUtils;
+
+{**
+ * Returns either Filename if it is absolute or a path relative to FontPath.
+ *}
+function FindFontFile(const Filename: string): IPath;
+begin
+  Result := FontPath.Append(Filename);
+  // if path does not exist, try as an absolute path
+  if (not Result.IsFile) then
+    Result := Path(Filename);
+end;
+
+procedure AddFontFallbacks(FontIni: TMemIniFile; Font: TFont);
+var
+  FallbackFont: IPath;
+  IdentName: string;
+  I: Integer;
+begin
+  // evaluate the ini-file's 'Fallbacks' section
+  for I := 1 to 10 do
+  begin
+    IdentName := 'File' + IntToStr(I);
+    FallbackFont := FindFontFile(FontIni.ReadString('Fallbacks', IdentName, ''));
+    if (FallbackFont.Equals(PATH_NONE)) then
+      Continue;
+    try
+      Font.AddFallback(FallbackFont);
+    except
+      on E: EFontError do
+        Log.LogError('Setting font fallback ''' + FallbackFont.ToNative() + ''' failed: ' + E.Message);
+    end;
+  end;
+end;
+
+const
+  FONT_NAMES: array [0..3] of string = (
+    'Normal', 'Bold', 'Outline1', 'Outline2'
+  );
+
+procedure BuildFonts;
+var
+  I: integer;
+  FontIni: TMemIniFile;
+  FontFile: IPath;
+  Outline: single;
+  Embolden: single;
+  OutlineFont: TFTScalableOutlineFont;
+  SectionName: string;
+begin
+  ActFont := 0;
+
+  SetLength(Fonts, Length(FONT_NAMES));
+
+  FontIni := TMemIniFile.Create(FontPath.Append('fonts.ini').ToNative);
+
+  try
+    for I := 0 to High(FONT_NAMES) do
+    begin
+      SectionName := 'Font_'+FONT_NAMES[I];
+
+      FontFile := FindFontFile(FontIni.ReadString(SectionName , 'File', ''));
+
+      // create either outlined or normal font
+      Outline := FontIni.ReadFloat(SectionName, 'Outline', 0.0);
+      if (Outline > 0.0) then
+      begin
+        // outlined font
+        OutlineFont := TFTScalableOutlineFont.Create(FontFile, 64, Outline, True, True);
+        OutlineFont.SetOutlineColor(
+          FontIni.ReadFloat(SectionName, 'OutlineColorR',  0.0),
+          FontIni.ReadFloat(SectionName, 'OutlineColorG',  0.0),
+          FontIni.ReadFloat(SectionName, 'OutlineColorB',  0.0),
+          FontIni.ReadFloat(SectionName, 'OutlineColorA', -1.0)
+        );
+        Fonts[I].Font := OutlineFont;
+        Fonts[I].Outlined := true;
+      end
+      else
+      begin
+        // normal font
+        Embolden := FontIni.ReadFloat(SectionName, 'Embolden', 0.0);
+        Fonts[I].Font := TFTScalableFont.Create(FontFile, 64, Embolden, True, True);
+        Fonts[I].Outlined := false;
+      end;
+
+      Fonts[I].Font.GlyphSpacing := FontIni.ReadFloat(SectionName, 'GlyphSpacing', 0.0);
+      Fonts[I].Font.Stretch := FontIni.ReadFloat(SectionName, 'Stretch', 1.0);
+
+      AddFontFallbacks(FontIni, Fonts[I].Font);
+    end;
+  except
+    on E: EFontError do
+      Log.LogCritical(E.Message, 'BuildFont');
+  end;
+
+  // close ini-file
+  FontIni.Free;
+end;
+
+
+// Deletes the font
+procedure KillFonts;
+var
+  I: integer;
+begin
+  for I := 0 to High(Fonts) do
+    Fonts[I].Font.Free;
+end;
+
+function glTextWidth(const text: UTF8String): real;
+var
+  Bounds: TBoundsDbl;
+begin
+  Bounds := Fonts[ActFont].Font.BBox(Text, true);
+  Result := Bounds.Right - Bounds.Left;
+end;
+
+// Custom GL "Print" Routine
+procedure glPrint(const Text: UTF8String);
+var
+  GLFont: PGLFont;
+begin
+  // if there is no text do nothing
+  if (Text = '') then
+    Exit;
+
+  GLFont := @Fonts[ActFont];
+
+  glPushMatrix();
+    // set font position
+    glTranslatef(GLFont.X, GLFont.Y + GLFont.Font.Ascender, GLFont.Z);
+    // draw string
+    GLFont.Font.Print(Text);
+  glPopMatrix();
+end;
+
+procedure ResetFont();
+begin
+  SetFontPos(0, 0);
+  SetFontZ(0);
+  SetFontItalic(False);
+  SetFontReflection(False, 0);
+end;
+
+procedure SetFontPos(X, Y: real);
+begin
+  Fonts[ActFont].X := X;
+  Fonts[ActFont].Y := Y;
+end;
+
+procedure SetFontZ(Z: real);
+begin
+  Fonts[ActFont].Z := Z;
+end;
+
+procedure SetFontSize(Size: real);
+begin
+  Fonts[ActFont].Font.Height := Size;
+end;
+
+procedure SetFontStyle(Style: integer);
+begin
+  ActFont := Style;
+end;
+
+procedure SetFontItalic(Enable: boolean);
+begin
+  if (Enable) then
+    Fonts[ActFont].Font.Style := Fonts[ActFont].Font.Style + [Italic]
+  else
+    Fonts[ActFont].Font.Style := Fonts[ActFont].Font.Style - [Italic]
+end;
+
+procedure SetFontReflection(Enable: boolean; Spacing: real);
+begin
+  if (Enable) then
+    Fonts[ActFont].Font.Style := Fonts[ActFont].Font.Style + [Reflect]
+  else
+    Fonts[ActFont].Font.Style := Fonts[ActFont].Font.Style - [Reflect];
+  Fonts[ActFont].Font.ReflectionSpacing := Spacing - Fonts[ActFont].Font.Descender;
+end;
+
+end.
diff --git a/songmanagement/src/base/UBeatTimer.pas b/songmanagement/src/base/UBeatTimer.pas
new file mode 100644
index 00000000..bc03de76
--- /dev/null
+++ b/songmanagement/src/base/UBeatTimer.pas
@@ -0,0 +1,299 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UBeatTimer;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UTime;
+
+type
+  (**
+   * TLyricsState contains all information concerning the
+   * state of the lyrics, e.g. the current beat or duration of the lyrics.
+   *)
+  TLyricsState = class
+    private
+      fTimer:        TRelativeTimer; // keeps track of the current time
+      fSyncSource:   TSyncSource;
+      fAvgSyncDiff:  real;
+      fLastClock:    real;       // last master clock value
+      // Note: do not use Timer.GetState() to check if lyrics are paused as
+      // Timer.Pause() is used for synching.
+      fPaused:       boolean;
+
+      function Synchronize(LyricTime: real): real;
+    public
+      OldBeat:      integer;    // previous discovered beat
+      CurrentBeat:  integer;    // current beat (rounded)
+      MidBeat:      real;       // current beat (float)
+
+      // now we use this for super synchronization!
+      // only used when analyzing voice
+      // TODO: change ...D to ...Detect(ed)
+      OldBeatD:     integer;    // previous discovered beat
+      CurrentBeatD: integer;    // current discovered beat (rounded)
+      MidBeatD:     real;       // current discovered beat (float)
+
+      // we use this for audible clicks
+      // TODO: Change ...C to ...Click
+      OldBeatC:     integer;    // previous discovered beat
+      CurrentBeatC: integer;
+      MidBeatC:     real;       // like CurrentBeatC
+
+      OldLine:      integer;    // previous displayed sentence
+
+      StartTime:    real;       // time till start of lyrics (= Gap)
+      TotalTime:    real;       // total song time
+
+      constructor Create();
+
+      {**
+       * Resets the LyricsState state.
+       *}
+      procedure Reset();
+
+      procedure UpdateBeats();
+
+      {**
+       * Sets a master clock for this LyricsState. If no sync-source is set
+       * or SyncSource is nil the internal timer is used.
+       *}
+      procedure SetSyncSource(SyncSource: TSyncSource);
+
+      {**
+       * Starts the timer. This is either done
+       * - immediately if WaitForTrigger is false or
+       * - after the first call to GetCurrentTime()/SetCurrentTime() or Start(false)
+       *}
+      procedure Start(WaitForTrigger: boolean = false);
+
+      {**
+       * Pauses the timer.
+       * The counter is preserved and can be resumed by a call to Start().
+       *}
+      procedure Pause();
+
+      {**
+       * Stops the timer.
+       * The counter is reset to 0.
+       *}
+      procedure Stop();
+
+      (**
+       * Returns/Sets the current song time (in seconds) used as base-timer for lyrics etc.
+       * If GetCurrentTime()/SetCurrentTime() if Start() was called
+       *)
+      function GetCurrentTime(): real;
+      procedure SetCurrentTime(Time: real);
+  end;
+
+implementation
+
+uses
+  UNote,
+  ULog,
+  SysUtils,
+  Math;
+
+
+constructor TLyricsState.Create();
+begin
+  // create a triggered timer, so we can Pause() it, set the time
+  // and Resume() it afterwards for better synching.
+  fTimer := TRelativeTimer.Create();
+
+  // reset state
+  Reset();
+end;
+
+procedure TLyricsState.Pause();
+begin
+  fTimer.Pause();
+  fPaused := true;
+end;
+
+procedure TLyricsState.Start(WaitForTrigger: boolean);
+begin
+  fTimer.Start(WaitForTrigger);
+  fPaused := false;
+  fLastClock := -1;
+  fAvgSyncDiff := -1;
+end;
+
+procedure TLyricsState.Stop();
+begin
+  fTimer.Stop();
+  fPaused := false;
+end;
+
+procedure TLyricsState.SetCurrentTime(Time: real);
+begin
+  fTimer.SetTime(Time);
+  fLastClock := -1;
+  fAvgSyncDiff := -1;
+end;
+
+{.$DEFINE LOG_SYNC}
+
+function TLyricsState.Synchronize(LyricTime: real): real;
+var
+  MasterClock: real;
+  TimeDiff: real;
+const
+  AVG_HISTORY_FACTOR = 0.7;
+  PAUSE_THRESHOLD = 0.010; // 10ms
+  FORWARD_THRESHOLD = 0.010; // 10ms
+begin
+  MasterClock := fSyncSource.GetClock();
+  Result := LyricTime;
+
+  // do not sync if lyrics are paused externally or if the timestamp is old
+  if (fPaused or (MasterClock = fLastClock)) then
+    Exit;
+
+  // calculate average time difference (some sort of weighted mean).
+  // The bigger AVG_HISTORY_FACTOR is, the smoother is the average diff.
+  // This is done as some timestamps might be wrong or even lower
+  // than their predecessor.
+  TimeDiff := MasterClock - LyricTime;
+  if (fAvgSyncDiff = -1) then
+    fAvgSyncDiff := TimeDiff
+  else
+    fAvgSyncDiff := TimeDiff * (1-AVG_HISTORY_FACTOR) +
+                    fAvgSyncDiff * AVG_HISTORY_FACTOR;
+
+  {$IFDEF LOG_SYNC}
+  //Log.LogError(Format('TimeDiff: %.3f', [TimeDiff]));
+  {$ENDIF}
+
+  // do not go backwards in time as this could mess up the score
+  if (fAvgSyncDiff > FORWARD_THRESHOLD) then
+  begin
+    {$IFDEF LOG_SYNC}
+    Log.LogError('Sync: ' + floatToStr(MasterClock) + ' > ' + floatToStr(LyricTime));
+    {$ENDIF}
+
+    Result := LyricTime + fAvgSyncDiff;
+    fTimer.SetTime(Result);
+    fTimer.Start();
+    fAvgSyncDiff := -1;
+  end
+  else if (fAvgSyncDiff < -PAUSE_THRESHOLD) then
+  begin
+    // wait until timer and master clock are in sync (> 10ms)
+    fTimer.Pause();
+
+    {$IFDEF LOG_SYNC}
+    Log.LogError('Pause: ' + floatToStr(MasterClock) + ' < ' + floatToStr(LyricTime));
+    {$ENDIF}
+  end
+  else if (fTimer.GetState = rtsPaused) and (fAvgSyncDiff >= 0) then
+  begin
+    fTimer.Start();
+
+    {$IFDEF LOG_SYNC}
+    Log.LogError('Unpause: ' + floatToStr(LyricTime));
+    {$ENDIF}
+  end;
+  fLastClock := MasterClock;
+end;
+
+function TLyricsState.GetCurrentTime(): real;
+var
+  LyricTime: real;
+begin
+  LyricTime := fTimer.GetTime();
+  if Assigned(fSyncSource) then
+    Result := Synchronize(LyricTime)
+  else
+    Result := LyricTime;
+end;
+
+procedure TLyricsState.SetSyncSource(SyncSource: TSyncSource);
+begin
+  fSyncSource := SyncSource;
+end;
+
+(**
+ * Resets the timer and state of the lyrics.
+ * The timer will be stopped afterwards so you have to call Resume()
+ * to start the lyrics timer. 
+ *)
+procedure TLyricsState.Reset();
+begin
+  Stop();
+  fPaused := false;
+
+  fSyncSource := nil;
+
+  StartTime := 0;
+  TotalTime := 0;
+
+  OldBeat      := -1;
+  MidBeat      := -1;
+  CurrentBeat  := -1;
+
+  OldBeatC     := -1;
+  MidBeatC     := -1;
+  CurrentBeatC := -1;
+
+  OldBeatD     := -1;
+  MidBeatD     := -1;
+  CurrentBeatD := -1;
+end;
+
+(**
+ * Updates the beat information (CurrentBeat/MidBeat/...) according to the
+ * current lyric time.
+ *)
+procedure TLyricsState.UpdateBeats();
+var
+  CurLyricsTime: real;
+begin
+  CurLyricsTime := GetCurrentTime();
+
+  OldBeat := CurrentBeat;
+  MidBeat := GetMidBeat(CurLyricsTime - StartTime / 1000);
+  CurrentBeat := Floor(MidBeat);
+
+  OldBeatC := CurrentBeatC;
+  MidBeatC := GetMidBeat(CurLyricsTime - StartTime / 1000);
+  CurrentBeatC := Floor(MidBeatC);
+
+  OldBeatD := CurrentBeatD;
+  // MidBeatD = MidBeat with additional GAP
+  MidBeatD := -0.5 + GetMidBeat(CurLyricsTime - (StartTime + 120 + 20) / 1000);
+  CurrentBeatD := Floor(MidBeatD);
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/base/UCatCovers.pas b/songmanagement/src/base/UCatCovers.pas
new file mode 100644
index 00000000..85cb850f
--- /dev/null
+++ b/songmanagement/src/base/UCatCovers.pas
@@ -0,0 +1,211 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UCatCovers;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UIni,
+  UPath;
+
+type
+  TCatCovers = class
+    protected
+      cNames:    array [TSortingType] of array of UTF8String;
+      cFiles:    array [TSortingType] of array of IPath;
+    public
+      constructor Create;
+      procedure Load; //Load Cover aus Cover.ini and Cover Folder
+      procedure LoadPath(const CoversPath: IPath);
+      procedure Add(Sorting: TSortingType; const Name: UTF8String; const Filename: IPath); //Add a Cover
+      function  CoverExists(Sorting: TSortingType; const Name: UTF8String): boolean; //Returns True when a cover with the given Name exists
+      function  GetCover(Sorting: TSortingType; const Name: UTF8String): IPath; //Returns the Filename of a Cover
+  end;
+
+var
+  CatCovers: TCatCovers;
+
+implementation
+
+uses
+  IniFiles,
+  SysUtils,
+  Classes,
+  UFilesystem,
+  ULog,
+  UMain,
+  UUnicodeUtils,
+  UPathUtils;
+
+constructor TCatCovers.Create;
+begin
+  inherited;
+  Load;
+end;
+
+procedure TCatCovers.Load;
+var
+  I: integer;
+begin
+  for I := 0 to CoverPaths.Count-1 do
+    LoadPath(CoverPaths[I] as IPath);
+end;
+
+(**
+ * Load Cover from Cover.ini and Cover Folder
+ *)
+procedure TCatCovers.LoadPath(const CoversPath: IPath);
+var
+  Ini: TMemIniFile;
+  List: TStringlist;
+  I: Integer;
+  SortType: TSortingType;
+  Filename: IPath;
+  Name, TmpName: UTF8String;
+  CatCover: IPath;
+  Iter: IFileIterator;
+  FileInfo: TFileInfo;
+begin
+  Ini := nil;
+  List := nil;
+
+  try
+    Ini  := TMemIniFile.Create(CoversPath.Append('covers.ini').ToNative);
+    List := TStringlist.Create;
+
+    //Add every Cover in Covers Ini for Every Sorting option
+    for SortType := Low(TSortingType) to High(TSortingType) do
+    begin
+      Ini.ReadSection(ISorting[Ord(SortType)], List);
+
+      for I := 0 to List.Count - 1 do
+      begin
+        CatCover := Path(Ini.ReadString(ISorting[Ord(SortType)], List.Strings[I], 'NoCover.jpg'));
+        Add(SortType, List.Strings[I], CoversPath.Append(CatCover));
+      end;
+    end;
+  finally
+    Ini.Free;
+    List.Free;
+  end;
+
+  //Add Covers from Folder
+  Iter := FileSystem.FileFind(CoversPath.Append('*.jpg'), 0);
+  while Iter.HasNext do
+  begin
+    FileInfo := Iter.Next;
+
+    //Add Cover if it doesn't exist for every Section
+    Filename := CoversPath.Append(FileInfo.Name);
+    Name := FileInfo.Name.SetExtension('').ToUTF8;
+
+    for SortType := Low(TSortingType) to High(TSortingType) do
+    begin
+      TmpName := Name;
+      if (SortType = sTitle) and (UTF8Pos('Title', TmpName) <> 0) then
+        UTF8Delete(TmpName, UTF8Pos('Title', TmpName), 5)
+      else if (SortType = sArtist) and (UTF8Pos('Artist', TmpName) <> 0) then
+        UTF8Delete(TmpName, UTF8Pos('Artist', TmpName), 6);
+
+      if not CoverExists(SortType, TmpName) then
+        Add(SortType, TmpName, Filename);
+    end;
+  end;
+end;
+
+  //Add a Cover
+procedure TCatCovers.Add(Sorting: TSortingType; const Name: UTF8String; const Filename: IPath);
+begin
+  if Filename.IsFile then //If Exists -> Add
+  begin
+    SetLength(CNames[Sorting], Length(CNames[Sorting]) + 1);
+    SetLength(CFiles[Sorting], Length(CNames[Sorting]) + 1);
+
+    CNames[Sorting][high(cNames[Sorting])] := UTF8Uppercase(Name);
+    CFiles[Sorting][high(cNames[Sorting])] := FileName;
+  end;
+end;
+
+  //Returns True when a cover with the given Name exists
+function TCatCovers.CoverExists(Sorting: TSortingType; const Name: UTF8String): boolean;
+var
+  I: Integer;
+  UpperName: UTF8String;
+begin
+  Result := False;
+  UpperName := UTF8Uppercase(Name); //Case Insensitiv
+
+  for I := 0 to high(cNames[Sorting]) do
+  begin
+    if (cNames[Sorting][I] = UpperName) then //Found Name
+    begin
+      Result := true;
+      break; //Break For Loop
+    end;
+  end;
+end;
+
+  //Returns the Filename of a Cover
+function TCatCovers.GetCover(Sorting: TSortingType; const Name: UTF8String): IPath;
+var
+  I: Integer;
+  UpperName: UTF8String;
+  NoCoverPath: IPath;
+begin
+  Result := PATH_NONE;
+  UpperName := UTF8Uppercase(Name);
+
+  for I := 0 to high(cNames[Sorting]) do
+  begin
+    if cNames[Sorting][I] = UpperName then
+    begin
+      Result := cFiles[Sorting][I];
+      Break;
+    end;
+  end;
+
+  //No Cover
+  if (Result.IsUnset) then
+  begin
+    for I := 0 to CoverPaths.Count-1 do
+    begin
+      NoCoverPath := (CoverPaths[I] as IPath).Append('NoCover.jpg');
+      if (NoCoverPath.IsFile) then
+      begin
+        Result := NoCoverPath;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/base/UCommandLine.pas b/songmanagement/src/base/UCommandLine.pas
new file mode 100644
index 00000000..ac0db2c2
--- /dev/null
+++ b/songmanagement/src/base/UCommandLine.pas
@@ -0,0 +1,345 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UCommandLine;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UPath;
+
+type
+  TScreenMode = (scmDefault, scmFullscreen, scmWindowed);
+
+  {**
+   * Reads infos from ParamStr and set some easy interface variables
+   *}
+  TCMDParams = class
+    private
+      fLanguage:   string;
+      fResolution: string;
+
+      procedure ShowHelp();
+
+      procedure ReadParamInfo;
+      procedure ResetVariables;
+
+      function GetLanguage:   integer;
+      function GetResolution: integer;
+    public
+      // some boolean variables set when reading infos
+      Debug:      boolean;
+      Benchmark:  boolean;
+      NoLog:      boolean;
+      ScreenMode: TScreenMode;
+      Joypad:     boolean;
+
+      // some value variables set when reading infos {-1: Not Set, others: Value}
+      Depth:      integer;
+      Screens:    integer;
+
+      // some strings set when reading infos {Length=0: Not Set}
+      SongPath:   IPath;
+      ConfigFile: IPath;
+      ScoreFile:  IPath;
+
+      // pseudo integer values
+      property Language:      integer read GetLanguage;
+      property Resolution:    integer read GetResolution;
+
+      // some procedures for reading infos
+      constructor Create;
+  end;
+
+var
+  Params:    TCMDParams;
+  
+const
+  cHelp            = 'help';
+  cDebug           = 'debug';
+  cMediaInterfaces = 'showinterfaces';
+
+
+implementation
+
+uses SysUtils,
+     UPlatform;
+
+{**
+ * Resets variables and reads info
+ *}
+constructor TCMDParams.Create;
+begin
+  inherited;
+  
+  if FindCmdLineSwitch( cHelp ) or FindCmdLineSwitch( 'h' ) then
+    ShowHelp();
+
+  ResetVariables;
+  ReadParamInfo;
+end;
+
+procedure TCMDParams.ShowHelp();
+
+  function Fmt(aString : string) : string;
+  begin
+    Result := Format('%-15s', [aString]);
+  end;
+
+begin
+  writeln;
+  writeln('**************************************************************');
+  writeln('  UltraStar Deluxe - Command line switches                    ');
+  writeln('**************************************************************');
+  writeln;
+  writeln('  '+ Fmt('Switch') +' : Purpose');
+  writeln('  ----------------------------------------------------------');
+  writeln('  '+ Fmt(cMediaInterfaces) +' : Show in-use media interfaces');
+  writeln('  '+ Fmt(cDebug) +' : Display Debugging info');
+  writeln;
+
+  platform.halt;
+end;
+
+{**
+ * Reset Class Variables
+ *}
+procedure TCMDParams.ResetVariables;
+begin
+  Debug       := False;
+  Benchmark   := False;
+  NoLog       := False;
+  ScreenMode  := scmDefault;
+  Joypad      := False;
+
+  // some value variables set when reading infos {-1: Not Set, others: Value}
+  fResolution := '';
+  fLanguage   := '';
+  Depth       := -1;
+  Screens     := -1;
+
+  // some strings set when reading infos {Length=0 Not Set}
+  SongPath    := PATH_NONE;
+  ConfigFile  := PATH_NONE;
+  ScoreFile   := PATH_NONE;
+end;
+
+{**
+ * Read command-line parameters
+ *}
+procedure TCMDParams.ReadParamInfo;
+var
+  I:        integer;
+  PCount:   integer;
+  Command:  string;
+begin
+  PCount := ParamCount;
+  //Log.LogError('ParamCount: ' + Inttostr(PCount));
+  
+  // check all parameters
+  for I := 1 to PCount do
+  begin
+    Command := ParamStr(I);
+    // check if the string is a parameter
+    if (Length(Command) > 1) and (Command[1] = '-') then
+    begin
+      // remove '-' from command
+      Command := LowerCase(Trim(Copy(Command, 2, Length(Command) - 1)));
+      //Log.LogError('Command prepared: ' + Command);
+
+      // check command
+
+      // boolean triggers
+      if (Command = 'debug') then
+        Debug       := True
+      else if (Command = 'benchmark') then
+        Benchmark   := True
+      else if (Command = 'nolog') then
+        NoLog       := True
+      else if (Command = 'fullscreen') then
+        ScreenMode  := scmFullscreen
+      else if (Command = 'window') then
+        ScreenMode  := scmWindowed
+      else if (Command = 'joypad') then
+        Joypad    := True
+
+      // integer variables
+      else if (Command = 'depth') then
+      begin
+        // check if there is another Parameter to get the Value from
+        if (PCount > I) then
+        begin
+          Command := ParamStr(I + 1);
+
+          // check for valid value
+          // FIXME: guessing an array-index of depth is very error prone.  
+          If (Command = '16') then
+            Depth := 0
+          Else If (Command = '32') then
+            Depth := 1;
+        end;
+      end
+
+      else if (Command = 'screens') then
+      begin
+        // check if there is another parameter to get the value from
+        if (PCount > I) then
+        begin
+          Command := ParamStr(I + 1);
+
+          // check for valid value
+          If (Command = '1') then
+            Screens := 0
+          Else If (Command = '2') then
+            Screens := 1;
+        end;
+      end
+
+      // pseudo integer values
+      else if (Command = 'language') then
+      begin
+        // check if there is another parameter to get the value from
+        if (PCount > I) then
+        begin
+          // write value to string
+          fLanguage := Lowercase(ParamStr(I + 1));
+        end;
+      end
+
+      else if (Command = 'resolution') then
+      begin
+        // check if there is another parameter to get the value from
+        if (PCount > I) then
+        begin
+          // write value to string
+          fResolution := Lowercase(ParamStr(I + 1));
+        end;
+      end
+
+      // string values
+      else if (Command = 'songpath') then
+      begin
+        // check if there is another parameter to get the value from
+        if (PCount > I) then
+        begin
+          // write value to string
+          SongPath := Path(ParamStr(I + 1));
+        end;
+      end
+
+      else if (Command = 'configfile') then
+      begin
+        // check if there is another parameter to get the value from
+        if (PCount > I) then
+        begin
+          // write value to string
+          ConfigFile := Path(ParamStr(I + 1));
+
+          // is this a relative path -> then add gamepath
+          if (not ConfigFile.IsAbsolute) then
+            ConfigFile := Platform.GetExecutionDir().Append(ConfigFile);
+        end;
+      end
+
+      else if (Command = 'scorefile') then
+      begin
+        // check if there is another parameter to get the value from
+        if (PCount > I) then
+        begin
+          // write value to string
+          ScoreFile := Path(ParamStr(I + 1));
+        end;
+      end;
+
+    end;
+
+  end;
+
+{
+  Log.LogInfo('Screens: ' + Inttostr(Screens));
+  Log.LogInfo('Depth: ' + Inttostr(Depth));
+
+  Log.LogInfo('Resolution: ' + Inttostr(Resolution));
+  Log.LogInfo('Resolution: ' + Inttostr(Language));
+
+  Log.LogInfo('sResolution: ' + sResolution);
+  Log.LogInfo('sLanguage: ' + sLanguage);
+
+  Log.LogInfo('ConfigFile: ' + ConfigFile);
+  Log.LogInfo('SongPath: ' + SongPath);
+  Log.LogInfo('ScoreFile: ' + ScoreFile);
+}
+
+end;
+
+//-------------
+// GetLanguage - Get Language ID from saved String Information
+//-------------
+function TCMDParams.GetLanguage: integer;
+{var
+  I: integer;
+}
+begin
+  Result := -1;
+{*  JB - 12sep07 to remove uINI dependency
+
+  //Search for Language
+  For I := 0 to high(ILanguage) do
+    if (LowerCase(ILanguage[I]) = sLanguage) then
+    begin
+      Result := I;
+      Break;
+    end;
+*}
+end;
+
+//-------------
+// GetResolution - Get Resolution ID from saved String Information
+//-------------
+function TCMDParams.GetResolution: integer;
+{var
+  I: integer;
+}
+begin
+  Result := -1;
+{*  JB - 12sep07 to remove uINI dependency
+
+  //Search for Resolution
+  For I := 0 to high(IResolution) do
+    if (LowerCase(IResolution[I]) = sResolution) then
+    begin
+      Result := I;
+      Break;
+    end;
+*}
+end;
+
+end.
diff --git a/songmanagement/src/base/UCommon.pas b/songmanagement/src/base/UCommon.pas
new file mode 100644
index 00000000..18022337
--- /dev/null
+++ b/songmanagement/src/base/UCommon.pas
@@ -0,0 +1,609 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UCommon;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  Classes,
+  {$IFDEF MSWINDOWS}
+  Windows,
+  {$ENDIF}
+  UConfig,
+  ULog,
+  UPath;
+
+type
+  TStringDynArray = array of string;
+  TUTF8StringDynArray = array of UTF8String;
+
+const
+  SepWhitespace = [#9, #10, #13, ' ']; // tab, lf, cr, space
+
+{**
+ * Splits a string into pieces separated by Separators.
+ * MaxCount specifies the max. number of pieces. If it is <= 0 the number is
+ * not limited. If > 0 the last array element will hold the rest of the string
+ * (with leading separators removed).
+ *
+ * Examples:
+ *   SplitString(' split  me now ', 0) -> ['split', 'me', 'now']
+ *   SplitString(' split  me now ', 1) -> ['split', 'me now']
+ *}
+function SplitString(const Str: string; MaxCount: integer = 0; Separators: TSysCharSet = SepWhitespace): TStringDynArray;
+
+
+type
+  TMessageType = (mtInfo, mtError);
+
+procedure ShowMessage(const msg: string; msgType: TMessageType = mtInfo);
+
+procedure ConsoleWriteLn(const msg: string);
+
+{$IFDEF FPC}
+function RandomRange(aMin: integer; aMax: integer): integer;
+{$ENDIF}
+
+procedure DisableFloatingPointExceptions();
+procedure SetDefaultNumericLocale();
+procedure RestoreNumericLocale();
+
+{$IFNDEF MSWINDOWS}
+procedure ZeroMemory(Destination: pointer; Length: dword);
+function MakeLong(a, b: word): longint;
+{$ENDIF}
+
+// A stable alternative to TList.Sort() (use TList.Sort() if applicable, see below)
+procedure MergeSort(List: TList; CompareFunc: TListSortCompare);
+
+function GetAlignedMem(Size: cardinal; Alignment: integer): pointer;
+procedure FreeAlignedMem(P: pointer);
+
+function GetArrayIndex(const SearchArray: array of UTF8String; Value: string; CaseInsensitiv: boolean = false): integer;
+
+
+implementation
+
+uses
+  Math,
+  {$IFDEF Delphi}
+  Dialogs,
+  {$ENDIF}
+  sdl,
+  UFilesystem,
+  UMain,
+  UUnicodeUtils;
+
+function SplitString(const Str: string; MaxCount: integer; Separators: TSysCharSet): TStringDynArray;
+
+  {*
+   * Adds Str[StartPos..Endpos-1] to the result array.
+   *}
+  procedure AddSplit(StartPos, EndPos: integer);
+  begin
+    SetLength(Result, Length(Result)+1);
+    Result[High(Result)] := Copy(Str, StartPos, EndPos-StartPos);
+  end;
+
+var
+  I: integer;
+  Start: integer;
+  Last: integer;
+begin
+  Start := 0;
+  SetLength(Result, 0);
+
+  for I := 1 to Length(Str) do
+  begin
+    if (Str[I] in Separators) then
+    begin
+      // end of component found
+      if (Start > 0) then
+      begin
+        AddSplit(Start, I);
+        Start := 0;
+      end;
+    end
+    else if (Start = 0) then
+    begin
+      // mark beginning of component
+      Start := I;
+      // check if this is the last component
+      if (Length(Result) = MaxCount-1) then
+      begin
+        // find last non-separator char
+        Last := Length(Str);
+        while (Str[Last] in Separators) do
+          Dec(Last);
+        // add component up to last non-separator
+        AddSplit(Start, Last);
+        Exit;
+      end;
+    end;
+  end;
+
+  // last component
+  if (Start > 0) then
+    AddSplit(Start, Length(Str)+1);
+end;
+
+// data used by the ...Locale() functions
+{$IF Defined(Linux) or Defined(FreeBSD)}
+
+var
+  PrevNumLocale: string;
+
+const
+  LC_NUMERIC  = 1;
+
+function setlocale(category: integer; locale: pchar): pchar; cdecl; external 'c' name 'setlocale';
+
+{$IFEND}
+
+// In Linux and maybe MacOSX some units (like cwstring) call setlocale(LC_ALL, '')
+// to set the language/country specific locale (e.g. charset) for this application.
+// Unfortunately, LC_NUMERIC is set by this call too.
+// It defines the decimal-separator and other country-specific numeric settings.
+// This parameter is used by the C string-to-float parsing functions atof() and strtod().
+// After changing LC_NUMERIC some external C-based libs (like projectM) are not
+// able to parse strings correctly
+// (e.g. in Germany "0.9" is not recognized as a valid number anymore but "0,9" is).
+// So we reset the numeric settings to the default ('C').
+// Note: The behaviour of Pascal parsing functions (e.g. strtofloat()) is not
+//   changed by this because it doesn't use the locale-settings.
+// TODO:
+// - Check if this is needed in MacOSX (at least the locale is set in cwstring)
+// - Find out which libs are concerned by this problem.
+//   If only projectM is concerned by this problem set and restore the numeric locale
+//   for each call to projectM instead of changing it globally.
+procedure SetDefaultNumericLocale();
+begin
+  {$IF Defined(LINUX) or Defined(FreeBSD)}
+  PrevNumLocale := setlocale(LC_NUMERIC, nil);
+  setlocale(LC_NUMERIC, 'C');
+  {$IFEND}
+end;
+
+procedure RestoreNumericLocale();
+begin
+  {$IF Defined(LINUX) or Defined(FreeBSD)}
+  setlocale(LC_NUMERIC, PChar(PrevNumLocale));
+  {$IFEND}
+end;
+
+(*
+ * If an invalid floating point operation was performed the Floating-point unit (FPU)
+ * generates a Floating-point exception (FPE). Dependending on the settings in
+ * the FPU's control-register (interrupt mask) the FPE is handled by the FPU itself
+ * (we will call this as "FPE disabled" later on) or is passed to the application
+ * (FPE enabled).
+ * If FPEs are enabled a floating-point division by zero (e.g. 10.0 / 0.0) is
+ * considered an error and an exception is thrown. Otherwise the FPU will handle
+ * the error and return the result infinity (INF) (10.0 / 0.0 = INF) without
+ * throwing an error to the application.
+ * The same applies to a division by INF that either raises an exception
+ * (FPE enabled) or returns 0.0 (FPE disabled).
+ * Normally (as with C-programs), Floating-point exceptions (FPE) are DISABLED
+ * on program startup (at least with Intel CPUs), but for some strange reasons
+ * they are ENABLED in pascal (both delphi and FPC) by default.
+ * Many libs operating with floating-point values rely heavily on the C-specific
+ * behaviour. So using them in delphi is a ticking time-bomb because sooner or
+ * later they will crash because of an FPE (this problem occurs massively
+ * in OpenGL-based libs like projectM). In contrast to this no error will occur
+ * if the lib is linked to a C-program.
+ *
+ * Further info on FPUs:
+ * For x86 and x86_64 CPUs we have to consider two FPU instruction sets.
+ * The math co-processor i387 (aka 8087 or x87) set introduced with the i386
+ * and SSE (Streaming SIMD Extensions) introduced with the Pentium3.
+ * Both of them have separate control-registers (x87: FPUControlWord, SSE: MXCSR)
+ * to control FPEs. Either has (among others) 6bits to enable/disable several
+ * exception types (Invalid,Denormalized,Zero,Overflow,Underflow,Precision).
+ * Those exception-types must all be masked (=1) to get the default C behaviour.
+ * The control-registers can be set with the asm-ops FLDCW (x87) and LDMXCSR (SSE).
+ * Instead of using assembler code, we can use Set8087CW() provided by delphi and
+ * FPC to set the x87 control-word. FPC also provides SetSSECSR() for SSE's MXCSR.
+ * Note that both Delphi and FPC enable FPEs (e.g. for div-by-zero) on program
+ * startup but only FPC enables FPEs (especially div-by-zero) for SSE too.
+ * So we have to mask FPEs for x87  in Delphi and FPC and for SSE in FPC only.
+ * FPC and Delphi both provide a SetExceptionMask() for control of the FPE
+ * mask. SetExceptionMask() sets the masks for x87 in Delphi and for x87 and SSE
+ * in FPC (seems as if Delphi [2005] is not SSE aware). So SetExceptionMask()
+ * is what we need and it even is plattform and CPU independent.
+ *
+ * Pascal OpenGL headers (like the Delphi standard ones or JEDI-SDL headers)
+ * already call Set8087CW() to disable FPEs but due to some bugs in the JEDI-SDL
+ * headers they do not work properly with FPC. I already patched them, so they
+ * work at least until they are updated the next time. In addition Set8086CW()
+ * does not suffice to disable FPEs because the SSE FPEs are not disabled by this.
+ * FPEs with SSE are a big problem with some libs because many linux distributions
+ * optimize code for SSE or Pentium3 (for example: int(INF) which convert the
+ * double value "infinity" to an integer might be automatically optimized by
+ * using SSE's CVTSD2SI instruction). So SSE FPEs must be turned off in any case
+ * to make USDX portable.
+ *
+ * Summary:
+ * Call this function on initialization to make sure FPEs are turned off.
+ * It will solve a lot of errors with FPEs in external libs.
+ *)
+procedure DisableFloatingPointExceptions();
+begin
+  (*
+  // We will use SetExceptionMask() instead of Set8087CW()/SetSSECSR().
+  // Note: Leave these lines for documentation purposes just in case
+  //       SetExceptionMask() does not work anymore (due to bugs in FPC etc.).
+  {$IF Defined(CPU386) or Defined(CPUI386) or Defined(CPUX86_64)}
+  Set8087CW($133F);
+  {$IFEND}
+  {$IF Defined(FPC)}
+  if (has_sse_support) then
+    SetSSECSR($1F80);
+  {$IFEND}
+  *)
+  
+  // disable all of the six FPEs (x87 and SSE) to be compatible with C/C++ and
+  // other libs which rely on the standard FPU behaviour (no div-by-zero FPE anymore).
+  SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide,
+                    exOverflow, exUnderflow, exPrecision]);
+end;
+
+{$IFNDEF MSWINDOWS}
+procedure ZeroMemory(Destination: pointer; Length: dword);
+begin
+  FillChar(Destination^, Length, 0);
+end;
+
+function MakeLong(A, B: word): longint;
+begin
+  Result := (LongInt(B) shl 16) + A;
+end;
+
+{$ENDIF}
+
+{$IFDEF FPC}
+function RandomRange(aMin: integer; aMax: integer): integer;
+begin
+  RandomRange := Random(aMax - aMin) + aMin ;
+end;
+{$ENDIF}
+
+
+{$IFDEF FPC}
+var
+  MessageList: TStringList;
+  ConsoleHandler: TThreadID;
+  // Note: TRTLCriticalSection is defined in the units System and Libc, use System one
+  ConsoleCriticalSection: System.TRTLCriticalSection;
+  ConsoleEvent: PRTLEvent;
+  ConsoleQuit: boolean;
+{$ENDIF}
+
+(*
+ * Write to console if one is available.
+ * It checks if a console is available before output so it will not
+ * crash on windows if none is available.
+ * Do not use this function directly because it is not thread-safe,
+ * use ConsoleWriteLn() instead.
+ *)
+procedure _ConsoleWriteLn(const aString: string); {$IFDEF HasInline}inline;{$ENDIF}
+begin
+  {$IFDEF MSWINDOWS}
+  // sanity check to avoid crashes with writeln()
+  if (IsConsole) then
+  begin
+  {$ENDIF}
+    Writeln(aString);
+  {$IFDEF MSWINDOWS}
+  end;
+  {$ENDIF}
+end;
+
+{$IFDEF FPC}
+{*
+ * The console-handlers main-function.
+ * TODO: create a quit-event on closing.
+ *}
+function ConsoleHandlerFunc(param: pointer): PtrInt;
+var
+  i: integer;
+  quit: boolean;
+begin
+  quit := false;
+  while (not quit) do
+  begin
+    // wait for new output or quit-request
+    RTLeventWaitFor(ConsoleEvent);
+
+    System.EnterCriticalSection(ConsoleCriticalSection);
+    // output pending messages
+    for i := 0 to MessageList.Count - 1 do
+    begin
+      _ConsoleWriteLn(MessageList[i]);
+    end;
+    MessageList.Clear();
+
+    // use local quit-variable to avoid accessing
+    // ConsoleQuit outside of the critical section
+    if (ConsoleQuit) then
+      quit := true;
+
+    RTLeventResetEvent(ConsoleEvent);
+    System.LeaveCriticalSection(ConsoleCriticalSection);
+  end;
+  result := 0;
+end;
+{$ENDIF}
+
+procedure InitConsoleOutput();
+begin
+  {$IFDEF FPC}
+  // init thread-safe output
+  MessageList := TStringList.Create();
+  System.InitCriticalSection(ConsoleCriticalSection);
+  ConsoleEvent := RTLEventCreate();
+  ConsoleQuit := false;
+  // must be a thread managed by FPC. Otherwise (e.g. SDL-thread)
+  // it will crash when using Writeln.
+  ConsoleHandler := BeginThread(@ConsoleHandlerFunc);
+  {$ENDIF}
+end;
+
+procedure FinalizeConsoleOutput();
+begin
+  {$IFDEF FPC}
+  // terminate console-handler
+  System.EnterCriticalSection(ConsoleCriticalSection);
+  ConsoleQuit := true;
+  RTLeventSetEvent(ConsoleEvent);
+  System.LeaveCriticalSection(ConsoleCriticalSection);
+  WaitForThreadTerminate(ConsoleHandler, 0);
+  // free data
+  System.DoneCriticalsection(ConsoleCriticalSection);
+  RTLeventDestroy(ConsoleEvent);
+  MessageList.Free();
+  {$ENDIF}
+end;
+
+{*
+ * FPC uses threadvars (TLS) managed by FPC for console output locking.
+ * Using WriteLn() from external threads (like in SDL callbacks)
+ * will crash the program as those threadvars have never been initialized.
+ * The solution is to create an FPC-managed thread which has the TLS data
+ * and use it to handle the console-output (hence it is called Console-Handler)
+ *}
+procedure ConsoleWriteLn(const msg: string);
+begin
+{$IFDEF CONSOLE}
+  {$IFDEF FPC}
+  // TODO: check for the main-thread and use a simple _ConsoleWriteLn() then?
+  //GetCurrentThreadThreadId();
+  System.EnterCriticalSection(ConsoleCriticalSection);
+  MessageList.Add(msg);
+  RTLeventSetEvent(ConsoleEvent);
+  System.LeaveCriticalSection(ConsoleCriticalSection);
+  {$ELSE}
+  _ConsoleWriteLn(msg);
+  {$ENDIF}
+{$ENDIF}
+end;
+
+procedure ShowMessage(const msg: String; msgType: TMessageType);
+{$IFDEF MSWINDOWS}
+var Flags: cardinal;
+{$ENDIF}
+begin
+{$IF Defined(MSWINDOWS)}
+  case msgType of
+    mtInfo:  Flags := MB_ICONINFORMATION or MB_OK;
+    mtError: Flags := MB_ICONERROR or MB_OK;
+    else Flags := MB_OK;
+  end;
+  MessageBox(0, PChar(msg), PChar(USDXVersionStr()), Flags);
+{$ELSE}
+  ConsoleWriteln(msg);
+{$IFEND}
+end;
+
+(*
+ * Recursive part of the MergeSort algorithm.
+ * OutList will be either InList or TempList and will be swapped in each
+ * depth-level of recursion. By doing this it we can directly merge into the
+ * output-list. If we only had In- and OutList parameters we had to merge into
+ * InList after the recursive calls and copy the data to the OutList afterwards.
+ *)
+procedure _MergeSort(InList, TempList, OutList: TList; StartPos, BlockSize: integer;
+                    CompareFunc: TListSortCompare);
+var
+  LeftSize, RightSize: integer; // number of elements in left/right block
+  LeftEnd,  RightEnd:  integer; // Index after last element in left/right block
+  MidPos: integer; // index of first element in right block
+  Pos: integer;    // position in output list
+begin
+  LeftSize := BlockSize div 2;
+  RightSize := BlockSize - LeftSize;
+  MidPos := StartPos + LeftSize;
+
+  // sort left and right halves of this block by recursive calls of this function
+  if (LeftSize >= 2) then
+    _MergeSort(InList, OutList, TempList, StartPos, LeftSize, CompareFunc)
+  else
+    TempList[StartPos] := InList[StartPos];
+  if (RightSize >= 2) then
+    _MergeSort(InList, OutList, TempList, MidPos, RightSize, CompareFunc)
+  else
+    TempList[MidPos] := InList[MidPos];
+
+  // merge sorted left and right sub-lists into output-list 
+  LeftEnd := MidPos;
+  RightEnd := StartPos + BlockSize;
+  Pos := StartPos;
+  while ((StartPos < LeftEnd) and (MidPos < RightEnd)) do
+  begin
+    if (CompareFunc(TempList[StartPos], TempList[MidPos]) <= 0) then
+    begin
+      OutList[Pos] := TempList[StartPos];
+      Inc(StartPos);
+    end
+    else
+    begin
+      OutList[Pos] := TempList[MidPos];
+      Inc(MidPos);
+    end;
+    Inc(Pos);
+  end;
+
+  // copy remaining elements to output-list
+  while (StartPos < LeftEnd) do
+  begin
+    OutList[Pos] := TempList[StartPos];
+    Inc(StartPos);
+    Inc(Pos);
+  end;
+  while (MidPos < RightEnd) do
+  begin
+    OutList[Pos] := TempList[MidPos];
+    Inc(MidPos);
+    Inc(Pos);
+  end;
+end;
+
+(*
+ * Stable alternative to the instable TList.Sort() (uses QuickSort) implementation.
+ * A stable sorting algorithm preserves preordered items. E.g. if sorting by
+ * songs by title first and artist afterwards, the songs of each artist will
+ * be ordered by title. In contrast to this an unstable algorithm (like QuickSort)
+ * may destroy an existing order, so the songs of an artist will not be ordered
+ * by title anymore after sorting by artist in the previous example.
+ * If you do not need a stable algorithm, use TList.Sort() instead.
+ *)
+procedure MergeSort(List: TList; CompareFunc: TListSortCompare);
+var
+  TempList: TList;
+begin
+  TempList := TList.Create();
+  TempList.Count := List.Count;
+  if (List.Count >= 2) then
+    _MergeSort(List, TempList, List, 0, List.Count, CompareFunc);
+  TempList.Free;
+end;
+
+(**
+ * Returns the index of Value in SearchArray
+ * or -1 if Value is not in SearchArray.
+ *)
+function GetArrayIndex(const SearchArray: array of UTF8String; Value: string;
+    CaseInsensitiv: boolean = false): integer;
+var
+  i: integer;
+begin
+  Result := -1;
+
+  for i := 0 to High(SearchArray) do
+  begin
+    if (SearchArray[i] = Value) or
+       (CaseInsensitiv and (CompareText(SearchArray[i], Value) = 0)) then
+    begin
+      Result := i;
+      Break;
+    end;
+  end;
+end;
+
+
+type
+  // stores the unaligned pointer of data allocated by GetAlignedMem()
+  PMemAlignHeader = ^TMemAlignHeader;
+  TMemAlignHeader = pointer;
+
+(**
+ * Use this function to assure that allocated memory is aligned on a specific
+ * byte boundary.
+ * Alignment must be a power of 2.
+ *
+ * Important: Memory allocated with GetAlignedMem() MUST be freed with
+ * FreeAlignedMem(), FreeMem() will cause a segmentation fault.
+ *
+ * Hint: If you do not need dynamic memory, consider to allocate memory
+ * statically and use the {$ALIGN x} compiler directive. Note that delphi
+ * supports an alignment "x" of up to 8 bytes only whereas FPC supports
+ * alignments on 16 and 32 byte boundaries too.
+ *)
+{$WARNINGS OFF}
+function GetAlignedMem(Size: cardinal; Alignment: integer): pointer;
+var
+  OrigPtr: pointer;
+const
+  MIN_ALIGNMENT = 16;
+begin
+  // Delphi and FPC (tested with 2.2.0) align memory blocks allocated with
+  // GetMem() at least on 8 byte boundaries. Delphi uses a minimal alignment
+  // of either 8 or 16 bytes depending on the size of the requested block
+  // (see System.GetMinimumBlockAlignment). As we do not want to change the
+  // boundary for the worse, we align at least on MIN_ALIGN.
+  if (Alignment < MIN_ALIGNMENT) then
+    Alignment := MIN_ALIGNMENT;
+
+  // allocate unaligned memory
+  GetMem(OrigPtr, SizeOf(TMemAlignHeader) + Size + Alignment);
+  if (OrigPtr = nil) then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  // reserve space for the header
+  Result := pointer(PtrUInt(OrigPtr) + SizeOf(TMemAlignHeader));
+  // align memory
+  Result := pointer(PtrUInt(Result) + Alignment - PtrUInt(Result) mod Alignment);
+
+  // set header with info on old pointer for FreeMem
+  PMemAlignHeader(PtrUInt(Result) - SizeOf(TMemAlignHeader))^ := OrigPtr;
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure FreeAlignedMem(P: pointer);
+begin
+  if (P <> nil) then
+    FreeMem(PMemAlignHeader(PtrUInt(P) - SizeOf(TMemAlignHeader))^);
+end;
+{$WARNINGS ON}
+
+
+initialization
+  InitConsoleOutput();
+
+finalization
+  FinalizeConsoleOutput();
+
+end.
diff --git a/songmanagement/src/base/UConfig.pas b/songmanagement/src/base/UConfig.pas
new file mode 100644
index 00000000..e48b5493
--- /dev/null
+++ b/songmanagement/src/base/UConfig.pas
@@ -0,0 +1,232 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UConfig;
+
+// -------------------------------------------------------------------
+// Note on version comparison (for developers only):
+// -------------------------------------------------------------------
+// Delphi (in contrast to FPC) DOESN'T support MACROS. So we
+// can't define a macro like VERSION_MAJOR(version) to extract
+// parts of the version-number or to create version numbers for
+// comparison purposes as with a MAKE_VERSION(maj, min, rev) macro.
+// So we have to define constants for every part of the version here.
+//
+// In addition FPC (in contrast to delphi) DOES NOT support floating-
+// point numbers in $IF compiler-directives (e.g. {$IF VERSION > 1.23})
+// It also DOESN'T support arithmetic operations so we aren't able to
+// compare versions this way (brackets aren't supported too):
+//   {$IF VERSION > ((VER_MAJ*2)+(VER_MIN*23)+(VER_REL*1))}
+//
+// Hence we have to use fixed numbers in the directives. At least
+// Pascal allows leading 0s so 0005 equals 5 (octals are
+// preceded by & and not by 0 in FPC).
+// We also fix the count of digits for each part of the version number
+// to 3 (aaaiiirrr with aaa=major, iii=minor, rrr=release version)
+//
+// A check for a library with at least a version of 2.5.11 would look
+// like this:
+//   {$IF LIB_VERSION >= 002005011}
+//
+// If you just need to check the major version do this:
+//   {$IF LIB_VERSION_MAJOR >= 23}
+//
+// IMPORTANT:
+//   Because this unit must be included in a uses-section it is
+//   not possible to use the version-numbers in this uses-clause.
+//   Example:
+//     interface
+//     uses
+//       versions, // include this file
+//       {$IF USE_UNIT_XYZ}xyz;{$IFEND}      // Error: USE_UNIT_XYZ not defined
+//     const
+//       {$IF USE_UNIT_XYZ}test = 2;{$IFEND} // OK
+//     uses
+//       {$IF USE_UNIT_XYZ}xyz;{$IFEND}      // OK
+//
+//   Even if this file was an include-file no constants could be declared
+//   before the interface's uses clause.
+//   In FPC macros {$DEFINE VER:= 3} could be used to declare the version-numbers
+//   but this is incompatible to Delphi. In addition macros do not allow expand
+//   arithmetic expressions. Although you can define
+//     {$DEFINE FPC_VER:= FPC_VERSION*1000000+FPC_RELEASE*1000+FPC_PATCH}
+//   the following check would fail:
+//     {$IF FPC_VERSION_INT >= 002002000}
+//   would fail because FPC_VERSION_INT is interpreted as a string.
+//
+// PLEASE consider this if you use version numbers in $IF compiler-
+// directives. Otherwise you might break portability.
+// -------------------------------------------------------------------
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$MACRO ON} // for evaluation of FPC_VERSION/RELEASE/PATCH
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils;
+
+const
+  // IMPORTANT:
+  // If IncludeConstants is defined, the const-sections
+  // of the config-file will be included too.
+  // This switch is necessary because it is not possible to
+  // include the const-sections in the switches.inc.
+  // switches.inc is always included before the first uses-
+  // section but at that place no const-section is allowed.
+  // So we have to include the config-file in switches.inc
+  // with IncludeConstants undefined and in UConfig.pas with
+  // IncludeConstants defined (see the note above).
+  {$DEFINE IncludeConstants}
+
+  // include config-file (defines + constants)
+  {$IF Defined(MSWindows)}
+    {$I ..\config-win.inc}
+  {$ELSEIF Defined(Linux)}
+    {$I ../config-linux.inc}
+  {$ELSEIF Defined(FreeBSD)}
+    {$I ../config-freebsd.inc}
+  {$ELSEIF Defined(Darwin)}
+    {$I ../config-darwin.inc}
+  {$ELSE}
+    {$MESSAGE Fatal 'Unknown OS'}
+  {$IFEND}
+
+{* Libraries *}
+
+  VERSION_MAJOR   = 1000000;
+  VERSION_MINOR   = 1000;
+  VERSION_RELEASE = 1;
+
+  (*
+   * Current version of UltraStar Deluxe
+   *)
+  USDX_VERSION_MAJOR   = 1;
+  USDX_VERSION_MINOR   = 1;
+  USDX_VERSION_RELEASE = 0;
+  USDX_VERSION_STATE   = '';
+  USDX_STRING = 'UltraStar Deluxe';
+
+  (*
+   * FPC version numbers are already defined as built-in macros:
+   *   FPC_VERSION (MAJOR)
+   *   FPC_RELEASE (MINOR)
+   *   FPC_PATCH   (RELEASE)
+   * Since FPC_VERSION is already defined, we will use FPC_VERSION_INT as
+   * composed version number.
+   *)
+  {$IFNDEF FPC}
+  // Delphi 7 evaluates every $IF-directive even if it is disabled by a surrounding
+  // $IF or $IFDEF so the follwing will give you an error in delphi:
+  //   {$IFDEF FPC}{$IF (FPC_VERSION > 2)}...{$IFEND}{$ENDIF}
+  // The reason for this error is that FPC_VERSION is not a valid constant.
+  // To avoid this error, we define dummys here.
+  FPC_VERSION = 0;
+  FPC_RELEASE = 0;
+  FPC_PATCH   = 0;
+  {$ENDIF}
+
+  FPC_VERSION_INT = (FPC_VERSION * VERSION_MAJOR) +
+                    (FPC_RELEASE * VERSION_MINOR) +
+                    (FPC_PATCH * VERSION_RELEASE);
+
+  // FPC 2.2.0 unicode support is very buggy. The cwstring unit for example
+  // always crashes whenever UTF8ToAnsi() is called on a non UTF8 encoded string
+  // what is fixed in 2.2.2.
+  {$IF Defined(FPC) and (FPC_VERSION_INT < 2002002)} // < 2.2.2
+    {$MESSAGE FATAL 'FPC >= 2.2.2 required!'}
+  {$IFEND}
+
+  {$IFDEF HaveFFmpeg}
+
+  LIBAVCODEC_VERSION = (LIBAVCODEC_VERSION_MAJOR * VERSION_MAJOR) +
+                       (LIBAVCODEC_VERSION_MINOR * VERSION_MINOR) +
+                       (LIBAVCODEC_VERSION_RELEASE * VERSION_RELEASE);
+
+  LIBAVFORMAT_VERSION = (LIBAVFORMAT_VERSION_MAJOR * VERSION_MAJOR) +
+                        (LIBAVFORMAT_VERSION_MINOR * VERSION_MINOR) +
+                        (LIBAVFORMAT_VERSION_RELEASE * VERSION_RELEASE);
+
+  LIBAVUTIL_VERSION = (LIBAVUTIL_VERSION_MAJOR * VERSION_MAJOR) +
+                      (LIBAVUTIL_VERSION_MINOR * VERSION_MINOR) +
+                      (LIBAVUTIL_VERSION_RELEASE * VERSION_RELEASE);
+
+  {$IFDEF HaveSWScale}
+  LIBSWSCALE_VERSION = (LIBSWSCALE_VERSION_MAJOR * VERSION_MAJOR) +
+                       (LIBSWSCALE_VERSION_MINOR * VERSION_MINOR) +
+                       (LIBSWSCALE_VERSION_RELEASE * VERSION_RELEASE);
+  {$ENDIF}
+
+  {$ENDIF}
+
+  {$IFDEF HaveProjectM}
+  PROJECTM_VERSION = (PROJECTM_VERSION_MAJOR * VERSION_MAJOR) +
+                     (PROJECTM_VERSION_MINOR * VERSION_MINOR) +
+                     (PROJECTM_VERSION_RELEASE * VERSION_RELEASE);
+  {$ENDIF}
+
+  {$IFDEF HavePortaudio}
+  PORTAUDIO_VERSION = (PORTAUDIO_VERSION_MAJOR * VERSION_MAJOR) +
+                      (PORTAUDIO_VERSION_MINOR * VERSION_MINOR) +
+                      (PORTAUDIO_VERSION_RELEASE * VERSION_RELEASE);
+  {$ENDIF}
+
+  {$IFDEF HaveLibsamplerate}
+  LIBSAMPLERATE_VERSION = (LIBSAMPLERATE_VERSION_MAJOR * VERSION_MAJOR) +
+                          (LIBSAMPLERATE_VERSION_MINOR * VERSION_MINOR) +
+                          (LIBSAMPLERATE_VERSION_RELEASE * VERSION_RELEASE);
+  {$ENDIF}
+
+function USDXVersionStr(): string;
+function USDXShortVersionStr(): string;
+
+implementation
+
+uses
+  StrUtils, Math;
+
+function USDXShortVersionStr(): string;
+begin
+  Result :=
+    USDX_STRING +
+    IfThen(USDX_VERSION_STATE <> '', ' '+USDX_VERSION_STATE);
+end;
+
+function USDXVersionStr(): string;
+begin
+  Result :=
+    USDX_STRING + ' V ' +
+    IntToStr(USDX_VERSION_MAJOR) + '.' +
+    IntToStr(USDX_VERSION_MINOR) + '.' +
+    IntToStr(USDX_VERSION_RELEASE) +
+    IfThen(USDX_VERSION_STATE <> '', ' '+USDX_VERSION_STATE) +
+    ' Build';
+end;
+
+end.
diff --git a/songmanagement/src/base/UCovers.pas b/songmanagement/src/base/UCovers.pas
new file mode 100644
index 00000000..6c7c9e48
--- /dev/null
+++ b/songmanagement/src/base/UCovers.pas
@@ -0,0 +1,459 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UCovers;
+
+{
+  TODO:
+  - adjust database to new song-loading (e.g. use SongIDs)
+  - support for deletion of outdated covers
+  - support for update of changed covers
+  - use paths relative to the song for removable disks support
+    (a drive might have a different drive-name the next time it is connected,
+     so "H:/songs/..." will not match "I:/songs/...") 
+}
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  SQLite3,
+  SQLiteTable3,
+  SysUtils,
+  Classes,
+  UImage,
+  UTexture,
+  UPath;
+
+type
+  ECoverDBException = class(Exception)
+  end;
+
+  TCover = class
+    private
+      ID: int64;
+      Filename: IPath;
+    public
+      constructor Create(ID: int64; Filename: IPath);
+      function GetPreviewTexture(): TTexture;
+      function GetTexture(): TTexture;
+  end;
+
+  TThumbnailInfo = record
+    CoverWidth: integer;         // Original width of cover
+    CoverHeight: integer;        // Original height of cover
+    PixelFormat: TImagePixelFmt; // Pixel-format of thumbnail
+  end;
+  
+  TCoverDatabase = class
+    private
+      DB: TSQLiteDatabase;
+      procedure InitCoverDatabase();
+      function CreateThumbnail(const Filename: IPath; var Info: TThumbnailInfo): PSDL_Surface;
+      function LoadCover(CoverID: int64): TTexture;
+      procedure DeleteCover(CoverID: int64);
+      function FindCoverIntern(const Filename: IPath): int64;
+      procedure Open();
+      function GetVersion(): integer;
+      procedure SetVersion(Version: integer);
+    public
+      constructor Create();
+      destructor Destroy; override;
+      function AddCover(const Filename: IPath): TCover;
+      function FindCover(const Filename: IPath): TCover;
+      function CoverExists(const Filename: IPath): boolean;
+      function GetMaxCoverSize(): integer;
+      procedure SetMaxCoverSize(Size: integer);
+  end;
+
+  TBlobWrapper = class(TCustomMemoryStream)
+     function Write(const Buffer; Count: Integer): Integer; override;
+  end;
+
+var
+  Covers: TCoverDatabase;
+
+implementation
+
+uses
+  UMain,
+  ULog,
+  UPlatform,
+  UIni,
+  Math,
+  DateUtils;
+
+const
+  COVERDB_FILENAME: UTF8String = 'cover.db';
+  COVERDB_VERSION = 01; // 0.1
+  COVER_TBL = 'Cover';
+  COVER_THUMBNAIL_TBL = 'CoverThumbnail';
+  COVER_IDX = 'Cover_Filename_IDX';
+
+// Note: DateUtils.DateTimeToUnix() will throw an exception in FPC
+function DateTimeToUnixTime(time: TDateTime): int64;
+begin
+  Result := Round((time - UnixDateDelta) * SecsPerDay);
+end;
+
+// Note: DateUtils.UnixToDateTime() will throw an exception in FPC
+function UnixTimeToDateTime(timestamp: int64): TDateTime;
+begin
+  Result := timestamp / SecsPerDay + UnixDateDelta;
+end;
+
+
+{ TBlobWrapper }
+
+function TBlobWrapper.Write(const Buffer; Count: Integer): Integer;
+begin
+  SetPointer(Pointer(Buffer), Count);
+  Result := Count;
+end;
+
+
+{ TCover }
+
+constructor TCover.Create(ID: int64; Filename: IPath);
+begin
+  Self.ID := ID;
+  Self.Filename := Filename;
+end;
+
+function TCover.GetPreviewTexture(): TTexture;
+begin
+  Result := Covers.LoadCover(ID);
+end;
+
+function TCover.GetTexture(): TTexture;
+begin
+  Result := Texture.LoadTexture(Filename);
+end;
+
+
+{ TCoverDatabase }
+
+constructor TCoverDatabase.Create();
+begin
+  inherited;
+
+  Open();
+  InitCoverDatabase();
+end;
+
+destructor TCoverDatabase.Destroy;
+begin
+  DB.Free;
+  inherited;
+end;
+
+function TCoverDatabase.GetVersion(): integer;
+begin
+  Result := DB.GetTableValue('PRAGMA user_version');
+end;
+
+procedure TCoverDatabase.SetVersion(Version: integer);
+begin
+  DB.ExecSQL(Format('PRAGMA user_version = %d', [Version]));
+end;
+
+function TCoverDatabase.GetMaxCoverSize(): integer;
+begin
+  Result := ITextureSizeVals[Ini.TextureSize];
+end;
+
+procedure TCoverDatabase.SetMaxCoverSize(Size: integer);
+var
+  I: integer;
+begin
+  // search for first valid cover-size > Size
+  for I := 0 to Length(ITextureSizeVals)-1 do
+  begin
+    if (Size <= ITextureSizeVals[I]) then
+    begin
+      Ini.TextureSize := I;
+      Exit;
+    end;
+  end;
+
+  // fall-back to highest size
+  Ini.TextureSize := High(ITextureSizeVals);
+end;
+
+procedure TCoverDatabase.Open();
+var
+  Version: integer;
+  Filename: IPath;
+begin
+  Filename := Platform.GetGameUserPath().Append(COVERDB_FILENAME);
+
+  DB := TSQLiteDatabase.Create(Filename.ToUTF8());
+  Version := GetVersion();
+
+  // check version, if version is too old/new, delete database file
+  if ((Version <> 0) and (Version <> COVERDB_VERSION)) then
+  begin
+    Log.LogInfo('Outdated cover-database file found', 'TCoverDatabase.Open');
+    // close and delete outdated file
+    DB.Free;
+    if (not Filename.DeleteFile()) then
+      raise ECoverDBException.Create('Could not delete ' + Filename.ToNative);
+    // reopen
+    DB := TSQLiteDatabase.Create(Filename.ToUTF8());
+    Version := 0;
+  end;
+
+  // set version number after creation
+  if (Version = 0) then
+    SetVersion(COVERDB_VERSION);
+
+  // speed-up disk-writing. The default FULL-synchronous mode is too slow.
+  // With this option disk-writing is approx. 4 times faster but the database
+  // might be corrupted if the OS crashes, although this is very unlikely.
+  DB.ExecSQL('PRAGMA synchronous = OFF;');
+  
+  // the next line rather gives a slow-down instead of a speed-up, so we do not use it
+  //DB.ExecSQL('PRAGMA temp_store = MEMORY;');
+end;
+
+procedure TCoverDatabase.InitCoverDatabase();
+begin
+  DB.ExecSQL('CREATE TABLE IF NOT EXISTS ['+COVER_TBL+'] (' +
+               '[ID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT, ' +
+               '[Filename] TEXT  UNIQUE NOT NULL, ' +
+               '[Date] INTEGER  NOT NULL, ' +
+               '[Width] INTEGER  NOT NULL, ' +
+               '[Height] INTEGER  NOT NULL ' +
+             ')');
+
+  DB.ExecSQL('CREATE INDEX IF NOT EXISTS ['+COVER_IDX+'] ON ['+COVER_TBL+'](' +
+               '[Filename]  ASC' +
+             ')');
+
+  DB.ExecSQL('CREATE TABLE IF NOT EXISTS ['+COVER_THUMBNAIL_TBL+'] (' +
+               '[ID] INTEGER  NOT NULL PRIMARY KEY, ' +
+               '[Format] INTEGER  NOT NULL, ' +
+               '[Width] INTEGER  NOT NULL, ' +
+               '[Height] INTEGER  NOT NULL, ' +
+               '[Data] BLOB  NULL' +
+             ')');
+end;
+
+function TCoverDatabase.FindCoverIntern(const Filename: IPath): int64;
+begin
+  Result := DB.GetTableValue('SELECT [ID] FROM ['+COVER_TBL+'] ' +
+                             'WHERE [Filename] = ?',
+                             [Filename.ToUTF8]);
+end;
+
+function TCoverDatabase.FindCover(const Filename: IPath): TCover;
+var
+  CoverID: int64;
+begin
+  Result := nil;
+  try
+    CoverID := FindCoverIntern(Filename);
+    if (CoverID > 0) then
+      Result := TCover.Create(CoverID, Filename);
+  except on E: Exception do
+    Log.LogError(E.Message, 'TCoverDatabase.FindCover');
+  end;
+end;
+
+function TCoverDatabase.CoverExists(const Filename: IPath): boolean;
+begin
+  Result := false;
+  try
+    Result := (FindCoverIntern(Filename) > 0);
+  except on E: Exception do
+    Log.LogError(E.Message, 'TCoverDatabase.CoverExists');
+  end;
+end;
+
+function TCoverDatabase.AddCover(const Filename: IPath): TCover;
+var
+  CoverID: int64;
+  Thumbnail: PSDL_Surface;
+  CoverData: TBlobWrapper;
+  FileDate: TDateTime;
+  Info: TThumbnailInfo;
+begin
+  Result := nil;
+
+  //if (not FileExists(Filename)) then
+  //  Exit;
+
+  // TODO: replace '\' with '/' in filename
+  FileDate := Now(); //FileDateToDateTime(FileAge(Filename));
+
+  Thumbnail := CreateThumbnail(Filename, Info);
+  if (Thumbnail = nil) then
+    Exit;
+
+  CoverData := TBlobWrapper.Create;
+  CoverData.Write(Thumbnail^.pixels, Thumbnail^.h * Thumbnail^.pitch);
+
+  try
+    // Note: use a transaction to speed-up file-writing.
+    // Without data written by the first INSERT might be moved at the second INSERT. 
+    DB.BeginTransaction();
+
+    // add general cover info
+    DB.ExecSQL('INSERT INTO ['+COVER_TBL+'] ' +
+               '([Filename], [Date], [Width], [Height]) VALUES' +
+               '(?, ?, ?, ?)',
+               [Filename.ToUTF8, DateTimeToUnixTime(FileDate),
+                Info.CoverWidth, Info.CoverHeight]);
+
+    // get auto-generated cover ID
+    CoverID := DB.GetLastInsertRowID();
+
+    // add thumbnail info
+    DB.ExecSQL('INSERT INTO ['+COVER_THUMBNAIL_TBL+'] ' +
+               '([ID], [Format], [Width], [Height], [Data]) VALUES' +
+               '(?, ?, ?, ?, ?)',
+               [CoverID, Ord(Info.PixelFormat),
+                Thumbnail^.w, Thumbnail^.h, CoverData]);
+
+    Result := TCover.Create(CoverID, Filename);
+  except on E: Exception do
+    Log.LogError(E.Message, 'TCoverDatabase.AddCover');
+  end;
+
+  DB.Commit();
+  CoverData.Free;
+  SDL_FreeSurface(Thumbnail);
+end;
+
+function TCoverDatabase.LoadCover(CoverID: int64): TTexture;
+var
+  Width, Height: integer;
+  PixelFmt: TImagePixelFmt;
+  Data: PChar;
+  DataSize: integer;
+  Filename: IPath;
+  Table: TSQLiteUniTable;
+begin
+  Table := nil;
+
+  try
+    Table := DB.GetUniTable(Format(
+      'SELECT C.[Filename], T.[Format], T.[Width], T.[Height], T.[Data] ' +
+      'FROM ['+COVER_TBL+'] C ' +
+        'INNER JOIN ['+COVER_THUMBNAIL_TBL+'] T ' +
+        'USING(ID) ' +
+      'WHERE [ID] = %d', [CoverID]));
+
+    Filename := Path(Table.FieldAsString(0));
+    PixelFmt := TImagePixelFmt(Table.FieldAsInteger(1));
+    Width    := Table.FieldAsInteger(2);
+    Height   := Table.FieldAsInteger(3);
+
+    Data := Table.FieldAsBlobPtr(4, DataSize);
+    if (Data <> nil) and
+       (PixelFmt = ipfRGB) then
+    begin
+      Result := Texture.CreateTexture(Data, Filename, Width, Height, 24)
+    end
+    else
+    begin
+      // FillChar() does not decrement the ref-count of ref-counted fields
+      // -> reset Name field manually
+      Result.Name := nil;
+      FillChar(Result, SizeOf(TTexture), 0);
+    end;
+  except on E: Exception do
+    Log.LogError(E.Message, 'TCoverDatabase.LoadCover');
+  end;
+
+  Table.Free;
+end;
+
+procedure TCoverDatabase.DeleteCover(CoverID: int64);
+begin
+  DB.ExecSQL(Format('DELETE FROM ['+COVER_TBL+'] WHERE [ID] = %d', [CoverID]));
+  DB.ExecSQL(Format('DELETE FROM ['+COVER_THUMBNAIL_TBL+'] WHERE [ID] = %d', [CoverID]));
+end;
+
+(**
+ * Returns a pointer to an array of bytes containing the texture data in the
+ * requested size
+ *)
+function TCoverDatabase.CreateThumbnail(const Filename: IPath; var Info: TThumbnailInfo): PSDL_Surface;
+var
+  //TargetAspect, SourceAspect: double;
+  //TargetWidth, TargetHeight: integer;
+  Thumbnail: PSDL_Surface;
+  MaxSize: integer;
+begin
+  Result := nil;
+
+  MaxSize := GetMaxCoverSize();
+
+  Thumbnail := LoadImage(Filename);
+  if (not assigned(Thumbnail)) then
+  begin
+    Log.LogError('Could not load cover: "'+ Filename.ToNative +'"', 'TCoverDatabase.AddCover');
+    Exit;
+  end;
+
+  // Convert pixel format as needed
+  AdjustPixelFormat(Thumbnail, TEXTURE_TYPE_PLAIN);
+
+  Info.CoverWidth  := Thumbnail^.w;
+  Info.CoverHeight := Thumbnail^.h;
+  Info.PixelFormat := ipfRGB;
+
+  (* TODO: keep aspect ratio
+  TargetAspect := Width / Height;
+  SourceAspect := TexSurface.w / TexSurface.h;
+
+  // Scale texture to covers dimensions (keep aspect)
+  if (SourceAspect >= TargetAspect) then
+  begin
+    TargetWidth := Width;
+    TargetHeight := Trunc(Width / SourceAspect);
+  end
+  else
+  begin
+    TargetHeight := Height;
+    TargetWidth := Trunc(Height * SourceAspect);
+  end;
+  *)
+
+  // TODO: do not scale if image is smaller
+  ScaleImage(Thumbnail, MaxSize, MaxSize);
+  
+  Result := Thumbnail;
+end;
+
+end.
+
diff --git a/songmanagement/src/base/UDataBase.pas b/songmanagement/src/base/UDataBase.pas
new file mode 100644
index 00000000..5cb15182
--- /dev/null
+++ b/songmanagement/src/base/UDataBase.pas
@@ -0,0 +1,720 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UDataBase;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  SQLiteTable3,
+  UPath,
+  USong,
+  USongs,
+  UTextEncoding;
+
+//--------------------
+//DataBaseSystem - Class including all DB methods
+//--------------------
+type
+  TStatType = (
+    stBestScores,   // Best scores
+    stBestSingers,  // Best singers
+    stMostSungSong, // Most sung songs
+    stMostPopBand   // Most popular band
+  );
+
+  // abstract super-class for statistic results
+  TStatResult = class
+    public
+      Typ: TStatType;
+  end;
+
+  TStatResultBestScores = class(TStatResult)
+    public
+      Singer:       UTF8String;
+      Score:        word;
+      Difficulty:   byte;
+      SongArtist:   UTF8String;
+      SongTitle:    UTF8String;
+      Date:         UTF8String;
+  end;
+
+  TStatResultBestSingers = class(TStatResult)
+    public
+      Player:       UTF8String;
+      AverageScore: word;
+  end;
+
+  TStatResultMostSungSong = class(TStatResult)
+    public
+      Artist:       UTF8String;
+      Title:        UTF8String;
+      TimesSung:    word;
+  end;
+
+  TStatResultMostPopBand = class(TStatResult)
+    public
+      ArtistName:   UTF8String;
+      TimesSungTot: word;
+  end;
+
+
+  TDataBaseSystem = class
+    private
+      ScoreDB:      TSQLiteDatabase;
+      fFilename: IPath;
+
+      function GetVersion(): integer;
+      procedure SetVersion(Version: integer);
+    public
+      property Filename: IPath read fFilename;
+
+      destructor Destroy; override;
+
+      procedure Init(const Filename: IPath);
+      procedure ConvertFrom101To110();
+      procedure ReadScore(Song: TSong);
+      procedure AddScore(Song: TSong; Level: integer; const Name: UTF8String; Score: integer);
+      procedure WriteScore(Song: TSong);
+
+      function GetStats(Typ: TStatType; Count: byte; Page: cardinal; Reversed: boolean): TList;
+      procedure FreeStats(StatList: TList);
+      function GetTotalEntrys(Typ: TStatType): cardinal;
+      function GetStatReset: TDateTime;
+      function FormatDate(time_stamp: integer): UTF8String;
+  end;
+
+var
+  DataBase: TDataBaseSystem;
+
+implementation
+
+uses
+  DateUtils,
+  ULanguage,
+  StrUtils,
+  SysUtils,
+  ULog;
+
+{
+ cDBVersion - history
+ 0 = USDX 1.01 or no Database
+ 01 = USDX 1.1
+}
+const
+  cDBVersion = 01; // 0.1
+  cUS_Scores = 'us_scores';
+  cUS_Songs  = 'us_songs';
+  cUS_Statistics_Info = 'us_statistics_info';
+
+(**
+ * Open database and create tables if they do not exist
+ *)
+procedure TDataBaseSystem.Init(const Filename: IPath);
+var
+  Version:            integer;
+  finalizeConversion: boolean;
+begin
+  if Assigned(ScoreDB) then
+    Exit;
+
+  Log.LogStatus('Initializing database: "' + Filename.ToNative + '"', 'TDataBaseSystem.Init');
+
+  try
+
+    // open database
+    ScoreDB   := TSQLiteDatabase.Create(Filename.ToUTF8);
+    fFilename := Filename;
+
+    Version := GetVersion();
+
+    // add Table cUS_Statistics_Info
+    // needed in the conversion from 1.01 to 1.1
+    if not ScoreDB.TableExists(cUS_Statistics_Info) then
+    begin
+      Log.LogInfo('Outdated song database found - missing table"' + cUS_Statistics_Info + '"', 'TDataBaseSystem.Init');
+      ScoreDB.ExecSQL('CREATE TABLE IF NOT EXISTS [' + cUS_Statistics_Info + '] (' +
+                      '[ResetTime] INTEGER' +
+                      ');');
+      // insert creation timestamp
+      ScoreDB.ExecSQL(Format('INSERT INTO [' + cUS_Statistics_Info + '] ' +
+                             '([ResetTime]) VALUES(%d);',
+                             [DateTimeToUnix(Now())]));
+    end;
+
+    // convert data from 1.01 to 1.1
+    // part #1 - prearrangement
+    finalizeConversion := false;
+    if (Version = 0) AND ScoreDB.TableExists('US_Scores') then
+    begin
+      // rename old tables - to be able to insert new table structures
+      ScoreDB.ExecSQL('ALTER TABLE US_Scores RENAME TO us_scores_101;');
+      ScoreDB.ExecSQL('ALTER TABLE US_Songs RENAME TO us_songs_101;');
+      finalizeConversion := true; // means: conversion has to be done!
+    end;
+
+    // Set version number after creation
+    if (Version = 0) then
+      SetVersion(cDBVersion);
+
+    // SQLite does not handle VARCHAR(n) or INT(n) as expected.
+    // Texts do not have a restricted length, no matter which type is used,
+    // so use the native TEXT type. INT(n) is always INTEGER.
+    // In addition, SQLiteTable3 will fail if other types than the native SQLite
+    // types are used (especially FieldAsInteger). Also take care to write the
+    // types in upper-case letters although SQLite does not care about this -
+    // SQLiteTable3 is very sensitive in this regard.
+    ScoreDB.ExecSQL('CREATE TABLE IF NOT EXISTS [' + cUS_Scores + '] (' +
+                      '[SongID] INTEGER NOT NULL, ' +
+                      '[Difficulty] INTEGER NOT NULL, ' +
+                      '[Player] TEXT NOT NULL, ' +
+                      '[Score] INTEGER NOT NULL, ' +
+                      '[Date] INTEGER NULL' +
+                    ');');
+
+    ScoreDB.ExecSQL('CREATE TABLE IF NOT EXISTS [' + cUS_Songs + '] (' +
+                      '[ID] INTEGER PRIMARY KEY, ' +
+                      '[Artist] TEXT NOT NULL, ' +
+                      '[Title] TEXT NOT NULL, ' +
+                      '[TimesPlayed] INTEGER NOT NULL, ' +
+                      '[Rating] INTEGER NULL' +
+                    ');');
+
+    //add column date to cUS-Scores
+    if not ScoreDB.ContainsColumn(cUS_Scores, 'Date') then
+    begin
+      Log.LogInfo('adding column date to "' + cUS_Scores + '"', 'TDataBaseSystem.Init');
+      ScoreDB.ExecSQL('ALTER TABLE ' + cUS_Scores + ' ADD COLUMN [Date] INTEGER NULL');
+    end;
+
+    // add column rating to cUS_Songs
+    // just for users of nightly builds and developers!
+    if not ScoreDB.ContainsColumn(cUS_Songs, 'Rating') then
+    begin
+      Log.LogInfo('Outdated song database found - adding column rating to "' + cUS_Songs + '"', 'TDataBaseSystem.Init');
+      ScoreDB.ExecSQL('ALTER TABLE ' + cUS_Songs + ' ADD COLUMN [Rating] INTEGER NULL');
+    end;
+
+    // convert data from previous versions
+    // part #2 - accomplishment
+    if finalizeConversion then
+    begin
+      //convert data from 1.01 to 1.1
+      if ScoreDB.TableExists('us_scores_101') then
+        ConvertFrom101To110();
+    end;
+
+  except
+    on E: Exception do
+    begin
+      Log.LogError(E.Message, 'TDataBaseSystem.Init');
+      FreeAndNil(ScoreDB);
+    end;
+  end;
+
+end;
+
+(**
+ * Convert Database from 1.01 to 1.1
+ *)
+procedure TDataBaseSystem.ConvertFrom101To110();
+var
+  TableData:      TSQLiteUniTable;
+  tempUTF8String: UTF8String;
+begin
+  if not ScoreDB.ContainsColumn('us_scores_101', 'Date') then
+  begin
+    Log.LogInfo(
+      'Outdated song database found - ' +
+      'begin conversion from V1.01 to V1.1', 'TDataBaseSystem.Convert101To110');
+
+    // insert old values into new db-schemes (/tables)
+    ScoreDB.ExecSQL(
+      'INSERT INTO ' + cUS_Scores +
+      ' SELECT  SongID, Difficulty, Player, Score, ''NULL'' FROM us_scores_101;');
+  end else
+  begin
+    Log.LogInfo(
+      'Outdated song database  found - ' +
+      'begin conversion from V1.01 Challenge Mod to V1.1', 'TDataBaseSystem.Convert101To110');
+
+    // insert old values into new db-schemes (/tables)
+    ScoreDB.ExecSQL(
+      'INSERT INTO ' + cUS_Scores +
+      ' SELECT  SongID, Difficulty, Player, Score, Date FROM us_scores_101;');
+  end;
+
+    ScoreDB.ExecSQL(
+      'INSERT INTO ' + cUS_Songs +
+      ' SELECT  ID, Artist, Title, TimesPlayed, ''NULL'' FROM us_songs_101;');
+
+    // now we have to convert all the texts for unicode support:
+
+    // player names
+    TableData := nil;
+    try
+      TableData := ScoreDB.GetUniTable(
+        'SELECT [rowid], [Player] ' +
+        'FROM [' + cUS_Scores + '];');
+
+      // Go through all Entrys
+      while (not TableData.EOF) do
+      begin
+        // Convert name into UTF8 and alter all entrys
+        DecodeStringUTF8(TableData.FieldByName['Player'], tempUTF8String, encCP1252);
+        ScoreDB.ExecSQL(
+          'UPDATE [' + cUS_Scores + '] ' +
+          'SET [Player] = ? ' +
+          'WHERE [rowid] = ? ',
+          [tempUTF8String,
+          TableData.FieldAsInteger(TableData.FieldIndex['rowid'])]);
+
+        TableData.Next;
+      end; // while
+
+    except
+      on E: Exception do
+        Log.LogError(E.Message, 'TDataBaseSystem.Convert101To110');
+    end;
+
+    TableData.Free;
+
+    // song artist and song title
+    TableData := nil;
+    try
+      TableData := ScoreDB.GetUniTable(
+        'SELECT [ID], [Artist], [Title] ' +
+        'FROM [' + cUS_Songs + '];');
+
+      // Go through all Entrys
+      while (not TableData.EOF) do
+      begin
+        // Convert Artist into UTF8 and alter all entrys
+        DecodeStringUTF8(TableData.FieldByName['Artist'], tempUTF8String, encCP1252);
+        //Log.LogError(TableData.FieldByName['Artist']+' -> '+tempUTF8String+' (encCP1252)');
+        ScoreDB.ExecSQL(
+          'UPDATE [' + cUS_Songs + '] ' +
+          'SET [Artist] = ? ' +
+          'WHERE [ID] = ?',
+          [tempUTF8String,
+          TableData.FieldAsInteger(TableData.FieldIndex['ID'])]);
+
+        // Convert Title into UTF8 and alter all entrys
+        DecodeStringUTF8(TableData.FieldByName['Title'], tempUTF8String, encCP1252);
+        ScoreDB.ExecSQL(
+          'UPDATE [' + cUS_Songs + '] ' +
+          'SET [Title] = ? ' +
+          'WHERE [ID] = ? ',
+          [tempUTF8String,
+          TableData.FieldAsInteger(TableData.FieldIndex['ID'])]);
+
+        TableData.Next;
+      end; // while
+
+    except
+      on E: Exception do
+        Log.LogError(E.Message, 'TDataBaseSystem.Convert101To110');
+    end;
+
+    TableData.Free;
+
+    //now drop old tables
+    ScoreDB.ExecSQL('DROP TABLE us_scores_101;');
+    ScoreDB.ExecSQL('DROP TABLE us_songs_101;');
+end;
+
+(**
+ * Frees Database
+ *)
+destructor TDataBaseSystem.Destroy;
+begin
+  Log.LogInfo('TDataBaseSystem.Free', 'TDataBaseSystem.Destroy');
+  ScoreDB.Free;
+  inherited;
+end;
+
+(**
+ * Format a UNIX-Timestamp into DATE (If 0 then '')
+ *)
+function TDataBaseSystem.FormatDate(time_stamp: integer): UTF8String;
+var
+  Year, Month, Day: word;
+begin
+  Result:='';
+  try
+    if time_stamp<>0 then
+    begin
+      DecodeDate(UnixToDateTime(time_stamp), Year, Month, Day);
+      Result := Format(Language.Translate('STAT_FORMAT_DATE'), [Day, Month, Year]);
+    end;
+  except
+    on E: EConvertError do
+    Log.LogError('Error Parsing FormatString "STAT_FORMAT_DATE": ' + E.Message);
+  end;
+end;
+
+
+(**
+ * Read Scores into SongArray
+ *)
+procedure TDataBaseSystem.ReadScore(Song: TSong);
+var
+  TableData:  TSQLiteUniTable;
+  Difficulty: integer;
+  I: integer;
+  PlayerListed: boolean;
+begin
+  if not Assigned(ScoreDB) then
+    Exit;
+
+  TableData := nil;
+  try
+    // Search Song in DB
+    TableData := ScoreDB.GetUniTable(
+      'SELECT [Difficulty], [Player], [Score], [Date] FROM [' + cUS_Scores + '] ' +
+      'WHERE [SongID] = (' +
+        'SELECT [ID] FROM [' + cUS_Songs + '] ' +
+        'WHERE [Artist] = ? AND [Title] = ? ' +
+        'LIMIT 1) ' +
+      'ORDER BY [Score] DESC;', //no LIMIT! see filter below!
+      [Song.Artist, Song.Title]);
+
+    // Empty Old Scores
+    SetLength(Song.Score[0], 0); //easy
+    SetLength(Song.Score[1], 0); //medium
+    SetLength(Song.Score[2], 0); //hard
+
+    // Go through all Entrys
+    while (not TableData.EOF) do
+    begin
+      // Add one Entry to Array
+      Difficulty := TableData.FieldAsInteger(TableData.FieldIndex['Difficulty']);
+      if ((Difficulty >= 0) and (Difficulty <= 2)) and
+         (Length(Song.Score[Difficulty]) < 5) then
+      begin
+        //filter player
+        PlayerListed:=false;
+        if (Length(Song.Score[Difficulty])>0) then
+        begin
+          for I := 0 to Length(Song.Score[Difficulty]) - 1 do
+          begin
+            if (Song.Score[Difficulty, I].Name = TableData.FieldByName['Player']) then
+            begin
+              PlayerListed:=true;
+              break;
+            end;
+          end;
+        end;
+
+        if not PlayerListed then
+        begin
+          SetLength(Song.Score[Difficulty], Length(Song.Score[Difficulty]) + 1);
+
+          Song.Score[Difficulty, High(Song.Score[Difficulty])].Name  :=
+            TableData.FieldByName['Player'];
+          Song.Score[Difficulty, High(Song.Score[Difficulty])].Score :=
+            TableData.FieldAsInteger(TableData.FieldIndex['Score']);
+          Song.Score[Difficulty, High(Song.Score[Difficulty])].Date :=
+            FormatDate(TableData.FieldAsInteger(TableData.FieldIndex['Date']));
+        end;
+      end;
+
+      TableData.Next;
+    end; // while
+
+  except
+    for Difficulty := 0 to 2 do
+    begin
+      SetLength(Song.Score[Difficulty], 1);
+      Song.Score[Difficulty, 1].Name := 'Error Reading ScoreDB';
+    end;
+  end;
+
+  TableData.Free;
+end;
+
+(**
+ * Adds one new score to DB
+ *)
+procedure TDataBaseSystem.AddScore(Song: TSong; Level: integer; const Name: UTF8String; Score: integer);
+var
+  ID:        integer;
+  TableData: TSQLiteTable;
+begin
+  if not Assigned(ScoreDB) then
+    Exit;
+
+  // Prevent 0 Scores from being added EDIT: ==> UScreenTop5.pas!
+  //if (Score <= 0) then
+  //  Exit;
+
+  TableData := nil;
+
+  try
+
+    ID := ScoreDB.GetTableValue(
+        'SELECT [ID] FROM [' + cUS_Songs + '] ' +
+        'WHERE [Artist] = ? AND [Title] = ?',
+        [Song.Artist, Song.Title]);
+    if (ID = 0) then
+    begin
+      // Create song if it does not exist
+      ScoreDB.ExecSQL(
+          'INSERT INTO [' + cUS_Songs + '] ' +
+          '([ID], [Artist], [Title], [TimesPlayed]) VALUES ' +
+          '(NULL, ?, ?, 0);',
+          [Song.Artist, Song.Title]);
+      // Get song-ID
+      ID := ScoreDB.GetLastInsertRowID();
+    end;
+    // Create new entry
+    ScoreDB.ExecSQL(
+      'INSERT INTO [' + cUS_Scores + '] ' +
+      '([SongID] ,[Difficulty], [Player], [Score], [Date]) VALUES ' +
+      '(?, ?, ?, ?, ?);',
+      [ID, Level, Name, Score, DateTimeToUnix(Now())]);
+
+  except on E: Exception do
+    Log.LogError(E.Message, 'TDataBaseSystem.AddScore');
+  end;
+
+  TableData.Free;
+end;
+
+(**
+ * Not needed with new system.
+ * Used to increment played count
+ *)
+procedure TDataBaseSystem.WriteScore(Song: TSong);
+begin
+  if not Assigned(ScoreDB) then
+    Exit;
+
+  try
+    // Increase TimesPlayed
+    ScoreDB.ExecSQL(
+        'UPDATE [' + cUS_Songs + '] ' +
+        'SET [TimesPlayed] = [TimesPlayed] + 1 ' +
+        'WHERE [Title] = ? AND [Artist] = ?;',
+        [Song.Title, Song.Artist]);
+  except on E: Exception do
+    Log.LogError(E.Message, 'TDataBaseSystem.WriteScore');
+  end;
+end;
+
+(**
+ * Writes some stats to array.
+ * Returns nil if the database is not ready or a list with zero or more statistic
+ * entries.
+ * Free the result-list with FreeStats() after usage to avoid memory leaks.
+ *)
+function TDataBaseSystem.GetStats(Typ: TStatType; Count: byte; Page: cardinal; Reversed: boolean): TList;
+var
+  Query:     string;
+  TableData: TSQLiteUniTable;
+  Stat:      TStatResult;
+begin
+  Result := nil;
+
+  if not Assigned(ScoreDB) then
+    Exit;
+
+  {Todo:  Add Prevention that only players with more than 5 scores are selected at type 2}
+
+  // Create query
+  case Typ of
+    stBestScores: begin
+      Query := 'SELECT [Player], [Difficulty], [Score], [Artist], [Title], [Date] FROM [' + cUS_Scores + '] ' +
+               'INNER JOIN [' + cUS_Songs + '] ON ([SongID] = [ID]) ORDER BY [Score]';
+    end;
+    stBestSingers: begin
+      Query := 'SELECT [Player], ROUND(AVG([Score])) FROM [' + cUS_Scores + '] ' +
+               'GROUP BY [Player] ORDER BY AVG([Score])';
+    end;
+    stMostSungSong: begin
+      Query := 'SELECT [Artist], [Title], [TimesPlayed] FROM [' + cUS_Songs + '] ' +
+               'ORDER BY [TimesPlayed]';
+    end;
+    stMostPopBand: begin
+      Query := 'SELECT [Artist], SUM([TimesPlayed]) FROM [' + cUS_Songs + '] ' +
+               'GROUP BY [Artist] ORDER BY SUM([TimesPlayed])';
+    end;
+  end;
+
+  // Add order direction
+  Query := Query + IfThen(Reversed, ' ASC', ' DESC');
+
+  // Add limit
+  Query := Query + ' LIMIT ' + InttoStr(Count * Page) + ', ' + InttoStr(Count) + ';';
+
+  // Execute query
+  try
+    TableData := ScoreDB.GetUniTable(Query);
+  except
+    on E: Exception do
+    begin
+      Log.LogError(E.Message, 'TDataBaseSystem.GetStats');
+      Exit;
+    end;
+  end;
+
+  Result := TList.Create;
+  Stat := nil;
+
+  // Copy result to stats array
+  while not TableData.EOF do
+  begin
+    case Typ of
+      stBestScores: begin
+        Stat := TStatResultBestScores.Create;
+        with TStatResultBestScores(Stat) do
+        begin
+          Singer := TableData.Fields[0];
+          Difficulty := TableData.FieldAsInteger(1);
+          Score := TableData.FieldAsInteger(2);
+          SongArtist := TableData.Fields[3];
+          SongTitle := TableData.Fields[4];
+          Date := FormatDate(TableData.FieldAsInteger(5));
+        end;
+      end;
+      stBestSingers: begin
+        Stat := TStatResultBestSingers.Create;
+        with TStatResultBestSingers(Stat) do
+        begin
+          Player := TableData.Fields[0];
+          AverageScore := TableData.FieldAsInteger(1);
+        end;
+      end;
+      stMostSungSong: begin
+        Stat := TStatResultMostSungSong.Create;
+        with TStatResultMostSungSong(Stat) do
+        begin
+          Artist := TableData.Fields[0];
+          Title  := TableData.Fields[1];
+          TimesSung  := TableData.FieldAsInteger(2);
+        end;
+      end;
+      stMostPopBand: begin
+        Stat := TStatResultMostPopBand.Create;
+        with TStatResultMostPopBand(Stat) do
+        begin
+          ArtistName := TableData.Fields[0];
+          TimesSungTot := TableData.FieldAsInteger(1);
+        end;
+      end
+      else
+        Log.LogCritical('Unknown stat-type', 'TDataBaseSystem.GetStats');
+    end;
+
+    Stat.Typ := Typ;
+    Result.Add(Stat);
+
+    TableData.Next;
+  end;
+
+  TableData.Free;
+end;
+
+procedure TDataBaseSystem.FreeStats(StatList: TList);
+var
+  Index: integer;
+begin
+  if (StatList = nil) then
+    Exit;
+  for Index := 0 to StatList.Count-1 do
+    TStatResult(StatList[Index]).Free;
+  StatList.Free;
+end;
+
+(**
+ * Gets total number of entrys for a stats query
+ *)
+function TDataBaseSystem.GetTotalEntrys(Typ: TStatType): cardinal;
+var
+  Query: string;
+begin
+  Result := 0;
+
+  if not Assigned(ScoreDB) then
+    Exit;
+
+  try
+    // Create query
+    case Typ of
+      stBestScores:
+        Query := 'SELECT COUNT([SongID]) FROM [' + cUS_Scores + '];';
+      stBestSingers:
+        Query := 'SELECT COUNT(DISTINCT [Player]) FROM [' + cUS_Scores + '];';
+      stMostSungSong:
+        Query := 'SELECT COUNT([ID]) FROM [' + cUS_Songs + '];';
+      stMostPopBand:
+        Query := 'SELECT COUNT(DISTINCT [Artist]) FROM [' + cUS_Songs + '];';
+    end;
+
+    Result := ScoreDB.GetTableValue(Query);
+  except on E: Exception do
+    Log.LogError(E.Message, 'TDataBaseSystem.GetTotalEntrys');
+  end;
+
+end;
+
+(**
+ * Gets reset date of statistic data
+ *)
+function TDataBaseSystem.GetStatReset: TDateTime;
+var
+  Query: string;
+begin
+  Result := 0;
+
+  if not Assigned(ScoreDB) then
+    Exit;
+
+  try
+    Query := 'SELECT [ResetTime] FROM [' + cUS_Statistics_Info + '];';
+    Result := UnixToDateTime(ScoreDB.GetTableValue(Query));
+  except on E: Exception do
+    Log.LogError(E.Message, 'TDataBaseSystem.GetStatReset');
+  end;
+end;
+
+function TDataBaseSystem.GetVersion(): integer;
+begin
+  Result := ScoreDB.GetTableValue('PRAGMA user_version');
+end;
+
+procedure TDataBaseSystem.SetVersion(Version: integer);
+begin
+  ScoreDB.ExecSQL(Format('PRAGMA user_version = %d', [Version]));
+end;
+
+end.
diff --git a/songmanagement/src/base/UDraw.pas b/songmanagement/src/base/UDraw.pas
new file mode 100644
index 00000000..5bec3eab
--- /dev/null
+++ b/songmanagement/src/base/UDraw.pas
@@ -0,0 +1,1163 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UDraw;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UThemes,
+  UGraphicClasses;
+
+procedure SingDraw;
+procedure SingDrawBackground;
+procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer);
+procedure SingDrawNoteLines(Left, Top, Right: real; Space: integer);
+procedure SingDrawLyricHelper(Left, LyricsMid: real);
+procedure SingDrawBeatDelimeters(Left, Top, Right: real; NrLines: integer);
+procedure SingDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer);
+procedure SingDrawPlayerLine(X, Y, W: real; PlayerIndex: integer; Space: integer);
+procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, PlayerIndex: integer; Space: integer);
+
+// TimeBar
+procedure SingDrawTimeBar();
+
+//Draw Editor NoteLines
+procedure EditDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer);
+
+type
+  TRecR = record
+    Top:    real;
+    Left:   real;
+    Right:  real;
+    Bottom: real;
+
+    Width:  real;
+    WMid:   real;
+    Height: real;
+    HMid:   real;
+    Mid:    real;
+  end;
+
+var
+  NotesW:   real;
+  NotesH:   real;
+  Starfr:   integer;
+  StarfrG:  integer;
+
+  //SingBar
+  TickOld:  cardinal;
+  TickOld2: cardinal;
+
+implementation
+
+uses
+  SysUtils,
+  Math,
+  gl,
+  TextGL,
+  UDrawTexture,
+  UGraphic,
+  UIni,
+  ULog,
+  ULyrics,
+  UNote,
+  UMusic,
+  URecord,
+  UScreenSing,
+  UTexture;
+
+procedure SingDrawBackground;
+var
+  Rec:    TRecR;
+  TexRec: TRecR;
+begin
+  if (ScreenSing.Tex_Background.TexNum > 0) then
+  begin
+    if (Ini.MovieSize <= 1) then  //HalfSize BG
+    begin
+      (* half screen + gradient *)
+      Rec.Top := 110; // 80
+      Rec.Bottom := Rec.Top + 20;
+      Rec.Left  := 0;
+      Rec.Right := 800;
+
+      TexRec.Top := (Rec.Top / 600) * ScreenSing.Tex_Background.TexH;
+      TexRec.Bottom := (Rec.Bottom / 600) * ScreenSing.Tex_Background.TexH;
+      TexRec.Left := 0;
+      TexRec.Right := ScreenSing.Tex_Background.TexW;
+
+      glEnable(GL_TEXTURE_2D);
+      glBindTexture(GL_TEXTURE_2D, ScreenSing.Tex_Background.TexNum);
+      glEnable(GL_BLEND);
+      glBegin(GL_QUADS);
+        (* gradient draw *)
+        (* top *)
+        glColor4f(1, 1, 1, 0);
+        glTexCoord2f(TexRec.Right, TexRec.Top);    glVertex2f(Rec.Right, Rec.Top);
+        glTexCoord2f(TexRec.Left,  TexRec.Top);    glVertex2f(Rec.Left,  Rec.Top);
+        glColor4f(1, 1, 1, 1);
+        glTexCoord2f(TexRec.Left,  TexRec.Bottom); glVertex2f(Rec.Left,  Rec.Bottom);
+        glTexCoord2f(TexRec.Right, TexRec.Bottom); glVertex2f(Rec.Right, Rec.Bottom);
+        (* mid *)
+        Rec.Top := Rec.Bottom;
+        Rec.Bottom := 490 - 20; // 490 - 20
+        TexRec.Top := TexRec.Bottom;
+        TexRec.Bottom := (Rec.Bottom / 600) * ScreenSing.Tex_Background.TexH;
+        glTexCoord2f(TexRec.Left,  TexRec.Top);    glVertex2f(Rec.Left,  Rec.Top);
+        glTexCoord2f(TexRec.Left,  TexRec.Bottom); glVertex2f(Rec.Left,  Rec.Bottom);
+        glTexCoord2f(TexRec.Right, TexRec.Bottom); glVertex2f(Rec.Right, Rec.Bottom);
+        glTexCoord2f(TexRec.Right, TexRec.Top);    glVertex2f(Rec.Right, Rec.Top);
+        (* bottom *)
+        Rec.Top := Rec.Bottom;
+        Rec.Bottom := 490; // 490
+        TexRec.Top := TexRec.Bottom;
+        TexRec.Bottom := (Rec.Bottom / 600) * ScreenSing.Tex_Background.TexH;
+        glTexCoord2f(TexRec.Right, TexRec.Top);    glVertex2f(Rec.Right, Rec.Top);
+        glTexCoord2f(TexRec.Left,  TexRec.Top);    glVertex2f(Rec.Left,  Rec.Top);
+        glColor4f(1, 1, 1, 0);
+        glTexCoord2f(TexRec.Left,  TexRec.Bottom); glVertex2f(Rec.Left,  Rec.Bottom);
+        glTexCoord2f(TexRec.Right, TexRec.Bottom); glVertex2f(Rec.Right, Rec.Bottom);
+
+      glEnd;
+      glDisable(GL_TEXTURE_2D);
+      glDisable(GL_BLEND);
+    end
+    else //Full Size BG
+    begin
+      glEnable(GL_TEXTURE_2D);
+      glBindTexture(GL_TEXTURE_2D, ScreenSing.Tex_Background.TexNum);
+      //glEnable(GL_BLEND);
+      glBegin(GL_QUADS);
+
+        glTexCoord2f(0, 0);   glVertex2f(0,  0);
+        glTexCoord2f(0,  ScreenSing.Tex_Background.TexH);   glVertex2f(0,  600);
+        glTexCoord2f( ScreenSing.Tex_Background.TexW,  ScreenSing.Tex_Background.TexH);   glVertex2f(800, 600);
+        glTexCoord2f( ScreenSing.Tex_Background.TexW, 0);   glVertex2f(800, 0);
+
+      glEnd;
+      glDisable(GL_TEXTURE_2D);
+      //glDisable(GL_BLEND);
+    end;
+  end;
+end;
+
+procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer);
+var
+  SampleIndex: integer;
+  Sound:       TCaptureBuffer;
+  MaxX, MaxY:  real;
+begin;
+  Sound := AudioInputProcessor.Sound[NrSound];
+
+  //  Log.LogStatus('Oscilloscope', 'SingDraw');
+  glColor3f(Skin_OscR, Skin_OscG, Skin_OscB);
+{
+  if (ParamStr(1) = '-black') or (ParamStr(1) = '-fsblack') then
+    glColor3f(1, 1, 1);
+}
+  MaxX := W-1;
+  MaxY := (H-1) / 2;
+
+  Sound.LockAnalysisBuffer();
+
+  glBegin(GL_LINE_STRIP);
+    for SampleIndex := 0 to High(Sound.AnalysisBuffer) do
+    begin
+      glVertex2f(X + MaxX * SampleIndex/High(Sound.AnalysisBuffer),
+                 Y + MaxY * (1 - Sound.AnalysisBuffer[SampleIndex]/-Low(Smallint)));
+    end;
+  glEnd;
+
+  Sound.UnlockAnalysisBuffer();
+end;
+
+procedure SingDrawNoteLines(Left, Top, Right: real; Space: integer);
+var
+  Count: integer;
+begin
+  glEnable(GL_BLEND);
+  glColor4f(Skin_P1_LinesR, Skin_P1_LinesG, Skin_P1_LinesB, 0.4);
+  glBegin(GL_LINES);
+  for Count := 0 to 9 do
+  begin
+    glVertex2f(Left,  Top + Count * Space);
+    glVertex2f(Right, Top + Count * Space);
+  end;
+  glEnd;
+  glDisable(GL_BLEND);
+end;
+
+procedure SingDrawBeatDelimeters(Left, Top, Right: real; NrLines: integer);
+var
+  Count: integer;
+  TempR: real;
+begin
+  TempR := (Right-Left) / (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start);
+  glEnable(GL_BLEND);
+  glBegin(GL_LINES);
+  for Count := Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start to Lines[NrLines].Line[Lines[NrLines].Current].End_ do
+  begin
+    if (Count mod Lines[NrLines].Resolution) = Lines[NrLines].NotesGAP then
+      glColor4f(0, 0, 0, 1)
+    else
+      glColor4f(0, 0, 0, 0.3);
+    glVertex2f(Left + TempR * (Count - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start), Top);
+    glVertex2f(Left + TempR * (Count - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start), Top + 135);
+  end;
+  glEnd;
+  glDisable(GL_BLEND);
+end;
+
+// draw blank Notebars
+procedure SingDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer);
+var
+  Rec:   TRecR;
+  Count: integer;
+  TempR: real;
+
+  PlayerNumber:  integer;
+
+  GoldenStarPos: real;
+
+  lTmpA, lTmpB : real;
+begin
+// We actually don't have a playernumber in this procedure, it should reside in NrLines - but it is always set to zero
+// So we exploit this behavior a bit - we give NrLines the playernumber, keep it in playernumber - and then we set NrLines to zero
+// This could also come quite in handy when we do the duet mode, cause just the notes for the player that has to sing should be drawn then
+// BUT this is not implemented yet, all notes are drawn! :D
+  if (ScreenSing.settings.NotesVisible and (1 shl NrLines) <> 0) then
+  begin
+
+    PlayerNumber := NrLines + 1; // Player 1 is 0
+    NrLines     := 0;
+
+  // exploit done
+
+    glColor3f(1, 1, 1);
+    glEnable(GL_TEXTURE_2D);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    lTmpA := (Right-Left);
+    lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start);
+
+  if ( lTmpA > 0 ) and ( lTmpB > 0 ) then
+    TempR := lTmpA / lTmpB
+  else
+    TempR := 0;
+
+  with Lines[NrLines].Line[Lines[NrLines].Current] do
+  begin
+    for Count := 0 to HighNote do
+    begin
+      with Note[Count] do
+      begin
+        if NoteType <> ntFreestyle then
+	begin
+
+            if Ini.EffectSing = 0 then
+              // If Golden note Effect of then Change not Color
+            begin
+              case NoteType of
+                ntNormal: glColor4f(1, 1, 1, 1);   // We set alpha to 1, cause we can control the transparency through the png itself
+                ntGolden: glColor4f(1, 1, 0.3, 1); // no stars, paint yellow -> glColor4f(1, 1, 0.3, 0.85); - we could
+            end; // case
+            end //Else all Notes same Color
+            else
+              glColor4f(1, 1, 1, 1);        // We set alpha to 1, cause we can control the transparency through the png itself
+
+          // left part
+          Rec.Left  := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX;
+          Rec.Right := Rec.Left + NotesW;
+          Rec.Top := Top - (Tone-BaseNote)*Space/2 - NotesH;
+          Rec.Bottom := Rec.Top + 2 * NotesH;
+          glBindTexture(GL_TEXTURE_2D, Tex_plain_Left[PlayerNumber].TexNum);
+          glBegin(GL_QUADS);
+            glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+            glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+            glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+            glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+          glEnd;
+
+            //We keep the postion of the top left corner b4 it's overwritten
+            GoldenStarPos := Rec.Left;
+            //done
+
+            // middle part
+            Rec.Left := Rec.Right;
+            Rec.Right := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - NotesW - 0.5 + 10*ScreenX;
+
+            glBindTexture(GL_TEXTURE_2D, Tex_plain_Mid[PlayerNumber].TexNum);
+            glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+            glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+            glBegin(GL_QUADS);
+              glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+              glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+              glTexCoord2f(round((Rec.Right-Rec.Left)/32), 1); glVertex2f(Rec.Right, Rec.Bottom);
+              glTexCoord2f(round((Rec.Right-Rec.Left)/32), 0); glVertex2f(Rec.Right, Rec.Top);
+            glEnd;
+
+        // right part
+        Rec.Left  := Rec.Right;
+        Rec.Right := Rec.Right + NotesW;
+
+            glBindTexture(GL_TEXTURE_2D, Tex_plain_Right[PlayerNumber].TexNum);
+            glBegin(GL_QUADS);
+              glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+              glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+              glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+              glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+            glEnd;
+
+          // Golden Star Patch
+          if (NoteType = ntGolden) and (Ini.EffectSing=1) then
+          begin
+            GoldenRec.SaveGoldenStarsRec(GoldenStarPos, Rec.Top, Rec.Right, Rec.Bottom);
+          end;
+
+          end; // if not FreeStyle
+        end; // with
+      end; // for
+    end; // with
+
+    glDisable(GL_BLEND);
+    glDisable(GL_TEXTURE_2D);
+  end;
+end;
+
+// draw sung notes
+procedure SingDrawPlayerLine(X, Y, W: real; PlayerIndex: integer; Space: integer);
+var
+  TempR:      real;
+  Rec:        TRecR;
+  N:          integer;
+//  R, G, B, A: real;
+  NotesH2:    real;
+begin
+  //Log.LogStatus('Player notes', 'SingDraw');
+{
+  if NrGracza = 0 then
+    LoadColor(R, G, B, 'P1Light')
+  else
+    LoadColor(R, G, B, 'P2Light');
+}
+  //R :=  71/255;
+  //G := 175/255;
+  //B := 247/255;
+
+  glColor3f(1, 1, 1);
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  //if Player[NrGracza].LengthNote > 0 then
+  begin
+    TempR := W / (Lines[0].Line[Lines[0].Current].End_ - Lines[0].Line[Lines[0].Current].Note[0].Start);
+    for N := 0 to Player[PlayerIndex].HighNote do
+    begin
+      with Player[PlayerIndex].Note[N] do
+      begin
+        // Left part of note
+        Rec.Left  := X + (Start-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR + 0.5 + 10*ScreenX;
+        Rec.Right := Rec.Left + NotesW;
+
+        // Draw it in half size, if not hit
+        if Hit then
+        begin
+          NotesH2 := NotesH
+        end
+        else
+        begin
+          NotesH2 := int(NotesH * 0.65);
+        end;
+
+        Rec.Top    := Y - (Tone-Lines[0].Line[Lines[0].Current].BaseNote)*Space/2 - NotesH2;
+        Rec.Bottom := Rec.Top + 2 * NotesH2;
+
+        // draw the left part
+        glColor3f(1, 1, 1);
+        glBindTexture(GL_TEXTURE_2D, Tex_Left[PlayerIndex+1].TexNum);
+        glBegin(GL_QUADS);
+          glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+          glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+          glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+          glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+        glEnd;
+
+        // Middle part of the note
+        Rec.Left  := Rec.Right;
+        Rec.Right := X + (Start+Length-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR - NotesW - 0.5  + 10*ScreenX;
+
+        // new
+        if (Start+Length-1 = LyricsState.CurrentBeatD) then
+          Rec.Right := Rec.Right - (1-Frac(LyricsState.MidBeatD)) * TempR;
+        // the left note is more right than the right note itself, sounds weird - so we fix that xD
+        if Rec.Right <= Rec.Left then
+          Rec.Right := Rec.Left;
+
+        // draw the middle part
+        glBindTexture(GL_TEXTURE_2D, Tex_Mid[PlayerIndex+1].TexNum);
+        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+        glBegin(GL_QUADS);
+          glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+          glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+          glTexCoord2f(round((Rec.Right-Rec.Left)/32), 1); glVertex2f(Rec.Right, Rec.Bottom);
+          glTexCoord2f(round((Rec.Right-Rec.Left)/32), 0); glVertex2f(Rec.Right, Rec.Top);
+        glEnd;
+        glColor3f(1, 1, 1);
+
+        // the right part of the note
+        Rec.Left  := Rec.Right;
+        Rec.Right := Rec.Right + NotesW;
+
+        glBindTexture(GL_TEXTURE_2D, Tex_Right[PlayerIndex+1].TexNum);
+        glBegin(GL_QUADS);
+          glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+          glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+          glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+          glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+        glEnd;
+
+        // Perfect note is stored
+        if Perfect and (Ini.EffectSing=1) then
+        begin
+          //A := 1 - 2*(LyricsState.GetCurrentTime() - GetTimeFromBeat(Start+Length));
+          if not (Start+Length-1 = LyricsState.CurrentBeatD) then
+          begin
+            //Star animation counter
+            //inc(Starfr);
+            //Starfr := Starfr mod 128;
+            GoldenRec.SavePerfectNotePos(Rec.Left, Rec.Top);
+          end;
+        end;
+      end; // with
+    end; // for
+
+    // actually we need a comparison here, to determine if the singing process
+    // is ahead Rec.Right even if there is no singing
+
+    if (Ini.EffectSing = 1) then
+      GoldenRec.GoldenNoteTwinkle(Rec.Top,Rec.Bottom,Rec.Right, PlayerIndex);
+  end; // if
+end;
+
+//draw Note glow
+procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, PlayerIndex: integer; Space: integer);
+var
+  Rec:            TRecR;
+  Count:          integer;
+  TempR:          real;
+  X1, X2, X3, X4: real;
+  W, H:           real;
+  lTmpA, lTmpB:   real;
+begin
+  if (ScreenSing.settings.NotesVisible and (1 shl PlayerIndex) <> 0) then
+  begin
+    glColor4f(1, 1, 1, sqrt((1+sin( AudioPlayback.Position * 3))/4)/ 2 + 0.5 );
+    glEnable(GL_TEXTURE_2D);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    lTmpA := (Right-Left);
+    lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start);
+
+    if ( lTmpA > 0 ) and ( lTmpB > 0 ) then
+      TempR := lTmpA / lTmpB
+    else
+      TempR := 0;
+
+    with Lines[NrLines].Line[Lines[NrLines].Current] do
+    begin
+      for Count := 0 to HighNote do
+      begin
+        with Note[Count] do
+        begin
+          if NoteType <> ntFreestyle then
+          begin
+            // begin: 14, 20
+            // easy: 6, 11
+            W := NotesW * 2 + 2;
+            H := NotesH * 1.5 + 3.5;
+
+            X2 := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX + 4;
+            X1 := X2-W;
+
+            X3 := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - 0.5 + 10*ScreenX - 4;
+            X4 := X3+W;
+
+            // left
+            Rec.Left  := X1;
+            Rec.Right := X2;
+            Rec.Top := Top - (Tone-BaseNote)*Space/2 - H;
+            Rec.Bottom := Rec.Top + 2 * H;
+
+            glBindTexture(GL_TEXTURE_2D, Tex_BG_Left[PlayerIndex+1].TexNum);
+            glBegin(GL_QUADS);
+              glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+              glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+              glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+              glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+            glEnd;
+
+            // middle part
+            Rec.Left  := X2;
+            Rec.Right := X3;
+
+            glBindTexture(GL_TEXTURE_2D, Tex_BG_Mid[PlayerIndex+1].TexNum);
+            glBegin(GL_QUADS);
+              glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+              glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+              glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+              glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+            glEnd;
+
+            // right part
+            Rec.Left  := X3;
+            Rec.Right := X4;
+
+            glBindTexture(GL_TEXTURE_2D, Tex_BG_Right[PlayerIndex+1].TexNum);
+            glBegin(GL_QUADS);
+              glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+              glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+              glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+              glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+            glEnd;
+          end; // if not FreeStyle
+        end; // with
+      end; // for
+    end; // with
+
+    glDisable(GL_BLEND);
+    glDisable(GL_TEXTURE_2D);
+  end;
+end;
+
+(**
+ * Draws the lyrics helper bar.
+ * Left: position the bar starts at
+ * LyricsMid: the middle of the lyrics relative to the position Left 
+ *)
+procedure SingDrawLyricHelper(Left, LyricsMid: real);
+var
+  Bounds: TRecR;           // bounds of the lyric help bar
+  BarProgress: real;       // progress of the lyrics helper
+  BarMoveDelta: real;      // current beat relative to the beat the bar starts to move at
+  BarAlpha: real;          // transparency
+  CurLine:  PLine;         // current lyric line (beat specific)
+  LineWidth: real;         // lyric line width
+  FirstNoteBeat: integer;  // beat of the first note in the current line
+  FirstNoteDelta: integer; // time in beats between the start of the current line and its first note
+  MoveStartX: real;        // x-pos. the bar starts to move from
+  MoveDist: real;          // number of pixels the bar will move
+  LyricEngine: TLyricEngine;
+const
+  BarWidth  = 50; // width  of the lyric helper bar
+  BarHeight = 30; // height of the lyric helper bar
+  BarMoveLimit = 40; // max. number of beats remaining before the bar starts to move
+begin
+  // get current lyrics line and the time in beats of its first note
+  CurLine := @Lines[0].Line[Lines[0].Current];
+
+  // FIXME: accessing ScreenSing is not that generic
+  LyricEngine := ScreenSing.Lyrics;
+
+  // do not draw the lyrics helper if the current line does not contain any note
+  if (Length(CurLine.Note) > 0) then
+  begin
+    // start beat of the first note of this line
+    FirstNoteBeat := CurLine.Note[0].Start;
+    // time in beats between the start of the current line and its first note
+    FirstNoteDelta := FirstNoteBeat - CurLine.Start;
+
+    // beats from current beat to the first note of the line
+    BarMoveDelta := FirstNoteBeat - LyricsState.MidBeat;
+
+    if (FirstNoteDelta > 8) and  // if the wait-time is large enough
+       (BarMoveDelta > 0) then   // and the first note of the line is not reached
+    begin
+      // let the bar blink to the beat
+      BarAlpha := 0.75 + cos(BarMoveDelta/2) * 0.25;
+
+      // if the number of beats to the first note is too big,
+      // the bar stays on the left side.
+      if (BarMoveDelta > BarMoveLimit) then
+        BarMoveDelta := BarMoveLimit;
+
+      // limit number of beats the bar moves
+      if (FirstNoteDelta > BarMoveLimit) then
+        FirstNoteDelta := BarMoveLimit;
+
+      // calc bar progress
+      BarProgress := 1 - BarMoveDelta / FirstNoteDelta;
+
+      // retrieve the width of the upper lyrics line on the display
+      if (LyricEngine.GetUpperLine() <> nil) then
+        LineWidth := LyricEngine.GetUpperLine().Width
+      else
+        LineWidth := 0;
+
+      // distance the bar will move (LyricRec.Left to beginning of text)
+      MoveDist := LyricsMid - LineWidth / 2 - BarWidth;
+      // if the line is too long the helper might move from right to left
+      // so we have to assure the start position is left of the text.
+      if (MoveDist >= 0) then
+        MoveStartX := Left
+      else
+        MoveStartX := Left + MoveDist;
+
+      // determine lyric help bar position and size
+      Bounds.Left := MoveStartX + BarProgress * MoveDist;
+      Bounds.Right := Bounds.Left + BarWidth;
+      Bounds.Top := Theme.LyricBar.IndicatorYOffset + Theme.LyricBar.UpperY ;
+      Bounds.Bottom := Bounds.Top + BarHeight + 3;
+
+      // draw lyric help bar
+      glEnable(GL_TEXTURE_2D);
+      glEnable(GL_BLEND);
+      glColor4f(1, 1, 1, BarAlpha);
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+      glBindTexture(GL_TEXTURE_2D, Tex_Lyric_Help_Bar.TexNum);
+      glBegin(GL_QUADS);
+        glTexCoord2f(0, 0); glVertex2f(Bounds.Left,  Bounds.Top);
+        glTexCoord2f(0, 1); glVertex2f(Bounds.Left,  Bounds.Bottom);
+        glTexCoord2f(1, 1); glVertex2f(Bounds.Right, Bounds.Bottom);
+        glTexCoord2f(1, 0); glVertex2f(Bounds.Right, Bounds.Top);
+      glEnd;
+      glDisable(GL_BLEND);
+    end;
+  end;
+end;
+
+procedure SingDraw;
+var
+  NR: TRecR;         // lyrics area bounds (NR = NoteRec?)
+  LyricEngine: TLyricEngine;
+begin
+  // positions
+  if Ini.SingWindow = 0 then
+    NR.Left := 120
+  else
+    NR.Left := 20;
+
+  NR.Right := 780;
+
+  NR.Width := NR.Right - NR.Left;
+  NR.WMid  := NR.Width / 2;
+  NR.Mid   := NR.Left + NR.WMid;
+
+  // FIXME: accessing ScreenSing is not that generic
+  LyricEngine := ScreenSing.Lyrics;
+
+  // draw time-bar
+  SingDrawTimeBar();
+
+  // draw note-lines
+
+  // to-do : needs fix when party mode works w/ 2 screens 
+  if (PlayersPlay = 1) and (Ini.NoteLines = 1) and (ScreenSing.settings.NotesVisible and (1) <> 0) then
+    SingDrawNoteLines(NR.Left + 10*ScreenX, Skin_P2_NotesB - 105, NR.Right + 10*ScreenX, 15);
+
+  if ((PlayersPlay = 2) or (PlayersPlay = 4)) and (Ini.NoteLines = 1) then
+  begin
+    if (ScreenSing.settings.NotesVisible and (1 shl 0) <> 0) then
+      SingDrawNoteLines(Nr.Left + 10*ScreenX, Skin_P1_NotesB - 105, Nr.Right + 10*ScreenX, 15);
+    if (ScreenSing.settings.NotesVisible and (1 shl 1) <> 0) then
+      SingDrawNoteLines(Nr.Left + 10*ScreenX, Skin_P2_NotesB - 105, Nr.Right + 10*ScreenX, 15);
+  end;
+
+  if ((PlayersPlay = 3) or (PlayersPlay = 6)) and (Ini.NoteLines = 1) then begin
+    if (ScreenSing.settings.NotesVisible and (1 shl 0) <> 0) then
+      SingDrawNoteLines(Nr.Left + 10*ScreenX, 120, Nr.Right + 10*ScreenX, 12);
+    if (ScreenSing.settings.NotesVisible and (1 shl 1) <> 0) then
+      SingDrawNoteLines(Nr.Left + 10*ScreenX, 245, Nr.Right + 10*ScreenX, 12);
+    if (ScreenSing.settings.NotesVisible and (1 shl 2) <> 0) then
+      SingDrawNoteLines(Nr.Left + 10*ScreenX, 370, Nr.Right + 10*ScreenX, 12);
+  end;
+
+  // draw Lyrics
+  LyricEngine.Draw(LyricsState.MidBeat);
+  SingDrawLyricHelper(NR.Left, NR.WMid);
+
+  // oscilloscope
+  if Ini.Oscilloscope = 1 then
+  begin
+    if PlayersPlay = 1 then
+      SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
+
+    if PlayersPlay = 2 then
+    begin
+      SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
+      SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
+    end;
+
+    if PlayersPlay = 4 then
+    begin
+      if ScreenAct = 1 then
+      begin
+        SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
+        SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
+      end;
+      if ScreenAct = 2 then
+      begin
+        SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2);
+        SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3);
+      end;
+    end;
+
+    if PlayersPlay = 3 then
+    begin
+      SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0);
+      SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
+      SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
+    end;
+
+    if PlayersPlay = 6 then
+    begin
+      if ScreenAct = 1 then
+      begin
+        SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0);
+        SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
+        SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
+      end;
+      if ScreenAct = 2 then
+      begin
+        SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3);
+        SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4);
+        SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5);
+      end;
+    end;
+
+  end;
+
+  // Set the note heights according to the difficulty level
+  case Ini.Difficulty of
+    0:
+      begin
+        NotesH := 11; // 9
+        NotesW := 6; // 5
+      end;
+    1:
+      begin
+        NotesH := 8; // 7
+        NotesW := 4; // 4
+      end;
+    2:
+      begin
+        NotesH := 5;
+        NotesW := 3;
+      end;
+  end;
+
+  // Draw the Notes
+  if PlayersPlay = 1 then
+  begin
+    SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 0, 15);  // Background glow    - colorized in playercolor
+    SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15);             // Plain unsung notes - colorized in playercolor
+    SingDrawPlayerLine(NR.Left + 20, Skin_P2_NotesB, NR.Width - 40, 0, 15);       // imho the sung notes
+  end;
+
+  if PlayersPlay = 2 then
+  begin
+    SingDrawPlayerBGLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 0, 15);
+    SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 1, 15);
+
+    SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15);
+    SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 1, 15);
+
+    SingDrawPlayerLine(NR.Left + 20, Skin_P1_NotesB, NR.Width - 40, 0, 15);
+    SingDrawPlayerLine(NR.Left + 20, Skin_P2_NotesB, NR.Width - 40, 1, 15);
+  end;
+
+  if PlayersPlay = 3 then
+  begin
+    NotesW := NotesW * 0.8;
+    NotesH := NotesH * 0.8;
+
+    SingDrawPlayerBGLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 0, 12);
+    SingDrawPlayerBGLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 1, 12);
+    SingDrawPlayerBGLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 2, 12);
+
+    SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12);
+    SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 1, 12);
+    SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 2, 12);
+
+    SingDrawPlayerLine(NR.Left + 20, 120+95, NR.Width - 40, 0, 12);
+    SingDrawPlayerLine(NR.Left + 20, 245+95, NR.Width - 40, 1, 12);
+    SingDrawPlayerLine(NR.Left + 20, 370+95, NR.Width - 40, 2, 12);
+  end;
+
+  if PlayersPlay = 4 then
+  begin
+    if ScreenAct = 1 then
+    begin
+      SingDrawPlayerBGLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 0, 15);
+      SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 1, 15);
+    end;
+    if ScreenAct = 2 then
+    begin
+      SingDrawPlayerBGLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 2, 15);
+      SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 3, 15);
+    end;
+
+    if ScreenAct = 1 then
+    begin
+      SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15);
+      SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 1, 15);
+    end;
+    if ScreenAct = 2 then
+    begin
+      SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 2, 15);
+      SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 3, 15);
+    end;
+
+    if ScreenAct = 1 then
+    begin
+      SingDrawPlayerLine(NR.Left + 20, Skin_P1_NotesB, NR.Width - 40, 0, 15);
+      SingDrawPlayerLine(NR.Left + 20, Skin_P2_NotesB, NR.Width - 40, 1, 15);
+    end;
+    if ScreenAct = 2 then
+    begin
+      SingDrawPlayerLine(NR.Left + 20, Skin_P1_NotesB, NR.Width - 40, 2, 15);
+      SingDrawPlayerLine(NR.Left + 20, Skin_P2_NotesB, NR.Width - 40, 3, 15);
+    end;
+  end;
+
+  if PlayersPlay = 6 then
+  begin
+    NotesW := NotesW * 0.8;
+    NotesH := NotesH * 0.8;
+
+    if ScreenAct = 1 then
+    begin
+      SingDrawPlayerBGLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 0, 12);
+      SingDrawPlayerBGLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 1, 12);
+      SingDrawPlayerBGLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 2, 12);
+    end;
+    if ScreenAct = 2 then
+    begin
+      SingDrawPlayerBGLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 3, 12);
+      SingDrawPlayerBGLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 4, 12);
+      SingDrawPlayerBGLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 5, 12);
+    end;
+
+    if ScreenAct = 1 then
+    begin
+      SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12);
+      SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 1, 12);
+      SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 2, 12);
+    end;
+    if ScreenAct = 2 then
+    begin
+      SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 3, 12);
+      SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 4, 12);
+      SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 5, 12);
+    end;
+
+    if ScreenAct = 1 then
+    begin
+      SingDrawPlayerLine(NR.Left + 20, 120+95, NR.Width - 40, 0, 12);
+      SingDrawPlayerLine(NR.Left + 20, 245+95, NR.Width - 40, 1, 12);
+      SingDrawPlayerLine(NR.Left + 20, 370+95, NR.Width - 40, 2, 12);
+    end;
+    if ScreenAct = 2 then
+    begin
+      SingDrawPlayerLine(NR.Left + 20, 120+95, NR.Width - 40, 3, 12);
+      SingDrawPlayerLine(NR.Left + 20, 245+95, NR.Width - 40, 4, 12);
+      SingDrawPlayerLine(NR.Left + 20, 370+95, NR.Width - 40, 5, 12);
+    end;
+  end;
+  glDisable(GL_BLEND);
+  glDisable(GL_TEXTURE_2D);
+end;
+
+{//SingBar Mod
+procedure SingDrawSingbar(X, Y, W, H: real; Percent: integer);
+var
+  R: real;
+  G: real;
+  B: real;
+  A: cardinal;
+  I: integer;
+
+begin;
+
+   //SingBar Background
+  glColor4f(1, 1, 1, 0.8);
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Back.TexNum);
+  glBegin(GL_QUADS);
+    glTexCoord2f(0, 0); glVertex2f(X, Y);
+    glTexCoord2f(0, 1); glVertex2f(X, Y+H);
+    glTexCoord2f(1, 1); glVertex2f(X+W, Y+H);
+    glTexCoord2f(1, 0); glVertex2f(X+W, Y);
+  glEnd;
+
+  //SingBar coloured Bar
+  case Percent of
+    0..22: begin
+          R := 1;
+          G := 0;
+          B := 0;
+        end;
+    23..42: begin
+          R := 1;
+          G := ((Percent-23)/100)*5;
+          B := 0;
+        end;
+    43..57: begin
+          R := 1;
+          G := 1;
+          B := 0;
+        end;
+    58..77: begin
+          R := 1-(Percent - 58)/100*5;
+          G := 1;
+          B := 0;
+        end;
+    78..99: begin
+          R := 0;
+          G := 1;
+          B := 0;
+        end;
+    end; //case
+
+  glColor4f(R, G, B, 1);
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Bar.TexNum);
+  //Size= Player[PlayerNum].ScorePercent of W
+    glBegin(GL_QUADS);
+    glTexCoord2f(0, 0); glVertex2f(X, Y);
+    glTexCoord2f(0, 1); glVertex2f(X, Y+H);
+    glTexCoord2f(1, 1); glVertex2f(X+(W/100 * (Percent +1)), Y+H);
+    glTexCoord2f(1, 0); glVertex2f(X+(W/100 * (Percent +1)), Y);
+  glEnd;
+
+  //SingBar Front
+  glColor4f(1, 1, 1, 0.6);
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Front.TexNum);
+  glBegin(GL_QUADS);
+    glTexCoord2f(0, 0); glVertex2f(X, Y);
+    glTexCoord2f(0, 1); glVertex2f(X, Y+H);
+    glTexCoord2f(1, 1); glVertex2f(X+W, Y+H);
+    glTexCoord2f(1, 0); glVertex2f(X+W, Y);
+  glEnd;
+end;
+//end Singbar Mod
+
+//PhrasenBonus - Line Bonus Pop Up
+procedure SingDrawLineBonus(const X, Y: Single; Color: TRGB; Alpha: Single; Text: string; Age: integer);
+var
+  Length, X2: real; //Length of Text
+  Size: integer;    //Size of Popup
+begin
+  if Alpha <> 0 then
+  begin
+
+//Set Font Propertys
+    SetFontStyle(2); //Font: Outlined1
+    if Age < 5 then
+      SetFontSize((Age + 1) * 3)
+    else
+      SetFontSize(18);
+    SetFontItalic(False);
+
+//Check Font Size
+    Length := glTextWidth (Text) + 3; //Little Space for a Better Look ^^
+
+//Text
+    SetFontPos (X + 50 - (Length / 2), Y + 12); //Position
+
+    if Age < 5 then
+      Size := Age * 10
+    else
+      Size := 50;
+
+//Draw  Background
+//    glColor4f(Color.R, Color.G, Color.B, Alpha); //Set Color
+    glColor4f(1, 1, 1, Alpha);
+
+    glEnable(GL_TEXTURE_2D);
+    glEnable(GL_BLEND);
+//    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+//New Method, Not Variable
+    glBindTexture(GL_TEXTURE_2D, Tex_SingLineBonusBack[2].TexNum);
+
+    glBegin(GL_QUADS);
+      glTexCoord2f(0, 0); glVertex2f(X + 50 - Size, Y + 25 - (Size/2));
+      glTexCoord2f(0, 1); glVertex2f(X + 50 - Size, Y + 25 + (Size/2));
+      glTexCoord2f(1, 1); glVertex2f(X + 50 + Size, Y + 25 + (Size/2));
+      glTexCoord2f(1, 0); glVertex2f(X + 50 + Size, Y + 25 - (Size/2));
+    glEnd;
+
+    glColor4f(1, 1, 1, Alpha); //Set Color
+//Draw Text
+    glPrint (Text);
+  end;
+end;
+//PhrasenBonus - Line Bonus Mod}
+
+// Draw Note Bars for Editor
+// There are 11 reasons for a new procedure:   (nice binary :D )
+// 1. It does not look good when you draw the golden note star effect in the editor
+// 2. You can see the freestyle notes in the editor semitransparent
+// 3. It is easier and faster then changing the old procedure
+procedure EditDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer);
+var
+  Rec:   TRecR;
+  Count: integer;
+  TempR: real;
+begin
+  glColor3f(1, 1, 1);
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  TempR := (Right-Left) / (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start);
+  with Lines[NrLines].Line[Lines[NrLines].Current] do
+  begin
+    for Count := 0 to HighNote do
+    begin
+      with Note[Count] do
+      begin
+
+        // Golden Note Patch
+        case NoteType of
+          ntFreestyle: glColor4f(1, 1, 1, 0.35);
+          ntNormal: glColor4f(1, 1, 1, 0.85);
+          ntGolden: Glcolor4f(1, 1, 0.3, 0.85);
+        end; // case
+
+        // left part
+        Rec.Left  := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX;
+        Rec.Right := Rec.Left + NotesW;
+        Rec.Top := Top - (Tone-BaseNote)*Space/2 - NotesH;
+        Rec.Bottom := Rec.Top + 2 * NotesH;
+        glBindTexture(GL_TEXTURE_2D, Tex_Left[Color].TexNum);
+        glBegin(GL_QUADS);
+          glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+          glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+          glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+          glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+        glEnd;
+
+        // middle part
+        Rec.Left  := Rec.Right;
+        Rec.Right := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - NotesW - 0.5 + 10*ScreenX;
+
+        glBindTexture(GL_TEXTURE_2D, Tex_Mid[Color].TexNum);
+        glBegin(GL_QUADS);
+          glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+          glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+          glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+          glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+        glEnd;
+
+        // right part
+        Rec.Left  := Rec.Right;
+        Rec.Right := Rec.Right + NotesW;
+
+        glBindTexture(GL_TEXTURE_2D, Tex_Right[Color].TexNum);
+        glBegin(GL_QUADS);
+          glTexCoord2f(0, 0); glVertex2f(Rec.Left,  Rec.Top);
+          glTexCoord2f(0, 1); glVertex2f(Rec.Left,  Rec.Bottom);
+          glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+          glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+        glEnd;
+
+      end; // with
+    end; // for
+  end; // with
+
+  glDisable(GL_BLEND);
+  glDisable(GL_TEXTURE_2D);
+end;
+
+procedure SingDrawTimeBar();
+var
+  x, y:           real;
+  width, height:  real;
+  LyricsProgress: real;
+  CurLyricsTime:  real;
+begin
+  x := Theme.Sing.StaticTimeProgress.x;
+  y := Theme.Sing.StaticTimeProgress.y;
+
+  width  := Theme.Sing.StaticTimeProgress.w;
+  height := Theme.Sing.StaticTimeProgress.h;
+
+  glColor4f(Theme.Sing.StaticTimeProgress.ColR,
+            Theme.Sing.StaticTimeProgress.ColG,
+            Theme.Sing.StaticTimeProgress.ColB, 1); //Set Color
+
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+
+  glBindTexture(GL_TEXTURE_2D, Tex_TimeProgress.TexNum);
+
+  glBegin(GL_QUADS);
+    glTexCoord2f(0, 0);
+    glVertex2f(x, y);
+
+    CurLyricsTime := LyricsState.GetCurrentTime();
+    if (CurLyricsTime > 0) and
+       (LyricsState.TotalTime > 0) then
+    begin
+      LyricsProgress := CurLyricsTime / LyricsState.TotalTime;
+      // avoid that the bar "overflows" for inaccurate song lengths
+      if (LyricsProgress > 1.0) then
+        LyricsProgress := 1.0;
+      glTexCoord2f((width * LyricsProgress) / 8, 0);
+      glVertex2f(x + width * LyricsProgress, y);
+
+      glTexCoord2f((width * LyricsProgress) / 8, 1);
+      glVertex2f(x + width * LyricsProgress, y + height);
+    end;
+
+    glTexCoord2f(0, 1);
+    glVertex2f(x, y + height);
+  glEnd;
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glcolor4f(1, 1, 1, 1);
+end;
+
+end.
+
diff --git a/songmanagement/src/base/UEditorLyrics.pas b/songmanagement/src/base/UEditorLyrics.pas
new file mode 100644
index 00000000..5030eff5
--- /dev/null
+++ b/songmanagement/src/base/UEditorLyrics.pas
@@ -0,0 +1,260 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UEditorLyrics;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  gl,
+  UMusic,
+  UTexture;
+
+type
+  TAlignmentType = (atLeft, atCenter, atRight);
+
+  TWord = record
+    X:         real;
+    Y:         real;
+    Size:      real;
+    Width:     real;
+    Text:      string;
+    ColR:      real;
+    ColG:      real;
+    ColB:      real;
+    FontStyle: integer;
+    Italic:    boolean;
+    Selected:  boolean;
+  end;
+
+  TEditorLyrics = class
+    private
+      AlignI:     TAlignmentType;
+      XR:         real;
+      YR:         real;
+      SizeR:      real;
+      SelectedI:  integer;
+      FontStyleI: integer;          // font number
+      Word:       array of TWord;
+
+      procedure SetX(Value: real);
+      procedure SetY(Value: real);
+      function GetClientX: real;
+      procedure SetAlign(Value: TAlignmentType);
+      function GetSize: real;
+      procedure SetSize(Value: real);
+      procedure SetSelected(Value: integer);
+      procedure SetFontStyle(Value: integer);
+      procedure AddWord(Text: UTF8String);
+      procedure Refresh;
+    public
+      ColR:   real;
+      ColG:   real;
+      ColB:   real;
+      ColSR:  real;
+      ColSG:  real;
+      ColSB:  real;
+      Italic: boolean;
+
+      constructor Create;
+      destructor Destroy; override;
+
+      procedure AddLine(NrLine: integer);
+
+      procedure Clear;
+      procedure Draw;
+    published
+      property X: real write SetX;
+      property Y: real write SetY;
+      property ClientX: real read GetClientX;
+      property Align: TAlignmentType write SetAlign;
+      property Size: real read GetSize write SetSize;
+      property Selected: integer read SelectedI write SetSelected;
+      property FontStyle: integer write SetFontStyle;
+  end;
+
+implementation
+
+uses
+  TextGL,
+  UGraphic,
+  UDrawTexture,
+  Math,
+  USkins;
+
+constructor TEditorLyrics.Create;
+begin
+  inherited;
+end;
+
+destructor TEditorLyrics.Destroy;
+begin
+  SetLength(Word, 0);
+  inherited;
+end;
+
+procedure TEditorLyrics.SetX(Value: real);
+begin
+  XR := Value;
+end;
+
+procedure TEditorLyrics.SetY(Value: real);
+begin
+  YR := Value;
+end;
+
+function TEditorLyrics.GetClientX: real;
+begin
+  Result := Word[0].X;
+end;
+
+procedure TEditorLyrics.SetAlign(Value: TAlignmentType);
+begin
+  AlignI := Value;
+end;
+
+function TEditorLyrics.GetSize: real;
+begin
+  Result := SizeR;
+end;
+
+procedure TEditorLyrics.SetSize(Value: real);
+begin
+  SizeR := Value;
+end;
+
+procedure TEditorLyrics.SetSelected(Value: integer);
+begin
+  if (-1 < SelectedI) and (SelectedI <= High(Word)) then
+  begin
+    Word[SelectedI].Selected := false;
+    Word[SelectedI].ColR := ColR;
+    Word[SelectedI].ColG := ColG;
+    Word[SelectedI].ColB := ColB;
+  end;
+
+  SelectedI := Value;
+  if (-1 < Value) and (Value <= High(Word)) then
+  begin
+    Word[Value].Selected := true;
+    Word[Value].ColR := ColSR;
+    Word[Value].ColG := ColSG;
+    Word[Value].ColB := ColSB;
+  end;
+
+  Refresh;
+end;
+
+procedure TEditorLyrics.SetFontStyle(Value: integer);
+begin
+  FontStyleI := Value;
+end;
+
+procedure TEditorLyrics.AddWord(Text: UTF8String);
+var
+  WordNum: integer;
+begin
+  WordNum := Length(Word);
+  SetLength(Word, WordNum + 1);
+  if WordNum = 0 then
+    Word[WordNum].X := XR
+  else
+    Word[WordNum].X := Word[WordNum - 1].X + Word[WordNum - 1].Width;
+
+  Word[WordNum].Y := YR;
+  Word[WordNum].Size := SizeR;
+  Word[WordNum].FontStyle := FontStyleI;
+  SetFontStyle(FontStyleI);
+  SetFontSize(SizeR);
+  SetFontItalic(Italic);
+  Word[WordNum].Width := glTextWidth(Text);
+  Word[WordNum].Text := Text;
+  Word[WordNum].ColR := ColR;
+  Word[WordNum].ColG := ColG;
+  Word[WordNum].ColB := ColB;
+  Word[WordNum].Italic := Italic;
+
+  Refresh;
+end;
+
+procedure TEditorLyrics.AddLine(NrLine: integer);
+var
+  NoteIndex: integer;
+begin
+  Clear;
+  for NoteIndex := 0 to Lines[0].Line[NrLine].HighNote do
+  begin
+    Italic := Lines[0].Line[NrLine].Note[NoteIndex].NoteType = ntFreestyle;
+    AddWord(Lines[0].Line[NrLine].Note[NoteIndex].Text);
+  end;
+  Selected := -1;
+end;
+
+procedure TEditorLyrics.Clear;
+begin
+  SetLength(Word, 0);
+  SelectedI := -1;
+end;
+
+procedure TEditorLyrics.Refresh;
+var
+  WordIndex:  integer;
+  TotalWidth: real;
+begin
+  if AlignI = atCenter then
+  begin
+    TotalWidth := 0;
+    for WordIndex := 0 to High(Word) do
+      TotalWidth := TotalWidth + Word[WordIndex].Width;
+
+    Word[0].X := XR - TotalWidth / 2;
+    for WordIndex := 1 to High(Word) do
+      Word[WordIndex].X := Word[WordIndex - 1].X + Word[WordIndex - 1].Width;
+  end;
+end;
+
+procedure TEditorLyrics.Draw;
+var
+  WordIndex: integer;
+begin
+  for WordIndex := 0 to High(Word) do
+  begin
+    SetFontStyle(Word[WordIndex].FontStyle);
+    SetFontPos(Word[WordIndex].X + 10*ScreenX, Word[WordIndex].Y);
+    SetFontSize(Word[WordIndex].Size);
+    SetFontItalic(Word[WordIndex].Italic);
+    glColor3f(Word[WordIndex].ColR, Word[WordIndex].ColG, Word[WordIndex].ColB);
+    glPrint(Word[WordIndex].Text);
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/base/UFiles.pas b/songmanagement/src/base/UFiles.pas
new file mode 100644
index 00000000..1a7ca8f8
--- /dev/null
+++ b/songmanagement/src/base/UFiles.pas
@@ -0,0 +1,214 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UFiles;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+{$I switches.inc}
+
+uses
+  SysUtils,
+  Classes,
+  ULog,
+  UMusic,
+  USongs,
+  USong,
+  UPath;
+
+procedure ResetSingTemp;
+
+type
+  TSaveSongResult = (ssrOK, ssrFileError, ssrEncodingError);
+
+{**
+ * Throws a TEncodingException if the song's fields cannot be encoded in the
+ * requested encoding.
+ *}
+function SaveSong(const Song: TSong; const Lines: TLines; const Name: IPath; Relative: boolean): TSaveSongResult;
+
+implementation
+
+uses
+  TextGL,
+  UIni,
+  UNote,
+  UPlatform,
+  UUnicodeUtils,
+  UTextEncoding;
+
+//--------------------
+// Resets the temporary Sentence Arrays for each Player and some other Variables
+//--------------------
+procedure ResetSingTemp;
+var
+  Count:  integer;
+begin
+  SetLength(Lines, Length(Player));
+  for Count := 0 to High(Player) do begin
+    SetLength(Lines[Count].Line, 1);
+    SetLength(Lines[Count].Line[0].Note, 0);
+    Lines[Count].Line[0].Lyric := '';
+    Player[Count].Score := 0;
+    Player[Count].LengthNote := 0;
+    Player[Count].HighNote := -1;
+  end;
+end;
+
+//--------------------
+// Saves a Song
+//--------------------
+function SaveSong(const Song: TSong; const Lines: TLines; const Name: IPath; Relative: boolean): TSaveSongResult;
+var
+  C:      integer;
+  N:      integer;
+  S:      AnsiString;
+  B:      integer;
+  RelativeSubTime: integer;
+  NoteState: AnsiString;
+  SongFile: TTextFileStream;
+
+  function EncodeToken(const Str: UTF8String): RawByteString;
+  var
+    Success: boolean;
+  begin
+    Success := EncodeStringUTF8(Str, Result, Song.Encoding);
+    if (not Success) then
+      SaveSong := ssrEncodingError;
+  end;
+
+  procedure WriteCustomTags;
+    var
+      I: integer;
+      Line: RawByteString;
+  begin
+    for I := 0 to High(Song.CustomTags) do
+    begin
+      Line := EncodeToken(Song.CustomTags[I].Content);
+      if (Length(Song.CustomTags[I].Tag) > 0) then
+        Line := EncodeToken(Song.CustomTags[I].Tag) + ':' + Line;
+
+      SongFile.WriteLine('#' + Line);
+    end;
+
+  end;
+
+begin
+  //  Relative := true; // override (idea - use shift+S to save with relative)
+  Result := ssrOK;
+
+  try
+    SongFile := TMemTextFileStream.Create(Name, fmCreate);
+    try
+      // to-do: should we really write the BOM?
+      //        it causes problems w/ older versions
+      //        e.g. usdx 1.0.1a or ultrastar < 0.7.0
+      if (Song.Encoding = encUTF8) then
+        SongFile.WriteString(UTF8_BOM);
+
+      // do not save "auto" encoding tag
+      if (Song.Encoding <> encAuto) then
+        SongFile.WriteLine('#ENCODING:' + EncodingName(Song.Encoding));
+      SongFile.WriteLine('#TITLE:'    + EncodeToken(Song.Title));
+      SongFile.WriteLine('#ARTIST:'   + EncodeToken(Song.Artist));
+
+      if Song.Creator     <> ''        then SongFile.WriteLine('#CREATOR:'   + EncodeToken(Song.Creator));
+      if Song.Edition     <> 'Unknown' then SongFile.WriteLine('#EDITION:'   + EncodeToken(Song.Edition));
+      if Song.Genre       <> 'Unknown' then SongFile.WriteLine('#GENRE:'     + EncodeToken(Song.Genre));
+      if Song.Language    <> 'Unknown' then SongFile.WriteLine('#LANGUAGE:'  + EncodeToken(Song.Language));
+      if Song.Year        <> 0         then SongFile.WriteLine('#YEAR:'      + IntToStr(Song.Year));
+
+      SongFile.WriteLine('#MP3:' + EncodeToken(Song.Mp3.ToUTF8));
+      if Song.Cover.IsSet      then    SongFile.WriteLine('#COVER:'       + EncodeToken(Song.Cover.ToUTF8));
+      if Song.Background.IsSet then    SongFile.WriteLine('#BACKGROUND:'  + EncodeToken(Song.Background.ToUTF8));
+      if Song.Video.IsSet      then    SongFile.WriteLine('#VIDEO:'       + EncodeToken(Song.Video.ToUTF8));
+
+      if Song.VideoGAP    <> 0  then    SongFile.WriteLine('#VIDEOGAP:'    + FloatToStr(Song.VideoGAP));
+      if Song.Resolution  <> 4  then    SongFile.WriteLine('#RESOLUTION:'  + IntToStr(Song.Resolution));
+      if Song.NotesGAP    <> 0  then    SongFile.WriteLine('#NOTESGAP:'    + IntToStr(Song.NotesGAP));
+      if Song.Start       <> 0  then    SongFile.WriteLine('#START:'       + FloatToStr(Song.Start));
+      if Song.Finish      <> 0  then    SongFile.WriteLine('#END:'         + IntToStr(Song.Finish));
+      if Relative               then    SongFile.WriteLine('#RELATIVE:yes');
+
+      SongFile.WriteLine('#BPM:' + FloatToStr(Song.BPM[0].BPM / 4));
+      SongFile.WriteLine('#GAP:' + FloatToStr(Song.GAP));
+
+      // write custom header tags
+      WriteCustomTags;
+
+      RelativeSubTime := 0;
+      for B := 1 to High(Song.BPM) do
+        SongFile.WriteLine('B ' + FloatToStr(Song.BPM[B].StartBeat) + ' '
+                                + FloatToStr(Song.BPM[B].BPM/4));
+
+      for C := 0 to Lines.High do
+      begin
+        for N := 0 to Lines.Line[C].HighNote do
+        begin
+          with Lines.Line[C].Note[N] do
+          begin
+            //Golden + Freestyle Note Patch
+            case Lines.Line[C].Note[N].NoteType of
+              ntFreestyle: NoteState := 'F ';
+              ntNormal: NoteState := ': ';
+              ntGolden: NoteState := '* ';
+            end; // case
+            S := NoteState + IntToStr(Start-RelativeSubTime) + ' '
+                           + IntToStr(Length) + ' '
+                           + IntToStr(Tone) + ' '
+                           + EncodeToken(Text);
+
+            SongFile.WriteLine(S);
+          end; // with
+        end; // N
+
+        if C < Lines.High then // don't write end of last sentence
+        begin
+          if not Relative then
+            S := '- ' + IntToStr(Lines.Line[C+1].Start)
+          else
+          begin
+            S := '- ' + IntToStr(Lines.Line[C+1].Start - RelativeSubTime) +
+              ' ' + IntToStr(Lines.Line[C+1].Start - RelativeSubTime);
+            RelativeSubTime := Lines.Line[C+1].Start;
+          end;
+          SongFile.WriteLine(S);
+        end;
+      end; // C
+
+      SongFile.WriteLine('E');
+    finally
+      SongFile.Free;
+    end;
+  except
+    Result := ssrFileError;
+  end;
+end;
+
+end.
+
diff --git a/songmanagement/src/base/UFilesystem.pas b/songmanagement/src/base/UFilesystem.pas
new file mode 100644
index 00000000..805bcfe5
--- /dev/null
+++ b/songmanagement/src/base/UFilesystem.pas
@@ -0,0 +1,692 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UFilesystem;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  Classes,
+  {$IFDEF MSWINDOWS}
+  Windows,
+  TntSysUtils,
+  {$ENDIF}
+  UPath;
+
+type
+  {$IFDEF MSWINDOWS}
+  TSytemSearchRec = TSearchRecW;
+  {$ELSE}
+  TSytemSearchRec = TSearchRec;
+  {$ENDIF}
+
+  TFileInfo = record
+    Time: integer;  // timestamp
+    Size: int64;    // file size (byte)
+    Attr: integer;  // file attributes
+    Name: IPath;    // basename with extension
+  end;
+
+  {**
+   * Iterates through the search results retrieved by FileFind().
+   * Example usage:
+   *   while(Iter.HasNext()) do
+   *     SearchRec := Iter.Next();
+   *}
+  IFileIterator = interface
+    function HasNext(): boolean;
+    function Next(): TFileInfo;
+  end;
+
+  {**
+   * Wrapper for SysUtils file functions.
+   * For documentation and examples, check the SysUtils equivalent.
+   *}
+  IFileSystem = interface
+    function ExpandFileName(const FileName: IPath): IPath;
+    function FileCreate(const FileName: IPath): TFileHandle;
+    function DirectoryCreate(const Dir: IPath): boolean;
+    function FileOpen(const FileName: IPath; Mode: longword): TFileHandle;
+    function FileAge(const FileName: IPath): integer; overload;
+    function FileAge(const FileName: IPath; out FileDateTime: TDateTime): boolean; overload;
+
+    function DirectoryExists(const Name: IPath): boolean;
+
+    {**
+     * On Windows: returns true only for files (not directories)
+     * On Apple/Unix: returns true for all kind of files (even directories)
+     * @seealso SysUtils.FileExists()
+     *}
+    function FileExists(const Name: IPath): boolean;
+
+    function FileGetAttr(const FileName: IPath): Cardinal;
+    function FileSetAttr(const FileName: IPath; Attr: integer): boolean;
+    function FileIsReadOnly(const FileName: IPath): boolean;
+    function FileSetReadOnly(const FileName: IPath; ReadOnly: boolean): boolean;
+    function FileIsAbsolute(const FileName: IPath): boolean;
+    function ForceDirectories(const Dir: IPath): boolean;
+    function RenameFile(const OldName, NewName: IPath): boolean;
+    function DeleteFile(const FileName: IPath): boolean;
+    function RemoveDir(const Dir: IPath): boolean;
+
+    {**
+     * Copies file Source to Target. If FailIfExists is true, the file is not
+     * copied if it already exists.
+     * Returns true if the file was successfully copied.
+     *}
+    function CopyFile(const Source, Target: IPath; FailIfExists: boolean): boolean;
+
+    function ExtractFileDrive(const FileName: IPath): IPath;
+    function ExtractFilePath(const FileName: IPath): IPath;
+    function ExtractFileDir(const FileName: IPath): IPath;
+    function ExtractFileName(const FileName: IPath): IPath;
+    function ExtractFileExt(const FileName: IPath): IPath;
+    function ExtractRelativePath(const BaseName: IPath; const FileName: IPath): IPath;
+
+    function ChangeFileExt(const FileName: IPath; const Extension: IPath): IPath;
+
+    function IncludeTrailingPathDelimiter(const FileName: IPath): IPath;
+    function ExcludeTrailingPathDelimiter(const FileName: IPath): IPath;
+
+    {**
+     * Searches for a file with filename Name in the directories given in DirList.
+     *}
+    function FileSearch(const Name: IPath; DirList: array of IPath): IPath;
+
+    {**
+     * More convenient version of FindFirst/Next/Close with iterator support.
+     *}
+    function FileFind(const FilePattern: IPath; Attr: integer): IFileIterator;
+
+    {**
+     * Old style search functions. Use FileFind() instead.
+     *}
+    function FindFirst(const FilePattern: IPath; Attr: integer; var F: TSytemSearchRec): integer;
+    function FindNext(var F: TSytemSearchRec): integer;
+    procedure FindClose(var F: TSytemSearchRec);
+
+    function GetCurrentDir: IPath;
+    function SetCurrentDir(const Dir: IPath): boolean;
+
+    {**
+     * Returns true if the filesystem is case-sensitive.
+     *}
+    function IsCaseSensitive(): boolean;
+  end;
+
+  function FileSystem(): IFileSystem;
+
+implementation
+
+type
+  TFileSystemImpl = class(TInterfacedObject, IFileSystem)
+  public
+    function ExpandFileName(const FileName: IPath): IPath;
+    function FileCreate(const FileName: IPath): TFileHandle;
+    function DirectoryCreate(const Dir: IPath): boolean;
+    function FileOpen(const FileName: IPath; Mode: longword): TFileHandle;
+    function FileAge(const FileName: IPath): integer; overload;
+    function FileAge(const FileName: IPath; out FileDateTime: TDateTime): boolean; overload;
+    function DirectoryExists(const Name: IPath): boolean;
+    function FileExists(const Name: IPath): boolean;
+    function FileGetAttr(const FileName: IPath): Cardinal;
+    function FileSetAttr(const FileName: IPath; Attr: integer): boolean;
+    function FileIsReadOnly(const FileName: IPath): boolean;
+    function FileSetReadOnly(const FileName: IPath; ReadOnly: boolean): boolean;
+    function FileIsAbsolute(const FileName: IPath): boolean;
+    function ForceDirectories(const Dir: IPath): boolean;
+    function RenameFile(const OldName, NewName: IPath): boolean;
+    function DeleteFile(const FileName: IPath): boolean;
+    function RemoveDir(const Dir: IPath): boolean;
+    function CopyFile(const Source, Target: IPath; FailIfExists: boolean): boolean;
+
+    function ExtractFileDrive(const FileName: IPath): IPath;
+    function ExtractFilePath(const FileName: IPath): IPath;
+    function ExtractFileDir(const FileName: IPath): IPath;
+    function ExtractFileName(const FileName: IPath): IPath;
+    function ExtractFileExt(const FileName: IPath): IPath;
+    function ExtractRelativePath(const BaseName: IPath; const FileName: IPath): IPath;
+    function ChangeFileExt(const FileName: IPath; const Extension: IPath): IPath;
+    function IncludeTrailingPathDelimiter(const FileName: IPath): IPath;
+    function ExcludeTrailingPathDelimiter(const FileName: IPath): IPath;
+
+    function FileSearch(const Name: IPath; DirList: array of IPath): IPath;
+    function FileFind(const FilePattern: IPath; Attr: integer): IFileIterator;
+
+    function FindFirst(const FilePattern: IPath; Attr: integer; var F: TSytemSearchRec): integer;
+    function FindNext(var F: TSytemSearchRec): integer;
+    procedure FindClose(var F: TSytemSearchRec);
+
+    function GetCurrentDir: IPath;
+    function SetCurrentDir(const Dir: IPath): boolean;
+
+    function IsCaseSensitive(): boolean;
+  end;
+
+  TFileIterator = class(TInterfacedObject, IFileIterator)
+  private
+    fHasNext: boolean;
+    fSearchRec: TSytemSearchRec;
+  public
+    constructor Create(const FilePattern: IPath; Attr: integer);
+    destructor Destroy(); override;
+
+    function HasNext(): boolean;
+    function Next(): TFileInfo;
+  end;
+
+
+var
+  FileSystem_Singleton: IFileSystem;
+
+function FileSystem(): IFileSystem;
+begin
+  Result := FileSystem_Singleton;
+end;
+
+function TFileSystemImpl.FileFind(const FilePattern: IPath; Attr: integer): IFileIterator;
+begin
+  Result := TFileIterator.Create(FilePattern, Attr);
+end;
+
+function TFileSystemImpl.IsCaseSensitive(): boolean;
+begin
+  // Windows and Mac OS X do not have case sensitive file systems
+  {$IF Defined(MSWINDOWS) or Defined(DARWIN)}
+    Result := false;
+  {$ELSE}
+    Result := true;
+  {$IFEND}
+end;
+
+function TFileSystemImpl.FileIsAbsolute(const FileName: IPath): boolean;
+var
+  NameStr: UTF8String;
+begin
+  Result := true;
+  NameStr := FileName.ToUTF8();
+
+  {$IFDEF MSWINDOWS}
+    // check if drive is given 'C:...'
+    if (FileName.GetDrive().ToUTF8 <> '') then
+      Exit;
+    // check if path starts with '\\'
+    if (Length(NameStr) >= 2) and
+       (NameStr[1] = PathDelim) and (NameStr[2] = PathDelim) then
+      Exit;
+  {$ELSE} // Unix based systems
+    // check if root dir given '/...'
+    if (Length(NameStr) >= 1) and (NameStr[1] = PathDelim) then
+      Exit;
+  {$ENDIF}
+
+  Result := false;
+end;
+
+{$IFDEF MSWINDOWS}
+
+function TFileSystemImpl.ExpandFileName(const FileName: IPath): IPath;
+begin
+  Result := Path(WideExpandFileName(FileName.ToWide()));
+end;
+
+function TFileSystemImpl.FileCreate(const FileName: IPath): TFileHandle;
+begin
+  Result := WideFileCreate(FileName.ToWide());
+end;
+
+function TFileSystemImpl.DirectoryCreate(const Dir: IPath): boolean;
+begin
+  Result := WideCreateDir(Dir.ToWide());
+end;
+
+function TFileSystemImpl.FileOpen(const FileName: IPath; Mode: longword): TFileHandle;
+begin
+  Result := WideFileOpen(FileName.ToWide(), Mode);
+end;
+
+function TFileSystemImpl.FileAge(const FileName: IPath): integer;
+begin
+  Result := WideFileAge(FileName.ToWide());
+end;
+
+function TFileSystemImpl.FileAge(const FileName: IPath; out FileDateTime: TDateTime): boolean;
+begin
+  Result := WideFileAge(FileName.ToWide(), FileDateTime);
+end;
+
+function TFileSystemImpl.DirectoryExists(const Name: IPath): boolean;
+begin
+  Result := WideDirectoryExists(Name.ToWide());
+end;
+
+function TFileSystemImpl.FileExists(const Name: IPath): boolean;
+begin
+  Result := WideFileExists(Name.ToWide());
+end;
+
+function TFileSystemImpl.FileGetAttr(const FileName: IPath): Cardinal;
+begin
+  Result := WideFileGetAttr(FileName.ToWide());
+end;
+
+function TFileSystemImpl.FileSetAttr(const FileName: IPath; Attr: integer): boolean;
+begin
+  Result := WideFileSetAttr(FileName.ToWide(), Attr);
+end;
+
+function TFileSystemImpl.FileIsReadOnly(const FileName: IPath): boolean;
+begin
+  Result := WideFileIsReadOnly(FileName.ToWide());
+end;
+
+function TFileSystemImpl.FileSetReadOnly(const FileName: IPath; ReadOnly: boolean): boolean;
+begin
+  Result := WideFileSetReadOnly(FileName.ToWide(), ReadOnly);
+end;
+
+function TFileSystemImpl.ForceDirectories(const Dir: IPath): boolean;
+begin
+  Result := WideForceDirectories(Dir.ToWide());
+end;
+
+function TFileSystemImpl.FileSearch(const Name: IPath; DirList: array of IPath): IPath;
+var
+  I: integer;
+  DirListStr: WideString;
+begin
+  DirListStr := '';
+  for I := 0 to High(DirList) do
+  begin
+    if (I > 0) then
+      DirListStr := DirListStr + PathSep;
+    DirListStr := DirListStr + DirList[I].ToWide();
+  end;
+  Result := Path(WideFileSearch(Name.ToWide(), DirListStr));
+end;
+
+function TFileSystemImpl.RenameFile(const OldName, NewName: IPath): boolean;
+begin
+  Result := WideRenameFile(OldName.ToWide(), NewName.ToWide());
+end;
+
+function TFileSystemImpl.DeleteFile(const FileName: IPath): boolean;
+begin
+  Result := WideDeleteFile(FileName.ToWide());
+end;
+
+function TFileSystemImpl.RemoveDir(const Dir: IPath): boolean;
+begin
+  Result := WideRemoveDir(Dir.ToWide());
+end;
+
+function TFileSystemImpl.CopyFile(const Source, Target: IPath; FailIfExists: boolean): boolean;
+begin
+  Result := WideCopyFile(Source.ToWide(), Target.ToWide(), FailIfExists);
+end;
+
+function TFileSystemImpl.ExtractFileDrive(const FileName: IPath): IPath;
+begin
+  Result := Path(WideExtractFileDrive(FileName.ToWide()));
+end;
+
+function TFileSystemImpl.ExtractFilePath(const FileName: IPath): IPath;
+begin
+  Result := Path(WideExtractFilePath(FileName.ToWide()));
+end;
+
+function TFileSystemImpl.ExtractFileDir(const FileName: IPath): IPath;
+begin
+  Result := Path(WideExtractFileDir(FileName.ToWide()));
+end;
+
+function TFileSystemImpl.ExtractFileName(const FileName: IPath): IPath;
+begin
+  Result := Path(WideExtractFileName(FileName.ToWide()));
+end;
+
+function TFileSystemImpl.ExtractFileExt(const FileName: IPath): IPath;
+begin
+  Result := Path(WideExtractFileExt(FileName.ToWide()));
+end;
+
+function TFileSystemImpl.ExtractRelativePath(const BaseName: IPath; const FileName: IPath): IPath;
+begin
+  Result := Path(WideExtractRelativePath(BaseName.ToWide(), FileName.ToWide()));
+end;
+
+function TFileSystemImpl.ChangeFileExt(const FileName: IPath; const Extension: IPath): IPath;
+begin
+  Result := Path(WideChangeFileExt(FileName.ToWide(), Extension.ToWide()));
+end;
+
+function TFileSystemImpl.IncludeTrailingPathDelimiter(const FileName: IPath): IPath;
+begin
+  Result := Path(WideIncludeTrailingPathDelimiter(FileName.ToWide()));
+end;
+
+function TFileSystemImpl.ExcludeTrailingPathDelimiter(const FileName: IPath): IPath;
+begin
+  Result := Path(WideExcludeTrailingPathDelimiter(FileName.ToWide()));
+end;
+
+function TFileSystemImpl.FindFirst(const FilePattern: IPath; Attr: integer; var F: TSytemSearchRec): integer;
+begin
+  Result := WideFindFirst(FilePattern.ToWide(), Attr, F);
+end;
+
+function TFileSystemImpl.FindNext(var F: TSytemSearchRec): integer;
+begin
+  Result := WideFindNext(F);
+end;
+
+procedure TFileSystemImpl.FindClose(var F: TSytemSearchRec);
+begin
+  WideFindClose(F);
+end;
+
+function TFileSystemImpl.GetCurrentDir: IPath;
+begin
+  Result := Path(WideGetCurrentDir());
+end;
+
+function TFileSystemImpl.SetCurrentDir(const Dir: IPath): boolean;
+begin
+  Result := WideSetCurrentDir(Dir.ToWide());
+end;
+
+{$ELSE} // UNIX
+
+function TFileSystemImpl.ExpandFileName(const FileName: IPath): IPath;
+begin
+  Result := Path(SysUtils.ExpandFileName(FileName.ToNative()));
+end;
+
+function TFileSystemImpl.FileCreate(const FileName: IPath): TFileHandle;
+begin
+  Result := SysUtils.FileCreate(FileName.ToNative());
+end;
+
+function TFileSystemImpl.DirectoryCreate(const Dir: IPath): boolean;
+begin
+  Result := SysUtils.CreateDir(Dir.ToNative());
+end;
+
+function TFileSystemImpl.FileOpen(const FileName: IPath; Mode: longword): TFileHandle;
+begin
+  Result := SysUtils.FileOpen(FileName.ToNative(), Mode);
+end;
+
+function TFileSystemImpl.FileAge(const FileName: IPath): integer;
+begin
+  Result := SysUtils.FileAge(FileName.ToNative());
+end;
+
+function TFileSystemImpl.FileAge(const FileName: IPath; out FileDateTime: TDateTime): boolean;
+var
+  FileDate: integer;
+begin
+  FileDate := SysUtils.FileAge(FileName.ToNative());
+  Result := (FileDate <> -1);
+  if (Result) then
+    FileDateTime := FileDateToDateTime(FileDate);
+end;
+
+function TFileSystemImpl.DirectoryExists(const Name: IPath): boolean;
+begin
+  Result := SysUtils.DirectoryExists(Name.ToNative());
+end;
+
+function TFileSystemImpl.FileExists(const Name: IPath): boolean;
+begin
+  Result := SysUtils.FileExists(Name.ToNative());
+end;
+
+function TFileSystemImpl.FileGetAttr(const FileName: IPath): Cardinal;
+begin
+  Result := SysUtils.FileGetAttr(FileName.ToNative());
+end;
+
+function TFileSystemImpl.FileSetAttr(const FileName: IPath; Attr: integer): boolean;
+begin
+  Result := (SysUtils.FileSetAttr(FileName.ToNative(), Attr) = 0);
+end;
+
+function TFileSystemImpl.FileIsReadOnly(const FileName: IPath): boolean;
+begin
+  Result := SysUtils.FileIsReadOnly(FileName.ToNative());
+end;
+
+function TFileSystemImpl.FileSetReadOnly(const FileName: IPath; ReadOnly: boolean): boolean;
+begin
+  Result := (SysUtils.FileSetAttr(FileName.ToNative(), faReadOnly) = 0);
+end;
+
+function TFileSystemImpl.ForceDirectories(const Dir: IPath): boolean;
+begin
+  Result := SysUtils.ForceDirectories(Dir.ToNative());
+end;
+
+function TFileSystemImpl.FileSearch(const Name: IPath; DirList: array of IPath): IPath;
+var
+  I: integer;
+  DirListStr: AnsiString;
+begin
+  DirListStr := '';
+  for I := 0 to High(DirList) do
+  begin
+    if (I > 0) then
+      DirListStr := DirListStr + PathSep;
+    DirListStr := DirListStr + DirList[I].ToNative();
+  end;
+  Result := Path(SysUtils.FileSearch(Name.ToNative(), DirListStr));
+end;
+
+function TFileSystemImpl.RenameFile(const OldName, NewName: IPath): boolean;
+begin
+  Result := SysUtils.RenameFile(OldName.ToNative(), NewName.ToNative());
+end;
+
+function TFileSystemImpl.DeleteFile(const FileName: IPath): boolean;
+begin
+  Result := SysUtils.DeleteFile(FileName.ToNative());
+end;
+
+function TFileSystemImpl.RemoveDir(const Dir: IPath): boolean;
+begin
+  Result := SysUtils.RemoveDir(Dir.ToNative());
+end;
+
+function TFileSystemImpl.CopyFile(const Source, Target: IPath; FailIfExists: boolean): boolean;
+const
+  COPY_BUFFER_SIZE = 4096; // a good tradeoff between speed and memory consumption
+var
+  SourceFile, TargetFile: TFileStream;
+  FileCopyBuffer: array [0..COPY_BUFFER_SIZE-1] of byte; // temporary copy-buffer.
+  NumberOfBytes: integer; // number of bytes read from SourceFile
+begin
+  Result := false;
+  SourceFile := nil;
+  TargetFile := nil;
+
+  // if overwrite is disabled return if the target file already exists
+  if (FailIfExists and FileExists(Target)) then
+    Exit;
+
+  try
+    try
+      // open source and target file (might throw an exception on error)
+      SourceFile := TFileStream.Create(Source.ToNative(), fmOpenRead);
+      TargetFile := TFileStream.Create(Target.ToNative(), fmCreate or fmOpenWrite);
+
+      while true do
+      begin
+        // read a block from the source file and check for errors or EOF
+        NumberOfBytes := SourceFile.Read(FileCopyBuffer, SizeOf(FileCopyBuffer));
+        if (NumberOfBytes <= 0) then
+          Break;
+        // write block to target file and check if everything was written
+        if (TargetFile.Write(FileCopyBuffer, NumberOfBytes) <> NumberOfBytes) then
+          Exit;
+      end;
+    except
+      Exit;
+    end;
+  finally
+    SourceFile.Free;
+    TargetFile.Free;
+  end;
+
+  Result := true;
+end;
+
+function TFileSystemImpl.ExtractFileDrive(const FileName: IPath): IPath;
+begin
+  Result := Path(SysUtils.ExtractFileDrive(FileName.ToNative()));
+end;
+
+function TFileSystemImpl.ExtractFilePath(const FileName: IPath): IPath;
+begin
+  Result := Path(SysUtils.ExtractFilePath(FileName.ToNative()));
+end;
+
+function TFileSystemImpl.ExtractFileDir(const FileName: IPath): IPath;
+begin
+  Result := Path(SysUtils.ExtractFileDir(FileName.ToNative()));
+end;
+
+function TFileSystemImpl.ExtractFileName(const FileName: IPath): IPath;
+begin
+  Result := Path(SysUtils.ExtractFileName(FileName.ToNative()));
+end;
+
+function TFileSystemImpl.ExtractFileExt(const FileName: IPath): IPath;
+begin
+  Result := Path(SysUtils.ExtractFileExt(FileName.ToNative()));
+end;
+
+function TFileSystemImpl.ExtractRelativePath(const BaseName: IPath; const FileName: IPath): IPath;
+begin
+  Result := Path(SysUtils.ExtractRelativePath(BaseName.ToNative(), FileName.ToNative()));
+end;
+
+function TFileSystemImpl.ChangeFileExt(const FileName: IPath; const Extension: IPath): IPath;
+begin
+  Result := Path(SysUtils.ChangeFileExt(FileName.ToNative(), Extension.ToNative()));
+end;
+
+function TFileSystemImpl.IncludeTrailingPathDelimiter(const FileName: IPath): IPath;
+begin
+  Result := Path(SysUtils.IncludeTrailingPathDelimiter(FileName.ToNative()));
+end;
+
+function TFileSystemImpl.ExcludeTrailingPathDelimiter(const FileName: IPath): IPath;
+begin
+  Result := Path(SysUtils.ExcludeTrailingPathDelimiter(FileName.ToNative()));
+end;
+
+function TFileSystemImpl.FindFirst(const FilePattern: IPath; Attr: integer; var F: TSytemSearchRec): integer;
+begin
+  Result := SysUtils.FindFirst(FilePattern.ToNative(), Attr, F);
+end;
+
+function TFileSystemImpl.FindNext(var F: TSytemSearchRec): integer;
+begin
+  Result := SysUtils.FindNext(F);
+end;
+
+procedure TFileSystemImpl.FindClose(var F: TSytemSearchRec);
+begin
+  SysUtils.FindClose(F);
+end;
+
+function TFileSystemImpl.GetCurrentDir: IPath;
+begin
+  Result := Path(SysUtils.GetCurrentDir());
+end;
+
+function TFileSystemImpl.SetCurrentDir(const Dir: IPath): boolean;
+begin
+  Result := SysUtils.SetCurrentDir(Dir.ToNative());
+end;
+
+{$ENDIF}
+
+
+{ TFileIterator }
+
+constructor TFileIterator.Create(const FilePattern: IPath; Attr: integer);
+begin
+  inherited Create();
+  fHasNext := (FileSystem.FindFirst(FilePattern, Attr, fSearchRec) = 0);
+end;
+
+destructor TFileIterator.Destroy();
+begin
+  FileSystem.FindClose(fSearchRec);
+  inherited;
+end;
+
+function TFileIterator.HasNext(): boolean;
+begin
+  Result := fHasNext;
+end;
+
+function TFileIterator.Next(): TFileInfo;
+begin
+  if (not fHasNext) then
+  begin
+    // Note: do not use FillChar() on records with ref-counted fields
+    Result.Time := 0;
+    Result.Size := 0;
+    Result.Attr := 0;
+    Result.Name := nil;
+    Exit;
+  end;
+
+  Result.Time := fSearchRec.Time;
+  Result.Size := fSearchRec.Size;
+  Result.Attr := fSearchRec.Attr;
+  Result.Name := Path(fSearchRec.Name);
+
+  // fetch next entry
+  fHasNext := (FileSystem.FindNext(fSearchRec) = 0);
+end;
+
+
+initialization
+  FileSystem_Singleton := TFileSystemImpl.Create;
+
+finalization
+  FileSystem_Singleton := nil;
+
+end.
diff --git a/songmanagement/src/base/UFont.pas b/songmanagement/src/base/UFont.pas
new file mode 100644
index 00000000..e680811b
--- /dev/null
+++ b/songmanagement/src/base/UFont.pas
@@ -0,0 +1,3067 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UFont;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+interface
+
+{$IFNDEF FREETYPE_DEMO}
+  // Flip direction of y-axis.
+  // Default is a cartesian coordinate system with y-axis in upper direction
+  // but with USDX the y-axis is in lower direction.
+  {$DEFINE FLIP_YAXIS}
+  {$DEFINE BITMAP_FONT}
+{$ENDIF}
+
+// Enables the Freetype font cache
+{$DEFINE ENABLE_FT_FACE_CACHE}
+
+uses
+  FreeType,
+  gl,
+  glext,
+  glu,
+  sdl,
+  Math,
+  Classes,
+  SysUtils,
+  UUnicodeUtils,
+  {$IFDEF BITMAP_FONT}
+  UTexture,
+  {$ENDIF}
+  UPath;
+
+type
+
+  PGLubyteArray = ^TGLubyteArray;
+  TGLubyteArray = array[0 .. (MaxInt div SizeOf(GLubyte))-1] of GLubyte;
+  TGLubyteDynArray = array of GLubyte;
+
+  TUCS4StringArray = array of UCS4String;
+
+  TGLColor = packed record
+    case byte of
+      0: ( vals: array[0..3] of GLfloat; );
+      1: ( r, g, b, a: GLfloat; );
+  end;
+
+  TBoundsDbl = record
+    Left, Right: double;
+    Bottom, Top: double;
+  end;
+
+  TPositionDbl = record
+    X, Y: double;
+  end;
+
+  TTextureSize = record
+    Width, Height: integer;
+  end;
+
+  TBitmapCoords = record
+    Left, Top: double;
+    Width, Height: integer;
+  end;
+
+  EFontError = class(Exception);
+
+  {**
+   * Abstract base class representing a glyph.
+   *}
+  TGlyph = class
+    protected
+      function GetAdvance(): TPositionDbl; virtual; abstract;
+      function GetBounds(): TBoundsDbl; virtual; abstract;
+    public
+      procedure Render(UseDisplayLists: boolean); virtual; abstract;
+      procedure RenderReflection(); virtual; abstract;
+
+      {** Distance to next glyph (in pixels) *}
+      property Advance: TPositionDbl read GetAdvance;
+      {** Glyph bounding box (in pixels) *}
+      property Bounds: TBoundsDbl read GetBounds;
+  end;
+
+  {**
+   * Font styles used by TFont.Style
+   *}
+  TFontStyle = set of (Italic, Underline, Reflect);
+
+  {**
+   * Base font class.
+   *}
+  TFont = class
+    private
+      {** Non-virtual reset-method used in Create() and Reset() }
+      procedure ResetIntern();
+
+    protected
+      fFilename: IPath;
+      fStyle: TFontStyle;
+      fUseKerning: boolean;       
+      fLineSpacing: single;       // must be inited by subclass
+      fReflectionSpacing: single; // must be inited by subclass to -2*Descender
+      fGlyphSpacing: single;
+      fReflectionPass: boolean;
+
+      {**
+       * Splits lines in Text seperated by newline (char-code #13).
+       * @param Text   UCS-4 encoded string
+       * @param Lines  splitted UCS4String lines
+       *}
+      procedure SplitLines(const Text: UCS4String; var Lines: TUCS4StringArray);
+
+      {**
+       * Print an array of UCS4Strings. Each array-item is a line of text.
+       * Lines of text are seperated by the line-spacing.
+       * This is the base function for all text drawing.
+       *}
+      procedure Print(const Text: TUCS4StringArray); overload; virtual;
+
+      {**
+       * Draws an underline.
+       *}
+      procedure DrawUnderline(const Text: UCS4String); virtual;
+
+      {**
+       * Renders (one) line of text.
+       *}
+      procedure Render(const Text: UCS4String); virtual; abstract;
+
+      {**
+       * Returns the bounds of text-lines contained in Text.
+       * @param(Advance  if true the right bound is set to the advance instead
+       *   of the minimal right bound.)
+       *}
+      function BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl; overload; virtual; abstract;
+
+      {**
+       * Resets all user settings to default values.
+       * Override methods should always call the inherited version.
+       *}
+      procedure Reset(); virtual;
+
+      function GetHeight(): single; virtual; abstract;
+      function GetAscender(): single; virtual; abstract;
+      function GetDescender(): single; virtual; abstract;
+      procedure SetLineSpacing(Spacing: single); virtual;
+      function GetLineSpacing(): single; virtual;
+      procedure SetGlyphSpacing(Spacing: single); virtual;
+      function GetGlyphSpacing(): single; virtual;
+      procedure SetReflectionSpacing(Spacing: single); virtual;
+      function GetReflectionSpacing(): single; virtual;
+      procedure SetStyle(Style: TFontStyle); virtual;
+      function GetStyle(): TFontStyle; virtual;
+      function GetUnderlinePosition(): single; virtual; abstract;
+      function GetUnderlineThickness(): single; virtual; abstract;
+      procedure SetUseKerning(Enable: boolean); virtual;
+      function GetUseKerning(): boolean; virtual;
+      procedure SetReflectionPass(Enable: boolean); virtual;
+
+      {** Returns true if the current render-pass is used to draw the reflection }
+      property ReflectionPass: boolean read fReflectionPass write SetReflectionPass;
+
+    public
+      constructor Create(const Filename: IPath);
+      destructor Destroy(); override;
+
+      {**
+       * Prints a text.
+       *}
+      procedure Print(const Text: UCS4String); overload;
+      {** UTF-16 version of @link(Print) }
+      procedure Print(const Text: WideString); overload;
+      {** UTF-8 version of @link(Print) }
+      procedure Print(const Text: UTF8String); overload;
+
+      {**
+       * Calculates the bounding box (width and height) around Text.
+       * Works with Italic and Underline styles but reflections created
+       * with the Reflect style are not considered.
+       * Note that the width might differ due to kerning with appended text,
+       * e.g. Width('VA') <= Width('V') + Width('A').
+       * @param Advance  if set to true, Result.Right is set to the advance of
+       * the given text rather than the min. right border. The advance width is
+       * bigger than the text's width as it additionally contains the advance
+       * and glyph-spacing of the last character.
+       *}
+      function BBox(const Text: UCS4String; Advance: boolean = true): TBoundsDbl; overload;
+      {** UTF-16 version of @link(BBox) }
+      function BBox(const Text: WideString; Advance: boolean = true): TBoundsDbl; overload;
+      {** UTF-8 version of @link(BBox) }
+      function BBox(const Text: UTF8String; Advance: boolean = true): TBoundsDbl; overload;
+
+      {**
+       * Adds a new font that is used if the default font misses a glyph
+       * @raises EFontError  if the fallback could not be initialized
+       *}
+      procedure AddFallback(const Filename: IPath); virtual; abstract;
+
+      {** Font height }
+      property Height: single read GetHeight;
+      {** Vertical distance from baseline to top of glyph }
+      property Ascender: single read GetAscender;
+      {** Vertical distance from baseline to bottom of glyph }
+      property Descender: single read GetDescender;
+      {** Vertical distance between two baselines }
+      property LineSpacing: single read GetLineSpacing write SetLineSpacing;
+      {** Space between end and start of next glyph added to the advance width }
+      property GlyphSpacing: single read GetGlyphSpacing write SetGlyphSpacing;
+      {** Distance between normal baseline and baseline of the reflection }
+      property ReflectionSpacing: single read GetReflectionSpacing write SetReflectionSpacing;
+      {** Font style (italic/underline/...) }
+      property Style: TFontStyle read GetStyle write SetStyle;
+      {** If set to true (default) kerning will be used if available }
+      property UseKerning: boolean read GetUseKerning write SetUseKerning;
+      {** Filename }
+      property Filename: IPath read fFilename;
+  end;
+
+const
+  //** Max. number of mipmap levels that a TScalableFont can contain
+  cMaxMipmapLevel = 5;
+
+type
+  {**
+   * Wrapper around TFont to allow font size changes.
+   * The font is scaled to the requested size by a modelview matrix
+   * transformation (glScale) and not by rescaling the internal bitmap
+   * representation. This way changing the size is really fast but the result
+   * may lack quality on large or small scale factors.
+   *}
+  TScalableFont = class(TFont)
+    private
+      procedure ResetIntern();
+
+    protected
+      fScale: single;        //**< current height to base-font height ratio
+      fStretch: single;      //**< stretch factor for width (Width * fStretch)
+      fBaseFont: TFont;      //**< shortcut for fMipmapFonts[0]
+      fUseMipmaps: boolean;  //**< true if mipmap fonts are generated
+      /// Mipmap fonts (size[level+1] = size[level]/2)
+      fMipmapFonts: array[0..cMaxMipmapLevel] of TFont;
+
+      procedure Render(const Text: UCS4String); override;
+      procedure Print(const Text: TUCS4StringArray); override;
+      function BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl; override;
+
+      {**
+       * Callback called for creation of each mipmap font.
+       * Must be defined by the subclass.
+       * Mipmaps created by this method are managed and freed by TScalableFont.
+       *}
+      function CreateMipmap(Level: integer; Scale: single): TFont; virtual; abstract;
+
+      {**
+       * Returns the mipmap level considering the current scale and projection
+       * matrix.
+       *}
+      function GetMipmapLevel(): integer;
+
+      {**
+       * Returns the scale applied to the given mipmap font.
+       * fScale * fBaseFont.Height / fMipmapFont[Level].Height
+       *}
+      function GetMipmapScale(Level: integer): single;
+
+      {**
+       * Chooses the mipmap that looks nicest with current scale and projection
+       * matrix.
+       *}
+      function ChooseMipmapFont(): TFont;
+
+      procedure SetHeight(Height: single); virtual;
+      function GetHeight(): single; override;
+      procedure SetStretch(Stretch: single); virtual;
+      function GetStretch(): single; virtual;
+      function GetAscender(): single; override;
+      function GetDescender(): single; override;
+      procedure SetLineSpacing(Spacing: single); override;
+      function GetLineSpacing(): single; override;
+      procedure SetGlyphSpacing(Spacing: single); override;
+      function GetGlyphSpacing(): single; override;
+      procedure SetReflectionSpacing(Spacing: single); override;
+      function GetReflectionSpacing(): single; override;
+      procedure SetStyle(Style: TFontStyle); override;
+      function GetStyle(): TFontStyle; override;
+      function GetUnderlinePosition(): single; override;
+      function GetUnderlineThickness(): single; override;
+      procedure SetUseKerning(Enable: boolean); override;
+
+    public
+      {**
+       * Creates a wrapper to make the base-font Font scalable.
+       * If UseMipmaps is set to true smaller fonts are created so that a
+       * resized (Height property changed) font looks nicer.
+       * The font passed is managed and freed by TScalableFont.
+       *}
+      constructor Create(Font: TFont; UseMipmaps: boolean); overload;
+
+      {**
+       * Frees memory. The fonts passed on Create() and mipmap creation
+       * are freed too. 
+       *}
+      destructor Destroy(); override;
+
+      {** @seealso TFont.Reset }
+      procedure Reset(); override;
+
+      {** Font height }
+      property Height: single read GetHeight write SetHeight;
+      {** Factor for font stretching (NewWidth = Width*Stretch), 1.0 by default }
+      property Stretch: single read GetStretch write SetStretch;
+  end;
+
+  {**
+   * Table for storage of max. 256 glyphs.
+   * Used for the second cache level. Indexed by the LSB of the UCS4Char
+   * char-code.
+   *}
+  PGlyphTable = ^TGlyphTable;
+  TGlyphTable = array[0..255] of TGlyph;
+
+  {**
+   * Cache for glyphs of a single font.
+   * The cached glyphs are stored inside a hash-list.
+   * Hashing is performed in two steps:
+   * 1. the least significant byte (LSB) of the UCS4Char character code
+   * is removed (shr 8) and the result (we call it BaseCode here) looked up in
+   * the hash-list.
+   * 2. Each entry of the hash-list contains a table with max. 256 entries.
+   * The LSB of the char-code of a glyph is the table-offset of that glyph.
+   *}
+  TGlyphCache = class
+    private
+      fHash: TList;
+
+      {**
+       * Finds a glyph-table storing cached glyphs with base-code BaseCode
+       * (= upper char-code bytes) in the hash-list and returns the table and
+       * its index.
+       * @param(InsertPos  the position of the tyble in the list if it was found,
+       *                   otherwise the position the table should be inserted)
+       *}
+      function FindGlyphTable(BaseCode: cardinal; out InsertPos: integer): PGlyphTable;
+
+    public
+      constructor Create();
+      destructor Destroy(); override;
+
+      {**
+       * Add glyph Glyph with char-code ch to the cache.
+       * @returns @true on success, @false otherwise
+       *}
+      function AddGlyph(ch: UCS4Char; const Glyph: TGlyph): boolean;
+
+      {**
+       * Removes the glyph with char-code ch from the cache.
+       *}
+      procedure DeleteGlyph(ch: UCS4Char);
+
+      {**
+       * Removes the glyph with char-code ch from the cache.
+       *}
+      function GetGlyph(ch: UCS4Char): TGlyph;
+
+      {**
+       * Checks if a glyph with char-code ch is cached.
+       *}
+      function HasGlyph(ch: UCS4Char): boolean;
+
+      {**
+       * Remove and free all cached glyphs. If KeepBaseSet is set to
+       * true, cached characters in the range 0..255 will not be flushed.
+       *}
+      procedure FlushCache(KeepBaseSet: boolean);
+  end;
+
+  {**
+   * Entry of a glyph-cache's (TGlyphCache) hash.
+   * Stores a BaseCode (upper-bytes of a glyph's char-code) and a table
+   * with all glyphs cached at the moment with that BaseCode.
+   *}
+  TGlyphCacheHashEntry = class
+    private
+      fBaseCode: cardinal;
+    public
+      GlyphTable: TGlyphTable;
+
+      constructor Create(BaseCode: cardinal);
+
+      {** Base-code (upper-bytes) of the glyphs stored in this entry's table }
+      property BaseCode: cardinal read fBaseCode;
+  end;
+
+  TCachedFont = class(TFont)
+    protected
+      fCache: TGlyphCache;
+
+      {**
+       * Retrieves a cached glyph with char-code ch from cache.
+       * If the glyph is not already cached, it is loaded with LoadGlyph().
+       *}
+      function GetGlyph(ch: UCS4Char): TGlyph;
+
+      {**
+       * Callback to create (load) a glyph with char-code ch.
+       * Implemented by subclasses.
+       *}
+      function LoadGlyph(ch: UCS4Char): TGlyph; virtual; abstract;
+
+    public
+      constructor Create(const Filename: IPath);
+      destructor Destroy(); override;
+
+      {**
+       * Remove and free all cached glyphs. If KeepBaseSet is set to
+       * true, the base glyphs are not be flushed.
+       * @seealso TGlyphCache.FlushCache
+       *}
+      procedure FlushCache(KeepBaseSet: boolean);
+  end;
+
+  TFTFont = class;
+
+  {**
+   * Freetype font face class.
+   *}
+  TFTFontFace = class
+    private
+      fFilename: IPath;             //**< filename of the font-file
+      fFace: FT_Face;               //**< Holds the height of the font
+      fFontUnitScale: TPositionDbl; //**< FT font-units to pixel ratio
+      fSize: integer;
+
+    public
+      {**
+       * @raises EFontError  if the glyph could not be initialized
+       *}
+      constructor Create(const Filename: IPath; Size: integer);
+      
+      destructor Destroy(); override;
+
+      property Filename: IPath read fFilename;
+      property Data: FT_Face read fFace;
+      property FontUnitScale: TPositionDbl read fFontUnitScale;
+      property Size: integer read fSize;
+  end;
+
+  {**
+   * Loading font faces with freetype is a slow process.
+   * Especially loading a font (e.g. fallback fonts) more than once is a waste
+   * of time. Just cache already loaded faces here.
+   *}
+  TFTFontFaceCache = class
+    private
+      fFaces:       array of TFTFontFace;
+      fFacesRefCnt: array of integer;      
+    public
+      {**
+       * @raises EFontError  if the font could not be initialized
+       *}
+      function LoadFace(const Filename: IPath; Size: integer): TFTFontFace;
+
+      procedure UnloadFace(Face: TFTFontFace);
+  end;
+
+  {**
+   * Freetype glyph.
+   * Each glyph stores a texture with the glyph's image.
+   *}
+  TFTGlyph = class(TGlyph)
+    private
+      fCharCode:  UCS4Char;     //**< Char code
+      fFace: TFTFontFace;       //**< Freetype face used for this glyph
+      fCharIndex: FT_UInt;      //**< Freetype specific char-index (<> char-code)
+      fDisplayList: GLuint;     //**< Display-list ID
+      fTexture: GLuint;         //**< Texture ID
+      fBitmapCoords: TBitmapCoords; //**< Left/Top offset and Width/Height of the bitmap (in pixels)
+      fTexOffset: TPositionDbl; //**< Right and bottom texture offset for removal of power-of-2 padding
+      fTexSize: TTextureSize;   //**< Texture size in pixels
+
+      fFont: TFTFont;           //**< Font associated with this glyph
+      fAdvance: TPositionDbl;   //**< Advance width of this glyph
+      fBounds: TBoundsDbl;      //**< Glyph bounds
+      fOutset: single;          //**< Extrusion outset
+
+      {**
+       * Extrudes the outline of a glyph's bitmap stored in TexBuffer with size
+       * fTexSize by Outset pixels.
+       * This is useful to create bold or outlined fonts.
+       * TexBuffer must be 2*Ceil(Outset) pixels higher and wider than the
+       * original glyph bitmap, otherwise the glyph borders cannot be extruded
+       * correctly.
+       * The bitmap must be 2* pixels wider and higher than the
+       * original glyph's bitmap with the latter centered in it.
+       *}
+      procedure StrokeBorder(var Glyph: FT_Glyph);
+
+      {**
+       * Creates an OpenGL texture (and display list) for the glyph.
+       * The glyph's and bitmap's metrics are set correspondingly.
+       * @param  LoadFlags  flags passed to FT_Load_Glyph()
+       * @raises EFontError  if the glyph could not be initialized
+       *}
+      procedure CreateTexture(LoadFlags: FT_Int32);
+
+    protected
+      function GetAdvance(): TPositionDbl; override;
+      function GetBounds(): TBoundsDbl; override;
+
+    public
+      {**
+       * Creates a glyph with char-code ch from font Font.
+       * @param LoadFlags  flags passed to FT_Load_Glyph()
+       *}
+      constructor Create(Font: TFTFont; ch: UCS4Char; Outset: single;
+                         LoadFlags: FT_Int32);
+      destructor Destroy(); override;
+
+      {** Renders the glyph (normal render pass) }
+      procedure Render(UseDisplayLists: boolean); override;
+      {** Renders the glyph's reflection }
+      procedure RenderReflection(); override;
+
+      {** Freetype specific char-index (<> char-code) }
+      property CharIndex: FT_UInt read fCharIndex;
+      
+      {** Freetype face used for this glyph }
+      property Face: TFTFontFace read fFace;
+  end;
+
+  TFontPart = ( fpNone, fpInner, fpOutline );
+  TFTFontFaceArray = array of TFTFontFace;
+
+  {**
+   * Freetype font class.
+   *}
+  TFTFont = class(TCachedFont)
+    private
+      procedure ResetIntern();
+      class function GetFaceCache(): TFTFontFaceCache;
+
+    protected
+      fFace: TFTFontFace;           //**< Default font face
+      fSize: integer;               //**< Font base size (in pixels)
+      fOutset: single;              //**< size of outset extrusion (in pixels)
+      fPreCache: boolean;           //**< pre-load base glyphs
+      fLoadFlags: FT_Int32;         //**< FT glpyh load-flags
+      fUseDisplayLists: boolean;    //**< true: use display-lists, false: direct drawing
+      fPart: TFontPart;             //**< indicates the part of an outline font
+      fFallbackFaces: TFTFontFaceArray; //**< available fallback faces, ordered by priority
+
+      {** @seealso TCachedFont.LoadGlyph }
+      function LoadGlyph(ch: UCS4Char): TGlyph; override;
+
+      procedure Render(const Text: UCS4String); override;
+      function BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl; override;
+
+      function GetHeight(): single; override;
+      function GetAscender(): single; override;
+      function GetDescender(): single; override;
+      function GetUnderlinePosition(): single; override;
+      function GetUnderlineThickness(): single; override;
+
+    public
+      {**
+       * Creates a font of size Size (in pixels) from the file Filename.
+       * If Outset (in pixels) is set to a value > 0 the glyphs will be extruded
+       * at their borders. Use it for e.g. a bold effect.
+       * @param  LoadFlags  flags passed to FT_Load_Glyph()
+       * @raises EFontError  if the font-file could not be loaded
+       *}
+      constructor Create(const Filename: IPath;
+                         Size: integer; Outset: single = 0.0;
+                         PreCache: boolean = true;
+                         LoadFlags: FT_Int32 = FT_LOAD_DEFAULT);
+
+      {**
+       * Frees all resources associated with the font.
+       *}
+      destructor Destroy(); override;
+
+      {** @seealso TFont.Reset }
+      procedure Reset(); override;
+
+      procedure AddFallback(const Filename: IPath); override;
+
+      {** Size of the base font }
+      property Size: integer read fSize;
+      {** Outset size }
+      property Outset: single read fOutset;
+      {** The part (inner/outline/none) this font represents in a composite font }
+      property Part: TFontPart read fPart write fPart;
+      {** Freetype face of this font }
+      property DefaultFace: TFTFontFace read fFace;
+      {** Available freetype fallback faces, ordered by priority }
+      property FallbackFaces: TFTFontFaceArray read fFallbackFaces;
+  end;
+
+  TFTScalableFont = class(TScalableFont)
+    protected
+      function GetOutset(): single; virtual;
+      function CreateMipmap(Level: integer; Scale: single): TFont; override;
+
+    public
+      {**
+       * Creates a scalable font of size Size (in pixels) from the file Filename.
+       * OutsetAmount is the ratio of the glyph extrusion.
+       * The extrusion in pixels is Size*OutsetAmount
+       * (0.0 -> no extrusion, 0.1 -> 10%).
+       *
+       * The memory size (in bytes) consumed by a scalable font
+       * - with UseMipmaps=false:
+       *  mem = size^2 * #cached_glyphs
+       * - with UseMipmaps=true (all mipmap levels):
+       *  mem = size^2 * #cached_glyphs * Sum[i=1..cMaxMipmapLevel](1/i^2)
+       * - with UseMipmaps=true (5 <= cMaxMipmapLevel <= 10):
+       *  mem ~= size^2 * #cached_glyphs * 1.5
+       *
+       * Examples (for 128 cached glyphs):
+       * - Size: 64 pixels: 768 KB (mipmapped) or 512 KB (non-mipmapped).
+       * - Size 128 pixels: 3 MB (mipmapped) or 2 MB (non-mipmapped)
+       *
+       * Note: once a glyph is cached there will
+       *}
+      constructor Create(const Filename: IPath;
+                         Size: integer; OutsetAmount: single = 0.0;
+                         UseMipmaps: boolean = true;
+                         PreCache: boolean = true);
+
+      procedure AddFallback(const Filename: IPath); override;
+                         
+      {** @seealso TGlyphCache.FlushCache }
+      procedure FlushCache(KeepBaseSet: boolean);
+
+      {** Outset size (in pixels) of the scaled font }
+      property Outset: single read GetOutset;
+  end;
+
+  
+  {**
+   * Represents a freetype font with an additional outline around its glyphs.
+   * The outline size is passed on creation and cannot be changed later.
+   *}
+  TFTOutlineFont = class(TFont)
+    private
+      fSize: integer;
+      fOutset: single;
+      fInnerFont, fOutlineFont: TFTFont;
+      fOutlineColor: TGLColor;
+      fPreCache: boolean;
+
+      procedure ResetIntern();
+      
+  protected
+      procedure DrawUnderline(const Text: UCS4String); override;
+      procedure Render(const Text: UCS4String); override;
+      function BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl; override;
+
+      function GetHeight(): single; override;
+      function GetAscender(): single; override;
+      function GetDescender(): single; override;
+      procedure SetLineSpacing(Spacing: single); override;
+      procedure SetGlyphSpacing(Spacing: single); override;
+      procedure SetReflectionSpacing(Spacing: single); override;
+      procedure SetStyle(Style: TFontStyle); override;
+      function GetStyle(): TFontStyle; override;
+      function GetUnderlinePosition(): single; override;
+      function GetUnderlineThickness(): single; override;
+      procedure SetUseKerning(Enable: boolean); override;
+      procedure SetReflectionPass(Enable: boolean); override;
+
+    public
+      constructor Create(const Filename: IPath;
+                         Size: integer; Outset: single;
+                         PreCache: boolean = true;
+                         LoadFlags: FT_Int32 = FT_LOAD_DEFAULT);
+      destructor Destroy; override;
+
+      {**
+       * Sets the color of the outline.
+       * If the alpha component is < 0, OpenGL's current alpha value will be
+       * used.
+       *}
+      procedure SetOutlineColor(r, g, b: GLfloat; a: GLfloat = -1.0);
+
+      {** @seealso TGlyphCache.FlushCache }
+      procedure FlushCache(KeepBaseSet: boolean);
+
+      procedure AddFallback(const Filename: IPath); override;
+      
+      {** @seealso TFont.Reset }
+      procedure Reset(); override;
+
+      {** Size of the base font }
+      property Size: integer read fSize;
+      {** Outset size }
+      property Outset: single read fOutset;
+  end;
+
+  {**
+   * Wrapper around TOutlineFont to allow font resizing.
+   * @seealso TScalableFont
+   *}
+  TFTScalableOutlineFont = class(TScalableFont)
+    protected
+      function GetOutset(): single; virtual;
+      function CreateMipmap(Level: integer; Scale: single): TFont; override;
+
+    public
+      constructor Create(const Filename: IPath;
+                         Size: integer; OutsetAmount: single;
+                         UseMipmaps: boolean = true;
+                         PreCache: boolean = true);
+
+      {** @seealso TFTOutlineFont.SetOutlineColor }
+      procedure SetOutlineColor(r, g, b: GLfloat; a: GLfloat = -1.0);
+
+      {** @seealso TGlyphCache.FlushCache }
+      procedure FlushCache(KeepBaseSet: boolean);
+
+      procedure AddFallback(const Filename: IPath); override;
+      
+      {** Outset size }
+      property Outset: single read GetOutset;
+  end;
+
+{$IFDEF BITMAP_FONT}
+
+  {**
+   * A bitmapped font loads it's glyphs from a bitmap and stores them in a
+   * texture. Unicode characters are not supported (but could be by supporting
+   * multiple textures each storing a subset of unicode glyphs).
+   * For backward compatibility only.
+   *}
+  TBitmapFont = class(TFont)
+    private
+      fTex:       TTexture;
+      fTexSize:   integer;
+      fBaseline:  integer;
+      fAscender:  integer;
+      fDescender: integer;
+      fWidths:    array[0..255] of byte; //**< half widths
+      fOutline:   integer;
+      fTempColor: TGLColor; //**< colours for the reflection
+
+      procedure ResetIntern();
+
+      procedure RenderChar(ch: UCS4Char; var AdvanceX: real);
+
+      {**
+       * Load font widths from an info file.
+       * @param  InfoFile  the name of the info (.dat) file
+       * @raises EFontError if the file is corrupted
+       *}
+      procedure LoadFontInfo(const InfoFile: IPath);
+
+    protected
+      procedure Render(const Text: UCS4String); override;
+      function BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl; override;
+
+      function GetHeight(): single; override;
+      function GetAscender(): single; override;
+      function GetDescender(): single; override;
+      function GetUnderlinePosition(): single; override;
+      function GetUnderlineThickness(): single; override;
+
+    public
+      {**
+       * Creates a bitmapped font from image Filename and font width info
+       * loaded from the corresponding file with ending .dat.
+       * @param(Baseline  y-coord of the baseline given in cartesian coords
+       *        (y-axis up) and from the lower edge of the glyphs bounding box)
+       * @param(Ascender  pixels from baseline to top of highest glyph)
+       *}
+      constructor Create(const Filename: IPath; Outline: integer;
+                         Baseline, Ascender, Descender: integer);
+      destructor Destroy(); override;
+
+      {**
+       * Corrects font widths provided by the info file.
+       * NewWidth := Width * WidthMult + WidthAdd
+       *}
+      procedure CorrectWidths(WidthMult: real; WidthAdd: integer);
+
+      {** @seealso TFont.Reset }
+      procedure Reset(); override;
+
+      procedure AddFallback(const Filename: IPath); override;
+  end;
+
+{$ENDIF BITMAP_FONT}
+
+  TFreeType = class
+    public
+      {**
+       * Returns a pointer to the freetype library singleton.
+       * If non exists, freetype will be initialized.
+       * @raises EFontError if initialization failed
+       *}
+      class function GetLibrary(): FT_Library;
+      class procedure FreeLibrary();
+  end;
+
+
+implementation
+
+uses Types;
+
+const
+  //** shear factor used for the italic effect (bigger value -> more bending)
+  cShearFactor = 0.25;
+  cShearMatrix: array[0..15] of GLfloat = (
+      1,            0, 0, 0,
+      cShearFactor, 1, 0, 0,
+      0,            0, 1, 0,
+      0,            0, 0, 1
+  );
+  cShearMatrixInv: array[0..15] of GLfloat = (
+      1,             0, 0, 0,
+      -cShearFactor, 1, 0, 0,
+      0,             0, 1, 0,
+      0,             0, 0, 1
+  );
+
+var
+  LibraryInst: FT_Library;
+
+function NewGLColor(r, g, b, a: GLfloat): TGLColor;
+begin
+  Result.r := r;
+  Result.g := g;
+  Result.b := b;
+  Result.a := a;
+end;
+
+{**
+ * Returns the first power of 2 >= Value.
+ *}
+function NextPowerOf2(Value: integer): integer; {$IFDEF HasInline}inline;{$ENDIF}
+begin
+  Result := 1;
+  while (Result < Value) do
+    Result := Result shl 1;
+end;
+
+
+{*
+ * TFont
+ *}
+
+constructor TFont.Create(const Filename: IPath);
+begin
+  inherited Create();
+  fFilename := Filename;
+  ResetIntern();
+end;
+
+destructor TFont.Destroy();
+begin
+  inherited;
+end;
+
+procedure TFont.ResetIntern();
+begin
+  fStyle := [];
+  fUseKerning := true;
+  fGlyphSpacing := 0.0;
+  fReflectionPass := false;
+
+  // must be set by subclasses
+  fLineSpacing := 0.0;
+  fReflectionSpacing := 0.0;
+end;
+
+procedure TFont.Reset();
+begin
+  ResetIntern();
+end;
+
+procedure TFont.SplitLines(const Text: UCS4String; var Lines: TUCS4StringArray);
+var
+  CharIndex: integer;
+  LineStart: integer;
+  LineLength: integer;
+  EOT: boolean; // End-Of-Text
+begin
+  // split lines on newline
+  SetLength(Lines, 0);
+  EOT := false;
+  LineStart := 0;
+
+  for CharIndex := 0 to High(Text) do
+  begin
+    // check for end of text (UCS4Strings are zero-terminated)
+    if (CharIndex = High(Text)) then
+      EOT := true;
+
+    // check for newline (carriage return (#13)) or end of text
+    if (Text[CharIndex] = 13) or EOT then
+    begin
+      LineLength := CharIndex - LineStart;
+      // check if last character was a newline
+      if (EOT and (LineLength = 0)) then
+        Break;      
+
+      // copy line (even if LineLength is 0)
+      SetLength(Lines, Length(Lines)+1);
+      Lines[High(Lines)] := UCS4Copy(Text, LineStart, LineLength);
+
+      LineStart := CharIndex+1;
+    end;
+  end;
+end;
+
+function TFont.BBox(const Text: UCS4String; Advance: boolean): TBoundsDbl;
+var
+  LineArray: TUCS4StringArray;
+begin
+  SplitLines(Text, LineArray);
+  Result := BBox(LineArray, Advance);
+  SetLength(LineArray, 0);
+end;
+
+function TFont.BBox(const Text: UTF8String; Advance: boolean): TBoundsDbl;
+begin
+  Result := BBox(UTF8Decode(Text), Advance);
+end;
+
+function TFont.BBox(const Text: WideString; Advance: boolean): TBoundsDbl;
+begin
+  Result := BBox(WideStringToUCS4String(Text), Advance);
+end;
+
+procedure TFont.Print(const Text: TUCS4StringArray);
+var
+  LineIndex: integer;
+begin
+  // recursively call this function to draw reflected text
+  if ((Reflect in Style) and not ReflectionPass) then
+  begin
+    ReflectionPass := true;
+    Print(Text);
+    ReflectionPass := false;
+  end;
+
+  // store current color, enable-flags, matrix-mode
+  glPushAttrib(GL_CURRENT_BIT or GL_ENABLE_BIT or GL_TRANSFORM_BIT);
+
+  // set OpenGL state
+  glMatrixMode(GL_MODELVIEW);
+  glDisable(GL_DEPTH_TEST);
+  glEnable(GL_BLEND);
+  glEnable(GL_TEXTURE_2D);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  {
+  // TODO: just draw texels with alpha > 0 to avoid setting z-buffer for them?
+  glAlphaFunc(GL_GREATER, 0);
+  glEnable(GL_ALPHA_TEST);
+
+  //TODO: Do we need depth-testing?
+  if (ReflectionPass) then
+  begin
+    glDepthMask(0);
+    glEnable(GL_DEPTH_TEST);
+  end;
+  }
+
+  {$IFDEF FLIP_YAXIS}
+  glPushMatrix();
+  glScalef(1, -1, 1);
+  {$ENDIF}
+
+  // display text
+  for LineIndex := 0 to High(Text) do
+  begin
+    glPushMatrix();
+
+    // move to baseline
+    glTranslatef(0, -LineSpacing*LineIndex, 0);
+
+    if ((Underline in Style) and not ReflectionPass) then
+    begin
+      glDisable(GL_TEXTURE_2D);
+      DrawUnderline(Text[LineIndex]);
+      glEnable(GL_TEXTURE_2D);
+    end;
+
+    // draw reflection
+    if (ReflectionPass) then
+    begin
+      // set reflection spacing
+      glTranslatef(0, -ReflectionSpacing, 0);
+      // flip y-axis
+      glScalef(1, -1, 1);
+    end;
+
+    // shear for italic effect
+    if (Italic in Style) then
+      glMultMatrixf(@cShearMatrix);
+
+    // render text line
+    Render(Text[LineIndex]);
+
+    glPopMatrix();
+  end;
+
+  // restore settings
+  {$IFDEF FLIP_YAXIS}
+  glPopMatrix();
+  {$ENDIF}
+  glPopAttrib();
+end;
+
+procedure TFont.Print(const Text: UCS4String);
+var
+  LineArray: TUCS4StringArray;
+begin
+  SplitLines(Text, LineArray);
+  Print(LineArray);
+  SetLength(LineArray, 0);
+end;
+
+procedure TFont.Print(const Text: UTF8String);
+begin
+  Print(UTF8Decode(Text));
+end;
+
+procedure TFont.Print(const Text: WideString);
+begin
+  Print(WideStringToUCS4String(Text));
+end;
+
+procedure TFont.DrawUnderline(const Text: UCS4String);
+var
+  UnderlineY1, UnderlineY2: single;
+  Bounds: TBoundsDbl;
+begin
+  UnderlineY1 := GetUnderlinePosition();
+  UnderlineY2 := UnderlineY1 + GetUnderlineThickness();
+  Bounds := BBox(Text, false);
+  glRectf(Bounds.Left, UnderlineY1, Bounds.Right, UnderlineY2);
+end;
+
+procedure TFont.SetStyle(Style: TFontStyle);
+begin
+  fStyle := Style;
+end;
+
+function TFont.GetStyle(): TFontStyle;
+begin
+  Result := fStyle;
+end;
+
+procedure TFont.SetLineSpacing(Spacing: single);
+begin
+  fLineSpacing := Spacing;
+end;
+
+function TFont.GetLineSpacing(): single;
+begin
+  Result := fLineSpacing;
+end;
+
+procedure TFont.SetGlyphSpacing(Spacing: single);
+begin
+  fGlyphSpacing := Spacing;
+end;
+
+function TFont.GetGlyphSpacing(): single;
+begin
+  Result := fGlyphSpacing;
+end;
+
+procedure TFont.SetReflectionSpacing(Spacing: single);
+begin
+  fReflectionSpacing := Spacing;
+end;
+
+function TFont.GetReflectionSpacing(): single;
+begin
+  Result := fReflectionSpacing;
+end;
+
+procedure TFont.SetUseKerning(Enable: boolean);
+begin
+  fUseKerning := Enable;
+end;
+
+function TFont.GetUseKerning(): boolean;
+begin
+  Result := fUseKerning;
+end;
+
+procedure TFont.SetReflectionPass(Enable: boolean);
+begin
+  fReflectionPass := Enable;
+end;
+
+
+{*
+ * TScalableFont
+ *}
+
+constructor TScalableFont.Create(Font: TFont; UseMipmaps: boolean);
+var
+  MipmapLevel: integer;
+begin
+  inherited Create(Font.Filename);
+  
+  fBaseFont := Font;
+  fMipmapFonts[0] := Font;
+  fUseMipmaps := UseMipmaps;
+  ResetIntern();
+
+  // create mipmap fonts if requested
+  if (UseMipmaps) then
+  begin
+    for MipmapLevel := 1 to cMaxMipmapLevel do
+    begin
+      fMipmapFonts[MipmapLevel] := CreateMipmap(MipmapLevel, 1/(1 shl MipmapLevel));
+      // stop if no smaller mipmap font is returned
+      if (fMipmapFonts[MipmapLevel] = nil) then
+        Break;
+    end;
+  end;
+end;
+
+destructor TScalableFont.Destroy();
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    fMipmapFonts[Level].Free;
+  inherited;
+end;
+
+procedure TScalableFont.ResetIntern();
+begin
+  fScale := 1.0;
+  fStretch := 1.0;
+end;
+
+procedure TScalableFont.Reset();
+var
+  Level: integer;
+begin
+  inherited;
+  ResetIntern();
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      fMipmapFonts[Level].Reset();
+end;
+
+{**
+ * Returns the mipmap level to use with regard to the current projection
+ * and modelview matrix, font scale and stretch.
+ *
+ * Note:
+ * - for Freetype fonts, hinting and grid-fitting must be disabled, otherwise
+ *   the glyph widths/heights ratios and advance widths of the mipmap fonts
+ *   do not match as they are adjusted sligthly (e.g. an 'a' at size 12px has
+ *   width 12px, but at size 6px width 8px).
+ * - returned mipmap-level is used for all glyphs of the current text to print.
+ *   This is faster, much easier to handle, since we just need to create
+ *   multiple sized fonts and select the one we need for the mipmap-level and
+ *   it avoids that neighbored glyphs use different mipmap-level which might
+ *   look odd because one glyph might look blurry and the other sharp.
+ *
+ * Motivation:
+ *   We do not use OpenGL for mipmapping as the results are very bad. At least
+ *   with automatic mipmap generation (gluBuildMipmaps) the fonts look rather
+ *   blurry.
+ *   Defining our own mipmaps by creating multiple textures with
+ *   for different mimap levels is a pain, as the font size passed to freetype
+ *   is not the size of the bitmaps created and it does not guarantee that a
+ *   glyph bitmap of a font with font-size s/2 is half the size of the font with
+ *   font-size s. If the bitmap size is just a single pixel bigger than the half
+ *   we might need a texture of the next power-of-2 and the texture would not be
+ *   half of the size of the next bigger mipmap. In addition we use a fixed one
+ *   pixel sized border to smooth the texture (see cTexSmoothBorder) and maybe
+ *   an outset that is added to the font, so creating a glyph mipmap that is
+ *   exactly half the size of the next bigger one is a very difficult task.
+ *
+ * Solution:
+ *   Use mipmap textures that are not exactly half the size of the next mipmap
+ *   level. OpenGL does not support this (at least not without extensions).
+ *   The trickiest task is to determine the mipmap to use by calculating the
+ *   amount of minification that is performed in this function.
+ *}
+function TScalableFont.GetMipmapLevel(): integer;
+var
+  ModelMatrix, ProjMatrix: T16dArray;
+  WinCoords: array[0..2, 0..2] of GLdouble;
+  ViewPortArray: TViewPortArray;
+  Dist, Dist2, DistSum: double;
+  WidthScale, HeightScale: double;
+const
+  // width/height of square used for determining the scale
+  cTestSize = 10.0;
+  // an offset to the mipmap-level to adjust the change-over of two consecutive
+  // mipmap levels. If for example the bias is 0.1 and unbiased level is 1.9
+  // the result level will be 2. A bias of 0.5 is equal to rounding.
+  // With bias=0.1 we prefer larger mipmaps over smaller ones.
+  cBias = 0.2;
+begin
+  // 1. retrieve current transformation matrices for gluProject
+  glGetDoublev(GL_MODELVIEW_MATRIX, @ModelMatrix);
+  glGetDoublev(GL_PROJECTION_MATRIX, @ProjMatrix);
+  glGetIntegerv(GL_VIEWPORT, @ViewPortArray);
+
+  // 2. project three of the corner points of a square with size cTestSize
+  // to window coordinates (the square is just a dummy for a glyph)
+
+  // project point (x1, y1) to window corrdinates
+  gluProject(0, 0, 0,
+             ModelMatrix, ProjMatrix, ViewPortArray,
+             @WinCoords[0][0], @WinCoords[0][1], @WinCoords[0][2]);
+  // project point (x2, y1) to window corrdinates
+  gluProject(cTestSize, 0, 0,
+             ModelMatrix, ProjMatrix, ViewPortArray,
+             @WinCoords[1][0], @WinCoords[1][1], @WinCoords[1][2]);
+  // project point (x1, y2) to window corrdinates
+  gluProject(0, cTestSize, 0,
+             ModelMatrix, ProjMatrix, ViewPortArray,
+             @WinCoords[2][0], @WinCoords[2][1], @WinCoords[2][2]);
+
+  // 3. Lets see how much the width and height of the square changed.
+  // Calculate the width and height as displayed on the screen in window
+  // coordinates and calculate the ratio to the original coordinates in
+  // modelview space so the ratio gives us the scale (minification here).
+
+  // projected width ||(x1, y1) - (x2, y1)||
+  Dist  := (WinCoords[0][0] - WinCoords[1][0]);
+  Dist2 := (WinCoords[0][1] - WinCoords[1][1]);
+
+  WidthScale := 1;
+  DistSum := Dist*Dist + Dist2*Dist2;
+  if (DistSum > 0) then
+  begin
+    WidthScale := cTestSize / Sqrt(DistSum);
+  end;
+
+  // projected height ||(x1, y1) - (x1, y2)||
+  Dist  := (WinCoords[0][0] - WinCoords[2][0]);
+  Dist2 := (WinCoords[0][1] - WinCoords[2][1]);
+
+  HeightScale := 1;
+  DistSum := Dist*Dist + Dist2*Dist2;
+  if (DistSum > 0) then
+  begin
+    HeightScale := cTestSize / Sqrt(DistSum);
+  end;
+
+  //writeln(Format('Scale %f, %f', [WidthScale, HeightScale]));
+
+  // 4. Now that we have got the scale, take the bigger minification scale
+  // and get it to a logarithmic scale as each mipmap is 1/2 the size of its
+  // predecessor (Mipmap_size[i] = Mipmap_size[i-1]/2).
+  // The result is our mipmap-level = the index of the mipmap to use.
+
+  // Level > 0: Minification; < 0: Magnification
+  Result := Trunc(Log2(Max(WidthScale, HeightScale)) + cBias);
+
+  // clamp to valid range
+  if (Result < 0) then
+    Result := 0;
+  if (Result > High(fMipmapFonts)) then
+    Result := High(fMipmapFonts);
+end;
+
+function TScalableFont.GetMipmapScale(Level: integer): single;
+begin
+  if (fMipmapFonts[Level] = nil) then
+  begin
+    Result := -1;
+    Exit;
+  end;
+
+  Result := fScale * fMipmapFonts[0].Height / fMipmapFonts[Level].Height;
+end;
+
+{**
+ * Returns the correct mipmap font for the current scale and projection
+ * matrix. The modelview scale is adjusted to the mipmap level, so
+ * Result.Print() will display the font in the correct size.
+ *}
+function TScalableFont.ChooseMipmapFont(): TFont;
+var
+  DesiredLevel: integer;
+  Level: integer;
+  MipmapScale: single;
+begin
+  Result := nil;
+  DesiredLevel := GetMipmapLevel();
+
+  // get the smallest mipmap available for the desired level
+  // as not all levels must be assigned to a font.
+  for Level := DesiredLevel downto 0 do
+  begin
+    if (fMipmapFonts[Level] <> nil) then
+    begin
+      Result := fMipmapFonts[Level];
+      Break;
+    end;
+  end;
+
+  // since the mipmap font (if level > 0) is smaller than the base-font
+  // we have to scale to get its size right.
+  MipmapScale := fMipmapFonts[0].Height/Result.Height;
+  glScalef(MipmapScale, MipmapScale, 0);
+end;
+
+procedure TScalableFont.Print(const Text: TUCS4StringArray);
+begin
+  glPushMatrix();
+
+  // set scale and stretching
+  glScalef(fScale * fStretch, fScale, 0);
+
+  // print text
+  if (fUseMipmaps) then
+    ChooseMipmapFont().Print(Text)
+  else
+    fBaseFont.Print(Text);
+
+  glPopMatrix();
+end;
+
+procedure TScalableFont.Render(const Text: UCS4String);
+begin
+  Assert(false, 'Unused TScalableFont.Render() was called');
+end;
+
+function TScalableFont.BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl;
+begin
+  Result := fBaseFont.BBox(Text, Advance);
+  Result.Left   := Result.Left * fScale * fStretch;
+  Result.Right  := Result.Right * fScale * fStretch;
+  Result.Top    := Result.Top * fScale;
+  Result.Bottom := Result.Bottom * fScale;
+end;
+
+procedure TScalableFont.SetHeight(Height: single);
+begin
+  fScale := Height / fBaseFont.GetHeight();
+end;
+
+function TScalableFont.GetHeight(): single;
+begin
+  Result := fBaseFont.GetHeight() * fScale;
+end;
+
+procedure TScalableFont.SetStretch(Stretch: single);
+begin
+  fStretch := Stretch;
+end;
+
+function TScalableFont.GetStretch(): single;
+begin
+  Result := fStretch;
+end;
+
+function TScalableFont.GetAscender(): single;
+begin
+  Result := fBaseFont.GetAscender() * fScale;
+end;
+
+function TScalableFont.GetDescender(): single;
+begin
+  Result := fBaseFont.GetDescender() * fScale;
+end;
+
+procedure TScalableFont.SetLineSpacing(Spacing: single);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      fMipmapFonts[Level].SetLineSpacing(Spacing / GetMipmapScale(Level));
+end;
+
+function TScalableFont.GetLineSpacing(): single;
+begin
+  Result := fBaseFont.GetLineSpacing() * fScale;
+end;
+
+procedure TScalableFont.SetGlyphSpacing(Spacing: single);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      fMipmapFonts[Level].SetGlyphSpacing(Spacing / GetMipmapScale(Level));
+end;
+
+function TScalableFont.GetGlyphSpacing(): single;
+begin
+  Result := fBaseFont.GetGlyphSpacing() * fScale;
+end;
+
+procedure TScalableFont.SetReflectionSpacing(Spacing: single);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if ((fMipmapFonts[Level] <> nil) AND (GetMipmapScale(Level) > 0)) then
+      fMipmapFonts[Level].SetReflectionSpacing(Spacing / GetMipmapScale(Level));
+end;
+
+function TScalableFont.GetReflectionSpacing(): single;
+begin
+  Result := fBaseFont.GetLineSpacing() * fScale;
+end;
+
+procedure TScalableFont.SetStyle(Style: TFontStyle);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      fMipmapFonts[Level].SetStyle(Style);
+end;
+
+function TScalableFont.GetStyle(): TFontStyle;
+begin
+  Result := fBaseFont.GetStyle();
+end;
+
+function TScalableFont.GetUnderlinePosition(): single;
+begin
+  Result := fBaseFont.GetUnderlinePosition();
+end;
+
+function TScalableFont.GetUnderlineThickness(): single;
+begin
+  Result := fBaseFont.GetUnderlinePosition();
+end;
+
+procedure TScalableFont.SetUseKerning(Enable: boolean);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      fMipmapFonts[Level].SetUseKerning(Enable);
+end;
+
+
+{*
+ * TCachedFont
+ *}
+
+constructor TCachedFont.Create(const Filename: IPath);
+begin
+  inherited Create(Filename);
+  fCache := TGlyphCache.Create();
+end;
+
+destructor TCachedFont.Destroy();
+begin
+  fCache.Free;
+  inherited;
+end;
+
+function TCachedFont.GetGlyph(ch: UCS4Char): TGlyph;
+begin
+  Result := fCache.GetGlyph(ch);
+  if (Result = nil) then
+  begin
+    Result := LoadGlyph(ch);
+    if (not fCache.AddGlyph(ch, Result)) then
+      Result.Free;
+  end;
+end;
+
+procedure TCachedFont.FlushCache(KeepBaseSet: boolean);
+begin
+  fCache.FlushCache(KeepBaseSet);
+end;
+
+{*
+ * TFTFontFaceCache
+ *}
+
+{*
+ * TFTFontFace
+ *}
+
+constructor TFTFontFace.Create(const Filename: IPath; Size: integer);
+begin
+  inherited Create();
+
+  fFilename := Filename;
+  fSize := Size;
+
+  // load font information
+  if (FT_New_Face(TFreeType.GetLibrary(), PChar(Filename.ToNative), 0, fFace) <> 0) then
+    raise EFontError.Create('FT_New_Face: Could not load font '''  + Filename.ToNative + '''');
+
+  // support scalable fonts only
+  if (not FT_IS_SCALABLE(fFace)) then
+    raise EFontError.Create('Font is not scalable');
+
+  if (FT_Set_Pixel_Sizes(fFace, 0, Size) <> 0) then
+    raise EFontError.Create('FT_Set_Pixel_Sizes failes');
+
+  // get scale factor for font-unit to pixel-size transformation
+  fFontUnitScale.X := fFace.size.metrics.x_ppem / fFace.units_per_EM;
+  fFontUnitScale.Y := fFace.size.metrics.y_ppem / fFace.units_per_EM;
+end;
+
+destructor TFTFontFace.Destroy();
+begin
+  // free face data
+  FT_Done_Face(fFace);
+  inherited;
+end;
+
+
+{*
+ * TFTFontFaceCache
+ *}
+
+function TFTFontFaceCache.LoadFace(const Filename: IPath; Size: integer): TFTFontFace;
+var
+  I: Integer;
+  Face: TFTFontFace;
+begin
+  {$IFDEF ENABLE_FT_FACE_CACHE}
+  for I := 0 to High(fFaces) do
+  begin
+    Face := fFaces[I];
+    // check if we have this file in our cache
+    if ((Face.Filename.Equals(Filename)) and (Face.Size = Size)) then
+    begin
+      // true -> return cached face and increment ref-count
+      Inc(fFacesRefCnt[I]);
+      Result := Face;
+      Exit;
+    end;
+  end;
+  {$ENDIF}
+
+  // face not in cache -> load it
+  Face := TFTFontFace.Create(Filename, Size);
+
+  // add face to cache
+  SetLength(fFaces, Length(fFaces)+1);
+  SetLength(fFacesRefCnt, Length(fFaces)+1);
+  fFaces[High(fFaces)] := Face;
+  fFacesRefCnt[High(fFaces)] := 1;
+
+  Result := Face;
+end;
+
+procedure TFTFontFaceCache.UnloadFace(Face: TFTFontFace);
+var
+  I: Integer;
+begin
+  for I := 0 to High(fFaces) do
+  begin
+    // search face in cache
+    if (fFaces[I] = Face) then
+    begin
+      // decrement ref-count and free face if ref-count is 0
+      Dec(fFacesRefCnt[I]);
+      if (fFacesRefCnt[I] <= 0) then
+        fFaces[I].Free;
+      Exit;
+    end;
+  end;
+end;
+
+
+{*
+ * TFTFont
+ *}
+
+constructor TFTFont.Create(
+    const Filename: IPath;
+    Size: integer; Outset: single;
+    PreCache: boolean;
+    LoadFlags: FT_Int32);
+var
+  ch: UCS4Char;
+begin
+  inherited Create(Filename);
+
+  fSize := Size;
+  fOutset := Outset;
+  fPreCache := PreCache;
+  fLoadFlags := LoadFlags;
+  fUseDisplayLists := true;
+  fPart := fpNone;
+
+  fFace := GetFaceCache.LoadFace(Filename, Size);
+
+  ResetIntern();
+
+  // pre-cache some commonly used glyphs (' ' - '~')
+  if (PreCache) then
+  begin
+    for ch := 32 to 126 do
+      fCache.AddGlyph(ch, TFTGlyph.Create(Self, ch, Outset, LoadFlags));
+  end;
+end;
+
+destructor TFTFont.Destroy();
+var
+  I: integer;
+begin
+  // free faces
+  GetFaceCache.UnloadFace(fFace);
+  for I := 0 to High(fFallbackFaces) do
+    GetFaceCache.UnloadFace(fFallbackFaces[I]);    
+
+  inherited;
+end;
+
+var
+  FontFaceCache: TFTFontFaceCache = nil;
+
+class function TFTFont.GetFaceCache(): TFTFontFaceCache;
+begin
+  if (FontFaceCache = nil) then
+    FontFaceCache := TFTFontFaceCache.Create;
+  Result := FontFaceCache;
+end;
+
+procedure TFTFont.ResetIntern();
+begin
+  // Note: outset and non outset fonts use same spacing
+  fLineSpacing := fFace.Data.height * fFace.FontUnitScale.Y;
+  fReflectionSpacing := -2*fFace.Data.descender * fFace.FontUnitScale.Y;
+end;
+
+procedure TFTFont.Reset();
+begin
+  inherited;
+  ResetIntern();
+end;
+
+procedure TFTFont.AddFallback(const Filename: IPath);
+var
+  FontFace: TFTFontFace;
+begin
+  FontFace := GetFaceCache.LoadFace(Filename, Size);
+  SetLength(fFallbackFaces, Length(fFallbackFaces) + 1);
+  fFallbackFaces[High(fFallbackFaces)] := FontFace;
+end;
+
+function TFTFont.LoadGlyph(ch: UCS4Char): TGlyph;
+begin
+  Result := TFTGlyph.Create(Self, ch, Outset, fLoadFlags);
+end;
+
+function TFTFont.BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl;
+var
+  Glyph, PrevGlyph: TFTGlyph;
+  TextLine: UCS4String;
+  LineYOffset: single;
+  LineIndex, CharIndex: integer;
+  LineBounds: TBoundsDbl;
+  KernDelta: FT_Vector;
+  UnderlinePos: double;
+begin
+  // Reset global bounds
+  Result.Left   := Infinity;
+  Result.Right  := 0;
+  Result.Bottom := Infinity;
+  Result.Top    := 0;
+
+  // reset last glyph
+  PrevGlyph := nil;
+
+  // display text
+  for LineIndex := 0 to High(Text) do
+  begin
+    // get next text line
+    TextLine := Text[LineIndex];
+    LineYOffset := -LineSpacing * LineIndex;
+
+    // reset line bounds
+    LineBounds.Left   := Infinity;
+    LineBounds.Right  := 0;
+    LineBounds.Bottom := Infinity;
+    LineBounds.Top    := 0;
+
+    // for each glyph image, compute its bounding box
+    for CharIndex := 0 to LengthUCS4(TextLine)-1 do
+    begin
+      Glyph := TFTGlyph(GetGlyph(TextLine[CharIndex]));
+      if (Glyph <> nil) then
+      begin
+        // get kerning
+        if (fUseKerning and FT_HAS_KERNING(fFace.Data) and (PrevGlyph <> nil)) then
+        begin
+          FT_Get_Kerning(fFace.Data, PrevGlyph.CharIndex, Glyph.CharIndex,
+                         FT_KERNING_UNSCALED, KernDelta);
+          LineBounds.Right := LineBounds.Right + KernDelta.x * fFace.FontUnitScale.X;
+        end;
+
+        // update left bound (must be done before right bound is updated)
+        if (LineBounds.Right + Glyph.Bounds.Left < LineBounds.Left) then
+          LineBounds.Left := LineBounds.Right + Glyph.Bounds.Left;
+
+        // update right bound
+        if (CharIndex < LengthUCS4(TextLine)-1) or  // not the last character
+           (TextLine[CharIndex] = Ord(' ')) or      // on space char (Bounds.Right = 0)
+           Advance then                             // or in advance mode
+        begin
+          // add advance and glyph spacing
+          LineBounds.Right := LineBounds.Right + Glyph.Advance.x + GlyphSpacing
+        end
+        else
+        begin
+          // add glyph's right bound
+          LineBounds.Right := LineBounds.Right + Glyph.Bounds.Right;
+        end;
+
+        // update bottom and top bounds
+        if (Glyph.Bounds.Bottom < LineBounds.Bottom) then
+          LineBounds.Bottom := Glyph.Bounds.Bottom;
+        if (Glyph.Bounds.Top > LineBounds.Top) then
+          LineBounds.Top := Glyph.Bounds.Top;
+      end;
+
+      PrevGlyph := Glyph;
+    end;
+
+    // handle italic font style
+    if (Italic in Style) then
+    begin
+      LineBounds.Left := LineBounds.Left + LineBounds.Bottom * cShearFactor;
+      LineBounds.Right := LineBounds.Right + LineBounds.Top * cShearFactor;
+    end;
+
+    // handle underlined font style
+    if (Underline in Style) then
+    begin
+      UnderlinePos := GetUnderlinePosition();
+      if (UnderlinePos < LineBounds.Bottom) then
+        LineBounds.Bottom := UnderlinePos;
+    end;
+
+    // add line offset
+    LineBounds.Bottom := LineBounds.Bottom + LineYOffset;
+    LineBounds.Top := LineBounds.Top + LineYOffset;
+
+    // adjust global bounds
+    if (Result.Left > LineBounds.Left) then
+      Result.Left := LineBounds.Left;
+    if (Result.Right < LineBounds.Right) then
+      Result.Right := LineBounds.Right;
+    if (Result.Bottom > LineBounds.Bottom) then
+      Result.Bottom := LineBounds.Bottom;
+    if (Result.Top < LineBounds.Top) then
+      Result.Top := LineBounds.Top;
+  end;
+
+  // if left or bottom bound was not set, set them to 0
+  if (IsInfinite(Result.Left)) then
+    Result.Left := 0.0;
+  if (IsInfinite(Result.Bottom)) then
+    Result.Bottom := 0.0;
+end;
+
+procedure TFTFont.Render(const Text: UCS4String);
+var
+  CharIndex: integer;
+  Glyph, PrevGlyph: TFTGlyph;
+  KernDelta: FT_Vector;
+begin
+  // reset last glyph
+  PrevGlyph := nil;
+
+  // draw current line
+  for CharIndex := 0 to LengthUCS4(Text)-1 do
+  begin
+    Glyph := TFTGlyph(GetGlyph(Text[CharIndex]));
+    if (Assigned(Glyph)) then
+    begin
+      // get kerning
+      if (fUseKerning and FT_HAS_KERNING(fFace.Data) and (PrevGlyph <> nil)) then
+      begin
+        FT_Get_Kerning(fFace.Data, PrevGlyph.CharIndex, Glyph.CharIndex,
+                       FT_KERNING_UNSCALED, KernDelta);
+        glTranslatef(KernDelta.x * fFace.FontUnitScale.X, 0, 0);
+      end;
+
+      if (ReflectionPass) then
+        Glyph.RenderReflection()
+      else
+        Glyph.Render(fUseDisplayLists);
+
+      glTranslatef(Glyph.Advance.x + fGlyphSpacing, 0, 0);
+    end;
+
+    PrevGlyph := Glyph;
+  end;
+end;
+
+function TFTFont.GetHeight(): single;
+begin
+  Result := Ascender - Descender;
+end;
+
+function TFTFont.GetAscender(): single;
+begin
+  Result := fFace.Data.ascender * fFace.FontUnitScale.Y + Outset*2;
+end;
+
+function TFTFont.GetDescender(): single;
+begin
+  // Note: outset is not part of the descender as the baseline is lifted
+  Result := fFace.Data.descender * fFace.FontUnitScale.Y;
+end;
+
+function TFTFont.GetUnderlinePosition(): single;
+begin
+  Result := fFace.Data.underline_position * fFace.FontUnitScale.Y - Outset;
+end;
+
+function TFTFont.GetUnderlineThickness(): single;
+begin
+  Result := fFace.Data.underline_thickness * fFace.FontUnitScale.Y + Outset*2;
+end;
+
+
+{*
+ * TFTScalableFont
+ *}
+
+constructor TFTScalableFont.Create(const Filename: IPath;
+                   Size: integer; OutsetAmount: single;
+                   UseMipmaps: boolean;
+                   PreCache: boolean);
+var
+  LoadFlags: FT_Int32;
+begin
+  LoadFlags := FT_LOAD_DEFAULT;
+  // Disable hinting and grid-fitting to preserve font outlines at each font
+  // size, otherwise the font widths/heights do not match resulting in ugly
+  // text size changes during zooming.
+  // A drawback is a reduced quality with smaller font sizes but it is not that
+  // bad with gray-scaled rendering (at least it looks better than OpenGL's
+  // linear downscaling on minification).
+  if (UseMipmaps) then
+    LoadFlags := LoadFlags or FT_LOAD_NO_HINTING;
+  inherited Create(
+      TFTFont.Create(Filename, Size, Size * OutsetAmount, PreCache, LoadFlags),
+      UseMipmaps);
+end;
+
+function TFTScalableFont.CreateMipmap(Level: integer; Scale: single): TFont;
+var
+  ScaledSize: integer;
+  BaseFont: TFTFont;
+begin
+  Result := nil;
+  BaseFont := TFTFont(fBaseFont);
+  ScaledSize := Round(BaseFont.Size * Scale);
+  // do not create mipmap fonts < 8 pixels
+  if (ScaledSize < 8) then
+    Exit;
+  Result := TFTFont.Create(BaseFont.Filename,
+      ScaledSize, BaseFont.Outset * Scale,
+      BaseFont.fPreCache,
+      FT_LOAD_DEFAULT or FT_LOAD_NO_HINTING);
+end;
+
+function TFTScalableFont.GetOutset(): single;
+begin
+  Result := TFTFont(fBaseFont).Outset * fScale;
+end;
+
+procedure TFTScalableFont.AddFallback(const Filename: IPath);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      TFTFont(fMipmapFonts[Level]).AddFallback(Filename);
+end;
+
+procedure TFTScalableFont.FlushCache(KeepBaseSet: boolean);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      TFTFont(fMipmapFonts[Level]).FlushCache(KeepBaseSet);
+end;
+
+
+{*
+ * TOutlineFont
+ *}
+
+constructor TFTOutlineFont.Create(
+    const Filename: IPath;
+    Size: integer; Outset: single;
+    PreCache: boolean;
+    LoadFlags: FT_Int32);
+begin
+  inherited Create(Filename);
+
+  fSize := Size;
+  fOutset := Outset;
+  fPreCache := PreCache;
+  fInnerFont := TFTFont.Create(Filename, Size, 0.0, PreCache, LoadFlags);
+  fInnerFont.Part := fpInner;
+  fOutlineFont := TFTFont.Create(Filename, Size, Outset, PreCache, LoadFlags);
+  fOutlineFont.Part := fpOutline;
+
+  ResetIntern();
+end;
+
+destructor TFTOutlineFont.Destroy;
+begin
+  fOutlineFont.Free;
+  fInnerFont.Free;
+  inherited;
+end;
+
+procedure TFTOutlineFont.ResetIntern();
+begin
+  // TODO: maybe swap fInnerFont/fOutlineFont.GlyphSpacing to use the spacing
+  // of the outline font?
+  //fInnerFont.GlyphSpacing := fOutset*2;
+  fOutlineFont.GlyphSpacing := -fOutset*2;
+
+  fLineSpacing := fOutlineFont.LineSpacing;
+  fReflectionSpacing := fOutlineFont.ReflectionSpacing;
+  fOutlineColor := NewGLColor(0, 0, 0, -1);
+end;
+
+procedure TFTOutlineFont.Reset();
+begin
+  inherited;
+  fInnerFont.Reset();
+  fOutlineFont.Reset();
+  ResetIntern();
+end;
+
+procedure TFTOutlineFont.DrawUnderline(const Text: UCS4String);
+var
+  CurrentColor: TGLColor;
+  OutlineColor: TGLColor;
+begin
+  // save current color
+  glGetFloatv(GL_CURRENT_COLOR, @CurrentColor.vals);
+
+  // if the outline's alpha component is < 0 use the current alpha
+  OutlineColor := fOutlineColor;
+  if (OutlineColor.a < 0) then
+    OutlineColor.a := CurrentColor.a;
+
+  // draw underline outline (in outline color)
+  glColor4fv(@OutlineColor.vals);
+  fOutlineFont.DrawUnderline(Text);
+  glColor4fv(@CurrentColor.vals);
+
+  // draw underline inner part (in current color)
+  glPushMatrix();
+  glTranslatef(fOutset, 0, 0);
+  fInnerFont.DrawUnderline(Text);
+  glPopMatrix();
+end;
+
+procedure TFTOutlineFont.Render(const Text: UCS4String);
+var
+  CurrentColor: TGLColor;
+  OutlineColor: TGLColor;
+begin
+  // save current color
+  glGetFloatv(GL_CURRENT_COLOR, @CurrentColor.vals);
+
+  // if the outline's alpha component is < 0 use the current alpha
+  OutlineColor := fOutlineColor;
+  if (OutlineColor.a < 0) then
+    OutlineColor.a := CurrentColor.a;
+
+  { setup and render outline font }
+
+  glColor4fv(@OutlineColor.vals);
+  glPushMatrix();
+  fOutlineFont.Render(Text);
+  glPopMatrix();
+  glColor4fv(@CurrentColor.vals);
+
+  { setup and render inner font }
+
+  glPushMatrix();
+  glTranslatef(fOutset, fOutset, 0);
+  fInnerFont.Render(Text);
+  glPopMatrix();
+end;
+
+procedure TFTOutlineFont.SetOutlineColor(r, g, b: GLfloat; a: GLfloat);
+begin
+  fOutlineColor := NewGLColor(r, g, b, a);
+end;
+
+procedure TFTOutlineFont.FlushCache(KeepBaseSet: boolean);
+begin
+  fOutlineFont.FlushCache(KeepBaseSet);
+  fInnerFont.FlushCache(KeepBaseSet);
+end;
+
+procedure TFTOutlineFont.AddFallback(const Filename: IPath);
+begin
+  fOutlineFont.AddFallback(Filename);
+  fInnerFont.AddFallback(Filename);
+end;
+
+function TFTOutlineFont.BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl;
+begin
+  Result := fOutlineFont.BBox(Text, Advance);
+end;
+
+function TFTOutlineFont.GetHeight(): single;
+begin
+  Result := fOutlineFont.Height;
+end;
+
+function TFTOutlineFont.GetAscender(): single;
+begin
+  Result := fOutlineFont.Ascender;
+end;
+
+function TFTOutlineFont.GetDescender(): single;
+begin
+  Result := fOutlineFont.Descender;
+end;
+
+procedure TFTOutlineFont.SetLineSpacing(Spacing: single);
+begin
+  inherited SetLineSpacing(Spacing);
+  fInnerFont.LineSpacing := Spacing;
+  fOutlineFont.LineSpacing := Spacing;
+end;
+
+procedure TFTOutlineFont.SetGlyphSpacing(Spacing: single);
+begin
+  inherited SetGlyphSpacing(Spacing);
+  fInnerFont.GlyphSpacing := Spacing;
+  fOutlineFont.GlyphSpacing := Spacing - Outset*2;
+end;
+
+procedure TFTOutlineFont.SetReflectionSpacing(Spacing: single);
+begin
+  inherited SetReflectionSpacing(Spacing);
+  fInnerFont.ReflectionSpacing := Spacing;
+  fOutlineFont.ReflectionSpacing := Spacing;
+end;
+
+procedure TFTOutlineFont.SetStyle(Style: TFontStyle);
+begin
+  inherited SetStyle(Style);
+  fInnerFont.Style := Style;
+  fOutlineFont.Style := Style;
+end;
+
+function TFTOutlineFont.GetStyle(): TFontStyle;
+begin
+  Result := inherited GetStyle();
+end;
+
+function TFTOutlineFont.GetUnderlinePosition(): single;
+begin
+  Result := fOutlineFont.GetUnderlinePosition();
+end;
+
+function TFTOutlineFont.GetUnderlineThickness(): single;
+begin
+  Result := fOutlineFont.GetUnderlinePosition();
+end;
+
+procedure TFTOutlineFont.SetUseKerning(Enable: boolean);
+begin
+  inherited SetUseKerning(Enable);
+  fInnerFont.fUseKerning := Enable;
+  fOutlineFont.fUseKerning := Enable;
+end;
+
+procedure TFTOutlineFont.SetReflectionPass(Enable: boolean);
+begin
+  inherited SetReflectionPass(Enable);
+  fInnerFont.fReflectionPass := Enable;
+  fOutlineFont.fReflectionPass := Enable;
+end;
+
+{**
+ * TScalableOutlineFont
+ *}
+
+constructor TFTScalableOutlineFont.Create(
+    const Filename: IPath;
+    Size: integer; OutsetAmount: single;
+    UseMipmaps: boolean;
+    PreCache: boolean);
+var
+  LoadFlags: FT_Int32;
+begin
+  LoadFlags := FT_LOAD_DEFAULT;
+  // Disable hinting and grid-fitting (see TFTScalableFont.Create)
+  if (UseMipmaps) then
+    LoadFlags := LoadFlags or FT_LOAD_NO_HINTING;
+  inherited Create(
+      TFTOutlineFont.Create(Filename, Size, Size*OutsetAmount, PreCache, LoadFlags),
+      UseMipmaps);
+end;
+
+function TFTScalableOutlineFont.CreateMipmap(Level: integer; Scale: single): TFont;
+var
+  ScaledSize: integer;
+  BaseFont: TFTOutlineFont;
+begin
+  Result := nil;
+  BaseFont := TFTOutlineFont(fBaseFont);
+  ScaledSize := Round(BaseFont.Size*Scale);
+  // do not create mipmap fonts < 8 pixels
+  if (ScaledSize < 8) then
+    Exit;
+  Result := TFTOutlineFont.Create(BaseFont.fFilename,
+      ScaledSize, BaseFont.fOutset*Scale,
+      BaseFont.fPreCache,
+      FT_LOAD_DEFAULT or FT_LOAD_NO_HINTING);
+end;
+
+function TFTScalableOutlineFont.GetOutset(): single;
+begin
+  Result := TFTOutlineFont(fBaseFont).Outset * fScale;
+end;
+
+procedure TFTScalableOutlineFont.SetOutlineColor(r, g, b: GLfloat; a: GLfloat);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      TFTOutlineFont(fMipmapFonts[Level]).SetOutlineColor(r, g, b, a);
+end;
+
+procedure TFTScalableOutlineFont.FlushCache(KeepBaseSet: boolean);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      TFTOutlineFont(fMipmapFonts[Level]).FlushCache(KeepBaseSet);
+end;
+
+procedure TFTScalableOutlineFont.AddFallback(const Filename: IPath);
+var
+  Level: integer;
+begin
+  for Level := 0 to High(fMipmapFonts) do
+    if (fMipmapFonts[Level] <> nil) then
+      TFTOutlineFont(fMipmapFonts[Level]).AddFallback(Filename);
+end;
+
+
+{*
+ * TFTGlyph
+ *}
+
+const
+  {**
+   * Size of the transparent border surrounding the glyph image in the texture.
+   * The border is necessary because OpenGL does not smooth texels at the
+   * border of a texture with the GL_CLAMP or GL_CLAMP_TO_EDGE styles.
+   * Without the border, magnified glyph textures look very ugly at their edges.
+   * It looks edgy, as if some pixels are missing especially on the left edge
+   * (just set cTexSmoothBorder to 0 to see what is meant by this).
+   * With the border even the glyphs edges are blended to the border (transparent)
+   * color and everything looks nice.
+   *
+   * Note:
+   * OpenGL already supports texture border by setting the border parameter
+   * of glTexImage*D() to 1 and using a texture size of 2^m+2b and setting the
+   * border pixels to the border color. In some forums it is discouraged to use
+   * the border parameter as only a few of the more modern graphics cards support
+   * this feature. On an ATI Radeon 9700 card, the slowed down to 0.5 fps and
+   * the glyph's background got black.  So instead of using this feature we
+   * handle it on our own. The only drawback is that textures might get bigger
+   * because the border might require a higher power of 2 size instead of just
+   * two additional pixels.
+   *}
+  cTexSmoothBorder = 1;
+
+procedure TFTGlyph.StrokeBorder(var Glyph: FT_Glyph);
+var
+  Outline: PFT_Outline;
+  OuterStroker, InnerStroker:  FT_Stroker;
+  OuterNumPoints, InnerNumPoints, GlyphNumPoints: FT_UInt;
+  OuterNumContours, InnerNumContours, GlyphNumContours: FT_UInt;
+  OuterBorder, InnerBorder: FT_StrokerBorder;
+  OutlineFlags: FT_Int;
+  UseStencil: boolean;
+begin
+  // It is possible to extrude the borders of a glyph with FT_Glyph_Stroke
+  // but it will extrude the border to the outside and the inside of a glyph
+  // although we just want to extrude to the outside.
+  // FT_Glyph_StrokeBorder extrudes to the outside but also fills the interior
+  // (this is what we need for bold fonts).
+  // In both cases the inner font and outline font (border) will overlap.
+  // Normally this does not matter but it does if alpha blending is active.
+  // In this case if e.g. the inner color is set to white, the outline to red
+  // and alpha to 0.5 the inner part will not be white it will be pink.
+
+  InnerStroker := nil;
+  OuterStroker := nil;
+
+  // If we are to create the interior of an outlined font (fInner = true)
+  // we have to create two borders:
+  // - one extruded to the outside by fOutset pixels and
+  // - one extruded to the inside by almost 0 zero pixels.
+  // The second one is used as a stencil for the first one, clearing the
+  // interiour of the glyph.
+  // The stencil is not needed to create bold fonts.
+  UseStencil := (fFont.Part = fpInner);
+
+  // we cannot extrude bitmaps, only vector based glyphs.
+  // Check for FT_GLYPH_FORMAT_OUTLINE otherwise a cast to FT_OutlineGlyph is
+  // invalid and FT_Stroker_ParseOutline() will crash
+  if (Glyph.format <> FT_GLYPH_FORMAT_OUTLINE) then
+    Exit;
+
+  Outline := @FT_OutlineGlyph(Glyph).outline;
+  
+  OuterBorder := FT_Outline_GetOutsideBorder(Outline);
+  if (OuterBorder = FT_STROKER_BORDER_LEFT) then
+    InnerBorder := FT_STROKER_BORDER_RIGHT
+  else
+    InnerBorder := FT_STROKER_BORDER_LEFT;
+
+  { extrude outer border }
+
+  if (FT_Stroker_New(Glyph.library_, OuterStroker) <> 0) then
+    raise EFontError.Create('FT_Stroker_New failed!');
+  FT_Stroker_Set(
+      OuterStroker,
+      Round(fOutset * 64),
+      FT_STROKER_LINECAP_ROUND,
+      FT_STROKER_LINEJOIN_BEVEL,
+      0);
+
+  // similar to FT_Glyph_StrokeBorder(inner = FT_FALSE) but it is possible to
+  // use FT_Stroker_ExportBorder() afterwards to combine inner and outer borders
+  if (FT_Stroker_ParseOutline(OuterStroker, Outline, FT_FALSE) <> 0) then
+    raise EFontError.Create('FT_Stroker_ParseOutline failed!');
+
+  FT_Stroker_GetBorderCounts(OuterStroker, OuterBorder, OuterNumPoints, OuterNumContours);
+
+  { extrude inner border (= stencil) }
+
+  if (UseStencil) then
+  begin
+    if (FT_Stroker_New(Glyph.library_, InnerStroker) <> 0) then
+      raise EFontError.Create('FT_Stroker_New failed!');
+    FT_Stroker_Set(
+        InnerStroker,
+        63, // extrude at most one pixel to avoid a black border
+        FT_STROKER_LINECAP_ROUND,
+        FT_STROKER_LINEJOIN_BEVEL,
+        0);
+
+    if (FT_Stroker_ParseOutline(InnerStroker, Outline, FT_FALSE) <> 0) then
+      raise EFontError.Create('FT_Stroker_ParseOutline failed!');
+
+    FT_Stroker_GetBorderCounts(InnerStroker, InnerBorder, InnerNumPoints, InnerNumContours);
+  end else begin
+    InnerNumPoints := 0;
+    InnerNumContours := 0;
+  end;
+
+  { combine borders (subtract: OuterBorder - InnerBorder) }
+
+  GlyphNumPoints := InnerNumPoints + OuterNumPoints;
+  GlyphNumContours := InnerNumContours + OuterNumContours;
+
+  // save flags before deletion (TODO: set them on the resulting outline)
+  OutlineFlags := Outline.flags;
+
+  // resize glyph outline to hold inner and outer border
+  FT_Outline_Done(Glyph.Library_, Outline);
+  if (FT_Outline_New(Glyph.Library_, GlyphNumPoints, GlyphNumContours, Outline) <> 0) then
+    raise EFontError.Create('FT_Outline_New failed!');
+
+  Outline.n_points := 0;
+  Outline.n_contours := 0;
+
+  // add points to outline. The inner-border is used as a stencil.
+  FT_Stroker_ExportBorder(OuterStroker, OuterBorder, Outline);
+  if (UseStencil) then
+    FT_Stroker_ExportBorder(InnerStroker, InnerBorder, Outline);
+  if (FT_Outline_Check(outline) <> 0) then
+    raise EFontError.Create('FT_Stroker_ExportBorder failed!');
+
+  if (InnerStroker <> nil) then
+    FT_Stroker_Done(InnerStroker);
+  if (OuterStroker <> nil) then
+    FT_Stroker_Done(OuterStroker);
+end;
+
+procedure TFTGlyph.CreateTexture(LoadFlags: FT_Int32);
+var
+  X, Y:          integer;
+  Glyph:         FT_Glyph;
+  BitmapGlyph:   FT_BitmapGlyph;
+  Bitmap:        PFT_Bitmap;
+  BitmapLine:    PByteArray;
+  BitmapBuffer:  PByteArray;
+  TexBuffer:     TGLubyteDynArray;
+  TexLine:       PGLubyteArray;
+  CBox:          FT_BBox;
+begin
+  // we need vector data for outlined glyphs so do not load bitmaps.
+  // This is necessary for mixed fonts that contain bitmap versions of smaller
+  // glyphs, for example in CJK fonts.
+  if (fOutset > 0) then
+    LoadFlags := LoadFlags or FT_LOAD_NO_BITMAP;
+
+  // load the Glyph for our character
+  if (FT_Load_Glyph(fFace.Data, fCharIndex, LoadFlags) <> 0) then
+    raise EFontError.Create('FT_Load_Glyph failed');
+
+  // move the face's glyph into a Glyph object
+  if (FT_Get_Glyph(fFace.Data^.glyph, Glyph) <> 0) then
+    raise EFontError.Create('FT_Get_Glyph failed');
+
+  if (fOutset > 0) then
+    StrokeBorder(Glyph);
+
+  // store scaled advance width/height in glyph-object
+  fAdvance.X := fFace.Data^.glyph^.advance.x / 64 + fOutset*2;
+  fAdvance.Y := fFace.Data^.glyph^.advance.y / 64 + fOutset*2;
+
+  // get the contour's bounding box (in 1/64th pixels, not font-units)
+  FT_Glyph_Get_CBox(Glyph, FT_GLYPH_BBOX_UNSCALED, CBox);
+  // convert 1/64th values to double values
+  fBounds.Left   := CBox.xMin / 64;
+  fBounds.Right  := CBox.xMax / 64 + fOutset*2;
+  fBounds.Bottom := CBox.yMin / 64;
+  fBounds.Top    := CBox.yMax / 64 + fOutset*2;
+
+  // convert the glyph to a bitmap (and destroy original glyph image).
+  // Request 8 bit gray level pixel mode. 
+  FT_Glyph_To_Bitmap(Glyph, FT_RENDER_MODE_NORMAL, nil, 1);
+  BitmapGlyph := FT_BitmapGlyph(Glyph);
+
+  // get bitmap offsets
+  fBitmapCoords.Left := BitmapGlyph^.left - cTexSmoothBorder;
+  // Note: add 1*fOutset for lifting the baseline so outset fonts to not intersect
+  // with the baseline; Ceil(fOutset) for the outset pixels added to the bitmap.
+  fBitmapCoords.Top  := BitmapGlyph^.top + fOutset+Ceil(fOutset) + cTexSmoothBorder;
+
+  // make accessing the bitmap easier
+  Bitmap := @BitmapGlyph^.bitmap;
+  // get bitmap dimensions
+  fBitmapCoords.Width  := Bitmap.width + (Ceil(fOutset) + cTexSmoothBorder)*2;
+  fBitmapCoords.Height := Bitmap.rows + (Ceil(fOutset) + cTexSmoothBorder)*2;
+
+  // get power-of-2 bitmap widths
+  fTexSize.Width  :=
+      NextPowerOf2(Bitmap.width + (Ceil(fOutset) + cTexSmoothBorder)*2);
+  fTexSize.Height :=
+      NextPowerOf2(Bitmap.rows + (Ceil(fOutset) + cTexSmoothBorder)*2);
+
+  // texture-widths ignoring empty (power-of-2) padding space
+  fTexOffset.X := fBitmapCoords.Width / fTexSize.Width;
+  fTexOffset.Y := fBitmapCoords.Height / fTexSize.Height;
+
+  // allocate memory for texture data
+  SetLength(TexBuffer, fTexSize.Width * fTexSize.Height);
+  FillChar(TexBuffer[0], Length(TexBuffer), 0);
+
+  // Freetype stores the bitmap with either upper (pitch is > 0) or lower
+  // (pitch < 0) glyphs line first. Set the buffer to the upper line.
+  // See http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-7.html
+  if (Bitmap.pitch > 0) then
+    BitmapBuffer := @Bitmap.buffer[0]
+  else
+    BitmapBuffer := @Bitmap.buffer[(Bitmap.rows-1) * Abs(Bitmap.pitch)];
+
+  // copy data to texture bitmap (upper line first).
+  for Y := 0 to Bitmap.rows-1 do
+  begin
+    // set pointer to first pixel in line that holds bitmap data.
+    // Each line starts with a cTexSmoothBorder pixel and multiple outset pixels
+    // that are added by Extrude() later.
+    TexLine := @TexBuffer[(Y + cTexSmoothBorder + Ceil(fOutset)) * fTexSize.Width +
+                          cTexSmoothBorder + Ceil(fOutset)];
+    // get next lower line offset, use pitch instead of width as it tells
+    // us the storage direction of the lines. In addition a line might be padded.
+    BitmapLine := @BitmapBuffer[Y * Bitmap.pitch];
+
+    // check for pixel mode and copy pixels
+    // Should be 8 bit gray, but even with FT_RENDER_MODE_NORMAL, freetype
+    // sometimes (e.g. 16px sized japanese fonts) fallbacks to 1 bit pixels.
+    case (Bitmap.pixel_mode) of
+      FT_PIXEL_MODE_GRAY: begin  // 8 bit gray
+        for X := 0 to Bitmap.width-1 do
+          TexLine[X] := BitmapLine[X];
+      end;
+      FT_PIXEL_MODE_MONO: begin  // 1 bit mono
+        for X := 0 to Bitmap.width-1 do
+          TexLine[X] := High(GLubyte) * ((BitmapLine[X div 8] shr (7-(X mod 8))) and $1);
+      end;
+      else begin
+        // unhandled pixel format
+      end;
+    end;
+  end;
+
+  // allocate resources for textures and display lists
+  glGenTextures(1, @fTexture);
+
+  // setup texture parameters
+  glBindTexture(GL_TEXTURE_2D, fTexture);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  // create alpha-map (GL_ALPHA component only).
+  // TexCoord (0,0) corresponds to the top left pixel of the glyph,
+  // (1,1) to the bottom right pixel. So the glyph is flipped as OpenGL uses
+  // a cartesian (y-axis up) coordinate system for textures.   
+  // See the cTexSmoothBorder comment for info on texture borders.
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, fTexSize.Width, fTexSize.Height,
+      0, GL_ALPHA, GL_UNSIGNED_BYTE, @TexBuffer[0]);
+
+  // free expanded data
+  SetLength(TexBuffer, 0);
+
+  // create the display list
+  fDisplayList := glGenLists(1);
+
+  // render to display-list
+  glNewList(fDisplayList, GL_COMPILE);
+    Render(false);
+  glEndList();
+
+  // free glyph data (bitmap, etc.)
+  FT_Done_Glyph(Glyph);
+end;
+
+constructor TFTGlyph.Create(Font: TFTFont; ch: UCS4Char; Outset: single;
+    LoadFlags: FT_Int32);
+var
+  I: integer;
+begin
+  inherited Create();
+
+  fFont := Font;
+  fOutset := Outset;
+  fCharCode := ch;
+
+  // Note: the default face is also used if no face (neither default nor fallback)
+  // contains a glyph for the given char.
+  fFace := Font.DefaultFace;
+
+  // search the Freetype char-index (use default UNICODE charmap) in the default face
+  fCharIndex := FT_Get_Char_Index(fFace.Data, FT_ULONG(ch));
+  if (fCharIndex = 0) then
+  begin
+    // glyph not in default font, search in fallback font faces
+    for I := 0 to High(Font.FallbackFaces) do
+    begin
+      fCharIndex := FT_Get_Char_Index(Font.FallbackFaces[I].Data, FT_ULONG(ch));
+      if (fCharIndex <> 0) then
+      begin
+        fFace := Font.FallbackFaces[I];
+        Break;
+      end;
+    end;
+  end;
+
+  CreateTexture(LoadFlags);
+end;
+
+destructor TFTGlyph.Destroy;
+begin
+  if (fDisplayList <> 0) then
+    glDeleteLists(fDisplayList, 1);
+  if (fTexture <> 0) then
+    glDeleteTextures(1, @fTexture);
+  inherited;
+end;
+
+procedure TFTGlyph.Render(UseDisplayLists: boolean);
+begin
+  // use display-lists if enabled and exit
+  if (UseDisplayLists) then
+  begin
+    glCallList(fDisplayList);
+    Exit;
+  end;
+
+  glBindTexture(GL_TEXTURE_2D, fTexture);
+  glPushMatrix();
+
+  // move to top left glyph position
+  glTranslatef(fBitmapCoords.Left, fBitmapCoords.Top, 0);
+
+  // draw glyph texture
+  glBegin(GL_QUADS);
+    // top right
+    glTexCoord2f(fTexOffset.X, 0);
+    glVertex2f(fBitmapCoords.Width, 0);
+
+    // top left
+    glTexCoord2f(0, 0);
+    glVertex2f(0, 0);
+
+    // bottom left
+    glTexCoord2f(0, fTexOffset.Y);
+    glVertex2f(0, -fBitmapCoords.Height);
+
+    // bottom right
+    glTexCoord2f(fTexOffset.X, fTexOffset.Y);
+    glVertex2f(fBitmapCoords.Width, -fBitmapCoords.Height);
+  glEnd();
+
+  glPopMatrix();
+end;
+
+procedure TFTGlyph.RenderReflection();
+var
+  Color: TGLColor;
+  TexUpperPos: single;
+  TexLowerPos: single;
+  UpperPos: single;
+const
+  CutOff = 0.6;
+begin
+  glPushMatrix();
+  glBindTexture(GL_TEXTURE_2D, fTexture);
+  glGetFloatv(GL_CURRENT_COLOR, @Color.vals);
+
+  // add extra space to the left of the glyph
+  glTranslatef(fBitmapCoords.Left, 0, 0);
+
+  // The upper position of the glyph, if CutOff is 1.0, it is fFont.Ascender.
+  // If CutOff is set to 0.5 only half of the glyph height is displayed.
+  UpperPos := fFont.Descender + fFont.Height * CutOff;
+
+  // the glyph texture's height is just the height of the glyph but not the font
+  // height. Setting a color for the upper and lower bounds of the glyph results
+  // in different color gradients. So we have to set the color values for the
+  // descender and ascender (as we have a cutoff, for the upper-pos here) as
+  // these positions are font but not glyph specific.
+
+  // To get the texture positions we have to enhance the texture at the top and
+  // bottom by the amount from the top to ascender (rather upper-pos here) and
+  // from the bottom (Height-Top) to descender. Then we have to convert those
+  // heights to texture coordinates by dividing by the bitmap Height and
+  // removing the power-of-2 padding space by multiplying with fTexOffset.Y
+  // (as fBitmapCoords.Height corresponds to fTexOffset.Y and not 1.0).
+  TexUpperPos  := -(UpperPos - fBitmapCoords.Top) / fBitmapCoords.Height * fTexOffset.Y;
+  TexLowerPos := (-(fFont.Descender + fBitmapCoords.Height - fBitmapCoords.Top) /
+                    fBitmapCoords.Height + 1) * fTexOffset.Y;
+
+  // draw glyph texture
+  glBegin(GL_QUADS);
+    // top right
+    glColor4f(Color.r, Color.g, Color.b, 0);
+    glTexCoord2f(fTexOffset.X, TexUpperPos);
+    glVertex2f(fBitmapCoords.Width, UpperPos);
+
+    // top left
+    glTexCoord2f(0, TexUpperPos);
+    glVertex2f(0, UpperPos);
+
+    // bottom left
+    glColor4f(Color.r, Color.g, Color.b, Color.a-0.3);
+    glTexCoord2f(0, TexLowerPos);
+    glVertex2f(0, fFont.Descender);
+
+    // bottom right
+    glTexCoord2f(fTexOffset.X, TexLowerPos);
+    glVertex2f(fBitmapCoords.Width, fFont.Descender);
+  glEnd();
+
+  glPopMatrix();
+
+  // restore old color
+  // Note: glPopAttrib(GL_CURRENT_BIT)/glPopAttrib() is much slower then
+  // glGetFloatv(GL_CURRENT_COLOR, ...)/glColor4fv(...)
+  glColor4fv(@Color.vals);
+end;
+
+function TFTGlyph.GetAdvance(): TPositionDbl;
+begin
+  Result := fAdvance;
+end;
+
+function TFTGlyph.GetBounds(): TBoundsDbl;
+begin
+  Result := fBounds;
+end;
+
+
+{*
+ * TGlyphCache
+ *}
+
+constructor TGlyphCache.Create();
+begin
+  inherited;
+  fHash := TList.Create();
+end;
+
+destructor TGlyphCache.Destroy();
+begin
+  // free cached glyphs
+  FlushCache(false);
+
+  // destroy TList
+  fHash.Free;
+  
+  inherited;
+end;
+
+function TGlyphCache.FindGlyphTable(BaseCode: cardinal; out InsertPos: integer): PGlyphTable;
+var
+  I: integer;
+  Entry: TGlyphCacheHashEntry;
+begin
+  Result := nil;
+
+  for I := 0 to fHash.Count-1 do
+  begin
+    Entry := TGlyphCacheHashEntry(fHash[I]);
+
+    if (Entry.BaseCode > BaseCode) then
+    begin
+      InsertPos := I;
+      Exit;
+    end;
+
+    if (Entry.BaseCode = BaseCode) then
+    begin
+      InsertPos := I;
+      Result := @Entry.GlyphTable;
+      Exit;
+    end;
+  end;
+
+  InsertPos := fHash.Count;
+end;
+
+function TGlyphCache.AddGlyph(ch: UCS4Char; const Glyph: TGlyph): boolean;
+var
+  BaseCode:  cardinal;
+  GlyphCode: integer;
+  InsertPos: integer;
+  GlyphTable: PGlyphTable;
+  Entry: TGlyphCacheHashEntry;
+begin
+  Result := false;
+
+  BaseCode := Ord(ch) shr 8;
+  GlyphTable := FindGlyphTable(BaseCode, InsertPos);
+  if (GlyphTable = nil) then
+  begin
+    Entry := TGlyphCacheHashEntry.Create(BaseCode);
+    GlyphTable := @Entry.GlyphTable;
+    fHash.Insert(InsertPos, Entry);
+  end;
+
+  // get glyph table offset
+  GlyphCode := Ord(ch) and $FF;
+  // insert glyph into table if not present
+  if (GlyphTable[GlyphCode] = nil) then
+  begin
+    GlyphTable[GlyphCode] := Glyph;
+    Result := true;
+  end;
+end;
+
+procedure TGlyphCache.DeleteGlyph(ch: UCS4Char);
+var
+  Table: PGlyphTable;
+  TableIndex, GlyphIndex: integer;
+  TableEmpty: boolean;
+begin
+  // find table
+  Table := FindGlyphTable(Ord(ch) shr 8, TableIndex);
+  if (Table = nil) then
+    Exit;
+
+  // find glyph    
+  GlyphIndex := Ord(ch) and $FF;
+  if (Table[GlyphIndex] <> nil) then
+  begin
+    // destroy glyph
+    FreeAndNil(Table[GlyphIndex]);
+
+    // check if table is empty
+    TableEmpty := true;
+    for GlyphIndex := 0 to High(Table^) do
+    begin
+      if (Table[GlyphIndex] <> nil) then
+      begin
+        TableEmpty := false;
+        Break;
+      end;
+    end;
+
+    // free empty table
+    if (TableEmpty) then
+    begin
+      fHash.Delete(TableIndex);
+    end;
+  end;
+end;
+
+function TGlyphCache.GetGlyph(ch: UCS4Char): TGlyph;
+var
+  InsertPos: integer;
+  Table: PGlyphTable;
+begin
+  Table := FindGlyphTable(Ord(ch) shr 8, InsertPos);
+  if (Table = nil) then
+    Result := nil
+  else
+    Result := Table[Ord(ch) and $FF];
+end;
+
+function TGlyphCache.HasGlyph(ch: UCS4Char): boolean;
+begin
+  Result := (GetGlyph(ch) <> nil);
+end;
+
+procedure TGlyphCache.FlushCache(KeepBaseSet: boolean);
+var
+  EntryIndex, TableIndex: integer;
+  Entry: TGlyphCacheHashEntry;
+begin
+  // destroy cached glyphs
+  for EntryIndex := 0 to fHash.Count-1 do
+  begin
+    Entry := TGlyphCacheHashEntry(fHash[EntryIndex]);
+
+    // the base set (0-255) has BaseCode 0 as the upper bytes are 0.
+    if KeepBaseSet and (Entry.fBaseCode = 0) then
+      Continue;
+
+    for TableIndex := 0 to High(Entry.GlyphTable) do
+    begin
+      if (Entry.GlyphTable[TableIndex] <> nil) then
+        FreeAndNil(Entry.GlyphTable[TableIndex]);
+    end;
+    FreeAndNil(Entry);
+  end;
+end;
+
+
+{*
+ * TGlyphCacheEntry
+ *}
+
+constructor TGlyphCacheHashEntry.Create(BaseCode: cardinal);
+begin
+  inherited Create();
+  fBaseCode := BaseCode;
+end;
+
+
+{*
+ * TFreeType
+ *}
+
+class function TFreeType.GetLibrary(): FT_Library;
+begin
+  if (LibraryInst = nil) then
+  begin
+    // initialize freetype
+    if (FT_Init_FreeType(LibraryInst) <> 0) then
+      raise EFontError.Create('FT_Init_FreeType failed');
+  end;
+  Result := LibraryInst;
+end;
+
+class procedure TFreeType.FreeLibrary();
+begin
+  if (LibraryInst <> nil) then
+    FT_Done_FreeType(LibraryInst);
+  LibraryInst := nil;
+end;
+
+
+{$IFDEF BITMAP_FONT}
+{*
+ * TBitmapFont
+ *}
+
+constructor TBitmapFont.Create(const Filename: IPath; Outline: integer;
+    Baseline, Ascender, Descender: integer);
+begin
+  inherited Create(Filename);
+
+  fTex := Texture.LoadTexture(true, Filename, TEXTURE_TYPE_TRANSPARENT, 0);
+  fTexSize := 1024;
+  fOutline := Outline;
+  fBaseline  := Baseline;
+  fAscender  := Ascender;
+  fDescender := Descender;
+
+  LoadFontInfo(Filename.SetExtension('.dat'));
+
+  ResetIntern();
+end;
+
+destructor TBitmapFont.Destroy();
+begin
+  glDeleteTextures(1, @fTex.TexNum);
+  inherited;
+end;
+
+procedure TBitmapFont.ResetIntern();
+begin
+  fLineSpacing := Height;
+end;
+
+procedure TBitmapFont.Reset();
+begin
+  inherited;
+  ResetIntern();
+end;
+
+procedure TBitmapFont.AddFallback(const Filename: IPath);
+begin
+  // no support for fallbacks
+end;
+
+procedure TBitmapFont.CorrectWidths(WidthMult: real; WidthAdd: integer);
+var
+  Count: integer;
+begin
+  for Count := 0 to 255 do
+    fWidths[Count] := Round(fWidths[Count] * WidthMult) + WidthAdd;
+end;
+
+procedure TBitmapFont.LoadFontInfo(const InfoFile: IPath);
+var
+  Stream: TStream;
+begin
+  FillChar(fWidths[0], Length(fWidths), 0);
+
+  Stream := nil;
+  try
+    Stream := TBinaryFileStream.Create(InfoFile, fmOpenRead);
+    Stream.Read(fWidths, 256);
+  except
+    raise EFontError.Create('Could not read font info file ''' +  InfoFile.ToNative + '''');
+  end;
+  Stream.Free;
+end;
+
+function TBitmapFont.BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl;
+var
+  LineIndex, CharIndex: integer;
+  CharCode: cardinal;
+  Line: UCS4String;
+  LineWidth: double;
+begin
+  Result.Left := 0;
+  Result.Right := 0;
+  Result.Top := Height;
+  Result.Bottom := 0;
+
+  for LineIndex := 0 to High(Text) do
+  begin
+    Line := Text[LineIndex];
+    LineWidth := 0;
+    for CharIndex := 0 to LengthUCS4(Line)-1 do
+    begin
+      CharCode := Ord(Line[CharIndex]);
+      if (CharCode < Length(fWidths)) then
+        LineWidth := LineWidth + fWidths[CharCode];
+    end;
+    if (LineWidth > Result.Right) then
+      Result.Right := LineWidth;
+  end;
+end;
+
+procedure TBitmapFont.RenderChar(ch: UCS4Char; var AdvanceX: real);
+var
+  TexX, TexY:        real;
+  TexR, TexB:        real;
+  GlyphWidth:        real;
+  PL, PT:            real;
+  PR, PB:            real;
+  CharCode:          cardinal;
+begin
+  CharCode := Ord(ch);
+  if (CharCode > High(fWidths)) then
+    CharCode := 0;
+
+  GlyphWidth := fWidths[CharCode];
+
+  // set texture positions
+  TexX := (CharCode mod 16) * 1/16 + 1/32 - (GlyphWidth/2 - fOutline)/fTexSize;
+  TexY := (CharCode div 16) * 1/16 + {2 texels} 2/fTexSize;
+  TexR := (CharCode mod 16) * 1/16 + 1/32 + (GlyphWidth/2 + fOutline)/fTexSize;
+  TexB := (1 + CharCode div 16) * 1/16 - {2 texels} 2/fTexSize;
+
+  // set vector positions
+  PL := AdvanceX - fOutline;
+  PR := PL + GlyphWidth + fOutline*2;
+  PB := -fBaseline;
+  PT := PB + fTexSize div 16;
+
+  (*
+  if (Font.Blend) then
+  begin
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  end;
+  *)
+
+  glEnable(GL_TEXTURE_2D);
+  glBindTexture(GL_TEXTURE_2D, fTex.TexNum);
+  
+  if (not ReflectionPass) then
+  begin
+    glBegin(GL_QUADS);
+      glTexCoord2f(TexX, TexY); glVertex2f(PL, PT);
+      glTexCoord2f(TexX, TexB); glVertex2f(PL, PB);
+      glTexCoord2f(TexR, TexB); glVertex2f(PR, PB);
+      glTexCoord2f(TexR, TexY); glVertex2f(PR, PT);
+    glEnd;
+  end
+  else
+  begin
+    glDepthRange(0, 10);
+    glDepthFunc(GL_LEQUAL);
+    glEnable(GL_DEPTH_TEST);
+
+    glBegin(GL_QUADS);
+      glTexCoord2f(TexX, TexY); glVertex2f(PL, PT);
+      glTexCoord2f(TexX, TexB); glVertex2f(PL, PB);
+      glTexCoord2f(TexR, TexB); glVertex2f(PR, PB);
+      glTexCoord2f(TexR, TexY); glVertex2f(PR, PT);
+    glEnd;
+
+    glBegin(GL_QUADS);
+      glTexCoord2f(TexX, TexY); glVertex2f(PL, PT);
+      glTexCoord2f(TexX, TexB); glVertex2f(PL, PB);
+      glTexCoord2f(TexR, TexB); glVertex2f(PR, PB);
+      glTexCoord2f(TexR, TexY); glVertex2f(PR, PT);
+
+(*
+      glColor4f(fTempColor.r, fTempColor.g, fTempColor.b, 0.7);
+      glTexCoord2f(TexX, TexB); glVertex3f(PL, PB, 0);
+      glTexCoord2f(TexR, TexB); glVertex3f(PR, PB, 0);
+
+      glColor4f(fTempColor.r, fTempColor.g, fTempColor.b, 0);
+      glTexCoord2f(TexR, (TexY + TexB)/2); glVertex3f(PR, (PT + PB)/2, 0);
+      glTexCoord2f(TexX, (TexY + TexB)/2); glVertex3f(PL, (PT + PB)/2, 0);
+*)
+    glEnd;
+
+    //write the colour back
+    glColor4fv(@fTempColor);
+
+    glDisable(GL_DEPTH_TEST);
+  end; // reflection
+
+  glDisable(GL_TEXTURE_2D);
+  (*
+  if (Font.Blend) then
+    glDisable(GL_BLEND);
+  *)
+
+  AdvanceX := AdvanceX + GlyphWidth;
+end;
+
+procedure TBitmapFont.Render(const Text: UCS4String);
+var
+  CharIndex: integer;
+  AdvanceX: real;
+begin
+  // if there is no text do nothing
+  if (Text = nil) or (Text[0] = 0) then
+    Exit;
+
+  //Save the current color and alpha (for reflection)
+  glGetFloatv(GL_CURRENT_COLOR, @fTempColor);
+
+  AdvanceX := 0;
+  for CharIndex := 0 to LengthUCS4(Text)-1 do
+  begin
+    RenderChar(Text[CharIndex], AdvanceX);
+  end;
+end;
+
+function TBitmapFont.GetHeight(): single;
+begin
+  Result := fAscender - fDescender;
+end;
+
+function TBitmapFont.GetAscender(): single;
+begin
+  Result := fAscender;
+end;
+
+function TBitmapFont.GetDescender(): single;
+begin
+  Result := fDescender;
+end;
+
+function TBitmapFont.GetUnderlinePosition(): single;
+begin
+  Result := -2.0;
+end;
+
+function TBitmapFont.GetUnderlineThickness(): single;
+begin
+  Result := 1.0;
+end;
+
+{$ENDIF BITMAP_FONT}
+
+
+initialization
+
+finalization
+  TFreeType.FreeLibrary();
+
+end.
diff --git a/songmanagement/src/base/UGraphic.pas b/songmanagement/src/base/UGraphic.pas
new file mode 100644
index 00000000..4f0c8c77
--- /dev/null
+++ b/songmanagement/src/base/UGraphic.pas
@@ -0,0 +1,852 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UGraphic;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  gl,
+  glext,
+  UTexture,
+  TextGL,
+  ULog,
+  SysUtils,
+  ULyrics,
+  UImage,
+  UMusic,
+  UScreenLoading,
+  UScreenMain,
+  UScreenName,
+  UScreenLevel,
+  UScreenOptions,
+  UScreenOptionsGame,
+  UScreenOptionsGraphics,
+  UScreenOptionsSound,
+  UScreenOptionsLyrics,
+  UScreenOptionsThemes,
+  UScreenOptionsRecord,
+  UScreenOptionsAdvanced,
+  UScreenSong,
+  UScreenSing,
+  UScreenScore,
+  UScreenTop5,
+  UScreenEditSub,
+  UScreenEdit,
+  UScreenEditConvert,
+  UScreenEditHeader,
+  UScreenOpen,
+  UThemes,
+  USkins,
+  UScreenSongMenu,
+  UScreenSongJumpto,
+  {Party Screens}
+  UScreenPartyNewRound,
+  UScreenPartyScore,
+  UScreenPartyOptions,
+  UScreenPartyWin,
+  UScreenPartyPlayer,
+  UScreenPartyRounds,
+  {Stats Screens}
+  UScreenStatMain,
+  UScreenStatDetail,
+  {CreditsScreen}
+  UScreenCredits,
+  {Popup for errors, etc.}
+  UScreenPopup;
+
+type
+  TRecR = record
+    Top:    real;
+    Left:   real;
+    Right:  real;
+    Bottom: real;
+  end;
+
+var
+  Screen:         PSDL_Surface;
+  LoadingThread:  PSDL_Thread;
+  Mutex:          PSDL_Mutex;
+
+  RenderW:    integer;
+  RenderH:    integer;
+  ScreenW:    integer;
+  ScreenH:    integer;
+  Screens:    integer;
+  ScreenAct:  integer;
+  ScreenX:    integer;
+
+  ScreenLoading:      TScreenLoading;
+  ScreenMain:         TScreenMain;
+  ScreenName:         TScreenName;
+  ScreenLevel:        TScreenLevel;
+  ScreenSong:         TScreenSong;
+  ScreenSing:         TScreenSing;
+  ScreenScore:        TScreenScore;
+  ScreenTop5:         TScreenTop5;
+  ScreenOptions:          TScreenOptions;
+  ScreenOptionsGame:      TScreenOptionsGame;
+  ScreenOptionsGraphics:  TScreenOptionsGraphics;
+  ScreenOptionsSound:     TScreenOptionsSound;
+  ScreenOptionsLyrics:    TScreenOptionsLyrics;
+  ScreenOptionsThemes:    TScreenOptionsThemes;
+  ScreenOptionsRecord:    TScreenOptionsRecord;
+  ScreenOptionsAdvanced:  TScreenOptionsAdvanced;
+  ScreenEditSub:      TScreenEditSub;
+  ScreenEdit:         TScreenEdit;
+  ScreenEditConvert:  TScreenEditConvert;
+  ScreenEditHeader:   TScreenEditHeader;
+  ScreenOpen:         TScreenOpen;
+
+  ScreenSongMenu:     TScreenSongMenu;
+  ScreenSongJumpto:     TScreenSongJumpto;
+
+  //Party Screens
+  //ScreenSingModi:         TScreenSingModi;
+  ScreenPartyNewRound:    TScreenPartyNewRound;
+  ScreenPartyScore:       TScreenPartyScore;
+  ScreenPartyWin:         TScreenPartyWin;
+  ScreenPartyOptions:     TScreenPartyOptions;
+  ScreenPartyPlayer:      TScreenPartyPlayer;
+  ScreenPartyRounds:      TScreenPartyRounds;
+
+  //StatsScreens
+  ScreenStatMain:         TScreenStatMain;
+  ScreenStatDetail:       TScreenStatDetail;
+
+  //CreditsScreen
+  ScreenCredits: TScreenCredits;
+
+  //popup mod
+  ScreenPopupCheck: TScreenPopupCheck;
+  ScreenPopupError: TScreenPopupError;
+  ScreenPopupInfo:  TScreenPopupInfo;
+
+  //Notes
+  Tex_Left:        array[1..6] of TTexture;   //rename to tex_note_left
+  Tex_Mid:         array[1..6] of TTexture;   //rename to tex_note_mid
+  Tex_Right:       array[1..6] of TTexture;   //rename to tex_note_right
+
+  Tex_plain_Left:  array[1..6] of TTexture;   //rename to tex_notebg_left
+  Tex_plain_Mid:   array[1..6] of TTexture;   //rename to tex_notebg_mid
+  Tex_plain_Right: array[1..6] of TTexture;   //rename to tex_notebg_right
+
+  Tex_BG_Left:     array[1..6] of TTexture;   //rename to tex_noteglow_left
+  Tex_BG_Mid:      array[1..6] of TTexture;   //rename to tex_noteglow_mid
+  Tex_BG_Right:    array[1..6] of TTexture;   //rename to tex_noteglow_right
+
+  Tex_Note_Star:  TTexture;
+  Tex_Note_Perfect_Star: TTexture;
+
+
+  Tex_Ball:       TTexture;
+  Tex_Lyric_Help_Bar: TTexture;
+  FullScreen:     boolean;
+
+  Tex_TimeProgress: TTexture;
+
+  //Sing Bar Mod
+  Tex_SingBar_Back:  TTexture;
+  Tex_SingBar_Bar:  TTexture;
+  Tex_SingBar_Front:  TTexture;
+  //end Singbar Mod
+
+  //PhrasenBonus - Line Bonus Mod
+  Tex_SingLineBonusBack: array[0..8] of TTexture;
+  //End PhrasenBonus - Line Bonus Mod
+
+  //ScoreBG Texs
+  Tex_ScoreBG: array [0..5] of TTexture;
+
+  //Score Screen Textures
+    Tex_Score_NoteBarLevel_Dark     : array [1..6] of TTexture;
+    Tex_Score_NoteBarRound_Dark     : array [1..6] of TTexture;
+
+    Tex_Score_NoteBarLevel_Light    : array [1..6] of TTexture;
+    Tex_Score_NoteBarRound_Light    : array [1..6] of TTexture;
+
+    Tex_Score_NoteBarLevel_Lightest : array [1..6] of TTexture;
+    Tex_Score_NoteBarRound_Lightest : array [1..6] of TTexture;
+
+    Tex_Score_Ratings               : array [0..7] of TTexture;
+
+  // arrows for SelectSlide
+    Tex_SelectS_ArrowL:  TTexture;
+    Tex_SelectS_ArrowR:  TTexture;
+
+  // textures for software mouse cursor
+    Tex_Cursor_Unpressed: TTexture;
+    Tex_Cursor_Pressed:   TTexture;
+
+
+  PboSupported: boolean;
+
+const
+  Skin_BGColorR = 1;
+  Skin_BGColorG = 1;
+  Skin_BGColorB = 1;
+
+  Skin_SpectrumR = 0;
+  Skin_SpectrumG = 0;
+  Skin_SpectrumB = 0;
+
+  Skin_Spectograph1R = 0.6;
+  Skin_Spectograph1G = 0.8;
+  Skin_Spectograph1B = 1;
+
+  Skin_Spectograph2R = 0;
+  Skin_Spectograph2G = 0;
+  Skin_Spectograph2B = 0.2;
+
+  Skin_FontR = 0;
+  Skin_FontG = 0;
+  Skin_FontB = 0;
+
+  Skin_FontHighlightR = 0.3; // 0.3
+  Skin_FontHighlightG = 0.3; // 0.3
+  Skin_FontHighlightB = 1;   // 1
+
+  Skin_TimeR = 0.25; //0,0,0
+  Skin_TimeG = 0.25;
+  Skin_TimeB = 0.25;
+
+  Skin_OscR = 0;
+  Skin_OscG = 0;
+  Skin_OscB = 0;
+
+  Skin_SpectrumT = 470;
+  Skin_SpectrumBot = 570;
+  Skin_SpectrumH = 100;
+
+  Skin_P1_LinesR = 0.5;  // 0.6 0.6 1
+  Skin_P1_LinesG = 0.5;
+  Skin_P1_LinesB = 0.5;
+
+  Skin_P2_LinesR = 0.5; // 1 0.6 0.6
+  Skin_P2_LinesG = 0.5;
+  Skin_P2_LinesB = 0.5;
+
+  Skin_P1_NotesB = 250;
+  Skin_P2_NotesB = 430; // 430 / 300
+
+  Skin_P1_ScoreT = 50;
+  Skin_P1_ScoreL = 20;
+
+  Skin_P2_ScoreT = 50;
+  Skin_P2_ScoreL = 640;
+
+procedure Initialize3D (Title: string);
+procedure Finalize3D;
+procedure Reinitialize3D;
+procedure SwapBuffers;
+
+procedure LoadTextures;
+procedure InitializeScreen;
+procedure LoadLoadingScreen;
+procedure LoadScreens;
+procedure UnloadScreens;
+
+function LoadingThreadFunction: integer;
+
+
+implementation
+
+uses
+  Classes,
+  UMain,
+  UIni,
+  UDisplay,
+  UCommandLine,
+  UPathUtils;
+
+procedure LoadFontTextures;
+begin
+  Log.LogStatus('Building Fonts', 'LoadTextures');
+  BuildFonts;
+end;
+
+procedure UnloadFontTextures;
+begin
+  Log.LogStatus('Kill Fonts', 'UnloadFontTextures');
+  KillFonts;
+end;
+
+procedure LoadTextures;
+
+var
+  P:       integer;
+  R, G, B: real;
+  Col:     integer;
+begin
+  Log.LogStatus('Loading Textures', 'LoadTextures');
+
+  // P1-6
+  // TODO... do it once for each player... this is a bit crappy !!
+  //                                       can we make it any better !?
+  for P := 1 to 6 do
+  begin
+    LoadColor(R, G, B, 'P' + IntToStr(P) + 'Light');
+    Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
+
+    { some colors for tests
+	Col := $10000 * Round(0.02*255) + $100 * Round(0.6 *255) + Round(0.8 *255); //blue
+	Col := $10000 * Round(0.8 *255)                                           ; //red
+	Col :=                            $100 * Round(0.85*255)                  ; //green
+	Col := $10000 * 255             + $100 * Round(0.52*255)                  ; //orange
+	Col := $10000 *            255  + $100 *            255                   ; //yellow
+	Col := $10000 * Round(0.82*255) +                   255                   ; //purple
+	Col := $10000 * Round(0.22*255) + $100 * Round(0.39*255) + Round(0.64*255); //dark blue
+	Col := $10000 * Round(0   *255) + $100 * Round(0   *255) + Round(0   *255); //black
+	Col := $10000 * Round(1.0 *255) + $100 * Round(0.43*255) + Round(0.70*255); //pink
+	Col := 0;       //black
+	Col := $FFFFFF; //white
+	Col := $FF0000; //red
+	Col := $00FF00; //green
+	Col := $002200; //light green
+	Col := $002222; //light greenblue
+	Col := $222200; //light yellow
+	Col := $340000; //red
+	Col := $FF6EB4; //pink
+	Col := $333333; //grey
+    }
+
+    Tex_Left[P]         := Texture.LoadTexture(Skin.GetTextureFileName('GrayLeft'),  TEXTURE_TYPE_COLORIZED, Col);
+    Tex_Mid[P]          := Texture.LoadTexture(Skin.GetTextureFileName('GrayMid'),   TEXTURE_TYPE_COLORIZED, Col);
+    Tex_Right[P]        := Texture.LoadTexture(Skin.GetTextureFileName('GrayRight'), TEXTURE_TYPE_COLORIZED, Col);
+
+    Tex_plain_Left[P]   := Texture.LoadTexture(Skin.GetTextureFileName('NotePlainLeft'),  TEXTURE_TYPE_COLORIZED, Col);
+    Tex_plain_Mid[P]    := Texture.LoadTexture(Skin.GetTextureFileName('NotePlainMid'),   TEXTURE_TYPE_COLORIZED, Col);
+    Tex_plain_Right[P]  := Texture.LoadTexture(Skin.GetTextureFileName('NotePlainRight'), TEXTURE_TYPE_COLORIZED, Col);
+
+    Tex_BG_Left[P]      := Texture.LoadTexture(Skin.GetTextureFileName('NoteBGLeft'),  TEXTURE_TYPE_COLORIZED, Col);
+    Tex_BG_Mid[P]       := Texture.LoadTexture(Skin.GetTextureFileName('NoteBGMid'),   TEXTURE_TYPE_COLORIZED, Col);
+    Tex_BG_Right[P]     := Texture.LoadTexture(Skin.GetTextureFileName('NoteBGRight'), TEXTURE_TYPE_COLORIZED, Col);
+  end;
+
+  Log.LogStatus('Loading Textures - B', 'LoadTextures');
+
+  Tex_Note_Perfect_Star := Texture.LoadTexture(Skin.GetTextureFileName('NotePerfectStar'), TEXTURE_TYPE_TRANSPARENT, 0);
+  Tex_Note_Star         := Texture.LoadTexture(Skin.GetTextureFileName('NoteStar') ,       TEXTURE_TYPE_TRANSPARENT, $FFFFFF);
+  Tex_Ball              := Texture.LoadTexture(Skin.GetTextureFileName('Ball'),            TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  Tex_Lyric_Help_Bar    := Texture.LoadTexture(Skin.GetTextureFileName('LyricHelpBar'),    TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+
+  Tex_SelectS_ArrowL    := Texture.LoadTexture(Skin.GetTextureFileName('Select_ArrowLeft'),    TEXTURE_TYPE_TRANSPARENT, 0);
+  Tex_SelectS_ArrowR    := Texture.LoadTexture(Skin.GetTextureFileName('Select_ArrowRight'),    TEXTURE_TYPE_TRANSPARENT, 0);
+
+  Tex_Cursor_Unpressed  := Texture.LoadTexture(Skin.GetTextureFileName('Cursor'), TEXTURE_TYPE_TRANSPARENT, 0);
+
+  if (Skin.GetTextureFileName('Cursor_Pressed').IsSet) then
+    Tex_Cursor_Pressed    := Texture.LoadTexture(Skin.GetTextureFileName('Cursor_Pressed'), TEXTURE_TYPE_TRANSPARENT, 0)
+  else
+    Tex_Cursor_Pressed.TexNum := 0;
+
+  //TimeBar mod
+  Tex_TimeProgress := Texture.LoadTexture(Skin.GetTextureFileName('TimeBar'));
+  //eoa TimeBar mod
+
+  //SingBar Mod
+  Tex_SingBar_Back  := Texture.LoadTexture(Skin.GetTextureFileName('SingBarBack'),  TEXTURE_TYPE_PLAIN, 0);
+  Tex_SingBar_Bar   := Texture.LoadTexture(Skin.GetTextureFileName('SingBarBar'),   TEXTURE_TYPE_PLAIN, 0);
+  Tex_SingBar_Front := Texture.LoadTexture(Skin.GetTextureFileName('SingBarFront'), TEXTURE_TYPE_PLAIN, 0);
+  //end Singbar Mod
+
+  Log.LogStatus('Loading Textures - C', 'LoadTextures');
+
+  //Line Bonus PopUp
+  for P := 0 to 8 do
+    begin
+      Case P of
+        0: begin
+          R := 1;
+          G := 0;
+          B := 0;
+        end;
+        1..3: begin
+          R := 1;
+          G := (P * 0.25);
+          B := 0;
+        end;
+        4: begin
+          R := 1;
+          G := 1;
+          B := 0;
+        end;
+        5..7: begin
+          R := 1-((P-4)*0.25);
+          G := 1;
+          B := 0;
+        end;
+        8: begin
+          R := 0;
+          G := 1;
+          B := 0;
+        end;
+      End;
+
+      Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
+      Tex_SingLineBonusBack[P] :=  Texture.LoadTexture(Skin.GetTextureFileName('LineBonusBack'), TEXTURE_TYPE_COLORIZED, Col);
+    end;
+
+//## backgrounds for the scores ##
+  for P := 0 to 5 do begin
+    LoadColor(R, G, B, 'P' + IntToStr(P+1) + 'Light');
+    Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
+    Tex_ScoreBG[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreBG'), TEXTURE_TYPE_COLORIZED, Col);
+  end;
+
+
+  Log.LogStatus('Loading Textures - D', 'LoadTextures');
+
+// ######################
+// Score screen textures
+// ######################
+
+//## the bars that visualize the score ##
+  for P := 1 to 6 do begin
+//NoteBar ScoreBar
+    LoadColor(R, G, B, 'P' + IntToStr(P) + 'Dark');
+    Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
+    Tex_Score_NoteBarLevel_Dark[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Dark'), TEXTURE_TYPE_COLORIZED, Col);
+    Tex_Score_NoteBarRound_Dark[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Dark_Round'), TEXTURE_TYPE_COLORIZED, Col);
+//LineBonus ScoreBar
+    LoadColor(R, G, B, 'P' + IntToStr(P) + 'Light');
+    Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
+    Tex_Score_NoteBarLevel_Light[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Light'), TEXTURE_TYPE_COLORIZED, Col);
+    Tex_Score_NoteBarRound_Light[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Light_Round'), TEXTURE_TYPE_COLORIZED, Col);
+//GoldenNotes ScoreBar
+    LoadColor(R, G, B, 'P' + IntToStr(P) + 'Lightest');
+    Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
+    Tex_Score_NoteBarLevel_Lightest[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Lightest'), TEXTURE_TYPE_COLORIZED, Col);
+    Tex_Score_NoteBarRound_Lightest[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Lightest_Round'), TEXTURE_TYPE_COLORIZED, Col);
+  end;
+
+//## rating pictures that show a picture according to your rate ##
+    for P := 0 to 7 do begin
+    Tex_Score_Ratings[P] := Texture.LoadTexture(Skin.GetTextureFileName('Rating_'+IntToStr(P)), TEXTURE_TYPE_TRANSPARENT, 0);
+  end;
+
+  Log.LogStatus('Loading Textures - Done', 'LoadTextures');
+end;
+
+(*
+ * Load OpenGL extensions. Must be called after SDL_SetVideoMode() and each
+ * time the pixel-format or render-context (RC) changes.
+ *)
+procedure LoadOpenGLExtensions;
+begin
+  // Load OpenGL 1.2 extensions for OpenGL 1.2 compatibility
+  if (not Load_GL_version_1_2()) then
+  begin
+    Log.LogCritical('Failed loading OpenGL 1.2', 'UGraphic.Initialize3D');
+  end;
+
+  // Other extensions e.g. OpenGL 1.3-2.0 or Framebuffer-Object might be loaded here
+  // ...
+  //Load_GL_EXT_framebuffer_object();
+
+  // PBO functions are loaded with VBO
+  //PboSupported := Load_GL_ARB_pixel_buffer_object()
+  //    and Load_GL_ARB_vertex_buffer_object();
+  //Log.LogWarn('PBOSupported: ' + BoolToStr(PboSupported, true), 'LoadOpenGLExtensions');
+  PboSupported := false;
+end;
+
+const
+  WINDOW_ICON = 'icons/ultrastardx-icon.png';
+
+procedure Initialize3D (Title: string);
+var
+  Icon: PSDL_Surface;
+begin
+  Log.LogStatus('SDL_Init', 'UGraphic.Initialize3D');
+  if ( SDL_InitSubSystem(SDL_INIT_VIDEO) = -1 ) then
+  begin
+    Log.LogCritical('SDL_Init Failed', 'UGraphic.Initialize3D');
+  end;
+
+  // load icon image (must be 32x32 for win32)
+  Icon := LoadImage(ResourcesPath.Append(WINDOW_ICON));
+  if (Icon <> nil) then
+    SDL_WM_SetIcon(Icon, nil);
+
+  SDL_WM_SetCaption(PChar(Title), nil);
+
+  { center window }
+  SDL_putenv('SDL_VIDEO_WINDOW_POS=center');
+  { workaround for buggy Intel 3D driver on Linux }
+  SDL_putenv('texture_tiling=false');
+
+  //Log.BenchmarkStart(2);
+
+  InitializeScreen;
+
+  //Log.BenchmarkEnd(2);
+  //Log.LogBenchmark('--> Setting Screen', 2);
+
+  //Log.BenchmarkStart(2);
+  Texture := TTextureUnit.Create;
+  // FIXME: this does not seem to be correct as Limit.
+  // Is the max. of either width or height.
+  Texture.Limit := 1024*1024;
+
+  //LoadTextures;
+  //Log.BenchmarkEnd(2);
+  //Log.LogBenchmark('--> Loading Textures', 2);
+
+  {
+  Log.BenchmarkStart(2);
+  Lyric:= TLyric.Create;
+  Log.BenchmarkEnd(2);
+  Log.LogBenchmark('--> Loading Fonts', 2);
+  }
+
+  // Note: do not initialize video modules earlier. They might depend on some
+  // SDL video functions or OpenGL extensions initialized in InitializeScreen()
+  InitializeVideo();
+
+  //Log.BenchmarkStart(2);
+
+  Log.LogStatus('TDisplay.Create', 'UGraphic.Initialize3D');
+  Display := TDisplay.Create;
+  //Display.SetCursor;
+
+  //Log.BenchmarkEnd(2); Log.LogBenchmark('====> Creating Display', 2);
+
+  //Log.LogStatus('Loading Screens', 'Initialize3D');
+  //Log.BenchmarkStart(3);
+
+  Log.LogStatus('Loading Font Textures', 'UGraphic.Initialize3D');
+  LoadFontTextures();
+
+  // Show the Loading Screen -------------
+  Log.LogStatus('Loading Loading Screen', 'UGraphic.Initialize3D');
+  LoadLoadingScreen;
+
+
+  Log.LogStatus(' Loading Textures', 'UGraphic.Initialize3D');
+  LoadTextures; // jb
+
+
+
+  // now that we have something to display while loading,
+  // start thread that loads the rest of ultrastar
+  //Mutex   := SDL_CreateMutex;
+  //SDL_UnLockMutex(Mutex);
+
+  // does not work this way because the loading thread tries to access opengl.
+  // See comment below
+  //LoadingThread  := SDL_CreateThread(@LoadingThread, nil);
+
+  // this would be run in the loadingthread
+  Log.LogStatus(' Loading Screens', 'UGraphic.Initialize3D');
+  LoadScreens;
+
+
+  // TODO:
+  // here should be a loop which
+  // * draws the loading screen (form time to time)
+  // * controlls the "process of the loading screen"
+  // * checks if the loadingthread has loaded textures (check mutex) and
+  //   * load the textures into opengl
+  //   * tells the loadingthread, that the memory for the texture can be reused
+  //     to load the netx texture (over another mutex)
+  // * runs as long as the loadingthread tells, that everything is loaded and ready (using a third mutex)
+  //
+  // therefor loadtexture have to be changed, that it, instat of caling some opengl functions
+  // for itself, it should change mutex
+  // the mainthread have to know somehow what opengl function have to be called with which parameters like
+  // texturetype, textureobjekt, textur-buffer-adress, ...
+
+  // wait for loading thread to finish
+  // currently does not work this way
+  // SDL_WaitThread(LoadingThread, I);
+  // SDL_DestroyMutex(Mutex);
+
+  Display.CurrentScreen^.FadeTo( @ScreenMain );
+
+  Log.BenchmarkEnd(2);
+  Log.LogBenchmark('--> Loading Screens', 2);
+
+  Log.LogStatus('Finish', 'Initialize3D');
+end;
+
+procedure SwapBuffers;
+begin
+  SDL_GL_SwapBuffers;
+  glMatrixMode(GL_PROJECTION);
+    glLoadIdentity;
+    glOrtho(0, RenderW, RenderH, 0, -1, 100);
+  glMatrixMode(GL_MODELVIEW);
+end;
+
+procedure Finalize3D;
+begin
+  // TODO: finalize other stuff
+  UnloadFontTextures;
+  SDL_QuitSubSystem(SDL_INIT_VIDEO);
+end;
+
+procedure Reinitialize3D;
+begin
+  InitializeScreen;
+end;
+
+procedure InitializeScreen;
+var
+  S:      string;
+  I:      integer;
+  W, H:   integer;
+  Depth:  Integer;
+  Fullscreen: boolean;
+begin
+  if (Params.Screens <> -1) then
+    Screens := Params.Screens + 1
+  else
+    Screens := Ini.Screens + 1;
+
+  // Set minimum color component sizes
+  // Note: do not request an alpha plane with SDL_GL_ALPHA_SIZE here as
+  // some cards/implementations do not support them (SDL_SetVideoMode fails).
+  // We do not the alpha plane anymore since offscreen rendering in back-buffer
+  // was removed.
+  SDL_GL_SetAttribute(SDL_GL_RED_SIZE,      5);
+  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,    5);
+  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,     5);
+
+  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,    16); // Z-Buffer depth
+  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,  1);
+
+  // VSYNC works for windows only at the moment. SDL_GL_SWAP_CONTROL under
+  // linux uses GLX_MESA_swap_control which is not supported by nvidea cards.
+  // Maybe use glXSwapIntervalSGI(1) from the GLX_SGI_swap_control extension instead.
+  //SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL,  1); // VSYNC (currently Windows only)
+
+  // If there is a resolution in Parameters, use it, else use the Ini value
+  I := Params.Resolution;
+  if (I <> -1) then
+    S := IResolution[I]
+  else
+    S := IResolution[Ini.Resolution];
+
+  I := Pos('x', S);
+  W := StrToInt(Copy(S, 1, I-1)) * Screens;
+  H := StrToInt(Copy(S, I+1, 1000));
+
+  if (Params.Depth <> -1) then
+    Depth := Params.Depth
+  else
+    Depth := Ini.Depth;
+
+  Log.LogStatus('SDL_SetVideoMode', 'Initialize3D');
+
+  // check whether to start in fullscreen or windowed mode.
+  // The command-line parameters take precedence over the ini settings.
+  Fullscreen := ((Ini.FullScreen = 1) or (Params.ScreenMode = scmFullscreen)) and
+                not (Params.ScreenMode = scmWindowed);
+
+  if Fullscreen then
+  begin
+    Log.LogStatus('SDL_SetVideoMode', 'Set Video Mode...   Full Screen');
+    screen := SDL_SetVideoMode(W, H, (Depth+1) * 16, SDL_OPENGL or SDL_FULLSCREEN );
+  end
+  else
+  begin
+    Log.LogStatus('SDL_SetVideoMode', 'Set Video Mode...   Windowed');
+    screen := SDL_SetVideoMode(W, H, 0, SDL_OPENGL or SDL_RESIZABLE);
+  end;
+
+  SDL_ShowCursor(0);
+
+  if (screen = nil) then
+  begin
+    Log.LogCritical('SDL_SetVideoMode Failed', 'Initialize3D');
+  end;
+
+  LoadOpenGLExtensions();
+
+  // define virtual (Render) and real (Screen) screen size
+  RenderW := 800;
+  RenderH := 600;
+  ScreenW := W;
+  ScreenH := H;
+
+  // clear screen once window is being shown
+  // Note: SwapBuffers uses RenderW/H, so they must be defined before
+  glClearColor(1, 1, 1, 1);
+  glClear(GL_COLOR_BUFFER_BIT);
+  SwapBuffers;
+end;
+
+procedure LoadLoadingScreen;
+begin
+  ScreenLoading := TScreenLoading.Create;
+  ScreenLoading.OnShow;
+  
+  Display.CurrentScreen := @ScreenLoading;
+
+  SwapBuffers;
+
+  ScreenLoading.Draw;
+  Display.Draw;
+
+  SwapBuffers;
+end;
+
+procedure LoadScreens;
+begin
+{  ScreenLoading := TScreenLoading.Create;
+  ScreenLoading.OnShow;
+  Display.CurrentScreen := @ScreenLoading;
+  ScreenLoading.Draw;
+  Display.Draw;
+  SwapBuffers;
+}
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Loading', 3); Log.BenchmarkStart(3);
+  ScreenMain :=             TScreenMain.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Main', 3); Log.BenchmarkStart(3);
+  ScreenName :=             TScreenName.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Name', 3); Log.BenchmarkStart(3);
+  ScreenLevel :=            TScreenLevel.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Level', 3); Log.BenchmarkStart(3);
+  ScreenSong :=             TScreenSong.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Song', 3); Log.BenchmarkStart(3);
+  ScreenSongMenu :=             TScreenSongMenu.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Song Menu', 3); Log.BenchmarkStart(3);
+  ScreenSing :=             TScreenSing.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Sing', 3); Log.BenchmarkStart(3);
+  ScreenScore :=            TScreenScore.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Score', 3); Log.BenchmarkStart(3);
+  ScreenTop5 :=             TScreenTop5.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Top5', 3); Log.BenchmarkStart(3);
+  ScreenOptions :=          TScreenOptions.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Options', 3); Log.BenchmarkStart(3);
+  ScreenOptionsGame :=      TScreenOptionsGame.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Options Game', 3); Log.BenchmarkStart(3);
+  ScreenOptionsGraphics  :=  TScreenOptionsGraphics.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Options Graphics', 3); Log.BenchmarkStart(3);
+  ScreenOptionsSound    :=     TScreenOptionsSound.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Options Sound', 3); Log.BenchmarkStart(3);
+  ScreenOptionsLyrics   :=    TScreenOptionsLyrics.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Options Lyrics', 3); Log.BenchmarkStart(3);
+  ScreenOptionsThemes   :=    TScreenOptionsThemes.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Options Themes', 3); Log.BenchmarkStart(3);
+  ScreenOptionsRecord   :=    TScreenOptionsRecord.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Options Record', 3); Log.BenchmarkStart(3);
+  ScreenOptionsAdvanced :=    TScreenOptionsAdvanced.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Options Advanced', 3); Log.BenchmarkStart(3);
+  ScreenEditSub :=          TScreenEditSub.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Edit Sub', 3); Log.BenchmarkStart(3);
+  ScreenEdit :=             TScreenEdit.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Edit', 3); Log.BenchmarkStart(3);
+  ScreenEditConvert :=      TScreenEditConvert.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen EditConvert', 3); Log.BenchmarkStart(3);
+//  ScreenEditHeader :=       TScreenEditHeader.Create(Skin.ScoreBG);
+//  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Edit Header', 3); Log.BenchmarkStart(3);
+  ScreenOpen :=             TScreenOpen.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Open', 3); Log.BenchmarkStart(3);
+  //ScreenSingModi :=         TScreenSingModi.Create;
+  //Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Sing with Modi support', 3); Log.BenchmarkStart(3);
+  ScreenSongMenu :=         TScreenSongMenu.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen SongMenu', 3); Log.BenchmarkStart(3);
+  ScreenSongJumpto :=         TScreenSongJumpto.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen SongJumpto', 3); Log.BenchmarkStart(3);
+  ScreenPopupCheck := TScreenPopupCheck.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Popup (Check)', 3); Log.BenchmarkStart(3);
+  ScreenPopupError := TScreenPopupError.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Popup (Error)', 3); Log.BenchmarkStart(3);
+  ScreenPopupInfo := TScreenPopupInfo.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Popup (Info)', 3); Log.BenchmarkStart(3);
+  ScreenPartyNewRound :=    TScreenPartyNewRound.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyNewRound', 3); Log.BenchmarkStart(3);
+  ScreenPartyScore :=       TScreenPartyScore.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyScore', 3); Log.BenchmarkStart(3);
+  ScreenPartyWin :=         TScreenPartyWin.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyWin', 3); Log.BenchmarkStart(3);
+  ScreenPartyOptions :=     TScreenPartyOptions.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyOptions', 3); Log.BenchmarkStart(3);
+  ScreenPartyPlayer :=      TScreenPartyPlayer.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyPlayer', 3); Log.BenchmarkStart(3);
+  ScreenPartyRounds :=      TScreenPartyRounds.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyRounds', 3); Log.BenchmarkStart(3);
+  ScreenStatMain :=         TScreenStatMain.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Stat Main', 3); Log.BenchmarkStart(3);
+  ScreenStatDetail :=       TScreenStatDetail.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Stat Detail', 3); Log.BenchmarkStart(3);
+  ScreenCredits    :=       TScreenCredits.Create;
+  Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Credits', 3); Log.BenchmarkStart(3);
+
+end;
+
+function LoadingThreadFunction: integer;
+begin
+  LoadScreens;
+  Result:= 1;
+end;
+
+procedure UnloadScreens;
+begin
+  ScreenMain.Free;
+  ScreenName.Free;
+  ScreenLevel.Free;
+  ScreenSong.Free;
+  ScreenSing.Free;
+  ScreenScore.Free;
+  ScreenTop5.Free;
+  ScreenOptions.Free;
+  ScreenOptionsGame.Free;
+  ScreenOptionsGraphics.Free;
+  ScreenOptionsSound.Free;
+  ScreenOptionsLyrics.Free;
+//  ScreenOptionsThemes.Free;
+  ScreenOptionsRecord.Free;
+  ScreenOptionsAdvanced.Free;
+  ScreenEditSub.Free;
+  ScreenEdit.Free;
+  ScreenEditConvert.Free;
+  ScreenOpen.Free;
+  //ScreenSingModi.Free;
+  ScreenSongMenu.Free;
+  ScreenSongJumpto.Free;
+  ScreenPopupCheck.Free;
+  ScreenPopupError.Free;
+  ScreenPopupInfo.Free;
+  ScreenPartyNewRound.Free;
+  ScreenPartyScore.Free;
+  ScreenPartyWin.Free;
+  ScreenPartyOptions.Free;
+  ScreenPartyPlayer.Free;
+  ScreenPartyRounds.Free;
+  ScreenStatMain.Free;
+  ScreenStatDetail.Free;
+end;
+
+end.
diff --git a/songmanagement/src/base/UGraphicClasses.pas b/songmanagement/src/base/UGraphicClasses.pas
new file mode 100644
index 00000000..55d91e39
--- /dev/null
+++ b/songmanagement/src/base/UGraphicClasses.pas
@@ -0,0 +1,726 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UGraphicClasses;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UTexture,
+  SDL;
+
+const
+  DelayBetweenFrames : cardinal = 60;
+
+type
+
+ TParticleType = (GoldenNote, PerfectNote, NoteHitTwinkle, PerfectLineTwinkle, ColoredStar, Flare);
+
+ TColour3f = record
+   r, g, b: real;
+ end;
+
+ TParticle = class
+   X, Y     : real;     //Position
+   Screen   : integer;
+   W, H     : cardinal; //dimensions of particle
+   Col      : array of TColour3f; // Colour(s) of particle
+   Scale    : array of real;      // Scaling factors of particle layers
+   Frame    : byte;     //act. Frame
+   Tex      : cardinal; //Tex num from Textur Manager
+   Live     : byte;     //How many Cycles before Kill
+   RecIndex : integer;  //To which rectangle this particle belongs (only GoldenNote)
+   StarType : TParticleType;  // GoldenNote | PerfectNote | NoteHitTwinkle | PerfectLineTwinkle
+   Alpha    : real;     // used for fading...
+   mX, mY   : real;     // movement-vector for PerfectLineTwinkle
+   SizeMod  : real;     // experimental size modifier
+   SurviveSentenceChange : Boolean;
+
+   constructor Create(cX, cY         : real;
+                      cScreen        : integer; 
+		      cLive          : byte; 
+		      cFrame         : integer; 
+		      cRecArrayIndex : integer; 
+		      cStarType      : TParticleType; 
+		      Player         : cardinal);
+   destructor Destroy(); override;
+   procedure Draw;
+   procedure LiveOn;
+ end;
+
+ RectanglePositions = record
+   xTop, yTop, xBottom, yBottom : real;
+   TotalStarCount   : integer;
+   CurrentStarCount : integer;
+   Screen           : integer;
+ end;
+
+ PerfectNotePositions = record
+   xPos, yPos : real;
+   Screen     : integer;
+ end;
+
+ TEffectManager = class
+   Particle      : array of TParticle;
+   LastTime      : cardinal;
+   RecArray      : array of RectanglePositions;
+   TwinkleArray  : array[0..5] of real; // store x-position of last twinkle for every player
+   PerfNoteArray : array of PerfectNotePositions;
+
+   FlareTex: TTexture;
+
+   constructor Create;
+   destructor  Destroy; override;
+   procedure Draw;
+   function  Spawn(X, Y: real;
+                   Screen: integer;
+                   Live: byte;
+                   StartFrame: integer;
+                   RecArrayIndex: integer;  // this is only used with GoldenNotes
+                   StarType: TParticleType;
+                   Player: cardinal         // for PerfectLineTwinkle
+             ): cardinal;
+   procedure SpawnRec();
+   procedure Kill(index: cardinal);
+   procedure KillAll();
+   procedure SentenceChange();
+   procedure SaveGoldenStarsRec(Xtop, Ytop, Xbottom, Ybottom: real);
+   procedure SavePerfectNotePos(Xtop, Ytop: real);
+   procedure GoldenNoteTwinkle(Top, Bottom, Right: real; Player: integer);
+   procedure SpawnPerfectLineTwinkle();
+ end;
+
+var
+  GoldenRec : TEffectManager;
+
+implementation
+
+uses
+  SysUtils,
+  Math,
+  gl,
+  UCommon,
+  UDrawTexture,
+  UGraphic,
+  UIni,
+  UNote,
+  USkins,
+  UThemes;
+
+//TParticle
+constructor TParticle.Create(cX, cY         : real;
+                             cScreen        : integer;
+			     cLive          : byte;
+			     cFrame         : integer;
+			     cRecArrayIndex : integer;
+			     cStarType      : TParticleType;
+			     Player         : cardinal);
+begin
+  inherited Create;
+  // in this constructor we set all initial values for our particle
+  X := cX;
+  Y := cY;
+  Screen := cScreen;
+  Live  := cLive;
+  Frame := cFrame;
+  RecIndex := cRecArrayIndex;
+  StarType := cStarType;
+  Alpha := (-cos((Frame+1)*2*pi/16)+1); // neat fade-in-and-out
+  SetLength(Scale,1);
+  Scale[0] := 1;
+  SurviveSentenceChange := False;
+  SizeMod := 1;
+  case cStarType of
+    GoldenNote:
+        begin
+          Tex := Tex_Note_Star.TexNum;
+          W := 20;
+          H := 20;
+          SetLength(Scale,4);
+          Scale[1] := 0.8;
+          Scale[2] := 0.4;
+          Scale[3] := 0.3;
+          SetLength(Col,4);
+          Col[0].r := 1;
+          Col[0].g := 0.7;
+          Col[0].b := 0.1;
+
+          Col[1].r := 1;
+          Col[1].g := 1;
+          Col[1].b := 0.4;
+
+          Col[2].r := 1;
+          Col[2].g := 1;
+          Col[2].b := 1;
+
+          Col[3].r := 1;
+          Col[3].g := 1;
+          Col[3].b := 1;
+        end;
+    PerfectNote:
+        begin
+          Tex := Tex_Note_Perfect_Star.TexNum;
+          W := 30;
+          H := 30;
+          SetLength(Col,1);
+          Col[0].r := 1;
+          Col[0].g := 1;
+          Col[0].b := 0.95;
+        end;
+    NoteHitTwinkle:
+        begin
+          Tex := Tex_Note_Star.TexNum;
+          Alpha := (Live/16);  // linear fade-out
+          W := 15;
+          H := 15;
+          Setlength(Col,1);
+          Col[0].r := 1;
+          Col[0].g := 1;
+          Col[0].b := RandomRange(10*Live,100)/90; //0.9;
+        end;
+    PerfectLineTwinkle:
+        begin
+          Tex := Tex_Note_Star.TexNum;
+          W := RandomRange(10,20);
+          H := W;
+          SizeMod := (-cos((Frame+1)*5*2*pi/16)*0.5+1.1);
+          SurviveSentenceChange := True;
+          // assign colours according to player given
+          SetLength(Scale,3);
+          Scale[1] := 0.3;
+          Scale[2] := 0.2;
+          SetLength(Col,3);
+          case Player of
+            0: LoadColor(Col[0].r,Col[0].g,Col[0].b,'P1Light');
+            1: LoadColor(Col[0].r,Col[0].g,Col[0].b,'P2Light');
+            2: LoadColor(Col[0].r,Col[0].g,Col[0].b,'P3Light');
+            3: LoadColor(Col[0].r,Col[0].g,Col[0].b,'P4Light');
+            4: LoadColor(Col[0].r,Col[0].g,Col[0].b,'P5Light');
+            5: LoadColor(Col[0].r,Col[0].g,Col[0].b,'P6Light');
+            else LoadColor(Col[0].r,Col[0].g,Col[0].b,'P1Light');
+          end;
+          Col[1].r := 1;
+          Col[1].g := 1;
+          Col[1].b := 0.4;
+          Col[2].r := Col[0].r+0.5;
+          Col[2].g := Col[0].g+0.5;
+          Col[2].b := Col[0].b+0.5;
+          mX := RandomRange(-5,5);
+          mY := RandomRange(-5,5);
+        end;
+    ColoredStar:
+        begin
+          Tex := Tex_Note_Star.TexNum;
+          W := RandomRange(10,20);
+          H := W;
+          SizeMod := (-cos((Frame+1)*5*2*pi/16)*0.5+1.1);
+          SurviveSentenceChange := True;
+          // assign colours according to player given
+          SetLength(Scale,1);
+          SetLength(Col,1);
+          Col[0].b := (Player and $ff)/255;
+          Col[0].g := ((Player shr 8) and $ff)/255;
+          Col[0].r := ((Player shr 16) and $ff)/255;
+          mX := 0;
+          mY := 0;
+        end;
+    Flare:
+        begin
+          Tex := Tex_Note_Star.TexNum;
+          W := 7;
+          H := 7;
+          SizeMod := (-cos((Frame+1)*5*2*pi/16)*0.5+1.1);
+          mX := RandomRange(-5,5);
+          mY := RandomRange(-5,5);
+          SetLength(Scale,4);
+          Scale[1] := 0.8;
+          Scale[2] := 0.4;
+          Scale[3] := 0.3;
+          SetLength(Col,4);
+          Col[0].r := 1;
+          Col[0].g := 0.7;
+          Col[0].b := 0.1;
+
+          Col[1].r := 1;
+          Col[1].g := 1;
+          Col[1].b := 0.4;
+
+          Col[2].r := 1;
+          Col[2].g := 1;
+          Col[2].b := 1;
+
+          Col[3].r := 1;
+          Col[3].g := 1;
+          Col[3].b := 1;
+
+        end;
+    else    // just some random default values
+        begin
+          Tex := Tex_Note_Star.TexNum;
+          Alpha := 1;
+          W := 20;
+          H := 20;
+          SetLength(Col,1);
+          Col[0].r := 1;
+          Col[0].g := 1;
+          Col[0].b := 1;
+        end;
+  end;
+end;
+
+destructor TParticle.Destroy();
+begin
+  SetLength(Scale,0);
+  SetLength(Col,0);
+  inherited;
+end;
+
+procedure TParticle.LiveOn;
+begin
+  //Live = 0 => Live forever  <blindy> ?? but if this is 0 they would be killed in the Manager at Draw
+  if (Live > 0) then
+    Dec(Live);
+
+  // animate frames
+  Frame := ( Frame + 1 ) mod 16;
+
+  // make our particles do funny stuff (besides being animated)
+  // changes of any particle-values throughout its life are done here
+  case StarType of
+    GoldenNote:
+        begin
+          Alpha := (-cos((Frame+1)*2*pi/16)+1); // neat fade-in-and-out
+        end;
+    PerfectNote:
+        begin
+          Alpha := (-cos((Frame+1)*2*pi/16)+1); // neat fade-in-and-out
+        end;
+    NoteHitTwinkle:
+        begin
+          Alpha := (Live/10);  // linear fade-out
+        end;
+    PerfectLineTwinkle:
+        begin
+          Alpha := (-cos((Frame+1)*2*pi/16)+1); // neat fade-in-and-out
+          SizeMod := (-cos((Frame+1)*5*2*pi/16)*0.5+1.1);
+          // move around
+          X := X + mX;
+          Y := Y + mY;
+        end;
+    ColoredStar:
+        begin
+          Alpha := (-cos((Frame+1)*2*pi/16)+1); // neat fade-in-and-out
+        end;
+    Flare:
+        begin
+          Alpha := (-cos((Frame+1)/16*1.7*pi+0.3*pi)+1); // neat fade-in-and-out
+          SizeMod := (-cos((Frame+1)*5*2*pi/16)*0.5+1.1);
+          // move around
+          X := X + mX;
+          Y := Y + mY;
+          mY := mY+1.8;
+//          mX := mX/2;
+        end;
+  end;
+end;
+
+procedure TParticle.Draw;
+var
+  L: cardinal;
+begin
+  if (ScreenAct = Screen) then
+  begin
+    glEnable(GL_TEXTURE_2D);
+	  glBindTexture(GL_TEXTURE_2D, Tex);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glEnable(GL_BLEND);
+	
+    // this draws (multiple) texture(s) of our particle
+    for L := 0 to High(Col) do
+    begin
+      glColor4f(Col[L].r, Col[L].g, Col[L].b, Alpha);
+
+      glBegin(GL_QUADS);
+	      glTexCoord2f((1/16) * Frame, 0);          glVertex2f(X-W*Scale[L]*SizeMod, Y-H*Scale[L]*SizeMod);
+        glTexCoord2f((1/16) * Frame + (1/16), 0); glVertex2f(X-W*Scale[L]*SizeMod, Y+H*Scale[L]*SizeMod);
+        glTexCoord2f((1/16) * Frame + (1/16), 1); glVertex2f(X+W*Scale[L]*SizeMod, Y+H*Scale[L]*SizeMod);
+        glTexCoord2f((1/16) * Frame, 1);          glVertex2f(X+W*Scale[L]*SizeMod, Y-H*Scale[L]*SizeMod);
+      glEnd;
+    end;
+	
+	  glDisable(GL_BLEND);
+    glDisable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glcolor4f(1,1,1,1);
+  end;
+end;
+// end of TParticle
+
+// TEffectManager
+
+constructor TEffectManager.Create;
+var
+  c: cardinal;
+begin
+  inherited;
+  LastTime := SDL_GetTicks();
+  for c := 0 to 5 do
+  begin
+    TwinkleArray[c] := 0;
+  end;
+end;
+
+destructor TEffectManager.Destroy;
+begin
+  Killall;
+  inherited;
+end;
+
+
+procedure TEffectManager.Draw;
+var
+  I: integer;
+  CurrentTime: cardinal;
+//const
+//  DelayBetweenFrames : cardinal = 100;
+begin
+
+  CurrentTime := SDL_GetTicks();
+  //Manage particle life
+  if (CurrentTime - LastTime) > DelayBetweenFrames then
+  begin
+    LastTime := CurrentTime;
+    for I := 0 to high(Particle) do
+      Particle[I].LiveOn;
+  end;
+
+  I := 0;
+  //Kill dead particles
+  while (I <= High(Particle)) do
+  begin
+    if (Particle[I].Live <= 0) then
+    begin
+      kill(I);
+    end
+    else
+    begin
+      inc(I);
+    end;
+  end;
+
+ //Draw
+  for I := 0 to high(Particle) do
+  begin
+    Particle[I].Draw;
+  end;
+end;
+
+// this method creates just one particle
+function TEffectManager.Spawn(X, Y: real; Screen: integer; Live: byte; StartFrame : integer; RecArrayIndex : integer; StarType : TParticleType; Player: cardinal): cardinal;
+begin
+  Result := Length(Particle);
+  SetLength(Particle, (Result + 1));
+  Particle[Result] := TParticle.Create(X, Y, Screen, Live, StartFrame, RecArrayIndex, StarType, Player);
+end;
+
+// manage Sparkling of GoldenNote Bars
+procedure TEffectManager.SpawnRec();
+var
+  Xkatze, Ykatze    : real;
+  RandomFrame : integer;
+  P : integer; // P as seen on TV as Positionman
+begin
+//Spawn a random amount of stars within the given coordinates
+//RandomRange(0,14) <- this one starts at a random  frame, 16 is our last frame - would be senseless to start a particle with 16, cause it would be dead at the next frame
+  for P := 0 to high(RecArray) do
+  begin
+    while (RecArray[P].TotalStarCount > RecArray[P].CurrentStarCount) do
+    begin
+      Xkatze := RandomRange(Ceil(RecArray[P].xTop), Ceil(RecArray[P].xBottom));
+      Ykatze := RandomRange(Ceil(RecArray[P].yTop), Ceil(RecArray[P].yBottom));
+      RandomFrame := RandomRange(0,14);
+      // Spawn a GoldenNote Particle
+      Spawn(Xkatze, Ykatze, RecArray[P].Screen, 16 - RandomFrame, RandomFrame, P, GoldenNote, 0);
+      inc(RecArray[P].CurrentStarCount);
+    end;
+  end;
+  draw;
+end;
+
+// kill one particle (with given index in our particle array)
+procedure TEffectManager.Kill(Index: cardinal);
+var
+  LastParticleIndex : integer;
+begin
+// delete particle indexed by Index,
+// overwrite it's place in our particle-array with the particle stored at the last array index,
+// shorten array
+  LastParticleIndex := high(Particle);
+  if not(LastParticleIndex = -1) then  // is there still a particle to delete?
+  begin
+    if not(Particle[Index].RecIndex = -1) then  // if it is a GoldenNote particle...
+      dec(RecArray[Particle[Index].RecIndex].CurrentStarCount); // take care of its associated GoldenRec
+    // now get rid of that particle
+    Particle[Index].Destroy;
+    Particle[Index] := Particle[LastParticleIndex];
+    SetLength(Particle, LastParticleIndex);
+  end;
+end;
+
+// clean up all particles and management structures
+procedure TEffectManager.KillAll();
+var
+  c: cardinal;
+begin
+//It's the kill all kennies rotuine
+  while Length(Particle) > 0 do  // kill all existing particles
+    Kill(0);
+  SetLength(RecArray,0);  // remove GoldenRec positions
+  SetLength(PerfNoteArray,0); // remove PerfectNote positions
+  for c := 0 to 5 do
+  begin
+    TwinkleArray[c] := 0; // reset GoldenNoteHit memory
+  end;
+end;
+
+procedure TEffectManager.SentenceChange();
+var
+  c: cardinal;
+begin
+  c := 0;
+  while c <= High(Particle) do
+  begin
+    if Particle[c].SurviveSentenceChange then
+      inc(c)
+    else
+      Kill(c);
+  end;
+  SetLength(RecArray,0);  // remove GoldenRec positions
+  SetLength(PerfNoteArray,0); // remove PerfectNote positions
+  for c := 0 to 5 do
+  begin
+    TwinkleArray[c] := 0; // reset GoldenNoteHit memory
+  end;
+end;
+
+procedure TeffectManager.GoldenNoteTwinkle(Top, Bottom, Right: real; Player: integer);
+//Twinkle stars while golden note hit
+// this is called from UDraw.pas, SingDrawPlayerCzesc
+var
+  C, P, XKatze, YKatze, LKatze: integer;
+  H: real;
+begin
+  // make sure we spawn only one time at one position
+  if (TwinkleArray[Player] < Right) then
+    for P := 0 to high(RecArray) do  // Are we inside a GoldenNoteRectangle?
+    begin
+      H := (Top+Bottom)/2; // helper...
+      with RecArray[P] do
+      if ((xBottom >= Right) and (xTop <= Right) and
+          (yTop <= H) and (yBottom >= H))
+          and (Screen = ScreenAct) then
+      begin
+        TwinkleArray[Player] := Right; // remember twinkle position for this player
+        for C := 1 to 10 do
+        begin
+          Ykatze := RandomRange(ceil(Top) , ceil(Bottom));
+          XKatze := RandomRange(-7,3);
+          LKatze := RandomRange(7,13);
+          Spawn(Ceil(Right)+XKatze, YKatze, ScreenAct, LKatze, 0, -1, NoteHitTwinkle, 0);
+        end;
+        for C := 1 to 3 do
+        begin
+          Ykatze := RandomRange(ceil(Top)-6 , ceil(Top));
+          XKatze := RandomRange(-5,1);
+          LKatze := RandomRange(4,7);
+          Spawn(Ceil(Right)+XKatze, YKatze, ScreenAct, LKatze, 0, -1, NoteHitTwinkle, 0);
+        end;
+        for C := 1 to 3 do
+        begin
+          Ykatze := RandomRange(ceil(Bottom), ceil(Bottom)+6);
+          XKatze := RandomRange(-5,1);
+          LKatze := RandomRange(4,7);
+          Spawn(Ceil(Right)+XKatze, YKatze, ScreenAct, LKatze, 0, -1, NoteHitTwinkle, 0);
+        end;
+        for C := 1 to 3 do
+        begin
+          Ykatze := RandomRange(ceil(Top)-10 , ceil(Top)-6);
+          XKatze := RandomRange(-5,1);
+          LKatze := RandomRange(1,4);
+          Spawn(Ceil(Right)+XKatze, YKatze, ScreenAct, LKatze, 0, -1, NoteHitTwinkle, 0);
+        end;
+        for C := 1 to 3 do
+        begin
+          Ykatze := RandomRange(ceil(Bottom)+6 , ceil(Bottom)+10);
+          XKatze := RandomRange(-5,1);
+          LKatze := RandomRange(1,4);
+          Spawn(Ceil(Right)+XKatze, YKatze, ScreenAct, LKatze, 0, -1, NoteHitTwinkle, 0);
+        end;
+
+        exit; // found a matching GoldenRec, did spawning stuff... done
+      end;
+    end;
+end;
+
+procedure TEffectManager.SaveGoldenStarsRec(Xtop, Ytop, Xbottom, Ybottom: real);
+var
+  P : integer;   // P like used in Positions
+  NewIndex : integer;
+begin
+  for P := 0 to high(RecArray) do  // Do we already have that "new" position?
+    begin
+      if (ceil(RecArray[P].xTop) = ceil(Xtop)) and
+      (ceil(RecArray[P].yTop) = ceil(Ytop)) and
+      (ScreenAct = RecArray[p].Screen) then
+        exit; // it's already in the array, so we don't have to create a new one
+    end;
+
+  // we got a new position, add the new positions to our array
+    NewIndex := Length(RecArray);
+    SetLength(RecArray, NewIndex + 1);
+    RecArray[NewIndex].xTop    := Xtop;
+    RecArray[NewIndex].yTop    := Ytop;
+    RecArray[NewIndex].xBottom := Xbottom;
+    RecArray[NewIndex].yBottom := Ybottom;
+    RecArray[NewIndex].TotalStarCount := ceil(Xbottom - Xtop) div 12 + 3;
+    RecArray[NewIndex].CurrentStarCount := 0;
+    RecArray[NewIndex].Screen := ScreenAct;
+end;
+
+procedure TEffectManager.SavePerfectNotePos(Xtop, Ytop: real);
+var
+  P : integer;   // P like used in Positions
+  NewIndex : integer;
+  RandomFrame : integer;
+  Xkatze, Ykatze : integer;
+begin
+  for P := 0 to high(PerfNoteArray) do  // Do we already have that "new" position?
+  begin
+    with PerfNoteArray[P] do
+    if (ceil(xPos) = ceil(Xtop)) and (ceil(yPos) = ceil(Ytop)) and
+       (Screen = ScreenAct) then
+      exit; // it's already in the array, so we don't have to create a new one
+  end; //for
+
+  // we got a new position, add the new positions to our array
+  NewIndex := Length(PerfNoteArray);
+  SetLength(PerfNoteArray, NewIndex + 1);
+  PerfNoteArray[NewIndex].xPos    := Xtop;
+  PerfNoteArray[NewIndex].yPos    := Ytop;
+  PerfNoteArray[NewIndex].Screen  := ScreenAct;
+
+  for P := 0 to 2 do
+  begin
+    Xkatze := RandomRange(ceil(Xtop) - 5 , ceil(Xtop) + 10);
+    Ykatze := RandomRange(ceil(Ytop) - 5 , ceil(Ytop) + 10);
+    RandomFrame := RandomRange(0,14);
+    Spawn(Xkatze, Ykatze, ScreenAct, 16 - RandomFrame, RandomFrame, -1, PerfectNote, 0);
+  end; //for
+
+end;
+
+procedure TEffectManager.SpawnPerfectLineTwinkle();
+var
+  P, I, Life: cardinal;
+  Left, Right, Top, Bottom: cardinal;
+  cScreen: integer;
+begin
+// calculation of coordinates done with hardcoded values like in UDraw.pas
+// might need to be adjusted if drawing of SingScreen is modified
+// coordinates may still be a bit weird and need adjustment
+  if Ini.SingWindow = 0 then
+  begin
+    Left := 130;
+  end
+  else
+  begin
+    Left := 30;
+  end;
+  Right := 770;
+  // spawn effect for every player with a perfect line
+  for P := 0 to PlayersPlay-1 do
+    if Player[P].LastSentencePerfect then
+    begin
+      // calculate area where notes of this player are drawn
+      case PlayersPlay of
+        1: begin
+             Bottom := Skin_P2_NotesB+10;
+             Top := Bottom-105;
+             cScreen := 1;
+           end;
+        2,4: begin
+               case P of
+                 0,2: begin
+                        Bottom := Skin_P1_NotesB+10;
+                        Top := Bottom-105;
+                      end;
+                 else begin
+                        Bottom := Skin_P2_NotesB+10;
+                        Top := Bottom-105;
+                      end;
+               end;
+               case P of
+                 0,1: cScreen := 1;
+                 else cScreen := 2;
+               end;
+             end;
+        3,6: begin
+               case P of
+                 0,3: begin
+                        Top := 130;
+                        Bottom := Top+85;
+                      end;
+                 1,4: begin
+                        Top := 255;
+                        Bottom := Top+85;
+                      end;
+                 2,5: begin
+                        Top := 380;
+                        Bottom := Top+85;
+                      end;
+               end;
+               case P of
+                 0,1,2: cScreen := 1;
+                 else cScreen := 2;
+               end;
+             end;
+      end;
+      // spawn Sparkling Stars inside calculated coordinates
+      for I := 0 to 80 do
+      begin
+        Life := RandomRange(8,16);
+        Spawn(RandomRange(Left,Right), RandomRange(Top,Bottom), cScreen, Life, 16-Life, -1, PerfectLineTwinkle, P);
+      end;
+    end;
+end;
+
+end.
+
diff --git a/songmanagement/src/base/UImage.pas b/songmanagement/src/base/UImage.pas
new file mode 100644
index 00000000..1866316e
--- /dev/null
+++ b/songmanagement/src/base/UImage.pas
@@ -0,0 +1,1131 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UImage;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  UPath;
+
+{$DEFINE HavePNG}
+{$DEFINE HaveBMP}
+{$DEFINE HaveJPG}
+
+const
+  PixelFmt_RGBA: TSDL_Pixelformat = (
+    palette:      nil;
+    BitsPerPixel:  32;
+    BytesPerPixel:  4;
+    Rloss:          0;
+    Gloss:          0;
+    Bloss:          0;
+    Aloss:          0;
+    Rshift:         0;
+    Gshift:         8;
+    Bshift:        16;
+    Ashift:        24;
+    Rmask:  $000000ff;
+    Gmask:  $0000ff00;
+    Bmask:  $00ff0000;
+    Amask:  $ff000000;
+    ColorKey:       0;
+    Alpha:        255
+  );
+
+  PixelFmt_RGB: TSDL_Pixelformat = (
+    palette:      nil;
+    BitsPerPixel:  24;
+    BytesPerPixel:  3;
+    Rloss:          0;
+    Gloss:          0;
+    Bloss:          0;
+    Aloss:          0;
+    Rshift:         0;
+    Gshift:         8;
+    Bshift:        16;
+    Ashift:         0;
+    Rmask:  $000000ff;
+    Gmask:  $0000ff00;
+    Bmask:  $00ff0000;
+    Amask:  $00000000;
+    ColorKey:       0;
+    Alpha:        255
+  );
+
+  PixelFmt_BGRA: TSDL_Pixelformat = (
+    palette:      nil;
+    BitsPerPixel:  32;
+    BytesPerPixel:  4;
+    Rloss:          0;
+    Gloss:          0;
+    Bloss:          0;
+    Aloss:          0;
+    Rshift:        16;
+    Gshift:         8;
+    Bshift:         0;
+    Ashift:        24;
+    Rmask:  $00ff0000;
+    Gmask:  $0000ff00;
+    Bmask:  $000000ff;
+    Amask:  $ff000000;
+    ColorKey:       0;
+    Alpha:        255
+  );
+
+  PixelFmt_BGR: TSDL_Pixelformat = (
+    palette:      nil;
+    BitsPerPixel:  24;
+    BytesPerPixel:  3;
+    Rloss:          0;
+    Gloss:          0;
+    Bloss:          0;
+    Aloss:          0;
+    Rshift:        16;
+    Gshift:         8;
+    Bshift:         0;
+    Ashift:         0;
+    Rmask:  $00ff0000;
+    Gmask:  $0000ff00;
+    Bmask:  $000000ff;
+    Amask:  $00000000;
+    ColorKey:       0;
+    Alpha:        255
+  );
+
+type
+  TImagePixelFmt = (
+    ipfRGBA, ipfRGB, ipfBGRA, ipfBGR
+  );
+
+(*******************************************************
+ * Image saving
+ *******************************************************)
+
+{$IFDEF HavePNG}
+function WritePNGImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
+{$ENDIF}
+{$IFDEF HaveBMP}
+function WriteBMPImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
+{$ENDIF}
+{$IFDEF HaveJPG}
+function WriteJPGImage(const FileName: IPath; Surface: PSDL_Surface; Quality: integer): boolean;
+{$ENDIF}
+
+(*******************************************************
+ * Image loading
+ *******************************************************)
+
+function LoadImage(const Filename: IPath): PSDL_Surface;
+
+(*******************************************************
+ * Image manipulation
+ *******************************************************)
+
+function PixelFormatEquals(fmt1, fmt2: PSDL_PixelFormat): boolean;
+procedure ScaleImage(var ImgSurface: PSDL_Surface; Width, Height: cardinal);
+procedure FitImage(var ImgSurface: PSDL_Surface; Width, Height: cardinal);
+procedure ColorizeImage(ImgSurface: PSDL_Surface; NewColor: cardinal);
+
+implementation
+
+uses
+  SysUtils,
+  Classes,
+  Math,
+  {$IFDEF MSWINDOWS}
+  Windows,
+  {$ENDIF}
+  {$IFDEF HaveJPG}
+    {$IFDEF Delphi}
+    Graphics,
+    jpeg,
+    {$ELSE}
+    jpeglib,
+    jerror,
+    jcparam,
+    jdatadst, jcapimin, jcapistd,
+    {$ENDIF}
+  {$ENDIF}
+  {$IFDEF HavePNG}
+  png,
+  {$ENDIF}
+  zlib,
+  sdl_image,
+  sdlutils,
+  sdlstreams,
+  UCommon,
+  ULog;
+
+function IsRGBSurface(pixelFmt: PSDL_PixelFormat): boolean;
+begin
+  Result := (pixelFmt.BitsPerPixel = 24) and
+            (pixelFmt.RMask = $0000FF)   and
+            (pixelFmt.GMask = $00FF00)   and
+            (pixelFmt.BMask = $FF0000);
+end;
+
+function IsRGBASurface(pixelFmt: PSDL_PixelFormat): boolean;
+begin
+  Result := (pixelFmt.BitsPerPixel = 32) and
+            (pixelFmt.RMask = $000000FF) and
+            (pixelFmt.GMask = $0000FF00) and
+            (pixelFmt.BMask = $00FF0000) and
+            (pixelFmt.AMask = $FF000000);
+end;
+
+function IsBGRSurface(pixelFmt: PSDL_PixelFormat): boolean;
+begin
+  Result := (pixelFmt.BitsPerPixel = 24) and
+            (pixelFmt.BMask = $0000FF)   and
+            (pixelFmt.GMask = $00FF00)   and
+            (pixelFmt.RMask = $FF0000);
+end;
+
+function IsBGRASurface(pixelFmt: PSDL_PixelFormat): boolean;
+begin
+  Result := (pixelFmt.BitsPerPixel = 32) and
+            (pixelFmt.BMask = $000000FF) and
+            (pixelFmt.GMask = $0000FF00) and
+            (pixelFmt.RMask = $00FF0000) and
+            (pixelFmt.AMask = $FF000000);
+end;
+
+// Converts alpha-formats to BGRA, non-alpha to BGR, and leaves BGR(A) as is
+// sets converted to true if the surface needed to be converted
+function ConvertToBGR_BGRASurface(Surface: PSDL_Surface; out Converted: boolean): PSDL_Surface;
+var
+  pixelFmt: PSDL_PixelFormat;
+begin
+  pixelFmt := Surface.format;
+  if (IsBGRSurface(pixelFmt) or IsBGRASurface(pixelFmt)) then
+  begin
+    Converted := false;
+    Result := Surface;
+  end
+  else
+  begin
+    // invalid format -> needs conversion
+    if (pixelFmt.AMask <> 0) then
+      Result := SDL_ConvertSurface(Surface, @PixelFmt_BGRA, SDL_SWSURFACE)
+    else
+      Result := SDL_ConvertSurface(Surface, @PixelFmt_BGR, SDL_SWSURFACE);
+    Converted := true;
+  end;
+end;
+
+// Converts alpha-formats to RGBA, non-alpha to RGB, and leaves RGB(A) as is
+// sets converted to true if the surface needed to be converted
+function ConvertToRGB_RGBASurface(Surface: PSDL_Surface; out Converted: boolean): PSDL_Surface;
+var
+  pixelFmt: PSDL_PixelFormat;
+begin
+  pixelFmt := Surface.format;
+  if (IsRGBSurface(pixelFmt) or IsRGBASurface(pixelFmt)) then
+  begin
+    Converted := false;
+    Result := Surface;
+  end
+  else
+  begin
+    // invalid format -> needs conversion
+    if (pixelFmt.AMask <> 0) then
+      Result := SDL_ConvertSurface(Surface, @PixelFmt_RGBA, SDL_SWSURFACE)
+    else
+      Result := SDL_ConvertSurface(Surface, @PixelFmt_RGB, SDL_SWSURFACE);
+    Converted := true;
+  end;
+end;
+
+(*******************************************************
+ * Image saving
+ *******************************************************)
+
+(***************************
+ * PNG section
+ *****************************)
+
+{$IFDEF HavePNG}
+
+// delphi does not support setjmp()/longjmp() -> define our own error-handler
+procedure user_error_fn(png_ptr: png_structp; error_msg: png_const_charp); cdecl;
+begin
+  raise Exception.Create(error_msg);
+end;
+
+procedure user_read_data(png_ptr: png_structp; data: png_bytep; length: png_size_t); cdecl;
+var
+  inFile: TStream;
+begin
+  inFile := TStream(png_get_io_ptr(png_ptr));
+  inFile.Read(data^, length);
+end;
+
+procedure user_write_data(png_ptr: png_structp; data: png_bytep; length: png_size_t); cdecl;
+var
+  outFile: TStream;
+begin
+  outFile := TStream(png_get_io_ptr(png_ptr));
+  outFile.Write(data^, length);
+end;
+
+procedure user_flush_data(png_ptr: png_structp); cdecl;
+//var
+//  outFile: TStream;
+begin
+  // binary files are flushed automatically, Flush() works with Text-files only
+  //outFile := TStream(png_get_io_ptr(png_ptr));
+  //outFile.Flush();
+end;
+
+procedure DateTimeToPngTime(time: TDateTime; var pngTime: png_time);
+var
+  year, month, day: word;
+  hour, minute, second, msecond: word;
+begin
+  DecodeDate(time, year, month, day);
+  pngTime.year  := png_uint_16(year);
+  pngTime.month := png_byte(month);
+  pngTime.day   := png_byte(day);
+  DecodeTime(time, hour, minute, second, msecond);
+  pngTime.hour   := png_byte(hour);
+  pngTime.minute := png_byte(minute);
+  pngTime.second := png_byte(second);
+end;
+
+(*
+ * ImageData must be in RGB-format
+ *)
+function WritePNGImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
+var
+  png_ptr:   png_structp;
+  info_ptr:  png_infop;
+  pngFile:   TStream;
+  row:       integer;
+  rowData:   array of png_bytep;
+//  rowStride: integer;
+  converted: boolean;
+  colorType: integer;
+//  time:      png_time;
+begin
+  Result := false;
+
+  // open file for writing
+  try
+    pngFile := TBinaryFileStream.Create(FileName, fmCreate);
+  except
+    Log.LogError('Could not open file: "' + FileName.ToNative + '"', 'WritePngImage');
+    Exit;
+  end;
+
+  // only 24bit (RGB) or 32bit (RGBA) data is supported, so convert to it
+  Surface := ConvertToRGB_RGBASurface(Surface, converted);
+
+  png_ptr := nil;
+
+  try
+    // initialize png (and enable a user-defined error-handler that throws an exception on error)
+    png_ptr := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, @user_error_fn, nil);
+    // the error-handler is called if png_create_write_struct() fails, so png_ptr should always be <> nil
+    if (png_ptr = nil) then
+    begin
+      Log.LogError('png_create_write_struct() failed', 'WritePngImage');
+      if (converted) then
+        SDL_FreeSurface(Surface);
+      Exit;
+    end;
+
+    info_ptr := png_create_info_struct(png_ptr);
+
+    if (Surface^.format^.BitsPerPixel = 24) then
+      colorType := PNG_COLOR_TYPE_RGB
+    else
+      colorType := PNG_COLOR_TYPE_RGBA;
+
+    // define write IO-functions (POSIX-style FILE-pointers are not available in Delphi)
+    png_set_write_fn(png_ptr, pngFile, @user_write_data, @user_flush_data);
+    png_set_IHDR(
+      png_ptr, info_ptr,
+      Surface.w, Surface.h,
+      8,
+      colorType,
+      PNG_INTERLACE_NONE,
+      PNG_COMPRESSION_TYPE_DEFAULT,
+      PNG_FILTER_TYPE_DEFAULT
+    );
+
+    // TODO: do we need the modification time?
+    //DateTimeToPngTime(Now, time);
+    //png_set_tIME(png_ptr, info_ptr, @time);
+
+    if (SDL_MUSTLOCK(Surface)) then
+      SDL_LockSurface(Surface);
+
+    // setup data
+    SetLength(rowData, Surface.h);
+    for row := 0 to Surface.h-1 do
+    begin
+      // set rowData-elements to beginning of each image row
+      // Note: the byte-count of a row is pitch (which is not width*bitsPerPixel if the image is aligned)
+      rowData[row] := @PChar(Surface.pixels)[(Surface.h-row-1) * Surface.pitch];
+    end;
+
+    if (SDL_MUSTLOCK(Surface)) then
+      SDL_UnlockSurface(Surface);
+
+    png_write_info(png_ptr, info_ptr);
+    png_write_image(png_ptr, png_bytepp(rowData));
+    png_write_end(png_ptr, nil);
+
+    Result := true;
+  except on E: Exception do
+    Log.LogError(E.message, 'WritePngImage');
+  end;
+
+  // free row-data
+  SetLength(rowData, 0);
+
+  // free png-resources
+  if (png_ptr <> nil) then
+    png_destroy_write_struct(@png_ptr, nil);
+
+  if (converted) then
+    SDL_FreeSurface(Surface);
+
+  // close file
+  pngFile.Free;
+end;
+
+{$ENDIF}
+
+(***************************
+ * BMP section
+ *****************************)
+
+{$IFDEF HaveBMP}
+
+{$IFNDEF MSWINDOWS}
+const
+  (* constants for the biCompression field *)
+  BI_RGB       = 0;
+  BI_RLE8      = 1;
+  BI_RLE4      = 2;
+  BI_BITFIELDS = 3;
+  BI_JPEG      = 4;
+  BI_PNG       = 5;
+
+type
+  BITMAPINFOHEADER = record
+    biSize:          longword;
+    biWidth:         longint;
+    biHeight:        longint;
+    biPlanes:        word;
+    biBitCount:      word;
+    biCompression:   longword;
+    biSizeImage:     longword;
+    biXPelsPerMeter: longint;
+    biYPelsPerMeter: longint;
+    biClrUsed:       longword;
+    biClrImportant:  longword;
+  end;
+  LPBITMAPINFOHEADER = ^BITMAPINFOHEADER;
+  TBITMAPINFOHEADER  = BITMAPINFOHEADER;
+  PBITMAPINFOHEADER  = ^BITMAPINFOHEADER;
+
+  RGBTRIPLE = record
+    rgbtBlue:  byte;
+    rgbtGreen: byte;
+    rgbtRed:   byte;
+  end;
+  tagRGBTRIPLE = RGBTRIPLE;
+  TRGBTRIPLE = RGBTRIPLE;
+  PRGBTRIPLE = ^RGBTRIPLE;
+
+  RGBQUAD = record
+    rgbBlue:     byte;
+    rgbGreen:    byte;
+    rgbRed:      byte;
+    rgbReserved: byte;
+  end;
+  tagRGBQUAD = RGBQUAD;
+  TRGBQUAD = RGBQUAD;
+  PRGBQUAD = ^RGBQUAD;
+
+  BITMAPINFO = record
+    bmiHeader: BITMAPINFOHEADER;
+    bmiColors: array[0..0] of RGBQUAD;
+  end;
+  LPBITMAPINFO = ^BITMAPINFO;
+  PBITMAPINFO = ^BITMAPINFO;
+  TBITMAPINFO = BITMAPINFO;
+
+  {$PACKRECORDS 2}
+  BITMAPFILEHEADER = record
+    bfType:      word;
+    bfSize:      longword;
+    bfReserved1: word;
+    bfReserved2: word;
+    bfOffBits:   longword;
+  end;
+  {$PACKRECORDS DEFAULT}
+{$ENDIF}
+
+(*
+ * ImageData must be in BGR-format
+ *)
+function WriteBMPImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
+var
+  bmpFile:    TStream;
+  FileInfo:   BITMAPINFOHEADER;
+  FileHeader: BITMAPFILEHEADER;
+  Converted:  boolean;
+  Row:        integer;
+  RowSize:    integer;
+begin
+  Result := false;
+
+  // open file for writing
+  try
+    bmpFile := TBinaryFileStream.Create(FileName, fmCreate);
+  except
+    Log.LogError('Could not open file: "' + FileName.ToNative + '"', 'WriteBMPImage');
+    Exit;
+  end;
+
+  // only 24bit (BGR) or 32bit (BGRA) data is supported, so convert to it
+  Surface := ConvertToBGR_BGRASurface(Surface, Converted);
+
+  // aligned (4-byte) row-size in bytes
+  RowSize := ((Surface.w * Surface.format.BytesPerPixel + 3) div 4) * 4;
+
+  // initialize bitmap info
+  FillChar(FileInfo, SizeOf(BITMAPINFOHEADER), 0);
+  with FileInfo do
+  begin
+    biSize := SizeOf(BITMAPINFOHEADER);
+    biWidth := Surface.w;
+    biHeight := Surface.h;
+    biPlanes := 1;
+    biBitCount := Surface^.format^.BitsPerPixel;
+    biCompression := BI_RGB;
+    biSizeImage := RowSize * Surface.h;
+  end;
+
+  // initialize header-data
+  FillChar(FileHeader, SizeOf(BITMAPFILEHEADER), 0);
+  with FileHeader do
+  begin
+    bfType := $4D42; // = 'BM'
+    bfOffBits := SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER);
+    bfSize := bfOffBits + FileInfo.biSizeImage;
+  end;
+
+  // and move the whole stuff into the file ;-)
+  try
+    // write headers
+    bmpFile.Write(FileHeader, SizeOf(BITMAPFILEHEADER));
+    bmpFile.Write(FileInfo,   SizeOf(BITMAPINFOHEADER));
+
+    // write image-data
+
+    if (SDL_MUSTLOCK(Surface)) then
+      SDL_LockSurface(Surface);
+
+    // BMP needs 4-byte alignment
+    if (Surface.pitch mod 4 = 0) then
+    begin
+      // aligned correctly -> write whole image at once
+      bmpFile.Write(Surface.pixels^, FileInfo.biSizeImage);
+    end
+    else
+    begin
+      // misaligned -> write each line separately
+      // Note: for the last line unassigned memory (> last Surface.pixels element)
+      //   will be copied to the padding area (last bytes of a row),
+      //   but we do not care because the content of padding data is ignored anyhow.
+      for Row := 0 to Surface.h do
+        bmpFile.Write(PChar(Surface.pixels)[Row * Surface.pitch], RowSize);
+    end;
+
+    if (SDL_MUSTLOCK(Surface)) then
+      SDL_UnlockSurface(Surface);
+
+    Result := true;
+  finally
+    Log.LogError('Could not write file: "' + FileName.ToNative + '"', 'WriteBMPImage');
+  end;
+
+  if (Converted) then
+    SDL_FreeSurface(Surface);
+
+  // close file
+  bmpFile.Free;
+end;
+
+{$ENDIF}
+
+(***************************
+ * JPG section
+ *****************************)
+
+{$IFDEF HaveJPG}
+
+function WriteJPGImage(const FileName: IPath; Surface: PSDL_Surface; Quality: integer): boolean;
+var
+  {$IFDEF Delphi}
+  Bitmap:     TBitmap;
+  BitmapInfo: TBitmapInfo;
+  Jpeg:       TJpegImage;
+  row:        integer;
+  FileStream: TBinaryFileStream;
+  {$ELSE}
+  cinfo:     jpeg_compress_struct;
+  jerr :     jpeg_error_mgr;
+  jpgFile:   TBinaryFileStream;
+  rowPtr:    array[0..0] of JSAMPROW;
+  {$ENDIF}
+  converted:  boolean;
+begin
+  Result := false;
+
+  {$IFDEF Delphi}
+    // only 24bit (BGR) data is supported, so convert to it
+    if (IsBGRSurface(Surface.format)) then
+      converted := false
+    else
+    begin
+      Surface := SDL_ConvertSurface(Surface, @PixelFmt_BGR, SDL_SWSURFACE);
+      converted := true;
+    end;
+
+    // create and setup bitmap
+    Bitmap := TBitmap.Create;
+    Bitmap.PixelFormat := pf24bit;
+    Bitmap.Width  := Surface.w;
+    Bitmap.Height := Surface.h;
+
+    // setup bitmap info on source image (Surface parameter)
+    ZeroMemory(@BitmapInfo, SizeOf(BitmapInfo));
+    with BitmapInfo.bmiHeader do
+    begin
+      biSize := SizeOf(BITMAPINFOHEADER);
+      biWidth  := Surface.w;
+      biHeight := Surface.h;
+      biPlanes := 1;
+      biBitCount := 24;
+      biCompression := BI_RGB;
+    end;
+
+    if (SDL_MUSTLOCK(Surface)) then
+      SDL_LockSurface(Surface);
+
+    // use fast Win32-API functions to copy data instead of Bitmap.Canvas.Pixels
+    if (Surface.pitch mod 4 = 0) then
+    begin
+      // if the image is aligned (to a 4-byte boundary) -> copy all data at once
+      // Note: surfaces created with SDL (e.g. with SDL_ConvertSurface) are aligned
+      SetDIBits(0, Bitmap.Handle, 0, Bitmap.Height, Surface.pixels, BitmapInfo, DIB_RGB_COLORS);
+    end
+    else
+    begin
+      // wrong alignment -> copy each line separately.
+      // Note: for the last line unassigned memory (> last Surface.pixels element)
+      //   will be copied to the padding area (last bytes of a row),
+      //   but we do not care because the content of padding data is ignored anyhow.
+      for row := 0 to Surface.h do
+      begin
+        SetDIBits(0, Bitmap.Handle, row, 1, @PChar(Surface.pixels)[row * Surface.pitch],
+          BitmapInfo, DIB_RGB_COLORS);
+      end;
+    end;
+
+    if (SDL_MUSTLOCK(Surface)) then
+      SDL_UnlockSurface(Surface);
+
+    // assign Bitmap to JPEG and store the latter
+    try
+      // init with nil so Free() will not fail if an exception occurs
+      Jpeg := nil;
+      Bitmap := nil;
+      FileStream := nil;
+
+      try
+        Jpeg := TJPEGImage.Create;
+        Jpeg.Assign(Bitmap);
+
+        // compress image (don't forget this line, otherwise it won't be compressed)
+        Jpeg.CompressionQuality := Quality;
+        Jpeg.Compress();
+
+        // Note: FileStream needed for unicode filename support
+        FileStream := TBinaryFileStream.Create(Filename, fmCreate);
+        Jpeg.SaveToStream(FileStream);
+      finally
+        FileStream.Free;
+        Bitmap.Free;
+        Jpeg.Free;
+      end;
+    except
+      Log.LogError('Could not save file: "' + FileName.ToNative + '"', 'WriteJPGImage');
+      Exit;
+    end;
+  {$ELSE}
+    // based on example.pas in FPC's packages/base/pasjpeg directory
+
+    // only 24bit (RGB) data is supported, so convert to it
+    if (IsRGBSurface(Surface.format)) then
+      converted := false
+    else
+    begin
+      Surface := SDL_ConvertSurface(Surface, @PixelFmt_RGB, SDL_SWSURFACE);
+      converted := true;
+    end;
+
+    // allocate and initialize JPEG compression object
+    cinfo.err := jpeg_std_error(jerr);
+    // msg_level that will be displayed. (Nomssi)
+    //jerr.trace_level := 3;
+    // initialize the JPEG compression object
+    jpeg_create_compress(@cinfo);
+
+    // open file for writing
+    try
+      jpgFile := TBinaryFileStream.Create(FileName, fmCreate);
+    except
+      Log.LogError('Could not open file: "' + FileName.ToNative + '"', 'WriteJPGImage');
+      Exit;
+    end;
+
+    // specify data destination
+    jpeg_stdio_dest(@cinfo, @jpgFile);
+
+    // set parameters for compression
+    cinfo.image_width := Surface.w;
+    cinfo.image_height := Surface.h;
+    cinfo.in_color_space := JCS_RGB;
+    cinfo.input_components := 3;
+    cinfo.data_precision := 8;
+
+    // set default compression parameters
+    jpeg_set_defaults(@cinfo);
+    jpeg_set_quality(@cinfo, quality, true);
+
+    // start compressor
+    jpeg_start_compress(@cinfo, true);
+
+    if (SDL_MUSTLOCK(Surface)) then
+      SDL_LockSurface(Surface);
+
+    while (cinfo.next_scanline < cinfo.image_height) do
+    begin
+      // Note: the byte-count of a row is pitch (which is not width*bitsPerPixel if the image is aligned)
+      rowPtr[0] := JSAMPROW(@PChar(Surface.pixels)[(Surface.h-cinfo.next_scanline-1) * Surface.pitch]);
+      jpeg_write_scanlines(@cinfo, JSAMPARRAY(@rowPtr), 1);
+    end;
+
+    if (SDL_MUSTLOCK(Surface)) then
+      SDL_UnlockSurface(Surface);
+
+    // finish compression
+    jpeg_finish_compress(@cinfo);
+    // close the output file
+    jpgFile.Free;
+
+    // release JPEG compression object
+    jpeg_destroy_compress(@cinfo);
+  {$ENDIF}
+
+  if (converted) then
+    SDL_FreeSurface(Surface);
+
+  Result := true;
+end;
+
+{$ENDIF}
+
+(*******************************************************
+ * Image loading
+ *******************************************************)
+
+(*
+ * Loads an image from the given file
+ *)
+function LoadImage(const Filename: IPath): PSDL_Surface;
+var
+  FilenameCaseAdj: IPath;
+  FileStream: TBinaryFileStream;
+  SDLStream: PSDL_RWops;
+begin
+  Result := nil;
+
+  // try to adjust filename's case and check if it exists
+  FilenameCaseAdj := Filename.AdjustCase(false);
+  if (not FilenameCaseAdj.IsFile) then
+  begin
+    Log.LogError('Image-File does not exist "' + FilenameCaseAdj.ToNative + '"', 'LoadImage');
+    Exit;
+  end;
+
+  // load from file
+  try
+    SDLStream := SDLStreamSetup(TBinaryFileStream.Create(FilenameCaseAdj, fmOpenRead));
+    Result := IMG_Load_RW(SDLStream, 1);
+    // Note: TBinaryFileStream is freed by SDLStream. SDLStream by IMG_Load_RW().
+  except
+    Log.LogError('Could not load from file "' + FilenameCaseAdj.ToNative + '"', 'LoadImage');
+    Exit;
+  end;
+end;
+
+(*******************************************************
+ * Image manipulation
+ *******************************************************)
+
+function PixelFormatEquals(fmt1, fmt2: PSDL_PixelFormat): boolean;
+begin
+  Result := 
+    (fmt1^.BitsPerPixel  = fmt2^.BitsPerPixel)  and
+    (fmt1^.BytesPerPixel = fmt2^.BytesPerPixel) and
+    (fmt1^.Rloss = fmt2^.Rloss)   and (fmt1^.Gloss = fmt2^.Gloss)   and (fmt1^.Bloss = fmt2^.Bloss)   and
+    (fmt1^.Rmask = fmt2^.Rmask)   and (fmt1^.Gmask = fmt2^.Gmask)   and (fmt1^.Bmask = fmt2^.Bmask)   and
+    (fmt1^.Rshift = fmt2^.Rshift) and (fmt1^.Gshift = fmt2^.Gshift) and (fmt1^.Bshift = fmt2^.Bshift)
+  ;
+end;
+
+procedure ScaleImage(var ImgSurface: PSDL_Surface; Width, Height: cardinal);
+var
+  TempSurface: PSDL_Surface;
+begin
+  TempSurface := ImgSurface;
+  ImgSurface := SDL_ScaleSurfaceRect(TempSurface,
+                  0, 0, TempSurface^.W,TempSurface^.H,
+                  Width, Height);
+  SDL_FreeSurface(TempSurface);
+end;
+
+procedure FitImage(var ImgSurface: PSDL_Surface; Width, Height: cardinal);
+var
+  TempSurface: PSDL_Surface;
+  ImgFmt: PSDL_PixelFormat;
+begin
+  TempSurface := ImgSurface;
+
+  // create a new surface with given width and height
+  ImgFmt := TempSurface^.format;
+  ImgSurface := SDL_CreateRGBSurface(
+    SDL_SWSURFACE, Width, Height, ImgFmt^.BitsPerPixel,
+    ImgFmt^.RMask, ImgFmt^.GMask, ImgFmt^.BMask, ImgFmt^.AMask);
+
+  // copy image from temp- to new surface
+  SDL_SetAlpha(ImgSurface, 0, 255);
+  SDL_SetAlpha(TempSurface, 0, 255);
+  SDL_BlitSurface(TempSurface, nil, ImgSurface, nil);
+
+  SDL_FreeSurface(TempSurface);
+end;
+
+(*
+// Old slow floating point version of ColorizeTexture.
+// For an easier understanding of the faster fixed point version below.
+procedure ColorizeTexture(TexSurface: PSDL_Surface; Col: cardinal);
+var
+  clr: array[0..2] of double; // [0: R, 1: G, 2: B]
+  hsv: array[0..2] of double; // [0: H(ue), 1: S(aturation), 2: V(alue)]
+  delta, f, p, q, t: double;
+  max: double;
+begin
+  clr[0] := PixelColors[0]/255;
+  clr[1] := PixelColors[1]/255;
+  clr[2] := PixelColors[2]/255;
+  max := maxvalue(clr);
+  delta := max - minvalue(clr);
+
+  hsv[0] := DestinationHue; // set H(ue)
+  hsv[2] := max; // set V(alue)
+  // calc S(aturation)
+  if (max = 0.0) then
+    hsv[1] := 0.0
+  else
+    hsv[1] := delta/max;
+
+  //ColorizePixel(PByteArray(Pixel), DestinationHue);
+  h_int := trunc(hsv[0]);             // h_int = |_h_|
+  f := hsv[0]-h_int;                  // f = h-h_int
+  p := hsv[2]*(1.0-hsv[1]);           // p = v*(1-s)
+  q := hsv[2]*(1.0-(hsv[1]*f));       // q = v*(1-s*f)
+  t := hsv[2]*(1.0-(hsv[1]*(1.0-f))); // t = v*(1-s*(1-f))
+  case h_int of
+    0: begin clr[0] := hsv[2]; clr[1] := t;      clr[2] := p;      end; // (v,t,p)
+    1: begin clr[0] := q;      clr[1] := hsv[2]; clr[2] := p;      end; // (q,v,p)
+    2: begin clr[0] := p;      clr[1] := hsv[2]; clr[2] := t;      end; // (p,v,t)
+    3: begin clr[0] := p;      clr[1] := q;      clr[2] := hsv[2]; end; // (p,q,v)
+    4: begin clr[0] := t;      clr[1] := p;      clr[2] := hsv[2]; end; // (t,p,v)
+    5: begin clr[0] := hsv[2]; clr[1] := p;      clr[2] := q;      end; // (v,p,q)
+  end;
+
+  // and store new rgb back into the image
+  PixelColors[0] := trunc(255*clr[0]);
+  PixelColors[1] := trunc(255*clr[1]);
+  PixelColors[2] := trunc(255*clr[2]);
+end;
+*)
+
+procedure ColorizeImage(ImgSurface: PSDL_Surface; NewColor: longword);
+
+  // First, the rgb colors are converted to hsv, second hue is replaced by
+  // the NewColor, saturation and value remain unchanged, finally this
+  // hsv color is converted back to rgb space.
+  // For the conversion algorithms of colors from rgb to hsv space
+  // and back simply check the wikipedia.
+  // In order to speed up starting time of USDX the division of reals is 
+  // replaced by division of longints, shifted by 10 bits to keep 
+  // digits.
+
+  // The use of longwards leeds to some type size mismatch warnings
+  // whenever differences are formed.
+  // This should not be a problem, since the results should all be positive.
+  // replacing longword by longint would probably resolve this cosmetic fault :-)
+
+  function ColorToHue(const Color: longword): longword;
+  // returns hue within the range [0.0-6.0] but shl 10, ie. times 1024
+  var
+    Red, Green, Blue: longint;
+    Min, Max, Delta:  longint;
+    Hue: double;
+  begin
+    // extract the colors
+    // division by 255 is omitted, since it is implicitly done
+    // when deviding by delta
+    Red   := ((Color and $ff0000) shr 16); // R
+    Green := ((Color and   $ff00) shr  8); // G
+    Blue  :=  (Color and     $ff)        ; // B
+
+    Min := Red;
+    if Green < Min then Min := Green;
+    if Blue  < Min then Min := Blue;
+
+    Max := Red;
+    if Green > Max then Max := Green;
+    if Blue  > Max then Max := Blue;
+
+    // calc hue
+    Delta := Max - Min;     // This gives a type size mismatch warning, because Delta is longword, ie. >= 0
+                            // But the assignments above are easy enough to be sure, that Max - Min is >= 0.
+    if (Delta = 0) then
+      Result := 0
+    else
+    begin
+      // The division by Delta is done separately afterwards.
+      // Necessary because Delphi did not do the type conversion from
+      // longword to double as expected.
+      // After the change to longint, we may not need it, but left for now
+      // Something to check
+      if      (Max = Red  ) then Hue :=             Green - Blue
+      else if (Max = Green) then Hue := 2.0*Delta + Blue  - Red
+      else if (Max = Blue ) then Hue := 4.0*Delta + Red   - Green;
+      Hue := Hue / Delta;
+      if (Hue < 0.0) then
+        Hue := Hue + 6.0;
+      Result := trunc(Hue*1024);           // '*1024' is shl 10
+ //     if NewColor = $000000 then
+ //       Log.LogError ('Hue: ' +  FloatToStr(Hue), 'ColorToHue');
+    end;
+  end;
+
+var
+  PixelIndex: longword;
+  Pixel: PByte;
+  PixelColors: PByteArray;
+  Red, Green, Blue: longword;
+  Hue, Sat: longword;
+  Min, Max, Delta: longword;
+  HueInteger: longword;
+  f, p, q, t: longword;
+  GreyReal: real;
+  Grey: byte;
+begin
+
+  Pixel := ImgSurface^.Pixels;
+
+  // check of the size of a pixel in bytes.
+  // It should be always 4, but this
+  // additional safeguard will show,
+  // whether something went wrong up to here.
+
+  if ImgSurface^.format.BytesPerPixel <> 4 then
+    Log.LogError ('ColorizeImage: The pixel size should be 4, but it is '
+                   + IntToStr(ImgSurface^.format.BytesPerPixel));
+
+  // Check whether the new color is white, grey or black, 
+  // because a greyscale must be created in a different
+  // way.
+  
+  Red   := ((NewColor and $ff0000) shr 16); // R
+  Green := ((NewColor and   $ff00) shr  8); // G
+  Blue  :=  (NewColor and     $ff)        ; // B
+  
+  if (Red = Green) and (Green = Blue) then // greyscale image
+  begin
+    // According to these recommendations (ITU-R BT.709-5)
+    // the conversion parameters for rgb to greyscale are
+    // 0.299, 0.587, 0.114
+    for PixelIndex := 0 to (ImgSurface^.W * ImgSurface^.H)-1 do
+    begin
+      PixelColors := PByteArray(Pixel);
+      {$IFDEF FPC_BIG_ENDIAN}
+      GreyReal := 0.299*PixelColors[3] + 0.587*PixelColors[2] + 0.114*PixelColors[1];
+      //       PixelColors[0] is alpha and remains untouched
+      {$ELSE}
+      GreyReal := 0.299*PixelColors[0] + 0.587*PixelColors[1] + 0.114*PixelColors[2];
+      //       PixelColors[3] is alpha and remains untouched
+      {$ENDIF}
+      Grey := round(GreyReal);
+      {$IFDEF FPC_BIG_ENDIAN}
+      PixelColors[3] := Grey;
+      PixelColors[2] := Grey;
+      PixelColors[1] := Grey;
+      //       PixelColors[0] is alpha and remains untouched
+      {$ELSE}
+      PixelColors[0] := Grey;
+      PixelColors[1] := Grey;
+      PixelColors[2] := Grey;
+      //       PixelColors[3] is alpha and remains untouched
+      {$ENDIF}
+      Inc(Pixel, ImgSurface^.format.BytesPerPixel);
+    end;
+    exit; // we are done with a greyscale image.
+  end;
+
+  Hue := ColorToHue(NewColor);   // Hue is shl 10
+  f   := Hue and $3ff;           // f is the dezimal part of hue
+  HueInteger := Hue shr 10;
+
+  for PixelIndex := 0 to (ImgSurface^.W * ImgSurface^.H)-1 do
+  begin
+    PixelColors := PByteArray(Pixel);
+    // inlined colorize per pixel
+
+    // uses fixed point math
+    // shl 10 is used for divisions
+
+    // get color values
+
+    {$IFDEF FPC_BIG_ENDIAN}
+    Red   := PixelColors[3];
+    Green := PixelColors[2];
+    Blue  := PixelColors[1];
+    //       PixelColors[0] is alpha and remains untouched
+    {$ELSE}
+    Red   := PixelColors[0];
+    Green := PixelColors[1];
+    Blue  := PixelColors[2];
+    //       PixelColors[3] is alpha and remains untouched
+    {$ENDIF}
+
+    //calculate luminance and saturation from rgb
+
+    Max := Red;
+    if Green > Max then Max := Green;
+    if Blue  > Max then Max := Blue ;
+
+    if (Max = 0) then               // the color is black
+    begin
+      {$IFDEF FPC_BIG_ENDIAN}
+      PixelColors[3] := 0;
+      PixelColors[2] := 0;
+      PixelColors[1] := 0;
+      {$ELSE}
+      PixelColors[0] := 0;
+      PixelColors[1] := 0;
+      PixelColors[2] := 0;
+      {$ENDIF}
+    end
+    else
+    begin
+      Min := Red;
+      if Green < Min then Min := Green;
+      if Blue  < Min then Min := Blue ;
+
+      if (Min = 255) then           // the color is white
+      begin
+        {$IFDEF FPC_BIG_ENDIAN}
+        PixelColors[3] := 255;
+        PixelColors[2] := 255;
+        PixelColors[1] := 255;
+        {$ELSE}
+        PixelColors[0] := 255;
+        PixelColors[1] := 255;
+        PixelColors[2] := 255;
+        {$ENDIF}
+      end
+      else                          // all colors except black and white
+      begin
+        Delta := Max - Min;         // This gives a type size mismatch warning, because Delta is longword, ie. >= 0
+                                    // But the assignments above are easy enough to be sure, that Max - Min is >= 0.
+        Sat := (Delta shl 10) div Max;  // shl 10
+
+        // shr 10 corrects that Sat and f are shl 10
+        // the resulting p, q and t are unshifted
+
+        p := (Max * (1024 -  Sat                     )) shr 10;
+        q := (Max * (1024 - (Sat *  f        ) shr 10)) shr 10;
+        t := (Max * (1024 - (Sat * (1024 - f)) shr 10)) shr 10;
+
+        // The above 3 lines give type size mismatch warning, but all variables are longword and the ranges should be ok.
+
+        case HueInteger of
+          0: begin Red := Max; Green := t;   Blue := p;   end; // (v,t,p)
+          1: begin Red := q;   Green := Max; Blue := p;   end; // (q,v,p)
+          2: begin Red := p;   Green := Max; Blue := t;   end; // (p,v,t)
+          3: begin Red := p;   Green := q;   Blue := Max; end; // (p,q,v)
+          4: begin Red := t;   Green := p;   Blue := Max; end; // (t,p,v)
+          5: begin Red := Max; Green := p;   Blue := q;   end; // (v,p,q)
+        end;
+
+        {$IFDEF FPC_BIG_ENDIAN}
+        PixelColors[3] := byte(Red);
+        PixelColors[2] := byte(Green);
+        PixelColors[1] := byte(Blue);
+        {$ELSE}
+        PixelColors[0] := byte(Red);
+        PixelColors[1] := byte(Green);
+        PixelColors[2] := byte(Blue);
+        {$ENDIF}
+
+      end;
+    end;
+
+    Inc(Pixel, ImgSurface^.format.BytesPerPixel);
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/base/UIni.pas b/songmanagement/src/base/UIni.pas
new file mode 100644
index 00000000..beb9faa8
--- /dev/null
+++ b/songmanagement/src/base/UIni.pas
@@ -0,0 +1,1232 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UIni;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  IniFiles,
+  SysUtils,
+  UCommon,
+  ULog,
+  UTextEncoding,
+  UFilesystem,
+  UPath;
+
+type
+  {**
+   * TInputDeviceConfig stores the configuration for an input device.
+   * Configurations will be stored in the InputDeviceConfig array.
+   * Note that not all devices listed in InputDeviceConfig are active devices.
+   * Some might be unplugged and hence unavailable.
+   * Available devices are held in TAudioInputProcessor.DeviceList. Each
+   * TAudioInputDevice listed there has a CfgIndex field which is the index to
+   * its configuration in the InputDeviceConfig array.
+   *}
+  PInputDeviceConfig = ^TInputDeviceConfig;
+  TInputDeviceConfig = record
+    Name:               string;  //**< Name of the input device
+    Input:              integer; //**< Index of the input source to use for recording
+    Latency:            integer; //**< Latency in ms, or LATENCY_AUTODETECT for default
+
+    {**
+     * Mapping of recording channels to players, e.g. ChannelToPlayerMap[0] = 2
+     * maps the channel 0 (left) to player 2.
+     * A player index of 0 (CHANNEL_OFF) means that the channel is not assigned
+     * to any player (the channel is off).
+     *}
+    ChannelToPlayerMap: array of integer;
+  end;
+
+{* Constants for TInputDeviceConfig *}
+const
+  CHANNEL_OFF = 0;         // for field ChannelToPlayerMap
+  LATENCY_AUTODETECT = -1; // for field Latency
+
+type
+
+//Options
+
+  TVisualizerOption      = (voOff, voWhenNoVideo, voOn);
+  TBackgroundMusicOption = (bmoOff, bmoOn);
+  TIni = class
+    private
+      function ExtractKeyIndex(const Key, Prefix, Suffix: string): integer;
+      function GetMaxKeyIndex(Keys: TStringList; const Prefix, Suffix: string): integer;
+      function ReadArrayIndex(const SearchArray: array of UTF8String; IniFile: TCustomIniFile;
+          IniSection: string; IniProperty: string; Default: integer): integer;
+
+      procedure TranslateOptionValues;
+      procedure LoadInputDeviceCfg(IniFile: TMemIniFile);
+      procedure SaveInputDeviceCfg(IniFile: TIniFile);
+      procedure LoadThemes(IniFile: TCustomIniFile);
+
+      procedure LoadPaths(IniFile: TCustomIniFile);
+      procedure LoadScreenModes(IniFile: TCustomIniFile);
+
+    public
+      Name:           array[0..11] of UTF8String;
+
+      // Templates for Names Mod
+      NameTeam:       array[0..2] of UTF8String;
+      NameTemplate:   array[0..11] of UTF8String;
+
+      //Filename of the opened iniFile
+      Filename:       IPath;
+
+      // Game
+      Players:        integer;
+      Difficulty:     integer;
+      Language:       integer;
+      Tabs:           integer;
+      TabsAtStartup:  integer; //Tabs at Startup fix
+      Sorting:        integer;
+      Debug:          integer;
+
+      // Graphics
+      Screens:        integer;
+      Resolution:     integer;
+      Depth:          integer;
+      VisualizerOption: integer;
+      FullScreen:     integer;
+      TextureSize:    integer;
+      SingWindow:     integer;
+      Oscilloscope:   integer;
+      Spectrum:       integer;
+      Spectrograph:   integer;
+      MovieSize:      integer;
+      VideoPreview:   integer;
+      VideoEnabled:   integer;
+
+      // Sound
+      MicBoost:       integer;
+      ClickAssist:    integer;
+      BeatClick:      integer;
+      SavePlayback:   integer;
+      ThresholdIndex: integer;
+      AudioOutputBufferSizeIndex: integer;
+      VoicePassthrough: integer;
+
+      SyncTo: integer;
+
+      //Song Preview
+      PreviewVolume:  integer;
+      PreviewFading:  integer;
+
+      // Lyrics
+      LyricsFont:     integer;
+      LyricsEffect:   integer;
+      NoteLines:      integer;
+
+      // Themes
+      Theme:          integer;
+      SkinNo:         integer;
+      Color:          integer;
+      BackgroundMusicOption: integer;
+
+      // Record
+      InputDeviceConfig: array of TInputDeviceConfig;
+
+      // Advanced
+      LoadAnimation:  integer;
+      EffectSing:     integer;
+      ScreenFade:     integer;
+      AskBeforeDel:   integer;
+      OnSongClick:    integer;
+      LineBonus:      integer;
+      PartyPopup:     integer;
+
+      // Controller
+      Joypad:         integer;
+      Mouse:          integer;
+
+      // default encoding for texts (lyrics, song-name, ...)
+      DefaultEncoding: TEncoding;
+
+      procedure Load();
+      procedure Save();
+      procedure SaveNames;
+      procedure SaveLevel;
+  end;
+
+var
+  Ini:         TIni;
+  IResolution: TUTF8StringDynArray;
+  ILanguage:   TUTF8StringDynArray;
+  ITheme:      TUTF8StringDynArray;
+  ISkin:       TUTF8StringDynArray;
+
+{*
+ * Options
+ *}
+
+const
+  IPlayers:     array[0..4] of UTF8String = ('1', '2', '3', '4', '6');
+  IPlayersVals: array[0..4] of integer    = ( 1 ,  2 ,  3 ,  4 ,  6 );
+
+  IDifficulty:  array[0..2] of UTF8String = ('Easy', 'Medium', 'Hard');
+  ITabs:        array[0..1] of UTF8String = ('Off', 'On');
+
+const
+  ISorting:     array[0..6] of UTF8String = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Artist2');
+type
+  TSortingType = (sEdition, sGenre, sLanguage, sFolder, sTitle, sArtist, sArtist2);
+
+const  
+  IDebug:            array[0..1] of UTF8String  = ('Off', 'On');
+
+  IScreens:          array[0..1] of UTF8String  = ('1', '2');
+  IFullScreen:       array[0..1] of UTF8String  = ('Off', 'On');
+  IDepth:            array[0..1] of UTF8String  = ('16 bit', '32 bit');
+  IVisualizer:       array[0..2] of UTF8String  = ('Off', 'WhenNoVideo','On');
+
+  IBackgroundMusic:  array[0..1] of UTF8String  = ('Off', 'On');
+
+  ITextureSize:      array[0..3] of UTF8String  = ('64', '128', '256', '512');
+  ITextureSizeVals:  array[0..3] of integer     = ( 64,   128,   256,   512);
+
+  ISingWindow:       array[0..1] of UTF8String  = ('Small', 'Big');
+
+  //SingBar Mod
+  IOscilloscope:     array[0..1] of UTF8String  = ('Off', 'On');
+
+  ISpectrum:         array[0..1] of UTF8String  = ('Off', 'On');
+  ISpectrograph:     array[0..1] of UTF8String  = ('Off', 'On');
+  IMovieSize:        array[0..2] of UTF8String  = ('Half', 'Full [Vid]', 'Full [BG+Vid]');
+  IVideoPreview:     array[0..1] of UTF8String  = ('Off', 'On');
+  IVideoEnabled:     array[0..1] of UTF8String  = ('Off', 'On');
+
+  IClickAssist:      array[0..1] of UTF8String  = ('Off', 'On');
+  IBeatClick:        array[0..1] of UTF8String  = ('Off', 'On');
+  ISavePlayback:     array[0..1] of UTF8String  = ('Off', 'On');
+
+  IThreshold:        array[0..3] of UTF8String  = ('5%', '10%', '15%', '20%');
+  IThresholdVals:    array[0..3] of single  = (0.05, 0.10,  0.15,  0.20);
+
+  IVoicePassthrough: array[0..1] of UTF8String  = ('Off', 'On');
+
+const
+  ISyncTo: array[0..2] of UTF8String  = ('Music', 'Lyrics', 'Off');
+type
+  TSyncToType = (stMusic, stLyrics, stOff);
+
+const  
+  IAudioOutputBufferSize:     array[0..9] of UTF8String  = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
+  IAudioOutputBufferSizeVals: array[0..9] of integer     = ( 0,      256,   512 ,  1024 ,  2048 ,  4096 ,  8192 ,  16384 ,  32768 ,  65536 );
+
+  IAudioInputBufferSize:      array[0..9] of UTF8String  = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
+  IAudioInputBufferSizeVals:  array[0..9] of integer     = ( 0,      256,   512 ,  1024 ,  2048 ,  4096 ,  8192 ,  16384 ,  32768 ,  65536 );
+
+  //Song Preview
+  IPreviewVolume:             array[0..10] of UTF8String = ('Off', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%');
+  IPreviewVolumeVals:         array[0..10] of single     = ( 0,   0.10,  0.20,  0.30,  0.40,  0.50,  0.60,  0.70,  0.80,  0.90,   1.00  );
+
+  IPreviewFading:             array[0..5] of UTF8String  = ('Off', '1 Sec', '2 Secs', '3 Secs', '4 Secs', '5 Secs');
+  IPreviewFadingVals:         array[0..5] of integer     = ( 0,     1,       2,        3,        4,        5      );
+
+  ILyricsFont:    array[0..2] of UTF8String = ('Plain', 'OLine1', 'OLine2');
+  ILyricsEffect:  array[0..4] of UTF8String = ('Simple', 'Zoom', 'Slide', 'Ball', 'Shift');
+  INoteLines:     array[0..1] of UTF8String = ('Off', 'On');
+
+  IColor:         array[0..8] of UTF8String = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black');
+
+  // Advanced
+  ILoadAnimation: array[0..1] of UTF8String = ('Off', 'On');
+  IEffectSing:    array[0..1] of UTF8String = ('Off', 'On');
+  IScreenFade:    array[0..1] of UTF8String = ('Off', 'On');
+  IAskbeforeDel:  array[0..1] of UTF8String = ('Off', 'On');
+  IOnSongClick:   array[0..2] of UTF8String = ('Sing', 'Select Players', 'Open Menu');
+  sStartSing = 0;
+  sSelectPlayer = 1;
+  sOpenMenu = 2;
+
+  ILineBonus:     array[0..1] of UTF8String = ('Off', 'On');
+  IPartyPopup:    array[0..1] of UTF8String = ('Off', 'On');
+
+  IJoypad:        array[0..1] of UTF8String = ('Off', 'On');
+  IMouse:         array[0..2] of UTF8String = ('Off', 'Hardware Cursor', 'Software Cursor');
+
+  // Recording options
+  IChannelPlayer: array[0..6] of UTF8String = ('Off', '1', '2', '3', '4', '5', '6');
+  IMicBoost:      array[0..3] of UTF8String = ('Off', '+6dB', '+12dB', '+18dB');
+
+{*
+ * Translated options
+ *}
+
+var
+  ILanguageTranslated:         array of UTF8String;
+
+  IDifficultyTranslated:       array[0..2] of UTF8String  = ('Easy', 'Medium', 'Hard');
+  ITabsTranslated:             array[0..1] of UTF8String  = ('Off', 'On');
+
+  ISortingTranslated:          array[0..6] of UTF8String  = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Artist2');
+
+  IDebugTranslated:            array[0..1] of UTF8String  = ('Off', 'On');
+
+  IFullScreenTranslated:       array[0..1] of UTF8String  = ('Off', 'On');
+  IVisualizerTranslated:       array[0..2] of UTF8String  = ('Off', 'WhenNoVideo','On');
+
+  IBackgroundMusicTranslated:  array[0..1] of UTF8String  = ('Off', 'On');
+  ISingWindowTranslated:       array[0..1] of UTF8String  = ('Small', 'Big');
+
+  //SingBar Mod
+  IOscilloscopeTranslated:     array[0..1] of UTF8String  = ('Off', 'On');
+
+  ISpectrumTranslated:         array[0..1] of UTF8String  = ('Off', 'On');
+  ISpectrographTranslated:     array[0..1] of UTF8String  = ('Off', 'On');
+  IMovieSizeTranslated:        array[0..2] of UTF8String  = ('Half', 'Full [Vid]', 'Full [BG+Vid]');
+  IVideoPreviewTranslated:     array[0..1] of UTF8String  = ('Off', 'On');
+  IVideoEnabledTranslated:     array[0..1] of UTF8String  = ('Off', 'On');
+
+  IClickAssistTranslated:      array[0..1] of UTF8String  = ('Off', 'On');
+  IBeatClickTranslated:        array[0..1] of UTF8String  = ('Off', 'On');
+  ISavePlaybackTranslated:     array[0..1] of UTF8String  = ('Off', 'On');
+
+  IVoicePassthroughTranslated: array[0..1] of UTF8String  = ('Off', 'On');
+
+  ISyncToTranslated:           array[0..2] of UTF8String  = ('Music', 'Lyrics', 'Off');
+
+  //Song Preview
+  IPreviewVolumeTranslated:    array[0..10] of UTF8String = ('Off', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%');
+
+  IAudioOutputBufferSizeTranslated: array[0..9] of UTF8String  = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
+
+  IAudioInputBufferSizeTranslated:  array[0..9] of UTF8String  = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
+
+  IPreviewFadingTranslated:    array[0..5] of UTF8String  = ('Off', '1 Sec', '2 Secs', '3 Secs', '4 Secs', '5 Secs');
+
+  ILyricsFontTranslated:       array[0..2] of UTF8String = ('Plain', 'OLine1', 'OLine2');
+  ILyricsEffectTranslated:     array[0..4] of UTF8String = ('Simple', 'Zoom', 'Slide', 'Ball', 'Shift');
+  INoteLinesTranslated:        array[0..1] of UTF8String = ('Off', 'On');
+
+  IColorTranslated:            array[0..8] of UTF8String = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black');
+
+  // Advanced
+  ILoadAnimationTranslated:    array[0..1] of UTF8String = ('Off', 'On');
+  IEffectSingTranslated:       array[0..1] of UTF8String = ('Off', 'On');
+  IScreenFadeTranslated:       array[0..1] of UTF8String = ('Off', 'On');
+  IAskbeforeDelTranslated:     array[0..1] of UTF8String = ('Off', 'On');
+  IOnSongClickTranslated:      array[0..2] of UTF8String = ('Sing', 'Select Players', 'Open Menu');
+  ILineBonusTranslated:        array[0..1] of UTF8String = ('Off', 'On');
+  IPartyPopupTranslated:       array[0..1] of UTF8String = ('Off', 'On');
+
+  IJoypadTranslated:           array[0..1] of UTF8String = ('Off', 'On');
+  IMouseTranslated:            array[0..2] of UTF8String = ('Off', 'Hardware Cursor', 'Software Cursor');
+
+  // Recording options
+  IChannelPlayerTranslated:    array[0..6] of UTF8String = ('Off', '1', '2', '3', '4', '5', '6');
+  IMicBoostTranslated:         array[0..3] of UTF8String = ('Off', '+6dB', '+12dB', '+18dB');
+
+implementation
+
+uses
+  StrUtils,
+  SDL,
+  UCommandLine,
+  ULanguage,
+  UPlatform,
+  UMain,
+  URecord,
+  USkins,
+  UThemes,
+  UPathUtils,
+  UUnicodeUtils;
+
+(**
+ * Translate and set the values of options, which need translation. 
+ *)
+procedure TIni.TranslateOptionValues;
+var
+  I: integer;
+begin
+  // Load Languagefile
+  if (Params.Language <> -1) then
+    ULanguage.Language.ChangeLanguage(ILanguage[Params.Language])
+  else
+    ULanguage.Language.ChangeLanguage(ILanguage[Ini.Language]);
+
+  SetLength(ILanguageTranslated, Length(ILanguage));
+  for I := 0 to High(ILanguage) do
+  begin
+    ILanguageTranslated[I] := ULanguage.Language.Translate(
+      'OPTION_VALUE_' + UpperCase(ILanguage[I])
+    );
+  end;
+
+  IDifficultyTranslated[0]            := ULanguage.Language.Translate('OPTION_VALUE_EASY');
+  IDifficultyTranslated[1]            := ULanguage.Language.Translate('OPTION_VALUE_MEDIUM');
+  IDifficultyTranslated[2]            := ULanguage.Language.Translate('OPTION_VALUE_HARD');
+
+  ITabsTranslated[0]                  := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  ITabsTranslated[1]                  := ULanguage.Language.Translate('OPTION_VALUE_ON');
+  
+  ISortingTranslated[0]               := ULanguage.Language.Translate('OPTION_VALUE_EDITION');
+  ISortingTranslated[1]               := ULanguage.Language.Translate('OPTION_VALUE_GENRE');
+  ISortingTranslated[2]               := ULanguage.Language.Translate('OPTION_VALUE_LANGUAGE');
+  ISortingTranslated[3]               := ULanguage.Language.Translate('OPTION_VALUE_FOLDER');
+  ISortingTranslated[4]               := ULanguage.Language.Translate('OPTION_VALUE_TITLE');
+  ISortingTranslated[5]               := ULanguage.Language.Translate('OPTION_VALUE_ARTIST');
+  ISortingTranslated[6]               := ULanguage.Language.Translate('OPTION_VALUE_ARTIST2');
+
+  IDebugTranslated[0]                 := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IDebugTranslated[1]                 := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IFullScreenTranslated[0]            := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IFullScreenTranslated[1]            := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IVisualizerTranslated[0]            := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IVisualizerTranslated[1]            := ULanguage.Language.Translate('OPTION_VALUE_WHENNOVIDEO');
+  IVisualizerTranslated[2]            := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IBackgroundMusicTranslated[0]       := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IBackgroundMusicTranslated[1]       := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  ISingWindowTranslated[0]            := ULanguage.Language.Translate('OPTION_VALUE_SMALL');
+  ISingWindowTranslated[1]            := ULanguage.Language.Translate('OPTION_VALUE_BIG');
+
+  IOscilloscopeTranslated[0]          := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IOscilloscopeTranslated[1]          := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  ISpectrumTranslated[0]              := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  ISpectrumTranslated[1]              := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  ISpectrographTranslated[0]          := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  ISpectrographTranslated[1]          := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IMovieSizeTranslated[0]             := ULanguage.Language.Translate('OPTION_VALUE_HALF');
+  IMovieSizeTranslated[1]             := ULanguage.Language.Translate('OPTION_VALUE_FULL_VID');
+  IMovieSizeTranslated[2]             := ULanguage.Language.Translate('OPTION_VALUE_FULL_VID_BG');
+
+  IVideoPreviewTranslated[0]          := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IVideoPreviewTranslated[1]          := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IVideoEnabledTranslated[0]          := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IVideoEnabledTranslated[1]          := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IClickAssistTranslated[0]           := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IClickAssistTranslated[1]           := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IBeatClickTranslated[0]             := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IBeatClickTranslated[1]             := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  ISavePlaybackTranslated[0]          := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  ISavePlaybackTranslated[1]          := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IVoicePassthroughTranslated[0]      := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IVoicePassthroughTranslated[1]      := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  ISyncToTranslated[Ord(stMusic)]     := ULanguage.Language.Translate('OPTION_VALUE_MUSIC');
+  ISyncToTranslated[Ord(stLyrics)]    := ULanguage.Language.Translate('OPTION_VALUE_LYRICS');
+  ISyncToTranslated[Ord(stOff)]       := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+
+  ILyricsFontTranslated[0]            := ULanguage.Language.Translate('OPTION_VALUE_PLAIN');
+  ILyricsFontTranslated[1]            := ULanguage.Language.Translate('OPTION_VALUE_OLINE1');
+  ILyricsFontTranslated[2]            := ULanguage.Language.Translate('OPTION_VALUE_OLINE2');
+
+  ILyricsEffectTranslated[0]          := ULanguage.Language.Translate('OPTION_VALUE_SIMPLE');
+  ILyricsEffectTranslated[1]          := ULanguage.Language.Translate('OPTION_VALUE_ZOOM');
+  ILyricsEffectTranslated[2]          := ULanguage.Language.Translate('OPTION_VALUE_SLIDE');
+  ILyricsEffectTranslated[3]          := ULanguage.Language.Translate('OPTION_VALUE_BALL');
+  ILyricsEffectTranslated[4]          := ULanguage.Language.Translate('OPTION_VALUE_SHIFT');
+
+  INoteLinesTranslated[0]             := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  INoteLinesTranslated[1]             := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IColorTranslated[0]                 := ULanguage.Language.Translate('OPTION_VALUE_BLUE');
+  IColorTranslated[1]                 := ULanguage.Language.Translate('OPTION_VALUE_GREEN');
+  IColorTranslated[2]                 := ULanguage.Language.Translate('OPTION_VALUE_PINK');
+  IColorTranslated[3]                 := ULanguage.Language.Translate('OPTION_VALUE_RED');
+  IColorTranslated[4]                 := ULanguage.Language.Translate('OPTION_VALUE_VIOLET');
+  IColorTranslated[5]                 := ULanguage.Language.Translate('OPTION_VALUE_ORANGE');
+  IColorTranslated[6]                 := ULanguage.Language.Translate('OPTION_VALUE_YELLOW');
+  IColorTranslated[7]                 := ULanguage.Language.Translate('OPTION_VALUE_BROWN');
+  IColorTranslated[8]                 := ULanguage.Language.Translate('OPTION_VALUE_BLACK');
+
+  // Advanced
+  ILoadAnimationTranslated[0]         := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  ILoadAnimationTranslated[1]         := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IEffectSingTranslated[0]            := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IEffectSingTranslated[1]            := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IScreenFadeTranslated[0]            := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IScreenFadeTranslated[1]            := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IAskbeforeDelTranslated[0]          := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IAskbeforeDelTranslated[1]          := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IOnSongClickTranslated[0]           := ULanguage.Language.Translate('OPTION_VALUE_SING');
+  IOnSongClickTranslated[1]           := ULanguage.Language.Translate('OPTION_VALUE_SELECT_PLAYERS');
+  IOnSongClickTranslated[2]           := ULanguage.Language.Translate('OPTION_VALUE_OPEN_MENU');
+
+  ILineBonusTranslated[0]             := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  ILineBonusTranslated[1]             := ULanguage.Language.Translate('OPTION_VALUE_ON');
+ 
+  IPartyPopupTranslated[0]            := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IPartyPopupTranslated[1]            := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IJoypadTranslated[0]                := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IJoypadTranslated[1]                := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+  IMouseTranslated[0]                 := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IMouseTranslated[1]                 := ULanguage.Language.Translate('OPTION_VALUE_HARDWARE_CURSOR');
+  IMouseTranslated[2]                 := ULanguage.Language.Translate('OPTION_VALUE_SOFTWARE_CURSOR');
+
+  IAudioOutputBufferSizeTranslated[0] := ULanguage.Language.Translate('OPTION_VALUE_AUTO');
+  IAudioOutputBufferSizeTranslated[1] := '256';
+  IAudioOutputBufferSizeTranslated[2] := '512';
+  IAudioOutputBufferSizeTranslated[3] := '1024';
+  IAudioOutputBufferSizeTranslated[4] := '2048';
+  IAudioOutputBufferSizeTranslated[5] := '4096';
+  IAudioOutputBufferSizeTranslated[6] := '8192';
+  IAudioOutputBufferSizeTranslated[7] := '16384';
+  IAudioOutputBufferSizeTranslated[8] := '32768';
+  IAudioOutputBufferSizeTranslated[9] := '65536';
+
+
+  IAudioInputBufferSizeTranslated[0]  := ULanguage.Language.Translate('OPTION_VALUE_AUTO');
+  IAudioInputBufferSizeTranslated[1]  := '256';
+  IAudioInputBufferSizeTranslated[2]  := '512';
+  IAudioInputBufferSizeTranslated[3]  := '1024';
+  IAudioInputBufferSizeTranslated[4]  := '2048';
+  IAudioInputBufferSizeTranslated[5]  := '4096';
+  IAudioInputBufferSizeTranslated[6]  := '8192';
+  IAudioInputBufferSizeTranslated[7]  := '16384';
+  IAudioInputBufferSizeTranslated[8]  := '32768';
+  IAudioInputBufferSizeTranslated[9]  := '65536';
+
+  //Song Preview
+  IPreviewVolumeTranslated[0]         := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IPreviewVolumeTranslated[1]         := '10%';
+  IPreviewVolumeTranslated[2]         := '20%';
+  IPreviewVolumeTranslated[3]         := '30%';
+  IPreviewVolumeTranslated[4]         := '40%';
+  IPreviewVolumeTranslated[5]         := '50%';
+  IPreviewVolumeTranslated[6]         := '60%';
+  IPreviewVolumeTranslated[7]         := '70%';
+  IPreviewVolumeTranslated[8]         := '80%';
+  IPreviewVolumeTranslated[9]         := '90%';
+  IPreviewVolumeTranslated[10]        := '100%';
+
+
+  IPreviewFadingTranslated[0]         :=        ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IPreviewFadingTranslated[1]         := '1 ' + ULanguage.Language.Translate('OPTION_VALUE_SEC');
+  IPreviewFadingTranslated[2]         := '2 ' + ULanguage.Language.Translate('OPTION_VALUE_SECS');
+  IPreviewFadingTranslated[3]         := '3 ' + ULanguage.Language.Translate('OPTION_VALUE_SECS');
+  IPreviewFadingTranslated[4]         := '4 ' + ULanguage.Language.Translate('OPTION_VALUE_SECS');
+  IPreviewFadingTranslated[5]         := '5 ' + ULanguage.Language.Translate('OPTION_VALUE_SECS');
+
+  // Recording options
+  IChannelPlayerTranslated[0]         := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IChannelPlayerTranslated[1]         := '1';
+  IChannelPlayerTranslated[2]         := '2';
+  IChannelPlayerTranslated[3]         := '3';
+  IChannelPlayerTranslated[4]         := '4';
+  IChannelPlayerTranslated[5]         := '5';
+  IChannelPlayerTranslated[6]         := '6';
+
+  IMicBoostTranslated[0]              := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+  IMicBoostTranslated[1]              := '+6dB';
+  IMicBoostTranslated[2]              := '+12dB';
+  IMicBoostTranslated[3]              := '+18dB';
+
+end;
+
+(**
+ * Extracts an index of a key that is surrounded by a Prefix/Suffix pair.
+ * Example: ExtractKeyIndex('MyKey[1]', '[', ']') will return 1.
+ *)
+function TIni.ExtractKeyIndex(const Key, Prefix, Suffix: string): integer;
+var
+  Value: string;
+  Start: integer;
+  PrefixPos, SuffixPos: integer;
+begin
+  Result := -1;
+
+  PrefixPos := Pos(Prefix, Key);
+  if (PrefixPos <= 0) then
+    Exit;
+  SuffixPos := Pos(Suffix, Key);
+  if (SuffixPos <= 0) then
+    Exit;
+
+  Start := PrefixPos + Length(Prefix);
+
+  // copy all between prefix and suffix
+  Value  := Copy(Key, Start, SuffixPos - Start);
+  Result := StrToIntDef(Value, -1);
+end;
+
+(**
+ * Finds the maximum key-index in a key-list.
+ * The indexes of the list are surrounded by Prefix/Suffix,
+ * e.g. MyKey[1] (Prefix='[', Suffix=']')
+ *)
+function TIni.GetMaxKeyIndex(Keys: TStringList; const Prefix, Suffix: string): integer;
+var
+  i:        integer;
+  KeyIndex: integer;
+begin
+  Result := -1;
+
+  for i := 0 to Keys.Count-1 do
+  begin
+    KeyIndex := ExtractKeyIndex(Keys[i], Prefix, Suffix);
+    if (KeyIndex > Result) then
+      Result := KeyIndex;
+  end;
+end;
+
+(**
+ * Reads the property IniSeaction:IniProperty from IniFile and
+ * finds its corresponding index in SearchArray.
+ * If SearchArray does not contain the property value, the default value is
+ * returned.
+ *)
+function TIni.ReadArrayIndex(const SearchArray: array of UTF8String; IniFile: TCustomIniFile;
+    IniSection: string; IniProperty: string; Default: integer): integer;
+var
+  StrValue: string;
+begin
+  StrValue := IniFile.ReadString(IniSection, IniProperty, SearchArray[Default]);
+  Result := GetArrayIndex(SearchArray, StrValue);
+  if (Result = -1) then
+  begin
+    Result := Default;
+  end;
+end;
+
+procedure TIni.LoadInputDeviceCfg(IniFile: TMemIniFile);
+var
+  DeviceCfg:    PInputDeviceConfig;
+  DeviceIndex:  integer;
+  ChannelCount: integer;
+  ChannelIndex: integer;
+  RecordKeys:   TStringList;
+  i:            integer;
+begin
+  RecordKeys := TStringList.Create();
+
+  // read all record-keys for filtering
+  IniFile.ReadSection('Record', RecordKeys);
+
+  SetLength(InputDeviceConfig, 0);
+
+  for i := 0 to RecordKeys.Count-1 do
+  begin
+    // find next device-name
+    DeviceIndex := ExtractKeyIndex(RecordKeys[i], 'DeviceName[', ']');
+    if (DeviceIndex >= 0) then
+    begin
+      if not IniFile.ValueExists('Record', Format('DeviceName[%d]', [DeviceIndex])) then
+        Continue;
+
+      // resize list
+      SetLength(InputDeviceConfig, Length(InputDeviceConfig)+1);
+
+      // read an input device's config.
+      // Note: All devices are appended to the list whether they exist or not.
+      //   Otherwise an external device's config will be lost if it is not
+      //   connected (e.g. singstar mics or USB-Audio devices).
+      DeviceCfg := @InputDeviceConfig[High(InputDeviceConfig)];
+      DeviceCfg.Name := IniFile.ReadString('Record', Format('DeviceName[%d]', [DeviceIndex]), '');
+      DeviceCfg.Input := IniFile.ReadInteger('Record', Format('Input[%d]', [DeviceIndex]), 0);
+      DeviceCfg.Latency := IniFile.ReadInteger('Record', Format('Latency[%d]', [DeviceIndex]), LATENCY_AUTODETECT);
+
+      // find the largest channel-number of the current device in the ini-file
+      ChannelCount := GetMaxKeyIndex(RecordKeys, 'Channel', Format('[%d]', [DeviceIndex]));
+      if (ChannelCount < 0) then
+        ChannelCount := 0;
+
+      SetLength(DeviceCfg.ChannelToPlayerMap, ChannelCount);
+
+      // read channel-to-player mapping for every channel of the current device
+      // or set non-configured channels to no player (=0).
+      for ChannelIndex := 0 to High(DeviceCfg.ChannelToPlayerMap) do
+      begin
+        DeviceCfg.ChannelToPlayerMap[ChannelIndex] :=
+          IniFile.ReadInteger('Record', Format('Channel%d[%d]', [ChannelIndex+1, DeviceIndex]), CHANNEL_OFF);
+      end;
+    end;
+  end;
+
+  RecordKeys.Free();
+
+  // MicBoost
+  MicBoost := GetArrayIndex(IMicBoost, IniFile.ReadString('Record', 'MicBoost', 'Off'));
+  // Threshold
+  ThresholdIndex := GetArrayIndex(IThreshold, IniFile.ReadString('Record', 'Threshold', IThreshold[1]));
+end;
+
+procedure TIni.SaveInputDeviceCfg(IniFile: TIniFile);
+var
+  DeviceIndex:  integer;
+  ChannelIndex: integer;
+begin
+  for DeviceIndex := 0 to High(InputDeviceConfig) do
+  begin
+    // DeviceName and DeviceInput
+    IniFile.WriteString('Record', Format('DeviceName[%d]', [DeviceIndex+1]),
+                        InputDeviceConfig[DeviceIndex].Name);
+    IniFile.WriteInteger('Record', Format('Input[%d]', [DeviceIndex+1]),
+                        InputDeviceConfig[DeviceIndex].Input);
+    IniFile.WriteInteger('Record', Format('Latency[%d]', [DeviceIndex+1]),
+                        InputDeviceConfig[DeviceIndex].Latency);
+
+    // Channel-to-Player Mapping
+    for ChannelIndex := 0 to High(InputDeviceConfig[DeviceIndex].ChannelToPlayerMap) do
+    begin
+      IniFile.WriteInteger('Record',
+                          Format('Channel%d[%d]', [ChannelIndex+1, DeviceIndex+1]),
+                          InputDeviceConfig[DeviceIndex].ChannelToPlayerMap[ChannelIndex]);
+    end;
+  end;
+
+  // MicBoost
+  IniFile.WriteString('Record', 'MicBoost', IMicBoost[MicBoost]);
+  // Threshold
+  IniFile.WriteString('Record', 'Threshold', IThreshold[ThresholdIndex]);
+end;
+
+procedure TIni.LoadPaths(IniFile: TCustomIniFile);
+var
+  PathStrings: TStringList;
+  I:           integer;
+begin
+  PathStrings := TStringList.Create;
+  IniFile.ReadSection('Directories', PathStrings);
+
+  // Load song-paths
+  for I := 0 to PathStrings.Count-1 do
+  begin
+    if (Pos('SONGDIR', UpperCase(PathStrings[I])) = 1) then
+    begin
+      AddSongPath(Path(IniFile.ReadString('Directories', PathStrings[I], '')));
+    end;
+  end;
+
+  PathStrings.Free;
+end;
+
+procedure TIni.LoadThemes(IniFile: TCustomIniFile);
+begin
+  // No Theme Found
+  if (Length(ITheme) = 0) then
+  begin
+    Log.CriticalError('Could not find any valid Themes.');
+  end;
+
+  Theme := GetArrayIndex(ITheme, IniFile.ReadString('Themes', 'Theme', 'DELUXE'), true);
+  if (Theme = -1) then
+    Theme := 0;
+
+  // Skin
+  Skin.onThemeChange;
+
+  SkinNo := GetArrayIndex(ISkin, IniFile.ReadString('Themes',    'Skin',   ISkin[UThemes.Theme.Themes[Theme].DefaultSkin]));
+
+  { there may be a not existing skin in the ini file
+    e.g. due to manual edit or corrupted file.
+    in this case we load the first Skin }
+  if SkinNo = -1 then
+    SkinNo := 0;
+
+  // Color
+  Color := GetArrayIndex(IColor, IniFile.ReadString('Themes',    'Color', IColor[Skin.GetDefaultColor(SkinNo)]));
+end;
+
+procedure TIni.LoadScreenModes(IniFile: TCustomIniFile);
+
+  // swap two strings
+  procedure swap(var s1, s2: UTF8String);
+  var
+    s3: string;
+  begin
+    s3 := s1;
+    s1 := s2;
+    s2 := s3;
+  end;
+
+var
+  Modes: PPSDL_Rect;
+  I:     integer;
+begin
+  // Screens
+  Screens := GetArrayIndex(IScreens, IniFile.ReadString('Graphics', 'Screens', IScreens[0]));
+
+  // FullScreen
+  FullScreen := GetArrayIndex(IFullScreen, IniFile.ReadString('Graphics', 'FullScreen', 'On'));
+
+  // Resolution
+  SetLength(IResolution, 0);
+
+  // Check if there are any modes available
+  // TODO: we should seperate windowed and fullscreen modes. Otherwise it is not
+  // possible to select a reasonable fullscreen mode when in windowed mode
+  if IFullScreen[FullScreen] = 'On' then
+    Modes  := SDL_ListModes(nil, SDL_OPENGL or SDL_FULLSCREEN)
+  else
+    Modes  := SDL_ListModes(nil, SDL_OPENGL or SDL_RESIZABLE) ;
+
+  if (Modes = nil) then
+  begin
+    Log.LogStatus( 'No resolutions Found' , 'Video');
+  end
+  else if (Modes = PPSDL_Rect(-1)) then
+  begin
+    // Fallback to some standard resolutions
+    SetLength(IResolution, 18);
+    IResolution[0] := '640x480';
+    IResolution[1] := '800x600';
+    IResolution[2] := '1024x768';
+    IResolution[3] := '1152x666';;
+    IResolution[4] := '1152x864';
+    IResolution[5] := '1280x800';
+    IResolution[6] := '1280x960';
+    IResolution[7] := '1280x1024';
+    IResolution[8] := '1366x768';
+    IResolution[9] := '1400x1050';
+    IResolution[10] := '1440x900';
+    IResolution[11] := '1600x900';
+    IResolution[12] := '1600x1200';
+    IResolution[13] := '1680x1050';
+    IResolution[14] := '1920x1080';
+    IResolution[15] := '1920x1200';
+    IResolution[16] := '2048x1152';
+    IResolution[17] := '2560x1600';
+
+    Resolution := GetArrayIndex(IResolution, IniFile.ReadString('Graphics', 'Resolution', '800x600'));
+    if Resolution = -1 then
+    begin
+      SetLength(IResolution, Length(IResolution) + 1);
+      IResolution[High(IResolution)] := IniFile.ReadString('Graphics', 'Resolution', '800x600');
+      Resolution := High(IResolution);
+    end;
+  end
+  else
+  begin
+    while assigned( Modes^ ) do //this should solve the biggest wine problem | THANKS Linnex (11.11.07)
+    begin
+      Log.LogStatus( 'Found Video Mode : ' + IntToStr(Modes^.w) + 'x' + IntToStr(Modes^.h) , 'Video');
+      SetLength(IResolution, Length(IResolution) + 1);
+      IResolution[High(IResolution)] := IntToStr(Modes^.w div (Screens+1)) + 'x' + IntToStr(Modes^.h);
+      Inc(Modes);
+    end;
+
+    // reverse order
+    Log.LogStatus( 'Log size of resolution: ' + IntToStr(Length(IResolution)), 'Video');
+    for I := 0 to (Length(IResolution) div 2) - 1 do
+    begin
+      swap(IResolution[I], IResolution[High(IResolution)-I]);
+    end;
+    Resolution := GetArrayIndex(IResolution, IniFile.ReadString('Graphics', 'Resolution', '800x600'));
+
+    if Resolution = -1 then
+    begin
+      Resolution := GetArrayIndex(IResolution, '800x600');
+      if Resolution = -1 then
+        Resolution := 0;
+    end;
+  end;
+
+  // if no modes were set, then failback to 800x600
+  // as per http://sourceforge.net/forum/message.php?msg_id=4544965
+  // THANKS : linnex at users.sourceforge.net
+  if Length(IResolution) < 1 then
+  begin
+    Log.LogStatus( 'Found Video Mode : NONE !!! ( Defaulted to 800 x 600 )', 'Video');
+    SetLength(IResolution, 1);
+    IResolution[0] := '800x600';
+    Resolution := 0;
+    Log.LogStatus('SDL_ListModes Defaulted Res To : ' + IResolution[0] , 'Graphics - Resolutions');
+
+    // Default to fullscreen OFF, in this case !
+    FullScreen := 0;
+  end;
+
+  // Depth
+  Depth := GetArrayIndex(IDepth, IniFile.ReadString('Graphics', 'Depth', '32 bit'));
+end;
+
+procedure TIni.Load();
+var
+  IniFile: TMemIniFile;
+  I:       integer;
+begin
+  GamePath := Platform.GetGameUserPath;
+
+  Log.LogStatus( 'GamePath : ' +GamePath.ToNative , '' );
+
+  if (Params.ConfigFile.IsSet) then
+    FileName := Params.ConfigFile
+  else
+    FileName := GamePath.Append('config.ini');
+
+  Log.LogStatus('Using config : ' + FileName.ToNative, 'Ini');
+  IniFile := TMemIniFile.Create(FileName.ToNative);
+
+  // Name
+  for I := 0 to 11 do
+    Name[I] := IniFile.ReadString('Name', 'P'+IntToStr(I+1), 'Player'+IntToStr(I+1));
+
+  // Templates for Names Mod
+  for I := 0 to 2 do
+    NameTeam[I] := IniFile.ReadString('NameTeam', 'T'+IntToStr(I+1), 'Team'+IntToStr(I+1));
+  for I := 0 to 11 do
+    NameTemplate[I] := IniFile.ReadString('NameTemplate', 'Name'+IntToStr(I+1), 'Template'+IntToStr(I+1));
+
+  // Players
+  Players := GetArrayIndex(IPlayers, IniFile.ReadString('Game', 'Players', IPlayers[0]));
+
+  // Difficulty
+  Difficulty := GetArrayIndex(IDifficulty, IniFile.ReadString('Game', 'Difficulty', 'Easy'));
+
+  // Language
+  Language := GetArrayIndex(ILanguage, IniFile.ReadString('Game', 'Language', 'English'));
+
+  // Tabs
+  Tabs := GetArrayIndex(ITabs, IniFile.ReadString('Game', 'Tabs', ITabs[0]));
+  TabsAtStartup := Tabs;	//Tabs at Startup fix
+
+  // Song Sorting
+  Sorting := GetArrayIndex(ISorting, IniFile.ReadString('Game', 'Sorting', ISorting[Ord(sEdition)]));
+
+  // Debug
+  Debug := GetArrayIndex(IDebug, IniFile.ReadString('Game', 'Debug', IDebug[0]));
+
+  LoadScreenModes(IniFile);
+
+  // TextureSize (aka CachedCoverSize)
+  TextureSize := GetArrayIndex(ITextureSize, IniFile.ReadString('Graphics', 'TextureSize', '256'));
+
+  // SingWindow
+  SingWindow := GetArrayIndex(ISingWindow, IniFile.ReadString('Graphics', 'SingWindow', 'Big'));
+
+  // Oscilloscope
+  Oscilloscope := GetArrayIndex(IOscilloscope, IniFile.ReadString('Graphics', 'Oscilloscope', IOscilloscope[0]));
+
+  // Spectrum
+  Spectrum := GetArrayIndex(ISpectrum, IniFile.ReadString('Graphics', 'Spectrum', 'Off'));
+
+  // Spectrograph
+  Spectrograph := GetArrayIndex(ISpectrograph, IniFile.ReadString('Graphics', 'Spectrograph', 'Off'));
+
+  // MovieSize
+  MovieSize := GetArrayIndex(IMovieSize, IniFile.ReadString('Graphics', 'MovieSize', IMovieSize[2]));
+
+  // VideoPreview
+  VideoPreview := GetArrayIndex(IVideoPreview, IniFile.ReadString('Graphics', 'VideoPreview', IVideoPreview[1]));
+
+  // VideoEnabled
+  VideoEnabled := GetArrayIndex(IVideoEnabled, IniFile.ReadString('Graphics', 'VideoEnabled', IVideoEnabled[1]));
+
+  // ClickAssist
+  ClickAssist := GetArrayIndex(IClickAssist, IniFile.ReadString('Sound', 'ClickAssist', 'Off'));
+
+  // BeatClick
+  BeatClick := GetArrayIndex(IBeatClick, IniFile.ReadString('Sound', 'BeatClick', IBeatClick[0]));
+
+  // SavePlayback
+  SavePlayback := GetArrayIndex(ISavePlayback, IniFile.ReadString('Sound', 'SavePlayback', ISavePlayback[0]));
+
+  // AudioOutputBufferSize
+  AudioOutputBufferSizeIndex := ReadArrayIndex(IAudioOutputBufferSize, IniFile, 'Sound', 'AudioOutputBufferSize', 0);
+
+  //Preview Volume
+  PreviewVolume := GetArrayIndex(IPreviewVolume, IniFile.ReadString('Sound', 'PreviewVolume', IPreviewVolume[7]));
+
+  //Preview Fading
+  PreviewFading := GetArrayIndex(IPreviewFading, IniFile.ReadString('Sound', 'PreviewFading', IPreviewFading[3]));
+
+  //AudioRepeat aka VoicePassthrough
+  VoicePassthrough := GetArrayIndex(IVoicePassthrough, IniFile.ReadString('Sound', 'VoicePassthrough', IVoicePassthrough[0]));
+
+  // Lyrics Font
+  LyricsFont := GetArrayIndex(ILyricsFont, IniFile.ReadString('Lyrics', 'LyricsFont', ILyricsFont[0]));
+
+  // Lyrics Effect
+  LyricsEffect := GetArrayIndex(ILyricsEffect, IniFile.ReadString('Lyrics', 'LyricsEffect', ILyricsEffect[4]));
+
+  // NoteLines
+  NoteLines := GetArrayIndex(INoteLines, IniFile.ReadString('Lyrics', 'NoteLines', INoteLines[1]));
+
+  // DefaultEncoding
+  DefaultEncoding := ParseEncoding(IniFile.ReadString('Lyrics', 'Encoding', ''), encAuto);
+
+  LoadThemes(IniFile);
+
+  LoadInputDeviceCfg(IniFile);
+
+  // LoadAnimation
+  LoadAnimation := GetArrayIndex(ILoadAnimation, IniFile.ReadString('Advanced', 'LoadAnimation', 'On'));
+
+  // ScreenFade
+  ScreenFade := GetArrayIndex(IScreenFade, IniFile.ReadString('Advanced', 'ScreenFade', 'On'));
+
+  // Visualizations
+  // <mog> this could be of use later..
+  //  VisualizerOption :=
+  //    TVisualizerOption(GetEnumValue(TypeInfo(TVisualizerOption),
+  //            IniFile.ReadString('Graphics', 'Visualization', 'Off')));
+  // || VisualizerOption := TVisualizerOption(GetArrayIndex(IVisualizer, IniFile.ReadString('Graphics', 'Visualization', 'Off')));
+  VisualizerOption := GetArrayIndex(IVisualizer, IniFile.ReadString('Graphics', 'Visualization', 'Off'));
+
+{**
+ * Background music
+ *}
+  BackgroundMusicOption := GetArrayIndex(IBackgroundMusic, IniFile.ReadString('Sound', 'BackgroundMusic', 'On'));
+
+  // EffectSing
+  EffectSing := GetArrayIndex(IEffectSing, IniFile.ReadString('Advanced', 'EffectSing', 'On'));
+
+  // AskbeforeDel
+  AskBeforeDel := GetArrayIndex(IAskbeforeDel, IniFile.ReadString('Advanced', 'AskbeforeDel', 'On'));
+
+  // OnSongClick
+  OnSongClick := GetArrayIndex(IOnSongClick, IniFile.ReadString('Advanced', 'OnSongClick', 'Sing'));
+
+  // Linebonus
+  LineBonus := GetArrayIndex(ILineBonus, IniFile.ReadString('Advanced', 'LineBonus', ILineBonus[1]));
+
+  // PartyPopup
+  PartyPopup := GetArrayIndex(IPartyPopup, IniFile.ReadString('Advanced', 'PartyPopup', 'On'));
+
+  // SyncTo
+  SyncTo := GetArrayIndex(ISyncTo, IniFile.ReadString('Advanced', 'SyncTo', ISyncTo[Ord(stMusic)]));
+
+  // Joypad
+  Joypad := GetArrayIndex(IJoypad, IniFile.ReadString('Controller',    'Joypad',   IJoypad[0]));
+
+  // Mouse
+  Mouse := GetArrayIndex(IMouse, IniFile.ReadString('Controller',    'Mouse',   IMouse[2]));
+
+  LoadPaths(IniFile);
+
+  TranslateOptionValues;
+
+  IniFile.Free;
+end;
+
+procedure TIni.Save;
+var
+  IniFile: TIniFile;
+begin
+  if (Filename.IsFile and Filename.IsReadOnly) then
+  begin
+    Log.LogError('Config-file is read-only', 'TIni.Save');
+    Exit;
+  end;
+
+  IniFile := TIniFile.Create(Filename.ToNative);
+
+  // Players
+  IniFile.WriteString('Game', 'Players', IPlayers[Players]);
+
+  // Difficulty
+  IniFile.WriteString('Game', 'Difficulty', IDifficulty[Difficulty]);
+
+  // Language
+  IniFile.WriteString('Game', 'Language', ILanguage[Language]);
+
+  // Tabs
+  IniFile.WriteString('Game', 'Tabs', ITabs[Tabs]);
+
+  // Sorting
+  IniFile.WriteString('Game', 'Sorting', ISorting[Sorting]);
+
+  // Debug
+  IniFile.WriteString('Game', 'Debug', IDebug[Debug]);
+
+  // Screens
+  IniFile.WriteString('Graphics', 'Screens', IScreens[Screens]);
+
+  // FullScreen
+  IniFile.WriteString('Graphics', 'FullScreen', IFullScreen[FullScreen]);
+
+  // Visualization
+  IniFile.WriteString('Graphics', 'Visualization', IVisualizer[VisualizerOption]);
+
+  // Resolution
+  IniFile.WriteString('Graphics', 'Resolution', IResolution[Resolution]);
+
+  // Depth
+  IniFile.WriteString('Graphics', 'Depth', IDepth[Depth]);
+
+  // TextureSize
+  IniFile.WriteString('Graphics', 'TextureSize', ITextureSize[TextureSize]);
+
+  // Sing Window
+  IniFile.WriteString('Graphics', 'SingWindow', ISingWindow[SingWindow]);
+
+  // Oscilloscope
+  IniFile.WriteString('Graphics', 'Oscilloscope', IOscilloscope[Oscilloscope]);
+
+  // Spectrum
+  IniFile.WriteString('Graphics', 'Spectrum', ISpectrum[Spectrum]);
+
+  // Spectrograph
+  IniFile.WriteString('Graphics', 'Spectrograph', ISpectrograph[Spectrograph]);
+
+  // Movie Size
+  IniFile.WriteString('Graphics', 'MovieSize', IMovieSize[MovieSize]);
+
+  // VideoPreview
+  IniFile.WriteString('Graphics', 'VideoPreview', IVideoPreview[VideoPreview]);
+
+  // VideoEnabled
+  IniFile.WriteString('Graphics', 'VideoEnabled', IVideoEnabled[VideoEnabled]);
+
+  // ClickAssist
+  IniFile.WriteString('Sound', 'ClickAssist', IClickAssist[ClickAssist]);
+
+  // BeatClick
+  IniFile.WriteString('Sound', 'BeatClick', IBeatClick[BeatClick]);
+
+  // AudioOutputBufferSize
+  IniFile.WriteString('Sound', 'AudioOutputBufferSize', IAudioOutputBufferSize[AudioOutputBufferSizeIndex]);
+
+  // Background music
+  IniFile.WriteString('Sound', 'BackgroundMusic', IBackgroundMusic[BackgroundMusicOption]);
+
+  // Song Preview
+  IniFile.WriteString('Sound', 'PreviewVolume', IPreviewVolume[PreviewVolume]);
+
+  // PreviewFading
+  IniFile.WriteString('Sound', 'PreviewFading', IPreviewFading[PreviewFading]);
+
+  // SavePlayback
+  IniFile.WriteString('Sound', 'SavePlayback', ISavePlayback[SavePlayback]);
+
+  // VoicePasstrough
+  IniFile.WriteString('Sound', 'VoicePassthrough', IVoicePassthrough[VoicePassthrough]);
+
+  // Lyrics Font
+  IniFile.WriteString('Lyrics', 'LyricsFont', ILyricsFont[LyricsFont]);
+
+  // Lyrics Effect
+  IniFile.WriteString('Lyrics', 'LyricsEffect', ILyricsEffect[LyricsEffect]);
+
+  // NoteLines
+  IniFile.WriteString('Lyrics', 'NoteLines', INoteLines[NoteLines]);
+
+  //Encoding default
+  IniFile.WriteString('Lyrics', 'Encoding', EncodingName(DefaultEncoding));
+
+  // Theme
+  IniFile.WriteString('Themes', 'Theme', ITheme[Theme]);
+
+  // Skin
+  IniFile.WriteString('Themes', 'Skin', ISkin[SkinNo]);
+
+  // Color
+  IniFile.WriteString('Themes', 'Color', IColor[Color]);
+
+  SaveInputDeviceCfg(IniFile);
+
+  //LoadAnimation
+  IniFile.WriteString('Advanced', 'LoadAnimation', ILoadAnimation[LoadAnimation]);
+
+  //EffectSing
+  IniFile.WriteString('Advanced', 'EffectSing', IEffectSing[EffectSing]);
+
+  //ScreenFade
+  IniFile.WriteString('Advanced', 'ScreenFade', IScreenFade[ScreenFade]);
+
+  //AskbeforeDel
+  IniFile.WriteString('Advanced', 'AskbeforeDel', IAskbeforeDel[AskBeforeDel]);
+
+  //OnSongClick
+  IniFile.WriteString('Advanced', 'OnSongClick', IOnSongClick[OnSongClick]);
+
+  //Line Bonus
+  IniFile.WriteString('Advanced', 'LineBonus', ILineBonus[LineBonus]);
+
+  //Party Popup
+  IniFile.WriteString('Advanced', 'PartyPopup', IPartyPopup[PartyPopup]);
+
+  //SyncTo
+  IniFile.WriteString('Advanced', 'SyncTo', ISyncTo[SyncTo]);
+
+  // Joypad
+  IniFile.WriteString('Controller', 'Joypad', IJoypad[Joypad]);
+
+  // Mouse
+  IniFile.WriteString('Controller', 'Mouse', IMouse[Mouse]);
+
+  // Directories (add a template if section is missing)
+  // Note: Value must be ' ' and not '', otherwise no key is generated on Linux
+  if (not IniFile.SectionExists('Directories')) then
+    IniFile.WriteString('Directories', 'SongDir1', ' ');
+
+  IniFile.Free;
+end;
+
+procedure TIni.SaveNames;
+var
+  IniFile: TIniFile;
+  I:       integer;
+begin
+  if not Filename.IsReadOnly() then
+  begin
+    IniFile := TIniFile.Create(Filename.ToNative);
+
+    //Name Templates for Names Mod
+    for I := 0 to High(Name) do
+      IniFile.WriteString('Name', 'P' + IntToStr(I+1), Name[I]);
+    for I := 0 to High(NameTeam) do
+      IniFile.WriteString('NameTeam', 'T' + IntToStr(I+1), NameTeam[I]);
+    for I := 0 to High(NameTemplate) do
+      IniFile.WriteString('NameTemplate', 'Name' + IntToStr(I+1), NameTemplate[I]);
+
+    IniFile.Free;
+  end;
+end;
+
+procedure TIni.SaveLevel;
+var
+  IniFile: TIniFile;
+begin
+  if not Filename.IsReadOnly() then
+  begin
+    IniFile := TIniFile.Create(Filename.ToNative);
+
+    // Difficulty
+    IniFile.WriteString('Game', 'Difficulty', IDifficulty[Difficulty]);
+
+    IniFile.Free;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/base/UJoystick.pas b/songmanagement/src/base/UJoystick.pas
new file mode 100644
index 00000000..30808812
--- /dev/null
+++ b/songmanagement/src/base/UJoystick.pas
@@ -0,0 +1,312 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UJoystick;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL;
+
+type
+  TJoyButton = record
+    State:      integer;
+    Enabled:    boolean;
+    Type_:      byte;
+    Sym:        cardinal;
+  end;
+
+  TJoyHatState = record
+    State:      Boolean;
+    LastTick:   Cardinal;
+    Enabled:    boolean;
+    Type_:      byte;
+    Sym:        cardinal;
+  end;
+
+  TJoyUnit = record
+    Button:   array[0..15] of TJoyButton;
+    HatState: Array[0..3]  of TJoyHatState;
+  end;
+
+  TJoy = class
+    constructor Create;
+    procedure Update;
+  end;
+
+var
+  Joy:        TJoy;
+  JoyUnit:    TJoyUnit;
+  SDL_Joy:    PSDL_Joystick;
+  JoyEvent:   TSDL_Event;
+
+implementation
+
+uses SysUtils,
+     ULog;
+
+constructor TJoy.Create;
+var
+  B: integer;
+  //N: integer;
+begin
+  inherited;
+
+  //Old Corvus5 Method
+  {// joystick support
+  SDL_JoystickEventState(SDL_IGNORE);
+  SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+  if SDL_NumJoysticks <> 1 then
+    Log.LogStatus('Joystick count <> 1', 'TJoy.Create');
+
+  SDL_Joy := SDL_JoystickOpen(0);
+  if SDL_Joy = nil then
+    Log.LogError('SDL_JoystickOpen failed', 'TJoy.Create');
+
+  if SDL_JoystickNumButtons(SDL_Joy) <> 16 then
+    Log.LogStatus('Joystick button count <> 16', 'TJoy.Create');
+
+//  SDL_JoystickEventState(SDL_ENABLE);
+  // Events don't work - thay hang the whole application with SDL_JoystickEventState(SDL_ENABLE)
+
+  // clear states
+  for B := 0 to 15 do
+    JoyUnit.Button[B].State := 1;
+
+  // mapping
+  JoyUnit.Button[1].Enabled := true;
+  JoyUnit.Button[1].Type_ := SDL_KEYDOWN;
+  JoyUnit.Button[1].Sym := SDLK_RETURN;
+  JoyUnit.Button[2].Enabled := true;
+  JoyUnit.Button[2].Type_ := SDL_KEYDOWN;
+  JoyUnit.Button[2].Sym := SDLK_ESCAPE;
+
+  JoyUnit.Button[12].Enabled := true;
+  JoyUnit.Button[12].Type_ := SDL_KEYDOWN;
+  JoyUnit.Button[12].Sym := SDLK_LEFT;
+  JoyUnit.Button[13].Enabled := true;
+  JoyUnit.Button[13].Type_ := SDL_KEYDOWN;
+  JoyUnit.Button[13].Sym := SDLK_DOWN;
+  JoyUnit.Button[14].Enabled := true;
+  JoyUnit.Button[14].Type_ := SDL_KEYDOWN;
+  JoyUnit.Button[14].Sym := SDLK_RIGHT;
+  JoyUnit.Button[15].Enabled := true;
+  JoyUnit.Button[15].Type_ := SDL_KEYDOWN;
+  JoyUnit.Button[15].Sym := SDLK_UP;
+  }
+  //New Sarutas method
+  SDL_JoystickEventState(SDL_IGNORE);
+  SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+  if SDL_NumJoysticks < 1 then
+  begin
+    Log.LogError('No Joystick found');
+    exit;
+  end;
+
+
+  SDL_Joy := SDL_JoystickOpen(0);
+  if SDL_Joy = nil then
+  begin
+    Log.LogError('Could not Init Joystick');
+    exit;
+  end;
+  //N := SDL_JoystickNumButtons(SDL_Joy);
+  //if N < 6 then Log.LogStatus('Joystick button count < 6', 'TJoy.Create');
+
+  for B := 0 to 5 do begin
+    JoyUnit.Button[B].Enabled := true;
+    JoyUnit.Button[B].State := 1;
+    JoyUnit.Button[B].Type_ := SDL_KEYDOWN;
+  end;
+
+  JoyUnit.Button[0].Sym := SDLK_Return;
+  JoyUnit.Button[1].Sym := SDLK_Escape;
+  JoyUnit.Button[2].Sym := SDLK_M;
+  JoyUnit.Button[3].Sym := SDLK_R;
+
+  JoyUnit.Button[4].Sym := SDLK_RETURN;
+  JoyUnit.Button[5].Sym := SDLK_ESCAPE;
+
+  //Set HatState
+  for B := 0 to 3 do begin
+    JoyUnit.HatState[B].Enabled := true;
+    JoyUnit.HatState[B].State := False;
+    JoyUnit.HatState[B].Type_ := SDL_KEYDOWN;
+  end;
+
+  JoyUnit.HatState[0].Sym := SDLK_UP;
+  JoyUnit.HatState[1].Sym := SDLK_RIGHT;
+  JoyUnit.HatState[2].Sym := SDLK_DOWN;
+  JoyUnit.HatState[3].Sym := SDLK_LEFT;
+end;
+
+procedure TJoy.Update;
+var
+  B:      integer;
+  State:  UInt8;
+  Tick:   Cardinal;
+  Axes:   Smallint;
+begin
+  SDL_JoystickUpdate;
+
+  //Manage Buttons
+  for B := 0 to 15 do begin
+    if (JoyUnit.Button[B].Enabled) and (JoyUnit.Button[B].State <> SDL_JoystickGetButton(SDL_Joy, B)) and (JoyUnit.Button[B].State = 0) then begin
+      JoyEvent.type_ := JoyUnit.Button[B].Type_;
+      JoyEvent.key.keysym.sym := JoyUnit.Button[B].Sym;
+      SDL_PushEvent(@JoyEvent);
+    end;
+  end;
+
+
+  for B := 0 to 15 do begin
+    JoyUnit.Button[B].State := SDL_JoystickGetButton(SDL_Joy, B);
+  end;
+
+  //Get Tick
+  Tick := SDL_GetTicks();
+
+  //Get CoolieHat
+  if (SDL_JoystickNumHats(SDL_Joy)>=1) then
+    State := SDL_JoystickGetHat(SDL_Joy, 0)
+  else
+    State := 0;
+
+  //Get Axis  
+  if (SDL_JoystickNumAxes(SDL_Joy)>=2) then
+  begin
+    //Down - Up (X- Axis)
+    Axes := SDL_JoystickGetAxis(SDL_Joy, 1);
+    If Axes >= 15000 then
+      State := State or SDL_HAT_Down
+    Else If Axes <= -15000 then
+      State := State or SDL_HAT_UP;
+
+    //Left - Right (Y- Axis)
+    Axes := SDL_JoystickGetAxis(SDL_Joy, 0);
+    If Axes >= 15000 then
+      State := State or SDL_HAT_Right
+    Else If Axes <= -15000 then
+      State := State or SDL_HAT_Left;
+  end;
+
+  //Manage Hat and joystick Events
+  if (SDL_JoystickNumHats(SDL_Joy)>=1) OR (SDL_JoystickNumAxes(SDL_Joy)>=2) then
+  begin
+
+    //Up Button
+    If (JoyUnit.HatState[0].Enabled) and ((SDL_HAT_UP AND State) = SDL_HAT_UP) then
+    begin //IF Button is newly Pressed or if he is Pressed longer than 500 msecs
+      if (JoyUnit.HatState[0].State = False) OR (JoyUnit.HatState[0].Lasttick < Tick) then
+      begin
+        //Set Tick and State
+        if JoyUnit.HatState[0].State then
+          JoyUnit.HatState[0].Lasttick := Tick + 200
+        else
+          JoyUnit.HatState[0].Lasttick := Tick + 500;
+
+        JoyUnit.HatState[0].State := True;
+
+        JoyEvent.type_ := JoyUnit.HatState[0].Type_;
+        JoyEvent.key.keysym.sym := JoyUnit.HatState[0].Sym;
+        SDL_PushEvent(@JoyEvent);
+      end;
+    end
+    else
+      JoyUnit.HatState[0].State := False;
+
+    //Right Button
+    If (JoyUnit.HatState[1].Enabled) and ((SDL_HAT_RIGHT AND State) = SDL_HAT_RIGHT) then
+    begin //IF Button is newly Pressed or if he is Pressed longer than 500 msecs
+      if (JoyUnit.HatState[1].State = False) OR (JoyUnit.HatState[1].Lasttick < Tick) then
+      begin
+        //Set Tick and State
+        if JoyUnit.HatState[1].State then
+          JoyUnit.HatState[1].Lasttick := Tick + 200
+        else
+          JoyUnit.HatState[1].Lasttick := Tick + 500;
+
+        JoyUnit.HatState[1].State := True;
+        
+        JoyEvent.type_ := JoyUnit.HatState[1].Type_;
+        JoyEvent.key.keysym.sym := JoyUnit.HatState[1].Sym;
+        SDL_PushEvent(@JoyEvent);
+      end;
+    end
+    else
+      JoyUnit.HatState[1].State := False;
+
+    //Down button
+    If (JoyUnit.HatState[2].Enabled) and ((SDL_HAT_DOWN AND State) = SDL_HAT_DOWN) then
+    begin //IF Button is newly Pressed or if he is Pressed longer than 230 msecs
+      if (JoyUnit.HatState[2].State = False) OR (JoyUnit.HatState[2].Lasttick < Tick) then
+      begin
+        //Set Tick and State
+        if JoyUnit.HatState[2].State then
+          JoyUnit.HatState[2].Lasttick := Tick + 200
+        else
+          JoyUnit.HatState[2].Lasttick := Tick + 500;
+
+        JoyUnit.HatState[2].State := True;
+        
+        JoyEvent.type_ := JoyUnit.HatState[2].Type_;
+        JoyEvent.key.keysym.sym := JoyUnit.HatState[2].Sym;
+        SDL_PushEvent(@JoyEvent);
+      end;
+    end
+    else
+      JoyUnit.HatState[2].State := False;
+
+    //Left Button
+    If (JoyUnit.HatState[3].Enabled) and ((SDL_HAT_LEFT AND State) = SDL_HAT_LEFT) then
+    begin //IF Button is newly Pressed or if he is Pressed longer than 230 msecs
+      if (JoyUnit.HatState[3].State = False) OR (JoyUnit.HatState[3].Lasttick < Tick) then
+      begin
+        //Set Tick and State
+        if JoyUnit.HatState[3].State then
+          JoyUnit.HatState[3].Lasttick := Tick + 200
+        else
+          JoyUnit.HatState[3].Lasttick := Tick + 500;
+
+        JoyUnit.HatState[3].State := True;
+        
+        JoyEvent.type_ := JoyUnit.HatState[3].Type_;
+        JoyEvent.key.keysym.sym := JoyUnit.HatState[3].Sym;
+        SDL_PushEvent(@JoyEvent);
+      end;
+    end
+    else
+      JoyUnit.HatState[3].State := False;
+  end;
+
+end;
+
+end.
diff --git a/songmanagement/src/base/ULanguage.pas b/songmanagement/src/base/ULanguage.pas
new file mode 100644
index 00000000..5f8a2692
--- /dev/null
+++ b/songmanagement/src/base/ULanguage.pas
@@ -0,0 +1,302 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULanguage;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UUnicodeUtils;
+
+type
+  TLanguageEntry = record
+    ID:     AnsiString;  //**< identifier (ASCII)
+    Text:   UTF8String;  //**< translation (UTF-8)
+  end;
+
+  TLanguageList = record
+    Name:     AnsiString;  //**< language name (ASCII)
+  end;
+
+  TLanguageEntryArray = array of TLanguageEntry;
+
+  TLanguage = class
+    private
+      List:   array of TLanguageList;
+
+      Entry:        TLanguageEntryArray; //**< Entrys of Chosen Language
+      EntryDefault: TLanguageEntryArray; //**< Entrys of Standard Language
+      EntryConst:   TLanguageEntryArray; //**< Constant Entrys e.g. Version
+
+      Implode_Glue1, Implode_Glue2: UTF8String;
+
+      procedure LoadList;
+      function FindID(const ID: AnsiString; const EntryList: TLanguageEntryArray): integer;
+
+    public
+      constructor Create;
+      function Translate(const Text: RawByteString): UTF8String;
+      procedure ChangeLanguage(const Language: AnsiString);
+      procedure AddConst(const ID: AnsiString; const Text: UTF8String);
+      procedure ChangeConst(const ID: AnsiString; const Text: UTF8String);
+      function Implode(const Pieces: array of UTF8String): UTF8String;
+  end;
+
+var
+  Language:     TLanguage;
+
+implementation
+
+uses
+  UMain,
+  UIni,
+  IniFiles,
+  Classes,
+  SysUtils,
+  ULog,
+  UPath,
+  UFilesystem,
+  UPathUtils;
+
+{**
+ * LoadList, set default language, set standard implode glues
+ *}
+constructor TLanguage.Create;
+var
+  I, J: Integer;
+begin
+  inherited;
+
+  LoadList;
+
+  //Set Implode Glues for Backward Compatibility
+  Implode_Glue1 := ', ';
+  Implode_Glue2 := ' and ';
+
+  if (Length(List) = 0) then //No Language Files Loaded -> Abort Loading
+    Log.CriticalError('Could not load any Language File');
+
+  //Standard Language (If a Language File is Incomplete)
+  //Then use English Language
+  for I := 0 to high(List) do //Search for English Language
+  begin
+    //English Language Found -> Load
+    if Uppercase(List[I].Name) = 'ENGLISH' then
+    begin
+      ChangeLanguage('English');
+
+      SetLength(EntryDefault, Length(Entry));
+      for J := 0 to high(Entry) do
+        EntryDefault[J] := Entry[J];
+
+      SetLength(Entry, 0);
+      
+      Break;
+    end;
+
+    if (I = high(List)) then
+      Log.LogError('English Languagefile missing! No standard Translation loaded');
+  end;
+  //Standard Language END
+  
+end;
+
+{**
+ * Parse the Language Dir searching Translations
+ *}
+procedure TLanguage.LoadList;
+var
+  Iter: IFileIterator;
+  IniInfo: TFileInfo;
+  LangName: string;
+begin
+  SetLength(List, 0);
+  SetLength(ILanguage, 0);
+
+  Iter := FileSystem.FileFind(LanguagesPath.Append('*.ini'), 0);
+  while(Iter.HasNext) do
+  begin
+    IniInfo := Iter.Next;
+
+    LangName := IniInfo.Name.SetExtension('').ToUTF8;
+
+    SetLength(List, Length(List)+1);
+    List[High(List)].Name := LangName;
+
+    SetLength(ILanguage, Length(ILanguage)+1);
+    ILanguage[High(ILanguage)] := LangName;
+  end;
+end;
+
+{**
+ * Load the specified LanguageFile
+ *}
+procedure TLanguage.ChangeLanguage(const Language: AnsiString);
+var
+  IniFile:    TUnicodeMemIniFile;
+  E:          integer; // entry
+  S:          TStringList;
+begin
+  SetLength(Entry, 0);
+  IniFile := TUnicodeMemIniFile.Create(LanguagesPath.Append(Language + '.ini'));
+  S := TStringList.Create;
+
+  IniFile.ReadSectionValues('Text', S);
+  SetLength(Entry, S.Count);
+  for E := 0 to high(Entry) do
+  begin
+    if S.Names[E] = 'IMPLODE_GLUE1' then
+      Implode_Glue1 := S.ValueFromIndex[E]+ ' '
+    else if S.Names[E] = 'IMPLODE_GLUE2' then
+      Implode_Glue2 := ' ' + S.ValueFromIndex[E] + ' ';
+
+    Entry[E].ID := S.Names[E];
+    Entry[E].Text := S.ValueFromIndex[E];
+  end;
+
+  S.Free;
+  IniFile.Free;
+end;
+
+{**
+ * Find the index of ID an array of language entries.
+ * @returns the index on success, -1 otherwise.
+ *}
+function TLanguage.FindID(const ID: AnsiString; const EntryList: TLanguageEntryArray): integer;
+var
+  Index: integer;
+begin
+  for Index := 0 to High(EntryList) do
+  begin
+    if ID = EntryList[Index].ID then
+    begin
+      Result := Index;
+      Exit;
+    end;
+  end;
+  Result := -1;
+end;
+
+{**
+ * Translate the Text.
+ * If Text is an ID, text will be translated according to the current language
+ * setting. If Text is not a known ID, it will be returned as is. 
+ * @param Text either an ID or an UTF-8 encoded string 
+ *}
+function TLanguage.Translate(const Text: RawByteString): UTF8String;
+var
+  E:  integer; // entry
+  ID: AnsiString;
+  EntryIndex: integer;
+begin
+  // fallback result in case Text is not a known ID
+  Result := Text;
+
+  // normalize ID case
+  ID := UpperCase(Text);
+
+  // Check if ID exists
+
+  //Const Mod
+  EntryIndex := FindID(ID, EntryConst);
+  if (EntryIndex >= 0) then
+  begin
+    Result := EntryConst[EntryIndex].Text;
+    Exit;
+  end;
+
+  EntryIndex := FindID(ID, Entry);
+  if (EntryIndex >= 0) then
+  begin
+    Result := Entry[EntryIndex].Text;
+    Exit;
+  end;
+
+  //Standard Language (If a Language File is Incomplete)
+  //Then use Standard Language
+  EntryIndex := FindID(ID, EntryDefault);
+  if (EntryIndex >= 0) then
+  begin
+    Result := EntryDefault[EntryIndex].Text;
+    Exit;
+  end;
+end;
+
+{**
+ * Add a Constant ID that will be Translated but not Loaded from the LanguageFile
+ *}
+procedure TLanguage.AddConst(const ID: AnsiString; const Text: UTF8String);
+begin
+  SetLength (EntryConst, Length(EntryConst) + 1);
+  EntryConst[high(EntryConst)].ID := ID;
+  EntryConst[high(EntryConst)].Text := Text;
+end;
+
+{**
+ * Change a Constant Value by ID
+ *}
+procedure TLanguage.ChangeConst(const ID: AnsiString; const Text: UTF8String);
+var
+  I: Integer;
+begin
+  for I := 0 to high(EntryConst) do
+  begin
+    if EntryConst[I].ID = ID then
+    begin
+     EntryConst[I].Text := Text;
+     Break;
+    end;
+  end;
+end;
+
+{**
+ * Connect an array of strings with ' and ' or ', ' to one string
+ *}
+function TLanguage.Implode(const Pieces: array of UTF8String): UTF8String;
+var
+  I: Integer;
+begin
+  Result := '';
+  //Go through Pieces
+  for I := 0 to high(Pieces) do
+  begin
+    //Add Value
+    Result := Result + Pieces[I];
+
+    //Add Glue
+    if (I < high(Pieces) - 1) then
+      Result := Result + Implode_Glue1
+    else if (I < high(Pieces)) then
+      Result := Result + Implode_Glue2;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/base/ULog.pas b/songmanagement/src/base/ULog.pas
new file mode 100644
index 00000000..e4ff4862
--- /dev/null
+++ b/songmanagement/src/base/ULog.pas
@@ -0,0 +1,441 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULog;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  UPath;
+
+(*
+ * LOG_LEVEL_[TYPE] defines the "minimum" index for logs of type TYPE. Each
+ * level greater than this BUT less or equal than LOG_LEVEL_[TYPE]_MAX is of this type.  
+ * This means a level "LOG_LEVEL_ERROR >= Level <= LOG_LEVEL_ERROR_MAX" e.g.
+ * "Level := LOG_LEVEL_ERROR+2" is considered an error level.
+ * This is nice for debugging if you have more or less important debug messages.
+ * For example you can assign LOG_LEVEL_DEBUG+10 for the more important ones and
+ * LOG_LEVEL_DEBUG+20 for less important ones and so on. By changing the log-level
+ * you can hide the less important ones.  
+ *)
+const
+  LOG_LEVEL_DEBUG_MAX    = MaxInt;
+  LOG_LEVEL_DEBUG        = 50;
+  LOG_LEVEL_INFO_MAX     = LOG_LEVEL_DEBUG-1;
+  LOG_LEVEL_INFO         = 40;
+  LOG_LEVEL_STATUS_MAX   = LOG_LEVEL_INFO-1;
+  LOG_LEVEL_STATUS       = 30;
+  LOG_LEVEL_WARN_MAX     = LOG_LEVEL_STATUS-1;
+  LOG_LEVEL_WARN         = 20;
+  LOG_LEVEL_ERROR_MAX    = LOG_LEVEL_WARN-1;
+  LOG_LEVEL_ERROR        = 10;
+  LOG_LEVEL_CRITICAL_MAX = LOG_LEVEL_ERROR-1;
+  LOG_LEVEL_CRITICAL     =  0;
+  LOG_LEVEL_NONE         = -1;
+
+  // define level that Log(File)Level is initialized with
+  LOG_LEVEL_DEFAULT      = LOG_LEVEL_WARN;
+  LOG_FILE_LEVEL_DEFAULT = LOG_LEVEL_ERROR;
+
+type
+  TLog = class
+  private
+    LogFile:             TextFile;
+    LogFileOpened:       boolean;
+    BenchmarkFile:       TextFile;
+    BenchmarkFileOpened: boolean;
+
+    LogLevel: integer;
+    // level of messages written to the log-file
+    LogFileLevel: integer;
+
+    procedure LogToFile(const Text: string);
+  public
+    BenchmarkTimeStart:   array[0..31] of real;
+    BenchmarkTimeLength:  array[0..31] of real;//TDateTime;
+
+    Title: String; //Application Title
+
+    // Write log message to log-file
+    FileOutputEnabled: Boolean;
+
+    constructor Create;
+
+    // destuctor
+    destructor Destroy; override;
+
+    // benchmark
+    procedure BenchmarkStart(Number: integer);
+    procedure BenchmarkEnd(Number: integer);
+    procedure LogBenchmark(const Text: string; Number: integer);
+
+    procedure SetLogLevel(Level: integer);
+    function GetLogLevel(): integer;
+
+    procedure LogMsg(const Text: string; Level: integer); overload;
+    procedure LogMsg(const Msg, Context: string; Level: integer); overload; {$IFDEF HasInline}inline;{$ENDIF}
+    procedure LogDebug(const Msg, Context: string); {$IFDEF HasInline}inline;{$ENDIF}
+    procedure LogInfo(const Msg, Context: string); {$IFDEF HasInline}inline;{$ENDIF}
+    procedure LogStatus(const Msg, Context: string); {$IFDEF HasInline}inline;{$ENDIF}
+    procedure LogWarn(const Msg, Context: string); {$IFDEF HasInline}inline;{$ENDIF}
+    procedure LogError(const Text: string); overload; {$IFDEF HasInline}inline;{$ENDIF}
+    procedure LogError(const Msg, Context: string); overload; {$IFDEF HasInline}inline;{$ENDIF}
+    //Critical Error (Halt + MessageBox)
+    procedure LogCritical(const Msg, Context: string); {$IFDEF HasInline}inline;{$ENDIF}
+    procedure CriticalError(const Text: string); {$IFDEF HasInline}inline;{$ENDIF}
+
+    // voice
+    procedure LogVoice(SoundNr: integer);
+    // buffer
+    procedure LogBuffer(const buf : Pointer; const bufLength : Integer; const filename : IPath);
+  end;
+
+procedure DebugWriteln(const aString: String);
+
+var
+  Log:    TLog;
+
+implementation
+
+uses
+  SysUtils,
+  DateUtils,
+  URecord,
+  UMain,  
+  UTime,
+  UCommon,
+  UCommandLine,
+  UPathUtils;
+
+(*
+ * Write to console if in debug mode (Thread-safe).
+ * If debug-mode is disabled nothing is done. 
+ *)
+procedure DebugWriteln(const aString: string);
+begin
+  {$IFNDEF DEBUG}
+  if Params.Debug then
+  begin
+  {$ENDIF}
+    ConsoleWriteLn(aString);
+  {$IFNDEF DEBUG}
+  end;
+  {$ENDIF}
+end;
+
+
+constructor TLog.Create;
+begin
+  inherited;
+  LogLevel := LOG_LEVEL_DEFAULT;
+  LogFileLevel := LOG_FILE_LEVEL_DEFAULT;
+  FileOutputEnabled := true;
+end;
+
+destructor TLog.Destroy;
+begin
+  if BenchmarkFileOpened then
+    CloseFile(BenchmarkFile);
+  //if AnalyzeFileOpened then
+  //  CloseFile(AnalyzeFile);
+  if LogFileOpened then
+    CloseFile(LogFile);
+  inherited;
+end;
+
+procedure TLog.BenchmarkStart(Number: integer);
+begin
+  BenchmarkTimeStart[Number] := USTime.GetTime; //Time;
+end;
+
+procedure TLog.BenchmarkEnd(Number: integer);
+begin
+  BenchmarkTimeLength[Number] := USTime.GetTime {Time} - BenchmarkTimeStart[Number];
+end;
+
+procedure TLog.LogBenchmark(const Text: string; Number: integer);
+var
+  Minutes:      integer;
+  Seconds:      integer;
+  Miliseconds:  integer;
+
+  MinutesS:     string;
+  SecondsS:     string;
+  MilisecondsS: string;
+
+  ValueText:    string;
+begin
+  if (FileOutputEnabled and Params.Benchmark) then
+  begin
+    if not BenchmarkFileOpened then
+    begin
+      BenchmarkFileOpened := true;
+      AssignFile(BenchmarkFile, LogPath.Append('Benchmark.log').ToNative);
+      {$I-}
+      Rewrite(BenchmarkFile);
+      if IOResult = 0 then
+        BenchmarkFileOpened := true;
+      {$I+}
+
+      //If File is opened write Date to Benchmark File
+      If (BenchmarkFileOpened) then
+      begin
+        WriteLn(BenchmarkFile, Title + ' Benchmark File');
+        WriteLn(BenchmarkFile, 'Date: ' + DatetoStr(Now) + ' Time: ' + TimetoStr(Now));
+        WriteLn(BenchmarkFile, '-------------------');
+
+        Flush(BenchmarkFile);
+      end;
+    end;
+
+    if BenchmarkFileOpened then
+    begin
+      Miliseconds := Trunc(Frac(BenchmarkTimeLength[Number]) * 1000);
+      Seconds := Trunc(BenchmarkTimeLength[Number]) mod 60;
+      Minutes := Trunc((BenchmarkTimeLength[Number] - Seconds) / 60);
+      //ValueText := FloatToStr(BenchmarkTimeLength[Number]);
+
+      {
+      ValueText := FloatToStr(SecondOf(BenchmarkTimeLength[Number]) +
+                              MilliSecondOf(BenchmarkTimeLength[Number])/1000);
+      if MinuteOf(BenchmarkTimeLength[Number]) >= 1 then
+        ValueText := IntToStr(MinuteOf(BenchmarkTimeLength[Number])) + ':' + ValueText;
+      WriteLn(FileBenchmark, Text + ': ' + ValueText + ' seconds');
+      }
+
+      if (Minutes = 0) and (Seconds = 0) then begin
+        MilisecondsS := IntToStr(Miliseconds);
+        ValueText := MilisecondsS + ' miliseconds';
+      end;
+
+      if (Minutes = 0) and (Seconds >= 1) then begin
+        MilisecondsS := IntToStr(Miliseconds);
+        while Length(MilisecondsS) < 3 do
+          MilisecondsS := '0' + MilisecondsS;
+
+        SecondsS := IntToStr(Seconds);
+
+        ValueText := SecondsS + ',' + MilisecondsS + ' seconds';
+      end;
+
+      if Minutes >= 1 then begin
+        MilisecondsS := IntToStr(Miliseconds);
+        while Length(MilisecondsS) < 3 do
+          MilisecondsS := '0' + MilisecondsS;
+
+        SecondsS := IntToStr(Seconds);
+        while Length(SecondsS) < 2 do
+          SecondsS := '0' + SecondsS;
+
+        MinutesS := IntToStr(Minutes);
+
+        ValueText := MinutesS + ':' + SecondsS + ',' + MilisecondsS + ' minutes';
+      end;
+
+      WriteLn(BenchmarkFile, Text + ': ' + ValueText);
+      Flush(BenchmarkFile);
+    end;
+  end;
+end;
+
+procedure TLog.LogToFile(const Text: string);
+begin
+  if (FileOutputEnabled and not LogFileOpened) then
+  begin
+    AssignFile(LogFile, LogPath.Append('Error.log').ToNative);
+    {$I-}
+    Rewrite(LogFile);
+    if IOResult = 0 then
+      LogFileOpened := true;
+    {$I+}
+
+    //If File is opened write Date to Error File
+    if (LogFileOpened) then
+    begin
+      WriteLn(LogFile, Title + ' Error Log');
+      WriteLn(LogFile, 'Date: ' + DatetoStr(Now) + ' Time: ' + TimetoStr(Now));
+      WriteLn(LogFile, '-------------------');
+
+      Flush(LogFile);
+    end;
+  end;
+
+  if LogFileOpened then
+  begin
+    try
+      WriteLn(LogFile, Text);
+      Flush(LogFile);
+    except
+      LogFileOpened := false;
+    end;
+  end;
+end;
+
+procedure TLog.SetLogLevel(Level: integer);
+begin
+  LogLevel := Level;
+end;
+
+function TLog.GetLogLevel(): integer;
+begin
+  Result := LogLevel;
+end;
+
+procedure TLog.LogMsg(const Text: string; Level: integer);
+var
+  LogMsg: string;
+begin
+  // TODO: what if (LogFileLevel < LogLevel)? Log to file without printing to
+  //  console or do not log at all? At the moment nothing is logged.
+  if (Level <= LogLevel) then
+  begin
+    if (Level <= LOG_LEVEL_CRITICAL_MAX) then
+      LogMsg := 'CRITICAL: ' + Text
+    else if (Level <= LOG_LEVEL_ERROR_MAX) then
+      LogMsg := 'ERROR:  ' + Text
+    else if (Level <= LOG_LEVEL_WARN_MAX) then
+      LogMsg := 'WARN:   ' + Text
+    else if (Level <= LOG_LEVEL_STATUS_MAX) then
+      LogMsg := 'STATUS: ' + Text
+    else if (Level <= LOG_LEVEL_INFO_MAX) then
+      LogMsg := 'INFO:   ' + Text
+    else
+      LogMsg := 'DEBUG:  ' + Text;
+
+    // output log-message
+    if (Level <= LogLevel) then
+    begin
+      DebugWriteLn(LogMsg);
+    end;
+    
+    // write message to log-file
+    if (Level <= LogFileLevel) then
+    begin
+      LogToFile(LogMsg);
+    end;
+  end;
+
+  // exit application on criticial errors (cannot be turned off)
+  if (Level <= LOG_LEVEL_CRITICAL_MAX) then
+  begin
+    // Show information (window)
+    ShowMessage(Text, mtError);
+    Halt;
+  end;
+end;
+
+procedure TLog.LogMsg(const Msg, Context: string; Level: integer);
+begin
+  LogMsg(Msg + ' ['+Context+']', Level);
+end;
+
+procedure TLog.LogDebug(const Msg, Context: string);
+begin
+  LogMsg(Msg, Context, LOG_LEVEL_DEBUG);
+end;
+
+procedure TLog.LogInfo(const Msg, Context: string);
+begin
+  LogMsg(Msg, Context, LOG_LEVEL_INFO);
+end;
+
+procedure TLog.LogStatus(const Msg, Context: string);
+begin
+  LogMsg(Msg, Context, LOG_LEVEL_STATUS);
+end;
+
+procedure TLog.LogWarn(const Msg, Context: string);
+begin
+  LogMsg(Msg, Context, LOG_LEVEL_WARN);
+end;
+
+procedure TLog.LogError(const Msg, Context: string);
+begin
+  LogMsg(Msg, Context, LOG_LEVEL_ERROR);
+end;
+
+procedure TLog.LogError(const Text: string);
+begin
+  LogMsg(Text, LOG_LEVEL_ERROR);
+end;
+
+procedure TLog.CriticalError(const Text: string);
+begin
+  LogMsg(Text, LOG_LEVEL_CRITICAL);
+end;
+
+procedure TLog.LogCritical(const Msg, Context: string);
+begin
+  LogMsg(Msg, Context, LOG_LEVEL_CRITICAL);
+end;
+
+procedure TLog.LogVoice(SoundNr: integer);
+var
+  FS:           TBinaryFileStream;
+  Prefix:       string;
+  FileName:     IPath;
+  Num:          integer;
+begin
+  for Num := 1 to 9999 do begin
+    Prefix := Format('Voice%.4d', [Num]);
+    FileName := LogPath.Append(Prefix + '.raw');
+    if not FileName.Exists() then
+      break
+  end;
+
+  FS := TBinaryFileStream.Create(FileName, fmCreate);
+
+  AudioInputProcessor.Sound[SoundNr].LogBuffer.Seek(0, soBeginning);
+  FS.CopyFrom(AudioInputProcessor.Sound[SoundNr].LogBuffer, AudioInputProcessor.Sound[SoundNr].LogBuffer.Size);
+
+  FS.Free;
+end;
+
+procedure TLog.LogBuffer(const buf: Pointer; const bufLength: Integer; const filename: IPath);
+var
+  f : TBinaryFileStream;
+begin
+  try
+    f := TBinaryFileStream.Create( filename, fmCreate);
+    try
+      f.Write( buf^, bufLength);
+    finally
+      f.Free;
+    end;
+  except on e : Exception do
+    Log.LogError('TLog.LogBuffer: Failed to log buffer into file "' + filename.ToNative + '". ErrMsg: ' + e.Message);
+  end;
+end;
+
+end.
+
+
diff --git a/songmanagement/src/base/ULyrics.pas b/songmanagement/src/base/ULyrics.pas
new file mode 100644
index 00000000..3f62db9c
--- /dev/null
+++ b/songmanagement/src/base/ULyrics.pas
@@ -0,0 +1,726 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULyrics;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  gl,
+  glext,
+  UTexture,
+  UThemes,
+  UMusic;
+
+type
+  // stores two textures for enabled/disabled states
+  TPlayerIconTex = array [0..1] of TTexture;
+
+  TLyricsEffect = (lfxSimple, lfxZoom, lfxSlide, lfxBall, lfxShift);
+  
+  PLyricWord = ^TLyricWord;
+  TLyricWord = record
+    X:          real;     // left corner
+    Width:      real;     // width
+    Start:      cardinal; // start of the word in quarters (beats)
+    Length:     cardinal; // length of the word in quarters
+    Text:       UTF8String; // text
+    Freestyle:  boolean;  // is freestyle?
+  end;
+  TLyricWordArray = array of TLyricWord;
+
+  TLyricLine = class
+    public
+      Text:           UTF8String;   // text
+      Width:          real;         // width
+      Height:         real;         // height
+      Words:          TLyricWordArray;   // words in this line
+      CurWord:        integer;      // current active word idx (only valid if line is active)
+      Start:          integer;      // start of this line in quarters (Note: negative start values are possible due to gap)
+      StartNote:      integer;      // start of the first note of this line in quarters
+      Length:         integer;      // length in quarters (from start of first to the end of the last note)
+      Players:        byte;         // players that should sing that line (bitset, Player1: 1, Player2: 2, Player3: 4)
+      LastLine:       boolean;      // is this the last line of the song?
+
+      constructor Create();
+      destructor Destroy(); override;
+      procedure Reset();
+  end;
+
+  TLyricEngine = class
+    private
+      LastDrawBeat:   real;
+      UpperLine:      TLyricLine;    // first line displayed (top)
+      LowerLine:      TLyricLine;    // second lind displayed (bottom)
+      QueueLine:      TLyricLine;    // third line (will be displayed when lower line is finished)
+
+      IndicatorTex:   TTexture;      // texture for lyric indikator
+      BallTex:        TTexture;      // texture of the ball for the lyric effect
+
+      QueueFull:      boolean;       // set to true if the queue is full and a line will be replaced with the next AddLine
+      LCounter:       integer;       // line counter
+
+      // duet mode - textures for player icons
+      // FIXME: do not use a fixed player count, use MAX_PLAYERS instead
+      PlayerIconTex:  array[0..5] of TPlayerIconTex;
+
+      // Some helper procedures for lyric drawing
+      procedure DrawLyrics (Beat: real);
+      procedure UpdateLineMetrics(LyricLine: TLyricLine);
+      procedure DrawLyricsWords(LyricLine: TLyricLine; X, Y: real; StartWord, EndWord: integer);
+      procedure DrawLyricsLine(X, W, Y, H: real; Line: TLyricLine; Beat: real);
+      procedure DrawPlayerIcon(Player: byte; Enabled: boolean; X, Y: real; Size, Alpha: real);
+      procedure DrawBall(XBall, YBall, Alpha: real);
+
+    public
+      // positions, line specific settings
+      UpperLineX:     real;       // X start-pos of UpperLine
+      UpperLineW:     real;       // Width of UpperLine with icon(s) and text
+      UpperLineY:     real;       // Y start-pos of UpperLine
+      UpperLineH:     real;       // Max. font-size of lyrics text in UpperLine
+
+      LowerLineX:     real;       // X start-pos of LowerLine
+      LowerLineW:     real;       // Width of LowerLine with icon(s) and text
+      LowerLineY:     real;       // Y start-pos of LowerLine
+      LowerLineH:     real;       // Max. font-size of lyrics text in LowerLine
+
+      // display propertys
+      LineColor_en:   TRGBA;      // Color of words in an enabled line
+      LineColor_dis:  TRGBA;      // Color of words in a disabled line
+      LineColor_act:  TRGBA;      // Color of the active word
+      FontStyle:      byte;       // Font for the lyric text
+      
+      { // currently not used
+       FadeInEffect:   byte;       // Effect for line fading in: 0: No Effect; 1: Fade Effect; 2: Move Upwards from Bottom to Pos
+       FadeOutEffect:  byte;       // Effect for line fading out: 0: No Effect; 1: Fade Effect; 2: Move Upwards
+      }
+
+      // song specific settings
+      BPM:            real;
+      Resolution:     integer;
+
+      // properties to easily read options of this class
+      property IsQueueFull: boolean read QueueFull;  // line in queue?
+      property LineCounter: integer read LCounter;   // lines that were progressed so far (after last clear)
+
+      procedure AddLine(Line: PLine);              // adds a line to the queue, if there is space
+      procedure Draw (Beat: real);                 // draw the current (active at beat) lyrics
+
+      // clears all cached song specific information
+      procedure Clear(cBPM: real = 0; cResolution: integer = 0);
+
+      function GetUpperLine(): TLyricLine;
+      function GetLowerLine(): TLyricLine;
+
+      function GetUpperLineIndex(): integer;
+
+      constructor Create(ULX, ULY, ULW, ULH, LLX, LLY, LLW, LLH: real);
+      procedure   LoadTextures;
+      destructor  Destroy; override;
+  end;
+
+implementation
+
+uses
+  SysUtils,
+  USkins,
+  TextGL,
+  UGraphic,
+  UDisplay,
+  ULog,
+  math,
+  UIni;
+
+{ TLyricLine }
+
+constructor TLyricLine.Create();
+begin
+  inherited;
+  Reset();
+end;
+
+destructor TLyricLine.Destroy();
+begin
+  SetLength(Words, 0);
+  inherited;
+end;
+
+procedure TLyricLine.Reset();
+begin
+  Start     := 0;
+  StartNote := 0;
+  Length    := 0;
+  LastLine  := False;
+
+  Text      := '';
+  Width     := 0;
+
+  // duet mode: players of that line (default: all)
+  Players   := $FF;
+
+  SetLength(Words, 0);
+  CurWord   := -1;
+end;
+
+
+{ TLyricEngine }
+
+{**
+ * Initializes the engine.
+ *}
+constructor TLyricEngine.Create(ULX, ULY, ULW, ULH, LLX, LLY, LLW, LLH: real);
+begin
+  inherited Create();
+
+  BPM := 0;
+  Resolution := 0;
+  LCounter := 0;
+  QueueFull := False;
+
+  UpperLine := TLyricLine.Create;
+  LowerLine := TLyricLine.Create;
+  QueueLine := TLyricLine.Create;
+
+  LastDrawBeat := 0;
+
+  UpperLineX := ULX;
+  UpperLineW := ULW;
+  UpperLineY := ULY;
+  UpperLineH := ULH;
+
+  LowerLineX := LLX;
+  LowerLineW := LLW;
+  LowerLineY := LLY;
+  LowerLineH := LLH;
+
+  LoadTextures;
+end;
+
+
+{**
+ * Frees memory.
+ *}
+destructor TLyricEngine.Destroy;
+begin
+  UpperLine.Free;
+  LowerLine.Free;
+  QueueLine.Free;
+  inherited;
+end;
+
+{**
+ * Clears all cached Song specific Information.
+ *}
+procedure TLyricEngine.Clear(cBPM: real; cResolution: integer);
+begin
+  BPM := cBPM;
+  Resolution := cResolution;
+  LCounter := 0;
+  QueueFull := False;
+
+  LastDrawBeat:=0;
+end;
+
+
+{**
+ * Loads textures needed for the drawing the lyrics,
+ * player icons, a ball for the ball effect and the lyric indicator.
+ *}
+procedure TLyricEngine.LoadTextures;
+var
+  I: Integer;
+begin
+  // lyric indicator (bar that indicates when the line start)
+  IndicatorTex := Texture.LoadTexture(Skin.GetTextureFileName('LyricHelpBar'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+
+  // ball for current word hover in ball effect
+  BallTex := Texture.LoadTexture(Skin.GetTextureFileName('Ball'), TEXTURE_TYPE_TRANSPARENT, 0);
+
+  // duet mode: load player icon
+  for I := 0 to 5 do
+  begin
+    PlayerIconTex[I][0] := Texture.LoadTexture(Skin.GetTextureFileName('LyricIcon_P' + InttoStr(I+1)), TEXTURE_TYPE_TRANSPARENT, 0);
+    PlayerIconTex[I][1] := Texture.LoadTexture(Skin.GetTextureFileName('LyricIconD_P' + InttoStr(I+1)), TEXTURE_TYPE_TRANSPARENT, 0);
+  end;
+end;
+
+{**
+ * Adds LyricLine to queue.
+ * The LyricEngine stores three lines in its queue:
+ *   UpperLine: the upper line displayed in the lyrics
+ *   LowerLine: the lower line displayed in the lyrics
+ *   QueueLine: an offscreen line that precedes LowerLine
+ * If the queue is full the next call to AddLine will replace UpperLine with
+ * LowerLine, LowerLine with QueueLine and QueueLine with the Line parameter.
+ *}
+procedure TLyricEngine.AddLine(Line: PLine);
+var
+  LyricLine: TLyricLine;
+  I: integer;
+begin
+  // only add lines, if there is space
+  if not IsQueueFull then
+  begin
+    // set LyricLine to line to write to
+    if (LineCounter = 0) then
+      LyricLine := UpperLine
+    else if (LineCounter = 1) then
+      LyricLine := LowerLine
+    else
+    begin
+      // now the queue is full
+      LyricLine := QueueLine;
+      QueueFull := True;
+    end;
+  end
+  else
+  begin // rotate lines (round-robin-like)
+    LyricLine := UpperLine;
+    UpperLine := LowerLine;
+    LowerLine := QueueLine;
+    QueueLine := LyricLine;
+  end;
+
+  // reset line state
+  LyricLine.Reset();
+
+  // check if sentence has notes
+  if (Line <> nil) and (Length(Line.Note) > 0) then
+  begin
+    // copy values from SongLine to LyricLine
+    LyricLine.Start     := Line.Start;
+    LyricLine.StartNote := Line.Note[0].Start;
+    LyricLine.Length    := Line.Note[High(Line.Note)].Start +
+                           Line.Note[High(Line.Note)].Length -
+                           Line.Note[0].Start;
+    LyricLine.LastLine  := Line.LastLine;
+
+    // copy words
+    SetLength(LyricLine.Words, Length(Line.Note));
+    for I := 0 to High(Line.Note) do
+    begin
+      LyricLine.Words[I].Start     := Line.Note[I].Start;
+      LyricLine.Words[I].Length    := Line.Note[I].Length;
+      LyricLine.Words[I].Text      := Line.Note[I].Text;
+      LyricLine.Words[I].Freestyle := Line.Note[I].NoteType = ntFreestyle;
+
+      LyricLine.Text := LyricLine.Text + LyricLine.Words[I].Text;
+    end;
+
+    UpdateLineMetrics(LyricLine);
+  end;
+
+  // increase the counter
+  Inc(LCounter);
+end;
+
+{**
+ * Draws Lyrics.
+ * Draw just manages the Lyrics, drawing is done by a call of DrawLyrics.
+ * @param Beat: current Beat in Quarters
+ *}
+procedure TLyricEngine.Draw(Beat: real);
+begin
+  DrawLyrics(Beat);
+  LastDrawBeat := Beat;
+end;
+
+{**
+ * Main Drawing procedure.
+ *}
+procedure TLyricEngine.DrawLyrics(Beat: real);
+begin
+  DrawLyricsLine(UpperLineX, UpperLineW, UpperLineY, UpperLineH, UpperLine, Beat);
+  DrawLyricsLine(LowerLineX, LowerLineW, LowerLineY, LowerLineH, LowerLine, Beat);
+end;
+
+{**
+ * Draws a Player's icon.
+ *}
+procedure TLyricEngine.DrawPlayerIcon(Player: byte; Enabled: boolean; X, Y: real; Size, Alpha: real);
+var
+  IEnabled: byte;
+begin
+  if Enabled then
+    IEnabled := 0
+  else
+    IEnabled := 1;
+
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glBindTexture(GL_TEXTURE_2D, PlayerIconTex[Player][IEnabled].TexNum);
+
+  glColor4f(1, 1, 1, Alpha);
+  glBegin(GL_QUADS);
+    glTexCoord2f(0, 0); glVertex2f(X, Y);
+    glTexCoord2f(0, 1); glVertex2f(X, Y + Size);
+    glTexCoord2f(1, 1); glVertex2f(X + Size, Y + Size);
+    glTexCoord2f(1, 0); glVertex2f(X + Size, Y);
+  glEnd;
+
+  glDisable(GL_BLEND);
+  glDisable(GL_TEXTURE_2D);
+end;
+
+{**
+ * Draws the Ball over the LyricLine if needed.
+ *}
+procedure TLyricEngine.DrawBall(XBall, YBall, Alpha: real);
+begin
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glBindTexture(GL_TEXTURE_2D, BallTex.TexNum);
+
+  glColor4f(1, 1, 1, Alpha);
+  glBegin(GL_QUADS);
+    glTexCoord2f(0, 0); glVertex2f(XBall - 10, YBall);
+    glTexCoord2f(0, 1); glVertex2f(XBall - 10, YBall + 20);
+    glTexCoord2f(1, 1); glVertex2f(XBall + 10, YBall + 20);
+    glTexCoord2f(1, 0); glVertex2f(XBall + 10, YBall);
+  glEnd;
+
+  glDisable(GL_BLEND);
+  glDisable(GL_TEXTURE_2D);
+end;
+
+procedure TLyricEngine.DrawLyricsWords(LyricLine: TLyricLine;
+    X, Y: real; StartWord, EndWord: integer);
+var
+  I: integer;
+  PosX: real;
+  CurWord: PLyricWord;
+begin
+  PosX := X;
+
+  // set word positions and line size and draw the line
+  for I := StartWord to EndWord do
+  begin
+    CurWord := @LyricLine.Words[I];
+    SetFontItalic(CurWord.Freestyle);
+    SetFontPos(PosX, Y);
+    glPrint(CurWord.Text);
+    PosX := PosX + CurWord.Width;
+  end;
+end;
+
+procedure TLyricEngine.UpdateLineMetrics(LyricLine: TLyricLine);
+var
+  I: integer;
+  PosX: real;
+  CurWord: PLyricWord;
+  RequestWidth, RequestHeight: real;
+begin
+  PosX := 0;
+
+  // setup font
+  SetFontStyle(FontStyle);
+  ResetFont();
+
+  // check if line is lower or upper line and set sizes accordingly
+  // Note: at the moment upper and lower lines have same width/height
+  // and this function is just called by AddLine() but this may change
+  // so that it is called by DrawLyricsLine().
+  //if (LyricLine = LowerLine) then
+  //begin
+  //  RequestWidth  := LowerLineW;
+  //  RequestHeight := LowerLineH;
+  //end
+  //else
+  //begin
+    RequestWidth  := UpperLineW;
+    RequestHeight := UpperLineH;
+  //end;
+
+  // set font size to a reasonable value
+  LyricLine.Height := RequestHeight * 0.9;
+  SetFontSize(LyricLine.Height);
+  LyricLine.Width := glTextWidth(LyricLine.Text);
+
+  // change font-size to fit into the lyric bar
+  if (LyricLine.Width > RequestWidth) then
+  begin
+    LyricLine.Height := Trunc(LyricLine.Height * (RequestWidth / LyricLine.Width));
+    // the line is very loooong, set font to at least 1px
+    if (LyricLine.Height < 1) then
+      LyricLine.Height := 1;
+
+    SetFontSize(LyricLine.Height);
+    LyricLine.Width := glTextWidth(LyricLine.Text);
+  end;
+
+  // calc word positions and widths
+  for I := 0 to High(LyricLine.Words) do
+  begin
+    CurWord := @LyricLine.Words[I];
+
+    // - if current word is italic but not the next word get the width of the
+    // italic font to avoid overlapping.
+    // - if two italic words follow each other use the normal style's
+    // width otherwise the spacing between the words will be too big.
+    // - if it is the line's last word use normal width  
+    if CurWord.Freestyle and
+       (I+1 < Length(LyricLine.Words)) and
+       (not LyricLine.Words[I+1].Freestyle) then
+    begin
+      SetFontItalic(true);
+    end;
+
+    CurWord.X := PosX;
+    CurWord.Width := glTextWidth(CurWord.Text);
+    PosX := PosX + CurWord.Width;
+    SetFontItalic(false);
+  end;
+end;
+
+
+{**
+ * Draws one LyricLine
+ *}
+procedure TLyricEngine.DrawLyricsLine(X, W, Y, H: real; Line: TLyricLine; Beat: real);
+var
+  CurWord:        PLyricWord;     // current word
+  LastWord:       PLyricWord;     // last word in line
+  NextWord:       PLyricWord;     // word following current word
+  Progress:       real;           // progress of singing the current word
+  LyricX, LyricY: real;           // left/top lyric position
+  WordY: real;                    // word y-position
+  LyricsEffect: TLyricsEffect;
+  Alpha: real;                    // alphalevel to fade out at end
+  ClipPlaneEq: array[0..3] of GLdouble; // clipping plane for slide effect 
+  {// duet mode
+  IconSize: real;                 // size of player icons
+  IconAlpha: real;                // alpha level of player icons
+  }
+begin
+  // do not draw empty lines
+  if (Length(Line.Words) = 0) then
+    Exit;
+
+  {
+  // duet mode
+  IconSize := (2 * Height);
+  IconAlpha := Frac(Beat/(Resolution*4));
+
+  DrawPlayerIcon (0, True, X, Y + (42 - IconSize) / 2 , IconSize, IconAlpha);
+  DrawPlayerIcon (1, True, X + IconSize + 1,  Y + (42 - IconSize) / 2, IconSize, IconAlpha);
+  DrawPlayerIcon (2, True, X + (IconSize + 1)*2, Y + (42 - IconSize) / 2, IconSize, IconAlpha);
+  }
+
+  // set font size and style
+  SetFontStyle(FontStyle);
+  ResetFont();
+  SetFontSize(Line.Height);
+
+  // center lyrics
+  LyricX := X + (W - Line.Width) / 2;
+  LyricY := Y + (H - Line.Height) / 2;
+  // get lyrics effect
+  LyricsEffect := TLyricsEffect(Ini.LyricsEffect);
+
+  // TODO: what about alpha in freetype outline fonts?
+  Alpha := 1;
+
+  // check if this line is active (at least its first note must be active)
+  if (Beat >= Line.StartNote) then
+  begin
+    // if this line just got active, CurWord is -1,
+    // this means we should try to make the first word active
+    if (Line.CurWord = -1) then
+      Line.CurWord := 0;
+
+    // check if the current active word is still active.
+    // Otherwise proceed to the next word if there is one in this line.
+    // Note: the max. value of Line.CurWord is High(Line.Words)
+    if (Line.CurWord < High(Line.Words)) and
+       (Beat >= Line.Words[Line.CurWord + 1].Start) then
+    begin
+      Inc(Line.CurWord);
+    end;
+
+    // determine current and last word in this line.
+    // If the end of the line is reached use the last word as current word.
+    LastWord := @Line.Words[High(Line.Words)];
+    CurWord := @Line.Words[Line.CurWord];
+    if (Line.CurWord+1 < Length(Line.Words)) then
+      NextWord := @Line.Words[Line.CurWord+1]
+    else
+      NextWord := nil;
+
+    // calc the progress of the lyrics effect
+    Progress := (Beat - CurWord.Start) / CurWord.Length;
+    if (Progress >= 1) then
+      Progress := 1;
+    if (Progress <= 0) then
+      Progress := 0;
+
+    // last word of this line finished, but this line did not hide -> fade out
+    if Line.LastLine and
+       (Beat > LastWord.Start + LastWord.Length) then
+    begin
+      Alpha := 1 - (Beat - (LastWord.Start + LastWord.Length)) / 15;
+      if (Alpha < 0) then
+        Alpha := 0;
+    end;
+
+    // draw sentence before current word
+    if (LyricsEffect in [lfxSimple, lfxBall, lfxShift]) then
+      // only highlight current word and not that ones before in this line
+      glColorRGB(LineColor_en, Alpha)
+    else
+      glColorRGB(LineColor_act, Alpha);
+    DrawLyricsWords(Line, LyricX, LyricY, 0, Line.CurWord-1);
+
+    // draw rest of sentence (without current word)
+    glColorRGB(LineColor_en, Alpha);
+    if (NextWord <> nil) then
+    begin
+      DrawLyricsWords(Line, LyricX + NextWord.X, LyricY,
+                      Line.CurWord+1, High(Line.Words));
+    end;
+
+    // draw current word
+    if (LyricsEffect in [lfxSimple, lfxBall, lfxShift]) then
+    begin
+      if (LyricsEffect = lfxShift) then
+        WordY := LyricY - 8 * (1-Progress)
+      else
+        WordY := LyricY;
+
+      // change the color of the current word
+      glColor4f(LineColor_act.r, LineColor_act.g, LineColor_act.b, Alpha);
+      DrawLyricsWords(Line, LyricX + CurWord.X, WordY, Line.CurWord, Line.CurWord);
+    end
+    // change color and zoom current word
+    else if (LyricsEffect = lfxZoom) then
+    begin
+      glPushMatrix;
+
+      // zoom at word center
+      glTranslatef(LyricX + CurWord.X + CurWord.Width/2,
+                   LyricY + Line.Height/2, 0);
+      glScalef(1.0 + (1-Progress) * 0.5, 1.0 + (1-Progress) * 0.5, 1.0);
+
+      glColor4f(LineColor_act.r, LineColor_act.g, LineColor_act.b, Alpha);
+      DrawLyricsWords(Line, -CurWord.Width/2, -Line.Height/2, Line.CurWord, Line.CurWord);
+
+      glPopMatrix;
+    end
+    // split current word into active and non-active part
+    else if (LyricsEffect = lfxSlide) then
+    begin
+      // enable clipping and set clip equation coefficients to zeros
+      glEnable(GL_CLIP_PLANE0);
+      FillChar(ClipPlaneEq[0], SizeOf(ClipPlaneEq), 0);
+
+      glPushMatrix;
+      glTranslatef(LyricX + CurWord.X, LyricY, 0);
+
+      // clip non-active right part of the current word
+      ClipPlaneEq[0] := -1;
+      ClipPlaneEq[3] := CurWord.Width * Progress;
+      glClipPlane(GL_CLIP_PLANE0, @ClipPlaneEq);
+      // and draw active left part
+      glColor4f(LineColor_act.r, LineColor_act.g, LineColor_act.b, Alpha);
+      DrawLyricsWords(Line, 0, 0, Line.CurWord, Line.CurWord);
+
+      // clip active left part of the current word
+      ClipPlaneEq[0] := -ClipPlaneEq[0];
+      ClipPlaneEq[3] := -ClipPlaneEq[3];
+      glClipPlane(GL_CLIP_PLANE0, @ClipPlaneEq);
+      // and draw non-active right part
+      glColor4f(LineColor_en.r, LineColor_en.g, LineColor_en.b, Alpha);
+      DrawLyricsWords(Line, 0, 0, Line.CurWord, Line.CurWord);
+
+      glPopMatrix;
+
+      glDisable(GL_CLIP_PLANE0);
+    end;
+
+    // draw the ball onto the current word
+    if (LyricsEffect = lfxBall) then
+    begin
+      DrawBall(LyricX + CurWord.X + CurWord.Width * Progress,
+               LyricY - 15 - 15*sin(Progress * Pi), Alpha);
+    end;
+  end
+  else
+  begin
+    // this section is called if the whole line can be drawn at once and no
+    // word is highlighted.
+
+    // enable the upper, disable the lower line
+    if (Line = UpperLine) then
+      glColorRGB(LineColor_en)
+    else
+      glColorRGB(LineColor_dis);
+
+    DrawLyricsWords(Line, LyricX, LyricY, 0, High(Line.Words));
+  end;
+end;
+
+{**
+ * @returns a reference to the upper line
+ *}
+function TLyricEngine.GetUpperLine(): TLyricLine;
+begin
+  Result := UpperLine;
+end;
+
+{**
+ * @returns a reference to the lower line
+ *}
+function TLyricEngine.GetLowerLine(): TLyricLine;
+begin
+  Result := LowerLine;
+end;
+
+{**
+ * @returns the index of the upper line
+ *}
+function TLyricEngine.GetUpperLineIndex(): integer;
+const
+  QUEUE_SIZE = 3;
+begin
+  // no line in queue
+  if (LineCounter <= 0) then
+    Result := -1
+  // no line has been removed from queue yet
+  else if (LineCounter <= QUEUE_SIZE) then
+    Result := 0
+  // lines have been removed from queue already
+  else
+    Result := LineCounter - QUEUE_SIZE;
+end;
+
+end.
+
diff --git a/songmanagement/src/base/UMain.pas b/songmanagement/src/base/UMain.pas
new file mode 100644
index 00000000..14a543d1
--- /dev/null
+++ b/songmanagement/src/base/UMain.pas
@@ -0,0 +1,598 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMain;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  SDL;
+
+procedure Main;
+procedure MainLoop;
+procedure CheckEvents;
+
+type
+  TMainThreadExecProc = procedure(Data: Pointer);
+
+const
+  MAINTHREAD_EXEC_EVENT = SDL_USEREVENT + 2;
+
+{*
+ * Delegates execution of procedure Proc to the main thread.
+ * The Data pointer is passed to the procedure when it is called.
+ * The main thread is notified by signaling a MAINTHREAD_EXEC_EVENT which
+ * is handled in CheckEvents.
+ * Note that Data must not be a pointer to local data. If you want to pass local
+ * data, use Getmem() or New() or create a temporary object.
+ *}
+procedure MainThreadExec(Proc: TMainThreadExecProc; Data: Pointer);
+
+implementation
+
+uses
+  Math,
+  gl,
+  UCatCovers,
+  UCommandLine,
+  UCommon,
+  UConfig,
+  UCovers,
+  UDataBase,
+  UDisplay,
+  UGraphic,
+  UGraphicClasses,
+  UIni,
+  UJoystick,
+  ULanguage,
+  ULog,
+  UPathUtils,
+  UPlaylist,
+  UMusic,
+  URecord,
+  UBeatTimer,
+  UPlatform,
+  USkins,
+  USongs,
+  UThemes,
+  UParty,
+  ULuaCore,
+  UHookableEvent,
+  ULuaGl,
+  ULuaLog,
+  ULuaTexture,
+  ULuaTextGL,
+  ULuaParty,
+  ULuaScreenSing,
+  UTime;
+
+procedure Main;
+var
+  WindowTitle: string;
+  BadPlayer: integer;
+begin
+  {$IFNDEF Debug}
+  try
+  {$ENDIF}
+    WindowTitle := USDXVersionStr;
+
+    Platform.Init;
+
+    if Platform.TerminateIfAlreadyRunning(WindowTitle) then
+      Exit;
+
+    // fix floating-point exceptions (FPE)
+    DisableFloatingPointExceptions();
+    // fix the locale for string-to-float parsing in C-libs
+    SetDefaultNumericLocale();
+
+    // setup separators for parsing
+    // Note: ThousandSeparator must be set because of a bug in TIniFile.ReadFloat
+    ThousandSeparator := ',';
+    DecimalSeparator := '.';
+
+    //------------------------------
+    // StartUp - create classes and load files
+    //------------------------------
+
+    // initialize SDL
+    // without SDL_INIT_TIMER SDL_GetTicks() might return strange values
+    SDL_Init(SDL_INIT_VIDEO or SDL_INIT_TIMER);
+    SDL_EnableUnicode(1);
+
+    // create luacore first so other classes can register their events
+    LuaCore := TLuaCore.Create;
+
+
+    USTime := TTime.Create;
+    VideoBGTimer := TRelativeTimer.Create;
+
+    // Commandline Parameter Parser
+    Params := TCMDParams.Create;
+
+    // Log + Benchmark
+    Log := TLog.Create;
+    Log.Title := WindowTitle;
+    Log.FileOutputEnabled := not Params.NoLog;
+    Log.BenchmarkStart(0);
+
+    // Language
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Initialize Paths', 'Initialization');
+    InitializePaths;
+    Log.LogStatus('Load Language', 'Initialization');
+    Language := TLanguage.Create;
+
+    // add const values:
+    Language.AddConst('US_VERSION', USDXVersionStr);
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Language', 1);
+
+    // Skin
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Loading Skin List', 'Initialization');
+    Skin := TSkin.Create;
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Skin List', 1);
+
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Loading Theme List', 'Initialization');
+    Theme := TTheme.Create;
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Theme List', 1);
+
+    // Ini + Paths
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Load Ini', 'Initialization');
+    Ini := TIni.Create;
+    Ini.Load;
+
+    // it is possible that this is the first run, create a .ini file if neccessary
+    Log.LogStatus('Write Ini', 'Initialization');
+    Ini.Save;
+
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Ini', 1);
+
+    // Sound
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Initialize Sound', 'Initialization');
+    InitializeSound();
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Initializing Sound', 1);
+
+    // Lyrics-engine with media reference timer
+    LyricsState := TLyricsState.Create();
+
+    // Theme
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Load Theme', 'Initialization');
+    Theme.LoadTheme(Ini.Theme, Ini.Color);
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Theme', 1);
+
+    // Covers Cache
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Creating Covers Cache', 'Initialization');
+    Covers := TCoverDatabase.Create;
+    Log.LogBenchmark('Loading Covers Cache Array', 1);
+    Log.BenchmarkStart(1);
+
+    // Category Covers
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Creating Category Covers Array', 'Initialization');
+    CatCovers:= TCatCovers.Create;
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Category Covers Array', 1);
+
+    // Songs
+    //Log.BenchmarkStart(1);
+    Log.LogStatus('Creating Song Array', 'Initialization');
+    Songs := TSongs.Create;
+    //Songs.LoadSongList;
+
+    Log.LogStatus('Creating 2nd Song Array', 'Initialization');
+    CatSongs := TCatSongs.Create;
+
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Songs', 1);
+
+    // Graphics
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Initialize 3D', 'Initialization');
+    Initialize3D(WindowTitle);
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Initializing 3D', 1);
+
+    // Score Saving System
+    Log.BenchmarkStart(1);
+    Log.LogStatus('DataBase System', 'Initialization');
+    DataBase := TDataBaseSystem.Create;
+
+    if (Params.ScoreFile.IsUnset) then
+      DataBase.Init(Platform.GetGameUserPath.Append('Ultrastar.db'))
+    else
+      DataBase.Init(Params.ScoreFile);
+
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading DataBase System', 1);
+
+    // Playlist Manager
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Playlist Manager', 'Initialization');
+    PlaylistMan := TPlaylistManager.Create;
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Playlist Manager', 1);
+
+    // GoldenStarsTwinkleMod
+    Log.BenchmarkStart(1);
+    Log.LogStatus('Effect Manager', 'Initialization');
+    GoldenRec := TEffectManager.Create;
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Particle System', 1);
+
+    // Joypad
+    if (Ini.Joypad = 1) or (Params.Joypad) then
+    begin
+      Log.BenchmarkStart(1);
+      Log.LogStatus('Initialize Joystick', 'Initialization');
+      Joy := TJoy.Create;
+      Log.BenchmarkEnd(1);
+      Log.LogBenchmark('Initializing Joystick', 1);
+    end;
+
+    // Lua
+    Log.BenchmarkStart(1);
+    Party := TPartyGame.Create;
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Initializing Party Manager', 1);
+
+    Log.BenchmarkStart(1);
+    LuaCore.RegisterModule('Log', ULuaLog_Lib_f);
+    LuaCore.RegisterModule('Gl', ULuaGl_Lib_f);
+    LuaCore.RegisterModule('TextGl', ULuaTextGl_Lib_f);
+    LuaCore.RegisterModule('Party', ULuaParty_Lib_f);
+    LuaCore.RegisterModule('ScreenSing', ULuaScreenSing_Lib_f);
+
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Initializing LuaCore', 1);
+
+    Log.BenchmarkStart(1);
+    LuaCore.LoadPlugins;
+    Log.BenchmarkEnd(1);
+    Log.LogBenchmark('Loading Lua Plugins', 1);
+
+    LuaCore.DumpPlugins;
+
+    Log.BenchmarkEnd(0);
+    Log.LogBenchmark('Loading Time', 0);
+
+    { prepare software cursor }
+    Display.SetCursor;
+
+    {**
+      * Start background music
+      *}
+    SoundLib.StartBgMusic;
+
+    // check microphone settings, goto record options if they are corrupt
+    BadPlayer := AudioInputProcessor.ValidateSettings;
+    if (BadPlayer <> 0) then
+    begin
+      ScreenPopupError.ShowPopup(
+          Format(Language.Translate('ERROR_PLAYER_DEVICE_ASSIGNMENT'),
+          [BadPlayer]));
+      Display.CurrentScreen^.FadeTo( @ScreenOptionsRecord );
+    end;
+
+    //------------------------------
+    // Start Mainloop
+    //------------------------------
+    Log.LogStatus('Main Loop', 'Initialization');
+    MainLoop;
+
+  {$IFNDEF Debug}
+  finally
+  {$ENDIF}
+    //------------------------------
+    // Finish Application
+    //------------------------------
+
+    // TODO:
+    // call an uninitialize routine for every initialize step
+    // or at least use the corresponding Free methods
+
+    Log.LogStatus('Finalize Media', 'Finalization');
+    FinalizeMedia();
+
+    Log.LogStatus('Uninitialize 3D', 'Finalization');
+    Finalize3D();
+
+    Log.LogStatus('Finalize SDL', 'Finalization');
+    SDL_Quit();
+
+    Log.LogStatus('Finalize Log', 'Finalization');
+    Log.Free;
+  {$IFNDEF Debug}
+  end;
+  {$ENDIF}
+end;
+
+procedure MainLoop;
+const
+  MAX_FPS = 100;
+var
+  Delay:            integer;
+  TicksCurrent:     cardinal;
+  TicksBeforeFrame: cardinal;
+  Done:             boolean;
+begin
+  SDL_EnableKeyRepeat(125, 125);
+
+  Done := false;
+
+  CountSkipTime();  // JB - for some reason this seems to be needed when we use the SDL Timer functions.
+  repeat
+    TicksBeforeFrame := SDL_GetTicks;
+    
+    // joypad
+    if (Ini.Joypad = 1) or (Params.Joypad) then
+      Joy.Update;
+
+    // keyboard events
+    CheckEvents;
+
+    // display
+    Done := not Display.Draw;
+    SwapBuffers;
+
+    // FPS limiter
+    TicksCurrent := SDL_GetTicks;
+    Delay := 1000 div MAX_FPS - (TicksCurrent - TicksBeforeFrame);
+
+    if Delay >= 1 then
+      SDL_Delay(Delay); // dynamic, maximum is 100 fps
+
+    CountSkipTime;
+
+  until Done;
+end;
+
+procedure DoQuit;
+begin
+  // if question option is enabled then show exit popup
+  if (Ini.AskbeforeDel = 1) then
+  begin
+    Display.CurrentScreen^.CheckFadeTo(nil,'MSG_QUIT_USDX');
+  end
+  else // if ask-for-exit is disabled then simply exit
+  begin
+    Display.Fade := 0;
+    Display.NextScreenWithCheck := nil;
+    Display.CheckOK := true;
+  end;
+end;
+
+procedure CheckEvents;
+var
+  Event:     TSDL_event;
+  mouseDown: boolean;
+  mouseBtn:  integer;
+  KeepGoing: boolean;
+begin
+  KeepGoing := true;
+  while (SDL_PollEvent(@Event) <> 0) do
+  begin
+    case Event.type_ of
+      SDL_QUITEV:
+      begin
+        Display.Fade := 0;
+        Display.NextScreenWithCheck := nil;
+        Display.CheckOK := true;
+      end;
+
+      SDL_MOUSEMOTION, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP:
+      begin
+        if (Ini.Mouse > 0) then
+        begin
+          case Event.type_ of
+            SDL_MOUSEMOTION:
+            begin
+              mouseDown := false;
+              mouseBtn  := 0;
+            end;
+            SDL_MOUSEBUTTONDOWN:
+            begin
+              mouseDown := true;
+              mouseBtn  := Event.button.button;
+              
+              if (mouseBtn = SDL_BUTTON_LEFT) or (mouseBtn = SDL_BUTTON_RIGHT) then
+                Display.OnMouseButton(true);
+            end;
+            SDL_MOUSEBUTTONUP:
+            begin
+              mouseDown := false;
+              mouseBtn  := Event.button.button;
+
+              if (mouseBtn = SDL_BUTTON_LEFT) or (mouseBtn = SDL_BUTTON_RIGHT) then
+                Display.OnMouseButton(false);
+            end;
+          end;
+
+          Display.MoveCursor(Event.button.X * 800 * Screens / ScreenW,
+                             Event.button.Y * 600 / ScreenH);
+
+          if not Assigned(Display.NextScreen) then
+          begin //drop input when changing screens
+            if (ScreenPopupError <> nil) and (ScreenPopupError.Visible) then
+              KeepGoing := ScreenPopupError.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y)
+            else if (ScreenPopupInfo <> nil) and (ScreenPopupInfo.Visible) then
+              KeepGoing := ScreenPopupInfo.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y)
+            else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
+              KeepGoing := ScreenPopupCheck.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y)
+            else
+            begin
+              KeepGoing := Display.CurrentScreen^.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y);
+
+              // if screen wants to exit
+              if not KeepGoing then
+                DoQuit;
+            end;
+          end;
+        end;
+      end;
+      SDL_VIDEORESIZE:
+      begin
+        ScreenW := Event.resize.w;
+        ScreenH := Event.resize.h;
+        // Note: do NOT call SDL_SetVideoMode on Windows and MacOSX here.
+        // This would create a new OpenGL render-context and all texture data
+        // would be invalidated.
+        // On Linux the mode MUST be reset, otherwise graphics will be corrupted.
+        // Update: It seems to work now without creating a new OpenGL context. At least
+        // with Win7 and SDL 1.2.14. Maybe it generally works now with SDL 1.2.14 and we
+        // can switch it on for windows.
+        // Important: Unless SDL_SetVideoMode() is called (it is not on Windows), Screen.w
+        // and Screen.h are not valid after a resize and still contain the old size. Use
+        // ScreenW and ScreenH instead.
+        {$IF Defined(Linux) or Defined(FreeBSD)}
+        if boolean( Ini.FullScreen ) then
+          SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_FULLSCREEN)
+        else
+          SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE);
+        {$ELSE}
+        Screen.W := ScreenW;
+        Screen.H := ScreenH;
+        {$IFEND}
+      end;
+      SDL_KEYDOWN:
+        begin
+          // translate CTRL-A (ASCII 1) - CTRL-Z (ASCII 26) to correct charcodes.
+          // keysyms (SDLK_A, ...) could be used instead but they ignore the
+          // current key mapping (if 'a' is pressed on a French keyboard the
+          // .unicode field will be 'a' and .sym SDLK_Q).
+          // IMPORTANT: if CTRL is pressed with a key different than 'A'-'Z' SDL
+          // will set .unicode to 0. There is no possibility to obtain a
+          // translated charcode. Use keysyms instead.
+          //if (Event.key.keysym.unicode in [1 .. 26]) then
+          //  Event.key.keysym.unicode := Ord('A') + Event.key.keysym.unicode - 1;
+
+          // remap the "keypad enter" key to the "standard enter" key
+          if (Event.key.keysym.sym = SDLK_KP_ENTER) then
+            Event.key.keysym.sym := SDLK_RETURN;
+
+          if not Assigned(Display.NextScreen) then
+          begin //drop input when changing screens
+            { to-do : F11 was used for fullscreen toggle, too here
+                      but we also use the key in screenname and some other
+                      screens. It is droped although fullscreen toggle doesn't
+                      even work on windows.
+                      should we add (Event.key.keysym.sym = SDLK_F11) here
+                      anyway? }
+            if ((Event.key.keysym.sym = SDLK_RETURN) and
+               ((Event.key.keysym.modifier and KMOD_ALT) <> 0)) then // toggle full screen
+            begin
+              Ini.FullScreen := integer( not boolean( Ini.FullScreen ) );
+
+              // FIXME: SDL_SetVideoMode creates a new OpenGL RC so we have to
+              // reload all texture data (-> whitescreen bug).
+              // Only Linux and FreeBSD are able to handle screen-switching this way.
+              {$IF Defined(Linux) or Defined(FreeBSD)}
+              if boolean( Ini.FullScreen ) then
+              begin
+                SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_FULLSCREEN);
+              end
+              else
+              begin
+                SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE);
+              end;
+
+              Display.SetCursor;
+
+              glViewPort(0, 0, ScreenW, ScreenH);
+              {$IFEND}
+            end
+            // if print is pressed -> make screenshot and save to screenshot path
+            else if (Event.key.keysym.sym = SDLK_SYSREQ) or (Event.key.keysym.sym = SDLK_PRINT) then
+              Display.SaveScreenShot
+            // if there is a visible popup then let it handle input instead of underlying screen
+            // shoud be done in a way to be sure the topmost popup has preference (maybe error, then check)
+            else if (ScreenPopupError <> nil) and (ScreenPopupError.Visible) then
+              KeepGoing := ScreenPopupError.ParseInput(Event.key.keysym.sym, Event.key.keysym.unicode, true)
+            else if (ScreenPopupInfo <> nil) and (ScreenPopupInfo.Visible) then
+              KeepGoing := ScreenPopupInfo.ParseInput(Event.key.keysym.sym, Event.key.keysym.unicode, true)
+            else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
+              KeepGoing := ScreenPopupCheck.ParseInput(Event.key.keysym.sym, Event.key.keysym.unicode, true)
+            else
+            begin
+              // check if screen wants to exit
+              KeepGoing := Display.ParseInput(Event.key.keysym.sym, Event.key.keysym.unicode, true);
+
+              // if screen wants to exit
+              if not KeepGoing then
+                DoQuit;
+
+            end;
+          end;
+        end;
+      SDL_JOYAXISMOTION:
+        begin
+          // not implemented
+        end;
+      SDL_JOYBUTTONDOWN:
+        begin
+          // not implemented
+        end;
+      MAINTHREAD_EXEC_EVENT:
+        with Event.user do
+        begin
+          TMainThreadExecProc(data1)(data2);
+        end;
+    end; // case
+  end; // while
+end;
+
+procedure MainThreadExec(Proc: TMainThreadExecProc; Data: Pointer);
+var
+  Event: TSDL_Event;
+begin
+  with Event.user do
+  begin
+    type_ := MAINTHREAD_EXEC_EVENT;
+    code  := 0;     // not used at the moment
+    data1 := @Proc;
+    data2 := Data;
+  end;
+  SDL_PushEvent(@Event);
+end;
+
+end.
diff --git a/songmanagement/src/base/UMusic.pas b/songmanagement/src/base/UMusic.pas
new file mode 100644
index 00000000..c775fd51
--- /dev/null
+++ b/songmanagement/src/base/UMusic.pas
@@ -0,0 +1,1235 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMusic;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  Classes,
+  UTime,
+  UBeatTimer,
+  UPath;
+
+type
+  TNoteType = (ntFreestyle, ntNormal, ntGolden);
+
+  {**
+   * acoStretch: Stretch to screen width and height
+   *   - ignores aspect
+   *   + no borders
+   *   + no image data loss
+   * acoCrop: Stretch to screen width or height, crop the other dimension
+   *   + keeps aspect
+   *   + no borders
+   *   - frame borders are cropped (image data loss)
+   * acoLetterBox: Stretch to screen width, add bars at or crop top and bottom
+   *   + keeps aspect
+   *   - borders at top and bottom
+   *   o top/bottom is cropped if width < height (unusual)
+   *}
+  TAspectCorrection = (acoStretch, acoCrop, acoLetterBox);
+
+  TRectCoords = record
+    Left, Right:  double;
+    Upper, Lower: double;
+  end;
+
+const
+  // ScoreFactor defines how a notehit of a specified notetype is
+  // measured in comparison to the other types
+  // 0 means this notetype is not rated at all
+  // 2 means a hit of this notetype will be rated w/ twice as much
+  // points as a hit of a notetype w/ ScoreFactor 1
+  ScoreFactor:         array[TNoteType] of integer = (0, 1, 2);
+
+type
+  (**
+   * TLineFragment represents a fragment of a lyrics line.
+   * This is a text-fragment (e.g. a syllable) assigned to a note pitch,
+   * represented by a bar in the sing-screen.
+   *)
+  PLineFragment = ^TLineFragment;
+  TLineFragment = record
+    Color:      integer;
+    Start:      integer;    // beat the fragment starts at
+    Length:     integer;    // length in beats
+    Tone:       integer;    // full range tone
+    Text:       UTF8String; // text assigned to this fragment (a syllable, word, etc.)
+    NoteType:   TNoteType;  // note-type: golden-note/freestyle etc.
+  end;
+
+  (**
+   * TLine represents one lyrics line and consists of multiple
+   * notes.
+   *)
+  PLine = ^TLine;
+  TLine = record
+    Start:      integer; // the start beat of this line (<> start beat of the first note of this line)
+    Lyric:      UTF8String;
+    //LyricWidth: real;    // @deprecated: width of the line in pixels.
+                         // Do not use this as the width is not correct.
+                         // Use TLyricsEngine.GetUpperLine().Width instead. 
+    End_:       integer;
+    BaseNote:   integer;
+    HighNote:   integer; // index of last note in line (= High(Note)?)
+    TotalNotes: integer; // value of all notes in the line
+    LastLine:   boolean;
+    Note:       array of TLineFragment;
+  end;
+
+  (**
+   * TLines stores sets of lyric lines and information on them.
+   * Normally just one set is defined but in duet mode it might for example
+   * contain two sets.  
+   *)
+  TLines = record
+    Current:    integer;  // for drawing of current line
+    High:       integer;  // = High(Line)!
+    Number:     integer;
+    Resolution: integer;
+    NotesGAP:   integer;
+    ScoreValue: integer;
+    Line:       array of TLine;
+  end;
+
+const
+  FFTSize = 512; // size of FFT data (output: FFTSize/2 values)
+type
+  TFFTData  = array[0..(FFTSize div 2)-1] of Single;
+
+type
+  PPCMStereoSample = ^TPCMStereoSample;
+  TPCMStereoSample = array[0..1] of SmallInt;
+  TPCMData  = array[0..511] of TPCMStereoSample;
+
+type
+  TStreamStatus = (ssStopped, ssPlaying, ssPaused);
+const
+  StreamStatusStr:  array[TStreamStatus] of string =
+    ('Stopped', 'Playing', 'Paused');
+
+type
+  TAudioSampleFormat = (
+    asfU8, asfS8,         // unsigned/signed  8 bits
+    asfU16LSB, asfS16LSB, // unsigned/signed 16 bits (endianness: LSB)
+    asfU16MSB, asfS16MSB, // unsigned/signed 16 bits (endianness: MSB)
+    asfU16, asfS16,       // unsigned/signed 16 bits (endianness: System)
+    asfS32,               // signed 32 bits (endianness: System)
+    asfFloat,             // float
+    asfDouble             // double
+  );
+
+const
+  // Size of one sample (one channel only) in bytes
+  AudioSampleSize: array[TAudioSampleFormat] of integer = (
+    1, 1,     // asfU8, asfS8
+    2, 2,     // asfU16LSB, asfS16LSB
+    2, 2,     // asfU16MSB, asfS16MSB
+    2, 2,     // asfU16,    asfS16
+    3,        // asfS24
+    4,        // asfS32
+    4         // asfFloat
+  );
+
+const
+  CHANNELMAP_LEFT  = 1;
+  CHANNELMAP_RIGHT = 2;
+  CHANNELMAP_FRONT = CHANNELMAP_LEFT or CHANNELMAP_RIGHT;
+
+type
+  TAudioFormatInfo = class
+    private
+      fSampleRate : double;
+      fChannels   : byte;
+      fFormat     : TAudioSampleFormat;
+      fFrameSize  : integer;
+
+      procedure SetChannels(Channels: byte);
+      procedure SetFormat(Format: TAudioSampleFormat);
+      procedure UpdateFrameSize();
+      function GetBytesPerSec(): double;
+    public
+      constructor Create(Channels: byte; SampleRate: double; Format: TAudioSampleFormat);
+      function Copy(): TAudioFormatInfo;
+
+      (**
+       * Returns the inverse ratio of the size of data in this format to its
+       * size in a given target format.
+       * Example: SrcSize*SrcInfo.GetRatio(TgtInfo) = TgtSize
+       *)
+      function GetRatio(TargetInfo: TAudioFormatInfo): double;
+
+      property SampleRate: double read fSampleRate write fSampleRate;
+      property Channels: byte read fChannels write SetChannels;
+      property Format: TAudioSampleFormat read fFormat write SetFormat;
+      property FrameSize: integer read fFrameSize;
+      property BytesPerSec: double read GetBytesPerSec;
+  end;
+
+type
+  TSoundEffect = class
+    public
+      EngineData: Pointer; // can be used for engine-specific data
+      procedure Callback(Buffer: PByteArray; BufSize: integer); virtual; abstract;
+  end;
+
+  TVoiceRemoval = class(TSoundEffect)
+    public
+      procedure Callback(Buffer: PByteArray; BufSize: integer); override;
+  end;
+
+type
+  TAudioProcessingStream = class;
+  TOnCloseHandler = procedure(Stream: TAudioProcessingStream);
+
+  TAudioProcessingStream = class
+    protected
+      OnCloseHandlers: array of TOnCloseHandler;
+
+      function GetLength(): real;           virtual; abstract;
+      function GetPosition(): real;         virtual; abstract;
+      procedure SetPosition(Time: real);    virtual; abstract;
+      function GetLoop(): boolean;          virtual; abstract;
+      procedure SetLoop(Enabled: boolean);  virtual; abstract;
+
+      procedure PerformOnClose();
+    public
+      function GetAudioFormatInfo(): TAudioFormatInfo; virtual; abstract;
+      procedure Close(); virtual; abstract;
+
+      (**
+       * Adds a new OnClose action handler.
+       * The handlers are performed in the order they were added.
+       * If not stated explicitely, member-variables might have been invalidated
+       * already. So do not use any member (variable/method/...) if you are not
+       * sure it is valid.
+       *)
+      procedure AddOnCloseHandler(Handler: TOnCloseHandler);
+
+      property Length: real read GetLength;
+      property Position: real read GetPosition write SetPosition;
+      property Loop: boolean read GetLoop write SetLoop;
+  end;
+
+  TAudioSourceStream = class(TAudioProcessingStream)
+    protected
+      function IsEOF(): boolean;            virtual; abstract;
+      function IsError(): boolean;          virtual; abstract;
+    public
+      function ReadData(Buffer: PByteArray; BufferSize: integer): integer; virtual; abstract;
+
+      property EOF: boolean read IsEOF;
+      property Error: boolean read IsError;
+  end;
+
+  (*
+   * State-Chart for playback-stream state transitions
+   * []: Transition, (): State
+   *
+   *               /---[Play/FadeIn]--->-\  /-------[Pause]----->-\
+   * -[Create]->(Stop)                  (Play)                 (Pause)
+   *              \\-<-[Stop/EOF*/Error]-/  \-<---[Play/FadeIn]--//
+   *               \-<------------[Stop/EOF*/Error]--------------/
+   *
+   * *: if not looped, otherwise stream is repeated
+   * Note: SetPosition() does not change the state.
+   *)
+
+  TAudioPlaybackStream = class(TAudioProcessingStream)
+    protected
+      AvgSyncDiff: double;  //** average difference between stream and sync clock
+      SyncSource: TSyncSource;
+      SourceStream: TAudioSourceStream;
+
+      function GetLatency(): double; virtual; abstract;
+      function GetStatus(): TStreamStatus;  virtual; abstract;
+      function GetVolume(): single;         virtual; abstract;
+      procedure SetVolume(Volume: single);  virtual; abstract;
+      function Synchronize(BufferSize: integer; FormatInfo: TAudioFormatInfo): integer;
+      procedure FillBufferWithFrame(Buffer: PByteArray; BufferSize: integer; Frame: PByteArray; FrameSize: integer);
+    public
+      (**
+       * Opens a SourceStream for playback.
+       * Note that the caller (not the TAudioPlaybackStream) is responsible to
+       * free the SourceStream after the Playback-Stream is closed.
+       * You may use an OnClose-handler to achieve this. GetSourceStream()
+       * guarantees to deliver this method's SourceStream parameter to
+       * the OnClose-handler. Freeing SourceStream at OnClose is allowed. 
+       *)
+      function Open(SourceStream: TAudioSourceStream): boolean; virtual; abstract;
+
+      procedure Play();                     virtual; abstract;
+      procedure Pause();                    virtual; abstract;
+      procedure Stop();                     virtual; abstract;
+      procedure FadeIn(Time: real; TargetVolume: single);  virtual; abstract;
+
+      procedure GetFFTData(var data: TFFTData);          virtual; abstract;
+      function GetPCMData(var data: TPCMData): Cardinal; virtual; abstract;
+
+      procedure AddSoundEffect(Effect: TSoundEffect);    virtual; abstract;
+      procedure RemoveSoundEffect(Effect: TSoundEffect); virtual; abstract;
+
+      procedure SetSyncSource(SyncSource: TSyncSource);
+      function GetSourceStream(): TAudioSourceStream;
+
+      property Status: TStreamStatus read GetStatus;
+      property Volume: single read GetVolume write SetVolume;
+  end;
+
+  TAudioDecodeStream = class(TAudioSourceStream)
+  end;
+
+  TAudioVoiceStream = class(TAudioSourceStream)
+    protected
+      FormatInfo: TAudioFormatInfo;
+      ChannelMap: integer;
+    public
+      destructor Destroy; override;
+
+      function Open(ChannelMap: integer; FormatInfo: TAudioFormatInfo): boolean; virtual;
+      procedure Close(); override;
+
+      procedure WriteData(Buffer: PByteArray; BufferSize: integer); virtual; abstract;
+      function GetAudioFormatInfo(): TAudioFormatInfo; override;
+
+      function GetLength(): real;           override;
+      function GetPosition(): real;         override;
+      procedure SetPosition(Time: real);    override;
+      function GetLoop(): boolean;          override;
+      procedure SetLoop(Enabled: boolean);  override;
+  end;
+
+type
+  // soundcard output-devices information
+  TAudioOutputDevice = class
+    public
+      Name: UTF8String; // soundcard name
+  end;
+  TAudioOutputDeviceList = array of TAudioOutputDevice;
+
+type
+  IGenericPlayback = Interface
+  ['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}']
+      function GetName: String;
+  end;
+
+  IVideo = interface
+  ['{58DFC674-9168-41EA-B59D-A61307242B80}']
+      procedure Play;
+      procedure Pause;
+      procedure Stop;
+
+      procedure SetLoop(Enable: boolean);
+      function GetLoop(): boolean;
+
+      procedure SetPosition(Time: real);
+      function GetPosition: real;
+
+      procedure SetScreen(Screen: integer);
+      function GetScreen(): integer;
+      
+      procedure SetScreenPosition(X, Y: double; Z: double = 0.0);
+      procedure GetScreenPosition(var X, Y, Z: double);
+
+      procedure  SetWidth(Width: double);
+       function GetWidth(): double;
+      
+      procedure  SetHeight(Height: double);
+       function GetHeight(): double;
+      
+      {**
+       * Sub-image of the video frame to draw.
+       * This can be used for zooming or similar purposes.
+       *}
+      procedure SetFrameRange(Range: TRectCoords);
+      function GetFrameRange(): TRectCoords;
+      
+      function GetFrameAspect(): real;
+      
+      procedure SetAspectCorrection(AspectCorrection: TAspectCorrection);
+      function GetAspectCorrection(): TAspectCorrection;
+      
+
+      procedure SetAlpha(Alpha: double);
+      function GetAlpha(): double;
+      
+      procedure SetReflectionSpacing(Spacing: double);
+      function GetReflectionSpacing(): double;
+
+      procedure GetFrame(Time: Extended);
+      procedure Draw();
+      procedure DrawReflection();
+       
+       
+      property Screen: integer read GetScreen;
+      property Width: double read GetWidth write SetWidth;
+      property Height: double read GetHeight write SetHeight;
+      property Alpha: double read GetAlpha write SetAlpha;
+      property ReflectionSpacing: double read GetReflectionSpacing write SetReflectionSpacing;
+      property FrameAspect: real read GetFrameAspect;
+      property AspectCorrection: TAspectCorrection read GetAspectCorrection write SetAspectCorrection;
+      property Loop: boolean read GetLoop write SetLoop;
+      property Position: real read GetPosition write SetPosition;
+  end;
+
+  IVideoPlayback = Interface( IGenericPlayback )
+  ['{3574C40C-28AE-4201-B3D1-3D1F0759B131}']
+      function Init(): boolean;
+      function Finalize: boolean;
+
+      function Open(const FileName : IPath): IVideo;
+  end;
+
+  IVideoVisualization = Interface( IVideoPlayback )
+  ['{5AC17D60-B34D-478D-B632-EB00D4078017}']
+  end;
+
+  IAudioPlayback = Interface( IGenericPlayback )
+  ['{E4AE0B40-3C21-4DC5-847C-20A87E0DFB96}']
+      function InitializePlayback: boolean;
+      function FinalizePlayback: boolean;
+      
+      function GetOutputDeviceList(): TAudioOutputDeviceList;
+
+      procedure SetAppVolume(Volume: single);
+      procedure SetVolume(Volume: single);
+      procedure SetLoop(Enabled: boolean);
+
+      procedure FadeIn(Time: real; TargetVolume: single);
+      procedure SetSyncSource(SyncSource: TSyncSource);
+
+      procedure Rewind;
+      function  Finished: boolean;
+      function  Length: real;
+
+      function Open(const Filename: IPath): boolean; // true if succeed
+      procedure Close;
+
+      procedure Play;
+      procedure Pause;
+      procedure Stop;
+
+      procedure SetPosition(Time: real);
+      function GetPosition: real;
+
+      property Position: real read GetPosition write SetPosition;
+
+      // Sounds
+      // TODO:
+      // add a TMediaDummyPlaybackStream implementation that will
+      // be used by the TSoundLib whenever OpenSound() fails, so checking for
+      // nil-pointers is not neccessary anymore.
+      // PlaySound/StopSound will be removed then, OpenSound will be renamed to
+      // CreateSound.
+      function OpenSound(const Filename: IPath): TAudioPlaybackStream;
+      procedure PlaySound(Stream: TAudioPlaybackStream);
+      procedure StopSound(Stream: TAudioPlaybackStream);
+
+      // Equalizer
+      procedure GetFFTData(var Data: TFFTData);
+
+      // Interface for Visualizer
+      function GetPCMData(var Data: TPCMData): Cardinal;
+
+      function CreateVoiceStream(ChannelMap: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream;
+  end;
+
+  IGenericDecoder = Interface
+  ['{557B0E9A-604D-47E4-B826-13769F3E10B7}']
+      function GetName(): string;
+      function InitializeDecoder(): boolean;
+      function FinalizeDecoder(): boolean;
+      //function IsSupported(const Filename: string): boolean;
+  end;
+
+  (*
+  IVideoDecoder = Interface( IGenericDecoder )
+  ['{2F184B2B-FE69-44D5-9031-0A2462391DCA}']
+       function Open(const Filename: IPath): TVideoDecodeStream;
+
+       procedure SetPosition(Time: real);
+       function GetPosition:  real;
+
+       procedure UpdateTexture(Texture: glUint);
+
+       property Loop: boolean read GetLoop write SetLoop;
+       property Position: real read GetPosition write SetPosition;
+  end;
+  *)
+
+  IAudioDecoder = Interface( IGenericDecoder )
+  ['{AB47B1B6-2AA9-4410-BF8C-EC79561B5478}']
+      function Open(const Filename: IPath): TAudioDecodeStream;
+  end;
+
+  IAudioInput = Interface
+  ['{A5C8DA92-2A0C-4AB2-849B-2F7448C6003A}']
+      function GetName: String;
+      function InitializeRecord: boolean;
+      function FinalizeRecord(): boolean;
+
+      procedure CaptureStart;
+      procedure CaptureStop;
+  end;
+
+type
+  TAudioConverter = class
+    protected
+      fSrcFormatInfo: TAudioFormatInfo;
+      fDstFormatInfo: TAudioFormatInfo;
+    public
+      function Init(SrcFormatInfo: TAudioFormatInfo; DstFormatInfo: TAudioFormatInfo): boolean; virtual;
+      destructor Destroy(); override;
+
+      (**
+       * Converts the InputBuffer and stores the result in OutputBuffer.
+       * If the result is not -1, InputSize will be set to the actual number of
+       * input-buffer bytes used.
+       * Returns the number of bytes written to the output-buffer or -1 if an error occured.
+       *)
+      function Convert(InputBuffer: PByteArray; OutputBuffer: PByteArray; var InputSize: integer): integer; virtual; abstract;
+
+      (**
+       * Destination/Source size ratio
+       *)
+      function GetRatio(): double; virtual; abstract;
+
+      function GetOutputBufferSize(InputSize: integer): integer; virtual; abstract;
+      property SrcFormatInfo: TAudioFormatInfo read fSrcFormatInfo;
+      property DstFormatInfo: TAudioFormatInfo read fDstFormatInfo;
+  end;
+
+(* TODO
+const
+  SOUNDID_START    = 0;
+  SOUNDID_BACK     = 1;
+  SOUNDID_SWOOSH   = 2;
+  SOUNDID_CHANGE   = 3;
+  SOUNDID_OPTION   = 4;
+  SOUNDID_CLICK    = 5;
+  LAST_SOUNDID = SOUNDID_CLICK;
+
+  BaseSoundFilenames: array[0..LAST_SOUNDID] of IPath = (
+    '%SOUNDPATH%/Common start.mp3',                 // Start
+    '%SOUNDPATH%/Common back.mp3',                  // Back
+    '%SOUNDPATH%/menu swoosh.mp3',                  // Swoosh
+    '%SOUNDPATH%/select music change music 50.mp3', // Change
+    '%SOUNDPATH%/option change col.mp3',            // Option
+    '%SOUNDPATH%/rimshot022b.mp3'                   // Click
+    {
+    '%SOUNDPATH%/bassdrumhard076b.mp3',             // Drum (unused)
+    '%SOUNDPATH%/hihatclosed068b.mp3',              // Hihat (unused)
+    '%SOUNDPATH%/claps050b.mp3',                    // Clap (unused)
+    '%SOUNDPATH%/Shuffle.mp3'                       // Shuffle (unused)
+    }
+  );
+*)
+
+type
+  TSoundLibrary = class
+    private
+      // TODO
+      //Sounds: array of TAudioPlaybackStream;
+    public
+      // TODO: move sounds to the private section
+      // and provide IDs instead.
+      Start:   TAudioPlaybackStream;
+      Back:    TAudioPlaybackStream;
+      Swoosh:  TAudioPlaybackStream;
+      Change:  TAudioPlaybackStream;
+      Option:  TAudioPlaybackStream;
+      Click:   TAudioPlaybackStream;
+      BGMusic: TAudioPlaybackStream;
+
+      constructor Create();
+      destructor Destroy(); override;
+
+      procedure LoadSounds();
+      procedure UnloadSounds();
+
+      procedure StartBgMusic();
+      procedure PauseBgMusic();
+      // TODO
+      //function AddSound(Filename: IPath): integer;
+      //procedure RemoveSound(ID: integer);
+      //function GetSound(ID: integer): TAudioPlaybackStream;
+      //property Sound[ID: integer]: TAudioPlaybackStream read GetSound; default;
+  end;
+
+var
+  // TODO: JB --- THESE SHOULD NOT BE GLOBAL
+  Lines: array of TLines;
+  LyricsState: TLyricsState;
+  SoundLib: TSoundLibrary;
+
+
+procedure InitializeSound;
+procedure InitializeVideo;
+procedure FinalizeMedia;
+
+function  Visualization(): IVideoPlayback;
+function  VideoPlayback(): IVideoPlayback;
+function  AudioPlayback(): IAudioPlayback;
+function  AudioInput(): IAudioInput;
+function  AudioDecoders(): TInterfaceList;
+
+function  MediaManager: TInterfaceList;
+
+procedure DumpMediaInterfaces();
+
+implementation
+
+uses
+  math,
+  UIni,
+  UNote,
+  UCommandLine,
+  URecord,
+  ULog,
+  UPathUtils;
+
+var
+  DefaultVideoPlayback : IVideoPlayback;
+  DefaultVisualization : IVideoPlayback;
+  DefaultAudioPlayback : IAudioPlayback;
+  DefaultAudioInput    : IAudioInput;
+  AudioDecoderList     : TInterfaceList;
+  MediaInterfaceList   : TInterfaceList;
+
+
+constructor TAudioFormatInfo.Create(Channels: byte; SampleRate: double; Format: TAudioSampleFormat);
+begin
+  inherited Create();
+  fChannels := Channels;
+  fSampleRate := SampleRate;
+  fFormat := Format;
+  UpdateFrameSize();
+end;
+
+procedure TAudioFormatInfo.SetChannels(Channels: byte);
+begin
+  fChannels := Channels;
+  UpdateFrameSize();
+end;
+
+procedure TAudioFormatInfo.SetFormat(Format: TAudioSampleFormat);
+begin
+  fFormat := Format;
+  UpdateFrameSize();
+end;
+
+function TAudioFormatInfo.GetBytesPerSec(): double;
+begin
+  Result := FrameSize * SampleRate; 
+end;
+
+procedure TAudioFormatInfo.UpdateFrameSize();
+begin
+  fFrameSize := AudioSampleSize[fFormat] * fChannels;
+end;
+
+function TAudioFormatInfo.Copy(): TAudioFormatInfo;
+begin
+  Result := TAudioFormatInfo.Create(Self.Channels, Self.SampleRate, Self.Format);
+end;
+
+function TAudioFormatInfo.GetRatio(TargetInfo: TAudioFormatInfo): double;
+begin
+  Result := (TargetInfo.FrameSize / Self.FrameSize) *
+            (TargetInfo.SampleRate / Self.SampleRate)
+end;
+
+
+function MediaManager: TInterfaceList;
+begin
+  if (not assigned(MediaInterfaceList)) then
+    MediaInterfaceList := TInterfaceList.Create();
+  Result := MediaInterfaceList;
+end;
+
+function  VideoPlayback(): IVideoPlayback;
+begin
+  Result := DefaultVideoPlayback;
+end;
+
+function  Visualization(): IVideoPlayback;
+begin
+  Result := DefaultVisualization;
+end;
+
+function AudioPlayback(): IAudioPlayback;
+begin
+  Result := DefaultAudioPlayback;
+end;
+
+function AudioInput(): IAudioInput;
+begin
+  Result := DefaultAudioInput;
+end;
+
+function AudioDecoders(): TInterfaceList;
+begin
+  Result := AudioDecoderList;
+end;
+
+procedure FilterInterfaceList(const IID: TGUID; InList, OutList: TInterfaceList);
+var
+  i: integer;
+  obj: IInterface;
+begin
+  if (not assigned(OutList)) then
+    Exit;
+
+  OutList.Clear;
+  for i := 0 to InList.Count-1 do
+  begin
+    if assigned(InList[i]) then
+    begin
+      // add object to list if it implements the interface searched for
+      if (InList[i].QueryInterface(IID, obj) = 0) then
+        OutList.Add(obj);
+    end;
+  end;
+end;
+
+procedure InitializeSound;
+var
+  i: integer;
+  InterfaceList: TInterfaceList;
+  CurrentAudioDecoder: IAudioDecoder;
+  CurrentAudioPlayback: IAudioPlayback;
+  CurrentAudioInput: IAudioInput;
+begin
+  // create a temporary list for interface enumeration
+  InterfaceList := TInterfaceList.Create();
+
+  // initialize all audio-decoders first
+  FilterInterfaceList(IAudioDecoder, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+  begin
+    CurrentAudioDecoder := InterfaceList[i] as IAudioDecoder;
+    if (not CurrentAudioDecoder.InitializeDecoder()) then
+    begin
+      Log.LogError('Initialize failed, Removing - '+ CurrentAudioDecoder.GetName);
+      MediaManager.Remove(CurrentAudioDecoder);
+    end;
+  end;
+
+  // create and setup decoder-list (see AudioDecoders())
+  AudioDecoderList := TInterfaceList.Create;
+  FilterInterfaceList(IAudioDecoder, MediaManager, AudioDecoders);
+
+  // find and initialize playback interface
+  DefaultAudioPlayback := nil;
+  FilterInterfaceList(IAudioPlayback, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+  begin
+    CurrentAudioPlayback := InterfaceList[i] as IAudioPlayback;
+    if (CurrentAudioPlayback.InitializePlayback()) then
+    begin
+      DefaultAudioPlayback := CurrentAudioPlayback;
+      break;
+    end;
+    Log.LogError('Initialize failed, Removing - '+ CurrentAudioPlayback.GetName);
+    MediaManager.Remove(CurrentAudioPlayback);
+  end;
+
+  // find and initialize input interface
+  DefaultAudioInput := nil;
+  FilterInterfaceList(IAudioInput, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+  begin
+    CurrentAudioInput := InterfaceList[i] as IAudioInput;
+    if (CurrentAudioInput.InitializeRecord()) then
+    begin
+      DefaultAudioInput := CurrentAudioInput;
+      break;
+    end;
+    Log.LogError('Initialize failed, Removing - '+ CurrentAudioInput.GetName);
+    MediaManager.Remove(CurrentAudioInput);
+  end;
+
+  InterfaceList.Free;
+
+  // Update input-device list with registered devices
+  AudioInputProcessor.UpdateInputDeviceConfig();
+
+  // Load in-game sounds
+  SoundLib := TSoundLibrary.Create;
+end;
+
+procedure InitializeVideo();
+var
+  i: integer;
+  InterfaceList: TInterfaceList;
+  VideoInterface: IVideoPlayback;
+  VisualInterface: IVideoVisualization;
+begin
+  InterfaceList := TInterfaceList.Create;
+
+  // initialize and set video-playback singleton
+  DefaultVideoPlayback := nil;
+  FilterInterfaceList(IVideoPlayback, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+  begin
+    VideoInterface := InterfaceList[i] as IVideoPlayback;
+    if (VideoInterface.Init()) then
+    begin
+      DefaultVideoPlayback := VideoInterface;
+      break;
+    end;
+    Log.LogError('Initialize failed, Removing - '+ VideoInterface.GetName);
+    MediaManager.Remove(VideoInterface);
+  end;
+
+  // initialize and set visualization singleton
+  DefaultVisualization := nil;
+  FilterInterfaceList(IVideoVisualization, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+  begin
+    VisualInterface := InterfaceList[i] as IVideoVisualization;
+    if (VisualInterface.Init()) then
+    begin
+      DefaultVisualization := VisualInterface;
+      break;
+    end;
+    Log.LogError('Initialize failed, Removing - '+ VisualInterface.GetName);
+    MediaManager.Remove(VisualInterface);
+  end;
+
+  InterfaceList.Free;
+
+  // now that we have all interfaces, we can dump them
+  // TODO: move this to another place
+  if FindCmdLineSwitch(cMediaInterfaces) then
+  begin
+    DumpMediaInterfaces();
+    halt;
+  end;
+end;
+
+procedure UnloadMediaModules;
+var
+  i: integer;
+  InterfaceList: TInterfaceList;
+begin
+  FreeAndNil(AudioDecoderList);
+  DefaultAudioPlayback := nil;
+  DefaultAudioInput := nil;
+  DefaultVideoPlayback := nil;
+  DefaultVisualization := nil;
+
+  // create temporary interface list
+  InterfaceList := TInterfaceList.Create();
+
+  // finalize audio playback interfaces (should be done before the decoders)
+  FilterInterfaceList(IAudioPlayback, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+    (InterfaceList[i] as IAudioPlayback).FinalizePlayback();
+
+  // finalize audio input interfaces
+  FilterInterfaceList(IAudioInput, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+    (InterfaceList[i] as IAudioInput).FinalizeRecord();
+
+  // finalize audio decoder interfaces
+  FilterInterfaceList(IAudioDecoder, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+    (InterfaceList[i] as IAudioDecoder).FinalizeDecoder();
+
+  // finalize video interfaces
+  FilterInterfaceList(IVideoPlayback, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+    (InterfaceList[i] as IVideoPlayback).Finalize();
+
+  // finalize audio decoder interfaces
+  FilterInterfaceList(IVideoVisualization, MediaManager, InterfaceList);
+  for i := 0 to InterfaceList.Count-1 do
+    (InterfaceList[i] as IVideoVisualization).Finalize();
+
+  InterfaceList.Free;
+
+  // finally free interfaces (by removing all references to them)
+  FreeAndNil(MediaInterfaceList);
+end;
+
+procedure FinalizeMedia;
+begin
+  // stop, close and free sounds
+  SoundLib.Free;
+
+  // stop and close music stream
+  if (AudioPlayback <> nil) then
+    AudioPlayback.Close;
+
+  // stop any active captures
+  if (AudioInput <> nil) then
+    AudioInput.CaptureStop;
+
+  UnloadMediaModules();
+end;
+
+procedure DumpMediaInterfaces();
+begin
+  writeln( '' );
+  writeln( '--------------------------------------------------------------' );
+  writeln( '  In-use Media Interfaces                                     ' );
+  writeln( '--------------------------------------------------------------' );
+  writeln( 'Registered Audio Playback Interface : ' + AudioPlayback.GetName );
+  writeln( 'Registered Audio Input    Interface : ' + AudioInput.GetName    );
+  writeln( 'Registered Video Playback Interface : ' + VideoPlayback.GetName );
+  writeln( 'Registered Visualization  Interface : ' + Visualization.GetName );
+  writeln( '--------------------------------------------------------------' );
+  writeln( '' );
+end;
+
+
+{ TSoundLibrary }
+
+constructor TSoundLibrary.Create();
+begin
+  inherited;
+  LoadSounds();
+end;
+
+destructor TSoundLibrary.Destroy();
+begin
+  UnloadSounds();
+  inherited;
+end;
+
+procedure TSoundLibrary.LoadSounds();
+begin
+  UnloadSounds();
+
+  Start   := AudioPlayback.OpenSound(SoundPath.Append('Common start.mp3'));
+  Back    := AudioPlayback.OpenSound(SoundPath.Append('Common back.mp3'));
+  Swoosh  := AudioPlayback.OpenSound(SoundPath.Append('menu swoosh.mp3'));
+  Change  := AudioPlayback.OpenSound(SoundPath.Append('select music change music 50.mp3'));
+  Option  := AudioPlayback.OpenSound(SoundPath.Append('option change col.mp3'));
+  Click   := AudioPlayback.OpenSound(SoundPath.Append('rimshot022b.mp3'));
+
+  BGMusic := AudioPlayback.OpenSound(SoundPath.Append('background track.mp3'));
+
+  if (BGMusic <> nil) then
+    BGMusic.Loop := True;
+end;
+
+procedure TSoundLibrary.UnloadSounds();
+begin
+  FreeAndNil(Start);
+  FreeAndNil(Back);
+  FreeAndNil(Swoosh);
+  FreeAndNil(Change);
+  FreeAndNil(Option);
+  FreeAndNil(Click);
+  FreeAndNil(BGMusic);
+end;
+
+(* TODO
+function TSoundLibrary.GetSound(ID: integer): TAudioPlaybackStream;
+begin
+  if ((ID >= 0) and (ID < Length(Sounds))) then
+    Result := Sounds[ID]
+  else
+    Result := nil;
+end;
+*)
+
+procedure TSoundLibrary.StartBgMusic();
+begin
+  if (TBackgroundMusicOption(Ini.BackgroundMusicOption) = bmoOn) and
+    (Soundlib.BGMusic <> nil) and not (Soundlib.BGMusic.Status = ssPlaying) then
+  begin
+    AudioPlayback.PlaySound(Soundlib.BGMusic);
+  end;
+end;
+
+procedure TSoundLibrary.PauseBgMusic();
+begin
+  If (Soundlib.BGMusic <> nil) then
+  begin
+    Soundlib.BGMusic.Pause;
+  end;
+end;
+
+{ TVoiceRemoval }
+
+procedure TVoiceRemoval.Callback(Buffer: PByteArray; BufSize: integer);
+var
+  FrameIndex, FrameSize: integer;
+  Value: integer;
+  Sample: PPCMStereoSample;
+begin
+  FrameSize := 2 * SizeOf(SmallInt);
+  for FrameIndex := 0 to (BufSize div FrameSize)-1 do
+  begin
+    Sample := PPCMStereoSample(Buffer);
+    // channel difference
+    Value := Sample[0] - Sample[1];
+    // clip
+    if (Value > High(SmallInt)) then
+      Value := High(SmallInt)
+    else if (Value < Low(SmallInt)) then
+      Value := Low(SmallInt);
+    // assign result
+    Sample[0] := Value;
+    Sample[1] := Value;
+    // increase to next frame
+    Inc(PByte(Buffer), FrameSize);
+  end;
+end;
+
+{ TAudioConverter }
+
+function TAudioConverter.Init(SrcFormatInfo: TAudioFormatInfo; DstFormatInfo: TAudioFormatInfo): boolean;
+begin
+  fSrcFormatInfo := SrcFormatInfo.Copy();
+  fDstFormatInfo := DstFormatInfo.Copy();
+  Result := true;
+end;
+
+destructor TAudioConverter.Destroy();
+begin
+  FreeAndNil(fSrcFormatInfo);
+  FreeAndNil(fDstFormatInfo);
+end;
+
+
+{ TAudioProcessingStream }
+
+procedure TAudioProcessingStream.AddOnCloseHandler(Handler: TOnCloseHandler);
+begin
+  if (@Handler <> nil) then
+  begin
+    SetLength(OnCloseHandlers, System.Length(OnCloseHandlers)+1);
+    OnCloseHandlers[High(OnCloseHandlers)] := @Handler;
+  end;
+end;
+
+procedure TAudioProcessingStream.PerformOnClose();
+var i: integer;
+begin
+  for i := 0 to High(OnCloseHandlers) do
+  begin
+    OnCloseHandlers[i](Self);
+  end;
+end;
+
+
+{ TAudioPlaybackStream }
+
+function TAudioPlaybackStream.GetSourceStream(): TAudioSourceStream;
+begin
+  Result := SourceStream;
+end;
+
+procedure TAudioPlaybackStream.SetSyncSource(SyncSource: TSyncSource);
+begin
+  Self.SyncSource := SyncSource;
+  AvgSyncDiff := -1;
+end;
+
+{.$DEFINE LOG_SYNC}
+
+(*
+ * Results an adjusted size of the input buffer size to keep the stream in sync
+ * with the SyncSource. If no SyncSource was assigned to this stream, the
+ * input buffer size will be returned, so this method will have no effect.
+ *
+ * These are the possible cases:
+ *   - Result > BufferSize: stream is behind the sync-source (stream is too slow),
+ *                          (Result-BufferSize) bytes of the buffer must be skipped.
+ *   - Result = BufferSize: stream is in sync,
+ *                          there is nothing to do.
+ *   - Result < BufferSize: stream is ahead of the sync-source (stream is too fast),
+ *                          (BufferSize-Result) bytes of the buffer must be padded.
+ *)
+function TAudioPlaybackStream.Synchronize(BufferSize: integer; FormatInfo: TAudioFormatInfo): integer;
+var
+  TimeDiff: double;
+  FrameDiff: double;
+  FrameSkip: integer;
+  ReqFrames: integer;
+  MasterClock: real;
+  CurPosition: real;
+const
+  AVG_HISTORY_FACTOR = 0.7;
+  SYNC_REPOS_THRESHOLD = 5.000;
+  SYNC_SOFT_THRESHOLD  = 0.010;
+begin
+  Result := BufferSize;
+
+  if (not assigned(SyncSource)) then
+    Exit;
+
+  if (BufferSize <= 0) then
+    Exit;
+
+  CurPosition := Position;
+  MasterClock := SyncSource.GetClock();
+
+  // difference between sync-source and stream position
+  // (negative if the music-stream's position is ahead of the master clock)
+  TimeDiff := MasterClock - CurPosition;
+
+  // calculate average time difference (some sort of weighted mean).
+  // The bigger AVG_HISTORY_FACTOR is, the smoother is the average diff.
+  // This means that older diffs are weighted more with a higher history factor
+  // than with a lower. Do not use a too low history factor. FFmpeg produces
+  // very instable timestamps (pts) for ogg due to some bugs. They may differ
+  // +-50ms from the real stream position. Without filtering those glitches we
+  // would synch without any need, resulting in ugly plopping sounds.
+  if (AvgSyncDiff = -1) then
+    AvgSyncDiff := TimeDiff
+  else
+    AvgSyncDiff := TimeDiff * (1-AVG_HISTORY_FACTOR) +
+                   AvgSyncDiff * AVG_HISTORY_FACTOR;
+
+  {$IFDEF LOG_SYNC}
+  //Log.LogError(Format('c:%.3f | p:%.3f | d:%.3f | a:%.3f',
+  //    [MasterClock, CurPosition, TimeDiff, AvgSyncDiff]), 'Synch');
+  {$ENDIF}
+
+  // check if we are out of sync
+  if (Abs(AvgSyncDiff) >= SYNC_REPOS_THRESHOLD) then
+  begin
+    {$IFDEF LOG_SYNC}
+    Log.LogError(Format('ReposSynch: %.3f > %.3f',
+        [Abs(AvgSyncDiff), SYNC_REPOS_THRESHOLD]), 'Synch');
+    {$ENDIF}
+
+    // diff far is too large -> reposition stream
+    // (resulting position might still be out of sync)
+    SetPosition(CurPosition + AvgSyncDiff);
+
+    // reset sync info
+    AvgSyncDiff := -1;
+  end
+  else if (Abs(AvgSyncDiff) >= SYNC_SOFT_THRESHOLD) then
+  begin
+    {$IFDEF LOG_SYNC}
+    Log.LogError(Format('SoftSynch: %.3f > %.3f',
+        [Abs(AvgSyncDiff), SYNC_SOFT_THRESHOLD]), 'Synch');
+    {$ENDIF}
+
+    // hard sync: directly jump to the current position
+    FrameSkip := Round(AvgSyncDiff * FormatInfo.SampleRate);
+    Result := BufferSize + FrameSkip * FormatInfo.FrameSize;
+    if (Result < 0) then
+      Result := 0;
+
+    // reset sync info
+    AvgSyncDiff := -1;
+  end;
+end;
+
+(*
+ * Fills a buffer with copies of the given Frame or with 0 if Frame is nil.
+ *)
+procedure TAudioPlaybackStream.FillBufferWithFrame(Buffer: PByteArray; BufferSize: integer; Frame: PByteArray; FrameSize: integer);
+var
+  i: integer;
+  FrameCopyCount: integer;
+begin
+  // the buffer must at least contain place for one copy of the frame.
+  if ((Buffer = nil) or (BufferSize <= 0) or (BufferSize < FrameSize)) then
+    Exit;
+
+  // no valid frame -> fill with 0
+  if ((Frame = nil) or (FrameSize <= 0)) then
+  begin
+    FillChar(Buffer[0], BufferSize, 0);
+    Exit;
+  end;
+
+  // number of frames to copy
+  FrameCopyCount := BufferSize div FrameSize;
+  // insert as many copies of frame into the buffer as possible
+  for i := 0 to FrameCopyCount-1 do
+    Move(Frame[0], Buffer[i*FrameSize], FrameSize);
+end;
+
+{ TAudioVoiceStream }
+
+function TAudioVoiceStream.Open(ChannelMap: integer; FormatInfo: TAudioFormatInfo): boolean;
+begin
+  Self.ChannelMap := ChannelMap;
+  Self.FormatInfo := FormatInfo.Copy();
+  // a voice stream is always mono, reassure the the format is correct
+  Self.FormatInfo.Channels := 1;
+  Result := true;
+end;
+
+destructor TAudioVoiceStream.Destroy;
+begin
+  Close();
+  inherited;
+end;
+
+procedure TAudioVoiceStream.Close();
+begin
+  PerformOnClose();
+  FreeAndNil(FormatInfo);
+end;
+
+function TAudioVoiceStream.GetAudioFormatInfo(): TAudioFormatInfo;
+begin
+  Result := FormatInfo;
+end;
+
+function TAudioVoiceStream.GetLength(): real;
+begin
+  Result := -1;
+end;
+
+function TAudioVoiceStream.GetPosition(): real;
+begin
+  Result := -1;
+end;
+
+procedure TAudioVoiceStream.SetPosition(Time: real);
+begin
+end;
+
+function TAudioVoiceStream.GetLoop(): boolean;
+begin
+  Result := false;
+end;
+
+procedure TAudioVoiceStream.SetLoop(Enabled: boolean);
+begin
+end;
+
+
+end.
diff --git a/songmanagement/src/base/UNote.pas b/songmanagement/src/base/UNote.pas
new file mode 100644
index 00000000..ff9c6b57
--- /dev/null
+++ b/songmanagement/src/base/UNote.pas
@@ -0,0 +1,618 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UNote;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  Classes,
+  SDL,
+  UMusic,
+  URecord,
+  UTime,
+  UDisplay,
+  UIni,
+  ULog,
+  ULyrics,
+  UScreenSing,
+  USong,
+  gl;
+
+type
+  PPLayerNote = ^TPlayerNote;
+  TPlayerNote = record
+    Start:   integer;
+    Length:  integer;
+    Detect:  real;    // accurate place, detected in the note
+    Tone:    real;
+    Perfect: boolean; // true if the note matches the original one, light the star
+    Hit:     boolean; // true if the note hits the line
+  end;
+
+  PPLayer = ^TPlayer;
+  TPlayer = record
+    Name:           UTF8String;
+
+    // Index in Teaminfo record
+    TeamID:         byte;
+    PlayerID:       byte;
+
+    // Scores
+    Score:          real;
+    ScoreLine:      real;
+    ScoreGolden:    real;
+
+    ScoreInt:       integer;
+    ScoreLineInt:   integer;
+    ScoreGoldenInt: integer;
+    ScoreTotalInt:  integer;
+
+    // LineBonus
+    ScoreLast:      real;    // Last Line Score
+
+    // PerfectLineTwinkle (effect)
+    LastSentencePerfect: boolean;
+
+    HighNote:       integer; // index of last note (= High(Note)?)
+    LengthNote:     integer; // number of notes (= Length(Note)?).
+    Note:           array of TPlayerNote;
+  end;
+
+{* Player and music info *}
+var
+  {**
+   * Player info and state for each player.
+   * The amount of players is given by PlayersPlay.
+   *}
+  Player: array of TPlayer;
+
+  {**
+   * Number of players or teams playing.
+   * Possible values: 1 - 6
+   *}
+  PlayersPlay: integer;
+
+  {**
+   * Selected song for singing.
+   *}
+  CurrentSong: TSong;
+
+const
+  MAX_SONG_SCORE = 10000;     // max. achievable points per song
+  MAX_SONG_LINE_BONUS = 1000; // max. achievable line bonus per song
+
+procedure Sing(Screen: TScreenSing);
+procedure NewSentence(Screen: TScreenSing);
+procedure NewBeatClick(Screen: TScreenSing);  // executed when on then new beat for click
+procedure NewBeatDetect(Screen: TScreenSing); // executed when on then new beat for detection
+procedure NewNote(Screen: TScreenSing);       // detect note
+function  GetMidBeat(Time: real): real;
+function  GetTimeFromBeat(Beat: integer): real;
+
+implementation
+
+uses
+  Math,
+  StrUtils,
+  USongs,
+  UJoystick,
+  UCommandLine,
+  ULanguage,
+  //SDL_ttf,
+  USkins,
+  UCovers,
+  UCatCovers,
+  UDataBase,
+  UPlaylist,
+  UParty,
+  UConfig,
+  UCommon,
+  UGraphic,
+  UGraphicClasses,
+  UPathUtils,
+  UPlatform,
+  UThemes;
+
+function GetTimeForBeats(BPM, Beats: real): real;
+begin
+  Result := 60 / BPM * Beats;
+end;
+
+function GetBeats(BPM, msTime: real): real;
+begin
+  Result := BPM * msTime / 60;
+end;
+
+procedure GetMidBeatSub(BPMNum: integer; var Time: real; var CurBeat: real);
+var
+  NewTime: real;
+begin
+  if High(CurrentSong.BPM) = BPMNum then
+  begin
+    // last BPM
+    CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
+    Time := 0;
+  end
+  else
+  begin
+    // not last BPM
+    // count how much time is it for start of the new BPM and store it in NewTime
+    NewTime := GetTimeForBeats(CurrentSong.BPM[BPMNum].BPM, CurrentSong.BPM[BPMNum+1].StartBeat - CurrentSong.BPM[BPMNum].StartBeat);
+
+    // compare it to remaining time
+    if (Time - NewTime) > 0 then
+    begin
+      // there is still remaining time
+      CurBeat := CurrentSong.BPM[BPMNum].StartBeat;
+      Time := Time - NewTime;
+    end
+    else
+    begin
+      // there is no remaining time
+      CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
+      Time := 0;
+    end; // if
+  end; // if
+end;
+
+function GetMidBeat(Time: real): real;
+var
+  CurBeat: real;
+  CurBPM:  integer;
+begin
+  // static BPM
+  if Length(CurrentSong.BPM) = 1 then
+  begin
+    Result := Time * CurrentSong.BPM[0].BPM / 60;
+  end
+  // variable BPM
+  else if Length(CurrentSong.BPM) > 1 then
+  begin
+    CurBeat := 0;
+    CurBPM := 0;
+    while (Time > 0) do
+    begin
+      GetMidBeatSub(CurBPM, Time, CurBeat);
+      Inc(CurBPM);
+    end;
+
+    Result := CurBeat;
+  end
+  // invalid BPM
+  else
+  begin
+    Result := 0;
+  end;
+end;
+
+function GetTimeFromBeat(Beat: integer): real;
+var
+  CurBPM: integer;
+begin
+  // static BPM
+  if Length(CurrentSong.BPM) = 1 then
+  begin
+    Result := CurrentSong.GAP / 1000 + Beat * 60 / CurrentSong.BPM[0].BPM;
+  end
+  // variable BPM
+  else if Length(CurrentSong.BPM) > 1 then
+  begin
+    Result := CurrentSong.GAP / 1000;
+    CurBPM := 0;
+    while (CurBPM <= High(CurrentSong.BPM)) and
+          (Beat > CurrentSong.BPM[CurBPM].StartBeat) do
+    begin
+      if (CurBPM < High(CurrentSong.BPM)) and
+         (Beat >= CurrentSong.BPM[CurBPM+1].StartBeat) then
+      begin
+        // full range
+        Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
+                           (CurrentSong.BPM[CurBPM+1].StartBeat - CurrentSong.BPM[CurBPM].StartBeat);
+      end;
+
+      if (CurBPM = High(CurrentSong.BPM)) or
+         (Beat < CurrentSong.BPM[CurBPM+1].StartBeat) then
+      begin
+        // in the middle
+        Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
+                           (Beat - CurrentSong.BPM[CurBPM].StartBeat);
+      end;
+      Inc(CurBPM);
+    end;
+
+    {
+    while (Time > 0) do
+    begin
+      GetMidBeatSub(CurBPM, Time, CurBeat);
+      Inc(CurBPM);
+    end;
+    }
+  end
+  // invalid BPM
+  else
+  begin
+    Result := 0;
+  end;
+end;
+
+procedure Sing(Screen: TScreenSing);
+var
+  Count:   integer;
+  CountGr: integer;
+  CP:      integer;
+begin
+  LyricsState.UpdateBeats();
+
+  // sentences routines
+  for CountGr := 0 to 0 do //High(Lines)
+  begin;
+    CP := CountGr;
+    // old parts
+    LyricsState.OldLine := Lines[CP].Current;
+
+    // choose current parts
+    for Count := 0 to Lines[CP].High do
+    begin
+      if LyricsState.CurrentBeat >= Lines[CP].Line[Count].Start then
+        Lines[CP].Current := Count;
+    end;
+
+    // clean player note if there is a new line
+    // (optimization on halfbeat time)
+    if Lines[CP].Current <> LyricsState.OldLine then
+      NewSentence(Screen);
+
+  end; // for CountGr
+
+  // make some operations on clicks
+  if {(LyricsState.CurrentBeatC >= 0) and }(LyricsState.OldBeatC <> LyricsState.CurrentBeatC) then
+    NewBeatClick(Screen);
+
+  // make some operations when detecting new voice pitch
+  if (LyricsState.CurrentBeatD >= 0) and (LyricsState.OldBeatD <> LyricsState.CurrentBeatD) then
+    NewBeatDetect(Screen);
+end;
+
+procedure NewSentence(Screen: TScreenSing);
+var
+  i: integer;
+begin
+  // clean note of player
+  for i := 0 to High(Player) do
+  begin
+    Player[i].LengthNote := 0;
+    Player[i].HighNote := -1;
+    SetLength(Player[i].Note, 0);
+  end;
+
+  // on sentence change...
+  Screen.onSentenceChange(Lines[0].Current);
+end;
+
+procedure NewBeatClick;
+var
+  Count: integer;
+begin
+  // beat click
+  if ((Ini.BeatClick = 1) and
+      ((LyricsState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0)) then
+  begin
+    AudioPlayback.PlaySound(SoundLib.Click);
+  end;
+
+  for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
+  begin
+    if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LyricsState.CurrentBeatC) then
+    begin
+      // click assist
+      if Ini.ClickAssist = 1 then
+        AudioPlayback.PlaySound(SoundLib.Click);
+
+      // drum machine
+      (*
+      TempBeat := LyricsState.CurrentBeat; // + 2;
+      if (TempBeat mod 8 = 0) then Music.PlayDrum;
+      if (TempBeat mod 8 = 4) then Music.PlayClap;
+      //if (TempBeat mod 4 = 2) then Music.PlayHihat;
+      if (TempBeat mod 4 <> 0) then Music.PlayHihat;
+      *)
+    end;
+  end;
+end;
+
+procedure NewBeatDetect(Screen: TScreenSing);
+  var
+    SentenceEnd: integer;
+    I: cardinal;
+begin
+  NewNote(Screen);
+
+  // check for sentence end
+  // we check all lines here because a new sentence may
+  // have been started even before the old one finishes
+  // due to corrupt lien breaks
+  // checking only current line works to, but may lead to
+  // weird ratings for the song files w/ the mentioned
+  // errors
+  // To-Do Philipp : check current and last line should
+  // do it for most corrupt txt and for lines in
+  // non-corrupt txts that start immediatly after the prev.
+  // line ends
+  if (assigned(Screen)) then
+  begin
+    for I := 0 to Lines[0].High do
+    begin
+      with Lines[0].Line[I] do
+      begin
+        if (HighNote >= 0) then
+        begin
+          SentenceEnd := Note[HighNote].Start + Note[HighNote].Length;
+
+          if (LyricsState.OldBeatD < SentenceEnd) and (LyricsState.CurrentBeatD >= SentenceEnd) then
+            Screen.OnSentenceEnd(I);
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure NewNote(Screen: TScreenSing);
+var
+  LineFragmentIndex:   integer;
+  CurrentLineFragment: PLineFragment;
+  PlayerIndex:         integer;
+  CurrentSound:        TCaptureBuffer;
+  CurrentPlayer:       PPlayer;
+  LastPlayerNote:      PPlayerNote;
+  Line: 	       PLine;
+  SentenceIndex:       integer;
+  SentenceMin:         integer;
+  SentenceMax:         integer;
+  SentenceDetected:    integer; // sentence of detected note
+  NoteAvailable:       boolean;
+  NewNote:             boolean;
+  Range:               integer;
+  NoteHit:             boolean;
+  MaxSongPoints:       integer; // max. points for the song (without line bonus)
+  CurNotePoints:       real;    // Points for the cur. Note (PointsperNote * ScoreFactor[CurNote])
+begin
+  // TODO: add duet mode support
+  // use Lines[LineSetIndex] with LineSetIndex depending on the current player
+
+  // count min and max sentence range for checking 
+  // (detection is delayed to the notes we see on the screen)
+  SentenceMin := Lines[0].Current-1;
+  if (SentenceMin < 0) then
+    SentenceMin := 0;
+  SentenceMax := Lines[0].Current;
+
+  // check for an active note at the current time defined in the lyrics
+  NoteAvailable := false;
+  SentenceDetected := SentenceMin;
+  for SentenceIndex := SentenceMin to SentenceMax do
+  begin
+    Line := @Lines[0].Line[SentenceIndex];
+    for LineFragmentIndex := 0 to Line.HighNote do
+    begin
+      CurrentLineFragment := @Line.Note[LineFragmentIndex];
+      // check if line is active
+      if ((CurrentLineFragment.Start <= LyricsState.CurrentBeatD) and
+          (CurrentLineFragment.Start + CurrentLineFragment.Length-1 >= LyricsState.CurrentBeatD)) and
+         (CurrentLineFragment.NoteType <> ntFreestyle) and       // but ignore FreeStyle notes
+         (CurrentLineFragment.Length > 0) then                   // and make sure the note length is at least 1
+      begin
+        SentenceDetected := SentenceIndex;
+        NoteAvailable := true;
+        Break;
+      end;
+    end;
+    // TODO: break here, if NoteAvailable is true? We would then use the first instead
+    // of the last note matching the current beat if notes overlap. But notes
+    // should not overlap at all.
+    // if (NoteAvailable) then
+    //  Break;
+  end;
+
+  // analyze player signals
+  for PlayerIndex := 0 to PlayersPlay-1 do
+  begin
+    CurrentPlayer := @Player[PlayerIndex];
+    CurrentSound := AudioInputProcessor.Sound[PlayerIndex];
+
+    // at the beginning of the song there is no previous note
+    if (Length(CurrentPlayer.Note) > 0) then
+      LastPlayerNote := @CurrentPlayer.Note[CurrentPlayer.HighNote]
+    else
+      LastPlayerNote := nil;
+
+    // analyze buffer
+    CurrentSound.AnalyzeBuffer;
+
+    // add some noise
+    // TODO: do we need this?
+    //LyricsState.Tone := LyricsState.Tone + Round(Random(3)) - 1;
+
+    // add note if possible
+    if (CurrentSound.ToneValid and NoteAvailable) then
+    begin
+      Line := @Lines[0].Line[SentenceDetected];
+
+      // process until last note
+      for LineFragmentIndex := 0 to Line.HighNote do
+      begin
+        CurrentLineFragment := @Line.Note[LineFragmentIndex];
+        if (CurrentLineFragment.Start <= LyricsState.OldBeatD+1) and
+           (CurrentLineFragment.Start + CurrentLineFragment.Length > LyricsState.OldBeatD+1) then
+        begin
+          // compare notes (from song-file and from player)
+
+          // move players tone to proper octave
+          while (CurrentSound.Tone - CurrentLineFragment.Tone > 6) do
+            CurrentSound.Tone := CurrentSound.Tone - 12;
+
+          while (CurrentSound.Tone - CurrentLineFragment.Tone < -6) do
+            CurrentSound.Tone := CurrentSound.Tone + 12;
+
+          // half size notes patch
+          NoteHit := false;
+
+          // if Ini.Difficulty = 0 then Range := 2;
+          // if Ini.Difficulty = 1 then Range := 1;
+          // if Ini.Difficulty = 2 then Range := 0;
+          Range := 2 - Ini.Difficulty;
+
+          // check if the player hit the correct tone within the tolerated range
+          if (Abs(CurrentLineFragment.Tone - CurrentSound.Tone) <= Range) then
+          begin
+            // adjust the players tone to the correct one
+            // TODO: do we need to do this?
+            // Philipp: I think we do, at least when we draw the notes.
+            //          Otherwise the notehit thing would be shifted to the
+            //          correct unhit note. I think this will look kind of strange.
+            CurrentSound.Tone := CurrentLineFragment.Tone;
+
+            // half size notes patch
+            NoteHit := true;
+
+            if (Ini.LineBonus > 0) then
+              MaxSongPoints := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS
+            else
+              MaxSongPoints := MAX_SONG_SCORE;
+
+            // Note: ScoreValue is the sum of all note values of the song
+            // (MaxSongPoints / ScoreValue) is the points that a player
+            // gets for a hit of one beat of a normal note
+            // CurNotePoints is the amount of points that is meassured
+            // for a hit of the note per full beat
+            CurNotePoints := (MaxSongPoints / Lines[0].ScoreValue) * ScoreFactor[CurrentLineFragment.NoteType];
+            
+            case CurrentLineFragment.NoteType of
+              ntNormal: CurrentPlayer.Score       := CurrentPlayer.Score       + CurNotePoints;
+              ntGolden: CurrentPlayer.ScoreGolden := CurrentPlayer.ScoreGolden + CurNotePoints;
+            end;
+
+            // a problem if we use floor instead of round is that a score of
+            // 10000 points is only possible if the last digit of the total points
+            // for golden and normal notes is 0.
+            // if we use round, the max score is 10000 for most songs
+            // but a score of 10010 is possible if the last digit of the total
+            // points for golden and normal notes is 5
+            // the best solution is to use round for one of these scores
+            // and round the other score in the opposite direction
+            // so we assure that the highest possible score is 10000 in every case.
+            CurrentPlayer.ScoreInt := round(CurrentPlayer.Score / 10) * 10;
+
+            if (CurrentPlayer.ScoreInt < CurrentPlayer.Score) then
+              //normal score is floored so we have to ceil golden notes score
+              CurrentPlayer.ScoreGoldenInt := ceil(CurrentPlayer.ScoreGolden / 10) * 10
+            else
+              //normal score is ceiled so we have to floor golden notes score
+              CurrentPlayer.ScoreGoldenInt := floor(CurrentPlayer.ScoreGolden / 10) * 10;
+
+
+            CurrentPlayer.ScoreTotalInt := CurrentPlayer.ScoreInt +
+                                           CurrentPlayer.ScoreGoldenInt +
+                                           CurrentPlayer.ScoreLineInt;
+          end;
+
+        end; // operation
+      end; // for
+
+      // check if we have to add a new note or extend the note's length
+      if (SentenceDetected = SentenceMax) then
+      begin
+        // we will add a new note
+        NewNote := true;
+
+        // if previous note (if any) was the same, extend previous note
+        if ((CurrentPlayer.LengthNote > 0) and
+            (LastPlayerNote <> nil) and
+            (LastPlayerNote.Tone = CurrentSound.Tone) and
+            ((LastPlayerNote.Start + LastPlayerNote.Length) = LyricsState.CurrentBeatD)) then
+        begin
+          NewNote := false;
+        end;
+
+        // if is not as new note to control
+        for LineFragmentIndex := 0 to Line.HighNote do
+        begin
+          if (Line.Note[LineFragmentIndex].Start = LyricsState.CurrentBeatD) then
+            NewNote := true;
+        end;
+
+        // add new note
+        if NewNote then
+        begin
+          // new note
+          Inc(CurrentPlayer.LengthNote);
+          Inc(CurrentPlayer.HighNote);
+          SetLength(CurrentPlayer.Note, CurrentPlayer.LengthNote);
+
+          // update player's last note
+          LastPlayerNote := @CurrentPlayer.Note[CurrentPlayer.HighNote];
+          with LastPlayerNote^ do
+          begin
+            Start  := LyricsState.CurrentBeatD;
+            Length := 1;
+            Tone   := CurrentSound.Tone; // Tone || ToneAbs
+            Detect := LyricsState.MidBeat;
+            Hit    := NoteHit; // half note patch
+          end;
+        end
+        else
+        begin
+          // extend note length
+          if (LastPlayerNote <> nil) then
+            Inc(LastPlayerNote.Length);
+        end;
+
+        // check for perfect note and then light the star (on Draw)
+        for LineFragmentIndex := 0 to Line.HighNote do
+        begin
+          CurrentLineFragment := @Line.Note[LineFragmentIndex];
+          if (CurrentLineFragment.Start  = LastPlayerNote.Start) and
+             (CurrentLineFragment.Length = LastPlayerNote.Length) and
+             (CurrentLineFragment.Tone   = LastPlayerNote.Tone) then
+          begin
+            LastPlayerNote.Perfect := true;
+          end;
+        end;
+      end; // if SentenceDetected = SentenceMax
+
+    end; // if Detected
+  end; // for PlayerIndex
+
+  //Log.LogStatus('EndBeat', 'NewBeat');
+end;
+
+end.
diff --git a/songmanagement/src/base/UParty.pas b/songmanagement/src/base/UParty.pas
new file mode 100644
index 00000000..bc485dca
--- /dev/null
+++ b/songmanagement/src/base/UParty.pas
@@ -0,0 +1,1026 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UParty;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  ULua;
+
+type
+  { array holds ids of modes or Party_Round_Random
+    its length defines the number of rounds
+    it is used as argument for TPartyGame.StartParty }
+  ARounds = array of integer;
+
+  { element of APartyTeamRanking returned by TPartyGame.GetTeamRanking
+    and parameter for TPartyGame.SetWinner }
+  TParty_TeamRanking = record
+    Team: Integer; //< id of team
+    Rank: Integer; //< 1 to Length(Teams) e.g. 1 is for placed first
+  end;
+  AParty_TeamRanking = array of TParty_TeamRanking; //< returned by TPartyGame.GetTeamRanking
+
+  TParty_RoundList = record
+    Index: integer;
+    Name: UTF8String;
+  end;
+  AParty_ModeList = array of TParty_RoundList;
+
+  { record used by TPartyGame to store round specific data }
+  TParty_Round = record
+    Mode:   Integer;
+    AlreadyPlayed: Boolean; //< true if round was already played
+    Ranking: AParty_TeamRanking;
+    RankingSet: Boolean; //< true if Self.Ranking is already set
+  end;
+
+  TParty_ModeInfo = record
+    Name: String; // name of this mode
+    Parent: Integer;   // Id of owning plugin
+
+    CanNonParty: Boolean; //< is playable when not in party mode
+    CanParty: Boolean;    //< is playable in party mode
+
+    // one bit in the following settings stands for
+    // a player or team count
+    // PlayerCount = 2 or 4 indicates that the mode is playable with 2 and 3 players per team
+    // TeamCount = 1 or 2 or 4 or 8 or 16 or 32 indicates that the mode is playable with 1 to 6 teams
+    PlayerCount: Integer;   //< playable with one, two, three etc. players per team
+    TeamCount: Integer;     //< playable with one, two, three etc. different teams
+
+
+    Functions: record // lua functions that will be called at specific events
+      BeforeSongSelect: String; // default actions are executed if functions = nil
+      AfterSongSelect: String;
+
+      BeforeSing: String;
+      OnSing: String;
+      AfterSing: String;
+    end;
+  end;
+
+  { used by TPartyGame to store player specific data }
+  TParty_PlayerInfo = record
+    Name: String;         //< Playername
+    TimesPlayed: Integer; //< How often this Player has Sung
+  end;
+
+  { used by TPartyGame to store team specific data }
+  TParty_TeamInfo = record
+    Name:  String;        //< name of the Team
+    Score: Word;          //< current score
+    JokersLeft: Integer;  //< jokers this team has left
+
+    NextPlayer: Integer;  //Id of the player that plays the next (the current) song
+
+    Players: array of TParty_PlayerInfo;
+  end;
+
+  TPartyGame = class
+  private
+    bPartyGame: boolean; //< are we playing party or standard mode
+    CurRound: Integer;   //< indicates which of the elements of Rounds is played next (at the moment)
+
+    bPartyStarted: Boolean;
+
+    TimesPlayed: array of Integer; //< times every mode was played in current party game (for random mode calculation)
+
+    procedure GenScores;
+    function GetRandomMode: integer;
+    function GetRandomPlayer(Team: integer): integer;
+
+    { returns true if a mode is playable with current playerconfig }
+    function ModePlayable(I: integer): boolean;
+
+    function CallLua(Parent: Integer; Func: String):Boolean;
+
+    procedure SetRankingByScore;
+  public
+    //Teams: TTeamInfo;
+    Rounds: array of TParty_Round;    //< holds info which modes are played in this party game (if started)
+    Teams: array of TParty_TeamInfo;  //< holds info of teams playing in current round (private for easy manipulation of lua functions)
+
+    Modes: array of TParty_ModeInfo;  //< holds info of registred party modes
+
+    property CurrentRound: Integer read CurRound;
+
+    constructor Create;
+
+    { set the attributes of Info to default values }
+    procedure DefaultModeInfo(var Info: TParty_ModeInfo);
+
+    { registers a new mode, returns true on success
+      (mode name does not already exist) }
+    function RegisterMode(Info: TParty_ModeInfo): Boolean;
+
+    { returns true if modes are available for
+      players and teams that are currently set
+      up. if there are no teams set up it returns
+      if there are any party modes available }
+    function ModesAvailable: Boolean;
+
+    { returns an array with the name of all available modes (that
+      are playable with current player configuration }
+    function GetAvailableModes: AParty_ModeList;
+
+    { clears all party specific data previously stored }
+    procedure Clear;
+
+    { adds a team to the team array, returning its id
+      can only be called when game is not already started }
+    function AddTeam(Name: String): Integer;
+
+    { adds a player to the player array, returning its id
+      can only be called when game is not already started }
+    function AddPlayer(Team: Integer; Name: String): Integer;
+
+    { starts a new PartyGame, returns true on success
+      before a call of this function teams and players
+      has to be added by AddTeam and AddPlayer }
+
+    function StartGame(Rounds: ARounds): Boolean;
+
+    { sets the winner(s) of current round
+      returns true on success }
+    function SetRanking(Ranking: AParty_TeamRanking): Boolean;
+
+    { increases players TimesPlayed value }
+    procedure IncTimesPlayed;
+
+    { increases round counter by 1 and clears all round specific information;
+      returns the number of the current round or -1 if last round has already
+      been played }
+    function NextRound: integer;
+
+    { indicates that current round has already been played }
+    procedure RoundPlayed;
+
+    { true if in a Party Game (not in standard mode) }
+    property PartyGame: Boolean read BPartyGame;
+
+
+    { returns true if last round was already played }
+    function GameFinished: Boolean;
+
+    { call plugins defined function and/or default procedure
+      only default procedure is called when no function is defined by plugin
+      if plugins function returns true then default is called after plugins
+      function was executed}
+    procedure CallBeforeSongSelect;
+    procedure CallAfterSongSelect;
+    procedure CallBeforeSing;
+    procedure CallOnSing;
+    procedure CallAfterSing;
+
+    { returns an array[1..6] of TParty_TeamRanking.
+      the index stands for the placing,
+      team is the team number (in the team array)
+      rank is correct rank if some teams have the
+      same score. 
+      }
+    function GetTeamRanking: AParty_TeamRanking;
+
+    { returns a string like "Team 1 (and Team 2) win" }
+    function GetWinnerString(Round: integer): UTF8String;
+
+    destructor  Destroy; override;
+  end;
+
+const
+  { minimal amount of teams for party mode }
+  Party_Teams_Min = 2;
+
+  { maximal amount of teams for party mode }
+  Party_Teams_Max = 3;
+
+  { minimal amount of players for party mode }
+  Party_Players_Min = 1;
+
+  { maximal amount of players for party mode }
+  Party_Players_Max = 4;
+
+  { amount of jokers each team gets at the beginning of the game }
+  Party_Count_Jokers = 5;
+
+  { to indicate that element (mode) should set randomly in ARounds array }
+  Party_Round_Random = -1;
+
+  { values for TParty_TeamRanking.Rank }
+  PR_First = 1;
+  PR_Second = 2;
+  PR_Third = 3;
+  
+  StandardModus = 0; //Modus Id that will be played in non-party mode
+
+var
+  Party: TPartyGame;
+
+implementation
+
+uses
+  UGraphic,
+  ULanguage,
+  ULog,
+  ULuaCore,
+  UDisplay,
+  USong,
+  UNote,
+  SysUtils;
+
+//-------------
+// Just the constructor
+//-------------
+constructor TPartyGame.Create;
+begin
+  inherited;
+
+  Clear;
+end;
+
+destructor TPartyGame.Destroy;
+begin
+  inherited;
+end;
+
+{ clears all party specific data previously stored }
+procedure TPartyGame.Clear;
+  var
+    I: Integer;
+begin
+  bPartyGame := false; // no party game
+  CurRound := low(integer);
+
+  bPartyStarted := false; //game not startet
+
+  SetLength(Teams, 0); //remove team info
+  SetLength(Rounds, 0); //remove round info
+
+  // clear times played
+  for I := 0 to High(TimesPlayed) do
+    TimesPlayed[I] := 0;
+end;
+
+{ private: some intelligent randomnes for plugins }
+function TPartyGame.GetRandomMode: integer;
+var
+  LowestTP: integer;
+  NumPwithLTP: integer;
+  I: integer;
+  R: integer;
+begin
+  Result := 0; //If there are no matching modes, play first modus
+  LowestTP := high(Integer);
+  NumPwithLTP := 0;
+
+  // search for the plugins less played yet
+  for I := 0 to high(Modes) do
+  begin
+    if (ModePlayable(I)) then
+    begin
+      if (TimesPlayed[I] < lowestTP) then
+      begin
+        lowestTP := TimesPlayed[I];
+        NumPwithLTP := 1;
+      end
+      else if (TimesPlayed[I] = lowestTP) then
+      begin
+        Inc(NumPwithLTP);
+      end;
+    end;
+  end;
+
+  // create random number
+  R := Random(NumPwithLTP);
+
+  // select the random mode from the modes with less timesplayed
+  for I := 0 to high(Modes) do
+  begin
+    if (TimesPlayed[I] = lowestTP) and (ModePlayable(I)) then
+    begin
+      //Plugin found
+      if (R = 0) then
+      begin
+        Result := I;
+        Inc(TimesPlayed[I]);
+        Break;
+      end;
+
+      Dec(R);
+    end;
+  end;
+end;
+
+{ private: GetRandomPlayer - returns a random player
+                             that does not play to often ;) }
+function TPartyGame.GetRandomPlayer(Team: integer): integer;
+var
+  I, R: integer;
+  lowestTP: Integer;
+  NumPwithLTP: Integer;
+begin
+  LowestTP := high(Integer);
+  NumPwithLTP := 0;
+  Result := 0;
+
+  // search for players that have less played yet
+  for I := 0 to High(Teams[Team].Players) do
+  begin
+    if (Teams[Team].Players[I].TimesPlayed < lowestTP) then
+    begin
+      lowestTP := Teams[Team].Players[I].TimesPlayed;
+      NumPwithLTP := 1;
+    end
+    else if (Teams[Team].Players[I].TimesPlayed = lowestTP) then
+    begin
+      Inc(NumPwithLTP);
+    end;
+  end;
+
+  // create random number
+  R := Random(NumPwithLTP);
+
+  // search for selected random player
+  for I := 0 to High(Teams[Team].Players) do
+  begin
+    if Teams[Team].Players[I].TimesPlayed = lowestTP then
+    begin
+      if (R = 0) then
+      begin // found selected player
+        Result := I;
+        Break;
+      end;
+
+      Dec(R);
+    end;
+  end;
+end;
+
+//----------
+//GenScores - inc scores for cur. round
+//----------
+procedure TPartyGame.GenScores;
+var
+  I: Integer;
+begin
+  if (Length(Teams) = 2) then
+  begin // score generation for 2 teams, winner gets 1 point
+    for I := 0 to High(Rounds[CurRound].Ranking) do
+      if (Rounds[CurRound].Ranking[I].Rank = PR_First) then
+        Inc(Teams[Rounds[CurRound].Ranking[I].Team].Score);
+  end
+  else if (Length(Teams) = 3) then
+  begin // score generation for 3 teams,
+    // winner gets 3 points 2nd gets 1 point
+    for I := 0 to High(Rounds[CurRound].Ranking) do
+      if (Rounds[CurRound].Ranking[I].Rank = PR_First) then
+        Inc(Teams[Rounds[CurRound].Ranking[I].Team].Score, 3)
+      else if (Rounds[CurRound].Ranking[I].Rank = PR_Second) then
+        Inc(Teams[Rounds[CurRound].Ranking[I].Team].Score);
+  end
+end;
+
+{ set the attributes of Info to default values }
+procedure TPartyGame.DefaultModeInfo(var Info: TParty_ModeInfo);
+begin
+  Info.Name := 'undefined';
+  Info.Parent := -1; //< not loaded by plugin (e.g. Duell)
+  Info.CanNonParty := false;
+  Info.CanParty := false;
+  Info.PlayerCount := High(Integer); //< no restrictions either on player count
+  Info.TeamCount := High(Integer);   //< nor on team count
+  Info.Functions.BeforeSongSelect := ''; //< use default functions
+  Info.Functions.AfterSongSelect  := '';
+  Info.Functions.BeforeSing       := '';
+  Info.Functions.OnSing           := '';
+  Info.Functions.AfterSing        := '';
+end;
+
+{ registers a new mode, returns true on success
+  (mode name does not already exist) }
+function TPartyGame.RegisterMode(Info: TParty_ModeInfo): Boolean;
+  var
+    Len: integer;
+    LowerName: String;
+    I: integer;
+begin
+  Result := false;
+
+  if (Info.Name <> 'undefined') then
+  begin
+    // search for a plugin w/ same name
+    LowerName := lowercase(Info.Name); // case sensitive search
+    for I := 0 to high(Modes) do
+      if (LowerName = lowercase(Modes[I].Name)) then
+        exit; //< no success (name already exist)
+
+    // add new mode to array and append and clear a new TimesPlayed element
+    Len := Length(Modes);
+    SetLength(Modes, Len + 1);
+    SetLength(TimesPlayed, Len + 1);
+
+    Modes[Len] := Info;
+    TimesPlayed[Len] := 0;
+
+    Result := True;
+  end;
+end;
+
+{ returns true if a mode is playable with current playerconfig }
+function TPartyGame.ModePlayable(I: integer): boolean;
+  var
+    J: integer;
+begin
+  if (Length(Teams) = 0) then
+    Result := true
+  else
+  begin
+    if (Modes[I].TeamCount and (1 shl (Length(Teams) - 1)) <> 0) then
+    begin
+      Result := true;
+
+      for J := 0 to High(Teams) do
+        Result := Result and (Modes[I].PlayerCount and (1 shl (Length(Teams[J].Players) - 1)) <> 0);
+    end
+    else
+      Result := false;
+  end;
+end;
+
+{ returns true if modes are available for
+  players and teams that are currently set
+  up. if there are no teams set up it returns
+  if there are any party modes available }
+function TPartyGame.ModesAvailable: Boolean;
+  var
+    I: integer;
+    CountTeams: integer;
+begin
+  CountTeams := Length(Teams);
+  if CountTeams = 0 then
+  begin
+    Result := (Length(Modes) > 0);
+  end
+  else
+  begin
+    Result := false;
+    for I := 0 to High(Modes) do
+    begin
+      Result := ModePlayable(I);
+
+      if Result then
+        Exit;
+    end;
+  end;
+end;       
+
+{ returns an array with the name of all available modes (that
+  are playable with current player configuration }
+function TPartyGame.GetAvailableModes: AParty_ModeList;
+  var
+    I: integer;
+    Len: integer;
+begin
+  Len := 0;
+  SetLength(Result, Len + 1);
+  Result[Len].Index := Party_Round_Random;
+  Result[Len].Name := Language.Translate('MODE_RANDOM_NAME');
+
+  for I := 0 to High(Modes) do
+    if (ModePlayable(I)) then
+    begin
+      Inc(Len);
+      SetLength(Result, Len + 1);
+      Result[Len].Index := I;
+      Result[Len].Name := Language.Translate('MODE_' + Uppercase(Modes[I].Name) + '_NAME');
+    end;
+end;
+
+{ adds a team to the team array, returning its id
+  can only be called when game is not already started }
+function TPartyGame.AddTeam(Name: String): Integer;
+begin
+  Result := -1;
+  if (not bPartyStarted) and (Length(Name) > 0) and (Length(Teams) < Party_Teams_Max) then
+  begin
+    Result := Length(Teams);
+    SetLength(Teams, Result + 1);
+
+    Teams[Result].Name := Name;
+    Teams[Result].Score := 0;
+    Teams[Result].JokersLeft := Party_Count_Jokers;
+    Teams[Result].NextPlayer := -1;
+  end;
+end;
+
+{ adds a player to the player array, returning its id
+  can only be called when game is not already started }
+function TPartyGame.AddPlayer(Team: Integer; Name: String): Integer;
+begin
+  Result := -1;
+
+  if (not bPartyStarted) and (Team >= 0) and (Team <= High(Teams)) and (Length(Teams[Team].Players) < Party_Players_Max) and (Length(Name) > 0) then
+  begin
+    // append element to players array
+    Result := Length(Teams[Team].Players);
+    SetLength(Teams[Team].Players, Result + 1);
+
+    // fill w/ data
+    Teams[Team].Players[Result].Name := Name;
+    Teams[Team].Players[Result].TimesPlayed := 0;
+  end;
+end;
+
+{ starts a new PartyGame, returns true on success
+  before a call of this function teams and players
+  has to be added by AddTeam and AddPlayer }
+function TPartyGame.StartGame(Rounds: ARounds): Boolean;
+  var
+    I: integer;
+begin
+  Result := false;
+
+  if (not bPartyStarted) and (Length(Rounds) > 0) and (Length(Teams) >= Party_Teams_Min) then
+  begin
+    // check teams for minimal player count
+    for I := 0 to High(Teams) do
+      if (Length(Teams[I].Players) < Party_Players_Min) then
+        exit;
+
+    // create rounds array
+    SetLength(Self.Rounds, Length(Rounds));
+
+    for I := 0 to High(Rounds) do
+    begin
+      // copy round or select a random round
+      if (Rounds[I] <> Party_Round_Random) and (Rounds[I] >= 0) and (Rounds[I] <= High(Modes)) then
+        Self.Rounds[I].Mode := Rounds[I]
+      else
+        Self.Rounds[I].Mode := GetRandomMode;
+
+      Self.Rounds[I].AlreadyPlayed := false;
+      Self.Rounds[I].RankingSet := false;
+
+      SetLength(Self.Rounds[I].Ranking, 0);
+    end;
+
+    // get the party started!11
+    bPartyStarted := true;
+    bPartyGame := true;
+    CurRound := low(integer); //< set not to -1 to indicate that party game is not finished
+
+    // first round
+    NextRound;
+
+    Result := True;
+  end;
+end;
+
+{ sets the winner(s) of current round
+  returns true on success }
+function TPartyGame.SetRanking(Ranking: AParty_TeamRanking): Boolean;
+  var
+    I, J: Integer;
+    TeamExists: Integer;
+    Len: Integer;
+    Temp: TParty_TeamRanking;
+begin
+  if (bPartyStarted) and (CurRound >= 0) and (CurRound <= High(Rounds)) then
+  begin
+    Rounds[CurRound].Ranking := Ranking;
+    Result := true;
+
+    // look for teams that don't exist
+    TeamExists := 0;
+    for I := 0 to High(Rounds[CurRound].Ranking) do
+      TeamExists := TeamExists or (1 shl (Rounds[CurRound].Ranking[I].Team-1));
+
+    // create teams that don't exist
+    Len := Length(Rounds[CurRound].Ranking);
+    for I := 0 to High(Teams) do
+      if (TeamExists and (1 shl I) = 0) then
+      begin
+        Inc(Len);
+        SetLength(Rounds[CurRound].Ranking, Len);
+        Rounds[CurRound].Ranking[Len-1].Team := I + 1;
+        Rounds[CurRound].Ranking[Len-1].Rank := Length(Teams);
+      end;
+
+    // we may remove rankings from invalid teams here to
+    // but at the moment this is not necessary, because the
+    // functions this function is called from don't create
+    // invalid rankings
+
+    // bubble sort rankings by team
+    J := High(Rounds[CurRound].Ranking);
+    repeat
+      for I := 0 to J - 1 do
+        if (Rounds[CurRound].Ranking[I].Team > Rounds[CurRound].Ranking[I+1].Team) then
+        begin
+          Temp := Rounds[CurRound].Ranking[I];
+          Rounds[CurRound].Ranking[I] := Rounds[CurRound].Ranking[I+1];
+          Rounds[CurRound].Ranking[I+1] := Temp;
+        end;
+      Dec(J);
+    until J <= 0;
+
+    //set rounds RankingSet to true
+    Rounds[CurRound].RankingSet := true;
+  end
+  else
+    Result := false;
+end;
+
+{ sets ranking of current round by score saved in players array }
+procedure TPartyGame.SetRankingByScore;
+  var
+    I, J: Integer;
+    Rank: Integer;
+    Ranking: AParty_TeamRanking;
+    Scores: array of Integer;
+    TmpRanking: TParty_TeamRanking;
+    TmpScore: Integer;
+begin
+  if (Length(Player) = Length(Teams)) then
+  begin
+    SetLength(Ranking, Length(Teams));
+    SetLength(Scores, Length(Teams));
+
+    // fill ranking array
+    for I := 0 to High(Ranking) do
+    begin
+      Ranking[I].Team := I;
+      Ranking[I].Rank := 0;
+      Scores[I] := Player[I].ScoreTotalInt;
+    end;
+
+    // bubble sort by score
+    J := High(Ranking);
+    repeat
+      for I := 0 to J - 1 do
+        if (Scores[I] < Scores[I+1]) then
+        begin
+          TmpRanking := Ranking[I];
+          Ranking[I] := Ranking[I+1];
+          Ranking[I+1] := TmpRanking;
+
+          TmpScore := Scores[I];
+          Scores[I] := Scores[I+1];
+          Scores[I+1] := TmpScore;
+        end;
+      Dec(J);
+    until J <= 0;
+
+    // set rank field
+    Rank := 1; //first rank has id 1
+    for I := 0 to High(Ranking) do
+    begin
+      Ranking[I].Rank := Rank;
+
+      if (I < High(Ranking)) and (Scores[I] <> Scores[I+1]) then
+        Inc(Rank); // next rank if next team has different score
+    end;
+  end
+  else
+    SetLength(Ranking, 0);
+
+  SetRanking(Ranking);
+end;
+
+{ increases players TimesPlayed value }
+procedure TPartyGame.IncTimesPlayed;
+  var I: Integer;
+begin
+  for I := 0 to High(Teams) do
+    with Teams[I] do
+      Inc(Players[NextPlayer].TimesPlayed);
+end;
+
+{ increases round counter by 1 and clears all round specific information;
+  returns the number of the current round or -1 if last round has already
+  been played }
+function TPartyGame.NextRound: integer;
+  var I: Integer;
+begin
+  // some lines concerning the previous round
+  if (CurRound >= 0) then
+  begin
+    IncTimesPlayed;
+    
+    Rounds[CurRound].AlreadyPlayed := true;
+
+    GenScores;
+  end;
+
+  // increase round counter
+  Inc(CurRound);
+  if (CurRound < -1) then // we start first round
+    CurRound := 0;
+
+  if (CurRound > High(Rounds)) then
+    CurRound := -1; //< last round played
+
+  Result := CurRound;
+
+  // some lines concerning the next round
+  if (CurRound >= 0) then
+  begin
+    // select player
+    for I := 0 to High(Teams) do
+      Teams[I].NextPlayer := GetRandomPlayer(I);
+  end;
+end;
+
+{ indicates that current round has already been played }
+procedure TPartyGame.RoundPlayed;
+begin
+  if (bPartyStarted) and (CurRound >= 0) and (CurRound <= High(Rounds)) then
+  begin
+    // set rounds ranking by score if it was not set by plugin
+    if (not Rounds[CurRound].RankingSet) then
+      SetRankingByScore;
+
+    Rounds[CurRound].AlreadyPlayed := True;
+  end;
+end;
+
+{ returns true if last round was already played }
+function TPartyGame.GameFinished: Boolean;
+begin
+  Result := (bPartyStarted and (CurRound = -1));
+end;
+
+{ private: calls the specified function Func from lua plugin Parent
+           if both exist.
+           return true if default function should be called
+           (function or plugin does not exist, or function returns
+           true) }
+function TPartyGame.CallLua(Parent: Integer; Func: String):Boolean;
+  var
+    P: TLuaPlugin;
+begin
+  // call default function by default
+  Result := true;
+
+  // check for core plugin and empty function name
+  if (Parent >= 0) and (Length(Func) > 0) then
+  begin
+    // get plugin that registred the mode
+    P := LuaCore.GetPluginById(Parent);
+
+    if (P <> nil) then
+    begin
+      if (P.CallFunctionByName(Func, 0, 1)) then
+        // check result
+        Result := (lua_toboolean(P.LuaState, 1));
+    end;
+  end;
+end;
+
+{ call plugins defined function and/or default procedure
+  only default procedure is called when no function is defined by plugin
+  if plugins function returns true then default is called after plugins
+  function was executed}
+procedure TPartyGame.CallBeforeSongSelect;
+  var
+    ExecuteDefault: boolean;
+begin
+  if not bPartyStarted then
+    ExecuteDefault := true
+  else if (CurRound >= 0) then
+  begin
+    // we set screen song to party mode
+    // plugin should not have to do this if it
+    // don't want default procedure to be executed
+    ScreenSong.Mode := smPartyMode;
+
+    with Modes[Rounds[CurRound].Mode] do
+      ExecuteDefault := (CallLua(Parent, Functions.BeforeSongSelect));
+  end
+  else
+    ExecuteDefault := true;
+
+  // execute default function:
+  if ExecuteDefault then
+  begin
+    // display song select screen
+    Display.FadeTo(@ScreenSong);
+  end;
+end;
+
+procedure TPartyGame.CallAfterSongSelect;
+  var
+    ExecuteDefault: boolean; 
+begin
+  if not bPartyStarted then
+    ExecuteDefault := true
+  else if (CurRound >= 0) then
+  begin
+    with Modes[Rounds[CurRound].Mode] do
+      ExecuteDefault := (CallLua(Parent, Functions.AfterSongSelect));
+  end
+  else
+    ExecuteDefault := true;
+
+  // execute default function:
+  if ExecuteDefault then
+  begin
+    // display sing screen
+    ScreenSong.StartSong;
+  end;
+end;
+
+procedure TPartyGame.CallBeforeSing;
+  var
+    ExecuteDefault: boolean;
+begin
+  if not bPartyStarted then
+    ExecuteDefault := true
+  else if (CurRound >= 0) then
+  begin
+    with Modes[Rounds[CurRound].Mode] do
+      ExecuteDefault := (CallLua(Parent, Functions.BeforeSing));
+  end
+  else
+    ExecuteDefault := true;
+
+  // execute default function:
+  if ExecuteDefault then
+  begin
+    //nothing atm
+    { to-do : compartmentalize TSingScreen.OnShow into
+              functions for init of a specific part of
+              sing screen.
+              these functions should be called here before
+              sing screen is shown, or it should be called
+              by plugin if it wants to define a custom
+              singscreen start up. }
+
+    //set correct playersplay
+    if (bPartyGame) then
+      PlayersPlay := Length(Teams);
+  end;
+end;
+
+procedure TPartyGame.CallOnSing;
+  var
+    ExecuteDefault: boolean;
+begin
+  if not bPartyStarted then
+    ExecuteDefault := true
+  else if (CurRound >= 0) then
+  begin
+    with Modes[Rounds[CurRound].Mode] do
+      ExecuteDefault := (CallLua(Parent, Functions.OnSing));;
+  end
+  else
+    ExecuteDefault := true;
+
+  // execute default function:
+  if ExecuteDefault then
+  begin
+    //nothing atm
+  end;
+end;
+
+procedure TPartyGame.CallAfterSing;
+  var
+    ExecuteDefault: boolean;
+begin
+  if not bPartyStarted then
+    ExecuteDefault := true
+  else if (CurRound >= 0) then
+  begin
+    with Modes[Rounds[CurRound].Mode] do
+      ExecuteDefault := (CallLua(Parent, Functions.AfterSing));
+  end
+  else
+    ExecuteDefault := true;
+
+  // execute default function:
+  if ExecuteDefault then
+  begin
+    if (bPartyGame) then
+      // display party score screen
+      Display.FadeTo(@ScreenPartyScore)
+    else //display standard score screen
+      Display.FadeTo(@ScreenScore);
+  end;
+end;
+
+{ returns an array[1..6] of integer. the index stands for the placing,
+  value is the team number (in the team array) }
+function TPartyGame.GetTeamRanking: AParty_TeamRanking;
+  var
+    I, J: Integer;
+    Temp: TParty_TeamRanking;
+    Rank: Integer;
+begin
+  SetLength(Result, Length(Teams));
+
+  // fill ranking array
+  for I := 0 to High(Result) do
+  begin
+    Result[I].Team := I;
+    Result[I].Rank := 0;
+  end;
+
+  // bubble sort by score
+  J := High(Result);
+  repeat
+    for I := 0 to J - 1 do
+      if (Teams[Result[I].Team].Score < Teams[Result[I+1].Team].Score) then
+      begin
+        Temp := Result[I];
+        Result[I] := Result[I+1];
+        Result[I+1] := Temp;
+      end;
+    Dec(J);
+  until J <= 0;
+
+  // set rank field
+  Rank := 1; //first rank has id 1
+  for I := 0 to High(Result) do
+  begin
+    Result[I].Rank := Rank;
+
+    if (I < High(Result)) and (Teams[Result[I].Team].Score <> Teams[Result[I+1].Team].Score) then
+      Inc(Rank); // next rank if next team has different score 
+  end; 
+end;
+
+{ returns a string like "Team 1 (and Team 2) win"
+  if Round is in range from 0 to high(Rounds) then
+  result is name of winners of specified round.
+  if Round is -1 the result is name of winners of
+  the whole party game}
+function TPartyGame.GetWinnerString(Round: integer): UTF8String;
+var
+  Winners: array of UTF8String;
+  I: integer;
+  Ranking: AParty_TeamRanking;
+begin
+  Result := '';
+  Ranking := nil;
+  
+  if (Round >= 0) and (Round <= High(Rounds)) then
+  begin
+    if (not Rounds[Round].AlreadyPlayed) then
+      Result := Language.Translate('PARTY_NOTPLAYEDYET')
+    else
+      Ranking := Rounds[Round].Ranking;
+  end
+  else if (Round = -1) then
+    Ranking := GetTeamRanking;
+
+
+  if (Ranking <> nil) then
+  begin
+    SetLength(Winners, 0);
+    for I := 0 to High(Ranking) do
+    begin
+      if (Ranking[I].Rank = PR_First) and (Ranking[I].Team >= 0) and (Ranking[I].Team <= High(Teams)) then
+      begin
+        SetLength(Winners, Length(Winners) + 1);
+        Winners[high(Winners)] := UTF8String(Teams[Ranking[I].Team].Name);
+      end;
+    end;
+
+    if (Length(Winners) > 0) then
+      Result := Language.Implode(Winners);
+  end;
+
+  if (Length(Result) = 0) then
+    Result := Language.Translate('PARTY_NOBODY');
+end;
+
+end.
diff --git a/songmanagement/src/base/UPath.pas b/songmanagement/src/base/UPath.pas
new file mode 100644
index 00000000..7cb2f649
--- /dev/null
+++ b/songmanagement/src/base/UPath.pas
@@ -0,0 +1,1427 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UPath;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+interface
+
+uses
+  SysUtils,
+  Classes,
+  IniFiles,
+  {$IFDEF MSWINDOWS}
+  TntClasses,
+  {$ENDIF}
+  UConfig,
+  UUnicodeUtils;
+
+type
+  IPath = interface;
+
+  {$IFDEF FPC}
+  TFileHandle = THandle;
+  {$ELSE}
+  TFileHandle = Longint;
+  {$ENDIF}
+
+  {**
+   * TUnicodeMemoryStream
+   *}
+  TUnicodeMemoryStream = class(TMemoryStream)
+  public
+    procedure LoadFromFile(const FileName: IPath);
+    procedure SaveToFile(const FileName: IPath);
+  end;
+
+  {**
+   * Unicode capable IniFile implementation.
+   * TMemIniFile and TIniFile are not able to handle INI-files with
+   * an UTF-8 BOM. This implementation checks if an UTF-8 BOM exists
+   * and removes it from the internal string-list.
+   * UTF8Encoded is set accordingly.
+   *}
+  TUnicodeMemIniFile = class(TMemIniFile)
+  private
+    FFilename: IPath;
+    FUTF8Encoded: boolean;
+  public
+    constructor Create(const FileName: IPath; UTF8Encoded: boolean = false); reintroduce;
+    procedure UpdateFile; override;
+    property UTF8Encoded: boolean READ FUTF8Encoded WRITE FUTF8Encoded;
+  end;
+  
+  {**
+   * TBinaryFileStream (inherited from THandleStream)
+   *}
+  {$IFDEF MSWINDOWS}
+  TBinaryFileStream = class(TTntFileStream)
+  {$ELSE}
+  TBinaryFileStream = class(TFileStream)
+  {$ENDIF}
+  public
+    {**
+     * @seealso TFileStream.Create for valid Mode parameters
+     *}
+    constructor Create(const FileName: IPath; Mode: word);
+  end;
+
+  {**
+   * TTextFileStream
+   *}
+  TTextFileStream = class(TStream)
+  protected
+    fLineBreak: RawByteString;
+    fFilename: IPath;
+    fMode: word;
+
+    function ReadLine(var Success: boolean): RawByteString; overload; virtual; abstract;
+  public
+    constructor Create(Filename: IPath; Mode: word);
+
+    function ReadString(): RawByteString; virtual; abstract;
+    function ReadLine(var Line: UTF8String): boolean; overload;
+    function ReadLine(var Line: AnsiString): boolean; overload;
+
+    procedure WriteString(const Str: RawByteString); virtual;
+    procedure WriteLine(const Line: RawByteString); virtual;
+
+    property LineBreak: RawByteString read fLineBreak write fLineBreak;
+    property Filename: IPath read fFilename;
+  end;
+
+  {**
+   * TMemTextStream
+   *}
+  TMemTextFileStream = class(TTextFileStream)
+  private
+    fStream: TMemoryStream;
+  protected
+    function GetSize: int64; override;
+
+    {**
+     * Copies fStream.Memory from StartPos to EndPos-1 to the result string;
+     *}
+    function CopyMemString(StartPos: int64; EndPos: int64): RawByteString;
+  public
+    constructor Create(Filename: IPath; Mode: word);
+    destructor Destroy(); override;
+
+    function Read(var Buffer; Count: longint): longint; override;
+    function Write(const Buffer; Count: longint): longint; override;
+    function Seek(Offset: longint; Origin: word): longint; override;
+    function Seek(const Offset: int64; Origin: TSeekOrigin): int64; override;
+
+    function ReadLine(var Success: boolean): RawByteString; override;
+    function ReadString(): RawByteString; override;
+  end;
+
+  {**
+  TUnicodeIniStream = class()
+  end;
+  *}
+
+  {**
+   * pdKeep:   Keep path as is, neither remove or append a delimiter
+   * pdAppend: Append a delimiter if path does not have a trailing one 
+   * pdRemove: Remove a trailing delimiter from the path 
+   *}
+  TPathDelimOption = (pdKeep, pdAppend, pdRemove);
+
+  IPathDynArray = array of IPath;
+
+  {**
+   * An IPath represents a filename, a directory or a filesystem path in general.
+   * It hides some of the operating system's specifics like path delimiters
+   * and encodings and provides an easy to use interface to handle them.
+   * Internally all paths are stored with the same path delimiter (PathDelim)
+   * and encoding (UTF-8). The transformation is already done AT THE CREATION of
+   * the IPath and hence calls to e.g. IPath.Equal() will not distinguish between
+   * Unix and Windows style paths.
+   *
+   * Create new paths with one of the Path() functions.
+   * If you need a string representation use IPath.ToNative/ToUTF8/ToWide.
+   * Note that due to the path-delimiter and encoding transformation the string
+   * might have changed. Path('one\test/path').ToUTF8() might return 'one/test/path'.
+   *
+   * It is recommended to use an IPath as long as possible without a string
+   * conversion (IPath.To...()). The whole Delphi (< 2009) and FPC RTL is ANSI
+   * only on Windows. If you would use for example FileExists(MyPath.ToNative)
+   * it would not find a file which contains characters that are not in the
+   * current locale. Same applies to AssignFile(), TFileStream.Create() and
+   * everything else in the RTL that expects a filename.
+   * As a rule of thumb: NEVER use any of the Delphi/FPC RTL filename functions
+   * if the filename parameter is not of a UTF8String or WideString type.
+   *
+   * If you need to open a file use TBinaryStream or TFileStream instead. Many
+   * of the RTL classes offer a LoadFromStream() method so ANSI Open() methods
+   * can be workaround.
+   *
+   * If there is only a ANSI and no IPath/UTF-8/WideString version and you cannot
+   * even pass a stream instead of a filename be aware that even if you know that
+   * a filename is ASCII only, subdirectories in an absolute path might contain
+   * some non-ASCII characters (for example the user's name) and hence might
+   * fail (if the characters are not in the current locale).
+   * It is rare but it happens.
+   *
+   * IMPORTANT:
+   *   This interface needs the cwstring unit on Unix (Max OS X / Linux) systems.
+   *   Cwstring functions (WideUpperCase, ...) cannot be used by external threads
+   *   as FPC uses Thread-Local-Storage for the implementation. As a result do not
+   *   call IPath stuff by external threads (e.g. in C callbacks or by SDL-threads).
+   *}
+  IPath = interface
+  ['{686BF103-CE43-4598-B85D-A2C3AF950897}']
+    {**
+     * Returns the path as an UTF8 encoded string.
+     * If UseNativeDelim is set to true, the native path delimiter ('\' on win32)
+     * is used. If it is set to false the (more) portable '/' delimiter will used.
+     *}
+    function ToUTF8(UseNativeDelim: boolean = true): UTF8String;
+
+    {**
+     * Returns the path as an UTF-16 encoded string.
+     * If UseNativeDelim is set to true, the native path delimiter ('\' on win32)
+     * is used. If it is set to false the delimiter will be '/'.
+     *}
+    function ToWide(UseNativeDelim: boolean = true): WideString;
+
+    {**
+     * Returns the path with the system's native encoding and path delimiter.
+     * Win32: ANSI (use the UTF-16 version IPath.ToWide() whenever possible)
+     * Mac:   UTF8
+     * Unix:  UTF8 or ANSI according to LC_CTYPE
+     *}
+    function ToNative(): RawByteString;
+
+    {**
+     * Note: File must be closed with FileClose(Handle) after usage
+     * @seealso SysUtils.FileOpen()
+     *}
+    function Open(Mode: longword): TFileHandle;
+
+    {** @seealso SysUtils.ExtractFileDrive() *}
+    function GetDrive(): IPath;
+
+    {** @seealso SysUtils.ExtractFilePath() *}
+    function GetPath(): IPath;
+
+    {** @seealso SysUtils.ExtractFileDir() *}
+    function GetDir(): IPath;
+
+    {** @seealso SysUtils.ExtractFileName() *}
+    function GetName(): IPath;
+
+    {** @seealso SysUtils.ExtractFileExtension() *}
+    function GetExtension(): IPath;
+
+    {**
+     * Returns a copy of the path with the extension changed to Extension.
+     * The file itself is not changed, use Rename() for this task.
+     * @seealso SysUtils.ChangeFileExt()
+     *}
+    function SetExtension(const Extension: IPath): IPath; overload;
+    function SetExtension(const Extension: RawByteString): IPath; overload;
+    function SetExtension(const Extension: WideString): IPath; overload;
+
+    {**
+     * Returns the representation of the path relative to Basename.
+     * Note that the basename must be terminated with a path delimiter
+     * otherwise the last path component will be ignored.
+     * @seealso SysUtils.ExtractRelativePath()
+     *}
+    function GetRelativePath(const BaseName: IPath): IPath;
+
+    {** @seealso SysUtils.ExpandFileName() *}
+    function GetAbsolutePath(): IPath;
+
+    {**
+     * Returns the concatenation of this path with Child. If this path does not
+     * end with a path delimiter one is inserted in front of the Child path.
+     * Example: Path('parent').Append(Path('child')) -> Path('parent/child')
+     *}
+    function Append(const Child: IPath; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
+    function Append(const Child: RawByteString; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
+    function Append(const Child: WideString; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
+
+    {**
+     * Splits the path into its components. Path delimiters are not removed from
+     * components. 
+     * Example: C:\test\my\dir -> ['C:\', 'test\', 'my\', 'dir']
+     *}
+    function SplitDirs(): IPathDynArray;
+
+    {**
+     * Returns the parent directory or PATH_NONE if none exists.
+     *}
+    function GetParent(): IPath;
+
+    {**
+     * Checks if this path is a subdir of or file inside Parent.
+     * If Direct is true this path must be a direct child.
+     * Example: C:\test\file is a direct child of C:\test and a child of C:\
+     *}
+    function IsChildOf(const Parent: IPath; Direct: boolean): boolean;
+
+    {**
+     * Adjusts the case of the path on case senstitive filesystems.
+     * If the path does not exist or the filesystem is case insensitive
+     * the original path will be returned. Otherwise a corrected copy.
+     *}
+    function AdjustCase(AdjustAllLevels: boolean): IPath;
+
+    {** @seealso SysUtils.IncludeTrailingPathDelimiter() *}
+    function AppendPathDelim(): IPath;
+
+    {** @seealso SysUtils.ExcludeTrailingPathDelimiter() *}
+    function RemovePathDelim(): IPath;
+
+    function Exists(): boolean;
+    function IsFile(): boolean;
+    function IsDirectory(): boolean;
+    function IsAbsolute(): boolean;
+    function GetFileAge(): integer; overload;
+    function GetFileAge(out FileDateTime: TDateTime): boolean; overload;
+    function GetAttr(): cardinal;
+    function SetAttr(Attr: Integer): boolean;
+    function IsReadOnly(): boolean;
+    function SetReadOnly(ReadOnly: boolean): boolean;
+
+    {**
+     * Checks if this path points to nothing, that means the path consists of
+     * the empty string '' and hence equals PATH_NONE.
+     * This is a shortcut for IPath.Equals('') or IPath.Equals(PATH_NONE).
+     * If IsUnset() returns true this path and PATH_NONE are equal but they must
+     * not be identical as the references might point to different objects.
+     *
+     * Example:
+     *   Path('').Equals(PATH_EMPTY) -> true
+     *   Path('') = PATH_EMPTY       -> false
+     *}
+    function IsUnset(): boolean;
+    function IsSet(): boolean;
+
+    {**
+     * Compares this path with Other and returns true if both paths are
+     * equal. Both paths are expanded and trailing slashes excluded before
+     * comparison. If IgnoreCase is true, the case will be ignored on
+     * case-sensitive filesystems.
+     *}
+    function Equals(const Other: IPath; IgnoreCase: boolean = false): boolean; overload;
+    function Equals(const Other: RawByteString; IgnoreCase: boolean = false): boolean; overload;
+    function Equals(const Other: WideString; IgnoreCase: boolean = false): boolean; overload;
+
+    {**
+     * Searches for a file in DirList. The Result is nil if the file was
+     * not found. Use IFileSystem.FileFind() instead if you want to use
+     * wildcards.
+     * @seealso SysUtils.FileSearch()
+     *}
+    function FileSearch(const DirList: IPath): IPath;
+
+    {**
+     * File must be closed with FileClose(Handle) after usage
+     *}
+    function CreateFile(): TFileHandle;
+    function DeleteFile(): boolean;
+    function CreateDirectory(Force: boolean = false): boolean;
+    function DeleteEmptyDir(): boolean;
+    function Rename(const NewName: IPath): boolean;
+    function CopyFile(const Target: IPath; FailIfExists: boolean): boolean;
+
+    // TODO: Dirwatch stuff
+    // AddFileChangeListener(Listener: TFileChangeListener);
+
+    {**
+     * Internal string representation. For debugging only.
+     *}
+    function GetIntern: UTF8String;
+    property Intern: UTF8String READ GetIntern;
+  end;
+
+{**
+ * Creates a new path with the given pathname. PathName can be either in UTF8
+ * or the local encoding.
+ * Notes:
+ * - On Apple only UTF8 is supported
+ * - Same applies to Unix with LC_CTYPE set to UTF8 encoding (default on newer systems)
+ *}
+function Path(const PathName: RawByteString; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
+function Path(PathName: PChar; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
+
+{**
+ * Creates a new path with the given UTF-16 pathname.
+ *}
+function Path(const PathName: WideString; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
+
+{**
+ * Returns a singleton for Path('').
+ *}
+function PATH_NONE(): IPath;
+
+implementation
+
+uses
+  RTLConsts,
+  UTextEncoding,
+  UFilesystem;
+
+{*
+ * Due to a compiler bug in FPC <= 2.2.4 reference counting does not work
+ * properly with interfaces (see http://bugs.freepascal.org/view.php?id=14019).
+ *
+ * There are two (probably more) scenarios causes a program to crash:
+ *
+ * 1. Assume we execute Path('fail').GetParent().ToUTF8(). The compiler will
+ * internally create a temporary variable to hold the result of Path('fail').
+ * This temporary var is then passed as Self to GetParent(). Unfortunately FPC
+ * does already decrement the ref-count of the temporary var at the end of the
+ * call to Path('fail') and the ref-count drops to zero and the temp object
+ * is destroyed as FPC erroneously assumes that the temp is not used anymore.
+ * As a result the Self variable in GetParent() will be invalid, the same
+ * applies to TPathImpl.fName which reference count dropped to zero when the
+ * temp was destroyed. Hence GetParent() will likely crash.
+ * If it does not, ToUTF8() will either return some random string
+ * (e.g. '' or stupid stuff like 'fhwkjehdk') or crash.
+ * Either way the result of ToUTF8() is messed up.
+ * This scenario applies whenever a function (or method) is called that returns
+ * an interfaced object (e.g. an IPath) and the result is used without storing
+ * a reference to it in a (temporary) variable first.
+ *
+ *  Tmp := Path('fail'); Tmp2 := Tmp.GetParent(); Tmp2.ToUTF8();
+ *
+ * will not crash but is very impractical and error-prone. Note that Tmp2 cannot
+ * be replaced with Tmp (see scenario 2).
+ *
+ * 2. Another situation this bug will ruin our lives is when a variable to an
+ * interfaced object is used at the left and right side of an assignment as in:
+ *   MyPath := MyPath.GetParent()
+ *
+ * Although the bug is already fixed in the FPC development version 2.3.1
+ * it will take quite some time till the next FPC release (> 2.2.4) in which
+ * this issue is fixed.
+ *
+ * To workaround this bug we use some very simple and stupid kind of garbage
+ * collection. New IPaths are stored in an IInterfaceList (call it GarbaegeList)
+ * to artificially increase the ref-count of the newly created object.
+ * This keeps the object alive when FPC's temporary variable comes to the end
+ * of its lifetime and the object's ref-count is decremented
+ * (and is now 1 instead of 0).
+ * Later on, the object is either garbage or referenced by another variable.
+ *
+ * Look at
+ *   MyPath := Path('SomeDir/SubDir').GetParent()
+ *
+ * (1) The result of Path('SomeDir/SubDir') is garbage as it is not used anymore.
+ * (2) The result of GetParent() is referenced by MyPath
+ * Object (1) has a reference count of 1 (as it is only referenced by the
+ * GarbageList). Object (2) is referenced twice (MyPath + GarbageList).
+ * When the reference to (2) is finally stored in MyPath we can safely remove
+ * (1) and (2) from the GarbageList so (1) will be freed and the ref-count of
+ * (2) will be decremented to 1.
+ *
+ * As we do not know when it is safe to remove an object from the GarbageList
+ * we assume that there are max. GarbageMaxCount IPath elements created until
+ * the execution of the expression is performed and a reference to the resulting
+ * object is assigned to a variable so all temps can be safely deleted.
+ *
+ * Worst-case scenarios are recursive calls or calls with large call stacks with
+ * functions that return an IPath. Also keep in mind that multiple threads might
+ * be executing such functions at the same time.
+ * A reasonable count might be a max. of 20.000 elements. With an average length
+ * of 40 UTF8 chars (maybe 60 byte with class info, pointer etc.) per IPath
+ * this will consume ~1.2MB.
+ *}
+{$IFDEF FPC}
+{$IF FPC_VERSION_INT <= 002002004} // <= 2.2.4
+  {$DEFINE HAVE_REFCNTBUG}
+{$IFEND}
+{$ENDIF}
+
+{$IFDEF HAVE_REFCNTBUG}
+const
+  // when GarbageList.Count reaches GarbageMaxCount the oldest references in
+  // GarbageList will be deleted until GarbageList.Count equals GarbageAfterCleanCount.
+  GarbageMaxCount = 20000;
+  GarbageAfterCleanCount = GarbageMaxCount-1000;
+
+var
+  GarbageList: IInterfaceList;
+{$ENDIF}
+
+type
+  TPathImpl = class(TInterfacedObject, IPath)
+    private
+      fName: UTF8String; //<** internal filename string, always UTF8 with PathDelim
+
+      {**
+       * Unifies the filename. Path-delimiters are replaced by '/'.
+       *}
+      procedure Unify(DelimOption: TPathDelimOption);
+
+      {**
+       * Returns a copy of fName with path delimiters changed to '/'.
+       *}
+      function GetPortableString(): UTF8String;
+
+      procedure AssertRefCount; {$IFDEF HasInline}inline;{$ENDIF}
+
+    public
+      constructor Create(const Name: UTF8String; DelimOption: TPathDelimOption);
+      destructor Destroy(); override;
+
+      function ToUTF8(UseNativeDelim: boolean): UTF8String;
+      function ToWide(UseNativeDelim: boolean): WideString;
+      function ToNative(): RawByteString;
+
+      function Open(Mode: longword): TFileHandle;
+
+      function GetDrive(): IPath;
+      function GetPath(): IPath;
+      function GetDir(): IPath;
+      function GetName(): IPath;
+      function GetExtension(): IPath;
+
+      function SetExtension(const Extension: IPath): IPath; overload;
+      function SetExtension(const Extension: RawByteString): IPath; overload;
+      function SetExtension(const Extension: WideString): IPath; overload;
+
+      function GetRelativePath(const BaseName: IPath): IPath;
+      function GetAbsolutePath(): IPath;
+      function GetParent(): IPath;
+      function SplitDirs(): IPathDynArray;
+
+      function Append(const Child: IPath; DelimOption: TPathDelimOption): IPath; overload;
+      function Append(const Child: RawByteString; DelimOption: TPathDelimOption): IPath; overload;
+      function Append(const Child: WideString; DelimOption: TPathDelimOption): IPath; overload;
+
+      function Equals(const Other: IPath; IgnoreCase: boolean): boolean; overload;
+      function Equals(const Other: RawByteString; IgnoreCase: boolean): boolean; overload;
+      function Equals(const Other: WideString; IgnoreCase: boolean): boolean; overload;
+
+      function IsChildOf(const Parent: IPath; Direct: boolean): boolean;
+
+      function AdjustCase(AdjustAllLevels: boolean): IPath;
+
+      function AppendPathDelim(): IPath;
+      function RemovePathDelim(): IPath;
+
+      function GetFileAge(): integer; overload;
+      function GetFileAge(out FileDateTime: TDateTime): boolean; overload;
+      function Exists(): boolean;
+      function IsFile(): boolean;
+      function IsDirectory(): boolean;
+      function IsAbsolute(): boolean;
+      function GetAttr(): cardinal;
+      function SetAttr(Attr: Integer): boolean;
+      function IsReadOnly(): boolean;
+      function SetReadOnly(ReadOnly: boolean): boolean;
+
+      function IsUnset(): boolean;
+      function IsSet(): boolean;
+
+      function FileSearch(const DirList: IPath): IPath;
+
+      function CreateFile(): TFileHandle;
+      function DeleteFile(): boolean;
+      function CreateDirectory(Force: boolean): boolean;
+      function DeleteEmptyDir(): boolean;
+      function Rename(const NewName: IPath): boolean;
+      function CopyFile(const Target: IPath; FailIfExists: boolean): boolean;
+
+      function GetIntern(): UTF8String;
+  end;
+
+function Path(const PathName: RawByteString; DelimOption: TPathDelimOption): IPath;
+begin
+  if (IsUTF8String(PathName)) then
+    Result := TPathImpl.Create(PathName, DelimOption)
+  else if (IsNativeUTF8()) then
+    Result := PATH_NONE
+  else
+    Result := TPathImpl.Create(AnsiToUtf8(PathName), DelimOption);
+end;
+
+function Path(PathName: PChar; DelimOption: TPathDelimOption): IPath;
+begin
+  Result := Path(RawByteString(PathName));
+end;
+
+function Path(const PathName: WideString; DelimOption: TPathDelimOption): IPath;
+begin
+  Result := TPathImpl.Create(UTF8Encode(PathName), DelimOption);
+end;
+
+
+
+procedure TPathImpl.AssertRefCount;
+begin
+  {$IFDEF HAVE_REFCNTBUG}
+  if (FRefCount <= 0) then
+    raise Exception.Create('RefCount error: ' + IntToStr(FRefCount));
+  {$ENDIF}
+end;
+
+constructor TPathImpl.Create(const Name: UTF8String; DelimOption: TPathDelimOption);
+begin
+  inherited Create();
+  fName := Name;
+  Unify(DelimOption);
+  {$IFDEF HAVE_REFCNTBUG}
+  GarbageList.Lock;
+  if (GarbageList.Count >= GarbageMaxCount) then
+  begin
+    while (GarbageList.Count > GarbageAfterCleanCount) do
+      GarbageList.Delete(0);
+  end;
+  GarbageList.Add(Self);
+  GarbageList.Unlock;
+  {$ENDIF}
+end;
+
+destructor TPathImpl.Destroy();
+begin
+  inherited;
+end;
+
+procedure TPathImpl.Unify(DelimOption: TPathDelimOption);
+var
+  I: integer;
+begin
+  // convert all path delimiters to native ones
+  for I := 1 to Length(fName) do
+  begin
+    if (fName[I] in ['\', '/']) and (fName[I] <> PathDelim) then
+      fName[I] := PathDelim;
+  end;
+
+  // Include/ExcludeTrailingPathDelimiter need PathDelim as path delimiter 
+  case DelimOption of
+    pdAppend: fName := IncludeTrailingPathDelimiter(fName);
+    pdRemove: fName := ExcludeTrailingPathDelimiter(fName);
+  end;
+end;
+
+function TPathImpl.GetPortableString(): UTF8String;
+var
+  I: integer;
+begin
+  Result := fName;
+  if (PathDelim = '/') then
+    Exit;
+
+  for I := 1 to Length(Result) do
+  begin
+    if (Result[I] = PathDelim) then
+      Result[I] := '/';
+  end;
+end;
+
+function TPathImpl.ToUTF8(UseNativeDelim: boolean): UTF8String;
+begin
+  AssertRefCount;
+
+  if (UseNativeDelim) then
+    Result := fName
+  else
+    Result := GetPortableString();
+end;
+
+function TPathImpl.ToWide(UseNativeDelim: boolean): WideString;
+begin
+  if (UseNativeDelim) then
+    Result := UTF8Decode(fName)
+  else
+    Result := UTF8Decode(GetPortableString());
+end;
+
+function TPathImpl.ToNative(): RawByteString;
+begin
+  if (IsNativeUTF8()) then
+    Result := fName
+  else
+    Result := Utf8ToAnsi(fName);
+end;
+
+function TPathImpl.GetDrive(): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.ExtractFileDrive(Self);
+end;
+
+function TPathImpl.GetPath(): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.ExtractFilePath(Self);
+end;
+
+function TPathImpl.GetDir(): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.ExtractFileDir(Self);
+end;
+
+function TPathImpl.GetName(): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.ExtractFileName(Self);
+end;
+
+function TPathImpl.GetExtension(): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.ExtractFileExt(Self);
+end;
+
+function TPathImpl.SetExtension(const Extension: IPath): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.ChangeFileExt(Self, Extension);
+end;
+
+function TPathImpl.SetExtension(const Extension: RawByteString): IPath;
+begin
+  Result := SetExtension(Path(Extension));
+end;
+
+function TPathImpl.SetExtension(const Extension: WideString): IPath;
+begin
+  Result := SetExtension(Path(Extension));
+end;
+
+function TPathImpl.GetRelativePath(const BaseName: IPath): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.ExtractRelativePath(BaseName, Self);
+end;
+
+function TPathImpl.GetAbsolutePath(): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.ExpandFileName(Self);
+end;
+
+function TPathImpl.GetParent(): IPath;
+var
+  CurPath, ParentPath: IPath;
+begin
+  AssertRefCount;
+
+  Result := PATH_NONE;
+
+  CurPath := Self.RemovePathDelim();
+  // check if current path has a parent (no further '/')
+  if (Pos(PathDelim, CurPath.ToUTF8()) = 0) then
+    Exit;
+
+  // set new path and check if it has changed to avoid endless loops
+  // e.g. with invalid paths like '/C:' (GetPath() uses ':' as delimiter too)
+  // on delphi/win32
+  ParentPath := CurPath.GetPath();
+  if (ParentPath.ToUTF8 = CurPath.ToUTF8)  then
+    Exit;
+
+  Result := ParentPath;
+end;
+
+function TPathImpl.SplitDirs(): IPathDynArray;
+var
+  CurPath: IPath;
+  Components: array of IPath;
+  CurPathStr: UTF8String;
+  DelimPos: integer;
+  I: integer;
+begin
+  SetLength(Result, 0);
+
+  if (Length(Self.ToUTF8(true)) = 0) then
+    Exit;
+
+  CurPath := Self;
+  SetLength(Components, 0);
+  repeat
+    SetLength(Components, Length(Components)+1);
+
+    CurPathStr := CurPath.ToUTF8();
+    DelimPos := LastDelimiter(PathDelim, SysUtils.ExcludeTrailingPathDelimiter(CurPathStr));
+    Components[High(Components)] := Path(Copy(CurPathStr, DelimPos+1, Length(CurPathStr)));
+
+    CurPath := CurPath.GetParent();
+  until (CurPath = PATH_NONE);
+
+  // reverse list
+  SetLength(Result, Length(Components));
+  for I := 0 to High(Components) do
+    Result[I] := Components[High(Components)-I];
+end;
+
+function TPathImpl.Append(const Child: IPath; DelimOption: TPathDelimOption): IPath;
+var
+  TmpResult: IPath;
+begin
+  AssertRefCount;
+
+  if (fName = '') then
+    TmpResult := Child
+  else
+    TmpResult := Path(Self.AppendPathDelim().ToUTF8() + Child.ToUTF8());
+
+  case DelimOption of
+    pdKeep: Result := TmpResult;
+    pdAppend: Result := TmpResult.AppendPathDelim;
+    pdRemove: Result := TmpResult.RemovePathDelim;
+  end;
+end;
+
+function TPathImpl.Append(const Child: RawByteString; DelimOption: TPathDelimOption): IPath;
+begin
+  AssertRefCount;
+  Result := Append(Path(Child), DelimOption);
+end;
+
+function TPathImpl.Append(const Child: WideString; DelimOption: TPathDelimOption): IPath;
+begin
+  AssertRefCount;
+  Result := Append(Path(Child), DelimOption);
+end;
+
+function TPathImpl.Equals(const Other: IPath; IgnoreCase: boolean): boolean;
+var
+  SelfPath, OtherPath: UTF8String;
+begin
+  SelfPath := Self.GetAbsolutePath().RemovePathDelim().ToUTF8();
+  OtherPath := Other.GetAbsolutePath().RemovePathDelim().ToUTF8();
+  if (FileSystem.IsCaseSensitive() and not IgnoreCase) then
+    Result := (CompareStr(SelfPath, OtherPath) = 0)
+  else
+    Result := (CompareText(SelfPath, OtherPath) = 0);
+end;
+
+function TPathImpl.Equals(const Other: RawByteString; IgnoreCase: boolean): boolean;
+begin
+  Result := Equals(Path(Other), IgnoreCase);
+end;
+
+function TPathImpl.Equals(const Other: WideString; IgnoreCase: boolean): boolean;
+begin
+  Result := Equals(Path(Other), IgnoreCase);
+end;
+
+function TPathImpl.IsChildOf(const Parent: IPath; Direct: boolean): boolean;
+var
+  SelfPath, ParentPath: UTF8String;
+begin
+  Result := false;
+
+  if (Direct) then
+  begin
+    SelfPath := Self.GetParent().GetAbsolutePath().AppendPathDelim().ToUTF8();
+    ParentPath := Parent.GetAbsolutePath().AppendPathDelim().ToUTF8();
+
+    // simply check if this paths parent path (SelfPath) equals ParentPath
+    Result := (SelfPath = ParentPath);
+  end
+  else
+  begin
+    SelfPath := Self.GetAbsolutePath().AppendPathDelim().ToUTF8();
+    ParentPath := Parent.GetAbsolutePath().AppendPathDelim().ToUTF8();
+
+    if (Length(SelfPath) <= Length(ParentPath)) then
+      Exit;
+
+    // check if ParentPath is a substring of SelfPath
+    if (FileSystem.IsCaseSensitive()) then
+      Result := (StrLComp(PAnsiChar(SelfPath), PAnsiChar(ParentPath), Length(ParentPath)) = 0)
+    else
+      Result := (StrLIComp(PAnsiChar(SelfPath), PAnsiChar(ParentPath), Length(ParentPath)) = 0)
+  end;
+end;
+
+function AdjustCaseRecursive(CurPath: IPath; AdjustAllLevels: boolean): IPath;
+var
+  OldParent, AdjustedParent: IPath;
+  LocalName: IPath;
+  PathFound: IPath;
+  PathWithAdjParent: IPath;
+  SearchInfo: TFileInfo;
+  FileIter: IFileIterator;
+  Pattern: IPath;
+begin
+  // if case-sensitive path exists there is no need to adjust case
+  if (CurPath.Exists()) then
+  begin
+    Result := CurPath;
+    Exit;
+  end;
+
+  LocalName := CurPath.RemovePathDelim().GetName();
+
+  // try to adjust parent
+  OldParent := CurPath.GetParent();
+  if (OldParent <> PATH_NONE) then
+  begin
+    if (not AdjustAllLevels) then
+    begin
+      AdjustedParent := OldParent;
+    end
+    else
+    begin
+      AdjustedParent := AdjustCaseRecursive(OldParent, AdjustAllLevels);
+      if (AdjustedParent = nil) then
+      begin
+        // parent path was not found case-insensitive
+        Result := nil;
+        Exit;
+      end;
+
+      // check if the path with adjusted parent can be found now
+      PathWithAdjParent := AdjustedParent.Append(LocalName);
+      if (PathWithAdjParent.Exists()) then
+      begin
+        Result := PathWithAdjParent;
+        Exit;
+      end;
+    end;
+    Pattern := AdjustedParent.Append(Path('*'));
+  end
+  else // path has no parent
+  begin
+    // the top path can either be absolute or relative
+    if (CurPath.IsAbsolute) then
+    begin
+      // the only absolute directory at Unix without a parent is root ('/')
+      // and hence does not need to be adjusted
+      Result := CurPath;
+      Exit;
+    end;
+    // this is a relative path, search in the current working dir
+    AdjustedParent := nil;
+    Pattern := Path('*');
+  end;
+
+  // compare name with all files in the current directory case-insensitive
+  FileIter := FileSystem.FileFind(Pattern, faAnyFile);
+  while (FileIter.HasNext()) do
+  begin
+    SearchInfo := FileIter.Next();
+    PathFound := SearchInfo.Name;
+    if (CompareText(LocalName.ToUTF8, PathFound.ToUTF8) = 0) then
+    begin
+      if (AdjustedParent <> nil) then
+        Result := AdjustedParent.Append(PathFound)
+      else
+        Result := PathFound;
+      Exit;
+    end;
+  end;
+
+  // no matching file found
+  Result := nil;
+end;
+
+function TPathImpl.AdjustCase(AdjustAllLevels: boolean): IPath;
+begin
+  AssertRefCount;
+
+  Result := Self;
+
+  if (FileSystem.IsCaseSensitive) then
+  begin
+    Result := AdjustCaseRecursive(Self, AdjustAllLevels);
+    if (Result = nil) then
+      Result := Self;
+  end;
+end;
+
+function TPathImpl.AppendPathDelim(): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.IncludeTrailingPathDelimiter(Self);
+end;
+
+function TPathImpl.RemovePathDelim(): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.ExcludeTrailingPathDelimiter(Self);
+end;
+
+function TPathImpl.CreateFile(): TFileHandle;
+begin
+  Result := FileSystem.FileCreate(Self);
+end;
+
+function TPathImpl.CreateDirectory(Force: boolean): boolean;
+begin
+  if (Force) then
+    Result := FileSystem.ForceDirectories(Self)
+  else
+    Result := FileSystem.DirectoryCreate(Self);
+end;
+
+function TPathImpl.Open(Mode: longword): TFileHandle;
+begin
+  Result := FileSystem.FileOpen(Self, Mode);
+end;
+
+function TPathImpl.GetFileAge(): integer;
+begin
+  Result := FileSystem.FileAge(Self);
+end;
+
+function TPathImpl.GetFileAge(out FileDateTime: TDateTime): boolean;
+begin
+  Result := FileSystem.FileAge(Self, FileDateTime);
+end;
+
+function TPathImpl.Exists(): boolean;
+begin
+  // note the different specifications of FileExists() on Win32 <> Unix
+  {$IFDEF MSWINDOWS}
+  Result := IsFile() or IsDirectory();
+  {$ELSE}
+  Result := FileSystem.FileExists(Self);
+  {$ENDIF}
+end;
+
+function TPathImpl.IsFile(): boolean;
+begin
+  // note the different specifications of FileExists() on Win32 <> Unix
+  {$IFDEF MSWINDOWS}
+  Result := FileSystem.FileExists(Self);
+  {$ELSE}
+  Result := Exists() and not IsDirectory();
+  {$ENDIF}
+end;
+
+function TPathImpl.IsDirectory(): boolean;
+begin
+  Result := FileSystem.DirectoryExists(Self);
+end;
+
+function TPathImpl.IsAbsolute(): boolean;
+begin
+  AssertRefCount;
+  Result := FileSystem.FileIsAbsolute(Self);
+end;
+
+function TPathImpl.GetAttr(): cardinal;
+begin
+  Result := FileSystem.FileGetAttr(Self);
+end;
+
+function TPathImpl.SetAttr(Attr: Integer): boolean;
+begin
+  Result := FileSystem.FileSetAttr(Self, Attr);
+end;
+
+function TPathImpl.IsReadOnly(): boolean;
+begin
+  Result := FileSystem.FileIsReadOnly(Self);
+end;
+
+function TPathImpl.SetReadOnly(ReadOnly: boolean): boolean;
+begin
+  Result := FileSystem.FileSetReadOnly(Self, ReadOnly);
+end;
+
+function TPathImpl.IsUnset(): boolean;
+begin
+  Result := (fName = '');
+end;
+
+function TPathImpl.IsSet(): boolean;
+begin
+  Result := (fName <> '');
+end;
+
+function TPathImpl.FileSearch(const DirList: IPath): IPath;
+begin
+  AssertRefCount;
+  Result := FileSystem.FileSearch(Self, DirList);
+end;
+
+function TPathImpl.Rename(const NewName: IPath): boolean;
+begin
+  Result := FileSystem.RenameFile(Self, NewName);
+end;
+
+function TPathImpl.DeleteFile(): boolean;
+begin
+  Result := FileSystem.DeleteFile(Self);
+end;
+
+function TPathImpl.DeleteEmptyDir(): boolean;
+begin
+  Result := FileSystem.RemoveDir(Self);
+end;
+
+function TPathImpl.CopyFile(const Target: IPath; FailIfExists: boolean): boolean;
+begin
+  Result := FileSystem.CopyFile(Self, Target, FailIfExists);
+end;
+
+function TPathImpl.GetIntern(): UTF8String;
+begin
+  Result := fName;
+end;
+
+
+{ TBinaryFileStream }
+
+constructor TBinaryFileStream.Create(const FileName: IPath; Mode: word);
+begin
+{$IFDEF MSWINDOWS}
+  inherited Create(FileName.ToWide(), Mode);
+{$ELSE}
+  inherited Create(FileName.ToNative(), Mode);
+{$ENDIF}
+end;
+
+{ TTextStream }
+
+constructor TTextFileStream.Create(Filename: IPath; Mode: word);
+begin
+  inherited Create();
+  fMode := Mode;
+  fFilename := Filename;
+  fLineBreak := sLineBreak;
+end;
+
+function TTextFileStream.ReadLine(var Line: UTF8String): boolean;
+begin
+  Line := ReadLine(Result);
+end;
+
+function TTextFileStream.ReadLine(var Line: AnsiString): boolean;
+begin
+  Line := ReadLine(Result);
+end;
+
+procedure TTextFileStream.WriteString(const Str: RawByteString);
+begin
+  WriteBuffer(Str[1], Length(Str));
+end;
+
+procedure TTextFileStream.WriteLine(const Line: RawByteString);
+begin
+  WriteBuffer(Line[1], Length(Line));
+  WriteBuffer(fLineBreak[1], Length(fLineBreak));
+end;
+
+{ TMemTextStream }
+
+constructor TMemTextFileStream.Create(Filename: IPath; Mode: word);
+var
+  FileStream: TBinaryFileStream;
+begin
+  inherited Create(Filename, Mode);
+
+  fStream := TMemoryStream.Create();
+
+  // load data to memory in read mode
+  if ((Mode and 3) in [fmOpenRead, fmOpenReadWrite]) then
+  begin
+    FileStream := TBinaryFileStream.Create(Filename, fmOpenRead);
+    try
+      fStream.LoadFromStream(FileStream);
+    finally
+      FileStream.Free;
+    end;
+  end
+  // check if file exists for write-mode
+  else if ((Mode and 3) = fmOpenWrite) and (not Filename.IsFile) then
+  begin
+    raise EFOpenError.CreateResFmt(@SFOpenError,
+          [FileName.GetAbsolutePath.ToNative]);
+  end;
+end;
+
+destructor TMemTextFileStream.Destroy();
+var
+  FileStream: TBinaryFileStream;
+  SaveMode: word;
+begin
+  // save changes in write mode (= not read-only mode)
+  if ((fMode and 3) <> fmOpenRead) then
+  begin
+    if (fMode = fmCreate) then
+      SaveMode := fmCreate
+    else
+      SaveMode := fmOpenWrite;
+    FileStream := TBinaryFileStream.Create(fFilename, SaveMode);
+    try
+      fStream.SaveToStream(FileStream);
+    finally
+      FileStream.Free;
+    end;
+  end;
+
+  fStream.Free;
+  inherited;
+end;
+
+function TMemTextFileStream.GetSize: int64;
+begin
+  Result := fStream.Size;
+end;
+
+function TMemTextFileStream.Read(var Buffer; Count: longint): longint;
+begin
+  Result := fStream.Read(Buffer, Count);
+end;
+
+function TMemTextFileStream.Write(const Buffer; Count: longint): longint;
+begin
+  Result := fStream.Write(Buffer, Count);
+end;
+
+function TMemTextFileStream.Seek(Offset: longint; Origin: word): longint;
+begin
+  Result := fStream.Seek(Offset, Origin);
+end;
+
+function TMemTextFileStream.Seek(const Offset: int64; Origin: TSeekOrigin): int64;
+begin
+  Result := fStream.Seek(Offset, Origin);
+end;
+
+function TMemTextFileStream.CopyMemString(StartPos: int64; EndPos: int64): RawByteString;
+var
+  LineLength: cardinal;
+  Temp: RawByteString;
+begin
+  LineLength := EndPos - StartPos;
+  if (LineLength > 0) then
+  begin
+    // set string length to line-length (+ zero-terminator)
+    SetLength(Temp, LineLength);
+    StrLCopy(PAnsiChar(Temp),
+             @PAnsiChar(fStream.Memory)[StartPos],
+             LineLength);
+    Result := Temp;
+  end
+  else
+  begin
+    Result := '';
+  end;
+end;
+
+function TMemTextFileStream.ReadString(): RawByteString;
+var
+  TextPtr: PAnsiChar;
+  CurPos, StartPos, FileSize: int64;
+begin
+  TextPtr := PAnsiChar(fStream.Memory);
+  CurPos := Position;
+  FileSize := Size;
+  StartPos := -1;
+
+  while (CurPos < FileSize) do
+  begin
+    // check for whitespace (tab, lf, cr, space)
+    if (TextPtr[CurPos] in [#9, #10, #13, ' ']) then
+    begin
+      // check if we are at the end of a string
+      if (StartPos > -1) then
+        Break;
+    end
+    else if (StartPos = -1) then // start of string found
+    begin
+      StartPos := CurPos;
+    end;
+    Inc(CurPos);
+  end;
+
+  if (StartPos = -1) then
+    Result := ''
+  else
+  begin
+    Result := CopyMemString(StartPos, CurPos);
+    fStream.Position := CurPos;
+  end;
+end;
+
+{*
+ * Implementation of ReadLine(). We need separate versions for UTF8String
+ * and AnsiString as "var" parameter types have to fit exactly.
+ * To avoid a var-parameter here, the internal version the Line parameter is
+ * used as return value.
+ *}
+function TMemTextFileStream.ReadLine(var Success: boolean): RawByteString;
+var
+  TextPtr: PAnsiChar;
+  CurPos, FileSize: int64;
+begin
+  TextPtr := PAnsiChar(fStream.Memory);
+  CurPos := fStream.Position;
+  FileSize := Size;
+
+  // check for EOF
+  if (CurPos >= FileSize) then
+  begin
+    Result := '';
+    Success := false;
+    Exit;
+  end;
+
+  Success := true;
+
+  while (CurPos < FileSize) do
+  begin
+    if (TextPtr[CurPos] in [#10, #13]) then
+    begin
+      // copy text line
+      Result := CopyMemString(fStream.Position, CurPos);
+
+      // handle windows style #13#10 (\r\n) newlines
+      if (TextPtr[CurPos] = #13) and
+         (CurPos+1 < FileSize) and
+         (TextPtr[CurPos+1] = #10) then
+      begin
+        Inc(CurPos);
+      end;
+
+      // update stream pos
+      fStream.Position := CurPos+1;
+
+      Exit;
+    end;
+    Inc(CurPos);
+  end;
+
+  Result := CopyMemString(fStream.Position, CurPos);
+  fStream.Position := FileSize;
+end;
+
+{ TUnicodeMemoryStream }
+
+procedure TUnicodeMemoryStream.LoadFromFile(const FileName: IPath);
+var
+  Stream: TStream;
+begin
+  Stream := TBinaryFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+  try
+    LoadFromStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+procedure TUnicodeMemoryStream.SaveToFile(const FileName: IPath);
+var
+  Stream: TStream;
+begin
+  Stream := TBinaryFileStream.Create(FileName, fmCreate);
+  try
+    SaveToStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+{ TUnicodeMemIniFile }
+
+constructor TUnicodeMemIniFile.Create(const FileName: IPath; UTF8Encoded: boolean);
+var
+  List: TStringList;
+  Stream: TBinaryFileStream;
+  BOMBuf: array[0..2] of AnsiChar;
+begin
+  inherited Create('');
+  FFilename := FileName;
+  FUTF8Encoded := UTF8Encoded;
+
+  if FileName.Exists() then
+  begin
+    List := nil;
+    Stream := nil;
+    try
+      List := TStringList.Create;
+      Stream := TBinaryFileStream.Create(FileName, fmOpenRead);
+      if (Stream.Read(BOMBuf[0], SizeOf(BOMBuf)) = 3) and
+         (CompareMem(PChar(UTF8_BOM), @BomBuf, Length(UTF8_BOM))) then
+      begin
+        // truncate BOM
+        FUTF8Encoded := true;
+      end
+      else
+      begin
+        // rewind file
+        Stream.Seek(0, soBeginning);
+      end;
+      List.LoadFromStream(Stream);
+      SetStrings(List);
+    finally
+      Stream.Free;
+      List.Free;
+    end;
+  end;
+end;
+
+procedure TUnicodeMemIniFile.UpdateFile;
+var
+  List: TStringList;
+  Stream: TBinaryFileStream;
+begin
+  List := nil;
+  Stream := nil;
+  try
+    List := TStringList.Create;
+    GetStrings(List);
+    Stream := TBinaryFileStream.Create(FFileName, fmCreate);
+    if UTF8Encoded then
+      Stream.Write(UTF8_BOM, Length(UTF8_BOM));
+    List.SaveToStream(Stream);
+  finally
+    List.Free;
+    Stream.Free;
+  end;
+end;
+
+
+var
+  PATH_NONE_Singelton: IPath;
+
+function PATH_NONE(): IPath;
+begin
+  Result := PATH_NONE_Singelton;
+end;
+
+initialization
+  {$IFDEF HAVE_REFCNTBUG}
+  GarbageList := TInterfaceList.Create();
+  GarbageList.Capacity := GarbageMaxCount;
+  {$ENDIF}
+  PATH_NONE_Singelton := Path('');
+
+finalization
+  PATH_NONE_Singelton := nil;
+
+end.
diff --git a/songmanagement/src/base/UPathUtils.pas b/songmanagement/src/base/UPathUtils.pas
new file mode 100644
index 00000000..2bfcde42
--- /dev/null
+++ b/songmanagement/src/base/UPathUtils.pas
@@ -0,0 +1,201 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UPathUtils;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  Classes,
+  UPath;
+
+var
+  // Absolute Paths
+  GamePath:         IPath;
+  SoundPath:        IPath;
+  SongPaths:        IInterfaceList;
+  LogPath:          IPath;
+  ThemePath:        IPath;
+  SkinsPath:        IPath;
+  ScreenshotsPath:  IPath;
+  CoverPaths:       IInterfaceList;
+  LanguagesPath:    IPath;
+  PluginPath:       IPath;
+  VisualsPath:      IPath;
+  FontPath:         IPath;
+  ResourcesPath:    IPath;
+  PlaylistPath:     IPath;
+
+function FindPath(out PathResult: IPath; const RequestedPath: IPath; NeedsWritePermission: boolean): boolean;
+procedure InitializePaths;
+procedure AddSongPath(const Path: IPath);
+
+implementation
+
+uses
+  StrUtils,
+  UPlatform,
+  UCommandLine,
+  ULog;
+
+procedure AddSpecialPath(var PathList: IInterfaceList; const Path: IPath);
+var
+  Index: integer;
+  PathAbs, PathTmp: IPath;
+  OldPath, OldPathAbs, OldPathTmp: IPath;
+begin
+  if (PathList = nil) then
+    PathList := TInterfaceList.Create;
+
+  if Path.Equals(PATH_NONE) or not Path.CreateDirectory(true) then
+    Exit;
+
+  PathTmp := Path.GetAbsolutePath();
+  PathAbs := PathTmp.AppendPathDelim();
+
+  // check if path or a part of the path was already added
+  for Index := 0 to PathList.Count-1 do
+  begin
+    OldPath := PathList[Index] as IPath;
+    OldPathTmp := OldPath.GetAbsolutePath();
+    OldPathAbs := OldPathTmp.AppendPathDelim();
+
+    // check if the new directory is a sub-directory of a previously added one.
+    // This is also true, if both paths point to the same directories.
+    if (OldPathAbs.IsChildOf(PathAbs, false) or OldPathAbs.Equals(PathAbs)) then
+    begin
+      // ignore the new path
+      Exit;
+    end;
+
+    // check if a previously added directory is a sub-directory of the new one.
+    if (PathAbs.IsChildOf(OldPathAbs, false)) then
+    begin
+      // replace the old with the new one.
+      PathList[Index] := PathAbs;
+      Exit;
+    end;
+  end;
+
+  PathList.Add(PathAbs);
+end;
+
+procedure AddSongPath(const Path: IPath);
+begin
+  AddSpecialPath(SongPaths, Path);
+end;
+
+procedure AddCoverPath(const Path: IPath);
+begin
+  AddSpecialPath(CoverPaths, Path);
+end;
+
+(**
+ * Initialize a path variable
+ * After setting paths, make sure that paths exist
+ *)
+function FindPath(
+  out PathResult: IPath;
+  const RequestedPath: IPath;
+  NeedsWritePermission: boolean): boolean;
+begin
+  Result := false;
+
+  if (RequestedPath.Equals(PATH_NONE)) then
+    Exit;
+
+  // Make sure the directory exists
+  if (not RequestedPath.CreateDirectory(true)) then
+  begin
+    PathResult := PATH_NONE;
+    Exit;
+  end;
+
+  PathResult := RequestedPath.AppendPathDelim();
+
+  if (NeedsWritePermission) and RequestedPath.IsReadOnly() then
+    Exit;
+
+  Result := true;
+end;
+
+(**
+ * Function sets all absolute paths e.g. song path and makes sure the directorys exist
+ *)
+procedure InitializePaths;
+var
+  SharedPath, UserPath: IPath;
+begin
+  // Log directory (must be writable)
+  if (not FindPath(LogPath, Platform.GetLogPath, true)) then
+  begin
+    Log.FileOutputEnabled := false;
+    Log.LogWarn('Log directory "'+ Platform.GetLogPath.ToNative +'" not available', 'InitializePaths');
+  end;
+
+  SharedPath := Platform.GetGameSharedPath;
+  UserPath := Platform.GetGameUserPath;
+
+  FindPath(SoundPath,     SharedPath.Append('sounds'),    false);
+  FindPath(ThemePath,     SharedPath.Append('themes'),    false);
+  FindPath(SkinsPath,     SharedPath.Append('themes'),    false);
+  FindPath(LanguagesPath, SharedPath.Append('languages'), false);
+  FindPath(PluginPath,    SharedPath.Append('plugins'),   false);
+  FindPath(VisualsPath,   SharedPath.Append('visuals'),   false);
+  FindPath(FontPath,      SharedPath.Append('fonts'),     false);
+  FindPath(ResourcesPath, SharedPath.Append('resources'), false);
+
+  // Playlists are not shared as we need one directory to write too
+  FindPath(PlaylistPath, UserPath.Append('playlists'), true);
+
+  // Screenshot directory (must be writable)
+  if (not FindPath(ScreenshotsPath, UserPath.Append('screenshots'), true)) then
+  begin
+    Log.LogWarn('Screenshot directory "'+ UserPath.ToNative +'" not available', 'InitializePaths');
+  end;
+
+  // Add song paths
+  AddSongPath(Params.SongPath);
+{$IF Defined(DARWIN)}
+  AddSongPath(Platform.GetMusicPath);
+  AddSongPath(UserPath.Append('songs'));
+{$ELSE}
+  AddSongPath(SharedPath.Append('songs'));
+  AddSongPath(UserPath.Append('songs'));
+{$IFEND}
+
+  // Add category cover paths
+  AddCoverPath(SharedPath.Append('covers'));
+  AddCoverPath(UserPath.Append('covers'));
+end;
+
+end.
diff --git a/songmanagement/src/base/UPlatform.pas b/songmanagement/src/base/UPlatform.pas
new file mode 100644
index 00000000..6d884979
--- /dev/null
+++ b/songmanagement/src/base/UPlatform.pas
@@ -0,0 +1,136 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UPlatform;
+
+// Comment by Eddie:
+// This unit defines an interface for platform specific utility functions.
+// The Interface is implemented in separate files for each platform:
+// UPlatformWindows, UPlatformLinux and UPlatformMacOSX.
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  UPath;
+
+type
+  TPlatform = class
+    function GetExecutionDir(): IPath;
+    procedure Init; virtual;
+
+    function TerminateIfAlreadyRunning(var WndTitle: string): boolean; virtual;
+    procedure Halt; virtual;
+
+    function GetLogPath:        IPath; virtual; abstract;
+    function GetMusicPath:      IPath; virtual; abstract;
+    function GetGameSharedPath: IPath; virtual; abstract;
+    function GetGameUserPath:   IPath; virtual; abstract;
+  end;
+
+  function Platform(): TPlatform;
+
+implementation
+
+uses
+  SysUtils,
+  {$IF Defined(MSWINDOWS)}
+  UPlatformWindows,
+  {$ELSEIF Defined(DARWIN)}
+  UPlatformMacOSX,
+  {$ELSEIF Defined(UNIX)}
+  UPlatformLinux,
+  {$IFEND}
+  ULog,
+  UUnicodeUtils,
+  UFilesystem;
+
+
+// I modified it to use the Platform_singleton in this location (in the implementation)
+// so that this variable can NOT be overwritten from anywhere else in the application.
+// the accessor function platform, emulates all previous calls to work the same way.  
+var
+  Platform_singleton: TPlatform;
+
+function Platform: TPlatform;
+begin
+  Result := Platform_singleton;
+end;
+
+(**
+ * Default Init() implementation
+ *)
+procedure TPlatform.Init;
+begin
+end;
+
+(**
+ * Default Halt() implementation
+ *)
+procedure TPlatform.Halt;
+begin
+  // Note: Application.terminate is NOT the same
+  System.Halt;
+end;
+
+{**
+ * Returns the directory of the executable
+ *}
+function TPlatform.GetExecutionDir(): IPath;
+var
+  ExecName, ExecDir: IPath;
+begin
+  ExecName := Path(ParamStr(0));
+  ExecDir := ExecName.GetPath;
+  Result := ExecDir.GetAbsolutePath();
+end;
+
+(**
+ * Default TerminateIfAlreadyRunning() implementation
+ *)
+function TPlatform.TerminateIfAlreadyRunning(var WndTitle: string): boolean;
+begin
+  Result := false;
+end;
+
+initialization
+{$IF Defined(MSWINDOWS)}
+  Platform_singleton := TPlatformWindows.Create;
+{$ELSEIF Defined(DARWIN)}
+  Platform_singleton := TPlatformMacOSX.Create;
+{$ELSEIF Defined(UNIX)}
+  Platform_singleton := TPlatformLinux.Create;
+{$IFEND}
+
+finalization
+  Platform_singleton.Free;
+
+end.
diff --git a/songmanagement/src/base/UPlatformLinux.pas b/songmanagement/src/base/UPlatformLinux.pas
new file mode 100644
index 00000000..693facaa
--- /dev/null
+++ b/songmanagement/src/base/UPlatformLinux.pas
@@ -0,0 +1,149 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UPlatformLinux;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  UPlatform,
+  UConfig,
+  UPath;
+
+type
+  TPlatformLinux = class(TPlatform)
+    private
+      UseLocalDirs: boolean;
+
+      procedure DetectLocalExecution();
+      function GetHomeDir(): IPath;
+    public
+      procedure Init; override;
+      
+      function GetLogPath        : IPath; override;
+      function GetGameSharedPath : IPath; override;
+      function GetGameUserPath   : IPath; override;
+  end;
+
+implementation
+
+uses
+  UCommandLine,
+  BaseUnix,
+  pwd,
+  SysUtils,
+  ULog;
+
+const
+  {$I paths.inc}
+
+procedure TPlatformLinux.Init;
+begin
+  inherited Init();
+  DetectLocalExecution();
+end;
+
+{**
+ * Detects whether the game was executed locally or globally.
+ * - It is local if it was not installed and directly executed from
+ *   within the game folder. In this case resources (themes, language-files)
+ *   reside in the directory of the executable.
+ * - It is global if the game was installed (e.g. to /usr/bin) and
+ *   the resources are in a separate folder (e.g. /usr/share/ultrastardx)
+ *   which name is stored in the INSTALL_DATADIR constant in paths.inc.
+ *
+ * Sets UseLocalDirs to true if the game is executed locally, false otherwise.
+ *}
+procedure TPlatformLinux.DetectLocalExecution();
+var
+  LocalDir, LanguageDir: IPath;
+begin
+  // we just check if the 'languages' folder exists in the
+  // directory of the executable. If so -> local execution.
+  LocalDir := GetExecutionDir();
+  LanguageDir := LocalDir.Append('languages');
+  UseLocalDirs := LanguageDir.IsDirectory;
+end;
+
+function TPlatformLinux.GetLogPath: IPath;
+begin
+  if UseLocalDirs then
+    Result := GetExecutionDir()
+  else
+    Result := GetGameUserPath().Append('logs', pdAppend);
+
+  // create non-existing directories
+  Result.CreateDirectory(true);
+end;
+
+function TPlatformLinux.GetGameSharedPath: IPath;
+begin
+  if UseLocalDirs then
+    Result := GetExecutionDir()
+  else
+    Result := Path(INSTALL_DATADIR, pdAppend);
+end;
+
+function TPlatformLinux.GetGameUserPath: IPath;
+begin
+  if UseLocalDirs then
+    Result := GetExecutionDir()
+  else
+    Result := GetHomeDir().Append('.ultrastardx', pdAppend);
+end;
+
+{**
+ * Returns the user's home directory terminated by a path delimiter
+ *}
+function TPlatformLinux.GetHomeDir(): IPath;
+var
+  PasswdEntry: PPasswd;
+begin
+  Result := PATH_NONE;
+
+  // try to retrieve the info from passwd
+  PasswdEntry := FpGetpwuid(FpGetuid());
+  if (PasswdEntry <> nil) then
+    Result := Path(PasswdEntry.pw_dir);
+  // fallback if passwd does not contain the path
+  if (Result.IsUnset) then
+    Result := Path(GetEnvironmentVariable('HOME'));
+  // add trailing path delimiter (normally '/')
+  if (Result.IsSet) then
+    Result := Result.AppendPathDelim();
+
+  // GetUserDir() is another function that returns a user path.
+  // It uses env-var HOME or a fallback to a temp-dir.
+  //Result := GetUserDir();
+end;
+
+end.
diff --git a/songmanagement/src/base/UPlatformMacOSX.pas b/songmanagement/src/base/UPlatformMacOSX.pas
new file mode 100644
index 00000000..3a3e3f79
--- /dev/null
+++ b/songmanagement/src/base/UPlatformMacOSX.pas
@@ -0,0 +1,302 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UPlatformMacOSX;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  ULog,
+  UPlatform,
+  UFilesystem,
+  UPath;
+
+type
+  {**
+   * @abstract(Provides Mac OS X specific details.)
+   * @lastmod(August 1, 2008)
+   * The UPlatformMacOSX unit takes care of setting paths to resource folders.
+   *
+   * (Note for non-Maccies: "folder" is the Mac name for directory.)
+   *
+   * Note on the resource folders:
+   *  1. Installation of an application on the mac works as follows: Extract and
+   *     copy an application and if you don't like or need the application
+   *     anymore you move the folder to the trash - and you're done.
+   *  2. The use of folders in the user's home directory is against Apple's
+   *     guidelines and strange to an average user.
+   *  3. Even worse is using /usr/local/... since all lowercase folders in / are
+   *     not visible to an average user in the Finder, at least not without some
+   *     "tricks".
+   *
+   * The best way would be to store everything within the application bundle.
+   * However, this requires USDX to offer the handling of the resources. Until
+   * this is implemented, the second best solution is as follows:
+   *
+   * According to Aple guidelines handling of resources and folders should follow
+   * these lines:
+   *
+   * Acceptable places for files are folders named UltraStarDeluxe either in
+   *   /Library/Application Support/
+   * or
+   *   ~/Library/Application Support/
+   *
+   * So
+   * GetGameSharedPath could return
+   *   /Library/Application Support/UltraStarDeluxe/.
+   * GetGameUserPath could return
+   *   ~/Library/Application Support/UltraStarDeluxe/.
+   *
+   * Right now, only $HOME/Library/Application Support/UltraStarDeluxe
+   * is used. So every user needs the complete set of files and folders.
+   * Future versions may also use shared resources in
+   * /Library/Application Support/UltraStarDeluxe. However, this is
+   * not treated yet in the code outside this unit.
+   *
+   * USDX checks, whether GetGameUserPath exists. If not, USDX creates it.
+   * The existence of needed files is then checked and if a file is missing
+   * it is copied to there from within the folder Contents in the Application
+   * bundle, which contains the default files. USDX should not delete files or
+   * folders in Application Support/UltraStarDeluxe automatically or without
+   * user confirmation.
+   *
+   * The log and benchmark files are stored in
+   * $HOME/Library/Log/UltraStar Deluxe/
+   * 
+   * Music should go into ~/Music/UltraStar Deluxe/
+   *
+   * ~/Library/Application Support/UltraStarDeluxe/songs is also used.
+   * The idea is to remove this at some time.
+   *
+   *}
+  TPlatformMacOSX = class(TPlatform)
+    private
+      {**
+       * GetBundlePath returns the path to the application bundle
+       * UltraStarDeluxe.app.
+       *}
+      function GetBundlePath: IPath;
+
+      {**
+       * GetApplicationSupportPath returns the path to
+       * $HOME/Library/Application Support/UltraStarDeluxe.
+       *}
+      function GetApplicationSupportPath: IPath;
+
+      {**
+       * see the description of @link(Init).
+       *}
+      procedure CreateUserFolders();
+
+      {**
+       * GetHomeDir returns the path to $HOME.
+       *}
+      function GetHomeDir: IPath;
+
+    public
+      {**
+       * Init simply calls @link(CreateUserFolders), which in turn scans the
+       * folder UltraStarDeluxe.app/Contents for all files and
+       * folders. $HOME/Library/Application Support/UltraStarDeluxe
+       * is then checked for their presence and missing ones are copied.
+       *}
+      procedure Init; override;
+
+      {**
+       * GetLogPath returns the path for log messages. Currently it is set to
+       * $HOME/Library/Logs/UltraStar Deluxe/.
+       *}
+      function  GetLogPath:        IPath; override;
+
+      {**
+       * GetMusicPath returns the path for music. Currently it is set to
+       * $HOME/Music/UltraStar Deluxe/.
+       *}
+      function  GetMusicPath:      IPath; override;
+
+      {**
+       * GetGameSharedPath returns the path for shared resources. Currently it
+       * is also set to $HOME/Library/Application Support/UltraStarDeluxe.
+       * However it is not used.
+       *}
+      function  GetGameSharedPath: IPath; override;
+
+      {**
+       * GetGameUserPath returns the path for user resources. Currently it is
+       * set to $HOME/Library/Application Support/UltraStarDeluxe.
+       * This is where a user can add themes, ....
+       *}
+      function  GetGameUserPath:   IPath; override;
+  end;
+
+implementation
+
+uses
+  SysUtils;
+
+procedure TPlatformMacOSX.Init;
+begin
+  CreateUserFolders();
+end;
+
+procedure TPlatformMacOSX.CreateUserFolders();
+var
+  RelativePath: IPath;
+  // BaseDir contains the path to the folder, where a search is performed.
+  // It is set to the entries in @link(DirectoryList) one after the other.
+  BaseDir: IPath;
+  // OldBaseDir contains the path to the folder, where the search started.
+  // It is used to return to it, when the search is completed in all folders.
+  OldBaseDir: IPath;
+  Iter:       IFileIterator;
+  FileInfo:   TFileInfo;
+  CurPath:    IPath;
+  // These two lists contain all folder and file names found
+  // within the folder @link(BaseDir).
+  DirectoryList, FileList: IInterfaceList;
+  // DirectoryIsFinished contains the index of the folder in @link(DirectoryList),
+  // which is the last one completely searched. Later folders are still to be
+  // searched for additional files and folders.
+  DirectoryIsFinished: longint;
+  I: longint;
+  // These three are for creating directories, due to possible symlinks
+  CreatedDirectory: boolean;
+  FileAttrs:        integer;
+  DirectoryPath:    IPath;
+  UserPath:         IPath;
+  SrcFile, TgtFile: IPath;
+begin
+  // Get the current folder and save it in OldBaseDir for returning to it, when
+  // finished.
+  OldBaseDir := FileSystem.GetCurrentDir();
+
+  // UltraStarDeluxe.app/Contents contains all the default files and folders.
+  BaseDir := OldBaseDir.Append('UltraStarDeluxe.app/Contents');
+  FileSystem.SetCurrentDir(BaseDir);
+
+  // Right now, only $HOME/Library/Application Support/UltraStarDeluxe is used.
+  UserPath := GetGameUserPath();
+
+  DirectoryIsFinished := 0;
+  // replace with IInterfaceList
+  DirectoryList := TInterfaceList.Create();
+  FileList := TInterfaceList.Create();
+  DirectoryList.Add(Path('.'));
+
+  // create the folder and file lists
+  repeat
+    RelativePath := (DirectoryList[DirectoryIsFinished] as IPath);
+    FileSystem.SetCurrentDir(BaseDir.Append(RelativePath));
+    Iter := FileSystem.FileFind(Path('*'), faAnyFile);
+    while (Iter.HasNext) do    
+    begin
+      FileInfo := Iter.Next;
+      CurPath := FileInfo.Name;
+      if CurPath.IsDirectory() then
+      begin
+        if (not CurPath.Equals('.')) and 
+	   (not CurPath.Equals('..')) and 
+	   (not CurPath.Equals('MacOS')) then
+          DirectoryList.Add(RelativePath.Append(CurPath));
+      end
+      else
+        Filelist.Add(RelativePath.Append(CurPath));
+    end;
+    Inc(DirectoryIsFinished);
+  until (DirectoryIsFinished = DirectoryList.Count);
+
+  // create missing folders
+  UserPath.CreateDirectory(true); // should not be necessary since (UserPathName+'/.') is created.
+  for I := 0 to DirectoryList.Count-1 do
+  begin
+    CurPath          := DirectoryList[I] as IPath;
+    DirectoryPath    := UserPath.Append(CurPath);
+    CreatedDirectory := DirectoryPath.CreateDirectory();
+    FileAttrs        := DirectoryPath.GetAttr();
+    // Maybe analyse the target of the link with FpReadlink().
+    // Let's assume the symlink is pointing to an existing directory.
+    if (not CreatedDirectory) and (FileAttrs and faSymLink > 0) then
+      Log.LogError('Failed to create the folder "'+ DirectoryPath.ToNative +'"',
+                   'TPlatformMacOSX.CreateUserFolders');
+  end;
+
+  // copy missing files
+  for I := 0 to Filelist.Count-1 do
+  begin
+    CurPath := Filelist[I] as IPath;
+    SrcFile := BaseDir.Append(CurPath);
+    TgtFile := UserPath.Append(CurPath);
+    SrcFile.CopyFile(TgtFile, true);
+  end;
+
+  // go back to the initial folder
+  FileSystem.SetCurrentDir(OldBaseDir);
+end;
+
+function TPlatformMacOSX.GetBundlePath: IPath;
+begin
+  // Mac applications are packaged in folders.
+  // Cutting the last two folders yields the application folder.
+  Result := GetExecutionDir().GetParent().GetParent();
+end;
+
+function TPlatformMacOSX.GetHomeDir: IPath;
+begin
+  Result := Path(GetEnvironmentVariable('HOME'));
+end;
+
+function TPlatformMacOSX.GetApplicationSupportPath: IPath;
+begin
+  Result := GetHomeDir.Append('Library/Application Support/UltraStarDeluxe', pdAppend);
+end;
+
+function TPlatformMacOSX.GetLogPath: IPath;
+begin
+  Result := GetHomeDir.Append('Library/Logs/UltraStar Deluxe', pdAppend);
+end;
+
+function TPlatformMacOSX.GetMusicPath: IPath;
+begin
+  Result := GetHomeDir.Append('Music/UltraStar Deluxe', pdAppend);
+end;
+
+function TPlatformMacOSX.GetGameSharedPath: IPath;
+begin
+  Result := GetApplicationSupportPath;
+end;
+
+function TPlatformMacOSX.GetGameUserPath: IPath;
+begin
+  Result := GetApplicationSupportPath;
+end;
+
+end.
diff --git a/songmanagement/src/base/UPlatformWindows.pas b/songmanagement/src/base/UPlatformWindows.pas
new file mode 100644
index 00000000..91d3cce6
--- /dev/null
+++ b/songmanagement/src/base/UPlatformWindows.pas
@@ -0,0 +1,209 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UPlatformWindows;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+// turn off messages for platform specific symbols
+{$WARN SYMBOL_PLATFORM OFF}
+
+uses
+  Classes,
+  UPlatform,
+  UPath;
+
+type
+  TPlatformWindows = class(TPlatform)
+    private
+      UseLocalDirs: boolean;
+      
+      function GetSpecialPath(CSIDL: integer): IPath;
+      procedure DetectLocalExecution();
+    public
+      procedure Init; override;
+      function TerminateIfAlreadyRunning(var WndTitle: String): Boolean; override;
+
+      function GetLogPath: IPath; override;
+      function GetGameSharedPath: IPath; override;
+      function GetGameUserPath: IPath; override;
+  end;
+
+implementation
+
+uses
+  SysUtils,
+  ShlObj,
+  Windows,
+  UConfig;
+
+procedure TPlatformWindows.Init;
+begin
+  inherited Init();
+  DetectLocalExecution();
+end;
+
+//------------------------------
+//Start more than One Time Prevention
+//------------------------------
+function TPlatformWindows.TerminateIfAlreadyRunning(var WndTitle: String): Boolean;
+var
+  hWnd: THandle;
+  I: Integer;
+begin
+    Result := false;
+    hWnd:= FindWindow(nil, PChar(WndTitle));
+    //Programm already started
+    if (hWnd <> 0) then
+    begin
+      I := Messagebox(0, PChar('Another Instance of Ultrastar is already running. Continue ?'), PChar(WndTitle), MB_ICONWARNING or MB_YESNO);
+      if (I = IDYes) then
+      begin
+        I := 1;
+        repeat
+          Inc(I);
+          hWnd := FindWindow(nil, PChar(WndTitle + ' Instance ' + InttoStr(I)));
+        until (hWnd = 0);
+        WndTitle := WndTitle + ' Instance ' + InttoStr(I);
+      end
+      else
+        Result := true;
+    end;
+end;
+
+(**
+ * Returns the path of a special folder.
+ *
+ * Some Folder IDs:
+ * CSIDL_APPDATA       (e.g. C:\Documents and Settings\username\Application Data)
+ * CSIDL_LOCAL_APPDATA (e.g. C:\Documents and Settings\username\Local Settings\Application Data)
+ * CSIDL_PROFILE       (e.g. C:\Documents and Settings\username)
+ * CSIDL_PERSONAL      (e.g. C:\Documents and Settings\username\My Documents)
+ * CSIDL_MYMUSIC       (e.g. C:\Documents and Settings\username\My Documents\My Music)
+ *)
+function TPlatformWindows.GetSpecialPath(CSIDL: integer): IPath;
+var
+  Buffer: array [0..MAX_PATH-1] of WideChar;
+begin
+  if (SHGetSpecialFolderPathW(0, @Buffer, CSIDL, false)) then
+    Result := Path(Buffer)
+  else
+    Result := PATH_NONE;
+end;
+
+{**
+ * Detects whether the was executed locally or globally.
+ * - Local mode:
+ *   - Condition:
+ *     - config.ini is writable or creatable in the directory of the executable.
+ *   - Examples:
+ *     - The USDX zip-archive has been unpacked to a directory with write.
+ *       permissions
+ *     - XP: USDX was installed to %ProgramFiles% and the user is an admin.
+ *     - USDX is started from an external HD- or flash-drive
+ *   - Behavior:
+ *     Config files like config.ini or score db reside in the directory of the
+ *     executable. This is useful to enable windows users to have a portable
+ *     installation e.g. on an external hdd.
+ *     This is also the default behaviour of usdx prior to version 1.1
+ * - Global mode:
+ *   - Condition:
+ *     - config.ini is not writable.
+ *   - Examples:
+ *     - Vista/7: USDX was installed to %ProgramFiles%.
+ *     - XP: USDX was installed to %ProgramFiles% and the user is not an admin.
+ *     - USDX is started from CD
+ *   - Behavior:
+ *     - The config files are in a separate folder (e.g. %APPDATA%\ultrastardx)
+ *
+ * On windows, resources (themes, language-files)
+ * reside in the directory of the executable in any case
+ *
+ * Sets UseLocalDirs to true if the game is executed locally, false otherwise.
+ *}
+procedure TPlatformWindows.DetectLocalExecution();
+var
+  LocalDir, ConfigIni: IPath;
+  Handle: TFileHandle;
+begin
+  LocalDir := GetExecutionDir();
+  ConfigIni := LocalDir.Append('config.ini');
+
+  // check if config.ini is writable or creatable, if so use local dirs
+  UseLocalDirs := false;
+  if (ConfigIni.Exists()) then
+  begin
+    // do not use a read-only config file
+    if (not ConfigIni.IsReadOnly()) then
+    begin
+      // Just open the file in read-write mode to be sure that we have access
+      // rights for it.
+      // Note: Do not use IsReadOnly() as it does not check file privileges, so
+      // a non-read-only file might not be writable for us.
+      Handle := ConfigIni.Open(fmOpenReadWrite);
+      if (Handle <> -1) then
+      begin
+        FileClose(Handle);
+        UseLocalDirs := true;
+      end;
+    end;
+  end
+  else // config.ini does not exist
+  begin
+    // try to create config.ini
+    Handle := ConfigIni.CreateFile();
+    if (Handle <> -1) then
+    begin
+      FileClose(Handle);
+      UseLocalDirs := true;
+    end;
+  end;
+end;
+
+function TPlatformWindows.GetLogPath: IPath;
+begin
+  Result := GetGameUserPath;
+end;
+
+function TPlatformWindows.GetGameSharedPath: IPath;
+begin
+  Result := GetExecutionDir();
+end;
+
+function TPlatformWindows.GetGameUserPath: IPath;
+begin
+  if UseLocalDirs then
+    Result := GetExecutionDir()
+  else
+    Result := GetSpecialPath(CSIDL_APPDATA).Append('ultrastardx', pdAppend);
+end;
+
+end.
diff --git a/songmanagement/src/base/UPlaylist.pas b/songmanagement/src/base/UPlaylist.pas
new file mode 100644
index 00000000..f12e06cf
--- /dev/null
+++ b/songmanagement/src/base/UPlaylist.pas
@@ -0,0 +1,520 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UPlaylist;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  USong,
+  UPath,
+  UPathUtils;
+
+type
+  TPlaylistItem = record
+    Artist: UTF8String;
+    Title:  UTF8String;
+    SongID: Integer;
+  end;
+
+  APlaylistItem = array of TPlaylistItem;
+
+  TPlaylist = record
+    Name:     UTF8String;
+    Filename: IPath;
+    Items:    APlaylistItem;
+  end;
+
+  APlaylist = array of TPlaylist;
+
+  //----------
+  //TPlaylistManager - Class for Managing Playlists (Loading, Displaying, Saving)
+  //----------
+  TPlaylistManager = class
+    private
+
+    public
+      Mode:         TSingMode;     //Current Playlist Mode for SongScreen
+      CurPlayList:  Cardinal;
+      CurItem:      Cardinal;
+
+      Playlists:    APlaylist;
+
+      constructor Create;
+      procedure   LoadPlayLists;
+      function    LoadPlayList(Index: Cardinal; const Filename: IPath): Boolean;
+      procedure   SavePlayList(Index: Cardinal);
+
+      procedure   SetPlayList(Index: Cardinal);
+
+      function    AddPlaylist(const Name: UTF8String): Cardinal;
+      procedure   DelPlaylist(const Index: Cardinal);
+
+      procedure   AddItem(const SongID: Cardinal; const iPlaylist: Integer = -1);
+      procedure   DelItem(const iItem: Cardinal; const iPlaylist: Integer = -1);
+
+      procedure   GetNames(var PLNames: array of UTF8String);
+      function    GetIndexbySongID(const SongID: Cardinal; const iPlaylist: Integer = -1): Integer;
+    end;
+
+    {Modes:
+      0: Standard Mode
+      1: Category Mode
+      2: PlayList Mode}
+
+  var
+    PlayListMan:  TPlaylistManager;
+
+
+implementation
+
+uses
+  SysUtils,
+  USongs,
+  ULog,
+  UMain,
+  UFilesystem,
+  UGraphic,
+  UThemes,
+  UUnicodeUtils;
+
+//----------
+//Create - Construct Class - Dummy for now
+//----------
+constructor TPlayListManager.Create;
+begin
+  inherited;
+  LoadPlayLists;
+end;
+
+//----------
+//LoadPlayLists - Load list of Playlists from PlayList Folder
+//----------
+Procedure   TPlayListManager.LoadPlayLists;
+var
+  Len:  Integer;
+  PlayListBuffer: TPlayList;
+  Iter: IFileIterator;
+  FileInfo: TFileInfo;
+begin
+  SetLength(Playlists, 0);
+
+  Iter := FileSystem.FileFind(PlayListPath.Append('*.upl'), 0);
+  while (Iter.HasNext) do
+  begin
+    Len := Length(Playlists);
+    SetLength(Playlists, Len + 1);
+
+    FileInfo := Iter.Next;
+
+    if not LoadPlayList(Len, FileInfo.Name) then
+      SetLength(Playlists, Len)
+    else
+    begin
+      // Sort the Playlists - Insertion Sort
+      PlayListBuffer := Playlists[Len];
+      Dec(Len);
+      while (Len >= 0) AND (CompareText(Playlists[Len].Name, PlayListBuffer.Name) >= 0) do
+      begin
+          Playlists[Len+1] := Playlists[Len];
+          Dec(Len);
+      end;
+      Playlists[Len+1] := PlayListBuffer;
+    end;
+  end;
+end;
+
+//----------
+//LoadPlayList - Load a Playlist in the Array
+//----------
+function TPlayListManager.LoadPlayList(Index: Cardinal; const Filename: IPath): Boolean;
+
+  function FindSong(Artist, Title: UTF8String): Integer;
+  var I: Integer;
+  begin
+    Result := -1;
+
+    For I := low(CatSongs.Song) to high(CatSongs.Song) do
+    begin
+      if (CatSongs.Song[I].Title = Title) and (CatSongs.Song[I].Artist = Artist) then
+      begin
+        Result := I;
+        Break;
+      end;
+    end;
+  end;
+
+var
+  TextStream: TTextFileStream;
+  Line: UTF8String;
+  PosDelimiter: Integer;
+  SongID: Integer;
+  Len: Integer;
+  FilenameAbs: IPath;
+begin
+  //Load File
+  try
+    FilenameAbs := PlaylistPath.Append(Filename);
+    TextStream := TMemTextFileStream.Create(FilenameAbs, fmOpenRead);
+  except
+    begin
+      Log.LogError('Could not load Playlist: ' + FilenameAbs.ToNative);
+      Result := False;
+      Exit;
+    end;
+  end;
+  Result := True;
+
+  //Set Filename
+  Playlists[Index].Filename := Filename;
+  Playlists[Index].Name := '';
+
+  //Read Until End of File
+  while TextStream.ReadLine(Line) do
+  begin
+    if (Length(Line) > 0) then
+    begin
+      PosDelimiter := UTF8Pos(':', Line);
+      if (PosDelimiter <> 0) then
+      begin
+        //Comment or Name String
+        if (Line[1] = '#') then
+        begin
+          //Found Name Value
+          if (Uppercase(Trim(copy(Line, 2, PosDelimiter - 2))) = 'NAME') then
+            PlayLists[Index].Name := Trim(copy(Line, PosDelimiter + 1,Length(Line) - PosDelimiter))
+            
+        end
+        //Song Entry
+        else
+        begin
+          SongID := FindSong(Trim(copy(Line, 1, PosDelimiter - 1)), Trim(copy(Line, PosDelimiter + 1, Length(Line) - PosDelimiter)));
+          if (SongID <> -1) then
+          begin
+            Len := Length(PlayLists[Index].Items);
+            SetLength(PlayLists[Index].Items, Len + 1);
+
+            PlayLists[Index].Items[Len].SongID := SongID;
+
+            PlayLists[Index].Items[Len].Artist := Trim(copy(Line, 1, PosDelimiter - 1));
+            PlayLists[Index].Items[Len].Title  := Trim(copy(Line, PosDelimiter + 1, Length(Line) - PosDelimiter));
+          end
+          else Log.LogError('Could not find Song in Playlist: ' + PlayLists[Index].Filename.ToNative + ', ' + Line);
+        end;
+      end;
+    end;
+  end;
+
+  //If no special name is given, use Filename
+  if PlayLists[Index].Name = '' then
+  begin
+    PlayLists[Index].Name := FileName.SetExtension('').ToUTF8;
+  end;
+
+  //Finish (Close File)
+  TextStream.Free;
+end;
+
+{**
+ * Saves the specified Playlist
+ *}
+procedure   TPlayListManager.SavePlayList(Index: Cardinal);
+var
+  TextStream: TTextFileStream;
+  PlaylistFile: IPath;
+  I: Integer;
+begin
+  PlaylistFile := PlaylistPath.Append(Playlists[Index].Filename);
+
+  // cannot update read-only file
+  if PlaylistFile.IsFile() and PlaylistFile.IsReadOnly() then
+    Exit;
+
+  // open file for rewriting
+  TextStream := TMemTextFileStream.Create(PlaylistFile, fmCreate);
+  try
+    // Write version (not nessecary but helpful)
+    TextStream.WriteLine('######################################');
+    TextStream.WriteLine('#Ultrastar Deluxe Playlist Format v1.0');
+    TextStream.WriteLine(Format('#Playlist %s with %d Songs.',
+                         [ Playlists[Index].Name, Length(Playlists[Index].Items) ]));
+    TextStream.WriteLine('######################################');
+
+    // Write name information
+    TextStream.WriteLine('#Name: ' + Playlists[Index].Name);
+
+    // Write song information
+    TextStream.WriteLine('#Songs:');
+
+    for I := 0 to high(Playlists[Index].Items) do
+    begin
+      TextStream.WriteLine(Playlists[Index].Items[I].Artist + ' : ' + Playlists[Index].Items[I].Title);
+    end;
+  except
+    Log.LogError('Could not write Playlistfile "' + Playlists[Index].Name + '"');
+  end;
+  TextStream.Free;
+end;
+
+{**
+ * Display a Playlist in CatSongs
+ *}
+procedure TPlayListManager.SetPlayList(Index: Cardinal);
+var
+  I: Integer;
+begin
+  if (Int(Index) > High(PlayLists)) then
+    exit;
+
+  //Hide all Songs
+  for I := 0 to high(CatSongs.Song) do
+     CatSongs.Song[I].Visible := False;
+
+  //Show Songs in PL
+  for I := 0 to high(PlayLists[Index].Items) do
+  begin
+    CatSongs.Song[PlayLists[Index].Items[I].SongID].Visible := True;
+  end;
+
+  //Set CatSongsMode + Playlist Mode
+  CatSongs.CatNumShow := -3;
+  Mode := smPlayListRandom;
+
+  //Set CurPlaylist
+  CurPlaylist := Index;
+
+  //Show Cat in Topleft:
+  ScreenSong.ShowCatTLCustom(Format(Theme.Playlist.CatText,[Playlists[Index].Name]));
+
+  //Fix SongSelection
+  ScreenSong.Interaction := 0;
+  ScreenSong.SelectNext;
+  ScreenSong.FixSelected;
+
+  //Play correct Music
+  ScreenSong.ChangeMusic;
+end;
+
+//----------
+//AddPlaylist - Adds a Playlist and Returns the Index
+//----------
+function TPlayListManager.AddPlaylist(const Name: UTF8String): cardinal;
+var
+  I: Integer;
+  PlaylistFile: IPath;
+begin
+  Result := Length(Playlists);
+  SetLength(Playlists, Result + 1);
+  
+  // Sort the Playlists - Insertion Sort
+  while (Result > 0) and (CompareText(Playlists[Result - 1].Name, Name) >= 0) do
+  begin
+    Dec(Result);
+    Playlists[Result+1] := Playlists[Result];
+  end;
+  Playlists[Result].Name := Name;
+
+  // clear playlist items
+  SetLength(Playlists[Result].Items, 0);
+
+  I := 1;
+  PlaylistFile := PlaylistPath.Append(Name + '.upl');
+  while (PlaylistFile.Exists) do
+  begin
+    Inc(I);
+    PlaylistFile := PlaylistPath.Append(Name + InttoStr(I) + '.upl');
+  end;
+  Playlists[Result].Filename := PlaylistFile.GetName;
+
+  //Save new Playlist
+  SavePlayList(Result);
+end;
+
+//----------
+//DelPlaylist - Deletes a Playlist
+//----------
+procedure   TPlayListManager.DelPlaylist(const Index: Cardinal);
+var
+  I: Integer;
+  Filename: IPath;
+begin
+  if Int(Index) > High(Playlists) then
+    Exit;
+
+  Filename := PlaylistPath.Append(Playlists[Index].Filename);
+
+  //If not FileExists or File is not Writeable then exit
+  if (not Filename.IsFile()) or (Filename.IsReadOnly()) then
+    Exit;
+
+
+  //Delete Playlist from FileSystem
+  if not Filename.DeleteFile() then
+    Exit;
+
+  //Delete Playlist from Array
+  //move all PLs to the Hole
+  for I := Index to High(Playlists)-1 do
+    PlayLists[I] := PlayLists[I+1];
+
+  //Delete last Playlist
+  SetLength (Playlists, High(Playlists));
+
+  //If Playlist is Displayed atm
+  //-> Display Songs
+  if (CatSongs.CatNumShow = -3) and (Index = CurPlaylist) then
+  begin
+    ScreenSong.UnLoadDetailedCover;
+    ScreenSong.HideCatTL;
+    CatSongs.SetFilter('', fltAll);
+    ScreenSong.Interaction := 0;
+    ScreenSong.FixSelected;
+    ScreenSong.ChangeMusic;
+  end;
+end;
+
+//----------
+//AddItem - Adds an Item to a specific Playlist
+//----------
+Procedure   TPlayListManager.AddItem(const SongID: Cardinal; const iPlaylist: Integer);
+var
+  P: Cardinal;
+  Len: Cardinal;
+begin
+  if iPlaylist = -1 then
+    P := CurPlaylist
+  else if (iPlaylist >= 0) AND (iPlaylist <= high(Playlists)) then
+    P := iPlaylist
+  else
+    exit;
+
+  if (Int(SongID) <= High(CatSongs.Song)) AND (NOT CatSongs.Song[SongID].Main) then
+  begin
+    Len := Length(Playlists[P].Items);
+    SetLength(Playlists[P].Items, Len + 1);
+
+    Playlists[P].Items[Len].SongID  := SongID;
+    Playlists[P].Items[Len].Title   := CatSongs.Song[SongID].Title;
+    Playlists[P].Items[Len].Artist  := CatSongs.Song[SongID].Artist;
+
+    //Save Changes
+    SavePlayList(P);
+
+    //Correct Display when Editing current Playlist
+    if (CatSongs.CatNumShow = -3) and (P = CurPlaylist) then
+      SetPlaylist(P);
+  end;
+end;
+
+//----------
+//DelItem - Deletes an Item from a specific Playlist
+//----------
+Procedure   TPlayListManager.DelItem(const iItem: Cardinal; const iPlaylist: Integer);
+var
+  I: Integer;
+  P: Cardinal;
+begin
+  if iPlaylist = -1 then
+    P := CurPlaylist
+  else if (iPlaylist >= 0) AND (iPlaylist <= high(Playlists)) then
+    P := iPlaylist
+  else
+    exit;
+
+  if (Int(iItem) <= high(Playlists[P].Items)) then
+  begin
+    //Move all entrys behind deleted one to Front
+    For I := iItem to High(Playlists[P].Items) - 1 do
+      Playlists[P].Items[I] := Playlists[P].Items[I + 1];
+
+    //Delete Last Entry
+    SetLength(PlayLists[P].Items, Length(PlayLists[P].Items) - 1);
+
+    //Save Changes
+    SavePlayList(P);
+  end;
+
+  //Delete Playlist if Last Song is deleted
+  if (Length(PlayLists[P].Items) = 0) then
+  begin
+    DelPlaylist(P);
+  end
+  //Correct Display when Editing current Playlist
+  else if (CatSongs.CatNumShow = -3) and (P = CurPlaylist) then
+    SetPlaylist(P);
+end;
+
+//----------
+//GetNames - Writes Playlist Names in a Array
+//----------
+procedure TPlayListManager.GetNames(var PLNames: array of UTF8String);
+var
+  I: Integer;
+  Len: Integer;
+begin
+  Len := High(Playlists);
+  
+  if (Length(PLNames) <> Len + 1) then
+    exit;
+
+  For I := 0 to Len do
+    PLNames[I] := Playlists[I].Name;
+end;
+
+//----------
+//GetIndexbySongID - Returns Index in the specified Playlist of the given Song
+//----------
+Function    TPlayListManager.GetIndexbySongID(const SongID: Cardinal; const iPlaylist: Integer): Integer;
+var
+  P: Integer;
+  I: Integer;
+begin
+  Result := -1;
+
+  if iPlaylist = -1 then
+    P := CurPlaylist
+  else if (iPlaylist >= 0) AND (iPlaylist <= high(Playlists)) then
+    P := iPlaylist
+  else
+    exit;
+
+  For I := 0 to high(Playlists[P].Items) do
+  begin
+    if (Playlists[P].Items[I].SongID = Int(SongID)) then
+    begin
+      Result := I;
+      Break;
+    end;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/base/URecord.pas b/songmanagement/src/base/URecord.pas
new file mode 100644
index 00000000..5cddcc77
--- /dev/null
+++ b/songmanagement/src/base/URecord.pas
@@ -0,0 +1,904 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit URecord;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  Math,
+  sdl,
+  SysUtils,
+  UCommon,
+  UMusic,
+  UIni;
+
+const
+  BaseToneFreq = 65.4064; // lowest (half-)tone to analyze (C2 = 65.4064 Hz)
+  NumHalftones = 36;      // C2-B4 (for Whitney and my high voice)
+
+type
+  TCaptureBuffer = class
+    private
+      VoiceStream: TAudioVoiceStream; // stream for voice passthrough
+      AnalysisBufferLock: PSDL_Mutex;
+
+      function GetToneString: string; // converts a tone to its string represenatation;
+
+      procedure BoostBuffer(Buffer: PByteArray; Size: integer);
+      procedure ProcessNewBuffer(Buffer: PByteArray; BufferSize: integer);
+
+      // we call it to analyze sound by checking Autocorrelation
+      procedure AnalyzeByAutocorrelation;
+      // use this to check one frequency by Autocorrelation
+      function AnalyzeAutocorrelationFreq(Freq: real): real;
+    public
+      AnalysisBuffer:  array[0..4095] of smallint; // newest 4096 samples
+      AnalysisBufferSize: integer; // number of samples of BufferArray to analyze
+
+      LogBuffer:   TMemoryStream;              // full buffer
+
+      AudioFormat: TAudioFormatInfo;
+
+      // pitch detection
+      // TODO: remove ToneValid, set Tone/ToneAbs=-1 if invalid instead
+      ToneValid:    boolean;    // true if Tone contains a valid value (otherwise it contains noise)
+      Tone:         integer;    // tone relative to one octave (e.g. C2=C3=C4). Range: 0-11
+      ToneAbs:      integer;    // absolute (full range) tone (e.g. C2<>C3). Range: 0..NumHalftones-1
+
+      // methods
+      constructor Create;
+      destructor Destroy; override;
+
+      procedure Clear;
+
+      // use to analyze sound from buffers to get new pitch
+      procedure AnalyzeBuffer;
+      procedure LockAnalysisBuffer();   {$IFDEF HasInline}inline;{$ENDIF}
+      procedure UnlockAnalysisBuffer(); {$IFDEF HasInline}inline;{$ENDIF}
+
+      function MaxSampleVolume: single;
+      property ToneString: string READ GetToneString;
+  end;
+
+const
+  DEFAULT_SOURCE_NAME = '[Default]';
+
+type
+  TAudioInputSource = record
+    Name: UTF8String;
+  end;
+
+  // soundcard input-devices information
+  TAudioInputDevice = class
+    public
+      CfgIndex:      integer;   // index of this device in Ini.InputDeviceConfig
+      Name:          UTF8String;    // soundcard name
+      Source:        array of TAudioInputSource; // soundcard input-sources
+      SourceRestore: integer;  // source-index that will be selected after capturing (-1: not detected)
+      MicSource:     integer;  // source-index of mic (-1: none detected)
+
+      AudioFormat:     TAudioFormatInfo; // capture format info (e.g. 44.1kHz SInt16 stereo)
+      CaptureChannel:  array of TCaptureBuffer; // sound-buffer references used for mono or stereo channel's capture data
+
+      destructor Destroy; override;
+
+      procedure LinkCaptureBuffer(ChannelIndex: integer; Sound: TCaptureBuffer);
+
+      // TODO: add Open/Close functions so Start/Stop becomes faster
+      //function Open():    boolean; virtual; abstract;
+      //function Close():   boolean; virtual; abstract;
+      function Start():   boolean; virtual; abstract;
+      function Stop():    boolean; virtual; abstract;
+
+      function GetVolume(): single;        virtual; abstract;
+      procedure SetVolume(Volume: single); virtual; abstract;
+  end;
+
+  TBooleanDynArray = array of boolean;
+
+  TAudioInputProcessor = class
+    public
+      Sound:  array of TCaptureBuffer; // sound-buffers for every player
+      DeviceList: array of TAudioInputDevice;
+
+      constructor Create;
+      destructor Destroy; override;
+
+      procedure UpdateInputDeviceConfig;
+
+      {**
+       * Validates the mic settings.
+       * If a player was assigned to multiple mics a popup will be displayed
+       * with the ID of the player.
+       * The return value is the player number of the first player that is not
+       * configured correctly or 0 if all players are correct.
+       *}
+      function ValidateSettings: integer;
+
+      {**
+       * Checks if players 1 to PlayerCount are configured correctly.
+       * A player is configured if a device's channel is assigned to him.
+       * For each player (up to PlayerCount) the state will be in PlayerState.
+       * If a player's state is true the player is configured, otherwise not.
+       * The return value is the player number of the first player that is not
+       * configured correctly or 0 if all players are correct.
+       * The PlayerState array is zero based (index 0 for player 1).
+       *}
+      function CheckPlayersConfig(PlayerCount: cardinal;
+          var PlayerState: TBooleanDynArray): integer; overload;
+
+      {**
+       * Same as the array version but it does not output a state for each player.
+       *}
+      function CheckPlayersConfig(PlayerCount: cardinal): integer; overload;
+
+      {**
+       * Handle microphone input
+       *}
+      procedure HandleMicrophoneData(Buffer: PByteArray; Size: integer;
+                                     InputDevice: TAudioInputDevice);
+  end;
+
+  TAudioInputBase = class( TInterfacedObject, IAudioInput )
+    private
+      Started: boolean;
+    protected
+      function UnifyDeviceName(const name: UTF8String; deviceIndex: integer): UTF8String;
+    public
+      function GetName: String;           virtual; abstract;
+      function InitializeRecord: boolean; virtual; abstract;
+      function FinalizeRecord: boolean;   virtual;
+
+      procedure CaptureStart;
+      procedure CaptureStop;
+  end;
+
+  TSmallIntArray = array [0..(MaxInt div SizeOf(SmallInt))-1] of SmallInt;
+  PSmallIntArray = ^TSmallIntArray;
+
+  function AudioInputProcessor(): TAudioInputProcessor;
+
+implementation
+
+uses
+  ULog,
+  UNote;
+
+var
+  singleton_AudioInputProcessor : TAudioInputProcessor = nil;
+
+{ Global }
+
+function AudioInputProcessor(): TAudioInputProcessor;
+begin
+  if singleton_AudioInputProcessor = nil then
+    singleton_AudioInputProcessor := TAudioInputProcessor.create();
+
+  result := singleton_AudioInputProcessor;
+end;
+
+{ TAudioInputDevice }
+
+destructor TAudioInputDevice.Destroy;
+begin
+  Stop();
+  Source := nil;
+  CaptureChannel := nil;
+  FreeAndNil(AudioFormat);
+  inherited Destroy;
+end;
+
+procedure TAudioInputDevice.LinkCaptureBuffer(ChannelIndex: integer; Sound: TCaptureBuffer);
+var
+  DeviceCfg: PInputDeviceConfig;
+  OldSound: TCaptureBuffer;
+begin
+  // check bounds
+  if ((ChannelIndex < 0) or (ChannelIndex > High(CaptureChannel))) then
+    Exit;
+
+  // reset previously assigned (old) capture-buffer
+  OldSound := CaptureChannel[ChannelIndex];
+  if (OldSound <> nil) then
+  begin
+    // close voice stream
+    FreeAndNil(OldSound.VoiceStream);
+    // free old audio-format info
+    FreeAndNil(OldSound.AudioFormat);
+  end;
+
+  // set audio-format of new capture-buffer
+  if (Sound <> nil) then
+  begin
+    // copy the input-device audio-format ...
+    Sound.AudioFormat := AudioFormat.Copy;
+    // and adjust it because capture buffers are always mono
+    Sound.AudioFormat.Channels := 1;
+    DeviceCfg := @Ini.InputDeviceConfig[CfgIndex];
+
+    if (Ini.VoicePassthrough = 1) then
+    begin
+      // TODO: map odd players to the left and even players to the right speaker
+      Sound.VoiceStream := AudioPlayback.CreateVoiceStream(CHANNELMAP_FRONT, AudioFormat);
+    end;
+  end;
+
+  // replace old with new buffer (Note: Sound might be nil)
+  CaptureChannel[ChannelIndex] := Sound;
+end;
+
+{ TSound }
+
+constructor TCaptureBuffer.Create;
+begin
+  inherited;
+  LogBuffer := TMemoryStream.Create;
+  AnalysisBufferLock := SDL_CreateMutex();
+  AnalysisBufferSize := Length(AnalysisBuffer);
+end;
+
+destructor TCaptureBuffer.Destroy;
+begin
+  FreeAndNil(LogBuffer);
+  FreeAndNil(VoiceStream);
+  FreeAndNil(AudioFormat);
+  SDL_DestroyMutex(AnalysisBufferLock);
+  inherited;
+end;
+
+procedure TCaptureBuffer.LockAnalysisBuffer();
+begin
+  SDL_mutexP(AnalysisBufferLock);
+end;
+
+procedure TCaptureBuffer.UnlockAnalysisBuffer();
+begin
+  SDL_mutexV(AnalysisBufferLock);
+end;
+
+procedure TCaptureBuffer.Clear;
+begin
+  if assigned(LogBuffer) then
+    LogBuffer.Clear;
+  LockAnalysisBuffer();
+  FillChar(AnalysisBuffer[0], Length(AnalysisBuffer) * SizeOf(SmallInt), 0);
+  UnlockAnalysisBuffer();
+end;
+
+procedure TCaptureBuffer.ProcessNewBuffer(Buffer: PByteArray; BufferSize: integer);
+var
+  BufferOffset: integer;
+  SampleCount:  integer;
+  i:            integer;
+begin
+  // apply software boost
+  BoostBuffer(Buffer, BufferSize);
+
+  // voice passthrough (send data to playback-device)
+  if (assigned(VoiceStream)) then
+    VoiceStream.WriteData(Buffer, BufferSize);
+
+  // we assume that samples are in S16Int format
+  // TODO: support float too
+  if (AudioFormat.Format <> asfS16) then
+    Exit;
+
+  // process BufferArray
+  BufferOffset := 0;
+
+  SampleCount := BufferSize div SizeOf(SmallInt);
+
+  // check if we have more new samples than we can store
+  if (SampleCount > Length(AnalysisBuffer)) then
+  begin
+    // discard the oldest of the new samples
+    BufferOffset := (SampleCount - Length(AnalysisBuffer)) * SizeOf(SmallInt);
+    SampleCount := Length(AnalysisBuffer);
+  end;
+
+  LockAnalysisBuffer();
+  try
+
+    // move old samples to the beginning of the array (if necessary)
+    for i := 0 to High(AnalysisBuffer)-SampleCount do
+      AnalysisBuffer[i] := AnalysisBuffer[i+SampleCount];
+
+    // copy new samples to analysis buffer
+    Move(Buffer[BufferOffset], AnalysisBuffer[Length(AnalysisBuffer)-SampleCount],
+         SampleCount * SizeOf(SmallInt));
+
+  finally
+    UnlockAnalysisBuffer();
+  end;
+
+  // save capture-data to BufferLong if enabled
+  if (Ini.SavePlayback = 1) then
+  begin
+    // this is just for debugging (approx 15MB per player for a 3min song!!!)
+    // For an in-game replay-mode we need to compress data so we do not
+    // waste that much memory. Maybe ogg-vorbis with voice-preset in fast-mode?
+    // Or we could use a faster but not that efficient lossless compression.
+    LogBuffer.WriteBuffer(Buffer, BufferSize);
+  end;
+end;
+
+procedure TCaptureBuffer.AnalyzeBuffer;
+var
+  Volume:      single;
+  MaxVolume:   single;
+  SampleIndex: integer;
+  Threshold:   single;
+begin
+  ToneValid := false;
+  ToneAbs := -1;
+  Tone    := -1;
+
+  LockAnalysisBuffer();
+  try
+
+    // find maximum volume of first 1024 samples
+    MaxVolume := 0;
+    for SampleIndex := 0 to 1023 do
+    begin
+      Volume := Abs(AnalysisBuffer[SampleIndex]) / -Low(Smallint);
+      if Volume > MaxVolume then
+         MaxVolume := Volume;
+    end;
+
+    Threshold := IThresholdVals[Ini.ThresholdIndex];
+
+    // check if signal has an acceptable volume (ignore background-noise)
+    if MaxVolume >= Threshold then
+    begin
+      // analyse the current voice pitch
+      AnalyzeByAutocorrelation;
+      ToneValid := true;
+    end;
+
+  finally
+    UnlockAnalysisBuffer();
+  end;
+end;
+
+procedure TCaptureBuffer.AnalyzeByAutocorrelation;
+var
+  ToneIndex: integer;
+  CurFreq:   real;
+  CurWeight: real;
+  MaxWeight: real;
+  MaxTone:   integer;
+const
+  HalftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave)
+begin
+  // prepare to analyze
+  MaxWeight := -1;
+  MaxTone := 0; // this is not needed, but it satifies the compiler
+
+  // analyze halftones
+  // Note: at the lowest tone (~65Hz) and a buffer-size of 4096
+  // at 44.1 (or 48kHz) only 6 (or 5) samples are compared, this might be
+  // too few samples -> use a bigger buffer-size
+  for ToneIndex := 0 to NumHalftones-1 do
+  begin
+    CurFreq := BaseToneFreq * Power(HalftoneBase, ToneIndex);
+    CurWeight := AnalyzeAutocorrelationFreq(CurFreq);
+
+    // TODO: prefer higher frequencies (use >= or use downto)
+    if (CurWeight > MaxWeight) then
+    begin
+      // this frequency has a higher weight
+      MaxWeight := CurWeight;
+      MaxTone   := ToneIndex;
+    end;
+  end;
+
+  ToneAbs := MaxTone;
+  Tone    := MaxTone mod 12;
+end;
+
+// result medium difference
+function TCaptureBuffer.AnalyzeAutocorrelationFreq(Freq: real): real;
+var
+  Dist:                   real;    // distance (0=equal .. 1=totally different) between correlated samples
+  AccumDist:              real;    // accumulated distances
+  SampleIndex:            integer; // index of sample to analyze
+  CorrelatingSampleIndex: integer; // index of sample one period ahead
+  SamplesPerPeriod:       integer; // samples in one period
+begin
+  SampleIndex := 0;
+  SamplesPerPeriod := Round(AudioFormat.SampleRate/Freq);
+  CorrelatingSampleIndex := SampleIndex + SamplesPerPeriod;
+
+  AccumDist := 0;
+
+  // compare correlating samples
+  while (CorrelatingSampleIndex < AnalysisBufferSize) do
+  begin
+    // calc distance (correlation: 1-dist) to corresponding sample in next period
+    Dist := Abs(AnalysisBuffer[SampleIndex] - AnalysisBuffer[CorrelatingSampleIndex]) /
+            High(Word);
+    AccumDist := AccumDist + Dist;
+    Inc(SampleIndex);
+    Inc(CorrelatingSampleIndex);
+  end;
+
+  // return "inverse" average distance (=correlation)
+  Result := 1 - AccumDist / AnalysisBufferSize;
+end;
+
+function TCaptureBuffer.MaxSampleVolume: single;
+var
+  lSampleIndex: integer;
+  lMaxVol:      longint;
+begin;
+  LockAnalysisBuffer();
+  try
+    lMaxVol := 0;
+    for lSampleIndex := 0 to High(AnalysisBuffer) do
+    begin
+      if Abs(AnalysisBuffer[lSampleIndex]) > lMaxVol then
+        lMaxVol := Abs(AnalysisBuffer[lSampleIndex]);
+    end;
+  finally
+    UnlockAnalysisBuffer();
+  end;
+
+  result := lMaxVol / -Low(Smallint);
+end;
+
+const
+  ToneStrings: array[0..11] of string = (
+    'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'
+  );
+
+function TCaptureBuffer.GetToneString: string;
+begin
+  if (ToneValid) then
+    Result := ToneStrings[Tone] + IntToStr(ToneAbs div 12 + 2)
+  else
+    Result := '-';
+end;
+
+procedure TCaptureBuffer.BoostBuffer(Buffer: PByteArray; Size: integer);
+var
+  i:            integer;
+  Value:        longint;
+  SampleCount:  integer;
+  SampleBuffer: PSmallIntArray; // buffer handled as array of samples
+  Boost:        byte;
+begin
+  // TODO: set boost per device
+  case Ini.MicBoost of
+    0:   Boost := 1;
+    1:   Boost := 2;
+    2:   Boost := 4;
+    3:   Boost := 8;
+    else Boost := 1;
+  end;
+
+  // at the moment we will boost SInt16 data only
+  if (AudioFormat.Format = asfS16) then
+  begin
+    // interpret buffer as buffer of bytes
+    SampleBuffer := PSmallIntArray(Buffer);
+    SampleCount := Size div AudioFormat.FrameSize;
+
+    // boost buffer
+    for i := 0 to SampleCount-1 do
+    begin
+      Value := SampleBuffer^[i] * Boost;
+
+      if Value > High(Smallint) then
+        Value := High(Smallint);
+
+      if Value < Low(Smallint) then
+        Value := Low(Smallint);
+
+      SampleBuffer^[i] := Value;
+    end;
+  end;
+end;
+
+{ TAudioInputProcessor }
+
+constructor TAudioInputProcessor.Create;
+var
+  i: integer;
+begin
+  inherited;
+  SetLength(Sound, 6 {max players});//Ini.Players+1);
+  for i := 0 to High(Sound) do
+    Sound[i] := TCaptureBuffer.Create;
+end;
+
+destructor TAudioInputProcessor.Destroy;
+var
+  i: integer;
+begin
+  for i := 0 to High(Sound) do
+    Sound[i].Free;
+  SetLength(Sound, 0);
+  inherited;
+end;
+
+// updates InputDeviceConfig with current input-device information
+// See: TIni.LoadInputDeviceCfg()
+procedure TAudioInputProcessor.UpdateInputDeviceConfig;
+var
+  deviceIndex:    integer;
+  newDevice:      boolean;
+  deviceIniIndex: integer;
+  deviceCfg:      PInputDeviceConfig;
+  device:         TAudioInputDevice;
+  channelCount:   integer;
+  channelIndex:   integer;
+  i:              integer;
+begin
+  // Input devices - append detected soundcards
+  for deviceIndex := 0 to High(DeviceList) do
+  begin
+    newDevice := true;
+    //Search for Card in List
+    for deviceIniIndex := 0 to High(Ini.InputDeviceConfig) do
+    begin
+      deviceCfg := @Ini.InputDeviceConfig[deviceIniIndex];
+      device := DeviceList[deviceIndex];
+
+      if (deviceCfg.Name = Trim(device.Name)) then
+      begin
+        newDevice := false;
+
+        // store highest channel index as an offset for the new channels
+        channelIndex := High(deviceCfg.ChannelToPlayerMap);
+        // add missing channels or remove non-existing ones
+        SetLength(deviceCfg.ChannelToPlayerMap, device.AudioFormat.Channels);
+        // assign added channels to no player
+        for i := channelIndex+1 to High(deviceCfg.ChannelToPlayerMap) do
+        begin
+          deviceCfg.ChannelToPlayerMap[i] := CHANNEL_OFF;
+        end;
+
+        // associate ini-index with device
+        device.CfgIndex := deviceIniIndex;
+        break;
+      end;
+    end;
+
+    //If not in List -> Add
+    if newDevice then
+    begin
+      // resize list
+      SetLength(Ini.InputDeviceConfig, Length(Ini.InputDeviceConfig)+1);
+      deviceCfg := @Ini.InputDeviceConfig[High(Ini.InputDeviceConfig)];
+      device := DeviceList[deviceIndex];
+
+      // associate ini-index with device
+      device.CfgIndex := High(Ini.InputDeviceConfig);
+
+      deviceCfg.Name := Trim(device.Name);
+      deviceCfg.Input := 0;
+      deviceCfg.Latency := LATENCY_AUTODETECT;
+
+      channelCount := device.AudioFormat.Channels;
+      SetLength(deviceCfg.ChannelToPlayerMap, channelCount);
+
+      for channelIndex := 0 to channelCount-1 do
+      begin
+        // Do not set any default on first start of USDX.
+        // Otherwise most probably the wrong device (internal sound card)
+        // will be selected.
+        // It is better to force the user to configure the mics himself.
+        deviceCfg.ChannelToPlayerMap[channelIndex] := CHANNEL_OFF;
+      end;
+    end;
+  end;
+end;
+
+function TAudioInputProcessor.ValidateSettings: integer;
+const
+  MAX_PLAYER_COUNT = 6; // FIXME: there should be a global variable for this
+var
+  I, J: integer;
+  PlayerID: integer;
+  PlayerMap: array [0 .. MAX_PLAYER_COUNT - 1] of boolean;
+  InputDevice: TAudioInputDevice;
+  InputDeviceCfg: PInputDeviceConfig;
+begin
+  // mark all players as unassigned
+  for I := 0 to High(PlayerMap) do
+    PlayerMap[I] := false;
+
+  // iterate over all active devices
+  for I := 0 to High(DeviceList) do
+  begin
+    InputDevice := DeviceList[I];
+    InputDeviceCfg := @Ini.InputDeviceConfig[InputDevice.CfgIndex];
+    // iterate over all channels of the current devices
+    for J := 0 to High(InputDeviceCfg.ChannelToPlayerMap) do
+    begin
+      // get player that was mapped to the current device channel
+      PlayerID := InputDeviceCfg.ChannelToPlayerMap[J];
+      if (PlayerID <> CHANNEL_OFF) then
+      begin
+        // check if player is already assigned to another device/channel
+        if (PlayerMap[PlayerID - 1]) then
+        begin
+          Result := PlayerID;
+          Exit;
+        end;
+
+        // mark player as assigned to a device
+        PlayerMap[PlayerID - 1] := true;
+      end;
+    end;
+  end;
+  Result := 0;
+end;
+
+function TAudioInputProcessor.CheckPlayersConfig(PlayerCount: cardinal;
+  var PlayerState: TBooleanDynArray): integer;
+var
+  DeviceIndex:  integer;
+  ChannelIndex: integer;
+  Device:       TAudioInputDevice;
+  DeviceCfg:    PInputDeviceConfig;
+  PlayerIndex:  integer;
+  I: integer;
+begin
+  SetLength(PlayerState, PlayerCount);
+  // set all entries to "not configured"
+  for I := 0 to High(PlayerState) do
+  begin
+    PlayerState[I] := false;
+  end;
+
+  // check each used device
+  for DeviceIndex := 0 to High(AudioInputProcessor.DeviceList) do
+  begin
+    Device := AudioInputProcessor.DeviceList[DeviceIndex];
+    if not assigned(Device) then
+      continue;
+    DeviceCfg := @Ini.InputDeviceConfig[Device.CfgIndex];
+
+    // check if device is used
+    for ChannelIndex := 0 to High(DeviceCfg.ChannelToPlayerMap) do
+    begin
+      PlayerIndex := DeviceCfg.ChannelToPlayerMap[ChannelIndex] - 1;
+      if (PlayerIndex >= 0) and (PlayerIndex < PlayerCount) then
+        PlayerState[PlayerIndex] := true;
+    end;
+  end;
+
+  Result := 0;
+  for I := 0 to High(PlayerState) do
+  begin
+    if (PlayerState[I] = false) then
+    begin
+      Result := I + 1;
+      Break;
+    end;
+  end;
+end;
+
+function TAudioInputProcessor.CheckPlayersConfig(PlayerCount: cardinal): integer;
+var
+  PlayerState: TBooleanDynArray;
+begin
+  Result := CheckPlayersConfig(PlayerCount, PlayerState);
+end;
+
+{*
+ * Handles captured microphone input data.
+ * Params:
+ *   Buffer - buffer of signed 16bit interleaved stereo PCM-samples.
+ *     Interleaved means that a right-channel sample follows a left-
+ *     channel sample and vice versa (0:left[0],1:right[0],2:left[1],...).
+ *   Length - number of bytes in Buffer
+ *   Input - Soundcard-Input used for capture
+ *}
+procedure TAudioInputProcessor.HandleMicrophoneData(Buffer: PByteArray; Size: integer; InputDevice: TAudioInputDevice);
+var
+  MultiChannelBuffer:      PByteArray;  // buffer handled as array of bytes (offset relative to channel)
+  SingleChannelBuffer:     PByteArray;  // temporary buffer for new samples per channel
+  SingleChannelBufferSize: integer;
+  ChannelIndex:            integer;
+  CaptureChannel:          TCaptureBuffer;
+  AudioFormat:             TAudioFormatInfo;
+  SampleSize:              integer;
+  SamplesPerChannel:       integer;
+  i:                       integer;
+begin
+  AudioFormat := InputDevice.AudioFormat;
+  SampleSize := AudioSampleSize[AudioFormat.Format];
+  SamplesPerChannel := Size div AudioFormat.FrameSize;
+
+  SingleChannelBufferSize := SamplesPerChannel * SampleSize;
+  GetMem(SingleChannelBuffer, SingleChannelBufferSize);
+
+  // process channels
+  for ChannelIndex := 0 to High(InputDevice.CaptureChannel) do
+  begin
+    CaptureChannel := InputDevice.CaptureChannel[ChannelIndex];
+    // check if a capture buffer was assigned, otherwise there is nothing to do
+    if (CaptureChannel <> nil) then
+    begin
+      // set offset according to channel index
+      MultiChannelBuffer := @Buffer[ChannelIndex * SampleSize];
+      // separate channel-data from interleaved multi-channel (e.g. stereo) data
+      for i := 0 to SamplesPerChannel-1 do
+      begin
+        Move(MultiChannelBuffer[i*AudioFormat.FrameSize],
+             SingleChannelBuffer[i*SampleSize],
+             SampleSize);
+      end;
+      CaptureChannel.ProcessNewBuffer(SingleChannelBuffer, SingleChannelBufferSize);
+    end;
+  end;
+
+  FreeMem(SingleChannelBuffer);
+end;
+
+{ TAudioInputBase }
+
+function TAudioInputBase.FinalizeRecord: boolean;
+var
+  i: integer;
+begin
+  for i := 0 to High(AudioInputProcessor.DeviceList) do
+    AudioInputProcessor.DeviceList[i].Free();
+  AudioInputProcessor.DeviceList := nil;
+  Result := true;
+end;
+
+{*
+ * Start capturing on all used input-device.
+ *}
+procedure TAudioInputBase.CaptureStart;
+var
+  S:            integer;
+  DeviceIndex:  integer;
+  ChannelIndex: integer;
+  Device:       TAudioInputDevice;
+  DeviceCfg:    PInputDeviceConfig;
+  DeviceUsed:   boolean;
+  Player:       integer;
+begin
+  if (Started) then
+    CaptureStop();
+
+  // reset buffers
+  for S := 0 to High(AudioInputProcessor.Sound) do
+    AudioInputProcessor.Sound[S].Clear;
+
+  // start capturing on each used device
+  for DeviceIndex := 0 to High(AudioInputProcessor.DeviceList) do
+  begin
+    Device := AudioInputProcessor.DeviceList[DeviceIndex];
+    if not assigned(Device) then
+      continue;
+    DeviceCfg := @Ini.InputDeviceConfig[Device.CfgIndex];
+
+    DeviceUsed := false;
+
+    // check if device is used
+    for ChannelIndex := 0 to High(DeviceCfg.ChannelToPlayerMap) do
+    begin
+      Player := DeviceCfg.ChannelToPlayerMap[ChannelIndex] - 1;
+      if (Player < 0) or (Player >= PlayersPlay) then
+      begin
+        Device.LinkCaptureBuffer(ChannelIndex, nil);
+      end
+      else
+      begin
+        Device.LinkCaptureBuffer(ChannelIndex, AudioInputProcessor.Sound[Player]);
+        DeviceUsed := true;
+      end;
+    end;
+
+    // start device if used
+    if (DeviceUsed) then
+    begin
+      //Log.BenchmarkStart(2);
+      Device.Start();
+      //Log.BenchmarkEnd(2);
+      //Log.LogBenchmark('Device.Start', 2) ;
+    end;
+  end;
+
+  Started := true;
+end;
+
+{*
+ * Stop input-capturing on all soundcards.
+ *}
+procedure TAudioInputBase.CaptureStop;
+var
+  DeviceIndex:  integer;
+  ChannelIndex: integer;
+  Device:       TAudioInputDevice;
+  DeviceCfg:    PInputDeviceConfig;
+begin
+  for DeviceIndex := 0 to High(AudioInputProcessor.DeviceList) do
+  begin
+    Device := AudioInputProcessor.DeviceList[DeviceIndex];
+    if not assigned(Device) then
+      continue;
+
+    Device.Stop();
+
+    // disconnect capture buffers
+    DeviceCfg := @Ini.InputDeviceConfig[Device.CfgIndex];
+    for ChannelIndex := 0 to High(DeviceCfg.ChannelToPlayerMap) do
+      Device.LinkCaptureBuffer(ChannelIndex, nil);
+  end;
+
+  Started := false;
+end;
+
+function TAudioInputBase.UnifyDeviceName(const name: UTF8String; deviceIndex: integer): UTF8String;
+var
+  count: integer; // count of devices with this name
+
+  function IsDuplicate(const name: UTF8String): boolean;
+  var
+    i: integer;
+  begin
+    Result := false;
+    // search devices with same description
+    for i := 0 to deviceIndex-1 do
+    begin
+      if (AudioInputProcessor.DeviceList[i] <> nil) then
+      begin
+        if (AudioInputProcessor.DeviceList[i].Name = name) then
+        begin
+          Result := true;
+          Break;
+        end;
+      end;
+    end;
+  end;
+
+begin
+  count := 1;
+  result := name;
+
+  // if there is another device with the same ID, search for an available name
+  while (IsDuplicate(result)) do
+  begin
+    Inc(count);
+    // set description
+    result := name + ' ('+IntToStr(count)+')';
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/base/URingBuffer.pas b/songmanagement/src/base/URingBuffer.pas
new file mode 100644
index 00000000..684c13ee
--- /dev/null
+++ b/songmanagement/src/base/URingBuffer.pas
@@ -0,0 +1,165 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit URingBuffer;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils;
+
+type
+  TRingBuffer = class
+    private
+      RingBuffer: PByteArray;
+      BufferCount: integer;
+      BufferSize: integer;
+      WritePos: integer;
+      ReadPos: integer;
+    public
+      constructor Create(Size: integer);
+      destructor Destroy; override;
+      function Read(Buffer: PByteArray; Count: integer): integer;
+      function Write(Buffer: PByteArray; Count: integer): integer;
+      function Size(): integer;
+      function Available(): integer;
+      procedure Flush();
+  end;
+
+implementation
+
+uses
+  Math;
+
+constructor TRingBuffer.Create(Size: integer);
+begin
+  BufferSize := Size;
+
+  GetMem(RingBuffer, Size);
+  if (RingBuffer = nil) then
+    raise Exception.Create('No memory');
+end;
+
+destructor TRingBuffer.Destroy;
+begin
+  FreeMem(RingBuffer);
+end;
+
+function TRingBuffer.Read(Buffer: PByteArray; Count: integer): integer;
+var
+  PartCount: integer;
+begin
+  // adjust output count
+  if (Count > BufferCount) then
+  begin
+    //DebugWriteln('Read too much: ' + inttostr(count) +',count:'+ inttostr(BufferCount) + '/size:' + inttostr(BufferSize));
+    Count := BufferCount;
+  end;
+
+  // check if there is something to do
+  if (Count <= 0) then
+  begin
+    Result := Count;
+    Exit;
+  end;
+
+  // copy data to output buffer
+
+  // first step: copy from the area between the read-position and the end of the buffer
+  PartCount := Min(Count, BufferSize - ReadPos);
+  Move(RingBuffer[ReadPos], Buffer[0], PartCount);
+
+  // second step: if we need more data, copy from the beginning of the buffer
+  if (PartCount < Count) then
+    Move(RingBuffer[0], Buffer[0], Count-PartCount);
+
+  // mark the copied part of the buffer as free
+  BufferCount := BufferCount - Count;
+  ReadPos := (ReadPos + Count) mod BufferSize;
+
+  Result := Count;
+end;
+
+function TRingBuffer.Write(Buffer: PByteArray; Count: integer): integer;
+var
+  PartCount: integer;
+begin
+  // check for a reasonable request
+  if (Count <= 0) then
+  begin
+    Result := Count;
+    Exit;
+  end;
+
+  // skip input data if the input buffer is bigger than the ring-buffer
+  if (Count > BufferSize) then
+  begin
+    //DebugWriteln('Write skip data:' + inttostr(count) +',count:'+ inttostr(BufferCount) + '/size:' + inttostr(BufferSize));
+    Buffer := @Buffer[Count - BufferSize];
+    Count := BufferSize;
+  end;
+
+  // first step: copy to the area between the write-position and the end of the buffer
+  PartCount := Min(Count, BufferSize - WritePos);
+  Move(Buffer[0], RingBuffer[WritePos], PartCount);
+
+  // second step: copy data to front of buffer
+  if (PartCount < Count) then
+    Move(Buffer[PartCount], RingBuffer[0], Count-PartCount);
+
+  // update info
+  BufferCount := Min(BufferCount + Count, BufferSize);
+  WritePos := (WritePos + Count) mod BufferSize;
+  // if the buffer is full, we have to reposition the read-position
+  if (BufferCount = BufferSize) then
+    ReadPos := WritePos;
+
+  Result := Count;
+end;
+
+function TRingBuffer.Available(): integer;
+begin
+  Result := BufferCount;
+end;
+
+function TRingBuffer.Size(): integer;
+begin
+  Result := BufferSize;
+end;
+
+procedure TRingBuffer.Flush();
+begin
+  ReadPos := 0;
+  WritePos := 0;
+  BufferCount := 0;
+end;
+
+end.
diff --git a/songmanagement/src/base/USingNotes.pas b/songmanagement/src/base/USingNotes.pas
new file mode 100644
index 00000000..dcfaff9f
--- /dev/null
+++ b/songmanagement/src/base/USingNotes.pas
@@ -0,0 +1,42 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit USingNotes;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+{ Dummy Unit atm
+  For further explanation
+  Placeholder for Class that will handle the Notes Drawing}
+
+implementation
+
+end.
diff --git a/songmanagement/src/base/USingScores.pas b/songmanagement/src/base/USingScores.pas
new file mode 100644
index 00000000..26c5dfe8
--- /dev/null
+++ b/songmanagement/src/base/USingScores.pas
@@ -0,0 +1,1122 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit USingScores;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  gl,
+  UThemes,
+  UTexture;
+
+//////////////////////////////////////////////////////////////
+//                        ATTENTION:                        //
+// Enabled flag does not work atm. This should cause popups //
+// not to move and scores to stay until re-enabling.        //
+// To use e.g. in pause mode                                //
+// also invisible flag causes attributes not to change.     //
+// This should be fixed after next draw when visible = true,//
+// but not tested yet                                       //
+//////////////////////////////////////////////////////////////
+
+// some constants containing options that could change by time
+const
+  MaxPlayers = 6;   // maximum of players that could be added
+  MaxPositions = 6; // maximum of score positions that could be added
+
+type
+  //-----------
+  // TScorePlayer - record containing information about a players score
+  //-----------
+  TScorePlayer = record
+    Position:       byte;     // index of the position where the player should be drawn
+    Enabled:        boolean;  // is the score display enabled
+    Visible:        boolean;  // is the score display visible
+    Score:          word;     // current score of the player
+    ScoreDisplayed: word;     // score cur. displayed (for counting up)
+    ScoreBG:        TTexture; // texture of the players scores bg
+    Color:          TRGB;     // the players color
+    RBPos:          real;     // cur. percentille of the rating bar
+    RBTarget:       real;     // target position of rating bar
+    RBVisible:      boolean;  // is rating bar drawn
+  end;
+  aScorePlayer = array [0..MaxPlayers-1] of TScorePlayer;
+
+  //-----------
+  // TScorePosition - record containing information about a score position, that can be used
+  //-----------
+  PScorePosition = ^TScorePosition;
+  TScorePosition = record
+    // the position is used for which playercount
+    PlayerCount: byte;
+    // 1 - 1 player per screen
+    // 2 - 2 players per screen
+    // 4 - 3 players per screen
+    // 6 would be 2 and 3 players per screen
+
+    BGX: real;     // x position of the score bg
+    BGY: real;     // y position of the score bg
+    BGW: real;     // width of the score bg
+    BGH: real;     // height of the score bg
+
+    RBX: real;     // x position of the rating bar
+    RBY: real;     // y position of the rating bar
+    RBW: real;     // width of the rating bar
+    RBH: real;     // height of the rating bar
+
+    TextX: real;         // x position of the score text
+    TextY: real;         // y position of the score text
+    TextFont: byte;      // font of the score text
+    TextSize: integer;   // size of the score text
+
+    PUW:        real;     // width of the line bonus popup
+    PUH:        real;     // height of the line bonus popup
+    PUFont:     byte;     // font for the popups
+    PUFontSize: integer;  // font size for the popups
+    PUStartX:   real;     // x start position of the line bonus popup
+    PUStartY:   real;     // y start position of the line bonus popup
+    PUTargetX:  real;     // x target position of the line bonus popup
+    PUTargetY:  real;     // y target position of the line bonus popup
+  end;
+  aScorePosition = array [0..MaxPositions-1] of TScorePosition;
+
+  //-----------
+  // TScorePopUp - record containing information about a line bonus popup
+  // list, next item is saved in next attribute
+  //-----------
+  PScorePopUp = ^TScorePopUp;
+  TScorePopUp = record
+    Player:     byte;        // index of the popups player
+    TimeStamp:  cardinal;    // timestamp of popups spawn
+    Rating:     integer;     // 0 to 8, type of rating (cool, bad, etc.)
+    ScoreGiven: integer;     // score that has already been given to the player
+    ScoreDiff:  integer;     // difference between cur score at spawn and old score
+    Next:       PScorePopUp; // next item in list
+  end;
+  aScorePopUp = array of TScorePopUp;
+
+  //-----------
+  // TSingScores - class containing scores positions and drawing scores, rating bar + popups
+  //-----------
+  TSingScores = class
+    private
+      aPositions: aScorePosition;
+      aPlayers:  aScorePlayer;
+      oPositionCount: byte;
+      oPlayerCount:   byte;
+
+      // saves the first and last popup of the list
+      FirstPopUp: PScorePopUp;
+      LastPopUp:  PScorePopUp;
+
+      // only defined during draw, time passed between
+      // current and previous call of draw
+      TimePassed: Cardinal;
+
+      // draws a popup by pointer
+      procedure DrawPopUp(const PopUp: PScorePopUp);
+
+      // raises players score if RaiseScore was called
+      // has to be called after DrawPopUp and before
+      // DrawScore
+      procedure DoRaiseScore(const Index: integer);
+
+      // draws a score by playerindex
+      procedure DrawScore(const Index: integer);
+
+      // draws the rating bar by playerindex
+      procedure DrawRatingBar(const Index: integer);
+
+      // removes a popup w/o destroying the list
+      procedure KillPopUp(const last, cur: PScorePopUp);
+
+      // calculate the amount of points for a player that is
+      // still in popups and therfore not displayed
+      function GetPopUpPoints(const Index: integer): integer;
+    public
+      Settings: record // Record containing some Displaying Options
+        Phase1Time: real;     // time for phase 1 to complete (in msecs)
+                              // the plop up of the popup
+        Phase2Time: real;     // time for phase 2 to complete (in msecs)
+                              // the moving (mainly upwards) of the popup
+        Phase3Time: real;     // time for phase 3 to complete (in msecs)
+                              // the fade out and score adding
+
+        PopUpTex:   array [0..8] of TTexture; // textures for every popup rating
+
+        RatingBar_BG_Tex:  TTexture; // rating bar texs
+        RatingBar_FG_Tex:  TTexture;
+        RatingBar_Bar_Tex: TTexture;
+
+      end;
+
+      Visible:   boolean;  // visibility of all scores
+      Enabled:   boolean;  // scores are changed, popups are moved etc.
+      RBVisible: boolean;  // visibility of all rating bars
+
+      // properties for reading position and playercount
+      property PositionCount: byte         read oPositionCount;
+      property PlayerCount:   byte         read oPlayerCount;
+      property Players:       aScorePlayer read aPlayers;
+      property Positions: aScorePosition read aPositions;
+
+      // constructor just sets some standard settings
+      constructor Create;
+
+      // adds a position to array and increases position count
+      procedure AddPosition(const pPosition: PScorePosition);
+
+      // adds a player to array and increases player count
+      procedure AddPlayer(const ScoreBG: TTexture; const Color: TRGB; const Score: word = 0; const Enabled: boolean = true; const Visible: boolean = true);
+
+      // change a players visibility, enable
+      procedure ChangePlayerVisibility(const Index: byte; const pVisible: boolean);
+      procedure ChangePlayerEnabled(const Index: byte; const pEnabled: boolean);
+
+      // deletes all player information
+      procedure ClearPlayers;
+
+      // deletes positions and playerinformation
+      procedure Clear;
+
+      // loads some settings and the positions from theme
+      procedure LoadfromTheme;
+
+      // has to be called after positions and players have been added, before first call of draw
+      // it gives every player a score position
+      procedure Init;
+
+      // raises the score of a specified player to the specified score
+      procedure RaiseScore(Player: byte; Score: integer);
+
+      // sets the score of a specified player to the specified score
+      procedure SetScore(Player: byte; Score: integer);
+
+      // spawns a new line bonus popup for the player
+      procedure SpawnPopUp(const PlayerIndex: byte; const Rating: integer; const Score: integer);
+
+      // removes all popups from mem
+      procedure KillAllPopUps;
+
+      // draws scores and line bonus popups
+      procedure Draw;
+  end;
+
+implementation
+
+uses
+  SysUtils,
+  Math,
+  SDL,
+  TextGL,
+  ULog,
+  UGraphic;
+
+{**
+ * sets some standard settings
+ *}
+constructor TSingScores.Create;
+begin
+  inherited;
+
+  // clear popuplist pointers
+  FirstPopUp := nil;
+  LastPopUp  := nil;
+
+  // clear variables
+  Visible   := true;
+  Enabled   := true;
+  RBVisible := true;
+  
+  // clear position index
+  oPositionCount := 0;
+  oPlayerCount   := 0;
+
+  Settings.Phase1Time := 350;  // plop it up     . -> [   ]
+  Settings.Phase2Time := 550;  // shift it up        ^[   ]^
+  Settings.Phase3Time := 200;  // increase score      [s++]
+
+  Settings.PopUpTex[0].TexNum := 0;
+  Settings.PopUpTex[1].TexNum := 0;
+  Settings.PopUpTex[2].TexNum := 0;
+  Settings.PopUpTex[3].TexNum := 0;
+  Settings.PopUpTex[4].TexNum := 0;
+  Settings.PopUpTex[5].TexNum := 0;
+  Settings.PopUpTex[6].TexNum := 0;
+  Settings.PopUpTex[7].TexNum := 0;
+  Settings.PopUpTex[8].TexNum := 0;
+
+  Settings.RatingBar_BG_Tex.TexNum   := 0;
+  Settings.RatingBar_FG_Tex.TexNum   := 0;
+  Settings.RatingBar_Bar_Tex.TexNum  := 0;
+end;
+
+{**
+ * adds a position to array and increases position count
+ *}
+procedure TSingScores.AddPosition(const pPosition: PScorePosition);
+begin
+  if (PositionCount < MaxPositions) then
+  begin
+    aPositions[PositionCount] := pPosition^;
+    Inc(oPositionCount);
+  end;
+end;
+
+{**
+ * adds a player to array and increases player count
+ *}
+procedure TSingScores.AddPlayer(const ScoreBG: TTexture; const Color: TRGB; const Score: word; const Enabled: boolean; const Visible: boolean);
+begin
+  if (PlayerCount < MaxPlayers) then
+  begin
+    aPlayers[PlayerCount].Position  := High(byte);
+    aPlayers[PlayerCount].Enabled   := Enabled;
+    aPlayers[PlayerCount].Visible   := Visible;
+    aPlayers[PlayerCount].Score     := Score;
+    aPlayers[PlayerCount].ScoreDisplayed := Score;
+    aPlayers[PlayerCount].ScoreBG   := ScoreBG;
+    aPlayers[PlayerCount].Color     := Color;
+    aPlayers[PlayerCount].RBPos     := 0.5;
+    aPlayers[PlayerCount].RBTarget  := 0.5;
+    aPlayers[PlayerCount].RBVisible := true;
+
+    Inc(oPlayerCount);
+  end;
+end;
+
+{**
+ * change a players visibility
+ *}
+procedure TSingScores.ChangePlayerVisibility(const Index: byte; const pVisible: boolean);
+begin
+  if (Index < MaxPlayers) then
+    aPlayers[Index].Visible := pVisible;
+end;
+
+{**
+ * change player enabled
+ *}
+procedure TSingScores.ChangePlayerEnabled(const Index: byte; const pEnabled: boolean);
+begin
+  if (Index < MaxPlayers) then
+    aPlayers[Index].Enabled := pEnabled;
+end;
+
+{**
+ * procedure deletes all player information
+ *}
+procedure TSingScores.ClearPlayers;
+begin
+  KillAllPopUps;
+  oPlayerCount := 0;
+  TimePassed := 0;
+end;
+
+{**
+ * procedure deletes positions and playerinformation
+ *}
+procedure TSingScores.Clear;
+begin
+  KillAllPopUps;
+  oPlayerCount    := 0;
+  oPositionCount  := 0;
+  TimePassed := 0;
+end;
+
+{**
+ * procedure loads some settings and the positions from theme
+ *}
+procedure TSingScores.LoadfromTheme;
+var
+  I: integer;
+  procedure AddbyStatics(const PC: byte; const ScoreStatic, SingBarStatic: TThemeStatic; ScoreText: TThemeText);
+  var
+    nPosition: TScorePosition;
+  begin
+    nPosition.PlayerCount := PC; // only for one player playing
+
+    nPosition.BGX := ScoreStatic.X;
+    nPosition.BGY := ScoreStatic.Y;
+    nPosition.BGW := ScoreStatic.W;
+    nPosition.BGH := ScoreStatic.H;
+
+    nPosition.TextX     := ScoreText.X;
+    nPosition.TextY     := ScoreText.Y;
+    nPosition.TextFont  := ScoreText.Font;
+    nPosition.TextSize  := ScoreText.Size;
+
+    nPosition.RBX := SingBarStatic.X;
+    nPosition.RBY := SingBarStatic.Y;
+    nPosition.RBW := SingBarStatic.W;
+    nPosition.RBH := SingBarStatic.H;
+
+    nPosition.PUW := nPosition.BGW;
+    nPosition.PUH := nPosition.BGH;
+
+    nPosition.PUFont     := ftOutline1;
+    nPosition.PUFontSize := 18;
+
+    nPosition.PUStartX := nPosition.BGX;
+    nPosition.PUStartY := nPosition.TextY + 65;
+
+    nPosition.PUTargetX := nPosition.BGX;
+    nPosition.PUTargetY := nPosition.TextY;
+
+    AddPosition(@nPosition);
+  end;
+begin
+  Clear;
+
+  // set textures
+  // popup tex
+  for I := 0 to 8 do
+    Settings.PopUpTex[I] := Tex_SingLineBonusBack[I];
+
+  // rating bar tex  
+  Settings.RatingBar_BG_Tex   :=  Tex_SingBar_Back;
+  Settings.RatingBar_FG_Tex   :=  Tex_SingBar_Front;
+  Settings.RatingBar_Bar_Tex  :=  Tex_SingBar_Bar;
+
+  // load positions from theme
+
+  // player 1:
+  AddByStatics(1, Theme.Sing.StaticP1ScoreBG, Theme.Sing.StaticP1SingBar, Theme.Sing.TextP1Score);
+  AddByStatics(2, Theme.Sing.StaticP1TwoPScoreBG, Theme.Sing.StaticP1TwoPSingBar, Theme.Sing.TextP1TwoPScore);
+  AddByStatics(4, Theme.Sing.StaticP1ThreePScoreBG, Theme.Sing.StaticP1ThreePSingBar, Theme.Sing.TextP1ThreePScore);
+
+  // player 2:
+  AddByStatics(2, Theme.Sing.StaticP2RScoreBG, Theme.Sing.StaticP2RSingBar, Theme.Sing.TextP2RScore);
+  AddByStatics(4, Theme.Sing.StaticP2MScoreBG, Theme.Sing.StaticP2MSingBar, Theme.Sing.TextP2MScore);
+
+  // player 3:
+  AddByStatics(4, Theme.Sing.StaticP3RScoreBG, Theme.Sing.StaticP3SingBar, Theme.Sing.TextP3RScore);
+end;
+
+{**
+ * raises the score of a specified player to the specified score
+ *}
+procedure TSingScores.RaiseScore(Player: byte; Score: integer);
+begin
+  if (Player <= PlayerCount - 1) then
+    aPlayers[Player].Score := Score;
+end;
+
+{**
+ * sets the score of a specified player to the specified score
+ *}
+procedure TSingScores.SetScore(Player: byte; Score: integer);
+  var
+    Diff: Integer;
+begin
+  if (Player <= PlayerCount - 1) then
+  begin
+    Diff := Score - Players[Player].Score;
+    aPlayers[Player].Score := Score;
+    Inc(aPlayers[Player].ScoreDisplayed, Diff);
+  end;
+end;
+
+{**
+ * spawns a new line bonus popup for the player
+ *}
+procedure TSingScores.SpawnPopUp(const PlayerIndex: byte; const Rating: integer; const Score: integer);
+var
+  Cur: PScorePopUp;
+begin
+  if (PlayerIndex < PlayerCount) then
+  begin
+    // get memory and add data
+    GetMem(Cur, SizeOf(TScorePopUp));
+
+    Cur.Player    := PlayerIndex;
+    Cur.TimeStamp := SDL_GetTicks;
+
+    // limit rating value to 0..8
+    // a higher value would cause a crash when selecting the bg texture
+    if (Rating > 8) then
+      Cur.Rating := 8
+    else if (Rating < 0) then
+      Cur.Rating := 0
+    else
+      Cur.Rating := Rating;
+
+    Cur.ScoreGiven:= 0;
+    if (Players[PlayerIndex].Score < Score) then
+    begin
+      Cur.ScoreDiff := Score - Players[PlayerIndex].Score;
+      aPlayers[PlayerIndex].Score := Score;
+    end
+    else
+      Cur.ScoreDiff := 0;
+    Cur.Next := nil;
+
+    // Log.LogError('TSingScores.SpawnPopUp| Player: ' + InttoStr(PlayerIndex) + ', Score: ' + InttoStr(Score) + ', ScoreDiff: ' + InttoStr(Cur.ScoreDiff));
+
+    // add it to the chain
+    if (FirstPopUp = nil) then
+      // the first popup in the list
+      FirstPopUp := Cur
+    else
+    // second or earlier popup
+      LastPopUp.Next := Cur;
+
+    // set new popup to last popup in the list
+    LastPopUp := Cur;
+  end
+  else
+    Log.LogError('TSingScores: Try to add popup for non-existing player');
+end;
+
+{**
+ * removes a popup w/o destroying the list
+ *}
+procedure TSingScores.KillPopUp(const last, cur: PScorePopUp);
+begin
+  // give player the last points that missing till now
+  aPlayers[Cur.Player].ScoreDisplayed := aPlayers[Cur.Player].ScoreDisplayed + Cur.ScoreDiff - Cur.ScoreGiven;
+
+  // change bars position
+  if (Cur.ScoreDiff > 0) THEN
+  begin // popup w/ scorechange -> give missing percentille
+    aPlayers[Cur.Player].RBTarget := aPlayers[Cur.Player].RBTarget +
+                                     (Cur.ScoreDiff - Cur.ScoreGiven) / Cur.ScoreDiff
+                                     * (Cur.Rating / 20 - 0.26);
+  end
+  else
+  begin // popup w/o scorechange -> give complete percentille
+    aPlayers[Cur.Player].RBTarget := aPlayers[Cur.Player].RBTarget +
+                                     (Cur.Rating / 20 - 0.26);
+  end;
+
+  if (aPlayers[Cur.Player].RBTarget > 1) then
+    aPlayers[Cur.Player].RBTarget := 1
+  else
+  if (aPlayers[Cur.Player].RBTarget < 0) then
+    aPlayers[Cur.Player].RBTarget := 0;
+
+  // if this is the first popup => make next popup the first
+  if (Cur = FirstPopUp) then
+    FirstPopUp := Cur.Next
+  // else => remove curent popup from chain
+  else
+    Last.Next := Cur.Next;
+
+  // if this is the last popup, make popup before the last
+  if (Cur = LastPopUp) then
+    LastPopUp := Last;
+
+  // free the memory
+  FreeMem(Cur, SizeOf(TScorePopUp));
+end;
+
+{**
+ * removes all popups from mem
+ *}
+procedure TSingScores.KillAllPopUps;
+var
+  Cur:  PScorePopUp;
+  Last: PScorePopUp;
+begin
+  Cur := FirstPopUp;
+
+  // remove all popups:
+  while (Cur <> nil) do
+  begin
+    Last := Cur;
+    Cur  := Cur.Next;
+    FreeMem(Last, SizeOf(TScorePopUp));
+  end;
+
+  FirstPopUp := nil;
+  LastPopUp := nil;
+end;
+
+{**
+ * calculate the amount of points for a player that is
+ * still in popups and therfore not displayed
+ *}
+function TSingScores.GetPopUpPoints(const Index: integer): integer;
+  var
+    CurPopUp: PScorePopUp;
+begin
+  Result := 0;
+  
+  CurPopUp := FirstPopUp;
+  while (CurPopUp <> nil) do
+  begin
+    if (CurPopUp.Player = Index) then
+    begin // add points left "in" popup to result
+      Inc(Result, CurPopUp.ScoreDiff - CurPopUp.ScoreGiven);
+    end;
+    CurPopUp := CurPopUp.Next;
+  end;
+end;
+
+{**
+ * has to be called after positions and players have been added, before first call of draw
+ * it gives each player a score position
+ *}
+procedure TSingScores.Init;
+var
+  PlC:                 array [0..1] of byte; // playercount first screen and second screen
+  I, J:                integer;
+  MaxPlayersperScreen: byte;
+  CurPlayer:           byte;
+
+  function GetPositionCountbyPlayerCount(bPlayerCount: byte): byte;
+  var
+    I: integer;
+  begin
+    Result := 0;
+    bPlayerCount := 1 shl (bPlayerCount - 1);
+
+    for I := 0 to PositionCount - 1 do
+    begin
+      if ((aPositions[I].PlayerCount and bPlayerCount) <> 0) then
+        Inc(Result);
+    end;
+  end;
+
+  function GetPositionbyPlayernum(bPlayerCount, bPlayer: byte): byte;
+  var
+    I: integer;
+  begin
+    bPlayerCount := 1 shl (bPlayerCount - 1);
+    Result := High(byte);
+
+    for I := 0 to PositionCount - 1 do
+    begin
+      if ((aPositions[I].PlayerCount and bPlayerCount) <> 0) then
+      begin
+        if (bPlayer = 0) then
+        begin
+          Result := I;
+          Break;
+        end
+        else
+          Dec(bPlayer);
+      end;
+    end;
+  end;
+
+begin
+  MaxPlayersPerScreen := 0;
+
+  for I := 1 to 6 do
+  begin
+    // if there are enough positions -> write to maxplayers
+    if (GetPositionCountbyPlayerCount(I) = I) then
+      MaxPlayersPerScreen := I
+    else
+      Break;
+  end;
+
+  // split players to both screens or display on one screen
+  if (Screens = 2) and (MaxPlayersPerScreen < PlayerCount) then
+  begin
+    PlC[0] := PlayerCount div 2 + PlayerCount mod 2;
+    PlC[1] := PlayerCount div 2;
+  end
+  else
+  begin
+    PlC[0] := PlayerCount;
+    PlC[1] := 0;
+  end;
+
+  // check if there are enough positions for all players
+  for I := 0 to Screens - 1 do
+  begin
+    if (PlC[I] > MaxPlayersperScreen) then
+    begin
+      PlC[I] := MaxPlayersperScreen;
+      Log.LogError('More Players than available Positions, TSingScores');
+    end;
+  end;
+  
+  CurPlayer := 0;
+  // give every player a position
+  for I := 0 to Screens - 1 do
+    for J := 0 to PlC[I]-1 do
+    begin
+      aPlayers[CurPlayer].Position := GetPositionbyPlayernum(PlC[I], J) or (I shl 7);
+      // Log.LogError('Player ' + InttoStr(CurPlayer) + ' gets Position: ' + InttoStr(aPlayers[CurPlayer].Position));
+      Inc(CurPlayer);
+    end;
+end;
+
+{**
+ * draws scores and linebonus popups
+ *}
+procedure TSingScores.Draw;
+var
+  I: integer;
+  CurTime: cardinal;
+  CurPopUp, LastPopUp: PScorePopUp;
+begin
+  CurTime := SDL_GetTicks;
+  if (TimePassed <> 0) then
+    TimePassed := CurTime - TimePassed;
+
+  if Visible then
+  begin
+    // draw popups
+    LastPopUp := nil;
+    CurPopUp  := FirstPopUp;
+
+    while (CurPopUp <> nil) do
+    begin
+      if (CurTime - CurPopUp.TimeStamp > Settings.Phase1Time + Settings.Phase2Time + Settings.Phase3Time) then
+      begin
+        KillPopUp(LastPopUp, CurPopUp);
+        if (LastPopUp = nil) then
+          CurPopUp := FirstPopUp
+        else
+          CurPopUp  := LastPopUp.Next;
+      end
+      else
+      begin
+        DrawPopUp(CurPopUp);
+        LastPopUp := CurPopUp;
+        CurPopUp  := LastPopUp.Next;
+      end;
+    end;
+
+
+    if (RBVisible) then
+      // draw players w/ rating bar
+      for I := 0 to PlayerCount-1 do
+      begin
+        DoRaiseScore(I);
+        DrawScore(I);
+        DrawRatingBar(I);
+      end
+    else
+      // draw players w/o rating bar
+      for I := 0 to PlayerCount-1 do
+      begin
+        DoRaiseScore(I);
+        DrawScore(I);
+      end;
+
+  end; // eo visible
+
+  TimePassed := CurTime;
+end;
+
+{**
+ * raises players score if RaiseScore was called
+ * has to be called after DrawPopUp and before
+ * DrawScore
+ *}
+procedure TSingScores.DoRaiseScore(const Index: integer);
+  var
+    S: integer;
+    Diff: integer;
+  const
+    RaisePerSecond = 500;
+begin
+  S := (Players[Index].Score - (Players[Index].ScoreDisplayed + GetPopUpPoints(Index)));
+
+  if (S <> 0) then
+  begin
+    Diff := Round(RoundTo((RaisePerSecond * TimePassed) / 1000, 1));
+
+    { minimal raise per frame = 1 }
+    if Abs(Diff) < 1 then
+      Diff := Sign(S);
+
+    if (Abs(Diff) < Abs(S)) then
+      Inc(aPlayers[Index].ScoreDisplayed, Diff)
+    else
+      Inc(aPlayers[Index].ScoreDisplayed, S);
+  end;
+end;
+
+{**
+ * draws a popup by pointer
+ *}
+procedure TSingScores.DrawPopUp(const PopUp: PScorePopUp);
+var
+  Progress:          real;
+  CurTime:           cardinal;
+  X, Y, W, H, Alpha: real;
+  FontSize:          integer;
+  FontOffset:        real;
+  TimeDiff:          cardinal;
+  PIndex:            byte;
+  TextLen:           real;
+  ScoretoAdd:        word;
+  PosDiff:           real;
+begin
+  if (PopUp <> nil) then
+  begin
+    // only draw if player has a position
+    PIndex := Players[PopUp.Player].Position;
+    if PIndex <> High(byte) then
+    begin
+      // only draw if player is on cur screen
+      if ((Players[PopUp.Player].Position and 128) = 0) = (ScreenAct = 1) then
+      begin
+        CurTime := SDL_GetTicks;
+        if not (Enabled and Players[PopUp.Player].Enabled) then
+        // increase timestamp with tiem where there is no movement ...
+        begin
+          // Inc(PopUp.TimeStamp, LastRender);
+        end;
+        TimeDiff := CurTime - PopUp.TimeStamp;
+
+        // get position of popup
+        PIndex := PIndex and 127;
+
+    
+        // check for phase ...
+        if (TimeDiff <= Settings.Phase1Time) then
+        begin
+          // phase 1 - the ploping up
+          Progress := TimeDiff / Settings.Phase1Time;
+
+
+          W := aPositions[PIndex].PUW * Sin(Progress/2*Pi);
+          H := aPositions[PIndex].PUH * Sin(Progress/2*Pi);
+
+          X := aPositions[PIndex].PUStartX + (aPositions[PIndex].PUW - W)/2;
+          Y := aPositions[PIndex].PUStartY + (aPositions[PIndex].PUH - H)/2;
+
+          FontSize   := Round(Progress * aPositions[PIndex].PUFontSize);
+          FontOffset := (H - FontSize) / 2;
+          Alpha := 1;
+        end
+
+        else if (TimeDiff <= Settings.Phase2Time + Settings.Phase1Time) then
+        begin
+          // phase 2 - the moving
+          Progress := (TimeDiff - Settings.Phase1Time) / Settings.Phase2Time;
+
+          W := aPositions[PIndex].PUW;
+          H := aPositions[PIndex].PUH;
+
+          PosDiff := aPositions[PIndex].PUTargetX - aPositions[PIndex].PUStartX;
+          if PosDiff > 0 then
+            PosDiff := PosDiff + W;
+          X := aPositions[PIndex].PUStartX + PosDiff * sqr(Progress);
+
+          PosDiff := aPositions[PIndex].PUTargetY - aPositions[PIndex].PUStartY;
+          if PosDiff < 0 then
+            PosDiff := PosDiff + aPositions[PIndex].BGH;
+          Y := aPositions[PIndex].PUStartY + PosDiff * sqr(Progress);
+
+          FontSize   := aPositions[PIndex].PUFontSize;
+          FontOffset := (H - FontSize) / 2;
+          Alpha := 1 - 0.3 * Progress;
+        end
+
+        else
+        begin
+          // phase 3 - the fading out + score adding
+          Progress := (TimeDiff - Settings.Phase1Time - Settings.Phase2Time) / Settings.Phase3Time;
+
+          if (PopUp.Rating > 0) then
+          begin
+            // add scores if player enabled
+            if (Enabled and Players[PopUp.Player].Enabled) then
+            begin
+              ScoreToAdd := Round(PopUp.ScoreDiff * Progress) - PopUp.ScoreGiven;
+              Inc(PopUp.ScoreGiven, ScoreToAdd);
+              aPlayers[PopUp.Player].ScoreDisplayed := Players[PopUp.Player].ScoreDisplayed + ScoreToAdd;
+
+              // change bar positions
+	      if PopUp.ScoreDiff = 0 then
+		Log.LogError('TSingScores.DrawPopUp', 'PopUp.ScoreDiff is 0 and we want to divide by it. No idea how this happens.')
+	      else
+                aPlayers[PopUp.Player].RBTarget := aPlayers[PopUp.Player].RBTarget + ScoreToAdd/PopUp.ScoreDiff * (PopUp.Rating / 20 - 0.26);
+              if (aPlayers[PopUp.Player].RBTarget > 1) then
+                aPlayers[PopUp.Player].RBTarget := 1
+              else if (aPlayers[PopUp.Player].RBTarget < 0) then
+                aPlayers[PopUp.Player].RBTarget := 0;
+            end;
+
+            // set positions etc.
+            Alpha := 0.7 - 0.7 * Progress;
+
+            W := aPositions[PIndex].PUW;
+            H := aPositions[PIndex].PUH;
+
+            PosDiff := aPositions[PIndex].PUTargetX - aPositions[PIndex].PUStartX;
+            if (PosDiff > 0) then
+              PosDiff := W
+            else
+              PosDiff := 0;
+            X := aPositions[PIndex].PUTargetX + PosDiff * Progress;
+
+            PosDiff := aPositions[PIndex].PUTargetY - aPositions[PIndex].PUStartY;
+            if (PosDiff < 0) then
+              PosDiff := -aPositions[PIndex].BGH
+            else
+              PosDiff := 0;
+            Y := aPositions[PIndex].PUTargetY - PosDiff * (1 - Progress);
+
+            FontSize   := aPositions[PIndex].PUFontSize;
+            FontOffset := (H - FontSize) / 2;
+          end
+          else
+          begin
+            // here the effect that should be shown if a popup without score is drawn
+            // and or spawn with the graphicobjects etc.
+            // some work for blindy to do :p
+
+            // atm: just let it slide in the scores just like the normal popup
+            Alpha := 0;
+          end;
+        end;
+
+        // draw popup
+
+        if (Alpha > 0) and (Players[PopUp.Player].Visible) then
+        begin
+          // draw bg:
+          glEnable(GL_TEXTURE_2D);
+          glEnable(GL_BLEND);
+          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+          glColor4f(1,1,1, Alpha);
+          glBindTexture(GL_TEXTURE_2D, Settings.PopUpTex[PopUp.Rating].TexNum);
+
+          glBegin(GL_QUADS);
+            glTexCoord2f(0, 0); glVertex2f(X, Y);
+            glTexCoord2f(0, Settings.PopUpTex[PopUp.Rating].TexH); glVertex2f(X, Y + H);
+            glTexCoord2f(Settings.PopUpTex[PopUp.Rating].TexW, Settings.PopUpTex[PopUp.Rating].TexH); glVertex2f(X + W, Y + H);
+            glTexCoord2f(Settings.PopUpTex[PopUp.Rating].TexW, 0); glVertex2f(X + W, Y);
+          glEnd;
+
+          glDisable(GL_TEXTURE_2D);
+          glDisable(GL_BLEND);
+
+          // set font style and size
+          SetFontStyle(aPositions[PIndex].PUFont);
+          SetFontItalic(false);
+          SetFontSize(FontSize);
+          SetFontReflection(false, 0);
+
+          // draw text
+          TextLen := glTextWidth(Theme.Sing.LineBonusText[PopUp.Rating]);
+
+          // color and pos
+          SetFontPos (X + (W - TextLen) / 2, Y + FontOffset);
+          glColor4f(1, 1, 1, Alpha);
+
+          // draw
+          glPrint(Theme.Sing.LineBonusText[PopUp.Rating]);
+        end; // eo alpha check
+      end; // eo right screen
+    end; // eo player has position
+  end
+  else
+    Log.LogError('TSingScores: Try to draw a non-existing popup');
+end;
+
+{**
+ * draws a score by playerindex
+ *}
+procedure TSingScores.DrawScore(const Index: integer);
+var
+  Position: PScorePosition;
+  ScoreStr: String;
+begin
+  // only draw if player has a position
+  if Players[Index].Position <> High(byte) then
+  begin
+    // only draw if player is on cur screen
+    if (((Players[Index].Position and 128) = 0) = (ScreenAct = 1)) and Players[Index].Visible then
+    begin
+      Position := @aPositions[Players[Index].Position and 127];
+
+      // draw scorebg
+      glEnable(GL_TEXTURE_2D);
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+      glColor4f(1,1,1, 1);
+      glBindTexture(GL_TEXTURE_2D, Players[Index].ScoreBG.TexNum);
+
+      glBegin(GL_QUADS);
+        glTexCoord2f(0, 0); glVertex2f(Position.BGX, Position.BGY);
+        glTexCoord2f(0, Players[Index].ScoreBG.TexH); glVertex2f(Position.BGX, Position.BGY + Position.BGH);
+        glTexCoord2f(Players[Index].ScoreBG.TexW, Players[Index].ScoreBG.TexH); glVertex2f(Position.BGX + Position.BGW, Position.BGY + Position.BGH);
+        glTexCoord2f(Players[Index].ScoreBG.TexW, 0); glVertex2f(Position.BGX + Position.BGW, Position.BGY);
+      glEnd;
+
+      glDisable(GL_TEXTURE_2D);
+      glDisable(GL_BLEND);
+
+      // draw score text
+      SetFontStyle(Position.TextFont);
+      SetFontItalic(false);
+      SetFontSize(Position.TextSize);
+      SetFontPos(Position.TextX, Position.TextY);
+      SetFontReflection(false, 0);
+
+      ScoreStr := InttoStr(Players[Index].ScoreDisplayed div 10) + '0';
+      while (Length(ScoreStr) < 5) do
+        ScoreStr := '0' + ScoreStr;
+
+      glPrint(ScoreStr);
+
+    end; // eo right screen
+  end; // eo player has position
+end;
+
+
+procedure TSingScores.DrawRatingBar(const Index: integer);
+var
+  Position:   PScorePosition;
+  R, G, B:    real;
+  Size, Diff: real;
+begin
+  // only draw if player has a position
+  if Players[Index].Position <> High(byte) then
+  begin
+    // only draw if player is on cur screen
+    if (((Players[Index].Position and 128) = 0) = (ScreenAct = 1) and
+        Players[index].RBVisible and
+        Players[index].Visible) then
+    begin
+      Position := @aPositions[Players[Index].Position and 127];
+
+      if (Enabled and Players[Index].Enabled) then
+      begin
+        // move position if enabled
+        Diff := Players[Index].RBTarget - Players[Index].RBPos;
+        if (Abs(Diff) < 0.02) then
+          aPlayers[Index].RBPos := aPlayers[Index].RBTarget
+        else
+          aPlayers[Index].RBPos := aPlayers[Index].RBPos + Diff*0.1;
+      end;
+
+      // get colors for rating bar
+      if (Players[index].RBPos <= 0.22) then
+      begin
+        R := 1;
+        G := 0;
+        B := 0;
+      end
+      else if (Players[index].RBPos <= 0.42) then
+      begin
+        R := 1;
+        G := Players[index].RBPos * 5;
+        B := 0;
+      end
+      else if (Players[index].RBPos <= 0.57) then
+      begin
+        R := 1;
+        G := 1;
+        B := 0;
+      end
+      else if (Players[index].RBPos <= 0.77) then
+      begin
+        R := 1 - (Players[index].RBPos - 0.57) * 5;
+        G := 1;
+        B := 0;
+      end
+      else
+      begin
+        R := 0;
+        G := 1;
+        B := 0;
+      end;
+
+      // enable all glfuncs needed
+      glEnable(GL_TEXTURE_2D);
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+      // draw rating bar bg
+      glColor4f(1, 1, 1, 0.8);
+      glBindTexture(GL_TEXTURE_2D, Settings.RatingBar_BG_Tex.TexNum);
+
+      glBegin(GL_QUADS);
+        glTexCoord2f(0, 0);
+        glVertex2f(Position.RBX, Position.RBY);
+
+        glTexCoord2f(0, Settings.RatingBar_BG_Tex.TexH);
+        glVertex2f(Position.RBX, Position.RBY+Position.RBH);
+
+        glTexCoord2f(Settings.RatingBar_BG_Tex.TexW, Settings.RatingBar_BG_Tex.TexH);
+        glVertex2f(Position.RBX+Position.RBW, Position.RBY+Position.RBH);
+
+        glTexCoord2f(Settings.RatingBar_BG_Tex.TexW, 0);
+        glVertex2f(Position.RBX+Position.RBW, Position.RBY);
+      glEnd;
+
+      // draw rating bar itself
+      Size := Position.RBX + Position.RBW * Players[Index].RBPos;
+      glColor4f(R, G, B, 1);
+      glBindTexture(GL_TEXTURE_2D, Settings.RatingBar_Bar_Tex.TexNum);
+      glBegin(GL_QUADS);
+        glTexCoord2f(0, 0);
+        glVertex2f(Position.RBX, Position.RBY);
+
+        glTexCoord2f(0, Settings.RatingBar_Bar_Tex.TexH);
+        glVertex2f(Position.RBX, Position.RBY + Position.RBH);
+
+        glTexCoord2f(Settings.RatingBar_Bar_Tex.TexW, Settings.RatingBar_Bar_Tex.TexH);
+        glVertex2f(Size, Position.RBY + Position.RBH);
+
+        glTexCoord2f(Settings.RatingBar_Bar_Tex.TexW, 0);
+        glVertex2f(Size, Position.RBY);
+      glEnd;
+
+      // draw rating bar fg (the thing with the 3 lines to get better readability)
+      glColor4f(1, 1, 1, 0.6);
+      glBindTexture(GL_TEXTURE_2D, Settings.RatingBar_FG_Tex.TexNum);
+      glBegin(GL_QUADS);
+        glTexCoord2f(0, 0);
+        glVertex2f(Position.RBX, Position.RBY);
+
+        glTexCoord2f(0, Settings.RatingBar_FG_Tex.TexH);
+        glVertex2f(Position.RBX, Position.RBY + Position.RBH);
+
+        glTexCoord2f(Settings.RatingBar_FG_Tex.TexW, Settings.RatingBar_FG_Tex.TexH);
+        glVertex2f(Position.RBX + Position.RBW, Position.RBY + Position.RBH);
+
+        glTexCoord2f(Settings.RatingBar_FG_Tex.TexW, 0);
+        glVertex2f(Position.RBX + Position.RBW, Position.RBY);
+      glEnd;
+
+      // disable all enabled glfuncs
+      glDisable(GL_TEXTURE_2D);
+      glDisable(GL_BLEND);
+    end; // eo Right Screen
+  end; // eo Player has Position
+end;
+
+end.
diff --git a/songmanagement/src/base/USkins.pas b/songmanagement/src/base/USkins.pas
new file mode 100644
index 00000000..a909b081
--- /dev/null
+++ b/songmanagement/src/base/USkins.pas
@@ -0,0 +1,248 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit USkins;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UPath,
+  UCommon;
+
+type
+  TSkinTexture = record
+    Name:     string;
+    FileName: IPath;
+  end;
+
+  TSkinEntry = record
+    Theme:    string;
+    Name:     string;
+    Path:     IPath;
+    FileName: IPath;
+
+    DefaultColor: integer;
+    Creator:  string; // not used yet
+  end;
+
+  TSkin = class
+    Skin:        array of TSkinEntry;
+    SkinTexture: array of TSkinTexture;
+    SkinPath:    IPath;
+    Color:       integer;
+    constructor Create;
+    procedure LoadList;
+    procedure ParseDir(Dir: IPath);
+    procedure LoadHeader(FileName: IPath);
+    procedure LoadSkin(Name: string);
+    function GetTextureFileName(TextureName: string): IPath;
+    function GetSkinNumber(Name: string): integer;
+    function GetDefaultColor(SkinNo: integer): integer;
+
+    procedure GetSkinsByTheme(Theme: string; out Skins: TUTF8StringDynArray);
+
+    procedure onThemeChange;
+  end;
+
+var
+  Skin: TSkin;
+
+implementation
+
+uses
+  IniFiles,
+  Classes,
+  SysUtils,
+  Math,
+  UIni,
+  ULog,
+  UMain,
+  UPathUtils,
+  UFileSystem;
+
+constructor TSkin.Create;
+begin
+  inherited;
+  LoadList;
+//  LoadSkin('...');
+//  SkinColor := Color;
+end;
+
+procedure TSkin.LoadList;
+var
+  Iter: IFileIterator;
+  DirInfo: TFileInfo;
+begin
+  Iter := FileSystem.FileFind(SkinsPath.Append('*'), faDirectory);
+  while Iter.HasNext do
+  begin
+    DirInfo := Iter.Next();
+    if (not DirInfo.Name.Equals('.')) and (not DirInfo.Name.Equals('..')) then
+      ParseDir(SkinsPath.Append(DirInfo.Name, pdAppend));
+  end;
+end;
+
+procedure TSkin.ParseDir(Dir: IPath);
+var
+  Iter: IFileIterator;
+  IniInfo: TFileInfo;
+begin
+  Iter := FileSystem.FileFind(Dir.Append('*.ini'), 0);
+  while Iter.HasNext do
+  begin
+    IniInfo := Iter.Next;
+    LoadHeader(Dir.Append(IniInfo.Name));
+  end;
+end;
+
+procedure TSkin.LoadHeader(FileName: IPath);
+var
+  SkinIni: TMemIniFile;
+  S:       integer;
+begin
+  SkinIni := TMemIniFile.Create(FileName.ToNative);
+
+  S := Length(Skin);
+  SetLength(Skin, S+1);
+  
+  Skin[S].Path     := FileName.GetPath;
+  Skin[S].FileName := FileName.GetName;
+  Skin[S].Theme    := SkinIni.ReadString('Skin', 'Theme', '');
+  Skin[S].Name     := SkinIni.ReadString('Skin', 'Name', '');
+  Skin[S].Creator  := SkinIni.ReadString('Skin', 'Creator', '');
+  Skin[S].DefaultColor := Max(0, GetArrayIndex(IColor, SkinIni.ReadString('Skin', 'Color', ''), true));
+
+  SkinIni.Free;
+end;
+
+procedure TSkin.LoadSkin(Name: string);
+var
+  SkinIni: TMemIniFile;
+  SL:      TStringList;
+  T:       integer;
+  S:       integer;
+begin
+  S        := GetSkinNumber(Name);
+  SkinPath := Skin[S].Path;
+
+  SkinIni  := TMemIniFile.Create(SkinPath.Append(Skin[S].FileName).ToNative);
+
+  SL := TStringList.Create;
+  SkinIni.ReadSection('Textures', SL);
+
+  SetLength(SkinTexture, SL.Count);
+  for T := 0 to SL.Count-1 do
+  begin
+    SkinTexture[T].Name     := SL.Strings[T];
+    SkinTexture[T].FileName := Path(SkinIni.ReadString('Textures', SL.Strings[T], ''));
+  end;
+
+  SL.Free;
+  SkinIni.Free;
+end;
+
+function TSkin.GetTextureFileName(TextureName: string): IPath;
+var
+  T: integer;
+begin
+  Result := PATH_NONE;
+  
+  for T := 0 to High(SkinTexture) do
+  begin
+    if (SkinTexture[T].Name = TextureName) and
+       (SkinTexture[T].FileName.IsSet) then
+    begin
+      Result := SkinPath.Append(SkinTexture[T].FileName);
+    end;
+  end;
+
+  if (TextureName <> '') and (Result.IsSet) then
+  begin
+    //Log.LogError('', '-----------------------------------------');
+    //Log.LogError(TextureName+' - '+ Result, 'TSkin.GetTextureFileName');
+  end;
+end;
+
+function TSkin.GetSkinNumber(Name: string): integer;
+var
+  S: integer;
+begin
+  Result := 0; // set default to the first available skin
+  for S := 0 to High(Skin) do
+    if CompareText(Skin[S].Name, Name) = 0 then
+      Result := S;
+end;
+
+procedure TSkin.GetSkinsByTheme(Theme: string; out Skins: TUTF8StringDynArray);
+  var
+    I: Integer;
+    Len: integer;
+begin
+  SetLength(Skins, 0);
+  Len := 0;
+
+  for I := 0 to High(Skin) do
+    if CompareText(Theme, Skin[I].Theme) = 0 then
+    begin
+      SetLength(Skins, Len + 1);
+      Skins[Len] := Skin[I].Name;
+      Inc(Len);
+    end;
+end;
+
+{ returns number of default color for skin with
+  index SkinNo in ISkin (not in the actual skin array) }
+function TSkin.GetDefaultColor(SkinNo: integer): integer;
+  var
+    I: Integer;
+begin
+  Result := 0;
+
+  for I := 0 to High(Skin) do
+    if CompareText(ITheme[Ini.Theme], Skin[I].Theme) = 0 then
+    begin
+      if SkinNo > 0 then
+        Dec(SkinNo)
+      else
+      begin
+        Result := Skin[I].DefaultColor;
+        Break;
+      end;
+    end;
+end;
+
+procedure TSkin.onThemeChange;
+begin
+  Ini.SkinNo:=0;
+  GetSkinsByTheme(ITheme[Ini.Theme], ISkin);
+end;
+
+end.
diff --git a/songmanagement/src/base/USong.pas b/songmanagement/src/base/USong.pas
new file mode 100644
index 00000000..e92c5b45
--- /dev/null
+++ b/songmanagement/src/base/USong.pas
@@ -0,0 +1,1303 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit USong;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  {$IFDEF MSWINDOWS}
+    Windows,
+  {$ELSE}
+    {$IFNDEF DARWIN}
+      syscall,
+    {$ENDIF}
+    baseunix,
+    UnixType,
+  {$ENDIF}
+  SysUtils,
+  Classes,
+  UPlatform,
+  ULog,
+  UTexture,
+  UCommon,
+  {$IFDEF DARWIN}
+    cthreads,
+  {$ENDIF}
+  {$IFDEF USE_PSEUDO_THREAD}
+    PseudoThread,
+  {$ENDIF}
+  UCatCovers,
+  UXMLSong,
+  UUnicodeUtils,
+  UTextEncoding,
+  UFilesystem,
+  UPath;
+
+type
+
+  TSingMode = ( smNormal, smPartyMode, smPlaylistRandom );
+
+  TBPM = record
+    BPM:        real;
+    StartBeat:  real;
+  end;
+
+  TScore = record
+    Name:       UTF8String;
+    Score:      integer;
+    Date:       UTF8String;
+  end;
+
+  { used to hold header tags that are not supported by this version of
+    usdx (e.g. some tags from ultrastar 0.7.0) when songs are loaded in
+    songeditor. They will be written the end of the song header }
+  TCustomHeaderTag = record
+    Tag: UTF8String;
+    Content: UTF8String;
+  end;
+
+  TSong = class
+  private
+    FileLineNo  : integer;  // line, which is read last, for error reporting
+
+    function DecodeFilename(Filename: RawByteString): IPath;
+    procedure ParseNote(LineNumber: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: UTF8String);
+    procedure NewSentence(LineNumberP: integer; Param1, Param2: integer);
+
+    function ParseLyricStringParam(const Line: RawByteString; var LinePos: integer): RawByteString;
+    function ParseLyricIntParam(const Line: RawByteString; var LinePos: integer): integer;
+    function ParseLyricFloatParam(const Line: RawByteString; var LinePos: integer): extended;
+    function ParseLyricCharParam(const Line: RawByteString; var LinePos: integer): AnsiChar;
+    function ParseLyricText(const Line: RawByteString; var LinePos: integer): RawByteString;
+
+    function ReadTXTHeader(SongFile: TTextFileStream; ReadCustomTags: Boolean): boolean;
+    function ReadXMLHeader(const aFileName: IPath): boolean;
+
+    function GetFolderCategory(const aFileName: IPath): UTF8String;
+    function FindSongFile(Dir: IPath; Mask: UTF8String): IPath;
+  public
+    Path:         IPath; // kust path component of file (only set if file was found)
+    Folder:       UTF8String; // for sorting by folder (only set if file was found)
+    FileName:     IPath; // just name component of file (only set if file was found)
+
+    // filenames
+    Cover:      IPath;
+    Mp3:        IPath;
+    Background: IPath;
+    Video:      IPath;
+
+    // sorting methods
+    Genre:      UTF8String;
+    Edition:    UTF8String;
+    Language:   UTF8String;
+    Year:       Integer;
+
+    Title:      UTF8String;
+    Artist:     UTF8String;
+
+    Creator:    UTF8String;
+
+    CoverTex:   TTexture;
+
+    VideoGAP:   real;
+    NotesGAP:   integer;
+    Start:      real; // in seconds
+    Finish:     integer; // in miliseconds
+    Relative:   boolean;
+    Resolution: integer;
+    BPM:        array of TBPM;
+    GAP:        real; // in miliseconds
+
+    Encoding:   TEncoding;
+
+    CustomTags: array of TCustomHeaderTag;
+
+    Score:      array[0..2] of array of TScore;
+
+    // these are used when sorting is enabled
+    Visible:    boolean; // false if hidden, true if visible
+    Main:       boolean; // false for songs, true for category buttons
+    OrderNum:   integer; // has a number of category for category buttons and songs
+    OrderTyp:   integer; // type of sorting for this button (0=name)
+    CatNumber:  integer; // Count of Songs in Category for Cats and Number of Song in Category for Songs
+
+    Base    : array[0..1] of integer;
+    Rel     : array[0..1] of integer;
+    Mult    : integer;
+    MultBPM : integer;
+
+    LastError: AnsiString;
+    function  GetErrorLineNo: integer;
+    property  ErrorLineNo: integer read GetErrorLineNo;
+
+
+    constructor Create(); overload;
+    constructor Create(const aFileName : IPath); overload;
+    function    LoadSong: boolean;
+    function    LoadXMLSong: boolean;
+    function    Analyse(const ReadCustomTags: Boolean = false): boolean;
+    function    AnalyseXML(): boolean;
+    procedure   Clear();
+  end;
+
+implementation
+
+uses
+  StrUtils,
+  TextGL,
+  UIni,
+  UPathUtils,
+  UMusic,  //needed for Lines
+  UNote;   //needed for Player
+
+constructor TSong.Create();
+begin
+  inherited;
+
+  // to-do : special create for category "songs"
+  //dirty fix to fix folders=on
+  Self.Path     := PATH_NONE();
+  Self.FileName := PATH_NONE();
+  Self.Cover    := PATH_NONE();
+  Self.Mp3      := PATH_NONE();
+  Self.Background:= PATH_NONE();
+  Self.Video    := PATH_NONE();
+end;
+
+// This may be changed, when we rewrite song select code.
+// it is some kind of dirty, but imho the best possible
+// solution as we do atm not support nested categorys.
+// it works like the folder sorting in 1.0.1a
+// folder is set to the first folder under the songdir
+// so songs ~/.ultrastardx/songs/punk is in the same
+// category as songs in shared/ultrastardx/songs are.
+// note: folder is just the name of a category it has
+//       nothing to do with the path used for file loading
+function TSong.GetFolderCategory(const aFileName: IPath): UTF8String;
+var
+  I: Integer;
+  CurSongPath: IPath;
+  CurSongPathRel: IPath;
+begin
+  Result := 'Unknown'; //default folder category, if we can't locate the song dir
+
+  for I := 0 to SongPaths.Count-1 do
+  begin
+    CurSongPath := SongPaths[I] as IPath;
+    if (aFileName.IsChildOf(CurSongPath, false)) then
+    begin
+      if (aFileName.IsChildOf(CurSongPath, true)) then
+      begin
+        // songs are in the "root" of the songdir => use songdir for the categorys name
+        Result := CurSongPath.RemovePathDelim.ToUTF8;
+      end
+      else
+      begin
+        // use the first subdirectory below CurSongPath as the category name
+        CurSongPathRel := aFileName.GetRelativePath(CurSongPath.AppendPathDelim);
+        Result := CurSongPathRel.SplitDirs[0].RemovePathDelim.ToUTF8;
+      end;
+      Exit;
+    end;
+  end;
+end;
+
+constructor TSong.Create(const aFileName: IPath);
+begin
+  inherited Create();
+
+  Mult    := 1;
+  MultBPM := 4;
+
+  LastError := '';
+
+  Self.Path     := aFileName.GetPath;
+  Self.FileName := aFileName.GetName;
+  Self.Folder   := GetFolderCategory(aFileName);
+
+  (*
+  if (aFileName.IsFile) then
+  begin
+    if ReadTXTHeader(aFileName) then
+    begin
+      LoadSong();
+    end
+    else
+    begin
+      Log.LogError('Error Loading SongHeader, abort Song Loading');
+      Exit;
+    end;
+  end;
+  *)
+end;
+
+function TSong.FindSongFile(Dir: IPath; Mask: UTF8String): IPath;
+var
+  Iter: IFileIterator;
+  FileInfo: TFileInfo;
+  FileName: IPath;
+begin
+  Iter := FileSystem.FileFind(Dir.Append(Mask), faDirectory);
+  if (Iter.HasNext) then
+    Result := Iter.Next.Name
+  else
+    Result := PATH_NONE;
+end;
+
+function TSong.DecodeFilename(Filename: RawByteString): IPath;
+begin
+  Result := UPath.Path(DecodeStringUTF8(Filename, Encoding));
+end;
+
+type
+  EUSDXParseException = class(Exception);
+
+{**
+ * Parses the Line string starting from LinePos for a parameter.
+ * Leading whitespace is trimmed, same applies to the first trailing whitespace.
+ * After the call LinePos will point to the position after the first trailing
+ * whitespace.
+ *
+ * Raises an EUSDXParseException if no string was found.
+ *
+ * Example:
+ *   ParseLyricParam(Line:'Param0  Param1 Param2', LinePos:8, ...)
+ *   -> Param:'Param1', LinePos:16 (= start of 'Param2')
+ *}
+function TSong.ParseLyricStringParam(const Line: RawByteString; var LinePos: integer): RawByteString;
+var
+  Start: integer;
+  OldLinePos: integer;
+const
+  Whitespace = [#9, ' '];
+begin
+  OldLinePos := LinePos;
+
+  Start := 0;
+  while (LinePos <= Length(Line)) do
+  begin
+    if (Line[LinePos] in Whitespace) then
+    begin
+      // check for end of param
+      if (Start > 0) then
+        Break;
+    end
+    // check for beginning of param
+    else if (Start = 0) then
+    begin
+      Start := LinePos;
+    end;
+    Inc(LinePos);
+  end;
+
+  // check if param was found
+  if (Start = 0) then
+  begin
+    LinePos := OldLinePos;
+    raise EUSDXParseException.Create('String expected');
+  end
+  else
+  begin
+    // copy param without trailing whitespace
+    Result := Copy(Line, Start, LinePos-Start);
+    // skip first trailing whitespace (if not at EOL)
+    if (LinePos <= Length(Line)) then
+      Inc(LinePos);
+  end;
+end;
+
+function TSong.ParseLyricIntParam(const Line: RawByteString; var LinePos: integer): integer;
+var
+  Str: RawByteString;
+  OldLinePos: integer;
+begin
+  OldLinePos := LinePos;
+  Str := ParseLyricStringParam(Line, LinePos);
+
+  if not TryStrToInt(Str, Result) then
+  begin // on convert error
+    Result := 0;
+    LinePos := OldLinePos;
+    raise EUSDXParseException.Create('Integer expected');
+  end;
+end;
+
+function TSong.ParseLyricFloatParam(const Line: RawByteString; var LinePos: integer): extended;
+var
+  Str: RawByteString;
+  OldLinePos: integer;
+begin
+  OldLinePos := LinePos;
+  Str := ParseLyricStringParam(Line, LinePos);
+
+  if not TryStrToFloat(Str, Result) then
+  begin // on convert error
+    Result := 0;
+    LinePos := OldLinePos;
+    raise EUSDXParseException.Create('Float expected');
+  end;
+end;
+
+function TSong.ParseLyricCharParam(const Line: RawByteString; var LinePos: integer): AnsiChar;
+var
+  Str: RawByteString;
+  OldLinePos: integer;
+begin
+  OldLinePos := LinePos;
+  Str := ParseLyricStringParam(Line, LinePos);
+  
+  if (Length(Str) < 1) then
+  begin
+    LinePos := OldLinePos;
+    raise EUSDXParseException.Create('Character expected');
+  end
+  else if (Length(Str) > 1) then
+  begin
+    Log.LogWarn(Format('"%s" in line %d: %s',
+        [FileName.ToNative, FileLineNo, 'character expected but found "' + Str + '"']),
+        'TSong.ParseLyricCharParam');
+  end;
+       
+  LinePos := OldLinePos + 1;
+  Result := Str[1];
+end;
+
+{**
+ * Returns the rest of the line from LinePos as lyric text.
+ * Leading and trailing whitespace is not trimmed.
+ *}
+function TSong.ParseLyricText(const Line: RawByteString; var LinePos: integer): RawByteString;
+begin
+  if (LinePos > Length(Line)) then
+    Result := ''
+  else
+  begin
+    Result := Copy(Line, LinePos, Length(Line)-LinePos+1);
+    LinePos := Length(Line)+1;
+  end;
+end;
+
+//Load TXT Song
+function TSong.LoadSong(): boolean;
+var
+  CurLine: RawByteString;
+  LinePos:  integer;
+  Count:    integer;
+  Both:     boolean;
+
+  Param0:    AnsiChar;
+  Param1:    integer;
+  Param2:    integer;
+  Param3:    integer;
+  ParamLyric: UTF8String;
+
+  I:        integer;
+  NotesFound: boolean;
+  SongFile: TTextFileStream;
+  FileNamePath: IPath;
+begin
+  Result := false;
+  LastError := '';
+
+  FileNamePath := Path.Append(FileName);
+  if not FileNamePath.IsFile() then
+  begin
+    LastError := 'ERROR_CORRUPT_SONG_FILE_NOT_FOUND';
+    Log.LogError('File not found: "' + FileNamePath.ToNative + '"', 'TSong.LoadSong()');
+    Exit;
+  end;
+
+  MultBPM           := 4; // multiply beat-count of note by 4
+  Mult              := 1; // accuracy of measurement of note
+  Rel[0]            := 0;
+  Both              := false;
+
+  if Length(Player) = 2 then
+    Both := true;
+
+  try
+    // Open song file for reading.....
+    SongFile := TMemTextFileStream.Create(FileNamePath, fmOpenRead);
+    try
+      //Search for Note Beginning
+      FileLineNo := 0;
+      NotesFound := false;
+      while (SongFile.ReadLine(CurLine)) do
+      begin
+        Inc(FileLineNo);
+        if (Length(CurLine) > 0) and (CurLine[1] in [':', 'F', '*']) then
+        begin
+          NotesFound := true;
+          Break;
+        end;
+      end;
+
+      if (not NotesFound) then
+      begin //Song File Corrupted - No Notes
+        Log.LogError('Could not load txt File, no notes found: ' + FileNamePath.ToNative);
+        LastError := 'ERROR_CORRUPT_SONG_NO_NOTES';
+        Exit;
+      end;
+
+      SetLength(Lines, 2);
+      for Count := 0 to High(Lines) do
+      begin
+        Lines[Count].High := 0;
+        Lines[Count].Number := 1;
+        Lines[Count].Current := 0;
+        Lines[Count].Resolution := self.Resolution;
+        Lines[Count].NotesGAP   := self.NotesGAP;
+        Lines[Count].ScoreValue := 0;
+
+        //Add first line and set some standard values to fields
+        //see procedure NewSentence for further explantation
+        //concerning most of these values
+        SetLength(Lines[Count].Line, 1);
+        Lines[Count].Line[0].HighNote := -1;
+        Lines[Count].Line[0].LastLine := false;
+        Lines[Count].Line[0].BaseNote := High(Integer);
+        Lines[Count].Line[0].TotalNotes := 0;
+      end;
+
+      while true do
+      begin
+        LinePos := 1;
+
+        Param0 := ParseLyricCharParam(CurLine, LinePos);
+        if (Param0 = 'E') then
+        begin
+          Break
+        end
+        else if (Param0 in [':', '*', 'F']) then
+        begin
+          // read notes
+          Param1 := ParseLyricIntParam(CurLine, LinePos);
+          Param2 := ParseLyricIntParam(CurLine, LinePos);
+          Param3 := ParseLyricIntParam(CurLine, LinePos);
+          ParamLyric := ParseLyricText(CurLine, LinePos);
+
+          //Check for ZeroNote
+          if Param2 = 0 then
+          begin
+            Log.LogWarn(Format('"%s" in line %d: %s',
+              [FileNamePath.ToNative, FileLineNo,
+              'found note with length zero -> converted to FreeStyle']),
+              'TSong.LoadSong');
+            //Log.LogError('Found zero-length note at "'+Param0+' '+IntToStr(Param1)+' '+IntToStr(Param2)+' '+IntToStr(Param3)+ParamLyric+'" -> Note ignored!')
+            Param0 := 'F';
+          end;
+
+          // add notes
+          if not Both then
+            // P1
+            ParseNote(0, Param0, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamLyric)
+          else
+          begin
+            // P1 + P2
+            ParseNote(0, Param0, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamLyric);
+            ParseNote(1, Param0, (Param1+Rel[1]) * Mult, Param2 * Mult, Param3, ParamLyric);
+          end;
+        end // if
+
+        else if Param0 = '-' then
+        begin
+          // reads sentence
+          Param1 := ParseLyricIntParam(CurLine, LinePos);
+          if self.Relative then
+            Param2 := ParseLyricIntParam(CurLine, LinePos); // read one more data for relative system
+
+          // new sentence
+          if not Both then
+            // P1
+            NewSentence(0, (Param1 + Rel[0]) * Mult, Param2)
+          else
+          begin
+            // P1 + P2
+            NewSentence(0, (Param1 + Rel[0]) * Mult, Param2);
+            NewSentence(1, (Param1 + Rel[1]) * Mult, Param2);
+          end;
+        end // if
+
+        else if Param0 = 'B' then
+        begin
+          SetLength(self.BPM, Length(self.BPM) + 1);
+          self.BPM[High(self.BPM)].StartBeat := ParseLyricFloatParam(CurLine, LinePos);
+          self.BPM[High(self.BPM)].StartBeat := self.BPM[High(self.BPM)].StartBeat + Rel[0];
+
+          self.BPM[High(self.BPM)].BPM := ParseLyricFloatParam(CurLine, LinePos);
+          self.BPM[High(self.BPM)].BPM := self.BPM[High(self.BPM)].BPM * Mult * MultBPM;
+        end;
+
+        // Read next line in File
+        if (not SongFile.ReadLine(CurLine)) then
+          Break;
+
+        Inc(FileLineNo);
+      end; // while
+    finally
+      SongFile.Free;
+    end;
+  except
+    on E: Exception do
+    begin
+      Log.LogError(Format('Error loading file: "%s" in line %d,%d: %s',
+                  [FileNamePath.ToNative, FileLineNo, LinePos, E.Message]));
+      Exit;
+    end;
+  end;
+
+  for I := 0 to High(Lines) do
+  begin
+    if ((Both) or (I = 0)) then
+    begin
+      if (Length(Lines[I].Line) < 2) then
+      begin
+        LastError := 'ERROR_CORRUPT_SONG_NO_BREAKS';
+        Log.LogError('Error loading file: Can''t find any linebreaks in "' + FileNamePath.ToNative + '"');
+        exit;
+      end;
+
+      if (Lines[I].Line[Lines[I].High].HighNote < 0) then
+      begin
+        SetLength(Lines[I].Line, Lines[I].Number - 1);
+        Lines[I].High := Lines[I].High - 1;
+        Lines[I].Number := Lines[I].Number - 1;
+        Log.LogError('Error loading Song, sentence w/o note found in last line before E: ' + FileNamePath.ToNative);
+      end;
+    end;
+  end;
+
+  for Count := 0 to High(Lines) do
+  begin
+    if (High(Lines[Count].Line) >= 0) then
+      Lines[Count].Line[High(Lines[Count].Line)].LastLine := true;
+  end;
+
+  Result := true;
+end;
+
+//Load XML Song
+function TSong.LoadXMLSong(): boolean;
+var
+  Count:     integer;
+  Both:      boolean;
+  Param1:    integer;
+  Param2:    integer;
+  Param3:    integer;
+  ParamS:    string;
+  I, J:      integer;
+  NoteIndex: integer;
+
+  NoteType:  char;
+  SentenceEnd, Rest, Time: integer;
+  Parser: TParser;
+  FileNamePath: IPath;
+begin
+  Result := false;
+  LastError := '';
+
+  FileNamePath := Path.Append(FileName);
+  if not FileNamePath.IsFile() then
+  begin
+    Log.LogError('File not found: "' + FileNamePath.ToNative + '"', 'TSong.LoadSong()');
+    exit;
+  end;
+
+  MultBPM           := 4; // multiply beat-count of note by 4
+  Mult              := 1; // accuracy of measurement of note
+  Lines[0].ScoreValue := 0;
+  self.Relative     := false;
+  Rel[0]            := 0;
+  Both              := false;
+
+  if Length(Player) = 2 then
+    Both := true;
+
+  Parser := TParser.Create;
+  Parser.Settings.DashReplacement := '~';
+
+  for Count := 0 to High(Lines) do
+  begin
+    Lines[Count].High := 0;
+      Lines[Count].Number := 1;
+      Lines[Count].Current := 0;
+      Lines[Count].Resolution := self.Resolution;
+      Lines[Count].NotesGAP   := self.NotesGAP;
+      Lines[Count].ScoreValue := 0;
+
+      //Add first line and set some standard values to fields
+      //see procedure NewSentence for further explantation
+      //concerning most of these values
+      SetLength(Lines[Count].Line, 1);
+      Lines[Count].Line[0].HighNote := -1;
+      Lines[Count].Line[0].LastLine := false;
+      Lines[Count].Line[0].BaseNote := High(Integer);
+      Lines[Count].Line[0].TotalNotes := 0;
+  end;
+
+  //Try to Parse the Song
+
+  if Parser.ParseSong(FileNamePath) then
+  begin
+    //Writeln('XML Inputfile Parsed succesful');
+
+    //Start write parsed information to Song
+    //Notes Part
+    for I := 0 to High(Parser.SongInfo.Sentences) do
+    begin
+      //Add Notes
+      for J := 0 to High(Parser.SongInfo.Sentences[I].Notes) do
+      begin
+        case Parser.SongInfo.Sentences[I].Notes[J].NoteTyp of
+          NT_Normal:    NoteType := ':';
+          NT_Golden:    NoteType := '*';
+          NT_Freestyle: NoteType := 'F';
+        end;
+
+        Param1:=Parser.SongInfo.Sentences[I].Notes[J].Start;       //Note Start
+        Param2:=Parser.SongInfo.Sentences[I].Notes[J].Duration;    //Note Duration
+        Param3:=Parser.SongInfo.Sentences[I].Notes[J].Tone;        //Note Tone
+        ParamS:=' ' + Parser.SongInfo.Sentences[I].Notes[J].Lyric; //Note Lyric
+
+        if not Both then
+          // P1
+          ParseNote(0, NoteType, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamS)
+        else
+        begin
+          // P1 + P2
+          ParseNote(0, NoteType, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamS);
+          ParseNote(1, NoteType, (Param1+Rel[1]) * Mult, Param2 * Mult, Param3, ParamS);
+        end;
+
+      end; //J Forloop
+
+      //Add Sentence break
+      if (I < High(Parser.SongInfo.Sentences)) then
+      begin
+        SentenceEnd := Parser.SongInfo.Sentences[I].Notes[High(Parser.SongInfo.Sentences[I].Notes)].Start + Parser.SongInfo.Sentences[I].Notes[High(Parser.SongInfo.Sentences[I].Notes)].Duration;
+        Rest := Parser.SongInfo.Sentences[I+1].Notes[0].Start - SentenceEnd;
+
+        //Calculate Time
+        case Rest of
+          0, 1: Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start;
+          2:    Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start - 1;
+          3:    Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start - 2;
+          else
+            if (Rest >= 4) then
+              Time := SentenceEnd + 2
+            else //Sentence overlapping :/
+              Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start;
+        end;
+        // new sentence
+        if not Both then // P1
+          NewSentence(0, (Time + Rel[0]) * Mult, Param2)
+        else
+        begin // P1 + P2
+          NewSentence(0, (Time + Rel[0]) * Mult, Param2);
+          NewSentence(1, (Time + Rel[1]) * Mult, Param2);
+        end;
+
+      end;
+    end;
+    //End write parsed information to Song
+    Parser.Free;
+  end
+  else
+  begin
+    Log.LogError('Could not parse inputfile: ' + FileNamePath.ToNative);
+    exit;
+  end;
+
+  for Count := 0 to High(Lines) do
+  begin
+    Lines[Count].Line[High(Lines[Count].Line)].LastLine := true;
+  end;
+
+  Result := true;
+end;
+
+function TSong.ReadXMLHeader(const aFileName : IPath): boolean;
+var
+  Done        : byte;
+  Parser      : TParser;
+  FileNamePath: IPath;
+begin
+  Result := true;
+  Done   := 0;
+
+  //Parse XML
+  Parser := TParser.Create;
+  Parser.Settings.DashReplacement := '~';
+
+  FileNamePath := Self.Path.Append(Self.FileName);
+  if Parser.ParseSong(FileNamePath) then
+  begin
+    //-----------
+    //Required Attributes
+    //-----------
+
+    //Title
+    self.Title := Parser.SongInfo.Header.Title;
+
+    //Add Title Flag to Done
+    Done := Done or 1;
+
+    //Artist
+    self.Artist := Parser.SongInfo.Header.Artist;
+
+    //Add Artist Flag to Done
+    Done := Done or 2;
+
+    //MP3 File //Test if Exists
+    Self.Mp3 := FindSongFile(Self.Path, '*.mp3');
+    //Add Mp3 Flag to Done
+    if (Self.Path.Append(Self.Mp3).IsFile()) then
+      Done := Done or 4;
+
+    //Beats per Minute
+    SetLength(self.BPM, 1);
+    self.BPM[0].StartBeat := 0;
+
+    self.BPM[0].BPM := (Parser.SongInfo.Header.BPM * Parser.SongInfo.Header.Resolution/4  ) * Mult * MultBPM;
+
+    //Add BPM Flag to Done
+    if self.BPM[0].BPM <> 0 then
+      Done := Done or 8;
+
+    //---------
+    //Additional Header Information
+    //---------
+
+    // Gap
+    self.GAP := Parser.SongInfo.Header.Gap;
+
+    //Cover Picture
+    self.Cover := FindSongFile(Path, '*[CO].jpg');
+
+    //Background Picture
+    self.Background := FindSongFile(Path, '*[BG].jpg');
+
+    // Video File
+    //    self.Video := Value
+
+    // Video Gap
+    //  self.VideoGAP := StrtoFloatI18n( Value )
+
+    //Genre Sorting
+    self.Genre := Parser.SongInfo.Header.Genre;
+
+    //Edition Sorting
+    self.Edition := Parser.SongInfo.Header.Edition;
+
+    //Year Sorting
+    //Parser.SongInfo.Header.Year
+
+    //Language Sorting
+    self.Language := Parser.SongInfo.Header.Language;
+  end
+  else
+    Log.LogError('File incomplete or not SingStar XML (A): ' + aFileName.ToNative);
+
+  Parser.Free;
+
+  //Check if all Required Values are given
+  if (Done <> 15) then
+  begin
+    Result := false;
+    if (Done and 8) = 0 then      //No BPM Flag
+      Log.LogError('BPM tag missing: ' + self.FileName.ToNative)
+    else if (Done and 4) = 0 then //No MP3 Flag
+      Log.LogError('MP3 tag/file missing: ' + self.FileName.ToNative)
+    else if (Done and 2) = 0 then //No Artist Flag
+      Log.LogError('Artist tag missing: ' + self.FileName.ToNative)
+    else if (Done and 1) = 0 then //No Title Flag
+      Log.LogError('Title tag missing: ' + self.FileName.ToNative)
+    else //unknown Error
+      Log.LogError('File incomplete or not SingStar XML (B - '+ inttostr(Done) +'): ' + aFileName.ToNative);
+  end;
+
+end;
+
+{**
+ * "International" StrToFloat variant. Uses either ',' or '.' as decimal
+ * separator.
+ *}
+function StrToFloatI18n(const Value: string): extended;
+var
+  TempValue : string;
+begin
+  TempValue := Value;
+  if (Pos(',', TempValue) <> 0) then
+    TempValue[Pos(',', TempValue)] := '.';
+  Result := StrToFloatDef(TempValue, 0);
+end;
+
+function TSong.ReadTXTHeader(SongFile: TTextFileStream; ReadCustomTags: Boolean): boolean;
+var
+  Line, Identifier: string;
+  Value: string;
+  SepPos: integer; // separator position
+  Done: byte;      // bit-vector of mandatory fields
+  EncFile: IPath; // encoded filename
+  FullFileName: string;
+
+  { adds a custom header tag to the song
+    if there is no ':' in the read line, Tag should be empty
+    and the whole line should be in Content }
+  procedure AddCustomTag(const Tag, Content: String);
+    var Len: Integer;
+  begin
+    if ReadCustomTags then
+    begin
+      Len := Length(CustomTags);
+      SetLength(CustomTags, Len + 1);
+      CustomTags[Len].Tag := DecodeStringUTF8(Tag, Encoding);
+      CustomTags[Len].Content := DecodeStringUTF8(Content, Encoding);
+    end;
+  end;
+begin
+  Result := true;
+  Done   := 0;
+
+  FullFileName := Path.Append(Filename).ToNative;
+
+  //Read first Line
+  SongFile.ReadLine(Line);
+  if (Length(Line) <= 0) then
+  begin
+    Log.LogError('File starts with empty line: ' + FullFileName,
+                 'TSong.ReadTXTHeader');
+    Result := false;
+    Exit;
+  end;
+
+  // check if file begins with a UTF-8 BOM, if so set encoding to UTF-8
+  if (CheckReplaceUTF8BOM(Line)) then
+    Encoding := encUTF8;
+
+  //Read Lines while Line starts with # or its empty
+  while (Length(Line) = 0) or (Line[1] = '#') do
+  begin
+    //Increase Line Number
+    Inc (FileLineNo);
+    SepPos := Pos(':', Line);
+
+    //Line has no Seperator, ignore non header field
+    if (SepPos = 0) then
+    begin
+      AddCustomTag('', Copy(Line, 2, Length(Line) - 1));
+      // read next line
+      if (not SongFile.ReadLine(Line)) then
+      begin
+        Result := false;
+        Log.LogError('File incomplete or not Ultrastar txt (A): ' + FullFileName);
+        Break;
+      end;
+      Continue;
+    end;
+
+    //Read Identifier and Value
+    Identifier  := UpperCase(Trim(Copy(Line, 2, SepPos - 2))); //Uppercase is for Case Insensitive Checks
+    Value       := Trim(Copy(Line, SepPos + 1, Length(Line) - SepPos));
+
+    //Check the Identifier (If Value is given)
+    if (Length(Value) = 0) then
+    begin
+      Log.LogInfo('Empty field "'+Identifier+'" in file ' + FullFileName,
+                   'TSong.ReadTXTHeader');
+      AddCustomTag(Identifier, '');
+    end
+    else
+    begin
+
+      //-----------
+      //Required Attributes
+      //-----------
+
+      if (Identifier = 'TITLE') then
+      begin
+        DecodeStringUTF8(Value, Title, Encoding);
+        //Add Title Flag to Done
+        Done := Done or 1;
+      end
+
+      else if (Identifier = 'ARTIST') then
+      begin
+        DecodeStringUTF8(Value, Artist, Encoding);
+        //Add Artist Flag to Done
+        Done := Done or 2;
+      end
+
+      //MP3 File
+      else if (Identifier = 'MP3') then
+      begin
+        EncFile := DecodeFilename(Value);
+        if (Self.Path.Append(EncFile).IsFile) then
+        begin
+          self.Mp3 := EncFile;
+
+          //Add Mp3 Flag to Done
+          Done := Done or 4;
+        end;
+      end
+
+      //Beats per Minute
+      else if (Identifier = 'BPM') then
+      begin
+        SetLength(self.BPM, 1);
+        self.BPM[0].StartBeat := 0;
+
+        self.BPM[0].BPM := StrToFloatI18n( Value ) * Mult * MultBPM;
+
+        if self.BPM[0].BPM <> 0 then
+        begin
+          //Add BPM Flag to Done
+          Done := Done or 8;
+        end;
+      end
+
+      //---------
+      //Additional Header Information
+      //---------
+
+      // Gap
+      else if (Identifier = 'GAP') then
+      begin
+        self.GAP := StrToFloatI18n(Value);
+      end
+
+      //Cover Picture
+      else if (Identifier = 'COVER') then
+      begin
+        self.Cover := DecodeFilename(Value);
+      end
+
+      //Background Picture
+      else if (Identifier = 'BACKGROUND') then
+      begin
+        self.Background := DecodeFilename(Value);
+      end
+
+      // Video File
+      else if (Identifier = 'VIDEO') then
+      begin
+        EncFile := DecodeFilename(Value);
+        if (self.Path.Append(EncFile).IsFile) then
+          self.Video := EncFile
+        else
+          Log.LogError('Can''t find video file in song: ' + FullFileName);
+      end
+
+      // Video Gap
+      else if (Identifier = 'VIDEOGAP') then
+      begin
+        self.VideoGAP := StrToFloatI18n( Value )
+      end
+
+      //Genre Sorting
+      else if (Identifier = 'GENRE') then
+      begin
+        DecodeStringUTF8(Value, Genre, Encoding)
+      end
+
+      //Edition Sorting
+      else if (Identifier = 'EDITION') then
+      begin
+        DecodeStringUTF8(Value, Edition, Encoding)
+      end
+
+      //Creator Tag
+      else if (Identifier = 'CREATOR') then
+      begin
+        DecodeStringUTF8(Value, Creator, Encoding)
+      end
+
+      //Language Sorting
+      else if (Identifier = 'LANGUAGE') then
+      begin
+        DecodeStringUTF8(Value, Language, Encoding)
+      end
+
+      //Language Sorting
+      else if (Identifier = 'YEAR') then
+      begin
+        TryStrtoInt(Value, self.Year)
+      end
+
+      // Song Start
+      else if (Identifier = 'START') then
+      begin
+        self.Start := StrToFloatI18n( Value )
+      end
+
+      // Song Ending
+      else if (Identifier = 'END') then
+      begin
+        TryStrtoInt(Value, self.Finish)
+      end
+
+      // Resolution
+      else if (Identifier = 'RESOLUTION') then
+      begin
+        TryStrtoInt(Value, self.Resolution)
+      end
+
+      // Notes Gap
+      else if (Identifier = 'NOTESGAP') then
+      begin
+        TryStrtoInt(Value, self.NotesGAP)
+      end
+
+      // Relative Notes
+      else if (Identifier = 'RELATIVE') then
+      begin
+        if (UpperCase(Value) = 'YES') then
+          self.Relative := true;
+      end
+
+      // File encoding
+      else if (Identifier = 'ENCODING') then
+      begin
+        self.Encoding := ParseEncoding(Value, Ini.DefaultEncoding);
+      end
+
+      // unsupported tag
+      else
+      begin
+        AddCustomTag(Identifier, Value);
+      end;
+
+    end; // End check for non-empty Value
+
+    // read next line
+    if (not SongFile.ReadLine(Line)) then
+    begin
+      Result := false;
+      Log.LogError('File incomplete or not Ultrastar txt (A): ' + FullFileName);
+      Break;
+    end;
+  end; // while
+
+  if self.Cover.IsUnset then
+    self.Cover := FindSongFile(Path, '*[CO].jpg');
+
+  //Check if all Required Values are given
+  if (Done <> 15) then
+  begin
+    Result := false;
+    if (Done and 8) = 0 then      //No BPM Flag
+      Log.LogError('BPM tag missing: ' + FullFileName)
+    else if (Done and 4) = 0 then //No MP3 Flag
+      Log.LogError('MP3 tag/file missing: ' + FullFileName)
+    else if (Done and 2) = 0 then //No Artist Flag
+      Log.LogError('Artist tag missing: ' + FullFileName)
+    else if (Done and 1) = 0 then //No Title Flag
+      Log.LogError('Title tag missing: ' + FullFileName)
+    else //unknown Error
+      Log.LogError('File incomplete or not Ultrastar txt (B - '+ inttostr(Done) +'): ' + FullFileName);
+  end;
+end;
+
+function  TSong.GetErrorLineNo: integer;
+begin
+  if (LastError='ERROR_CORRUPT_SONG_ERROR_IN_LINE') then
+    Result := FileLineNo
+  else
+    Result := -1;
+end;
+
+procedure TSong.ParseNote(LineNumber: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: UTF8String);
+begin
+  with Lines[LineNumber].Line[Lines[LineNumber].High] do
+  begin
+    SetLength(Note, Length(Note) + 1);
+    HighNote := High(Note);
+
+    Note[HighNote].Start := StartP;
+    if HighNote = 0 then
+    begin
+      if Lines[LineNumber].Number = 1 then
+        Start := -100;
+        //Start := Note[HighNote].Start;
+    end;
+
+    Note[HighNote].Length := DurationP;
+
+    // back to the normal system with normal, golden and now freestyle notes
+    case TypeP of
+      'F':  Note[HighNote].NoteType := ntFreestyle;
+      ':':  Note[HighNote].NoteType := ntNormal;
+      '*':  Note[HighNote].NoteType := ntGolden;
+    end;
+
+    //add this notes value ("notes length" * "notes scorefactor") to the current songs entire value
+    Inc(Lines[LineNumber].ScoreValue, Note[HighNote].Length * ScoreFactor[Note[HighNote].NoteType]);
+
+    //and to the current lines entire value
+    Inc(TotalNotes, Note[HighNote].Length * ScoreFactor[Note[HighNote].NoteType]);
+
+
+    Note[HighNote].Tone := NoteP;
+
+    //if a note w/ a deeper pitch then the current basenote is found
+    //we replace the basenote w/ the current notes pitch
+    if Note[HighNote].Tone < BaseNote then
+      BaseNote := Note[HighNote].Tone;
+
+    Note[HighNote].Color := 1; // default color to 1 for editor
+
+    DecodeStringUTF8(LyricS, Note[HighNote].Text, Encoding);
+    Lyric := Lyric + Note[HighNote].Text;
+
+    End_ := Note[HighNote].Start + Note[HighNote].Length;
+  end; // with
+end;
+
+procedure TSong.NewSentence(LineNumberP: integer; Param1, Param2: integer);
+var
+  I: integer;
+begin
+
+  if (Lines[LineNumberP].Line[Lines[LineNumberP].High].HighNote  <> -1) then
+  begin //create a new line
+    SetLength(Lines[LineNumberP].Line, Lines[LineNumberP].Number + 1);
+    Inc(Lines[LineNumberP].High);
+    Inc(Lines[LineNumberP].Number);
+  end
+  else
+  begin //use old line if it there were no notes added since last call of NewSentence
+    Log.LogError('Error loading Song, sentence w/o note found in line ' +
+                 InttoStr(FileLineNo) + ': ' + Filename.ToNative);
+  end;
+
+  Lines[LineNumberP].Line[Lines[LineNumberP].High].HighNote := -1;
+
+  //set the current lines value to zero
+  //it will be incremented w/ the value of every added note
+  Lines[LineNumberP].Line[Lines[LineNumberP].High].TotalNotes := 0;
+
+  //basenote is the pitch of the deepest note, it is used for note drawing.
+  //if a note with a less value than the current sentences basenote is found,
+  //basenote will be set to this notes pitch. Therefore the initial value of
+  //this field has to be very high.
+  Lines[LineNumberP].Line[Lines[LineNumberP].High].BaseNote := High(Integer);
+
+
+  if self.Relative then
+  begin
+    Lines[LineNumberP].Line[Lines[LineNumberP].High].Start := Param1;
+    Rel[LineNumberP] := Rel[LineNumberP] + Param2;
+  end
+  else
+    Lines[LineNumberP].Line[Lines[LineNumberP].High].Start := Param1;
+
+  Lines[LineNumberP].Line[Lines[LineNumberP].High].LastLine := false;
+end;
+
+procedure TSong.Clear();
+begin
+  //Main Information
+  Title  := '';
+  Artist := '';
+
+  //Sortings:
+  Genre    := 'Unknown';
+  Edition  := 'Unknown';
+  Language := 'Unknown';
+  Year := 0;
+
+  // set to default encoding
+  Encoding := Ini.DefaultEncoding;
+
+  // clear custom header tags
+  SetLength(CustomTags, 0);
+
+  //Required Information
+  Mp3    := PATH_NONE;
+  SetLength(BPM, 0);
+
+  GAP    := 0;
+  Start  := 0;
+  Finish := 0;
+
+  //Additional Information
+  Background := PATH_NONE;
+  Cover      := PATH_NONE;
+  Video      := PATH_NONE;
+  VideoGAP   := 0;
+  NotesGAP   := 0;
+  Resolution := 4;
+  Creator    := '';
+
+  Relative := false;
+end;
+
+function TSong.Analyse(const ReadCustomTags: Boolean): boolean;
+var
+  SongFile: TTextFileStream;
+begin
+  Result := false;
+
+  //Reset LineNo
+  FileLineNo := 0;
+
+  //Open File and set File Pointer to the beginning
+  SongFile := TMemTextFileStream.Create(Self.Path.Append(Self.FileName), fmOpenRead);
+  try
+    //Clear old Song Header
+    Self.clear;
+
+    //Read Header
+    Result := Self.ReadTxTHeader(SongFile, ReadCustomTags)
+  finally
+    SongFile.Free;
+  end;
+end;
+
+
+function TSong.AnalyseXML(): boolean;
+
+begin
+  Result := false;
+
+  //Reset LineNo
+  FileLineNo := 0;
+
+  //Clear old Song Header
+  self.clear;
+
+  //Read Header
+  Result := self.ReadXMLHeader( FileName );
+
+end;
+
+end.
diff --git a/songmanagement/src/base/USongs.pas b/songmanagement/src/base/USongs.pas
new file mode 100644
index 00000000..cfc32a99
--- /dev/null
+++ b/songmanagement/src/base/USongs.pas
@@ -0,0 +1,845 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit USongs;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+{$IFDEF DARWIN}
+  {$IFDEF DEBUG}
+    {$DEFINE USE_PSEUDO_THREAD}
+  {$ENDIF}
+{$ENDIF}
+
+uses
+  SysUtils,
+  Classes,
+  {$IFDEF MSWINDOWS}
+    Windows,
+    DirWatch,
+  {$ELSE}
+    {$IFNDEF DARWIN}
+    syscall,
+    {$ENDIF}
+    baseunix,
+    UnixType,
+  {$ENDIF}
+  UPlatform,
+  ULog,
+  UTexture,
+  UCommon,
+  {$IFDEF USE_PSEUDO_THREAD}
+  PseudoThread,
+  {$ENDIF}
+  UPath,
+  USong,
+  UIni,
+  UCatCovers;
+
+type
+  TSongFilter = (
+    fltAll,
+    fltTitle,
+    fltArtist
+  );
+
+  TBPM = record
+    BPM:       real;
+    StartBeat: real;
+  end;
+
+  TScore = record
+    Name:   UTF8String;
+    Score:  integer;
+    Length: string;
+  end;
+
+  TPathDynArray = array of IPath;
+
+  {$IFDEF USE_PSEUDO_THREAD}
+  TSongs = class(TPseudoThread)
+  {$ELSE}
+  TSongs = class(TThread)
+  {$ENDIF}
+  private
+    fNotify, fWatch:     longint;
+    fParseSongDirectory: boolean;
+    fProcessing:         boolean;
+    {$ifdef MSWINDOWS}
+    fDirWatch:           TDirectoryWatch;
+    {$endif}
+    procedure int_LoadSongList;
+    procedure DoDirChanged(Sender: TObject);
+  protected
+    procedure Execute; override;
+  public
+    SongList: TList;          // array of songs
+    Selected: integer;        // selected song index
+    constructor Create();
+    destructor  Destroy(); override;
+
+
+    procedure LoadSongList;     // load all songs
+    procedure FindFilesByExtension(const Dir: IPath; const Ext: IPath; Recursive: Boolean; var Files: TPathDynArray);
+    procedure BrowseDir(Dir: IPath); // should return number of songs in the future
+    procedure BrowseTXTFiles(Dir: IPath);
+    procedure BrowseXMLFiles(Dir: IPath);
+    procedure Sort(Order: TSortingType);
+    property  Processing: boolean read fProcessing;
+  end;
+
+
+  TCatSongs = class
+    Song:       array of TSong; // array of categories with songs
+    Selected:   integer; // selected song index
+    Order:      integer; // order type (0=title)
+    CatNumShow: integer; // Category Number being seen
+    CatCount:   integer; // Number of Categorys
+
+    procedure SortSongs();
+    procedure Refresh;                                      // refreshes arrays by recreating them from Songs array
+    procedure ShowCategory(Index: integer);                 // expands all songs in category
+    procedure HideCategory(Index: integer);                 // hides all songs in category
+    procedure ClickCategoryButton(Index: integer);          // uses ShowCategory and HideCategory when needed
+    procedure ShowCategoryList;                             // Hides all Songs And Show the List of all Categorys
+    function FindNextVisible(SearchFrom: integer): integer; // Find Next visible Song
+    function VisibleSongs: integer;                         // returns number of visible songs (for tabs)
+    function VisibleIndex(Index: integer): integer;         // returns visible song index (skips invisible)
+
+    function SetFilter(FilterStr: UTF8String; Filter: TSongFilter): cardinal;
+  end;
+
+var
+  Songs:    TSongs;    // all songs
+  CatSongs: TCatSongs; // categorized songs
+
+const
+  IN_ACCESS        = $00000001; //* File was accessed */
+  IN_MODIFY        = $00000002; //* File was modified */
+  IN_ATTRIB        = $00000004; //* Metadata changed */
+  IN_CLOSE_WRITE   = $00000008; //* Writtable file was closed */
+  IN_CLOSE_NOWRITE = $00000010; //* Unwrittable file closed */
+  IN_OPEN          = $00000020; //* File was opened */
+  IN_MOVED_FROM    = $00000040; //* File was moved from X */
+  IN_MOVED_TO      = $00000080; //* File was moved to Y */
+  IN_CREATE        = $00000100; //* Subfile was created */
+  IN_DELETE        = $00000200; //* Subfile was deleted */
+  IN_DELETE_SELF   = $00000400; //* Self was deleted */
+
+
+implementation
+
+uses
+  StrUtils,
+  UCovers,
+  UFiles,
+  UGraphic,
+  UMain,
+  UPathUtils,
+  UNote,
+  UFilesystem,
+  UUnicodeUtils;
+
+constructor TSongs.Create();
+begin
+  // do not start thread BEFORE initialization (suspended = true)
+  inherited Create(true);
+  Self.FreeOnTerminate := true;
+
+  SongList := TList.Create();
+
+  // FIXME: threaded loading does not work this way.
+  // It will just cause crashes but nothing else at the moment.
+(*
+  {$ifdef MSWINDOWS}
+    fDirWatch := TDirectoryWatch.create(nil);
+    fDirWatch.OnChange     := DoDirChanged;
+    fDirWatch.Directory    := SongPath;
+    fDirWatch.WatchSubDirs := true;
+    fDirWatch.active       := true;
+  {$ENDIF}
+
+  // now we can start the thread
+  Resume();
+*)
+
+  // until it is fixed, simply load the song-list
+  int_LoadSongList();
+end;
+
+destructor TSongs.Destroy();
+begin
+  FreeAndNil(SongList);
+  inherited;
+end;
+
+procedure TSongs.DoDirChanged(Sender: TObject);
+begin
+  LoadSongList();
+end;
+
+procedure TSongs.Execute();
+var
+  fChangeNotify: THandle;
+begin
+{$IFDEF USE_PSEUDO_THREAD}
+  int_LoadSongList();
+{$ELSE}
+  fParseSongDirectory := true;
+
+  while not terminated do
+  begin
+
+    if fParseSongDirectory then
+    begin
+      Log.LogStatus('Calling int_LoadSongList', 'TSongs.Execute');
+      int_LoadSongList();
+    end;
+
+    Suspend();
+  end;
+{$ENDIF}
+end;
+
+procedure TSongs.int_LoadSongList;
+var
+  I: integer;
+begin
+  try
+    fProcessing := true;
+
+    Log.LogStatus('Searching For Songs', 'SongList');
+
+    // browse directories
+    for I := 0 to SongPaths.Count-1 do
+      BrowseDir(SongPaths[I] as IPath);
+
+    if assigned(CatSongs) then
+      CatSongs.Refresh;
+
+    if assigned(CatCovers) then
+      CatCovers.Load;
+
+    //if assigned(Covers) then
+    //  Covers.Load;
+
+    if assigned(ScreenSong)  then
+    begin
+      ScreenSong.GenerateThumbnails();
+      ScreenSong.OnShow; // refresh ScreenSong
+    end;
+
+  finally
+    Log.LogStatus('Search Complete', 'SongList');
+
+    fParseSongDirectory := false;
+    fProcessing         := false;
+  end;
+end;
+
+
+procedure TSongs.LoadSongList;
+begin
+  fParseSongDirectory := true;
+  Resume();
+end;
+
+procedure TSongs.BrowseDir(Dir: IPath);
+begin
+  BrowseTXTFiles(Dir);
+  BrowseXMLFiles(Dir);
+end;
+
+procedure TSongs.FindFilesByExtension(const Dir: IPath; const Ext: IPath; Recursive: Boolean; var Files: TPathDynArray);
+var
+  Iter: IFileIterator;
+  FileInfo: TFileInfo;
+  FileName: IPath;
+begin
+  // search for all files and directories
+  Iter := FileSystem.FileFind(Dir.Append('*'), faAnyFile);
+  while (Iter.HasNext) do
+  begin
+    FileInfo := Iter.Next;
+    FileName := FileInfo.Name;
+    if ((FileInfo.Attr and faDirectory) <> 0) then
+    begin
+      if Recursive and (not FileName.Equals('.')) and (not FileName.Equals('..')) then
+        FindFilesByExtension(Dir.Append(FileName), Ext, true, Files);
+    end
+    else
+    begin
+      if (Ext.Equals(FileName.GetExtension(), true)) then
+      begin
+        SetLength(Files, Length(Files)+1);
+        Files[High(Files)] := Dir.Append(FileName);
+      end;
+    end;
+  end;
+end;
+
+procedure TSongs.BrowseTXTFiles(Dir: IPath);
+var
+  I: integer;
+  Files: TPathDynArray;
+  Song: TSong;
+  Extension: IPath;
+begin
+  SetLength(Files, 0);
+  Extension := Path('.txt');
+  FindFilesByExtension(Dir, Extension, true, Files);
+
+  for I := 0 to High(Files) do
+  begin
+    Song := TSong.Create(Files[I]);
+
+    if Song.Analyse then
+      SongList.Add(Song)
+    else
+    begin
+      Log.LogError('AnalyseFile failed for "' + Files[I].ToNative + '".');
+      FreeAndNil(Song);
+    end;
+  end;
+
+  SetLength(Files, 0);
+end;
+
+procedure TSongs.BrowseXMLFiles(Dir: IPath);
+var
+  I: integer;
+  Files: TPathDynArray;
+  Song: TSong;
+  Extension: IPath;
+begin
+  SetLength(Files, 0);
+  Extension := Path('.xml');
+  FindFilesByExtension(Dir, Extension, true, Files);
+
+  for I := 0 to High(Files) do
+  begin
+    Song := TSong.Create(Files[I]);
+
+    if Song.AnalyseXML then
+      SongList.Add(Song)
+    else
+    begin
+      Log.LogError('AnalyseFile failed for "' + Files[I].ToNative + '".');
+      FreeAndNil(Song);
+    end;
+  end;
+
+  SetLength(Files, 0);
+end;
+
+(*
+ * Comparison functions for sorting
+ *)
+
+function CompareByEdition(Song1, Song2: Pointer): integer;
+begin
+  Result := UTF8CompareText(TSong(Song1).Edition, TSong(Song2).Edition);
+end;
+
+function CompareByGenre(Song1, Song2: Pointer): integer;
+begin
+  Result := UTF8CompareText(TSong(Song1).Genre, TSong(Song2).Genre);
+end;
+
+function CompareByTitle(Song1, Song2: Pointer): integer;
+begin
+  Result := UTF8CompareText(TSong(Song1).Title, TSong(Song2).Title);
+end;
+
+function CompareByArtist(Song1, Song2: Pointer): integer;
+begin
+  Result := UTF8CompareText(TSong(Song1).Artist, TSong(Song2).Artist);
+end;
+
+function CompareByFolder(Song1, Song2: Pointer): integer;
+begin
+  Result := UTF8CompareText(TSong(Song1).Folder, TSong(Song2).Folder);
+end;
+
+function CompareByLanguage(Song1, Song2: Pointer): integer;
+begin
+  Result := UTF8CompareText(TSong(Song1).Language, TSong(Song2).Language);
+end;
+
+procedure TSongs.Sort(Order: TSortingType);
+var
+  CompareFunc: TListSortCompare;
+begin
+  // FIXME: what is the difference between artist and artist2, etc.?
+  case Order of
+    sEdition: // by edition
+      CompareFunc := CompareByEdition;
+    sGenre: // by genre
+      CompareFunc := CompareByGenre;
+    sTitle: // by title
+      CompareFunc := CompareByTitle;
+    sArtist: // by artist
+      CompareFunc := CompareByArtist;
+    sFolder: // by folder
+      CompareFunc := CompareByFolder;
+    sArtist2: // by artist2
+      CompareFunc := CompareByArtist;
+    sLanguage: // by Language
+      CompareFunc := CompareByLanguage;
+    else
+      Log.LogCritical('Unsupported comparison', 'TSongs.Sort');
+      Exit; // suppress warning
+  end; // case
+
+  // Note: Do not use TList.Sort() as it uses QuickSort which is instable.
+  // For example, if a list is sorted by title first and
+  // by artist afterwards, the songs of an artist will not be sorted by title anymore.
+  // The stable MergeSort guarantees to maintain this order. 
+  MergeSort(SongList, CompareFunc);
+end;
+
+procedure TCatSongs.SortSongs();
+begin
+  case TSortingType(Ini.Sorting) of
+    sEdition: begin
+        Songs.Sort(sTitle);
+        Songs.Sort(sArtist);
+        Songs.Sort(sEdition);
+      end;
+    sGenre: begin
+        Songs.Sort(sTitle);
+        Songs.Sort(sArtist);
+        Songs.Sort(sGenre);
+      end;
+    sLanguage: begin
+        Songs.Sort(sTitle);
+        Songs.Sort(sArtist);
+        Songs.Sort(sLanguage);
+      end;
+    sFolder: begin
+        Songs.Sort(sTitle);
+        Songs.Sort(sArtist);
+        Songs.Sort(sFolder);
+      end;
+    sTitle: begin
+        Songs.Sort(sTitle);
+      end;
+    sArtist: begin
+        Songs.Sort(sTitle);
+        Songs.Sort(sArtist);
+      end;
+    sArtist2: begin
+        Songs.Sort(sTitle);
+        Songs.Sort(sArtist2);
+      end;
+  end; // case
+end;
+
+procedure TCatSongs.Refresh;
+var
+  SongIndex:   integer;
+  CurSong:     TSong;
+  CatIndex:    integer;    // index of current song in Song
+  Letter:      UCS4Char;   // current letter for sorting using letter
+  CurCategory: UTF8String; // current edition for sorting using edition, genre etc.
+  Order:       integer;    // number used for ordernum
+  LetterTmp:   UCS4Char;
+  CatNumber:   integer;    // Number of Song in Category
+
+  procedure AddCategoryButton(const CategoryName: UTF8String);
+  var
+    PrevCatBtnIndex: integer;
+  begin
+    Inc(Order);
+    CatIndex := Length(Song);
+    SetLength(Song, CatIndex+1);
+    Song[CatIndex]          := TSong.Create();
+    Song[CatIndex].Artist   := '[' + CategoryName + ']';
+    Song[CatIndex].Main     := true;
+    Song[CatIndex].OrderTyp := 0;
+    Song[CatIndex].OrderNum := Order;
+    Song[CatIndex].Cover    := CatCovers.GetCover(TSortingType(Ini.Sorting), CategoryName);
+    Song[CatIndex].Visible  := true;
+
+    // set number of songs in previous category
+    PrevCatBtnIndex := CatIndex - CatNumber - 1;
+    if ((PrevCatBtnIndex >= 0) and Song[PrevCatBtnIndex].Main) then
+      Song[PrevCatBtnIndex].CatNumber := CatNumber;
+
+    CatNumber := 0;
+ end;
+
+begin
+  CatNumShow  := -1;
+
+  SortSongs();
+
+  CurCategory := '';
+  Order       := 0;
+  CatNumber   := 0;
+
+  // Note: do NOT set Letter to ' ', otherwise no category-button will be
+  // created for songs beginning with ' ' if songs of this category exist.
+  // TODO: trim song-properties so ' ' will not occur as first chararcter. 
+  Letter      := 0;
+
+  // clear song-list
+  for SongIndex := 0 to Songs.SongList.Count - 1 do
+  begin
+    // free category buttons
+    // Note: do NOT delete songs, they are just references to Songs.SongList entries
+    CurSong := TSong(Songs.SongList[SongIndex]);
+    if (CurSong.Main) then
+      CurSong.Free;
+  end;
+  SetLength(Song, 0);
+
+  for SongIndex := 0 to Songs.SongList.Count - 1 do
+  begin
+    CurSong := TSong(Songs.SongList[SongIndex]);
+    // if tabs are on, add section buttons for each new section
+    if (Ini.Tabs = 1) then
+    begin
+      case (TSortingType(Ini.Sorting)) of
+        sEdition: begin
+          if (CompareText(CurCategory, CurSong.Edition) <> 0) then
+          begin
+            CurCategory := CurSong.Edition;
+
+            // add Category Button
+            AddCategoryButton(CurCategory);
+          end;
+        end;
+
+        sGenre: begin
+          if (CompareText(CurCategory, CurSong.Genre) <> 0) then
+          begin
+            CurCategory := CurSong.Genre;
+            // add Genre Button
+            AddCategoryButton(CurCategory);
+          end;
+        end;
+
+        sLanguage: begin
+          if (CompareText(CurCategory, CurSong.Language) <> 0) then
+          begin
+            CurCategory := CurSong.Language;
+            // add Language Button
+            AddCategoryButton(CurCategory);
+          end
+        end;
+
+        sTitle: begin
+          if (Length(CurSong.Title) >= 1) then
+          begin
+            LetterTmp := UCS4UpperCase(UTF8ToUCS4String(CurSong.Title)[0]);
+            { all numbers and some punctuation chars are put into a
+              category named '#'
+              we can't put the other punctuation chars into this category
+              because they are not in order, so there will be two different
+              categories named '#' } 
+            if (LetterTmp in [Ord('!') .. Ord('?')]) then
+              LetterTmp := Ord('#')
+            else
+              LetterTmp := UCS4UpperCase(LetterTmp);
+            if (Letter <> LetterTmp) then
+            begin
+              Letter := LetterTmp;
+              // add a letter Category Button
+              AddCategoryButton(UCS4ToUTF8String(Letter));
+            end;
+          end;
+        end;
+
+        sArtist: begin
+          if (Length(CurSong.Artist) >= 1) then
+          begin
+            LetterTmp := UCS4UpperCase(UTF8ToUCS4String(CurSong.Artist)[0]);
+            { all numbers and some punctuation chars are put into a
+              category named '#'
+              we can't put the other punctuation chars into this category
+              because they are not in order, so there will be two different
+              categories named '#' } 
+            if (LetterTmp in [Ord('!') .. Ord('?')]) then
+              LetterTmp := Ord('#')
+            else
+              LetterTmp := UCS4UpperCase(LetterTmp);
+              
+            if (Letter <> LetterTmp) then
+            begin
+              Letter := LetterTmp;
+              // add a letter Category Button
+              AddCategoryButton(UCS4ToUTF8String(Letter));
+            end;
+          end;
+        end;
+
+        sFolder: begin
+          if (UTF8CompareText(CurCategory, CurSong.Folder) <> 0) then
+          begin
+            CurCategory := CurSong.Folder;
+            // add folder tab
+            AddCategoryButton(CurCategory);
+          end;
+        end;
+
+        sArtist2: begin
+          { this new sorting puts all songs by the same artist into
+            a single category }
+          if (UTF8CompareText(CurCategory, CurSong.Artist) <> 0) then
+          begin
+            CurCategory := CurSong.Artist;
+            // add folder tab
+            AddCategoryButton(CurCategory);
+          end;
+        end;
+
+      end; // case (Ini.Sorting)
+    end; // if (Ini.Tabs = 1)
+
+    CatIndex := Length(Song);
+    SetLength(Song, CatIndex+1);
+
+    Inc(CatNumber); // increase number of songs in category
+
+    // copy reference to current song
+    Song[CatIndex] := CurSong;
+
+    // set song's category info
+    CurSong.OrderNum := Order; // assigns category
+    CurSong.CatNumber := CatNumber;
+
+    if (Ini.Tabs = 0) then
+      CurSong.Visible := true
+    else if (Ini.Tabs = 1) then
+      CurSong.Visible := false;
+{
+    if (Ini.Tabs = 1) and (Order = 1) then
+    begin
+      //open first tab
+      CurSong.Visible := true;
+    end;
+    CurSong.Visible := true;
+}
+  end;
+
+  // set CatNumber of last category
+  if (Ini.TabsAtStartup = 1) and (High(Song) >= 1) then
+  begin
+    // set number of songs in previous category
+    SongIndex := CatIndex - CatNumber;
+    if ((SongIndex >= 0) and Song[SongIndex].Main) then
+      Song[SongIndex].CatNumber := CatNumber;
+  end;
+
+  // update number of categories
+  CatCount := Order;
+end;
+
+procedure TCatSongs.ShowCategory(Index: integer);
+var
+  S: integer; // song
+begin
+  CatNumShow := Index;
+  for S := 0 to high(CatSongs.Song) do
+  begin
+{
+    if (CatSongs.Song[S].OrderNum = Index) and (not CatSongs.Song[S].Main) then
+      CatSongs.Song[S].Visible := true
+    else
+      CatSongs.Song[S].Visible := false;
+}
+//  KMS: This should be the same, but who knows :-)
+    CatSongs.Song[S].Visible := ((CatSongs.Song[S].OrderNum = Index) and (not CatSongs.Song[S].Main));
+  end;
+end;
+
+procedure TCatSongs.HideCategory(Index: integer); // hides all songs in category
+var
+  S: integer; // song
+begin
+  for S := 0 to high(CatSongs.Song) do
+  begin
+    if not CatSongs.Song[S].Main then
+      CatSongs.Song[S].Visible := false // hides all at now
+  end;
+end;
+
+procedure TCatSongs.ClickCategoryButton(Index: integer);
+var
+  Num: integer;
+begin
+  Num := CatSongs.Song[Index].OrderNum;
+  if Num <> CatNumShow then
+  begin
+    ShowCategory(Num);
+  end
+  else
+  begin
+    ShowCategoryList;
+  end;
+end;
+
+//Hide Categorys when in Category Hack
+procedure TCatSongs.ShowCategoryList;
+var
+  S: integer;
+begin
+  // Hide All Songs Show All Cats
+  for S := 0 to high(CatSongs.Song) do
+    CatSongs.Song[S].Visible := CatSongs.Song[S].Main;
+  CatSongs.Selected := CatNumShow; //Show last shown Category
+  CatNumShow := -1;
+end;
+//Hide Categorys when in Category Hack End
+
+// Wrong song selected when tabs on bug
+function TCatSongs.FindNextVisible(SearchFrom:integer): integer;// Find next Visible Song
+var
+  I: integer;
+begin
+  Result := -1;
+  I := SearchFrom;
+  while (Result = -1) do
+  begin
+    Inc (I);
+
+    if (I > High(CatSongs.Song)) then
+      I := Low(CatSongs.Song);
+    if (I = SearchFrom) then // Make One Round and no song found->quit
+      Break;
+
+    if (CatSongs.Song[I].Visible) then
+      Result := I;
+  end;
+end;
+// Wrong song selected when tabs on bug End
+
+(**
+ * Returns the number of visible songs.
+ *)
+function TCatSongs.VisibleSongs: integer;
+var
+  SongIndex: integer;
+begin
+  Result := 0;
+  for SongIndex := 0 to High(CatSongs.Song) do
+  begin
+    if (CatSongs.Song[SongIndex].Visible) then
+      Inc(Result);
+  end;
+end;
+
+(**
+ * Returns the index of a song in the subset of all visible songs.
+ * If all songs are visible, the result will be equal to the Index parameter. 
+ *)
+function TCatSongs.VisibleIndex(Index: integer): integer;
+var
+  SongIndex: integer;
+begin
+  Result := 0;
+  for SongIndex := 0 to Index - 1 do
+  begin
+    if (CatSongs.Song[SongIndex].Visible) then
+      Inc(Result);
+  end;
+end;
+
+function TCatSongs.SetFilter(FilterStr: UTF8String; Filter: TSongFilter): cardinal;
+var
+  I, J:      integer;
+  TmpString: UTF8String;
+  WordArray: array of UTF8String;
+begin
+  FilterStr := Trim(FilterStr);
+  if (FilterStr <> '') then
+  begin
+    Result := 0;
+
+    // initialize word array
+    SetLength(WordArray, 1);
+
+    // Copy words to SearchStr
+    I := Pos(' ', FilterStr);
+    while (I <> 0) do
+    begin
+      WordArray[High(WordArray)] := Copy(FilterStr, 1, I-1);
+      SetLength(WordArray, Length(WordArray) + 1);
+
+      FilterStr := TrimLeft(Copy(FilterStr, I+1, Length(FilterStr)-I));
+      I := Pos(' ', FilterStr);
+    end;
+
+    // Copy last word
+    WordArray[High(WordArray)] := FilterStr;
+
+    for I := 0 to High(Song) do
+    begin
+      if not Song[i].Main then
+      begin
+        case Filter of
+          fltAll:
+            TmpString := Song[I].Artist + ' ' + Song[i].Title + ' ' + Song[i].Folder;
+          fltTitle:
+            TmpString := Song[I].Title;
+          fltArtist:
+            TmpString := Song[I].Artist;
+        end;
+        Song[i].Visible := true;
+        // Look for every searched word
+        for J := 0 to High(WordArray) do
+        begin
+          Song[i].Visible := Song[i].Visible and
+                             UTF8ContainsText(TmpString, WordArray[J])
+        end;
+        if Song[i].Visible then
+          Inc(Result);
+      end
+      else
+        Song[i].Visible := false;
+    end;
+    CatNumShow := -2;
+  end
+  else
+  begin
+    for i := 0 to High(Song) do
+    begin
+      Song[i].Visible := (Ini.Tabs = 1) = Song[i].Main;
+      CatNumShow := -1;
+    end;
+    Result := 0;
+  end;
+end;
+
+// -----------------------------------------------------------------------------
+
+end.
diff --git a/songmanagement/src/base/UTextEncoding.pas b/songmanagement/src/base/UTextEncoding.pas
new file mode 100644
index 00000000..0c9ba4cc
--- /dev/null
+++ b/songmanagement/src/base/UTextEncoding.pas
@@ -0,0 +1,248 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UTextEncoding;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  UUnicodeUtils;
+
+type
+  TEncoding = (
+    encLocale,  // current locale (needs cwstring on linux)
+    encUTF8,    // UTF-8
+    encCP1250,  // Windows-1250 Central/Eastern Europe (used by Ultrastar)
+    encCP1252,  // Windows-1252 Western Europe (used by UltraStar Deluxe < 1.1)
+    encAuto     // try to match the w3c regex and decode as unicode on match
+                // and as fallback if not match
+  );
+
+const
+  UTF8_BOM: UTF8String = #$EF#$BB#$BF;
+
+{**
+ * Decodes Src encoded in SrcEncoding to a UTF-16 or UTF-8 encoded Dst string.
+ * Returns true if the conversion was successful.
+ *}
+function DecodeString(const Src: RawByteString; out Dst: WideString; SrcEncoding: TEncoding): boolean; overload;
+function DecodeString(const Src: RawByteString; SrcEncoding: TEncoding): WideString; overload;
+function DecodeStringUTF8(const Src: RawByteString; out Dst: UTF8String; SrcEncoding: TEncoding): boolean; overload;
+function DecodeStringUTF8(const Src: RawByteString; SrcEncoding: TEncoding): UTF8String; overload;
+
+{**
+ * Encodes the UTF-16 or UTF-8 encoded Src string to Dst using DstEncoding
+ * Returns true if the conversion was successful.
+ *}
+function EncodeString(const Src: WideString; out Dst: RawByteString; DstEncoding: TEncoding): boolean; overload;
+function EncodeString(const Src: WideString; DstEncoding: TEncoding): RawByteString; overload;
+function EncodeStringUTF8(const Src: UTF8String; out Dst: RawByteString; DstEncoding: TEncoding): boolean; overload;
+function EncodeStringUTF8(const Src: UTF8String; DstEncoding: TEncoding): RawByteString; overload;
+
+{**
+ * If Text starts with an UTF-8 BOM, the BOM is removed and true will
+ * be returned.
+ *}
+function CheckReplaceUTF8BOM(var Text: RawByteString): boolean;
+
+{**
+ * Parses an encoding string to its TEncoding equivalent.
+ * Surrounding whitespace and dashes ('-') are removed, the upper-cased
+ * resulting value is then compared with TEncodingNames.
+ * If the encoding was not found, the result is set to the Default encoding.
+ *}
+function ParseEncoding(const EncodingStr: AnsiString; Default: TEncoding): TEncoding;
+
+{**
+ * Returns the name of an encoding.
+ *}
+function EncodingName(Encoding: TEncoding): AnsiString;
+
+implementation
+
+uses
+  StrUtils,
+  pcre,
+  UCommon,
+  ULog;
+
+type
+  IEncoder = interface
+    function GetName(): AnsiString;
+    function Encode(const InStr: UCS4String; out OutStr: RawByteString): boolean;
+    function Decode(const InStr: RawByteString; out OutStr: UCS4String): boolean;
+  end;
+
+  TEncoder = class(TInterfacedObject, IEncoder)
+  public
+    function GetName(): AnsiString; virtual; abstract;
+    function Encode(const InStr: UCS4String; out OutStr: RawByteString): boolean; virtual; abstract;
+    function Decode(const InStr: RawByteString; out OutStr: UCS4String): boolean; virtual; abstract;
+  end;
+
+  TSingleByteEncoder = class(TEncoder)
+  public
+    function Encode(const InStr: UCS4String; out OutStr: RawByteString): boolean; override;
+    function Decode(const InStr: RawByteString; out OutStr: UCS4String): boolean; override;
+    function DecodeChar(InChr: AnsiChar; out OutChr: UCS4Char): boolean; virtual; abstract;
+    function EncodeChar(InChr: UCS4Char; out OutChr: AnsiChar): boolean; virtual; abstract;
+  end;
+
+const
+  ERROR_CHAR = '?';
+
+var
+  Encoders: array[TEncoding] of IEncoder;
+
+function TSingleByteEncoder.Encode(const InStr: UCS4String; out OutStr: RawByteString): boolean;
+var
+  I: integer;
+begin
+  SetLength(OutStr, LengthUCS4(InStr));
+  Result := true;
+  for I := 1 to Length(OutStr) do
+  begin
+    if (not EncodeChar(InStr[I-1], OutStr[I])) then
+      Result := false;
+  end;
+end;
+
+function TSingleByteEncoder.Decode(const InStr: RawByteString; out OutStr: UCS4String): boolean;
+var
+  I: integer;
+begin
+  SetLength(OutStr, Length(InStr)+1);
+  Result := true;
+  for I := 1 to Length(InStr) do
+  begin
+    if (not DecodeChar(InStr[I], OutStr[I-1])) then
+      Result := false;
+  end;
+  OutStr[High(OutStr)] := 0;
+end;
+
+function DecodeString(const Src: RawByteString; out Dst: WideString; SrcEncoding: TEncoding): boolean;
+var
+  DstUCS4: UCS4String;
+begin
+  Result := Encoders[SrcEncoding].Decode(Src, DstUCS4);
+  Dst := UCS4StringToWideString(DstUCS4);
+end;
+
+function DecodeString(const Src: RawByteString; SrcEncoding: TEncoding): WideString;
+begin
+  DecodeString(Src, Result, SrcEncoding);
+end;
+
+function DecodeStringUTF8(const Src: RawByteString; out Dst: UTF8String; SrcEncoding: TEncoding): boolean;
+var
+  DstUCS4: UCS4String;
+begin
+  Result := Encoders[SrcEncoding].Decode(Src, DstUCS4);
+  Dst := UCS4ToUTF8String(DstUCS4);
+end;
+
+function DecodeStringUTF8(const Src: RawByteString; SrcEncoding: TEncoding): UTF8String;
+begin
+  DecodeStringUTF8(Src, Result, SrcEncoding);
+end;
+
+function EncodeString(const Src: WideString; out Dst: RawByteString; DstEncoding: TEncoding): boolean;
+begin
+  Result := Encoders[DstEncoding].Encode(WideStringToUCS4String(Src), Dst);
+end;
+
+function EncodeString(const Src: WideString; DstEncoding: TEncoding): RawByteString;
+begin
+  EncodeString(Src, Result, DstEncoding);
+end;
+
+function EncodeStringUTF8(const Src: UTF8String; out Dst: RawByteString; DstEncoding: TEncoding): boolean;
+begin
+  Result := Encoders[DstEncoding].Encode(UTF8ToUCS4String(Src), Dst);
+end;
+
+function EncodeStringUTF8(const Src: UTF8String; DstEncoding: TEncoding): RawByteString;
+begin
+  EncodeStringUTF8(Src, Result, DstEncoding);
+end;
+
+function CheckReplaceUTF8BOM(var Text: RawByteString): boolean;
+begin
+  if AnsiStartsStr(UTF8_BOM, Text) then
+  begin
+    Text := Copy(Text, Length(UTF8_BOM)+1, Length(Text)-Length(UTF8_BOM));
+    Result := true;
+    Exit;
+  end;
+  Result := false;
+end;
+
+function ParseEncoding(const EncodingStr: AnsiString; Default: TEncoding): TEncoding;
+var
+  PrepStr: AnsiString; // prepared encoding string
+  Encoding: TEncoding;
+begin
+  // remove surrounding whitespace, replace dashes, to upper case
+  PrepStr := UpperCase(AnsiReplaceStr(Trim(EncodingStr), '-', ''));
+  for Encoding := Low(TEncoding) to High(TEncoding) do
+  begin
+    if (Encoders[Encoding].GetName() = PrepStr) then
+    begin
+      Result := Encoding;
+      Exit;
+    end;
+  end;
+  Result := Default;
+end;
+
+function EncodingName(Encoding: TEncoding): AnsiString;
+begin
+  Result := Encoders[Encoding].GetName();
+end;
+
+{$I ..\\encoding\\Locale.inc}
+{$I ..\\encoding\\UTF8.inc}
+{$I ..\\encoding\\CP1250.inc}
+{$I ..\\encoding\\CP1252.inc}
+{$I ..\\encoding\\Auto.inc}
+
+initialization
+  Encoders[encLocale] := TEncoderLocale.Create;
+  Encoders[encUTF8]   := TEncoderUTF8.Create;
+  Encoders[encCP1250] := TEncoderCP1250.Create;
+  Encoders[encCP1252] := TEncoderCP1252.Create;
+
+  // use USDX < 1.1 encoding for backward compatibility (encCP1252)
+  Encoders[encAuto] := TEncoderAuto.Create(Encoders[encUTF8], Encoders[encCP1252]);
+
+end.
diff --git a/songmanagement/src/base/UTexture.pas b/songmanagement/src/base/UTexture.pas
new file mode 100644
index 00000000..c1334dd7
--- /dev/null
+++ b/songmanagement/src/base/UTexture.pas
@@ -0,0 +1,548 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UTexture;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  gl,
+  glu,
+  glext,
+  Classes,
+  SysUtils,
+  UCommon,
+  UPath,
+  SDL,
+  SDL_Image;
+
+type
+  PTexture = ^TTexture;
+  TTexture = record
+    TexNum:   GLuint;
+    X:        real;
+    Y:        real;
+    Z:        real;
+    W:        real;
+    H:        real;
+    ScaleW:   real; // for dynamic scalling while leaving width constant
+    ScaleH:   real; // for dynamic scalling while leaving height constant
+    Rot:      real; // 0 - 2*pi
+    Int:      real; // intensity
+    ColR:     real;
+    ColG:     real;
+    ColB:     real;
+    TexW:     real; // percentage of width to use [0..1]
+    TexH:     real; // percentage of height to use [0..1]
+    TexX1:    real;
+    TexY1:    real;
+    TexX2:    real;
+    TexY2:    real;
+    Alpha:    real;
+    Name:     IPath; // experimental for handling cache images. maybe it's useful for dynamic skins
+  end;
+
+type
+  TTextureType = (
+    TEXTURE_TYPE_PLAIN,        // Plain (alpha = 1)
+    TEXTURE_TYPE_TRANSPARENT,  // Alpha is used
+    TEXTURE_TYPE_COLORIZED     // Alpha is used; Hue of the HSV color-model will be replaced by a new value
+  );
+
+const
+  TextureTypeStr: array[TTextureType] of string = (
+    'Plain',
+    'Transparent',
+    'Colorized'
+  );
+
+function TextureTypeToStr(TexType: TTextureType): string;
+function ParseTextureType(const TypeStr: string; Default: TTextureType): TTextureType;
+
+procedure AdjustPixelFormat(var TexSurface: PSDL_Surface; Typ: TTextureType);
+
+type
+  PTextureEntry = ^TTextureEntry;
+  TTextureEntry = record
+    Name:         IPath;
+    Typ:          TTextureType;
+    Color:        cardinal;
+
+    // we use normal TTexture, it's easier to implement and if needed - we copy ready data
+    Texture:      TTexture; // Full-size texture
+    TextureCache: TTexture; // Thumbnail texture
+  end;
+
+  TTextureDatabase = class
+    private
+      Texture: array of TTextureEntry;
+    public
+      procedure AddTexture(var Tex: TTexture; Typ: TTextureType; Color: cardinal; Cache: boolean);
+      function FindTexture(const Name: IPath; Typ: TTextureType; Color: cardinal): integer;
+  end;
+
+  TTextureUnit = class
+    private
+      TextureDatabase: TTextureDatabase;
+    public
+      Limit: integer;
+
+      procedure AddTexture(var Tex: TTexture; Typ: TTextureType; Cache: boolean = false); overload;
+      procedure AddTexture(var Tex: TTexture; Typ: TTextureType; Color: cardinal; Cache: boolean = false); overload;
+      function GetTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean = false): TTexture; overload;
+      function GetTexture(const Name: IPath; Typ: TTextureType; Col: LongWord; FromCache: boolean = false): TTexture; overload;
+      function LoadTexture(FromRegistry: boolean; const Identifier: IPath; Typ: TTextureType; Col: LongWord): TTexture; overload;
+      function LoadTexture(const Identifier: IPath; Typ: TTextureType; Col: LongWord): TTexture; overload;
+      function LoadTexture(const Identifier: IPath): TTexture; overload;
+      function CreateTexture(Data: PChar; const Name: IPath; Width, Height: word; BitsPerPixel: byte): TTexture;
+      procedure UnloadTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean); overload;
+      procedure UnloadTexture(const Name: IPath; Typ: TTextureType; Col: cardinal; FromCache: boolean); overload;
+      //procedure FlushTextureDatabase();
+
+      constructor Create;
+      destructor Destroy; override;
+  end;
+
+var
+  Texture: TTextureUnit;
+
+implementation
+
+uses
+  DateUtils,
+  StrUtils,
+  Math,
+  ULog,
+  UCovers,
+  UThemes,
+  UImage;
+
+procedure AdjustPixelFormat(var TexSurface: PSDL_Surface; Typ: TTextureType);
+var
+  TempSurface: PSDL_Surface;
+  NeededPixFmt: PSDL_Pixelformat;
+begin
+  if      (Typ = TEXTURE_TYPE_PLAIN) then
+    NeededPixFmt := @PixelFmt_RGB
+  else if (Typ = TEXTURE_TYPE_TRANSPARENT) or
+          (Typ = TEXTURE_TYPE_COLORIZED) then
+    NeededPixFmt := @PixelFmt_RGBA
+  else
+    NeededPixFmt := @PixelFmt_RGB;
+
+  if not PixelformatEquals(TexSurface^.format, NeededPixFmt) then
+  begin
+    TempSurface := TexSurface;
+    TexSurface := SDL_ConvertSurface(TempSurface, NeededPixFmt, SDL_SWSURFACE);
+    SDL_FreeSurface(TempSurface);
+  end;
+end;
+
+{ TTextureDatabase }
+
+procedure TTextureDatabase.AddTexture(var Tex: TTexture; Typ: TTextureType; Color: cardinal; Cache: boolean);
+var
+  TextureIndex: integer;
+begin
+  TextureIndex := FindTexture(Tex.Name, Typ, Color);
+  if (TextureIndex = -1) then
+  begin
+    TextureIndex := Length(Texture);
+    SetLength(Texture, TextureIndex+1);
+
+    Texture[TextureIndex].Name  := Tex.Name;
+    Texture[TextureIndex].Typ   := Typ;
+    Texture[TextureIndex].Color := Color;
+  end;
+
+  if (Cache) then
+    Texture[TextureIndex].TextureCache := Tex
+  else
+    Texture[TextureIndex].Texture      := Tex;
+end;
+
+function TTextureDatabase.FindTexture(const Name: IPath; Typ: TTextureType; Color: cardinal): integer;
+var
+  TextureIndex: integer;
+  CurrentTexture: PTextureEntry;
+begin
+  Result := -1;
+  for TextureIndex := 0 to High(Texture) do
+  begin
+    CurrentTexture := @Texture[TextureIndex];
+    if (CurrentTexture.Name.Equals(Name)) and
+       (CurrentTexture.Typ = Typ) then
+    begin
+      // colorized textures must match in their color too
+      if (CurrentTexture.Typ <> TEXTURE_TYPE_COLORIZED) or
+         (CurrentTexture.Color = Color) then
+      begin
+        Result := TextureIndex;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+{ TTextureUnit }
+
+constructor TTextureUnit.Create;
+begin
+  inherited Create;
+  TextureDatabase := TTextureDatabase.Create;
+end;
+
+destructor TTextureUnit.Destroy;
+begin
+  TextureDatabase.Free;
+  inherited Destroy;
+end;
+
+procedure TTextureUnit.AddTexture(var Tex: TTexture; Typ: TTextureType; Cache: boolean);
+begin
+  TextureDatabase.AddTexture(Tex, Typ, 0, Cache);
+end;
+
+procedure TTextureUnit.AddTexture(var Tex: TTexture; Typ: TTextureType; Color: cardinal; Cache: boolean);
+begin
+  TextureDatabase.AddTexture(Tex, Typ, Color, Cache);
+end;
+
+function TTextureUnit.LoadTexture(FromRegistry: boolean; const Identifier: IPath; Typ: TTextureType; Col: LongWord): TTexture;
+begin
+  // FIXME: what is the FromRegistry parameter supposed to do?
+  Result := LoadTexture(Identifier, Typ, Col);
+end;
+
+function TTextureUnit.LoadTexture(const Identifier: IPath): TTexture;
+begin
+  Result := LoadTexture(Identifier, TEXTURE_TYPE_PLAIN, 0);
+end;
+
+function TTextureUnit.LoadTexture(const Identifier: IPath; Typ: TTextureType; Col: LongWord): TTexture;
+var
+  TexSurface: PSDL_Surface;
+  newWidth, newHeight: integer;
+  oldWidth, oldHeight: integer;
+  ActTex: GLuint;
+begin
+  // zero texture data
+  FillChar(Result, SizeOf(Result), 0);
+
+  // load texture data into memory
+  TexSurface := LoadImage(Identifier);
+  if not assigned(TexSurface) then
+  begin
+    Log.LogError('Could not load texture: "' + Identifier.ToNative +'" with type "'+ TextureTypeToStr(Typ) +'"',
+                 'TTextureUnit.LoadTexture');
+    Exit;
+  end;
+
+  // convert pixel format as needed
+  AdjustPixelFormat(TexSurface, Typ);
+
+  // adjust texture size (scale down, if necessary)
+  newWidth   := TexSurface.W;
+  newHeight  := TexSurface.H;
+
+  if (newWidth > Limit) then
+    newWidth := Limit;
+
+  if (newHeight > Limit) then
+    newHeight := Limit;
+
+  if (TexSurface.W > newWidth) or (TexSurface.H > newHeight) then
+    ScaleImage(TexSurface, newWidth, newHeight);
+
+  // now we might colorize the whole thing
+  if (Typ = TEXTURE_TYPE_COLORIZED) then
+    ColorizeImage(TexSurface, Col);
+
+  // save actual dimensions of our texture
+  oldWidth  := newWidth;
+  oldHeight := newHeight;
+
+  // make texture dimensions be powers of 2
+  newWidth  := Round(Power(2, Ceil(Log2(newWidth))));
+  newHeight := Round(Power(2, Ceil(Log2(newHeight))));
+  if (newHeight <> oldHeight) or (newWidth <> oldWidth) then
+    FitImage(TexSurface, newWidth, newHeight);
+
+  // at this point we have the image in memory...
+  // scaled so that dimensions are powers of 2
+  // and converted to either RGB or RGBA
+
+  // if we got a Texture of Type Plain, Transparent or Colorized,
+  // then we're done manipulating it
+  // and could now create our openGL texture from it
+
+  // prepare OpenGL texture
+  glGenTextures(1, @ActTex);
+
+  glBindTexture(GL_TEXTURE_2D, ActTex);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+  // load data into gl texture
+  if (Typ = TEXTURE_TYPE_TRANSPARENT) or
+     (Typ = TEXTURE_TYPE_COLORIZED) then
+  begin
+    {$IFDEF FPC_BIG_ENDIAN}
+    glTexImage2D(GL_TEXTURE_2D, 0, 4, newWidth, newHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, TexSurface.pixels);
+    {$ELSE}
+    glTexImage2D(GL_TEXTURE_2D, 0, 4, newWidth, newHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, TexSurface.pixels);
+    {$ENDIF}
+  end
+  else //if Typ = TEXTURE_TYPE_PLAIN then
+  begin
+    {$IFDEF FPC_BIG_ENDIAN}
+    glTexImage2D(GL_TEXTURE_2D, 0, 3, newWidth, newHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, TexSurface.pixels);
+    {$ELSE}
+    glTexImage2D(GL_TEXTURE_2D, 0, 3, newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, TexSurface.pixels);
+    {$ENDIF}
+  end;
+
+  // setup texture struct
+  with Result do
+  begin
+    X := 0;
+    Y := 0;
+    Z := 0;
+    W := oldWidth;
+    H := oldHeight;
+    ScaleW := 1;
+    ScaleH := 1;
+    Rot := 0;
+    TexNum := ActTex;
+    TexW := oldWidth / newWidth;
+    TexH := oldHeight / newHeight;
+
+    Int   := 1;
+    ColR  := 1;
+    ColG  := 1;
+    ColB  := 1;
+    Alpha := 1;
+
+    // new test - default use whole texure, taking TexW and TexH as const and changing these
+    TexX1 := 0;
+    TexY1 := 0;
+    TexX2 := 1;
+    TexY2 := 1;
+
+    Name := Identifier;
+  end;
+
+  SDL_FreeSurface(TexSurface);
+end;
+
+function TTextureUnit.GetTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean): TTexture;
+begin
+  Result := GetTexture(Name, Typ, 0, FromCache);
+end;
+
+function TTextureUnit.GetTexture(const Name: IPath; Typ: TTextureType; Col: LongWord; FromCache: boolean): TTexture;
+var
+  TextureIndex: integer;
+begin
+  if (Name.IsUnset) then
+  begin
+    // zero texture data
+    FillChar(Result, SizeOf(Result), 0);
+    Exit;
+  end;
+
+  if (FromCache) then
+  begin
+    // use texture
+    TextureIndex := TextureDatabase.FindTexture(Name, Typ, Col);
+    if (TextureIndex > -1) then
+      Result := TextureDatabase.Texture[TextureIndex].TextureCache;
+    Exit;
+  end;
+
+  // find texture entry in database
+  TextureIndex := TextureDatabase.FindTexture(Name, Typ, Col);
+  if (TextureIndex = -1) then
+  begin
+    // create texture entry in database
+    TextureIndex := Length(TextureDatabase.Texture);
+    SetLength(TextureDatabase.Texture, TextureIndex+1);
+
+    TextureDatabase.Texture[TextureIndex].Name  := Name;
+    TextureDatabase.Texture[TextureIndex].Typ   := Typ;
+    TextureDatabase.Texture[TextureIndex].Color := Col;
+
+    // inform database that no textures have been loaded into memory
+    TextureDatabase.Texture[TextureIndex].Texture.TexNum      := 0;
+    TextureDatabase.Texture[TextureIndex].TextureCache.TexNum := 0;
+  end;
+
+  // load full texture
+  if (TextureDatabase.Texture[TextureIndex].Texture.TexNum = 0) then
+    TextureDatabase.Texture[TextureIndex].Texture := LoadTexture(false, Name, Typ, Col);
+
+  // use texture
+  Result := TextureDatabase.Texture[TextureIndex].Texture;
+end;
+
+function TTextureUnit.CreateTexture(Data: PChar; const Name: IPath; Width, Height: word; BitsPerPixel: byte): TTexture;
+var
+  //Error:     integer;
+  ActTex:    GLuint;
+begin
+  glGenTextures(1, @ActTex); // ActText = new texture number
+  glBindTexture(GL_TEXTURE_2D, ActTex);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+  {$IFDEF FPC_BIG_ENDIAN}
+  glTexImage2D(GL_TEXTURE_2D, 0, 3, Width, Height, 0, GL_BGR, GL_UNSIGNED_BYTE, Data);
+  {$ELSE}
+  glTexImage2D(GL_TEXTURE_2D, 0, 3, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
+  {$ENDIF}
+
+{
+  if Mipmapping then
+  begin
+    Error := gluBuild2DMipmaps(GL_TEXTURE_2D, 3, W, H, GL_RGB, GL_UNSIGNED_BYTE, @Data[0]);
+// FPC_BIG_ENDIAN   Error := gluBuild2DMipmaps(GL_TEXTURE_2D, 3, W, H, GL_BGR, GL_UNSIGNED_BYTE, @Data[0]);
+    if Error > 0 then
+      Log.LogError('gluBuild2DMipmaps() failed', 'TTextureUnit.CreateTexture');
+  end;
+}
+
+  Result.X := 0;
+  Result.Y := 0;
+  Result.Z := 0;
+  Result.W := 0;
+  Result.H := 0;
+  Result.ScaleW := 1;
+  Result.ScaleH := 1;
+  Result.Rot := 0;
+  Result.TexNum := ActTex;
+  Result.TexW := 1;
+  Result.TexH := 1;
+
+  Result.Int := 1;
+  Result.ColR := 1;
+  Result.ColG := 1;
+  Result.ColB := 1;
+  Result.Alpha := 1;
+
+  // new test - default use whole texure, taking TexW and TexH as const and changing these
+  Result.TexX1 := 0;
+  Result.TexY1 := 0;
+  Result.TexX2 := 1;
+  Result.TexY2 := 1;
+
+  Result.Name := Name;
+end;
+
+procedure TTextureUnit.UnloadTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean);
+begin
+  UnloadTexture(Name, Typ, 0, FromCache);
+end;
+
+procedure TTextureUnit.UnloadTexture(const Name: IPath; Typ: TTextureType; Col: cardinal; FromCache: boolean);
+var
+  T:      integer;
+  TexNum: GLuint;
+begin
+  T := TextureDatabase.FindTexture(Name, Typ, Col);
+
+  if not FromCache then
+  begin
+    TexNum := TextureDatabase.Texture[T].Texture.TexNum;
+    if TexNum > 0 then
+    begin
+      glDeleteTextures(1, PGLuint(@TexNum));
+      TextureDatabase.Texture[T].Texture.TexNum := 0;
+      //Log.LogError('Unload texture no '+IntToStr(TexNum));
+    end;
+  end
+  else
+  begin
+    TexNum := TextureDatabase.Texture[T].TextureCache.TexNum;
+    if TexNum > 0 then
+    begin
+      glDeleteTextures(1, @TexNum);
+      TextureDatabase.Texture[T].TextureCache.TexNum := 0;
+      //Log.LogError('Unload texture cache no '+IntToStr(TexNum));
+    end;
+  end;
+end;
+
+(* This needs some work
+procedure TTextureUnit.FlushTextureDatabase();
+var
+  i: integer;
+  Tex: ^TTexture;
+begin
+  for i := 0 to High(TextureDatabase.Texture) do
+  begin
+    // only delete non-cached entries
+    if (TextureDatabase.Texture[i].Texture.TexNum > 0) then
+    begin
+      Tex := @TextureDatabase.Texture[i].Texture;
+      glDeleteTextures(1, PGLuint(Tex^.TexNum));
+      Tex^.TexNum := 0;
+    end;
+  end;
+end;
+*)
+
+function TextureTypeToStr(TexType: TTextureType): string;
+begin
+  Result := TextureTypeStr[TexType];
+end;
+
+function ParseTextureType(const TypeStr: string; Default: TTextureType): TTextureType;
+var
+  TextureType:   TTextureType;
+  UpCaseStr: string;
+begin
+  UpCaseStr := UpperCase(TypeStr);
+  for TextureType := Low(TextureTypeStr) to High(TextureTypeStr) do
+  begin
+    if (UpCaseStr = UpperCase(TextureTypeStr[TextureType])) then
+    begin
+      Result := TextureType;
+      Exit;
+    end;
+  end;
+  Log.LogInfo('Unknown texture type: "' + TypeStr + '". Using default texture type "'
+      + TextureTypeToStr(Default) + '"', 'UTexture.ParseTextureType');
+  Result := Default;
+end;
+
+end.
diff --git a/songmanagement/src/base/UThemes.pas b/songmanagement/src/base/UThemes.pas
new file mode 100644
index 00000000..b385406f
--- /dev/null
+++ b/songmanagement/src/base/UThemes.pas
@@ -0,0 +1,2501 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UThemes;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  IniFiles,
+  SysUtils,
+  Classes,
+  ULog,
+  UTexture,
+  UPath;
+
+type
+  TRGB = record
+    R: single;
+    G: single;
+    B: single;
+  end;
+
+  TRGBA = record
+    R, G, B, A: double;
+  end;
+
+type
+  TBackgroundType =
+    (bgtNone, bgtColor, bgtTexture, bgtVideo, bgtFade, bgtAuto);
+
+const
+  BGT_Names: array [TBackgroundType] of string =
+    ('none', 'color', 'texture', 'video', 'fade', 'auto');
+
+type
+  TThemeBackground = record
+    BGType: TBackgroundType;
+    Color:  TRGB;
+    Tex:    string;
+    Alpha:  real;
+  end;
+
+const
+  //Defaul Background for Screens w/o Theme e.g. editor
+  DEFAULT_BACKGROUND: TThemeBackground = (
+    BGType: bgtColor;
+    Color:  (R:1; G:1; B:1);
+    Tex:    '';
+    Alpha:  1.0
+  );
+
+
+type
+  TThemeStatic = record
+    X:      integer;
+    Y:      integer;
+    Z:      real;
+    W:      integer;
+    H:      integer;
+    Color:  string;
+    ColR:   real;
+    ColG:   real;
+    ColB:   real;
+    Tex:    string;
+    Typ:    TTextureType;
+    TexX1:  real;
+    TexY1:  real;
+    TexX2:  real;
+    TexY2:  real;
+    //Reflection
+    Reflection:           boolean;
+    Reflectionspacing:    real;
+  end;
+  AThemeStatic = array of TThemeStatic;
+
+  TThemeText = record
+    X:      integer;
+    Y:      integer;
+    W:      integer;
+    Z:      real;
+    Color:  string;
+    ColR:   real;
+    ColG:   real;
+    ColB:   real;
+    Font:   integer;
+    Size:   integer;
+    Align:  integer;
+    Text:   UTF8String;
+    //Reflection
+    Reflection:           boolean;
+    ReflectionSpacing:    real;
+  end;
+  AThemeText = array of TThemeText;
+
+  TThemeButton = record
+    Text:   AThemeText;
+    X:      integer;
+    Y:      integer;
+    Z:      real;
+    W:      integer;
+    H:      integer;
+    Color:  string;
+    ColR:   real;
+    ColG:   real;
+    ColB:   real;
+    Int:    real;
+    DColor: string;
+    DColR:  real;
+    DColG:  real;
+    DColB:  real;
+    DInt:   real;
+    Tex:    string;
+    Typ:    TTextureType;
+
+    Visible: boolean;
+
+    //Reflection Mod
+    Reflection:           boolean;
+    Reflectionspacing:    real;
+    //Fade Mod
+    SelectH:    integer;
+    SelectW:    integer;
+    Fade:       boolean;
+    FadeText:   boolean;
+    DeSelectReflectionspacing : real;
+    FadeTex:    string;
+    FadeTexPos: integer;
+
+    //Button Collection Mod
+    Parent: byte; //Number of the Button Collection this Button is assigned to. IF 0: No Assignement
+  end;
+
+  //Button Collection Mod
+  TThemeButtonCollection = record
+    Style: TThemeButton;
+    ChildCount: byte; //No of assigned Childs
+    FirstChild: byte; //No of Child on whose Interaction Position the Button should be
+  end;
+
+  AThemeButtonCollection = array of TThemeButtonCollection;
+  PAThemeButtonCollection = ^AThemeButtonCollection;
+
+  TThemeSelectSlide = record
+    Tex:    string;
+    Typ:    TTextureType;
+    TexSBG: string;
+    TypSBG: TTextureType;
+    X:      integer;
+    Y:      integer;
+    W:      integer;
+    H:      integer;
+    Z:      real;
+    SBGW:   integer;
+
+    TextSize: integer;
+
+    showArrows:boolean;
+    oneItemOnly:boolean;
+
+    Text:   UTF8String;
+    ColR,  ColG,  ColB,  Int:     real;
+    DColR, DColG, DColB, DInt:    real;
+    TColR,  TColG,  TColB,  TInt:     real;
+    TDColR, TDColG, TDColB, TDInt:    real;
+    SBGColR,  SBGColG,  SBGColB,  SBGInt:     real;
+    SBGDColR, SBGDColG, SBGDColB, SBGDInt:    real;
+    STColR,  STColG,  STColB,  STInt:     real;
+    STDColR, STDColG, STDColB, STDInt:    real;
+    SkipX:    integer;
+  end;
+
+  TThemeEqualizer = record
+    Visible: boolean;
+    Direction: boolean;
+    Alpha: real;
+    X: integer;
+    Y: integer;
+    Z: real;
+    W: integer;
+    H: integer;
+    Space: integer;
+    Bands: integer;
+    Length: integer;
+    ColR, ColG, ColB: real;
+    Reflection:           boolean;
+    Reflectionspacing:    real;
+  end;
+
+  PThemeBasic = ^TThemeBasic;
+  TThemeBasic = class
+    Background:       TThemeBackground;
+    Text:             AThemeText;
+    Statics:           AThemeStatic;
+
+    //Button Collection Mod
+    ButtonCollection: AThemeButtonCollection;
+  end;
+
+  TThemeLoading = class(TThemeBasic)
+    StaticAnimation:  TThemeStatic;
+    TextLoading:      TThemeText;
+  end;
+
+  TThemeMain = class(TThemeBasic)
+    ButtonSolo:       TThemeButton;
+    ButtonMulti:      TThemeButton;
+    ButtonStat:       TThemeButton;
+    ButtonEditor:     TThemeButton;
+    ButtonOptions:    TThemeButton;
+    ButtonExit:       TThemeButton;
+
+    TextDescription:      TThemeText;
+    TextDescriptionLong:  TThemeText;
+    Description:          array[0..5] of UTF8String;
+    DescriptionLong:      array[0..5] of UTF8String;
+  end;
+
+  TThemeName = class(TThemeBasic)
+    ButtonPlayer:     array[1..6] of TThemeButton;
+  end;
+
+  TThemeLevel = class(TThemeBasic)
+    ButtonEasy:       TThemeButton;
+    ButtonMedium:     TThemeButton;
+    ButtonHard:       TThemeButton;
+  end;
+
+  TThemeSong = class(TThemeBasic)
+    TextArtist:       TThemeText;
+    TextTitle:        TThemeText;
+    TextNumber:       TThemeText;
+
+    //Video Icon Mod
+    VideoIcon:        TThemeStatic;
+
+   //Show Cat in TopLeft Mod
+    TextCat:          TThemeText;
+    StaticCat:        TThemeStatic;
+
+    //Cover Mod
+    Cover: record
+      Reflections: boolean;
+      X: integer;
+      Y: integer;
+      Z: integer;
+      W: integer;
+      H: integer;
+      Style: integer;
+    end;
+
+    //Equalizer Mod
+    Equalizer: TThemeEqualizer;
+
+
+    //Party and Non Party specific Statics and Texts
+    StaticParty:    AThemeStatic;
+    TextParty:      AThemeText;
+
+    StaticNonParty: AThemeStatic;
+    TextNonParty:   AThemeText;
+
+    //Party Mode
+    StaticTeam1Joker1: TThemeStatic;
+    StaticTeam1Joker2: TThemeStatic;
+    StaticTeam1Joker3: TThemeStatic;
+    StaticTeam1Joker4: TThemeStatic;
+    StaticTeam1Joker5: TThemeStatic;
+    StaticTeam2Joker1: TThemeStatic;
+    StaticTeam2Joker2: TThemeStatic;
+    StaticTeam2Joker3: TThemeStatic;
+    StaticTeam2Joker4: TThemeStatic;
+    StaticTeam2Joker5: TThemeStatic;
+    StaticTeam3Joker1: TThemeStatic;
+    StaticTeam3Joker2: TThemeStatic;
+    StaticTeam3Joker3: TThemeStatic;
+    StaticTeam3Joker4: TThemeStatic;
+    StaticTeam3Joker5: TThemeStatic;
+
+
+  end;
+
+   TThemeSing = class(TThemeBasic)
+
+    //TimeBar mod
+    StaticTimeProgress:   TThemeStatic;
+    TextTimeText      :   TThemeText;
+    //eoa TimeBar mod
+
+    StaticP1:         TThemeStatic;
+    TextP1:           TThemeText;
+    StaticP1ScoreBG:  TThemeStatic; //Static for ScoreBG
+    TextP1Score:      TThemeText;
+
+    //moveable singbar mod
+    StaticP1SingBar:         TThemeStatic;
+    StaticP1ThreePSingBar:   TThemeStatic;
+    StaticP1TwoPSingBar:     TThemeStatic;
+    StaticP2RSingBar:        TThemeStatic;
+    StaticP2MSingBar:        TThemeStatic;
+    StaticP3SingBar:         TThemeStatic;
+    //eoa moveable singbar
+
+    //added for ps3 skin
+    //game in 2/4 player modi
+    StaticP1TwoP:         TThemeStatic;
+    StaticP1TwoPScoreBG:  TThemeStatic; //Static for ScoreBG
+    TextP1TwoP:           TThemeText;
+    TextP1TwoPScore:      TThemeText;
+    //game in 3/6 player modi
+    StaticP1ThreeP:         TThemeStatic;
+    StaticP1ThreePScoreBG:  TThemeStatic; //Static for ScoreBG
+    TextP1ThreeP:           TThemeText;
+    TextP1ThreePScore:      TThemeText;
+    //eoa
+
+    StaticP2R:        TThemeStatic;
+    StaticP2RScoreBG: TThemeStatic; //Static for ScoreBG
+    TextP2R:          TThemeText;
+    TextP2RScore:     TThemeText;
+
+    StaticP2M:        TThemeStatic;
+    StaticP2MScoreBG: TThemeStatic; //Static for ScoreBG
+    TextP2M:          TThemeText;
+    TextP2MScore:     TThemeText;
+
+    StaticP3R:        TThemeStatic;
+    StaticP3RScoreBG: TThemeStatic; //Static for ScoreBG
+    TextP3R:          TThemeText;
+    TextP3RScore:     TThemeText;
+
+    //Linebonus Translations
+    LineBonusText:    array [0..8] of UTF8String;
+
+    //Pause Popup
+     PausePopUp:      TThemeStatic;
+  end;
+
+  TThemeLyricBar = record
+     IndicatorYOffset, UpperX, UpperW, UpperY, UpperH,
+     LowerX, LowerW, LowerY, LowerH  : integer;
+  end;
+
+  TThemeScore = class(TThemeBasic)
+    TextArtist:       TThemeText;
+    TextTitle:        TThemeText;
+
+    TextArtistTitle:  TThemeText;
+
+    PlayerStatic:     array[1..6] of AThemeStatic;
+    PlayerTexts:      array[1..6] of AThemeText;
+
+    TextName:         array[1..6] of TThemeText;
+    TextScore:        array[1..6] of TThemeText;
+
+    TextNotes:            array[1..6] of TThemeText;
+    TextNotesScore:       array[1..6] of TThemeText;
+    TextLineBonus:        array[1..6] of TThemeText;
+    TextLineBonusScore:   array[1..6] of TThemeText;
+    TextGoldenNotes:      array[1..6] of TThemeText;
+    TextGoldenNotesScore: array[1..6] of TThemeText;
+    TextTotal:            array[1..6] of TThemeText;
+    TextTotalScore:       array[1..6] of TThemeText;
+
+    StaticBoxLightest:    array[1..6] of TThemeStatic;
+    StaticBoxLight:       array[1..6] of TThemeStatic;
+    StaticBoxDark:        array[1..6] of TThemeStatic;
+
+    StaticRatings:        array[1..6] of TThemeStatic;
+
+    StaticBackLevel:        array[1..6] of TThemeStatic;
+    StaticBackLevelRound:   array[1..6] of TThemeStatic;
+    StaticLevel:            array[1..6] of TThemeStatic;
+    StaticLevelRound:       array[1..6] of TThemeStatic;
+    StaticPlayerIdBox:      array[1..6] of TThemeStatic;
+
+//    Description:          array[0..5] of string;}
+  end;
+
+  TThemeTop5 = class(TThemeBasic)
+    TextLevel:        TThemeText;
+    TextArtistTitle:  TThemeText;
+
+    StaticNumber:     AThemeStatic;
+    TextNumber:       AThemeText;
+    TextName:         AThemeText;
+    TextScore:        AThemeText;
+    TextDate:         AThemeText;
+  end;
+
+  TThemeOptions = class(TThemeBasic)
+    ButtonGame:       TThemeButton;
+    ButtonGraphics:   TThemeButton;
+    ButtonSound:      TThemeButton;
+    ButtonLyrics:     TThemeButton;
+    ButtonThemes:     TThemeButton;
+    ButtonRecord:     TThemeButton;
+    ButtonAdvanced:   TThemeButton;
+    ButtonExit:       TThemeButton;
+
+    TextDescription:      TThemeText;
+    Description:          array[0..7] of UTF8String;
+  end;
+
+  TThemeOptionsGame = class(TThemeBasic)
+    SelectPlayers:      TThemeSelectSlide;
+    SelectDifficulty:   TThemeSelectSlide;
+    SelectLanguage:     TThemeSelectSlide;
+    SelectTabs:         TThemeSelectSlide;
+    SelectSorting:      TThemeSelectSlide;
+    SelectDebug:        TThemeSelectSlide;
+    ButtonExit:         TThemeButton;
+  end;
+
+  TThemeOptionsGraphics = class(TThemeBasic)
+    SelectFullscreen:       TThemeSelectSlide;
+    SelectResolution:       TThemeSelectSlide;
+    SelectDepth:            TThemeSelectSlide;
+    SelectVisualizer:       TThemeSelectSlide;
+    SelectOscilloscope:     TThemeSelectSlide;
+    SelectLineBonus:        TThemeSelectSlide;
+    SelectMovieSize:        TThemeSelectSlide;
+    ButtonExit:             TThemeButton;
+  end;
+
+  TThemeOptionsSound = class(TThemeBasic)
+    SelectMicBoost:              TThemeSelectSlide;
+    SelectBackgroundMusic:       TThemeSelectSlide;
+    SelectClickAssist:           TThemeSelectSlide;
+    SelectBeatClick:             TThemeSelectSlide;
+    SelectThreshold:             TThemeSelectSlide;
+    SelectSlidePreviewVolume:    TThemeSelectSlide;
+    SelectSlidePreviewFading:    TThemeSelectSlide;
+    SelectSlideVoicePassthrough: TThemeSelectSlide;
+    ButtonExit:                  TThemeButton;
+  end;
+
+  TThemeOptionsLyrics = class(TThemeBasic)
+    SelectLyricsFont:   TThemeSelectSlide;
+    SelectLyricsEffect: TThemeSelectSlide;
+//    SelectSolmization:  TThemeSelectSlide;
+    SelectNoteLines:    TThemeSelectSlide;
+    ButtonExit:         TThemeButton;
+  end;
+
+  TThemeOptionsThemes = class(TThemeBasic)
+    SelectTheme:        TThemeSelectSlide;
+    SelectSkin:         TThemeSelectSlide;
+    SelectColor:        TThemeSelectSlide;
+    ButtonExit:         TThemeButton;
+  end;
+
+  TThemeOptionsRecord = class(TThemeBasic)
+    SelectSlideCard:       TThemeSelectSlide;
+    SelectSlideInput:      TThemeSelectSlide;
+    SelectSlideChannel:    TThemeSelectSlide;
+    ButtonExit:            TThemeButton;
+  end;
+
+  TThemeOptionsAdvanced = class(TThemeBasic)
+    SelectLoadAnimation:  TThemeSelectSlide;
+    SelectEffectSing:     TThemeSelectSlide;
+    SelectScreenFade:     TThemeSelectSlide;
+    SelectLineBonus:      TThemeSelectSlide;
+    SelectAskbeforeDel:   TThemeSelectSlide;
+    SelectOnSongClick:    TThemeSelectSlide;
+    SelectPartyPopup:     TThemeSelectSlide;
+    ButtonExit:           TThemeButton;
+  end;
+
+  TThemeEdit = class(TThemeBasic)
+    ButtonConvert:        TThemeButton;
+    ButtonExit:           TThemeButton;
+
+    TextDescription:      TThemeText;
+    TextDescriptionLong:  TThemeText;
+    Description:          array[0..5] of UTF8string;
+    DescriptionLong:      array[0..5] of UTF8string;
+  end;
+
+  //Error- and Check-Popup
+  TThemeError = class(TThemeBasic)
+    Button1: TThemeButton;
+    TextError: TThemeText;
+  end;
+
+  TThemeCheck = class(TThemeBasic)
+    Button1: TThemeButton;
+    Button2: TThemeButton;
+    TextCheck: TThemeText;
+  end;
+
+
+  //ScreenSong Menue
+  TThemeSongMenu = class(TThemeBasic)
+    Button1: TThemeButton;
+    Button2: TThemeButton;
+    Button3: TThemeButton;
+    Button4: TThemeButton;
+
+    SelectSlide3: TThemeSelectSlide;
+
+    TextMenu: TThemeText;
+  end;
+
+  TThemeSongJumpTo = class(TThemeBasic)
+    ButtonSearchText: TThemeButton;
+    SelectSlideType:  TThemeSelectSlide;
+    TextFound:        TThemeText;
+
+    //Translated Texts
+    Songsfound:       UTF8String;
+    NoSongsfound:     UTF8String;
+    CatText:          UTF8String;
+    IType:            array [0..2] of UTF8String;
+  end;
+
+  //Party Screens
+  TThemePartyNewRound = class(TThemeBasic)
+    TextRound1:        TThemeText;
+    TextRound2:        TThemeText;
+    TextRound3:        TThemeText;
+    TextRound4:        TThemeText;
+    TextRound5:        TThemeText;
+    TextRound6:        TThemeText;
+    TextRound7:        TThemeText;
+    TextWinner1:       TThemeText;
+    TextWinner2:       TThemeText;
+    TextWinner3:       TThemeText;
+    TextWinner4:       TThemeText;
+    TextWinner5:       TThemeText;
+    TextWinner6:       TThemeText;
+    TextWinner7:       TThemeText;
+    TextNextRound:     TThemeText;
+    TextNextRoundNo:   TThemeText;
+    TextNextPlayer1:   TThemeText;
+    TextNextPlayer2:   TThemeText;
+    TextNextPlayer3:   TThemeText;
+
+    StaticRound1:      TThemeStatic;
+    StaticRound2:      TThemeStatic;
+    StaticRound3:      TThemeStatic;
+    StaticRound4:      TThemeStatic;
+    StaticRound5:      TThemeStatic;
+    StaticRound6:      TThemeStatic;
+    StaticRound7:      TThemeStatic;
+
+    TextScoreTeam1:    TThemeText;
+    TextScoreTeam2:    TThemeText;
+    TextScoreTeam3:    TThemeText;
+    TextNameTeam1:     TThemeText;
+    TextNameTeam2:     TThemeText;
+    TextNameTeam3:     TThemeText;
+    TextTeam1Players:  TThemeText;
+    TextTeam2Players:  TThemeText;
+    TextTeam3Players:  TThemeText;
+
+    StaticTeam1:       TThemeStatic;
+    StaticTeam2:       TThemeStatic;
+    StaticTeam3:       TThemeStatic;
+    StaticNextPlayer1: TThemeStatic;
+    StaticNextPlayer2: TThemeStatic;
+    StaticNextPlayer3: TThemeStatic;
+  end;
+
+  TThemePartyScore = class(TThemeBasic)
+    TextScoreTeam1:    TThemeText;
+    TextScoreTeam2:    TThemeText;
+    TextScoreTeam3:    TThemeText;
+    TextNameTeam1:     TThemeText;
+    TextNameTeam2:     TThemeText;
+    TextNameTeam3:     TThemeText;
+    StaticTeam1:       TThemeStatic;
+    StaticTeam1BG:     TThemeStatic;
+    StaticTeam1Deco:   TThemeStatic;
+    StaticTeam2:       TThemeStatic;
+    StaticTeam2BG:     TThemeStatic;
+    StaticTeam2Deco:   TThemeStatic;
+    StaticTeam3:       TThemeStatic;
+    StaticTeam3BG:     TThemeStatic;
+    StaticTeam3Deco:   TThemeStatic;
+
+    DecoTextures:      record
+      ChangeTextures:  boolean;
+
+      FirstTexture:    string;
+      FirstTyp:        TTextureType;
+      FirstColor:      string;
+
+      SecondTexture:   string;
+      SecondTyp:       TTextureType;
+      SecondColor:     string;
+
+      ThirdTexture:    string;
+      ThirdTyp:        TTextureType;
+      ThirdColor:      string;
+    end;
+
+
+    TextWinner:        TThemeText;
+  end;
+
+  TThemePartyWin = class(TThemeBasic)
+    TextScoreTeam1:    TThemeText;
+    TextScoreTeam2:    TThemeText;
+    TextScoreTeam3:    TThemeText;
+    TextNameTeam1:     TThemeText;
+    TextNameTeam2:     TThemeText;
+    TextNameTeam3:     TThemeText;
+    StaticTeam1:       TThemeStatic;
+    StaticTeam1BG:     TThemeStatic;
+    StaticTeam1Deco:   TThemeStatic;
+    StaticTeam2:       TThemeStatic;
+    StaticTeam2BG:     TThemeStatic;
+    StaticTeam2Deco:   TThemeStatic;
+    StaticTeam3:       TThemeStatic;
+    StaticTeam3BG:     TThemeStatic;
+    StaticTeam3Deco:   TThemeStatic;
+
+    TextWinner:        TThemeText;
+  end;
+
+  TThemePartyOptions = class(TThemeBasic)
+    SelectLevel: TThemeSelectSlide;
+    SelectPlayList: TThemeSelectSlide;
+    SelectPlayList2: TThemeSelectSlide;
+
+    {ButtonNext: TThemeButton;
+    ButtonPrev: TThemeButton;}
+  end;
+
+  TThemePartyPlayer = class(TThemeBasic)
+    SelectTeams: TThemeSelectSlide;
+    SelectPlayers1: TThemeSelectSlide;
+    SelectPlayers2: TThemeSelectSlide;
+    SelectPlayers3: TThemeSelectSlide;
+
+    Team1Name: TThemeButton;
+    Player1Name: TThemeButton;
+    Player2Name: TThemeButton;
+    Player3Name: TThemeButton;
+    Player4Name: TThemeButton;
+
+    Team2Name: TThemeButton;
+    Player5Name: TThemeButton;
+    Player6Name: TThemeButton;
+    Player7Name: TThemeButton;
+    Player8Name: TThemeButton;
+
+    Team3Name: TThemeButton;
+    Player9Name: TThemeButton;
+    Player10Name: TThemeButton;
+    Player11Name: TThemeButton;
+    Player12Name: TThemeButton;
+
+    {ButtonNext: TThemeButton;
+    ButtonPrev: TThemeButton;}
+  end;
+
+  TThemePartyRounds = class(TThemeBasic)
+    SelectRoundCount: TThemeSelectSlide;
+    SelectRound: array [0..6] of TThemeSelectSlide;
+  end;
+
+  //Stats Screens
+  TThemeStatMain = class(TThemeBasic)
+    ButtonScores:     TThemeButton;
+    ButtonSingers:    TThemeButton;
+    ButtonSongs:      TThemeButton;
+    ButtonBands:      TThemeButton;
+    ButtonExit:       TThemeButton;
+
+    TextOverview:     TThemeText;
+  end;
+
+  TThemeStatDetail = class(TThemeBasic)
+    ButtonNext:       TThemeButton;
+    ButtonPrev:       TThemeButton;
+    ButtonReverse:    TThemeButton;
+    ButtonExit:       TThemeButton;
+
+    TextDescription:  TThemeText;
+    TextPage:         TThemeText;
+    TextList:         AThemeText;
+
+    Description:      array[0..3] of UTF8String;
+    DescriptionR:     array[0..3] of UTF8String;
+    FormatStr:        array[0..3] of UTF8String;
+    PageStr:          UTF8String;
+  end;
+
+  //Playlist Translations
+  TThemePlaylist = record
+    CatText:    UTF8String;
+  end;
+
+  TThemeEntry = record
+    Name: string;
+    Filename: IPath;
+    DefaultSkin: integer;
+    Creator: string;
+  end;
+
+  TTheme = class
+  private
+    {$IFDEF THEMESAVE}
+    ThemeIni:         TIniFile;
+    {$ELSE}
+    ThemeIni:         TMemIniFile;
+    {$ENDIF}
+
+    LastThemeBasic:   TThemeBasic;
+    procedure CreateThemeObjects();
+    procedure LoadHeader(FileName: IPath);
+  public
+    Themes:           array of TThemeEntry;
+    Loading:          TThemeLoading;
+    Main:             TThemeMain;
+    Name:             TThemeName;
+    Level:            TThemeLevel;
+    Song:             TThemeSong;
+    Sing:             TThemeSing;
+    LyricBar:         TThemeLyricBar;
+    Score:            TThemeScore;
+    Top5:             TThemeTop5;
+    Options:          TThemeOptions;
+    OptionsGame:      TThemeOptionsGame;
+    OptionsGraphics:  TThemeOptionsGraphics;
+    OptionsSound:     TThemeOptionsSound;
+    OptionsLyrics:    TThemeOptionsLyrics;
+    OptionsThemes:    TThemeOptionsThemes;
+    OptionsRecord:    TThemeOptionsRecord;
+    OptionsAdvanced:  TThemeOptionsAdvanced;
+    //edit
+    Edit:             TThemeEdit;
+    //error and check popup
+    ErrorPopup:       TThemeError;
+    CheckPopup:       TThemeCheck;
+    //ScreenSong extensions
+    SongMenu:         TThemeSongMenu;
+    SongJumpto:       TThemeSongJumpTo;
+    //Party Screens:
+    PartyNewRound:    TThemePartyNewRound;
+    PartyScore:       TThemePartyScore;
+    PartyWin:         TThemePartyWin;
+    PartyOptions:     TThemePartyOptions;
+    PartyPlayer:      TThemePartyPlayer;
+    PartyRounds:      TThemePartyRounds;
+
+    //Stats Screens:
+    StatMain:         TThemeStatMain;
+    StatDetail:       TThemeStatDetail;
+
+    Playlist:         TThemePlaylist;
+
+    ILevel: array[0..2] of UTF8String;
+
+    constructor Create;
+
+    procedure LoadList;
+
+    function LoadTheme(ThemeNum: integer; sColor: integer): boolean; // Load some theme settings from file
+
+    procedure LoadColors;
+
+    procedure ThemeLoadBasic(Theme: TThemeBasic; const Name: string);
+    procedure ThemeLoadBackground(var ThemeBackground: TThemeBackground; const Name: string);
+    procedure ThemeLoadText(var ThemeText: TThemeText; const Name: string);
+    procedure ThemeLoadTexts(var ThemeText: AThemeText; const Name: string);
+    procedure ThemeLoadStatic(var ThemeStatic: TThemeStatic; const Name: string);
+    procedure ThemeLoadStatics(var ThemeStatic: AThemeStatic; const Name: string);
+    procedure ThemeLoadButton(var ThemeButton: TThemeButton; const Name: string; Collections: PAThemeButtonCollection = nil);
+    procedure ThemeLoadButtonCollection(var Collection: TThemeButtonCollection; const Name: string);
+    procedure ThemeLoadButtonCollections(var Collections: AThemeButtonCollection; const Name: string);
+    procedure ThemeLoadSelectSlide(var ThemeSelectS: TThemeSelectSlide; const Name: string);
+    procedure ThemeLoadEqualizer(var ThemeEqualizer: TThemeEqualizer; const Name: string);
+
+    procedure ThemeSave(const FileName: string);
+    procedure ThemeSaveBasic(Theme: TThemeBasic; const Name: string);
+    procedure ThemeSaveBackground(ThemeBackground: TThemeBackground; const Name: string);
+    procedure ThemeSaveStatic(ThemeStatic: TThemeStatic; const Name: string);
+    procedure ThemeSaveStatics(ThemeStatic: AThemeStatic; const Name: string);
+    procedure ThemeSaveText(ThemeText: TThemeText; const Name: string);
+    procedure ThemeSaveTexts(ThemeText: AThemeText; const Name: string);
+    procedure ThemeSaveButton(ThemeButton: TThemeButton; const Name: string);
+  end;
+
+  TColor = record
+    Name:   string;
+    RGB:    TRGB;
+  end;
+
+procedure glColorRGB(Color: TRGB);  overload;
+procedure glColorRGB(Color: TRGB; Alpha: real);  overload;
+procedure glColorRGB(Color: TRGBA); overload;
+procedure glColorRGB(Color: TRGBA; Alpha: real); overload;
+
+function ColorExists(Name: string): integer;
+procedure LoadColor(var R, G, B: real; ColorName: string);
+function GetSystemColor(Color: integer): TRGB;
+function ColorSqrt(RGB: TRGB): TRGB;
+
+var
+  //Skin:         TSkin;
+  Theme:        TTheme;
+  Color:        array of TColor;
+
+implementation
+
+uses
+  UCommon,
+  ULanguage,
+  USkins,
+  UIni,
+  UPathUtils,
+  UFileSystem,
+  TextGL,
+  gl,
+  glext,
+  math,
+  StrUtils;
+
+//-----------
+//Helper procs to use TRGB in Opengl ...maybe this should be somewhere else
+//-----------
+procedure glColorRGB(Color: TRGB);  overload;
+begin
+  glColor3f(Color.R, Color.G, Color.B);
+end;
+
+procedure glColorRGB(Color: TRGB; Alpha: real);  overload;
+begin
+  glColor4f(Color.R, Color.G, Color.B, Alpha);
+end;
+
+procedure glColorRGB(Color: TRGBA); overload;
+begin
+  glColor4f(Color.R, Color.G, Color.B, Color.A);
+end;
+
+procedure glColorRGB(Color: TRGBA; Alpha: real); overload;
+begin
+  glColor4f(Color.R, Color.G, Color.B, Min(Color.A, Alpha));
+end;
+
+constructor TTheme.Create;
+begin
+  inherited Create();
+
+  Loading := TThemeLoading.Create;
+  Main := TThemeMain.Create;
+  Name := TThemeName.Create;
+  Level := TThemeLevel.Create;
+  Song := TThemeSong.Create;
+  Sing := TThemeSing.Create;
+  Score := TThemeScore.Create;
+  Top5 := TThemeTop5.Create;
+  Options := TThemeOptions.Create;
+  OptionsGame := TThemeOptionsGame.Create;
+  OptionsGraphics := TThemeOptionsGraphics.Create;
+  OptionsSound := TThemeOptionsSound.Create;
+  OptionsLyrics := TThemeOptionsLyrics.Create;
+  OptionsThemes := TThemeOptionsThemes.Create;
+  OptionsRecord := TThemeOptionsRecord.Create;
+  OptionsAdvanced := TThemeOptionsAdvanced.Create;
+
+  Edit := TThemeEdit.Create;
+
+  ErrorPopup := TThemeError.Create;
+  CheckPopup := TThemeCheck.Create;
+
+  SongMenu := TThemeSongMenu.Create;
+  SongJumpto := TThemeSongJumpto.Create;
+  //Party Screens
+  PartyNewRound := TThemePartyNewRound.Create;
+  PartyWin := TThemePartyWin.Create;
+  PartyScore := TThemePartyScore.Create;
+  PartyOptions := TThemePartyOptions.Create;
+  PartyPlayer := TThemePartyPlayer.Create;
+  PartyRounds := TThemePartyRounds.Create;
+
+  //Stats Screens:
+  StatMain :=   TThemeStatMain.Create;
+  StatDetail := TThemeStatDetail.Create;
+
+  //LoadTheme(FileName, Color);
+  LoadList;
+end;
+
+procedure TTheme.LoadHeader(FileName: IPath);
+  var
+    Entry: TThemeEntry;
+    Ini: TMemIniFile;
+    SkinName: string;
+    SkinsFound: boolean;
+    ThemeVersion: string;
+    I: integer;
+    Len: integer;
+    Skins: TUTF8StringDynArray;
+begin
+  Entry.Filename := ThemePath.Append(FileName);
+  //read info from theme header
+  Ini := TMemIniFile.Create(Entry.Filename.ToNative);
+
+  Entry.Name := Ini.ReadString('Theme', 'Name', FileName.SetExtension('').ToNative);
+  ThemeVersion := Trim(UpperCase(Ini.ReadString('Theme', 'US_Version', 'no version tag')));
+  Entry.Creator := Ini.ReadString('Theme', 'Creator', 'Unknown');
+  SkinName := Ini.ReadString('Theme', 'DefaultSkin', FileName.SetExtension('').ToNative);
+
+  Ini.Free;
+
+  // don't load theme with wrong version tag
+  if ThemeVersion <> 'USD 110' then
+  begin
+    Log.LogWarn('Wrong Version (' + ThemeVersion + ') in Theme : ' + Entry.Name, 'Theme.LoadHeader');
+  end
+  else
+  begin
+    //Search for Skins for this Theme
+    SkinsFound := false;
+    for I := Low(Skin.Skin) to High(Skin.Skin) do
+    begin
+      if (CompareText(Skin.Skin[I].Theme, Entry.Name) = 0) then
+      begin
+        SkinsFound := true;
+        break;
+      end;
+    end;
+
+    if SkinsFound then
+    begin
+      { found a valid Theme }
+      // set correct default skin
+      Skin.GetSkinsByTheme(Entry.Name, Skins);
+      Entry.DefaultSkin := max(0, GetArrayIndex(Skins, SkinName, true));
+  
+      Len := Length(Themes);
+      SetLength(Themes, Len + 1);
+      SetLength(ITheme, Len + 1);
+      Themes[Len] := Entry;
+      ITheme[Len] := Entry.Name;
+    end;
+  end;
+end;
+
+procedure TTheme.LoadList;
+  var
+    Iter: IFileIterator;
+    FileInfo: TFileInfo;
+begin
+  Log.LogStatus('Searching for Theme : ' + ThemePath.ToNative + '*.ini', 'Theme.LoadList');
+
+  Iter := FileSystem.FileFind(ThemePath.Append('*.ini'), 0);
+  while (Iter.HasNext) do
+  begin
+    FileInfo := Iter.Next;
+    Log.LogStatus('Found Theme: ' + FileInfo.Name.ToNative, 'Theme.LoadList');
+    LoadHeader(Fileinfo.Name);
+  end;
+end;
+
+function TTheme.LoadTheme(ThemeNum: integer; sColor: integer): boolean;
+var
+  I:    integer;
+begin
+  Result := false;
+
+  CreateThemeObjects();
+
+  Log.LogStatus('Loading: '+ Themes[ThemeNum].FileName.ToNative, 'TTheme.LoadTheme');
+
+  if not Themes[ThemeNum].FileName.IsFile() then
+  begin
+    Log.LogError('Theme does not exist ('+ Themes[ThemeNum].FileName.ToNative +')', 'TTheme.LoadTheme');
+  end;
+
+  if Themes[ThemeNum].FileName.IsFile() then
+  begin
+    Result := true;
+
+    {$IFDEF THEMESAVE}
+    ThemeIni := TIniFile.Create(Themes[ThemeNum].FileName.ToNative);
+    {$ELSE}
+    ThemeIni := TMemIniFile.Create(Themes[ThemeNum].FileName.ToNative);
+    {$ENDIF}
+
+    if ThemeIni.ReadString('Theme', 'Name', '') <> '' then
+    begin
+
+      {Skin.SkinName := ThemeIni.ReadString('Theme', 'Name', 'Singstar');
+      Skin.SkinPath := 'Skins\' + Skin.SkinName + '\';
+      Skin.SkinReg := false; }
+      Skin.Color := sColor;
+
+      Skin.LoadSkin(ISkin[Ini.SkinNo]);
+
+      LoadColors;
+
+//      ThemeIni.Free;
+//      ThemeIni := TIniFile.Create('Themes\Singstar\Main.ini');
+
+      // Loading
+      ThemeLoadBasic(Loading, 'Loading');
+      ThemeLoadText(Loading.TextLoading, 'LoadingTextLoading');
+      ThemeLoadStatic(Loading.StaticAnimation, 'LoadingStaticAnimation');
+
+      // Main
+      ThemeLoadBasic(Main, 'Main');
+
+      ThemeLoadText(Main.TextDescription, 'MainTextDescription');
+      ThemeLoadText(Main.TextDescriptionLong, 'MainTextDescriptionLong');
+      ThemeLoadButton(Main.ButtonSolo, 'MainButtonSolo');
+      ThemeLoadButton(Main.ButtonMulti, 'MainButtonMulti');
+      ThemeLoadButton(Main.ButtonStat, 'MainButtonStats');
+      ThemeLoadButton(Main.ButtonEditor, 'MainButtonEditor');
+      ThemeLoadButton(Main.ButtonOptions, 'MainButtonOptions');
+      ThemeLoadButton(Main.ButtonExit, 'MainButtonExit');
+
+      //Main Desc Text Translation Start
+
+      Main.Description[0] := Language.Translate('SING_SING');
+      Main.DescriptionLong[0] := Language.Translate('SING_SING_DESC');
+      Main.Description[1] := Language.Translate('SING_MULTI');
+      Main.DescriptionLong[1] := Language.Translate('SING_MULTI_DESC');
+      Main.Description[2] := Language.Translate('SING_STATS');
+      Main.DescriptionLong[2] := Language.Translate('SING_STATS_DESC');
+      Main.Description[3] := Language.Translate('SING_EDITOR');
+      Main.DescriptionLong[3] := Language.Translate('SING_EDITOR_DESC');
+      Main.Description[4] := Language.Translate('SING_GAME_OPTIONS');
+      Main.DescriptionLong[4] := Language.Translate('SING_GAME_OPTIONS_DESC');
+      Main.Description[5] := Language.Translate('SING_EXIT');
+      Main.DescriptionLong[5] := Language.Translate('SING_EXIT_DESC');
+
+      //Main Desc Text Translation End
+
+      Main.TextDescription.Text := Main.Description[0];
+      Main.TextDescriptionLong.Text := Main.DescriptionLong[0];
+
+      // Name
+      ThemeLoadBasic(Name, 'Name');
+
+      for I := 1 to 6 do
+        ThemeLoadButton(Name.ButtonPlayer[I], 'NameButtonPlayer'+IntToStr(I));
+
+      // Level
+      ThemeLoadBasic(Level, 'Level');
+
+      ThemeLoadButton(Level.ButtonEasy, 'LevelButtonEasy');
+      ThemeLoadButton(Level.ButtonMedium, 'LevelButtonMedium');
+      ThemeLoadButton(Level.ButtonHard, 'LevelButtonHard');
+
+
+      // Song
+      ThemeLoadBasic(Song, 'Song');
+
+      ThemeLoadText(Song.TextArtist, 'SongTextArtist');
+      ThemeLoadText(Song.TextTitle, 'SongTextTitle');
+      ThemeLoadText(Song.TextNumber, 'SongTextNumber');
+
+      //Video Icon Mod
+      ThemeLoadStatic(Song.VideoIcon, 'SongVideoIcon');
+
+      //Show Cat in TopLeft Mod
+      ThemeLoadStatic(Song.StaticCat, 'SongStaticCat');
+      ThemeLoadText(Song.TextCat, 'SongTextCat');
+
+      //Load Cover Pos and Size from Theme Mod
+      Song.Cover.X := ThemeIni.ReadInteger('SongCover', 'X', 300);
+      Song.Cover.Y := ThemeIni.ReadInteger('SongCover', 'Y', 190);
+      Song.Cover.W := ThemeIni.ReadInteger('SongCover', 'W', 300);
+      Song.Cover.H := ThemeIni.ReadInteger('SongCover', 'H', 200);
+      Song.Cover.Style := ThemeIni.ReadInteger('SongCover', 'Style', 4);
+      Song.Cover.Reflections := (ThemeIni.ReadInteger('SongCover', 'Reflections', 0) = 1);
+      //Load Cover Pos and Size from Theme Mod End
+
+      ThemeLoadEqualizer(Song.Equalizer, 'SongEqualizer');
+
+      //Party and Non Party specific Statics and Texts
+      ThemeLoadStatics (Song.StaticParty, 'SongStaticParty');
+      ThemeLoadTexts (Song.TextParty, 'SongTextParty');
+
+      ThemeLoadStatics (Song.StaticNonParty, 'SongStaticNonParty');
+      ThemeLoadTexts (Song.TextNonParty, 'SongTextNonParty');
+
+      //Party Mode
+      ThemeLoadStatic(Song.StaticTeam1Joker1, 'SongStaticTeam1Joker1');
+      ThemeLoadStatic(Song.StaticTeam1Joker2, 'SongStaticTeam1Joker2');
+      ThemeLoadStatic(Song.StaticTeam1Joker3, 'SongStaticTeam1Joker3');
+      ThemeLoadStatic(Song.StaticTeam1Joker4, 'SongStaticTeam1Joker4');
+      ThemeLoadStatic(Song.StaticTeam1Joker5, 'SongStaticTeam1Joker5');
+
+      ThemeLoadStatic(Song.StaticTeam2Joker1, 'SongStaticTeam2Joker1');
+      ThemeLoadStatic(Song.StaticTeam2Joker2, 'SongStaticTeam2Joker2');
+      ThemeLoadStatic(Song.StaticTeam2Joker3, 'SongStaticTeam2Joker3');
+      ThemeLoadStatic(Song.StaticTeam2Joker4, 'SongStaticTeam2Joker4');
+      ThemeLoadStatic(Song.StaticTeam2Joker5, 'SongStaticTeam2Joker5');
+
+      ThemeLoadStatic(Song.StaticTeam3Joker1, 'SongStaticTeam3Joker1');
+      ThemeLoadStatic(Song.StaticTeam3Joker2, 'SongStaticTeam3Joker2');
+      ThemeLoadStatic(Song.StaticTeam3Joker3, 'SongStaticTeam3Joker3');
+      ThemeLoadStatic(Song.StaticTeam3Joker4, 'SongStaticTeam3Joker4');
+      ThemeLoadStatic(Song.StaticTeam3Joker5, 'SongStaticTeam3Joker5');
+
+
+      //LyricBar      asd
+      LyricBar.UpperX := ThemeIni.ReadInteger('SingLyricsUpperBar', 'X', 0);
+      LyricBar.UpperW := ThemeIni.ReadInteger('SingLyricsUpperBar', 'W', 0);
+      LyricBar.UpperY := ThemeIni.ReadInteger('SingLyricsUpperBar', 'Y', 0);
+      LyricBar.UpperH := ThemeIni.ReadInteger('SingLyricsUpperBar', 'H', 0);
+      LyricBar.IndicatorYOffset := ThemeIni.ReadInteger('SingLyricsUpperBar', 'IndicatorYOffset', 0);
+      LyricBar.LowerX := ThemeIni.ReadInteger('SingLyricsLowerBar', 'X', 0);
+      LyricBar.LowerW := ThemeIni.ReadInteger('SingLyricsLowerBar', 'W', 0);
+      LyricBar.LowerY := ThemeIni.ReadInteger('SingLyricsLowerBar', 'Y', 0);
+      LyricBar.LowerH := ThemeIni.ReadInteger('SingLyricsLowerBar', 'H', 0);
+
+      // Sing
+      ThemeLoadBasic(Sing, 'Sing');
+      //TimeBar mod
+       ThemeLoadStatic(Sing.StaticTimeProgress, 'SingTimeProgress');
+       ThemeLoadText(Sing.TextTimeText, 'SingTimeText');
+      //eoa TimeBar mod
+
+    //moveable singbar mod
+      ThemeLoadStatic(Sing.StaticP1SingBar, 'SingP1SingBar');
+      ThemeLoadStatic(Sing.StaticP1TwoPSingBar, 'SingP1TwoPSingBar');
+      ThemeLoadStatic(Sing.StaticP1ThreePSingBar, 'SingP1ThreePSingBar');
+      ThemeLoadStatic(Sing.StaticP2RSingBar, 'SingP2RSingBar');
+      ThemeLoadStatic(Sing.StaticP2MSingBar, 'SingP2MSingBar');
+      ThemeLoadStatic(Sing.StaticP3SingBar, 'SingP3SingBar');
+    //eoa moveable singbar
+
+      ThemeLoadStatic(Sing.StaticP1, 'SingP1Static');
+      ThemeLoadText(Sing.TextP1, 'SingP1Text');
+      ThemeLoadStatic(Sing.StaticP1ScoreBG, 'SingP1Static2');
+      ThemeLoadText(Sing.TextP1Score, 'SingP1TextScore');
+  //Added for ps3 skin
+  //This one is shown in 2/4P mode
+  //if it exists, otherwise the one Player equivaltents are used
+      if (ThemeIni.SectionExists('SingP1TwoPTextScore')) then
+      begin
+        ThemeLoadStatic(Sing.StaticP1TwoP, 'SingP1TwoPStatic');
+        ThemeLoadText(Sing.TextP1TwoP, 'SingP1TwoPText');
+        ThemeLoadStatic(Sing.StaticP1TwoPScoreBG, 'SingP1TwoPStatic2');
+        ThemeLoadText(Sing.TextP1TwoPScore, 'SingP1TwoPTextScore');
+      end
+      else
+      begin
+        Sing.StaticP1TwoP := Sing.StaticP1;
+        Sing.TextP1TwoP := Sing.TextP1;
+        Sing.StaticP1TwoPScoreBG := Sing.StaticP1ScoreBG;
+        Sing.TextP1TwoPScore := Sing.TextP1Score;
+      end;
+
+  //This one is shown in 3/6P mode
+  //if it exists, otherwise the one Player equivaltents are used
+      if (ThemeIni.SectionExists('SingP1TwoPTextScore')) then
+      begin
+        ThemeLoadStatic(Sing.StaticP1ThreeP, 'SingP1ThreePStatic');
+        ThemeLoadText(Sing.TextP1ThreeP, 'SingP1ThreePText');
+        ThemeLoadStatic(Sing.StaticP1ThreePScoreBG, 'SingP1ThreePStatic2');
+        ThemeLoadText(Sing.TextP1ThreePScore, 'SingP1ThreePTextScore');
+      end
+      else
+      begin
+        Sing.StaticP1ThreeP := Sing.StaticP1;
+        Sing.TextP1ThreeP := Sing.TextP1;
+        Sing.StaticP1ThreePScoreBG := Sing.StaticP1ScoreBG;
+        Sing.TextP1ThreePScore := Sing.TextP1Score;
+      end;
+  //eoa
+      ThemeLoadStatic(Sing.StaticP2R, 'SingP2RStatic');
+      ThemeLoadText(Sing.TextP2R, 'SingP2RText');
+      ThemeLoadStatic(Sing.StaticP2RScoreBG, 'SingP2RStatic2');
+      ThemeLoadText(Sing.TextP2RScore, 'SingP2RTextScore');
+
+      ThemeLoadStatic(Sing.StaticP2M, 'SingP2MStatic');
+      ThemeLoadText(Sing.TextP2M, 'SingP2MText');
+      ThemeLoadStatic(Sing.StaticP2MScoreBG, 'SingP2MStatic2');
+      ThemeLoadText(Sing.TextP2MScore, 'SingP2MTextScore');
+
+      ThemeLoadStatic(Sing.StaticP3R, 'SingP3RStatic');
+      ThemeLoadText(Sing.TextP3R, 'SingP3RText');
+      ThemeLoadStatic(Sing.StaticP3RScoreBG, 'SingP3RStatic2');
+      ThemeLoadText(Sing.TextP3RScore, 'SingP3RTextScore');
+
+      //Line Bonus Texts
+      Sing.LineBonusText[0] := Language.Translate('POPUP_AWFUL');
+      Sing.LineBonusText[1] := Sing.LineBonusText[0];
+      Sing.LineBonusText[2] := Language.Translate('POPUP_POOR');
+      Sing.LineBonusText[3] := Language.Translate('POPUP_BAD');
+      Sing.LineBonusText[4] := Language.Translate('POPUP_NOTBAD');
+      Sing.LineBonusText[5] := Language.Translate('POPUP_GOOD');
+      Sing.LineBonusText[6] := Language.Translate('POPUP_GREAT');
+      Sing.LineBonusText[7] := Language.Translate('POPUP_AWESOME');
+      Sing.LineBonusText[8] := Language.Translate('POPUP_PERFECT');
+
+      //PausePopup
+      ThemeLoadStatic(Sing.PausePopUp, 'PausePopUpStatic');
+
+      // Score
+      ThemeLoadBasic(Score, 'Score');
+
+      ThemeLoadText(Score.TextArtist, 'ScoreTextArtist');
+      ThemeLoadText(Score.TextTitle, 'ScoreTextTitle');
+      ThemeLoadText(Score.TextArtistTitle, 'ScoreTextArtistTitle');
+
+      for I := 1 to 6 do
+      begin
+        ThemeLoadStatics(Score.PlayerStatic[I],        'ScorePlayer' + IntToStr(I) + 'Static');
+        ThemeLoadTexts(Score.PlayerTexts[I],           'ScorePlayer' + IntToStr(I) + 'Text');
+
+        ThemeLoadText(Score.TextName[I],               'ScoreTextName'             + IntToStr(I));
+        ThemeLoadText(Score.TextScore[I],              'ScoreTextScore'            + IntToStr(I));
+        ThemeLoadText(Score.TextNotes[I],              'ScoreTextNotes'            + IntToStr(I));
+        ThemeLoadText(Score.TextNotesScore[I],         'ScoreTextNotesScore'       + IntToStr(I));
+        ThemeLoadText(Score.TextLineBonus[I],          'ScoreTextLineBonus'        + IntToStr(I));
+        ThemeLoadText(Score.TextLineBonusScore[I],     'ScoreTextLineBonusScore'   + IntToStr(I));
+        ThemeLoadText(Score.TextGoldenNotes[I],        'ScoreTextGoldenNotes'      + IntToStr(I));
+        ThemeLoadText(Score.TextGoldenNotesScore[I],   'ScoreTextGoldenNotesScore' + IntToStr(I));
+        ThemeLoadText(Score.TextTotal[I],              'ScoreTextTotal'            + IntToStr(I));
+        ThemeLoadText(Score.TextTotalScore[I],         'ScoreTextTotalScore'       + IntToStr(I));
+
+        ThemeLoadStatic(Score.StaticBoxLightest[I],    'ScoreStaticBoxLightest'    + IntToStr(I));
+        ThemeLoadStatic(Score.StaticBoxLight[I],       'ScoreStaticBoxLight'       + IntToStr(I));
+        ThemeLoadStatic(Score.StaticBoxDark[I],        'ScoreStaticBoxDark'        + IntToStr(I));
+
+        ThemeLoadStatic(Score.StaticBackLevel[I],      'ScoreStaticBackLevel'      + IntToStr(I));
+        ThemeLoadStatic(Score.StaticBackLevelRound[I], 'ScoreStaticBackLevelRound' + IntToStr(I));
+        ThemeLoadStatic(Score.StaticLevel[I],          'ScoreStaticLevel'          + IntToStr(I));
+        ThemeLoadStatic(Score.StaticLevelRound[I],     'ScoreStaticLevelRound'     + IntToStr(I));
+        ThemeLoadStatic(Score.StaticPlayerIdBox[I],    'ScoreStaticPlayerIdBox'    + IntToStr(I));
+
+        ThemeLoadStatic(Score.StaticRatings[I],        'ScoreStaticRatingPicture'  + IntToStr(I));
+      end;
+
+      // Top5
+      ThemeLoadBasic(Top5, 'Top5');
+
+      ThemeLoadText(Top5.TextLevel,       'Top5TextLevel');
+      ThemeLoadText(Top5.TextArtistTitle, 'Top5TextArtistTitle');
+      ThemeLoadStatics(Top5.StaticNumber, 'Top5StaticNumber');
+      ThemeLoadTexts(Top5.TextNumber,     'Top5TextNumber');
+      ThemeLoadTexts(Top5.TextName,       'Top5TextName');
+      ThemeLoadTexts(Top5.TextScore,      'Top5TextScore');
+      ThemeLoadTexts(Top5.TextDate,       'Top5TextDate');
+
+      // Options
+      ThemeLoadBasic(Options, 'Options');
+
+      ThemeLoadButton(Options.ButtonGame,     'OptionsButtonGame');
+      ThemeLoadButton(Options.ButtonGraphics, 'OptionsButtonGraphics');
+      ThemeLoadButton(Options.ButtonSound,    'OptionsButtonSound');
+      ThemeLoadButton(Options.ButtonLyrics,   'OptionsButtonLyrics');
+      ThemeLoadButton(Options.ButtonThemes,   'OptionsButtonThemes');
+      ThemeLoadButton(Options.ButtonRecord,   'OptionsButtonRecord');
+      ThemeLoadButton(Options.ButtonAdvanced, 'OptionsButtonAdvanced');
+      ThemeLoadButton(Options.ButtonExit,     'OptionsButtonExit');
+
+      Options.Description[0] := Language.Translate('SING_OPTIONS_GAME_DESC');
+      Options.Description[1] := Language.Translate('SING_OPTIONS_GRAPHICS_DESC');
+      Options.Description[2] := Language.Translate('SING_OPTIONS_SOUND_DESC');
+      Options.Description[3] := Language.Translate('SING_OPTIONS_LYRICS_DESC');
+      Options.Description[4] := Language.Translate('SING_OPTIONS_THEMES_DESC');
+      Options.Description[5] := Language.Translate('SING_OPTIONS_RECORD_DESC');
+      Options.Description[6] := Language.Translate('SING_OPTIONS_ADVANCED_DESC');
+      Options.Description[7] := Language.Translate('SING_OPTIONS_EXIT');
+
+      ThemeLoadText(Options.TextDescription, 'OptionsTextDescription');
+      Options.TextDescription.Text := Options.Description[0];
+
+      // Options Game
+      ThemeLoadBasic(OptionsGame, 'OptionsGame');
+
+      ThemeLoadSelectSlide(OptionsGame.SelectPlayers,    'OptionsGameSelectPlayers');
+      ThemeLoadSelectSlide(OptionsGame.SelectDifficulty, 'OptionsGameSelectDifficulty');
+      ThemeLoadSelectSlide(OptionsGame.SelectLanguage,   'OptionsGameSelectSlideLanguage');
+      ThemeLoadSelectSlide(OptionsGame.SelectTabs,       'OptionsGameSelectTabs');
+      ThemeLoadSelectSlide(OptionsGame.SelectSorting,    'OptionsGameSelectSlideSorting');
+      ThemeLoadSelectSlide(OptionsGame.SelectDebug,      'OptionsGameSelectDebug');
+      ThemeLoadButton(OptionsGame.ButtonExit,            'OptionsGameButtonExit');
+
+      // Options Graphics
+      ThemeLoadBasic(OptionsGraphics, 'OptionsGraphics');
+
+      ThemeLoadSelectSlide(OptionsGraphics.SelectFullscreen,   'OptionsGraphicsSelectFullscreen');
+      ThemeLoadSelectSlide(OptionsGraphics.SelectResolution,   'OptionsGraphicsSelectSlideResolution');
+      ThemeLoadSelectSlide(OptionsGraphics.SelectDepth,        'OptionsGraphicsSelectDepth');
+      ThemeLoadSelectSlide(OptionsGraphics.SelectVisualizer,   'OptionsGraphicsSelectVisualizer');
+      ThemeLoadSelectSlide(OptionsGraphics.SelectOscilloscope, 'OptionsGraphicsSelectOscilloscope');
+      ThemeLoadSelectSlide(OptionsGraphics.SelectLineBonus,    'OptionsGraphicsSelectLineBonus');
+      ThemeLoadSelectSlide(OptionsGraphics.SelectMovieSize,    'OptionsGraphicsSelectMovieSize');
+      ThemeLoadButton(OptionsGraphics.ButtonExit,              'OptionsGraphicsButtonExit');
+
+      // Options Sound
+      ThemeLoadBasic(OptionsSound, 'OptionsSound');
+
+      ThemeLoadSelectSlide(OptionsSound.SelectBackgroundMusic,       'OptionsSoundSelectBackgroundMusic');
+      ThemeLoadSelectSlide(OptionsSound.SelectMicBoost,              'OptionsSoundSelectMicBoost');
+      ThemeLoadSelectSlide(OptionsSound.SelectClickAssist,           'OptionsSoundSelectClickAssist');
+      ThemeLoadSelectSlide(OptionsSound.SelectBeatClick,             'OptionsSoundSelectBeatClick');
+      ThemeLoadSelectSlide(OptionsSound.SelectThreshold,             'OptionsSoundSelectThreshold');
+      //Song Preview
+      ThemeLoadSelectSlide(OptionsSound.SelectSlidePreviewVolume,    'OptionsSoundSelectSlidePreviewVolume');
+      ThemeLoadSelectSlide(OptionsSound.SelectSlidePreviewFading,    'OptionsSoundSelectSlidePreviewFading');
+      ThemeLoadSelectSlide(OptionsSound.SelectSlideVoicePassthrough, 'OptionsSoundSelectVoicePassthrough');
+
+      ThemeLoadButton(OptionsSound.ButtonExit, 'OptionsSoundButtonExit');
+
+      // Options Lyrics
+      ThemeLoadBasic(OptionsLyrics, 'OptionsLyrics');
+
+      ThemeLoadSelectSlide(OptionsLyrics.SelectLyricsFont,   'OptionsLyricsSelectLyricsFont');
+      ThemeLoadSelectSlide(OptionsLyrics.SelectLyricsEffect, 'OptionsLyricsSelectLyricsEffect');
+      //ThemeLoadSelectSlide(OptionsLyrics.SelectSolmization,     'OptionsLyricsSelectSolmization');
+      ThemeLoadSelectSlide(OptionsLyrics.SelectNoteLines,    'OptionsLyricsSelectNoteLines');
+      ThemeLoadButton(OptionsLyrics.ButtonExit,              'OptionsLyricsButtonExit');
+
+      // Options Themes
+      ThemeLoadBasic(OptionsThemes, 'OptionsThemes');
+
+      ThemeLoadSelectSlide(OptionsThemes.SelectTheme, 'OptionsThemesSelectTheme');
+      ThemeLoadSelectSlide(OptionsThemes.SelectSkin,  'OptionsThemesSelectSkin');
+      ThemeLoadSelectSlide(OptionsThemes.SelectColor, 'OptionsThemesSelectColor');
+      ThemeLoadButton(OptionsThemes.ButtonExit,       'OptionsThemesButtonExit');
+
+      // Options Record
+      ThemeLoadBasic(OptionsRecord, 'OptionsRecord');
+
+      ThemeLoadSelectSlide(OptionsRecord.SelectSlideCard,     'OptionsRecordSelectSlideCard');
+      ThemeLoadSelectSlide(OptionsRecord.SelectSlideInput,    'OptionsRecordSelectSlideInput');
+      ThemeLoadSelectSlide(OptionsRecord.SelectSlideChannel,  'OptionsRecordSelectSlideChannel');
+      ThemeLoadButton(OptionsRecord.ButtonExit,               'OptionsRecordButtonExit');
+
+      //Options Advanced
+      ThemeLoadBasic(OptionsAdvanced, 'OptionsAdvanced');
+
+      ThemeLoadSelectSlide(OptionsAdvanced.SelectLoadAnimation, 'OptionsAdvancedSelectLoadAnimation');
+      ThemeLoadSelectSlide(OptionsAdvanced.SelectScreenFade,    'OptionsAdvancedSelectScreenFade');
+      ThemeLoadSelectSlide(OptionsAdvanced.SelectEffectSing,    'OptionsAdvancedSelectEffectSing');
+      ThemeLoadSelectSlide(OptionsAdvanced.SelectLineBonus,     'OptionsAdvancedSelectLineBonus');
+      ThemeLoadSelectSlide(OptionsAdvanced.SelectOnSongClick,   'OptionsAdvancedSelectSlideOnSongClick');
+      ThemeLoadSelectSlide(OptionsAdvanced.SelectAskbeforeDel,  'OptionsAdvancedSelectAskbeforeDel');
+      ThemeLoadSelectSlide(OptionsAdvanced.SelectPartyPopup,    'OptionsAdvancedSelectPartyPopup');
+      ThemeLoadButton     (OptionsAdvanced.ButtonExit,          'OptionsAdvancedButtonExit');
+
+      //Edit Menu
+      ThemeLoadBasic (Edit,               'Edit');
+
+      ThemeLoadButton(Edit.ButtonConvert, 'EditButtonConvert');
+      ThemeLoadButton(Edit.ButtonExit,    'EditButtonExit');
+
+      Edit.Description[0] := Language.Translate('SING_EDIT_BUTTON_DESCRIPTION_CONVERT');
+      Edit.Description[1] := Language.Translate('SING_EDIT_BUTTON_DESCRIPTION_EXIT');
+
+      ThemeLoadText(Edit.TextDescription, 'EditTextDescription');
+      Edit.TextDescription.Text := Edit.Description[0];
+
+      //error and check popup
+      ThemeLoadBasic (ErrorPopup, 'ErrorPopup');
+      ThemeLoadButton(ErrorPopup.Button1, 'ErrorPopupButton1');
+      ThemeLoadText  (ErrorPopup.TextError,'ErrorPopupText');
+      ThemeLoadBasic (CheckPopup, 'CheckPopup');
+      ThemeLoadButton(CheckPopup.Button1, 'CheckPopupButton1');
+      ThemeLoadButton(CheckPopup.Button2, 'CheckPopupButton2');
+      ThemeLoadText(CheckPopup.TextCheck , 'CheckPopupText');
+
+      //Song Menu
+      ThemeLoadBasic (SongMenu, 'SongMenu');
+      ThemeLoadButton(SongMenu.Button1, 'SongMenuButton1');
+      ThemeLoadButton(SongMenu.Button2, 'SongMenuButton2');
+      ThemeLoadButton(SongMenu.Button3, 'SongMenuButton3');
+      ThemeLoadButton(SongMenu.Button4, 'SongMenuButton4');
+      ThemeLoadSelectSlide(SongMenu.SelectSlide3, 'SongMenuSelectSlide3');
+
+      ThemeLoadText(SongMenu.TextMenu, 'SongMenuTextMenu');
+
+      //Song Jumpto
+      ThemeLoadBasic (SongJumpto, 'SongJumpto');
+      ThemeLoadButton(SongJumpto.ButtonSearchText, 'SongJumptoButtonSearchText');
+      ThemeLoadSelectSlide(SongJumpto.SelectSlideType, 'SongJumptoSelectSlideType');
+      ThemeLoadText(SongJumpto.TextFound, 'SongJumptoTextFound');
+      //Translations
+      SongJumpto.IType[0] := Language.Translate('SONG_JUMPTO_TYPE1');
+      SongJumpto.IType[1] := Language.Translate('SONG_JUMPTO_TYPE2');
+      SongJumpto.IType[2] := Language.Translate('SONG_JUMPTO_TYPE3');
+      SongJumpto.SongsFound := Language.Translate('SONG_JUMPTO_SONGSFOUND');
+      SongJumpto.NoSongsFound := Language.Translate('SONG_JUMPTO_NOSONGSFOUND');
+      SongJumpto.CatText := Language.Translate('SONG_JUMPTO_CATTEXT');
+
+      //Party Screens:
+      //Party NewRound
+      ThemeLoadBasic(PartyNewRound, 'PartyNewRound');
+
+      ThemeLoadText (PartyNewRound.TextRound1, 'PartyNewRoundTextRound1');
+      ThemeLoadText (PartyNewRound.TextRound2, 'PartyNewRoundTextRound2');
+      ThemeLoadText (PartyNewRound.TextRound3, 'PartyNewRoundTextRound3');
+      ThemeLoadText (PartyNewRound.TextRound4, 'PartyNewRoundTextRound4');
+      ThemeLoadText (PartyNewRound.TextRound5, 'PartyNewRoundTextRound5');
+      ThemeLoadText (PartyNewRound.TextRound6, 'PartyNewRoundTextRound6');
+      ThemeLoadText (PartyNewRound.TextRound7, 'PartyNewRoundTextRound7');
+      ThemeLoadText (PartyNewRound.TextWinner1, 'PartyNewRoundTextWinner1');
+      ThemeLoadText (PartyNewRound.TextWinner2, 'PartyNewRoundTextWinner2');
+      ThemeLoadText (PartyNewRound.TextWinner3, 'PartyNewRoundTextWinner3');
+      ThemeLoadText (PartyNewRound.TextWinner4, 'PartyNewRoundTextWinner4');
+      ThemeLoadText (PartyNewRound.TextWinner5, 'PartyNewRoundTextWinner5');
+      ThemeLoadText (PartyNewRound.TextWinner6, 'PartyNewRoundTextWinner6');
+      ThemeLoadText (PartyNewRound.TextWinner7, 'PartyNewRoundTextWinner7');
+      ThemeLoadText (PartyNewRound.TextNextRound, 'PartyNewRoundTextNextRound');
+      ThemeLoadText (PartyNewRound.TextNextRoundNo, 'PartyNewRoundTextNextRoundNo');
+      ThemeLoadText (PartyNewRound.TextNextPlayer1, 'PartyNewRoundTextNextPlayer1');
+      ThemeLoadText (PartyNewRound.TextNextPlayer2, 'PartyNewRoundTextNextPlayer2');
+      ThemeLoadText (PartyNewRound.TextNextPlayer3, 'PartyNewRoundTextNextPlayer3');
+
+      ThemeLoadStatic (PartyNewRound.StaticRound1, 'PartyNewRoundStaticRound1');
+      ThemeLoadStatic (PartyNewRound.StaticRound2, 'PartyNewRoundStaticRound2');
+      ThemeLoadStatic (PartyNewRound.StaticRound3, 'PartyNewRoundStaticRound3');
+      ThemeLoadStatic (PartyNewRound.StaticRound4, 'PartyNewRoundStaticRound4');
+      ThemeLoadStatic (PartyNewRound.StaticRound5, 'PartyNewRoundStaticRound5');
+      ThemeLoadStatic (PartyNewRound.StaticRound6, 'PartyNewRoundStaticRound6');
+      ThemeLoadStatic (PartyNewRound.StaticRound7, 'PartyNewRoundStaticRound7');
+
+      ThemeLoadText (PartyNewRound.TextScoreTeam1, 'PartyNewRoundTextScoreTeam1');
+      ThemeLoadText (PartyNewRound.TextScoreTeam2, 'PartyNewRoundTextScoreTeam2');
+      ThemeLoadText (PartyNewRound.TextScoreTeam3, 'PartyNewRoundTextScoreTeam3');
+      ThemeLoadText (PartyNewRound.TextNameTeam1, 'PartyNewRoundTextNameTeam1');
+      ThemeLoadText (PartyNewRound.TextNameTeam2, 'PartyNewRoundTextNameTeam2');
+      ThemeLoadText (PartyNewRound.TextNameTeam3, 'PartyNewRoundTextNameTeam3');
+
+      ThemeLoadText (PartyNewRound.TextTeam1Players, 'PartyNewRoundTextTeam1Players');
+      ThemeLoadText (PartyNewRound.TextTeam2Players, 'PartyNewRoundTextTeam2Players');
+      ThemeLoadText (PartyNewRound.TextTeam3Players, 'PartyNewRoundTextTeam3Players');
+
+      ThemeLoadStatic (PartyNewRound.StaticTeam1, 'PartyNewRoundStaticTeam1');
+      ThemeLoadStatic (PartyNewRound.StaticTeam2, 'PartyNewRoundStaticTeam2');
+      ThemeLoadStatic (PartyNewRound.StaticTeam3, 'PartyNewRoundStaticTeam3');
+      ThemeLoadStatic (PartyNewRound.StaticNextPlayer1, 'PartyNewRoundStaticNextPlayer1');
+      ThemeLoadStatic (PartyNewRound.StaticNextPlayer2, 'PartyNewRoundStaticNextPlayer2');
+      ThemeLoadStatic (PartyNewRound.StaticNextPlayer3, 'PartyNewRoundStaticNextPlayer3');
+
+      //Party Score
+      ThemeLoadBasic(PartyScore, 'PartyScore');
+
+      ThemeLoadText (PartyScore.TextScoreTeam1, 'PartyScoreTextScoreTeam1');
+      ThemeLoadText (PartyScore.TextScoreTeam2, 'PartyScoreTextScoreTeam2');
+      ThemeLoadText (PartyScore.TextScoreTeam3, 'PartyScoreTextScoreTeam3');
+      ThemeLoadText (PartyScore.TextNameTeam1, 'PartyScoreTextNameTeam1');
+      ThemeLoadText (PartyScore.TextNameTeam2, 'PartyScoreTextNameTeam2');
+      ThemeLoadText (PartyScore.TextNameTeam3, 'PartyScoreTextNameTeam3');
+
+      ThemeLoadStatic (PartyScore.StaticTeam1, 'PartyScoreStaticTeam1');
+      ThemeLoadStatic (PartyScore.StaticTeam1BG, 'PartyScoreStaticTeam1BG');
+      ThemeLoadStatic (PartyScore.StaticTeam1Deco, 'PartyScoreStaticTeam1Deco');
+      ThemeLoadStatic (PartyScore.StaticTeam2, 'PartyScoreStaticTeam2');
+      ThemeLoadStatic (PartyScore.StaticTeam2BG, 'PartyScoreStaticTeam2BG');
+      ThemeLoadStatic (PartyScore.StaticTeam2Deco, 'PartyScoreStaticTeam2Deco');
+      ThemeLoadStatic (PartyScore.StaticTeam3, 'PartyScoreStaticTeam3');
+      ThemeLoadStatic (PartyScore.StaticTeam3BG, 'PartyScoreStaticTeam3BG');
+      ThemeLoadStatic (PartyScore.StaticTeam3Deco, 'PartyScoreStaticTeam3Deco');
+
+      //Load Party Score DecoTextures Object
+      PartyScore.DecoTextures.ChangeTextures := (ThemeIni.ReadInteger('PartyScoreDecoTextures', 'ChangeTextures', 0) = 1);
+      PartyScore.DecoTextures.FirstTexture   :=  ThemeIni.ReadString('PartyScoreDecoTextures',  'FirstTexture', '');
+      PartyScore.DecoTextures.FirstTyp       :=  ParseTextureType(ThemeIni.ReadString('PartyScoreDecoTextures', 'FirstTyp', ''), TEXTURE_TYPE_COLORIZED);
+      PartyScore.DecoTextures.FirstColor     :=  ThemeIni.ReadString('PartyScoreDecoTextures',  'FirstColor', 'Black');
+
+      PartyScore.DecoTextures.SecondTexture  :=  ThemeIni.ReadString('PartyScoreDecoTextures',  'SecondTexture', '');
+      PartyScore.DecoTextures.SecondTyp      :=  ParseTextureType(ThemeIni.ReadString('PartyScoreDecoTextures', 'SecondTyp', ''), TEXTURE_TYPE_COLORIZED);
+      PartyScore.DecoTextures.SecondColor    :=  ThemeIni.ReadString('PartyScoreDecoTextures',  'SecondColor', 'Black');
+
+      PartyScore.DecoTextures.ThirdTexture   :=  ThemeIni.ReadString('PartyScoreDecoTextures',  'ThirdTexture', '');
+      PartyScore.DecoTextures.ThirdTyp       :=  ParseTextureType(ThemeIni.ReadString('PartyScoreDecoTextures', 'ThirdTyp', ''), TEXTURE_TYPE_COLORIZED);
+      PartyScore.DecoTextures.ThirdColor     :=  ThemeIni.ReadString('PartyScoreDecoTextures',  'ThirdColor', 'Black');
+
+      ThemeLoadText (PartyScore.TextWinner, 'PartyScoreTextWinner');
+
+      //Party Win
+      ThemeLoadBasic(PartyWin, 'PartyWin');
+
+      ThemeLoadText (PartyWin.TextScoreTeam1,    'PartyWinTextScoreTeam1');
+      ThemeLoadText (PartyWin.TextScoreTeam2,    'PartyWinTextScoreTeam2');
+      ThemeLoadText (PartyWin.TextScoreTeam3,    'PartyWinTextScoreTeam3');
+      ThemeLoadText (PartyWin.TextNameTeam1,     'PartyWinTextNameTeam1');
+      ThemeLoadText (PartyWin.TextNameTeam2,     'PartyWinTextNameTeam2');
+      ThemeLoadText (PartyWin.TextNameTeam3,     'PartyWinTextNameTeam3');
+
+      ThemeLoadStatic (PartyWin.StaticTeam1,     'PartyWinStaticTeam1');
+      ThemeLoadStatic (PartyWin.StaticTeam1BG,   'PartyWinStaticTeam1BG');
+      ThemeLoadStatic (PartyWin.StaticTeam1Deco, 'PartyWinStaticTeam1Deco');
+      ThemeLoadStatic (PartyWin.StaticTeam2,     'PartyWinStaticTeam2');
+      ThemeLoadStatic (PartyWin.StaticTeam2BG,   'PartyWinStaticTeam2BG');
+      ThemeLoadStatic (PartyWin.StaticTeam2Deco, 'PartyWinStaticTeam2Deco');
+      ThemeLoadStatic (PartyWin.StaticTeam3,     'PartyWinStaticTeam3');
+      ThemeLoadStatic (PartyWin.StaticTeam3BG,   'PartyWinStaticTeam3BG');
+      ThemeLoadStatic (PartyWin.StaticTeam3Deco, 'PartyWinStaticTeam3Deco');
+
+      ThemeLoadText (PartyWin.TextWinner,        'PartyWinTextWinner');
+
+      //Party Options
+      ThemeLoadBasic(PartyOptions, 'PartyOptions');
+      ThemeLoadSelectSlide(PartyOptions.SelectLevel, 'PartyOptionsSelectLevel');
+      ThemeLoadSelectSlide(PartyOptions.SelectPlayList, 'PartyOptionsSelectPlayList');
+      ThemeLoadSelectSlide(PartyOptions.SelectPlayList2, 'PartyOptionsSelectPlayList2');
+      {ThemeLoadButton (ButtonNext, 'ButtonNext');
+      ThemeLoadButton (ButtonPrev, 'ButtonPrev');}
+
+      //Party Player
+      ThemeLoadBasic(PartyPlayer, 'PartyPlayer');
+
+      ThemeLoadSelectSlide(PartyPlayer.SelectTeams, 'PartyPlayerSelectTeams');
+      ThemeLoadSelectSlide(PartyPlayer.SelectPlayers1, 'PartyPlayerSelectPlayers1');
+      ThemeLoadSelectSlide(PartyPlayer.SelectPlayers2, 'PartyPlayerSelectPlayers2');
+      ThemeLoadSelectSlide(PartyPlayer.SelectPlayers3, 'PartyPlayerSelectPlayers3');
+
+      ThemeLoadButton(PartyPlayer.Team1Name, 'PartyPlayerTeam1Name');
+      ThemeLoadButton(PartyPlayer.Player1Name, 'PartyPlayerPlayer1Name');
+      ThemeLoadButton(PartyPlayer.Player2Name, 'PartyPlayerPlayer2Name');
+      ThemeLoadButton(PartyPlayer.Player3Name, 'PartyPlayerPlayer3Name');
+      ThemeLoadButton(PartyPlayer.Player4Name, 'PartyPlayerPlayer4Name');
+
+      ThemeLoadButton(PartyPlayer.Team2Name, 'PartyPlayerTeam2Name');
+      ThemeLoadButton(PartyPlayer.Player5Name, 'PartyPlayerPlayer5Name');
+      ThemeLoadButton(PartyPlayer.Player6Name, 'PartyPlayerPlayer6Name');
+      ThemeLoadButton(PartyPlayer.Player7Name, 'PartyPlayerPlayer7Name');
+      ThemeLoadButton(PartyPlayer.Player8Name, 'PartyPlayerPlayer8Name');
+
+      ThemeLoadButton(PartyPlayer.Team3Name, 'PartyPlayerTeam3Name');
+      ThemeLoadButton(PartyPlayer.Player9Name, 'PartyPlayerPlayer9Name');
+      ThemeLoadButton(PartyPlayer.Player10Name, 'PartyPlayerPlayer10Name');
+      ThemeLoadButton(PartyPlayer.Player11Name, 'PartyPlayerPlayer11Name');
+      ThemeLoadButton(PartyPlayer.Player12Name, 'PartyPlayerPlayer12Name');
+
+      // Party Rounds
+      ThemeLoadBasic(PartyRounds, 'PartyRounds');
+
+      ThemeLoadSelectSlide(PartyRounds.SelectRoundCount, 'PartyRoundsSelectRoundCount');
+      for I := 0 to High(PartyRounds.SelectRound) do
+        ThemeLoadSelectSlide(PartyRounds.SelectRound[I], 'PartyRoundsSelectRound' + IntToStr(I + 1));
+
+      {ThemeLoadButton(ButtonNext, 'PartyPlayerButtonNext');
+      ThemeLoadButton(ButtonPrev, 'PartyPlayerButtonPrev');}
+
+      ThemeLoadBasic(StatMain, 'StatMain');
+
+      ThemeLoadButton(StatMain.ButtonScores, 'StatMainButtonScores');
+      ThemeLoadButton(StatMain.ButtonSingers, 'StatMainButtonSingers');
+      ThemeLoadButton(StatMain.ButtonSongs, 'StatMainButtonSongs');
+      ThemeLoadButton(StatMain.ButtonBands, 'StatMainButtonBands');
+      ThemeLoadButton(StatMain.ButtonExit, 'StatMainButtonExit');
+
+      ThemeLoadText (StatMain.TextOverview, 'StatMainTextOverview');
+
+
+      ThemeLoadBasic(StatDetail, 'StatDetail');
+
+      ThemeLoadButton(StatDetail.ButtonNext, 'StatDetailButtonNext');
+      ThemeLoadButton(StatDetail.ButtonPrev, 'StatDetailButtonPrev');
+      ThemeLoadButton(StatDetail.ButtonReverse, 'StatDetailButtonReverse');
+      ThemeLoadButton(StatDetail.ButtonExit, 'StatDetailButtonExit');
+
+      ThemeLoadText (StatDetail.TextDescription, 'StatDetailTextDescription');
+      ThemeLoadText (StatDetail.TextPage, 'StatDetailTextPage');
+      ThemeLoadTexts(StatDetail.TextList, 'StatDetailTextList');
+
+      //Translate Texts
+      StatDetail.Description[0] := Language.Translate('STAT_DESC_SCORES');
+      StatDetail.Description[1] := Language.Translate('STAT_DESC_SINGERS');
+      StatDetail.Description[2] := Language.Translate('STAT_DESC_SONGS');
+      StatDetail.Description[3] := Language.Translate('STAT_DESC_BANDS');
+
+      StatDetail.DescriptionR[0] := Language.Translate('STAT_DESC_SCORES_REVERSED');
+      StatDetail.DescriptionR[1] := Language.Translate('STAT_DESC_SINGERS_REVERSED');
+      StatDetail.DescriptionR[2] := Language.Translate('STAT_DESC_SONGS_REVERSED');
+      StatDetail.DescriptionR[3] := Language.Translate('STAT_DESC_BANDS_REVERSED');
+
+      StatDetail.FormatStr[0] := Language.Translate('STAT_FORMAT_SCORES');
+      StatDetail.FormatStr[1] := Language.Translate('STAT_FORMAT_SINGERS');
+      StatDetail.FormatStr[2] := Language.Translate('STAT_FORMAT_SONGS');
+      StatDetail.FormatStr[3] := Language.Translate('STAT_FORMAT_BANDS');
+
+      StatDetail.PageStr := Language.Translate('STAT_PAGE');
+
+      //Playlist Translations
+      Playlist.CatText := Language.Translate('PLAYLIST_CATTEXT');
+
+      //Level Translations
+      //Fill ILevel
+      ILevel[0] := Language.Translate('SING_EASY');
+      ILevel[1] := Language.Translate('SING_MEDIUM');
+      ILevel[2] := Language.Translate('SING_HARD');
+    end;
+
+    ThemeIni.Free;
+  end;
+end;
+
+procedure TTheme.ThemeLoadBasic(Theme: TThemeBasic; const Name: string);
+begin
+  ThemeLoadBackground(Theme.Background, Name);
+  ThemeLoadTexts(Theme.Text, Name + 'Text');
+  ThemeLoadStatics(Theme.Statics, Name + 'Static');
+  ThemeLoadButtonCollections(Theme.ButtonCollection, Name + 'ButtonCollection');
+
+  LastThemeBasic := Theme;
+end;
+
+procedure TTheme.ThemeLoadBackground(var ThemeBackground: TThemeBackground; const Name: string);
+var
+  BGType: string;
+  I: TBackgroundType;
+begin
+  BGType := LowerCase(ThemeIni.ReadString(Name + 'Background', 'Type', 'auto'));
+
+  ThemeBackground.BGType := bgtAuto;
+  for I := Low(BGT_Names) to High(BGT_Names) do
+  begin
+    if (BGT_Names[I] = BGType) then
+    begin
+      ThemeBackground.BGType := I;
+      Break;
+    end;
+  end;
+
+  ThemeBackground.Tex     := ThemeIni.ReadString(Name + 'Background', 'Tex', '');
+  ThemeBackground.Color.R := ThemeIni.ReadFloat(Name + 'Background', 'ColR', 1);
+  ThemeBackground.Color.G := ThemeIni.ReadFloat(Name + 'Background', 'ColG', 1);
+  ThemeBackground.Color.B := ThemeIni.ReadFloat(Name + 'Background', 'ColB', 1);
+  ThemeBackground.Alpha   := ThemeIni.ReadFloat(Name + 'Background', 'Alpha', 1);
+end;
+
+procedure TTheme.ThemeLoadText(var ThemeText: TThemeText; const Name: string);
+var
+  C: integer;
+begin
+  ThemeText.X     := ThemeIni.ReadInteger(Name, 'X', 0);
+  ThemeText.Y     := ThemeIni.ReadInteger(Name, 'Y', 0);
+  ThemeText.W     := ThemeIni.ReadInteger(Name, 'W', 0);
+
+  ThemeText.Z     := ThemeIni.ReadFloat(Name, 'Z', 0);
+
+  ThemeText.ColR  := ThemeIni.ReadFloat(Name, 'ColR', 0);
+  ThemeText.ColG  := ThemeIni.ReadFloat(Name, 'ColG', 0);
+  ThemeText.ColB  := ThemeIni.ReadFloat(Name, 'ColB', 0);
+
+  ThemeText.Font  := ThemeIni.ReadInteger(Name, 'Font', ftNormal);
+  ThemeText.Size  := ThemeIni.ReadInteger(Name, 'Size', 0);
+  ThemeText.Align := ThemeIni.ReadInteger(Name, 'Align', 0);
+
+  ThemeText.Text  := Language.Translate(ThemeIni.ReadString(Name, 'Text', ''));
+  ThemeText.Color := ThemeIni.ReadString(Name, 'Color', '');
+
+  //Reflection
+  ThemeText.Reflection         := (ThemeIni.ReadInteger(Name, 'Reflection', 0)) = 1;
+  ThemeText.Reflectionspacing  := ThemeIni.ReadFloat(Name, 'ReflectionSpacing', 15);
+
+  C := ColorExists(ThemeText.Color);
+  if C >= 0 then
+  begin
+    ThemeText.ColR := Color[C].RGB.R;
+    ThemeText.ColG := Color[C].RGB.G;
+    ThemeText.ColB := Color[C].RGB.B;
+  end;
+end;
+
+procedure TTheme.ThemeLoadTexts(var ThemeText: AThemeText; const Name: string);
+var
+  T: integer;
+begin
+  T := 1;
+  while ThemeIni.SectionExists(Name + IntToStr(T)) do
+  begin
+    SetLength(ThemeText, T);
+    ThemeLoadText(ThemeText[T-1], Name + IntToStr(T));
+    Inc(T);
+  end;
+end;
+
+procedure TTheme.ThemeLoadStatic(var ThemeStatic: TThemeStatic; const Name: string);
+var
+  C: integer;
+begin
+  ThemeStatic.Tex := ThemeIni.ReadString(Name, 'Tex', '');
+
+  ThemeStatic.X := ThemeIni.ReadInteger(Name, 'X', 0);
+  ThemeStatic.Y := ThemeIni.ReadInteger(Name, 'Y', 0);
+  ThemeStatic.Z := ThemeIni.ReadFloat  (Name, 'Z', 0);
+  ThemeStatic.W := ThemeIni.ReadInteger(Name, 'W', 0);
+  ThemeStatic.H := ThemeIni.ReadInteger(Name, 'H', 0);
+
+  ThemeStatic.Typ   := ParseTextureType(ThemeIni.ReadString(Name, 'Type', ''), TEXTURE_TYPE_PLAIN);
+  ThemeStatic.Color := ThemeIni.ReadString(Name, 'Color', '');
+
+  C := ColorExists(ThemeStatic.Color);
+  if C >= 0 then
+  begin
+    ThemeStatic.ColR := Color[C].RGB.R;
+    ThemeStatic.ColG := Color[C].RGB.G;
+    ThemeStatic.ColB := Color[C].RGB.B;
+  end;
+
+  ThemeStatic.TexX1 := ThemeIni.ReadFloat(Name, 'TexX1', 0);
+  ThemeStatic.TexY1 := ThemeIni.ReadFloat(Name, 'TexY1', 0);
+  ThemeStatic.TexX2 := ThemeIni.ReadFloat(Name, 'TexX2', 1);
+  ThemeStatic.TexY2 := ThemeIni.ReadFloat(Name, 'TexY2', 1);
+
+  //Reflection Mod
+  ThemeStatic.Reflection        := (ThemeIni.ReadInteger(Name, 'Reflection', 0) = 1);
+  ThemeStatic.ReflectionSpacing := ThemeIni.ReadFloat(Name, 'ReflectionSpacing', 15);
+end;
+
+procedure TTheme.ThemeLoadStatics(var ThemeStatic: AThemeStatic; const Name: string);
+var
+  S: integer;
+begin
+  S := 1;
+  while ThemeIni.SectionExists(Name + IntToStr(S)) do
+  begin
+    SetLength(ThemeStatic, S);
+    ThemeLoadStatic(ThemeStatic[S-1], Name + IntToStr(S));
+    Inc(S);
+  end;
+end;
+
+//Button Collection Mod
+procedure TTheme.ThemeLoadButtonCollection(var Collection: TThemeButtonCollection; const Name: string);
+var T: integer;
+begin
+  //Load Collection Style
+  ThemeLoadButton(Collection.Style, Name);
+
+  //Load Other Attributes
+  T := ThemeIni.ReadInteger (Name, 'FirstChild', 0);
+  if (T > 0) And (T < 256) then
+    Collection.FirstChild := T
+  else
+    Collection.FirstChild := 0;
+end;
+
+procedure TTheme.ThemeLoadButtonCollections(var Collections: AThemeButtonCollection; const Name: string);
+var
+  I: integer;
+begin
+  I := 1;
+  while ThemeIni.SectionExists(Name + IntToStr(I)) do
+  begin
+    SetLength(Collections, I);
+    ThemeLoadButtonCollection(Collections[I-1], Name + IntToStr(I));
+    Inc(I);
+  end;
+end;
+//End Button Collection Mod
+
+procedure TTheme.ThemeLoadButton(var ThemeButton: TThemeButton; const Name: string; Collections: PAThemeButtonCollection);
+var
+  C:    integer;
+  TLen: integer;
+  T:    integer;
+  Collections2: PAThemeButtonCollection;
+begin
+  if not ThemeIni.SectionExists(Name) then
+  begin
+    ThemeButton.Visible := False;
+    exit;
+  end;
+  ThemeButton.Tex := ThemeIni.ReadString(Name, 'Tex', '');
+  ThemeButton.X := ThemeIni.ReadInteger (Name, 'X', 0);
+  ThemeButton.Y := ThemeIni.ReadInteger (Name, 'Y', 0);
+  ThemeButton.Z := ThemeIni.ReadFloat   (Name, 'Z', 0);
+  ThemeButton.W := ThemeIni.ReadInteger (Name, 'W', 0);
+  ThemeButton.H := ThemeIni.ReadInteger (Name, 'H', 0);
+  ThemeButton.Typ := ParseTextureType(ThemeIni.ReadString(Name, 'Type', ''), TEXTURE_TYPE_PLAIN);
+
+  //Reflection Mod
+  ThemeButton.Reflection := (ThemeIni.ReadInteger(Name, 'Reflection', 0) = 1);
+  ThemeButton.ReflectionSpacing := ThemeIni.ReadFloat(Name, 'ReflectionSpacing', 15);
+
+  ThemeButton.ColR := ThemeIni.ReadFloat(Name, 'ColR', 1);
+  ThemeButton.ColG := ThemeIni.ReadFloat(Name, 'ColG', 1);
+  ThemeButton.ColB := ThemeIni.ReadFloat(Name, 'ColB', 1);
+  ThemeButton.Int :=  ThemeIni.ReadFloat(Name, 'Int', 1);
+  ThemeButton.DColR := ThemeIni.ReadFloat(Name, 'DColR', 1);
+  ThemeButton.DColG := ThemeIni.ReadFloat(Name, 'DColG', 1);
+  ThemeButton.DColB := ThemeIni.ReadFloat(Name, 'DColB', 1);
+  ThemeButton.DInt :=  ThemeIni.ReadFloat(Name, 'DInt', 1);
+
+  ThemeButton.Color := ThemeIni.ReadString(Name, 'Color', '');
+  C := ColorExists(ThemeButton.Color);
+  if C >= 0 then
+  begin
+    ThemeButton.ColR := Color[C].RGB.R;
+    ThemeButton.ColG := Color[C].RGB.G;
+    ThemeButton.ColB := Color[C].RGB.B;
+  end;
+
+  ThemeButton.DColor := ThemeIni.ReadString(Name, 'DColor', '');
+  C := ColorExists(ThemeButton.DColor);
+  if C >= 0 then
+  begin
+    ThemeButton.DColR := Color[C].RGB.R;
+    ThemeButton.DColG := Color[C].RGB.G;
+    ThemeButton.DColB := Color[C].RGB.B;
+  end;
+
+  ThemeButton.Visible := (ThemeIni.ReadInteger(Name, 'Visible', 1) = 1);
+
+  //Fade Mod
+  ThemeButton.SelectH := ThemeIni.ReadInteger (Name, 'SelectH', ThemeButton.H);
+  ThemeButton.SelectW := ThemeIni.ReadInteger (Name, 'SelectW', ThemeButton.W);
+
+  ThemeButton.DeSelectReflectionspacing := ThemeIni.ReadFloat(Name, 'DeSelectReflectionSpacing', ThemeButton.Reflectionspacing);
+
+  ThemeButton.Fade := (ThemeIni.ReadInteger(Name, 'Fade', 0) = 1);
+  ThemeButton.FadeText := (ThemeIni.ReadInteger(Name, 'FadeText', 0) = 1);
+
+
+  ThemeButton.FadeTex := ThemeIni.ReadString(Name, 'FadeTex', '');
+  ThemeButton.FadeTexPos:= ThemeIni.ReadInteger(Name, 'FadeTexPos', 0);
+  if (ThemeButton.FadeTexPos > 4) Or (ThemeButton.FadeTexPos < 0) then
+    ThemeButton.FadeTexPos := 0;
+
+  //Button Collection Mod
+  T := ThemeIni.ReadInteger(Name, 'Parent', 0);
+
+  //Set Collections to Last Basic Collections if no valid Value
+  if (Collections = nil) then
+    Collections2 := @LastThemeBasic.ButtonCollection
+  else
+    Collections2 := Collections;
+  //Test for valid Value
+  if (Collections2 <> nil) AND (T > 0) AND (T <= Length(Collections2^)) then
+  begin
+    Inc(Collections2^[T-1].ChildCount);
+    ThemeButton.Parent := T;
+  end
+  else
+    ThemeButton.Parent := 0;
+
+  //Read ButtonTexts
+  TLen := ThemeIni.ReadInteger(Name, 'Texts', 0);
+  SetLength(ThemeButton.Text, TLen);
+  for T := 1 to TLen do
+    ThemeLoadText(ThemeButton.Text[T-1], Name + 'Text' + IntToStr(T));
+end;
+
+procedure TTheme.ThemeLoadSelectSlide(var ThemeSelectS: TThemeSelectSlide; const Name: string);
+begin
+  ThemeSelectS.Text := Language.Translate(ThemeIni.ReadString(Name, 'Text', ''));
+
+  ThemeSelectS.Tex := {Skin.SkinPath + }ThemeIni.ReadString(Name, 'Tex', '');
+  ThemeSelectS.Typ := ParseTextureType(ThemeIni.ReadString(Name, 'Type', ''), TEXTURE_TYPE_PLAIN);
+  ThemeSelectS.TexSBG := {Skin.SkinPath + }ThemeIni.ReadString(Name, 'TexSBG', '');
+  ThemeSelectS.TypSBG := ParseTextureType(ThemeIni.ReadString(Name, 'TypeSBG', ''), TEXTURE_TYPE_PLAIN);
+
+  ThemeSelectS.X := ThemeIni.ReadInteger(Name, 'X', 0);
+  ThemeSelectS.Y := ThemeIni.ReadInteger(Name, 'Y', 0);
+  ThemeSelectS.W := ThemeIni.ReadInteger(Name, 'W', 0);
+  ThemeSelectS.H := ThemeIni.ReadInteger(Name, 'H', 0);
+
+  ThemeSelectS.Z := ThemeIni.ReadFloat(Name, 'Z', 0);
+
+  ThemeSelectS.TextSize := ThemeIni.ReadInteger(Name, 'TextSize', 30);
+
+  ThemeSelectS.SkipX := ThemeIni.ReadInteger(Name, 'SkipX', 0);
+
+  ThemeSelectS.SBGW := ThemeIni.ReadInteger(Name, 'SBGW', 400);
+
+  LoadColor(ThemeSelectS.ColR, ThemeSelectS.ColG,  ThemeSelectS.ColB, ThemeIni.ReadString(Name, 'Color', ''));
+  ThemeSelectS.Int :=  ThemeIni.ReadFloat(Name, 'Int', 1);
+  LoadColor(ThemeSelectS.DColR, ThemeSelectS.DColG,  ThemeSelectS.DColB, ThemeIni.ReadString(Name, 'DColor', ''));
+  ThemeSelectS.DInt :=  ThemeIni.ReadFloat(Name, 'DInt', 1);
+
+  LoadColor(ThemeSelectS.TColR, ThemeSelectS.TColG,  ThemeSelectS.TColB, ThemeIni.ReadString(Name, 'TColor', ''));
+  ThemeSelectS.TInt :=  ThemeIni.ReadFloat(Name, 'TInt', 1);
+  LoadColor(ThemeSelectS.TDColR, ThemeSelectS.TDColG,  ThemeSelectS.TDColB, ThemeIni.ReadString(Name, 'TDColor', ''));
+  ThemeSelectS.TDInt :=  ThemeIni.ReadFloat(Name, 'TDInt', 1);
+
+  LoadColor(ThemeSelectS.SBGColR, ThemeSelectS.SBGColG,  ThemeSelectS.SBGColB, ThemeIni.ReadString(Name, 'SBGColor', ''));
+  ThemeSelectS.SBGInt :=  ThemeIni.ReadFloat(Name, 'SBGInt', 1);
+  LoadColor(ThemeSelectS.SBGDColR, ThemeSelectS.SBGDColG,  ThemeSelectS.SBGDColB, ThemeIni.ReadString(Name, 'SBGDColor', ''));
+  ThemeSelectS.SBGDInt :=  ThemeIni.ReadFloat(Name, 'SBGDInt', 1);
+
+  LoadColor(ThemeSelectS.STColR, ThemeSelectS.STColG,  ThemeSelectS.STColB, ThemeIni.ReadString(Name, 'STColor', ''));
+  ThemeSelectS.STInt :=  ThemeIni.ReadFloat(Name, 'STInt', 1);
+  LoadColor(ThemeSelectS.STDColR, ThemeSelectS.STDColG,  ThemeSelectS.STDColB, ThemeIni.ReadString(Name, 'STDColor', ''));
+  ThemeSelectS.STDInt :=  ThemeIni.ReadFloat(Name, 'STDInt', 1);
+
+  ThemeSelectS.showArrows := (ThemeIni.ReadInteger(Name, 'ShowArrows', 0) = 1);
+  ThemeSelectS.oneItemOnly := (ThemeIni.ReadInteger(Name, 'OneItemOnly', 0) = 1);
+end;
+
+procedure TTheme.ThemeLoadEqualizer(var ThemeEqualizer: TThemeEqualizer; const Name: string);
+var I: integer;
+begin
+  ThemeEqualizer.Visible := (ThemeIni.ReadInteger(Name, 'Visible', 0) = 1);
+  ThemeEqualizer.Direction := (ThemeIni.ReadInteger(Name, 'Direction', 0) = 1);
+  ThemeEqualizer.Alpha := ThemeIni.ReadInteger(Name, 'Alpha', 1);
+  ThemeEqualizer.Space := ThemeIni.ReadInteger(Name, 'Space', 1);
+  ThemeEqualizer.X := ThemeIni.ReadInteger(Name, 'X', 0);
+  ThemeEqualizer.Y := ThemeIni.ReadInteger(Name, 'Y', 0);
+  ThemeEqualizer.Z := ThemeIni.ReadInteger(Name, 'Z', 1);
+  ThemeEqualizer.W := ThemeIni.ReadInteger(Name, 'PieceW', 8);
+  ThemeEqualizer.H := ThemeIni.ReadInteger(Name, 'PieceH', 8);
+  ThemeEqualizer.Bands := ThemeIni.ReadInteger(Name, 'Bands', 5);
+  ThemeEqualizer.Length := ThemeIni.ReadInteger(Name, 'Length', 12);
+  ThemeEqualizer.Reflection := (ThemeIni.ReadInteger(Name, 'Reflection', 0) = 1);
+  ThemeEqualizer.ReflectionSpacing := ThemeIni.ReadFloat(Name, 'ReflectionSpacing', 15);
+
+  //Color
+  I := ColorExists(ThemeIni.ReadString(Name, 'Color', 'Black'));
+  if I >= 0 then
+  begin
+    ThemeEqualizer.ColR := Color[I].RGB.R;
+    ThemeEqualizer.ColG := Color[I].RGB.G;
+    ThemeEqualizer.ColB := Color[I].RGB.B;
+  end
+  else
+  begin
+    ThemeEqualizer.ColR := 0;
+    ThemeEqualizer.ColG := 0;
+    ThemeEqualizer.ColB := 0;
+  end;
+end;
+
+procedure TTheme.LoadColors;
+var
+  SL:     TStringList;
+  C:      integer;
+  S:      string;
+begin
+  SL := TStringList.Create;
+  ThemeIni.ReadSection('Colors', SL);
+
+  // normal colors
+  SetLength(Color, SL.Count);
+  for C := 0 to SL.Count-1 do
+  begin
+    Color[C].Name := SL.Strings[C];
+
+    S := ThemeIni.ReadString('Colors', SL.Strings[C], '');
+
+    Color[C].RGB.R := StrToInt(Copy(S, 1, Pos(' ' , S)-1))/255;
+    Delete(S, 1, Pos(' ', S));
+
+    Color[C].RGB.G := StrToInt(Copy(S, 1, Pos(' ' , S)-1))/255;
+    Delete(S, 1, Pos(' ', S));
+
+    Color[C].RGB.B := StrToInt(S)/255;
+  end;
+
+  // skin color
+  SetLength(Color, SL.Count + 3);
+  C := SL.Count;
+  Color[C].Name := 'ColorDark';
+  Color[C].RGB := GetSystemColor(Skin.Color);  //Ini.Color);
+
+  C := C+1;
+  Color[C].Name := 'ColorLight';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  C := C+1;
+  Color[C].Name := 'ColorLightest';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  // players colors
+  SetLength(Color, Length(Color)+18);
+
+  // P1
+  C := C+1;
+  Color[C].Name := 'P1Dark';
+  Color[C].RGB := GetSystemColor(0); // 0 - blue
+
+  C := C+1;
+  Color[C].Name := 'P1Light';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  C := C+1;
+  Color[C].Name := 'P1Lightest';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  // P2
+  C := C+1;
+  Color[C].Name := 'P2Dark';
+  Color[C].RGB := GetSystemColor(3); // 3 - red
+
+  C := C+1;
+  Color[C].Name := 'P2Light';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  C := C+1;
+  Color[C].Name := 'P2Lightest';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  // P3
+  C := C+1;
+  Color[C].Name := 'P3Dark';
+  Color[C].RGB := GetSystemColor(1); // 1 - green
+
+  C := C+1;
+  Color[C].Name := 'P3Light';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  C := C+1;
+  Color[C].Name := 'P3Lightest';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  // P4
+  C := C+1;
+  Color[C].Name := 'P4Dark';
+  Color[C].RGB := GetSystemColor(4); // 4 - brown
+
+  C := C+1;
+  Color[C].Name := 'P4Light';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  C := C+1;
+  Color[C].Name := 'P4Lightest';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  // P5
+  C := C+1;
+  Color[C].Name := 'P5Dark';
+  Color[C].RGB := GetSystemColor(5); // 5 - yellow
+
+  C := C+1;
+  Color[C].Name := 'P5Light';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  C := C+1;
+  Color[C].Name := 'P5Lightest';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  // P6
+  C := C+1;
+  Color[C].Name := 'P6Dark';
+  Color[C].RGB := GetSystemColor(6); // 6 - violet
+
+  C := C+1;
+  Color[C].Name := 'P6Light';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+  C := C+1;
+  Color[C].Name := 'P6Lightest';
+  Color[C].RGB := ColorSqrt(Color[C-1].RGB);
+
+
+  SL.Free;
+end;
+
+function ColorExists(Name: string): integer;
+var
+  C: integer;
+begin
+  Result := -1;
+  for C := 0 to High(Color) do
+    if Color[C].Name = Name then
+      Result := C;
+end;
+
+procedure LoadColor(var R, G, B: real; ColorName: string);
+var
+  C: integer;
+begin
+  C := ColorExists(ColorName);
+  if C >= 0 then
+  begin
+    R := Color[C].RGB.R;
+    G := Color[C].RGB.G;
+    B := Color[C].RGB.B;
+  end;
+end;
+
+function GetSystemColor(Color: integer): TRGB;
+begin
+  case Color of
+    0:  begin
+          // blue
+          Result.R := 71/255;
+          Result.G := 175/255;
+          Result.B := 247/255;
+        end;
+    1:  begin
+          // green
+          Result.R := 63/255;
+          Result.G := 191/255;
+          Result.B := 63/255;
+        end;
+    2:  begin
+          // pink
+          Result.R := 255/255;
+{          Result.G := 63/255;
+          Result.B := 192/255;}
+          Result.G := 175/255;
+          Result.B := 247/255;
+        end;
+    3:  begin
+          // red
+          Result.R := 247/255;
+          Result.G := 71/255;
+          Result.B := 71/255;
+        end;
+        //'Violet', 'Orange', 'Yellow', 'Brown', 'Black'
+        //New Theme-Color Patch
+    4:  begin
+          // violet
+          Result.R := 212/255;
+          Result.G := 71/255;
+          Result.B := 247/255;
+        end;
+    5:  begin
+          // orange
+          Result.R := 247/255;
+          Result.G := 144/255;
+          Result.B := 71/255;
+        end;
+    6:  begin
+          // yellow
+          Result.R := 230/255;
+          Result.G := 230/255;
+          Result.B := 95/255;
+        end;
+    7:  begin
+          // brown
+          Result.R := 192/255;
+          Result.G := 127/255;
+          Result.B := 31/255;
+        end;
+    8:  begin
+          // black
+          Result.R := 0;
+          Result.G := 0;
+          Result.B := 0;
+        end;
+    //New Theme-Color Patch End
+
+    end;
+end;
+
+function ColorSqrt(RGB: TRGB): TRGB;
+begin
+  Result.R := sqrt(RGB.R);
+  Result.G := sqrt(RGB.G);
+  Result.B := sqrt(RGB.B);
+end;
+
+procedure TTheme.ThemeSave(const FileName: string);
+var
+  I: integer;
+begin
+  {$IFDEF THEMESAVE}
+  ThemeIni := TIniFile.Create(FileName);
+  {$ELSE}
+  ThemeIni := TMemIniFile.Create(FileName);
+  {$ENDIF}
+
+  ThemeSaveBasic(Loading, 'Loading');
+
+  ThemeSaveBasic(Main, 'Main');
+  ThemeSaveText(Main.TextDescription, 'MainTextDescription');
+  ThemeSaveText(Main.TextDescriptionLong, 'MainTextDescriptionLong');
+  ThemeSaveButton(Main.ButtonSolo, 'MainButtonSolo');
+  ThemeSaveButton(Main.ButtonEditor, 'MainButtonEditor');
+  ThemeSaveButton(Main.ButtonOptions, 'MainButtonOptions');
+  ThemeSaveButton(Main.ButtonExit, 'MainButtonExit');
+
+  ThemeSaveBasic(Name, 'Name');
+  for I := 1 to 6 do
+    ThemeSaveButton(Name.ButtonPlayer[I], 'NameButtonPlayer' + IntToStr(I));
+
+  ThemeSaveBasic(Level, 'Level');
+  ThemeSaveButton(Level.ButtonEasy, 'LevelButtonEasy');
+  ThemeSaveButton(Level.ButtonMedium, 'LevelButtonMedium');
+  ThemeSaveButton(Level.ButtonHard, 'LevelButtonHard');
+
+  ThemeSaveBasic(Song, 'Song');
+  ThemeSaveText(Song.TextArtist, 'SongTextArtist');
+  ThemeSaveText(Song.TextTitle, 'SongTextTitle');
+  ThemeSaveText(Song.TextNumber, 'SongTextNumber');
+
+  //Show CAt in Top Left Mod
+  ThemeSaveText(Song.TextCat, 'SongTextCat');
+  ThemeSaveStatic(Song.StaticCat, 'SongStaticCat');
+
+  ThemeSaveBasic(Sing, 'Sing');
+
+  //TimeBar mod
+  ThemeSaveStatic(Sing.StaticTimeProgress, 'SingTimeProgress');
+  ThemeSaveText(Sing.TextTimeText, 'SingTimeText');
+  //eoa TimeBar mod
+
+  ThemeSaveStatic(Sing.StaticP1, 'SingP1Static');
+  ThemeSaveText(Sing.TextP1, 'SingP1Text');
+  ThemeSaveStatic(Sing.StaticP1ScoreBG, 'SingP1Static2');
+  ThemeSaveText(Sing.TextP1Score, 'SingP1TextScore');
+
+  //moveable singbar mod
+  ThemeSaveStatic(Sing.StaticP1SingBar, 'SingP1SingBar');
+  ThemeSaveStatic(Sing.StaticP1TwoPSingBar, 'SingP1TwoPSingBar');
+  ThemeSaveStatic(Sing.StaticP1ThreePSingBar, 'SingP1ThreePSingBar');
+  ThemeSaveStatic(Sing.StaticP2RSingBar, 'SingP2RSingBar');
+  ThemeSaveStatic(Sing.StaticP2MSingBar, 'SingP2MSingBar');
+  ThemeSaveStatic(Sing.StaticP3SingBar, 'SingP3SingBar');
+  //eoa moveable singbar
+
+  //Added for ps3 skin
+  //This one is shown in 2/4P mode
+  ThemeSaveStatic(Sing.StaticP1TwoP, 'SingP1TwoPStatic');
+  ThemeSaveText(Sing.TextP1TwoP, 'SingP1TwoPText');
+  ThemeSaveStatic(Sing.StaticP1TwoPScoreBG, 'SingP1TwoPStatic2');
+  ThemeSaveText(Sing.TextP1TwoPScore, 'SingP1TwoPTextScore');
+
+  //This one is shown in 3/6P mode
+  ThemeSaveStatic(Sing.StaticP1ThreeP, 'SingP1ThreePStatic');
+  ThemeSaveText(Sing.TextP1ThreeP, 'SingP1ThreePText');
+  ThemeSaveStatic(Sing.StaticP1ThreePScoreBG, 'SingP1ThreePStatic2');
+  ThemeSaveText(Sing.TextP1ThreePScore, 'SingP1ThreePTextScore');
+  //eoa
+
+  ThemeSaveStatic(Sing.StaticP2R, 'SingP2RStatic');
+  ThemeSaveText(Sing.TextP2R, 'SingP2RText');
+  ThemeSaveStatic(Sing.StaticP2RScoreBG, 'SingP2RStatic2');
+  ThemeSaveText(Sing.TextP2RScore, 'SingP2RTextScore');
+
+  ThemeSaveStatic(Sing.StaticP2M, 'SingP2MStatic');
+  ThemeSaveText(Sing.TextP2M, 'SingP2MText');
+  ThemeSaveStatic(Sing.StaticP2MScoreBG, 'SingP2MStatic2');
+  ThemeSaveText(Sing.TextP2MScore, 'SingP2MTextScore');
+
+  ThemeSaveStatic(Sing.StaticP3R, 'SingP3RStatic');
+  ThemeSaveText(Sing.TextP3R, 'SingP3RText');
+  ThemeSaveStatic(Sing.StaticP3RScoreBG, 'SingP3RStatic2');
+  ThemeSaveText(Sing.TextP3RScore, 'SingP3RTextScore');
+
+  ThemeSaveBasic(Score, 'Score');
+  ThemeSaveText(Score.TextArtist, 'ScoreTextArtist');
+  ThemeSaveText(Score.TextTitle, 'ScoreTextTitle');
+
+  for I := 1 to 6 do
+  begin
+    ThemeSaveStatics(Score.PlayerStatic[I], 'ScorePlayer' + IntToStr(I) + 'Static');
+
+    ThemeSaveText(Score.TextName[I], 'ScoreTextName' + IntToStr(I));
+    ThemeSaveText(Score.TextScore[I], 'ScoreTextScore' + IntToStr(I));
+    ThemeSaveText(Score.TextNotes[I], 'ScoreTextNotes' + IntToStr(I));
+    ThemeSaveText(Score.TextNotesScore[I], 'ScoreTextNotesScore' + IntToStr(I));
+    ThemeSaveText(Score.TextLineBonus[I], 'ScoreTextLineBonus' + IntToStr(I));
+    ThemeSaveText(Score.TextLineBonusScore[I], 'ScoreTextLineBonusScore' + IntToStr(I));
+    ThemeSaveText(Score.TextGoldenNotes[I], 'ScoreTextGoldenNotes' + IntToStr(I));
+    ThemeSaveText(Score.TextGoldenNotesScore[I], 'ScoreTextGoldenNotesScore' + IntToStr(I));
+    ThemeSaveText(Score.TextTotal[I], 'ScoreTextTotal' + IntToStr(I));
+    ThemeSaveText(Score.TextTotalScore[I], 'ScoreTextTotalScore' + IntToStr(I));
+
+    ThemeSaveStatic(Score.StaticBackLevel[I], 'ScoreStaticBackLevel' + IntToStr(I));
+    ThemeSaveStatic(Score.StaticBackLevelRound[I], 'ScoreStaticBackLevelRound' + IntToStr(I));
+    ThemeSaveStatic(Score.StaticLevel[I], 'ScoreStaticLevel' + IntToStr(I));
+    ThemeSaveStatic(Score.StaticLevelRound[I], 'ScoreStaticLevelRound' + IntToStr(I));
+  end;
+
+  ThemeSaveBasic(Top5, 'Top5');
+  ThemeSaveText(Top5.TextLevel, 'Top5TextLevel');
+  ThemeSaveText(Top5.TextArtistTitle, 'Top5TextArtistTitle');
+  ThemeSaveStatics(Top5.StaticNumber, 'Top5StaticNumber');
+  ThemeSaveTexts(Top5.TextNumber, 'Top5TextNumber');
+  ThemeSaveTexts(Top5.TextName, 'Top5TextName');
+  ThemeSaveTexts(Top5.TextScore, 'Top5TextScore');
+
+
+  ThemeIni.Free;
+end;
+
+procedure TTheme.ThemeSaveBasic(Theme: TThemeBasic; const Name: string);
+begin
+  ThemeIni.WriteInteger(Name, 'Texts', Length(Theme.Text));
+
+  ThemeSaveBackground(Theme.Background, Name + 'Background');
+  ThemeSaveStatics(Theme.Statics, Name + 'Static');
+  ThemeSaveTexts(Theme.Text, Name + 'Text');
+end;
+
+procedure TTheme.ThemeSaveBackground(ThemeBackground: TThemeBackground; const Name: string);
+begin
+  if ThemeBackground.Tex <> '' then
+    ThemeIni.WriteString(Name, 'Tex', ThemeBackground.Tex)
+  else
+  begin
+    ThemeIni.EraseSection(Name);
+  end;
+end;
+
+procedure TTheme.ThemeSaveStatic(ThemeStatic: TThemeStatic; const Name: string);
+begin
+  ThemeIni.WriteInteger(Name, 'X', ThemeStatic.X);
+  ThemeIni.WriteInteger(Name, 'Y', ThemeStatic.Y);
+  ThemeIni.WriteInteger(Name, 'W', ThemeStatic.W);
+  ThemeIni.WriteInteger(Name, 'H', ThemeStatic.H);
+
+  ThemeIni.WriteString(Name, 'Tex', ThemeStatic.Tex);
+  ThemeIni.WriteString(Name, 'Type', TextureTypeToStr(ThemeStatic.Typ));
+  ThemeIni.WriteString(Name, 'Color', ThemeStatic.Color);
+
+  ThemeIni.WriteFloat(Name, 'TexX1', ThemeStatic.TexX1);
+  ThemeIni.WriteFloat(Name, 'TexY1', ThemeStatic.TexY1);
+  ThemeIni.WriteFloat(Name, 'TexX2', ThemeStatic.TexX2);
+  ThemeIni.WriteFloat(Name, 'TexY2', ThemeStatic.TexY2);
+end;
+
+procedure TTheme.ThemeSaveStatics(ThemeStatic: AThemeStatic; const Name: string);
+var
+  S: integer;
+begin
+  for S := 0 to Length(ThemeStatic)-1 do
+    ThemeSaveStatic(ThemeStatic[S], Name + {'Static' +} IntToStr(S+1));
+
+  ThemeIni.EraseSection(Name + {'Static' + }IntToStr(S+1));
+end;
+
+procedure TTheme.ThemeSaveText(ThemeText: TThemeText; const Name: string);
+begin
+  ThemeIni.WriteInteger(Name, 'X', ThemeText.X);
+  ThemeIni.WriteInteger(Name, 'Y', ThemeText.Y);
+
+  ThemeIni.WriteInteger(Name, 'Font', ThemeText.Font);
+  ThemeIni.WriteInteger(Name, 'Size', ThemeText.Size);
+  ThemeIni.WriteInteger(Name, 'Align', ThemeText.Align);
+
+  ThemeIni.WriteString(Name, 'Text', ThemeText.Text);
+  ThemeIni.WriteString(Name, 'Color', ThemeText.Color);
+
+  ThemeIni.WriteBool(Name, 'Reflection', ThemeText.Reflection);
+  ThemeIni.WriteFloat(Name, 'ReflectionSpacing', ThemeText.ReflectionSpacing);
+end;
+
+procedure TTheme.ThemeSaveTexts(ThemeText: AThemeText; const Name: string);
+var
+  T: integer;
+begin
+  for T := 0 to Length(ThemeText)-1 do
+    ThemeSaveText(ThemeText[T], Name + {'Text' + }IntToStr(T+1));
+
+  ThemeIni.EraseSection(Name + {'Text' + }IntToStr(T+1));
+end;
+
+procedure TTheme.ThemeSaveButton(ThemeButton: TThemeButton; const Name: string);
+var
+  T: integer;
+begin
+  ThemeIni.WriteString(Name, 'Tex', ThemeButton.Tex);
+  ThemeIni.WriteInteger(Name, 'X', ThemeButton.X);
+  ThemeIni.WriteInteger(Name, 'Y', ThemeButton.Y);
+  ThemeIni.WriteInteger(Name, 'W', ThemeButton.W);
+  ThemeIni.WriteInteger(Name, 'H', ThemeButton.H);
+  ThemeIni.WriteString(Name, 'Type', TextureTypeToStr(ThemeButton.Typ));
+  ThemeIni.WriteInteger(Name, 'Texts', Length(ThemeButton.Text));
+
+  ThemeIni.WriteString(Name, 'Color', ThemeButton.Color);
+
+{  ThemeButton.ColR := ThemeIni.ReadFloat(Name, 'ColR', 1);
+  ThemeButton.ColG := ThemeIni.ReadFloat(Name, 'ColG', 1);
+  ThemeButton.ColB := ThemeIni.ReadFloat(Name, 'ColB', 1);
+  ThemeButton.Int :=  ThemeIni.ReadFloat(Name, 'Int', 1);
+  ThemeButton.DColR := ThemeIni.ReadFloat(Name, 'DColR', 1);
+  ThemeButton.DColG := ThemeIni.ReadFloat(Name, 'DColG', 1);
+  ThemeButton.DColB := ThemeIni.ReadFloat(Name, 'DColB', 1);
+  ThemeButton.DInt :=  ThemeIni.ReadFloat(Name, 'DInt', 1);}
+
+{  C := ColorExists(ThemeIni.ReadString(Name, 'Color', ''));
+  if C >= 0 then
+  begin
+    ThemeButton.ColR := Color[C].RGB.R;
+    ThemeButton.ColG := Color[C].RGB.G;
+    ThemeButton.ColB := Color[C].RGB.B;
+  end;
+
+  C := ColorExists(ThemeIni.ReadString(Name, 'DColor', ''));
+  if C >= 0 then
+  begin
+    ThemeButton.DColR := Color[C].RGB.R;
+    ThemeButton.DColG := Color[C].RGB.G;
+    ThemeButton.DColB := Color[C].RGB.B;
+  end;}
+
+  for T := 0 to High(ThemeButton.Text) do
+    ThemeSaveText(ThemeButton.Text[T], Name + 'Text' + IntToStr(T+1));
+end;
+
+procedure TTheme.CreateThemeObjects();
+begin
+  freeandnil(Loading);
+  Loading := TThemeLoading.Create;
+
+  freeandnil(Main);
+  Main := TThemeMain.Create;
+
+  freeandnil(Name);
+  Name := TThemeName.Create;
+
+  freeandnil(Level);
+  Level := TThemeLevel.Create;
+
+  freeandnil(Song);
+  Song := TThemeSong.Create;
+
+  freeandnil(Sing);
+  Sing := TThemeSing.Create;
+
+  freeandnil(Score);
+  Score := TThemeScore.Create;
+
+  freeandnil(Top5);
+  Top5 := TThemeTop5.Create;
+
+  freeandnil(Options);
+  Options := TThemeOptions.Create;
+
+  freeandnil(OptionsGame);
+  OptionsGame := TThemeOptionsGame.Create;
+
+  freeandnil(OptionsGraphics);
+  OptionsGraphics := TThemeOptionsGraphics.Create;
+
+  freeandnil(OptionsSound);
+  OptionsSound := TThemeOptionsSound.Create;
+
+  freeandnil(OptionsLyrics);
+  OptionsLyrics := TThemeOptionsLyrics.Create;
+
+  freeandnil(OptionsThemes);
+  OptionsThemes := TThemeOptionsThemes.Create;
+
+  freeandnil(OptionsRecord);
+  OptionsRecord := TThemeOptionsRecord.Create;
+
+  freeandnil(OptionsAdvanced);
+  OptionsAdvanced := TThemeOptionsAdvanced.Create;
+
+  freeandnil(Edit);
+  Edit := TThemeEdit.Create;
+
+  freeandnil(ErrorPopup);
+  ErrorPopup := TThemeError.Create;
+
+  freeandnil(CheckPopup);
+  CheckPopup := TThemeCheck.Create;
+
+  freeandnil(SongMenu);
+  SongMenu := TThemeSongMenu.Create;
+
+  freeandnil(SongJumpto);
+  SongJumpto := TThemeSongJumpto.Create;
+
+  //Party Screens
+  freeandnil(PartyNewRound);
+  PartyNewRound := TThemePartyNewRound.Create;
+
+  freeandnil(PartyWin);
+  PartyWin := TThemePartyWin.Create;
+
+  freeandnil(PartyScore);
+  PartyScore := TThemePartyScore.Create;
+
+  freeandnil(PartyOptions);
+  PartyOptions := TThemePartyOptions.Create;
+
+  freeandnil(PartyPlayer);
+  PartyPlayer := TThemePartyPlayer.Create;
+
+  //Stats Screens:
+  freeandnil(StatMain);
+  StatMain := TThemeStatMain.Create;
+
+  freeandnil(StatDetail);
+  StatDetail := TThemeStatDetail.Create;
+
+ end;
+
+end.
diff --git a/songmanagement/src/base/UTime.pas b/songmanagement/src/base/UTime.pas
new file mode 100644
index 00000000..0610ef59
--- /dev/null
+++ b/songmanagement/src/base/UTime.pas
@@ -0,0 +1,246 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UTime;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+type
+  TTime = class
+    public
+      constructor Create;
+      function GetTime(): real;
+  end;
+
+  TRelativeTimerState = (rtsStopped, rtsWait, rtsPaused, rtsRunning);
+
+  TRelativeTimer = class
+    private
+      AbsoluteTime: int64;      // system-clock reference time for calculation of CurrentTime
+      RelativeTime: real;
+      TriggerMode: boolean;
+      State: TRelativeTimerState;
+    public
+      constructor Create();
+      procedure Start(WaitForTrigger: boolean = false);
+      procedure Pause();
+      procedure Stop();
+      function GetTime(): real;
+      procedure SetTime(Time: real);
+      function GetState(): TRelativeTimerState;
+  end;
+
+  TSyncSource = class
+    function GetClock(): real; virtual; abstract;
+  end;
+
+procedure CountSkipTimeSet;
+procedure CountSkipTime;
+procedure CountMidTime;
+
+var
+  USTime:       TTime;
+  VideoBGTimer: TRelativeTimer;
+
+  TimeNew:     int64;
+  TimeOld:     int64;
+  TimeSkip:    real;
+  TimeMid:     real;
+  TimeMidTemp: int64;
+
+implementation
+
+uses
+  sdl,
+  UCommon;
+  
+const
+  cSDLCorrectionRatio = 1000;
+
+(*
+BEST Option now ( after discussion with whiteshark ) seems to be to use SDL
+timer functions...
+
+SDL_delay
+SDL_GetTicks
+http://www.gamedev.net/community/forums/topic.asp?topic_id=466145&whichpage=1%EE%8D%B7
+*)
+
+
+procedure CountSkipTimeSet;
+begin
+  TimeNew := SDL_GetTicks();
+end;
+
+procedure CountSkipTime;
+begin
+  TimeOld  := TimeNew;
+  TimeNew  := SDL_GetTicks();
+  TimeSkip := (TimeNew-TimeOld) / cSDLCorrectionRatio;
+end;
+
+procedure CountMidTime;
+begin
+  TimeMidTemp := SDL_GetTicks();
+  TimeMid     := (TimeMidTemp - TimeNew) / cSDLCorrectionRatio;
+end;
+
+{**
+ * TTime
+ **}
+
+constructor TTime.Create;
+begin
+  inherited;
+  CountSkipTimeSet;
+end;
+
+function TTime.GetTime: real;
+begin
+  Result := SDL_GetTicks() / cSDLCorrectionRatio;
+end;
+
+{**
+ * TRelativeTimer
+ **}
+
+(**
+ * Creates a new relative timer.
+ * A relative timer works like a stop-watch. It can be paused and
+ * resumed afterwards, continuing with the counter it had when it was paused.
+ *)
+constructor TRelativeTimer.Create();
+begin
+  State := rtsStopped;
+  AbsoluteTime := 0;
+  RelativeTime := 0;
+end;
+
+(**
+ * Starts the timer.
+ * If WaitForTrigger is false the timer will be started immediately.
+ * If WaitForTrigger is true the timer will be started when a trigger event
+ * occurs. A trigger event is a call of one of the Get-/SetTime() methods.
+ * In addition the timer can be started by calling this method again with
+ * WaitForTrigger set to false.
+ *)
+procedure TRelativeTimer.Start(WaitForTrigger: boolean = false);
+begin
+  case (State) of
+    rtsStopped, rtsPaused: begin
+      if (WaitForTrigger) then
+      begin
+        State := rtsWait;
+      end
+      else
+      begin
+        State := rtsRunning;
+        AbsoluteTime := SDL_GetTicks();
+      end;
+    end;
+
+    rtsWait: begin
+      if (not WaitForTrigger) then
+      begin
+        State := rtsRunning;
+        AbsoluteTime := SDL_GetTicks();
+        RelativeTime := 0;
+      end;
+    end;
+  end;
+end;
+
+(**
+ * Pauses the timer and leaves the counter untouched.
+ *)
+procedure TRelativeTimer.Pause();
+begin
+  if (State = rtsRunning) then
+  begin
+    // Important: GetTime() must be called in running state
+    RelativeTime := GetTime();
+    State := rtsPaused;
+  end;
+end;
+
+(**
+ * Stops the timer and sets its counter to 0.
+ *)
+procedure TRelativeTimer.Stop();
+begin
+  if (State <> rtsStopped) then
+  begin
+    State := rtsStopped;
+    RelativeTime := 0;
+  end;
+end;
+
+(**
+ * Returns the current counter of the timer.
+ * If WaitForTrigger was true in Start() the timer will be started
+ * if it was not already running.
+ *)
+function TRelativeTimer.GetTime(): real;
+begin
+  case (State) of
+    rtsStopped, rtsPaused:
+      Result := RelativeTime;
+    rtsRunning:
+      Result := RelativeTime + (SDL_GetTicks() - AbsoluteTime) / cSDLCorrectionRatio;
+    rtsWait: begin
+      // start triggered
+      State := rtsRunning;
+      AbsoluteTime := SDL_GetTicks();
+      Result := RelativeTime;
+    end;
+  end;
+end;
+
+(**
+ * Sets the counter of the timer.
+ * If WaitForTrigger was true in Start() the timer will be started
+ * if it was not already running.
+ *)
+procedure TRelativeTimer.SetTime(Time: real);
+begin
+  RelativeTime := Time;
+  AbsoluteTime := SDL_GetTicks();
+  // start triggered
+  if (State = rtsWait) then
+    State := rtsRunning;
+end;
+
+function TRelativeTimer.GetState(): TRelativeTimerState;
+begin
+  Result := State;
+end;
+
+end.
diff --git a/songmanagement/src/base/UUnicodeUtils.pas b/songmanagement/src/base/UUnicodeUtils.pas
new file mode 100644
index 00000000..37b53a67
--- /dev/null
+++ b/songmanagement/src/base/UUnicodeUtils.pas
@@ -0,0 +1,670 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UUnicodeUtils;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+uses
+{$IFDEF MSWINDOWS}
+  Windows,
+{$ENDIF}
+  StrUtils,
+  SysUtils;
+
+type
+  // String with unknown encoding. Introduced with Delphi 2009 and maybe soon
+  // with FPC.
+  RawByteString = AnsiString;
+
+{**
+ * Returns true if the system uses UTF-8 as default string type
+ * (filesystem or API calls).
+ * This is always true on Mac OS X and always false on Win32. On Unix it depends
+ * on the LC_CTYPE setting.
+ * Do not use AnsiToUTF8() or UTF8ToAnsi() if this function returns true.
+ *}
+function IsNativeUTF8(): boolean;
+
+(*
+ * Character classes
+ *)
+
+function IsAlphaChar(ch: WideChar): boolean; overload;
+function IsAlphaChar(ch: UCS4Char): boolean; overload;
+
+function IsNumericChar(ch: WideChar): boolean; overload;
+function IsNumericChar(ch: UCS4Char): boolean; overload;
+
+function IsAlphaNumericChar(ch: WideChar): boolean; overload;
+function IsAlphaNumericChar(ch: UCS4Char): boolean; overload;
+
+function IsPunctuationChar(ch: WideChar): boolean; overload;
+function IsPunctuationChar(ch: UCS4Char): boolean; overload;
+
+function IsControlChar(ch: WideChar): boolean; overload;
+function IsControlChar(ch: UCS4Char): boolean; overload;
+
+function IsPrintableChar(ch: WideChar): boolean; overload;
+function IsPrintableChar(ch: UCS4Char): boolean; overload;
+
+{**
+ * Checks if the given string is a valid UTF-8 string.
+ * If an ANSI encoded string (with char codes >= 128) is passed, the
+ * function will most probably return false, as most ANSI strings sequences
+ * are illegal in UTF-8.
+ *}
+function IsUTF8String(const str: RawByteString): boolean;
+
+{**
+ * Iterates over an UTF-8 encoded string.
+ * StrPtr will be  increased to the beginning of the next character on each
+ * call.
+ * Results true if the given string starts with an UTF-8 encoded char.
+ *}
+function NextCharUTF8(var StrPtr: PAnsiChar; out Ch: UCS4Char): boolean;
+
+{**
+ * Deletes Count chars (not bytes) beginning at char- (not byte-) position Index.
+ * Index values start with 1.
+ *}
+procedure UTF8Delete(var Str: UTF8String; Index: Integer; Count: Integer);
+procedure UCS4Delete(var Str: UCS4String; Index: Integer; Count: Integer);
+
+{**
+ * Checks if the string is composed of ASCII characters.
+ *}
+function IsASCIIString(const str: RawByteString): boolean;
+
+{*
+ * String format conversion
+ *}
+
+function UTF8ToUCS4String(const str: UTF8String): UCS4String;
+function UCS4ToUTF8String(const str: UCS4String): UTF8String; overload;
+function UCS4ToUTF8String(ch: UCS4Char): UTF8String; overload;
+
+{**
+ * Returns the number of characters (not bytes) in string str.
+ *}
+function LengthUTF8(const str: UTF8String): integer;
+
+{**
+ * Returns the length of an UCS4String. Note that Length(UCS4String) returns
+ * the length+1 as UCS4Strings are zero-terminated.
+ *}
+function LengthUCS4(const str: UCS4String): integer;
+
+{** @seealso WideCompareStr *}
+function UTF8CompareStr(const S1, S2: UTF8String): integer;
+{** @seealso WideCompareText *}
+function UTF8CompareText(const S1, S2: UTF8String): integer;
+
+function UTF8StartsText(const SubText, Text: UTF8String): boolean;
+
+function UTF8ContainsStr(const Text, SubText: UTF8String): boolean;
+function UTF8ContainsText(const Text, SubText: UTF8String): boolean;
+
+{** @seealso WideUpperCase *}
+function UTF8UpperCase(const str: UTF8String): UTF8String;
+{** @seealso WideCompareText *}
+function UTF8LowerCase(const str: UTF8String): UTF8String;
+
+{**
+ * Converts a UCS-4 char ch to its upper-case representation.
+ *}
+function UCS4UpperCase(ch: UCS4Char): UCS4Char; overload;
+
+{**
+ * Converts a UCS-4 string str to its upper-case representation.
+ *}
+function UCS4UpperCase(const str: UCS4String): UCS4String; overload;
+
+{**
+ * Converts a UCS4Char to an UCS4String.
+ * Note that UCS4Strings are zero-terminated dynamic arrays.
+ *}
+function UCS4CharToString(ch: UCS4Char): UCS4String;
+
+{**
+ * @seealso System.Pos()
+ *}
+function UTF8Pos(const substr: UTF8String; const str: UTF8String): Integer;
+
+{**
+ * Copies a segment of str starting with Index (1-based) with Count characters (not bytes).
+ *}
+function UTF8Copy(const str: UTF8String; Index: Integer = 1; Count: Integer = -1): UTF8String;
+
+{**
+ * Copies a segment of str starting with Index (0-based) with Count characters.
+ * Note: Do not use Copy() to copy UCS4Strings as the result will not contain
+ * a trailing #0 character and hence is invalid.
+ *}
+function UCS4Copy(const str: UCS4String; Index: Integer = 0; Count: Integer = -1): UCS4String;
+
+(*
+ * Converts a WideString to its upper- or lower-case representation.
+ * Wrapper for WideUpper/LowerCase. Needed because some plattforms have
+ * problems with unicode support.
+ *
+ * Note that characters in UTF-16 might consist of one or two WideChar valus
+ * (see surrogates). So instead of using WideStringUpperCase(ch)[1] for single
+ * character access, convert to UCS-4 where each character is represented by
+ * one UCS4Char. 
+ *)
+function WideStringUpperCase(const str: WideString) : WideString; overload;
+function WideStringUpperCase(ch: WideChar): WideString; overload;
+function WideStringLowerCase(const str: WideString): WideString; overload;
+function WideStringLowerCase(ch: WideChar): WideString; overload;
+
+function WideStringReplaceChar(const text: WideString; search, rep: WideChar): WideString;
+
+implementation
+
+{$IFDEF UNIX}
+{$IFNDEF DARWIN}
+const
+  LC_CTYPE = 0;
+
+function setlocale(category: integer; locale: PChar): PChar; cdecl; external 'c';
+{$ENDIF}
+{$ENDIF}
+
+var
+  NativeUTF8: boolean;
+
+procedure InitUnicodeUtils();
+{$IFDEF UNIX}
+{$IFNDEF DARWIN}
+var
+  localeName: PChar;
+{$ENDIF}
+{$ENDIF}
+begin
+  {$IF Defined(DARWIN)}
+    NativeUTF8 := true;
+  {$ELSEIF Defined(MSWindows)}
+    NativeUTF8 := false;
+  {$ELSEIF Defined(UNIX)}
+    // check if locale name contains UTF8 or UTF-8
+    localeName := setlocale(LC_CTYPE, nil);
+    NativeUTF8 := Pos('UTF8', UpperCase(AnsiReplaceStr(localeName, '-', ''))) > 0;
+  {$ELSE}
+    raise Exception.Create('Unknown system');
+  {$IFEND}
+end;
+
+function IsNativeUTF8(): boolean;
+begin
+  Result := NativeUTF8;
+end;
+
+function IsAlphaChar(ch: WideChar): boolean;
+begin
+  {$IFDEF MSWINDOWS}
+    Result := IsCharAlphaW(ch);
+  {$ELSE}
+    // TODO: add chars > 255 (or replace with libxml2 functions?)
+    case ch of
+      'A'..'Z',  // A-Z
+      'a'..'z',  // a-z
+      #170,#181,#186,
+      #192..#214,
+      #216..#246,
+      #248..#255:
+        Result := true;
+      else
+        Result := false;
+    end;
+  {$ENDIF}
+end;
+
+function IsAlphaChar(ch: UCS4Char): boolean;
+begin
+  Result := IsAlphaChar(WideChar(Ord(ch)));
+end;
+
+function IsNumericChar(ch: WideChar): boolean;
+begin
+  // TODO: replace with libxml2 functions?
+  // ignore non-arabic numerals as we do not want to handle them
+  case ch of
+    '0'..'9':
+      Result := true;
+    else
+      Result := false;
+  end;
+end;
+
+function IsNumericChar(ch: UCS4Char): boolean;
+begin
+  Result := IsNumericChar(WideChar(Ord(ch)));
+end;
+
+function IsAlphaNumericChar(ch: WideChar): boolean;
+begin
+  Result := (IsAlphaChar(ch) or IsNumericChar(ch));
+end;
+
+function IsAlphaNumericChar(ch: UCS4Char): boolean;
+begin
+  Result := (IsAlphaChar(ch) or IsNumericChar(ch));
+end;
+
+function IsPunctuationChar(ch: WideChar): boolean;
+begin
+  // TODO: add chars > 255 (or replace with libxml2 functions?)
+  case ch of
+    ' '..'/',':'..'@','['..'`','{'..'~',
+    #160..#191,#215,#247:
+      Result := true;
+    else
+      Result := false;
+  end;
+end;
+
+function IsPunctuationChar(ch: UCS4Char): boolean;
+begin
+  Result := IsPunctuationChar(WideChar(Ord(ch)));
+end;
+
+function IsControlChar(ch: WideChar): boolean;
+begin
+  case ch of
+    #0..#31,
+    #127..#159:
+      Result := true;
+    else
+      Result := false;
+  end;
+end;
+
+function IsControlChar(ch: UCS4Char): boolean;
+begin
+  Result := IsControlChar(WideChar(Ord(ch)));
+end;
+
+function IsPrintableChar(ch: WideChar): boolean;
+begin
+  Result := not IsControlChar(ch);
+end;
+
+function IsPrintableChar(ch: UCS4Char): boolean;
+begin
+  Result := IsPrintableChar(WideChar(Ord(ch)));
+end;
+
+
+function NextCharUTF8(var StrPtr: PAnsiChar; out Ch: UCS4Char): boolean;
+
+  // find the most significant zero bit (Result: [7..-1])
+  function FindZeroMSB(b: byte): integer;
+  var
+    Mask: byte;
+  begin
+    Mask := $80;
+    Result := 7;
+    while (b and Mask <> 0) do
+    begin
+      Mask := Mask shr 1;
+      Dec(Result);
+    end;
+  end;
+
+var
+  ZeroBit: integer;
+  SeqCount: integer; // number of trailing bytes to follow
+const
+  Mask: array[1..3] of byte = ($1F, $0F, $07);
+begin
+  Result := false;
+  SeqCount := 0;
+  Ch := 0;
+
+  while (StrPtr^ <> #0) do
+  begin
+    if (StrPtr^ < #128) then
+    begin
+      // check that no more trailing bytes are expected
+      if (SeqCount = 0) then
+      begin
+        Ch := Ord(StrPtr^);
+        Inc(StrPtr);
+        Result := true;
+      end;
+      Break;
+    end
+    else
+    begin
+      ZeroBit := FindZeroMSB(Ord(StrPtr^));
+      // trailing byte expected
+      if (SeqCount > 0) then
+      begin
+        // check if trailing byte has pattern 10xxxxxx
+        if (ZeroBit <> 6) then
+        begin
+          Inc(StrPtr);
+          Break;
+        end;
+
+        Dec(SeqCount);
+        Ch := (Ch shl 6) or (Ord(StrPtr^) and $3F);
+
+        // check if char is finished
+        if (SeqCount = 0) then
+        begin
+          Inc(StrPtr);
+          Result := true;
+          Break;
+        end;
+      end
+      else // leading byte expected
+      begin
+        // check if pattern is one of 110xxxxx/1110xxxx/11110xxx
+        if (ZeroBit > 5) or (ZeroBit < 3) then
+        begin
+          Inc(StrPtr);
+          Break;
+        end;
+        // calculate number of trailing bytes (1, 2 or 3)
+        SeqCount := 6 - ZeroBit;
+        // extract first part of char
+        Ch := Ord(StrPtr^) and Mask[SeqCount];
+      end;
+    end;
+
+    Inc(StrPtr);
+  end;
+
+  if (not Result) then
+    Ch := Ord('?');
+end;
+
+function IsUTF8String(const str: RawByteString): boolean;
+var
+  Ch: UCS4Char;
+  StrPtr: PAnsiChar;
+begin
+  Result := true;
+  StrPtr := PChar(str);
+  while (StrPtr^ <> #0) do
+  begin
+    if (not NextCharUTF8(StrPtr, Ch)) then
+    begin
+      Result := false;
+      Exit;
+    end;
+  end;
+end;
+
+function IsASCIIString(const str: RawByteString): boolean;
+var
+  I: integer;
+begin
+  for I := 1 to Length(str) do
+  begin
+    if (str[I] >= #128) then
+    begin
+      Result := false;
+      Exit;
+    end;
+  end;    
+  Result := true;
+end;
+
+
+function UTF8ToUCS4String(const str: UTF8String): UCS4String;
+begin
+  Result := WideStringToUCS4String(UTF8Decode(str));
+end;
+
+function UCS4ToUTF8String(const str: UCS4String): UTF8String;
+begin
+  Result := UTF8Encode(UCS4StringToWideString(str));
+end;
+
+function UCS4ToUTF8String(ch: UCS4Char): UTF8String;
+begin
+  Result := UCS4ToUTF8String(UCS4CharToString(ch));
+end;
+
+function LengthUTF8(const str: UTF8String): integer;
+begin
+  Result := LengthUCS4(UTF8ToUCS4String(str));
+end;
+
+function LengthUCS4(const str: UCS4String): integer;
+begin
+  Result := High(str);
+  if (Result = -1) then
+    Result := 0;
+end;
+
+function UTF8CompareStr(const S1, S2: UTF8String): integer;
+begin
+  Result := WideCompareStr(UTF8Decode(S1), UTF8Decode(S2));
+end;
+
+function UTF8CompareText(const S1, S2: UTF8String): integer;
+begin
+  Result := WideCompareText(UTF8Decode(S1), UTF8Decode(S2));
+end;
+
+function UTF8StartsStr(const SubText, Text: UTF8String): boolean;
+begin
+  // TODO: use WideSameStr (slower but handles different representations of the same char)?
+  Result := (Pos(SubText, Text) = 1);
+end;
+
+function UTF8StartsText(const SubText, Text: UTF8String): boolean;
+begin
+  // TODO: use WideSameText (slower but handles different representations of the same char)?
+  Result := (Pos(UTF8UpperCase(SubText), UTF8UpperCase(Text)) = 1);
+end;
+
+function UTF8ContainsStr(const Text, SubText: UTF8String): boolean;
+begin
+  Result := Pos(SubText, Text) > 0;
+end;
+
+function UTF8ContainsText(const Text, SubText: UTF8String): boolean;
+begin
+  Result := Pos(UTF8UpperCase(SubText), UTF8UpperCase(Text)) > 0;
+end;
+
+function UTF8UpperCase(const str: UTF8String): UTF8String;
+begin
+  Result := UTF8Encode(WideStringUpperCase(UTF8Decode(str)));
+end;
+
+function UTF8LowerCase(const str: UTF8String): UTF8String;
+begin
+  Result := UTF8Encode(WideStringLowerCase(UTF8Decode(str)));
+end;
+
+function UCS4UpperCase(ch: UCS4Char): UCS4Char;
+begin
+  Result := UCS4UpperCase(UCS4CharToString(ch))[0];
+end;
+
+function UCS4UpperCase(const str: UCS4String): UCS4String;
+begin
+  // convert to upper-case as WideString and convert result back to UCS-4
+  Result := WideStringToUCS4String(
+            WideStringUpperCase(
+            UCS4StringToWideString(str)));
+end;
+
+function UCS4CharToString(ch: UCS4Char): UCS4String;
+begin
+  SetLength(Result, 2);
+  Result[0] := ch;
+  Result[1] := 0;
+end;
+
+function UTF8Pos(const substr: UTF8String; const str: UTF8String): Integer;
+begin
+  Result := Pos(substr, str);
+end;
+
+function UTF8Copy(const str: UTF8String; Index: Integer; Count: Integer): UTF8String;
+begin
+  Result := UCS4ToUTF8String(UCS4Copy(UTF8ToUCS4String(str), Index-1, Count));
+end;
+
+function UCS4Copy(const str: UCS4String; Index: Integer; Count: Integer): UCS4String;
+var
+  I: integer;
+  MaxCount: integer;
+begin
+  // calculate max. copy count
+  MaxCount := LengthUCS4(str)-Index;
+  if (MaxCount < 0) then
+    MaxCount := 0;
+  // adjust copy count
+  if (Count > MaxCount) or (Count < 0) then
+    Count := MaxCount;
+
+  // copy (and add zero terminator)
+  SetLength(Result, Count + 1);
+  for I := 0 to Count-1 do
+    Result[I] := str[Index+I];
+  Result[Count] := 0;
+end;
+
+procedure UTF8Delete(var Str: UTF8String; Index: Integer; Count: Integer);
+var
+  StrUCS4: UCS4String;
+begin
+  StrUCS4 := UTF8ToUCS4String(str);
+  UCS4Delete(StrUCS4, Index-1, Count);
+  Str := UCS4ToUTF8String(StrUCS4);
+end;
+
+procedure UCS4Delete(var Str: UCS4String; Index: Integer; Count: Integer);
+var
+  Len: integer;
+  OldStr: UCS4String;
+  I: integer;
+begin
+  Len := LengthUCS4(Str);
+  if (Count <= 0) or (Index < 0) or (Index >= Len) then
+    Exit;
+  if (Index + Count > Len) then
+    Count := Len-Index;
+  
+  OldStr := Str;
+  SetLength(Str, Len-Count+1);
+  for I := 0 to Index-1 do
+    Str[I] := OldStr[I];
+  for I := Index+Count to Len-1 do
+    Str[I-Count] := OldStr[I];
+  Str[High(Str)] := 0;
+end;
+
+function WideStringUpperCase(ch: WideChar): WideString;
+begin
+  // If WideChar #0 is converted to a WideString in Delphi, a string with
+  // length 1 and a single char #0 is returned. In FPC an empty (length=0)
+  // string will be returned. This will crash, if a non printable key was
+  // pressed, its char code (#0) is translated to upper-case and the the first
+  // character is accessed with Result[1].
+  // We cannot catch this error in the WideString parameter variant as the string
+  // has length 0 already.
+  
+  // Force min. string length of 1
+  if (ch = #0) then
+    Result := #0
+  else
+    Result := WideStringUpperCase(WideString(ch));
+end;
+
+function WideStringUpperCase(const str: WideString): WideString;
+begin
+  // On Linux and MacOSX the cwstring unit is necessary for Unicode function-calls.
+  // Otherwise you will get an EIntOverflow exception (thrown by unimplementedwidestring()).
+  // The Unicode manager cwstring does not work with MacOSX at the moment because
+  // of missing references to iconv.
+  // Note: Should be fixed now
+
+  {.$IFNDEF DARWIN}
+  {.$IFDEF NOIGNORE}
+    Result := WideUpperCase(str)
+  {.$ELSE}
+    //Result := UTF8Decode(UpperCase(UTF8Encode(str)));
+  {.$ENDIF}
+end;
+
+function WideStringLowerCase(ch: WideChar): WideString;
+begin
+  // see WideStringUpperCase
+  if (ch = #0) then
+    Result := #0
+  else
+    Result := WideStringLowerCase(WideString(ch));
+end;
+
+function WideStringLowerCase(const str: WideString): WideString;
+begin
+  // see WideStringUpperCase
+  Result := WideLowerCase(str)
+end;
+
+function WideStringReplaceChar(const text: WideString; search, rep: WideChar): WideString;
+var
+  iPos  : integer;
+//  sTemp : WideString;
+begin
+(*
+  result := text;
+  iPos   := Pos(search, result);
+  while (iPos > 0) do
+  begin
+    sTemp  := copy(result, iPos + length(search), length(result));
+    result := copy(result, 1, iPos - 1) + rep + sTEmp;
+    iPos   := Pos(search, result);
+  end;
+*)
+  result := text;
+
+  if search = rep then
+    exit;
+
+  for iPos := 1 to length(result) do
+  begin
+    if result[iPos] = search then
+      result[iPos] := rep;
+  end;
+end;
+
+initialization
+  InitUnicodeUtils;
+
+end.
diff --git a/songmanagement/src/base/UXMLSong.pas b/songmanagement/src/base/UXMLSong.pas
new file mode 100644
index 00000000..e9751eba
--- /dev/null
+++ b/songmanagement/src/base/UXMLSong.pas
@@ -0,0 +1,623 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UXMLSong;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  UPath,
+  UUnicodeUtils;
+
+type
+  TNote = record
+    Start:    Cardinal;
+    Duration: Cardinal;
+    Tone:     Integer;
+    NoteTyp:  Byte;
+    Lyric:    UTF8String;
+  end;
+  ANote = array of TNote;
+
+  TSentence = record
+    Singer:   Byte;
+    Duration: Cardinal;
+    Notes:    ANote;
+  end;
+  ASentence = array of TSentence;
+
+  TSongInfo = record
+    ID: Cardinal;
+    DualChannel: Boolean;
+    Header: record
+      Artist:     UTF8String;
+      Title:      UTF8String;
+      Gap:        Cardinal;
+      BPM:        Real;
+      Resolution: Byte;
+      Edition:    UTF8String;
+      Genre:      UTF8String;
+      Year:       UTF8String;
+      Language:   UTF8String;
+    end;
+    CountSentences: Cardinal;
+    Sentences: ASentence;
+  end;
+  
+  TParser = class
+    private
+      SSFile: TStringList;
+
+      ParserState: Byte;
+      CurPosinSong: Cardinal; //Cur Beat Pos in the Song
+      CurDuettSinger: Byte;   //Who sings this Part?
+      BindLyrics: Boolean;    //Should the Lyrics be bind to the last Word (no Space)
+      FirstNote: Boolean;     //Is this the First Note found? For Gap calculating
+
+      function  ParseLine(Line: RawByteString): Boolean;
+    public
+      SongInfo: TSongInfo;
+      ErrorMessage: string;
+      Edition: UTF8String;
+      SingstarVersion: string;
+
+      Settings: record
+        DashReplacement: Char;
+      end;
+
+      constructor Create;
+
+      function  ParseConfigForEdition(const Filename: IPath): String;
+
+      function  ParseSongHeader(const Filename: IPath): Boolean; //Parse Song Header only
+      function  ParseSong (const Filename: IPath): Boolean;      //Parse whole Song
+  end;
+
+const
+  PS_None = 0;
+  PS_Melody = 1;
+  PS_Sentence = 2;
+
+  NT_Normal = 1;
+  NT_Freestyle = 0;
+  NT_Golden = 2;
+
+  DS_Player1 = 1;
+  DS_Player2 = 2;
+  DS_Both    = 3;
+
+implementation
+
+uses
+  SysUtils,
+  StrUtils;
+
+constructor TParser.Create;
+begin
+  inherited Create;
+  ErrorMessage := '';
+
+  DecimalSeparator := '.';
+end;
+
+function TParser.ParseSong(const Filename: IPath): Boolean;
+var
+  I: Integer;
+  FileStream: TBinaryFileStream;
+begin
+  Result := False;
+  if Filename.IsFile() then
+  begin
+    ErrorMessage := 'Can''t open melody.xml file';
+
+    SSFile := TStringList.Create;
+    FileStream := TBinaryFileStream.Create(Filename, fmOpenRead);
+    try
+      SSFile.LoadFromStream(FileStream);
+
+      ErrorMessage := '';
+      Result := True;
+
+      I := 0;
+
+      SongInfo.CountSentences := 0;
+      CurDuettSinger := DS_Both; //Both is Singstar Standard
+      CurPosinSong   := 0; //Start at Pos 0
+      BindLyrics     := True; //Dont start with Space
+      FirstNote      := True; //First Note found should be the First Note ;)
+
+      SongInfo.Header.Language := '';
+      SongInfo.Header.Edition := Edition;
+      SongInfo.DualChannel := False;
+
+      ParserState    := PS_None;
+
+      SetLength(SongInfo.Sentences, 0);
+
+      while Result and (I < SSFile.Count) do
+      begin
+        Result := ParseLine(SSFile.Strings[I]);
+
+        Inc(I);
+      end;
+
+    finally
+      SSFile.Free;
+      FileStream.Free;
+    end;
+  end;
+end;
+
+function  TParser.ParseSongHeader (const Filename: IPath): Boolean;
+var
+  I: Integer;
+  Stream: TBinaryFileStream;
+begin
+  Result := False;
+
+  if Filename.IsFile() then
+  begin
+    SSFile := TStringList.Create;
+    Stream := TBinaryFileStream.Create(Filename, fmOpenRead);
+    try
+      SSFile.LoadFromStream(Stream);
+
+      If (SSFile.Count > 0) then
+      begin
+        Result := True;
+        I := 0;
+
+        SongInfo.CountSentences := 0;
+        CurDuettSinger := DS_Both; //Both is Singstar Standard
+        CurPosinSong   := 0; //Start at Pos 0
+        BindLyrics     := True; //Dont start with Space
+        FirstNote      := True; //First Note found should be the First Note ;)
+
+        SongInfo.ID := 0;
+        SongInfo.Header.Language := '';
+        SongInfo.Header.Edition := Edition;
+        SongInfo.DualChannel := False;
+        ParserState    := PS_None;
+
+        While (SongInfo.ID < 4) AND Result And (I < SSFile.Count) do
+        begin
+          Result := ParseLine(SSFile.Strings[I]);
+
+          Inc(I);
+        end;
+      end
+      else
+        ErrorMessage := 'Can''t open melody.xml file';
+
+    finally
+      SSFile.Free;
+      Stream.Free;
+    end;
+  end
+  else
+    ErrorMessage := 'Can''t find melody.xml file';
+end;
+
+Function TParser.ParseLine(Line: String): Boolean;
+var
+  Tag:    String;
+  Values: String;
+  AValues: Array of Record
+    Name: String;
+    Value: String;
+  end;
+  I, J, K:   Integer;
+  Duration, Tone: Integer;
+  Lyric: String;
+  NoteType: Byte;
+
+  Procedure MakeValuesArray;
+  var Len, Pos, State, StateChange: Integer;
+  begin
+    Len := -1;
+    SetLength(AValues, Len + 1);
+
+    Pos := 1;
+    State := 0;
+    While (Pos <= Length(Values)) AND (Pos <> 0) do
+    begin
+      Case State of
+
+        0: begin //Search for ValueName
+          If (Values[Pos] <> ' ') AND (Values[Pos] <> '=') then
+          begin
+            //Found Something
+            State := 1; //State search for '='
+            StateChange := Pos; //Save Pos of Change
+            Pos := PosEx('=', Values, Pos + 1);
+          end
+          else Inc(Pos); //When nothing found then go to next char
+        end;
+
+        1: begin //Search for Equal Mark
+          //Add New Value
+          Inc(Len);
+          SetLength(AValues, Len + 1);
+
+          AValues[Len].Name := UpperCase(Copy(Values, StateChange, Pos - StateChange));
+
+
+          State := 2; //Now Search for starting '"'
+          StateChange := Pos; //Save Pos of Change
+          Pos := PosEx('"', Values, Pos + 1);
+        end;
+
+        2: begin //Search for starting '"' or ' ' <- End if there was no "
+          If (Values[Pos] = '"') then
+          begin //Found starting '"'
+            State := 3; //Now Search for ending '"'
+            StateChange := Pos; //Save Pos of Change
+            Pos := PosEx('"', Values, Pos + 1);
+          end
+          else If (Values[Pos] = ' ') then //Found ending Space
+          begin
+            //Save Value to Array
+            AValues[Len].Value := Copy(Values, StateChange + 1, Pos - StateChange - 1);
+
+            //Search for next Valuename
+            State := 0;
+            StateChange := Pos;
+            Inc(Pos);
+          end;
+        end;
+
+        3: begin //Search for ending '"'
+          //Save Value to Array
+          AValues[Len].Value := Copy(Values, StateChange + 1, Pos - StateChange - 1);
+
+          //Search for next Valuename
+          State := 0;
+          StateChange := Pos;
+          Inc(Pos);
+        end;
+      end;
+
+      If (State >= 2) then
+      begin //Save Last Value
+        AValues[Len].Value := Copy(Values, StateChange + 1, Length(Values) - StateChange);
+      end;
+    end;
+  end;
+begin
+  Result := True;
+
+  Line := Trim(Line);
+  If (Length(Line) > 0) then
+  begin
+    I := Pos('<', Line);
+    J := PosEx(' ', Line, I+1);
+    K := PosEx('>', Line, I+1);
+
+    If (J = 0) then J := K
+    Else If (K < J) AND (K <> 0) then J := K; //Use nearest Tagname End indicator
+    Tag := UpperCase(copy(Line, I + 1, J - I - 1));
+    Values := copy(Line, J + 1, K - J - 1);
+
+    Case ParserState of
+      PS_None: begin//Search for Melody Tag
+        If (Tag = 'MELODY') then
+        begin
+          Inc(SongInfo.ID); //Inc SongID when header Information is added
+          MakeValuesArray;
+          For I := 0 to High(AValues) do
+          begin
+            If (AValues[I].Name = 'TEMPO') then
+            begin
+              SongInfo.Header.BPM := StrtoFloatDef(AValues[I].Value, 0);
+              If (SongInfo.Header.BPM <= 0) then
+              begin
+                Result := False;
+                ErrorMessage := 'Can''t read BPM from Song';
+              end;
+            end
+
+            Else If (AValues[I].Name = 'RESOLUTION') then
+            begin
+              AValues[I].Value := Uppercase(AValues[I].Value);
+              //Ultrastar Resolution is "how often a Beat is split / 4"
+              If (AValues[I].Value = 'HEMIDEMISEMIQUAVER') then
+                SongInfo.Header.Resolution := 64 div 4
+              Else If (AValues[I].Value = 'DEMISEMIQUAVER') then
+                SongInfo.Header.Resolution := 32 div 4
+              Else If (AValues[I].Value = 'SEMIQUAVER') then
+                SongInfo.Header.Resolution := 16 div 4
+              Else If (AValues[I].Value = 'QUAVER') then
+                SongInfo.Header.Resolution := 8 div 4
+              Else If (AValues[I].Value = 'CROTCHET') then
+                SongInfo.Header.Resolution := 4 div 4
+              Else
+              begin //Can't understand teh Resolution :/
+                Result := False;
+                ErrorMessage := 'Can''t read Resolution from Song';
+              end;
+            end
+
+            Else If (AValues[I].Name = 'GENRE') then
+            begin
+              SongInfo.Header.Genre := AValues[I].Value;
+            end
+
+            Else If (AValues[I].Name = 'YEAR') then
+            begin
+              SongInfo.Header.Year := AValues[I].Value;
+            end
+
+            Else If (AValues[I].Name = 'VERSION') then
+            begin
+              SingstarVersion := AValues[I].Value;
+            end;
+          end;
+
+          ParserState := PS_Melody; //In Melody Tag
+        end;
+      end;
+
+
+      PS_Melody: begin //Search for Sentence, Artist/Title Info or eo Melody
+        If (Tag = 'SENTENCE') then
+        begin
+          ParserState := PS_Sentence; //Parse in a Sentence Tag now
+          
+          //Increase SentenceCount
+          Inc(SongInfo.CountSentences);
+
+          BindLyrics := True; //Don't let Txts Begin w/ Space
+          
+          //Search for Duett Singer Info
+          MakeValuesArray;
+          For I := 0 to High(AValues) do
+            If (AValues[I].Name = 'SINGER') then
+            begin
+              AValues[I].Value := Uppercase(AValues[I].Value);
+              If (AValues[I].Value = 'SOLO 1') then
+                CurDuettSinger := DS_Player1
+              Else If (AValues[I].Value = 'SOLO 2') then
+                CurDuettSinger := DS_Player2
+              Else
+                CurDuettSinger := DS_Both; //In case of "Group" or anything that is not identified use Both
+            end;
+        end
+
+        Else If (Tag = '!--') then
+        begin //Comment, this may be Artist or Title Info
+          I := Pos(':', Values); //Search for Delimiter
+
+          If (I <> 0) then //If Found check for Title or Artist
+          begin
+            //Copy Title or Artist Tag to Tag String
+            Tag := Uppercase(Trim(Copy(Values, 1, I - 1)));
+
+            If (Tag = 'ARTIST') then
+            begin
+              SongInfo.Header.Artist := Trim(Copy(Values, I + 1, Length(Values) - I - 2));
+              Inc(SongInfo.ID); //Inc SongID when header Information is added
+            end
+            Else If (Tag = 'TITLE') then
+            begin
+              SongInfo.Header.Title := Trim(Copy(Values, I + 1, Length(Values) - I - 2));
+              Inc(SongInfo.ID); //Inc SongID when header Information is added
+            end;
+          end;
+        end
+
+        //Parsing for weird "Die toten Hosen" Tags
+        Else If (Tag = '!--ARTIST:') OR (Tag = '!--ARTIST') then
+        begin //Comment, with Artist Info
+          I := Pos(':', Values); //Search for Delimiter
+
+          Inc(SongInfo.ID); //Inc SongID when header Information is added
+
+          SongInfo.Header.Artist := Trim(Copy(Values, I + 1, Length(Values) - I - 2));
+        end
+
+        Else If (Tag = '!--TITLE:') OR (Tag = '!--TITLE') then
+        begin //Comment, with Artist Info
+          I := Pos(':', Values); //Search for Delimiter
+
+          Inc(SongInfo.ID); //Inc SongID when header Information is added
+
+          SongInfo.Header.Title := Trim(Copy(Values, I + 1, Length(Values) - I - 2));
+        end
+
+        Else If (Tag = '/MELODY') then
+        begin
+          ParserState := PS_None;
+          Exit; //Stop Parsing, Melody iTag ended
+        end
+      end;
+
+
+      PS_Sentence: begin //Search for Notes or eo Sentence
+        If (Tag = 'NOTE') then
+        begin //Found Note
+          //Get Values
+          MakeValuesArray;
+
+          NoteType := NT_Normal;
+          For I := 0 to High(AValues) do
+          begin
+            If (AValues[I].Name = 'DURATION') then
+            begin
+              Duration := StrtoIntDef(AValues[I].Value, -1);
+              If (Duration < 0) then
+              begin
+                Result := False;
+                ErrorMessage := 'Can''t read duration from Note in Line: "' + Line + '"';
+                Exit;
+              end;
+            end
+            Else If (AValues[I].Name = 'MIDINOTE') then
+            begin
+              Tone := StrtoIntDef(AValues[I].Value, 0);
+            end
+            Else If (AValues[I].Name = 'BONUS') AND (Uppercase(AValues[I].Value) = 'YES') then
+            begin
+              NoteType := NT_Golden;
+            end
+            Else If (AValues[I].Name = 'FREESTYLE') AND (Uppercase(AValues[I].Value) = 'YES') then
+            begin
+              NoteType := NT_Freestyle;
+            end
+            Else If (AValues[I].Name = 'LYRIC') then
+            begin
+              Lyric := AValues[I].Value;
+
+              If (Length(Lyric) > 0) then
+              begin
+                If (Lyric = '-') then
+                  Lyric[1] := Settings.DashReplacement;
+
+                If (not BindLyrics) then
+                  Lyric := ' ' + Lyric;
+
+
+                If (Length(Lyric) > 2) AND (Lyric[Length(Lyric)-1] = ' ') AND (Lyric[Length(Lyric)] = '-') then
+                begin //Between this and the next Lyric should be no space
+                  BindLyrics := True;
+                  SetLength(Lyric, Length(Lyric) - 2);
+                end
+                else
+                  BindLyrics := False; //There should be a Space
+              end;
+            end;
+          end;
+
+          //Add Note
+          I := SongInfo.CountSentences - 1;
+
+          If (Length(Lyric) > 0) then
+          begin //Real note, no rest
+            //First Note of Sentence
+            If (Length(SongInfo.Sentences) < SongInfo.CountSentences) then
+            begin
+              SetLength(SongInfo.Sentences, SongInfo.CountSentences);
+              SetLength(SongInfo.Sentences[I].Notes, 0);
+            end;
+
+            //First Note of Song -> Generate Gap
+            If (FirstNote) then
+            begin
+              //Calculate Gap
+              If (SongInfo.Header.Resolution <> 0) AND (SongInfo.Header.BPM <> 0) then
+                SongInfo.Header.Gap := Round(CurPosinSong / (SongInfo.Header.BPM*SongInfo.Header.Resolution) * 60000)
+              Else
+              begin
+                Result := False;
+                ErrorMessage := 'Can''t calculate Gap, no Resolution or BPM present.';
+                Exit;
+              end;
+
+              CurPosinSong := 0; //Start at 0, because Gap goes until here
+              Inc(SongInfo.ID); //Add Header Value therefore Inc
+              FirstNote := False;
+            end;
+
+            J := Length(SongInfo.Sentences[I].Notes);
+            SetLength(SongInfo.Sentences[I].Notes, J + 1);
+            SongInfo.Sentences[I].Notes[J].Start := CurPosinSong;
+            SongInfo.Sentences[I].Notes[J].Duration := Duration;
+            SongInfo.Sentences[I].Notes[J].Tone := Tone;
+            SongInfo.Sentences[I].Notes[J].NoteTyp := NoteType;
+            SongInfo.Sentences[I].Notes[J].Lyric := Lyric;
+
+            //Inc Pos in Song
+            Inc(CurPosInSong, Duration);
+          end
+          else
+          begin
+            //just change pos in Song
+            Inc(CurPosInSong, Duration);
+          end;
+
+
+        end
+        Else If (Tag = '/SENTENCE') then
+        begin //End of Sentence Tag
+          ParserState := PS_Melody;
+
+          //Delete Sentence if no Note is Added
+          If (Length(SongInfo.Sentences) <> SongInfo.CountSentences) then
+          begin
+            SongInfo.CountSentences := Length(SongInfo.Sentences);
+          end;
+        end;
+      end;
+    end;
+
+  end
+  else  //Empty Line -> parsed succesful ;)
+    Result := true;
+end;
+
+Function  TParser.ParseConfigForEdition(const Filename: IPath): String;
+var
+  txt: TStringlist;
+  Stream: TBinaryFileStream;
+  I: Integer;
+  J, K: Integer;
+  S: String;
+begin
+  Result := '';
+
+  Stream := TBinaryFileStream.Create(Filename, fmOpenRead);
+  try
+    txt := TStringlist.Create;
+    txt.LoadFromStream(Stream);
+    For I := 0 to txt.Count-1 do
+    begin
+      S := Trim(txt.Strings[I]);
+      J := Pos('<PRODUCT_NAME>', S);
+
+      If (J <> 0) then
+      begin
+        Inc(J, 14);
+        K := Pos('</PRODUCT_NAME>', S);
+        If (K<J) then K := Length(S) + 1;
+
+        Result := Copy(S, J, K - J);
+        Break;
+      end;
+    end;
+
+    Edition := Result;
+  finally
+    txt.Free;
+    Stream.Free;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/config-darwin.inc b/songmanagement/src/config-darwin.inc
new file mode 100644
index 00000000..5eb38d76
--- /dev/null
+++ b/songmanagement/src/config-darwin.inc
@@ -0,0 +1,58 @@
+{***************************************************************** 
+ * Configuration file for ultrastardx 1.1
+ * src/config-darwin.inc.  Generated from config.inc.in by configure.
+ *****************************************************************}
+
+{* Libraries *}
+
+{$IF Defined(IncludeConstants)}
+  lua_lib_name = 'lua';
+{$IFEND}
+
+{$DEFINE HaveFFmpeg}
+{$IF Defined(HaveFFmpeg) and Defined(IncludeConstants)}
+  av__codec = 'libavcodec';
+  LIBAVCODEC_VERSION_MAJOR   = 51;
+  LIBAVCODEC_VERSION_MINOR   = 49;
+  LIBAVCODEC_VERSION_RELEASE = 0;
+
+  av__format = 'libavformat';
+  LIBAVFORMAT_VERSION_MAJOR   = 52;
+  LIBAVFORMAT_VERSION_MINOR   = 2;
+  LIBAVFORMAT_VERSION_RELEASE = 0;
+
+  av__util = 'libavutil';
+  LIBAVUTIL_VERSION_MAJOR   = 49;
+  LIBAVUTIL_VERSION_MINOR   = 6;
+  LIBAVUTIL_VERSION_RELEASE = 0;
+{$IFEND}
+
+{$DEFINE HaveSWScale}
+{$IF Defined(HaveSWScale) and Defined(IncludeConstants)}
+  sw__scale = 'libswscale';
+  LIBSWSCALE_VERSION_MAJOR   = 0;
+  LIBSWSCALE_VERSION_MINOR   = 5;
+  LIBSWSCALE_VERSION_RELEASE = 0;
+{$IFEND}
+
+{$UNDEF HaveProjectM}
+{$IF Defined(HaveProjectM) and Defined(IncludeConstants)}
+  ProjectM_DataDir = '';
+  PROJECTM_VERSION_MAJOR   = 0;
+  PROJECTM_VERSION_MINOR   = 0;
+  PROJECTM_VERSION_RELEASE = 0;
+{$IFEND}
+
+{$DEFINE HavePortaudio}
+{$IF Defined(HavePortaudio) and Defined(IncludeConstants)}
+  PORTAUDIO_VERSION_MAJOR   = 19;
+  PORTAUDIO_VERSION_MINOR   = 0;
+  PORTAUDIO_VERSION_RELEASE = 0;
+{$IFEND}
+
+{$DEFINE HaveLibPcre}
+{$IF Defined(HaveLibPcre) and Defined(IncludeConstants)}
+  LIBPCRE_LIBDIR   = '/sw/lib';
+{$IFEND}
+
+{$UNDEF HavePortmixer}
diff --git a/songmanagement/src/config-win.inc b/songmanagement/src/config-win.inc
new file mode 100644
index 00000000..843fdb0e
--- /dev/null
+++ b/songmanagement/src/config-win.inc
@@ -0,0 +1,55 @@
+{*****************************************************************
+ * Configuration file for UltraStar Deluxe 1.1
+ *****************************************************************}
+
+{* Libraries *}
+
+{$DEFINE HaveFFmpeg}
+{$IF Defined(HaveFFmpeg) and Defined(IncludeConstants)}
+  av__codec = 'avcodec-52';
+  LIBAVCODEC_VERSION_MAJOR   = 52;
+  LIBAVCODEC_VERSION_MINOR   = 67;
+  LIBAVCODEC_VERSION_RELEASE = 2;
+
+  av__format = 'avformat-52';
+  LIBAVFORMAT_VERSION_MAJOR   = 52;
+  LIBAVFORMAT_VERSION_MINOR   = 62;
+  LIBAVFORMAT_VERSION_RELEASE = 0;
+
+  av__util = 'avutil-50';
+  LIBAVUTIL_VERSION_MAJOR   = 50;
+  LIBAVUTIL_VERSION_MINOR   = 15;
+  LIBAVUTIL_VERSION_RELEASE = 2;
+{$IFEND}
+
+{$DEFINE HaveSWScale}
+{$IF Defined(HaveSWScale) and Defined(IncludeConstants)}
+  sw__scale = 'swscale-0';
+  LIBSWSCALE_VERSION_MAJOR   = 0;
+  LIBSWSCALE_VERSION_MINOR   = 10;
+  LIBSWSCALE_VERSION_RELEASE = 0;
+{$IFEND}
+
+{$DEFINE HaveProjectM}
+{$IF Defined(HaveProjectM) and Defined(IncludeConstants)}
+  ProjectM_DataDir = 'Visuals\projectM';
+  PROJECTM_VERSION_MAJOR   = 1;
+  PROJECTM_VERSION_MINOR   = 10;
+  PROJECTM_VERSION_RELEASE = 0;
+{$IFEND}
+
+{$UNDEF HavePortaudio}
+{$IF Defined(HavePortaudio) and Defined(IncludeConstants)}
+  PORTAUDIO_VERSION_MAJOR   = 19;
+  PORTAUDIO_VERSION_MINOR   = 0;
+  PORTAUDIO_VERSION_RELEASE = 0;
+{$IFEND}
+
+{$UNDEF HavePortmixer}
+
+{$UNDEF HaveLibsamplerate}
+{$IF Defined(HaveLibsamplerate) and Defined(IncludeConstants)}
+  LIBSAMPLERATE_VERSION_MAJOR   = 0;
+  LIBSAMPLERATE_VERSION_MINOR   = 1;
+  LIBSAMPLERATE_VERSION_RELEASE = 3;
+{$IFEND}
diff --git a/songmanagement/src/config.inc.in b/songmanagement/src/config.inc.in
new file mode 100644
index 00000000..d57c7ab4
--- /dev/null
+++ b/songmanagement/src/config.inc.in
@@ -0,0 +1,58 @@
+{***************************************************************** 
+ * Configuration file for @PACKAGE_STRING@
+ * @configure_input@
+ *****************************************************************}
+
+{* Libraries *}
+
+{$IF Defined(IncludeConstants)}
+  lua_lib_name = '@lua_LIB_NAME@';
+{$IFEND}
+
+{$@DEFINE_HAVE_FFMPEG@ HaveFFmpeg}
+{$IF Defined(HaveFFmpeg) and Defined(IncludeConstants)}
+  av__codec = 'libavcodec';
+  LIBAVCODEC_VERSION_MAJOR   = @libavcodec_VERSION_MAJOR@;
+  LIBAVCODEC_VERSION_MINOR   = @libavcodec_VERSION_MINOR@;
+  LIBAVCODEC_VERSION_RELEASE = @libavcodec_VERSION_RELEASE@;
+
+  av__format = 'libavformat';
+  LIBAVFORMAT_VERSION_MAJOR   = @libavformat_VERSION_MAJOR@;
+  LIBAVFORMAT_VERSION_MINOR   = @libavformat_VERSION_MINOR@;
+  LIBAVFORMAT_VERSION_RELEASE = @libavformat_VERSION_RELEASE@;
+
+  av__util = 'libavutil';
+  LIBAVUTIL_VERSION_MAJOR   = @libavutil_VERSION_MAJOR@;
+  LIBAVUTIL_VERSION_MINOR   = @libavutil_VERSION_MINOR@;
+  LIBAVUTIL_VERSION_RELEASE = @libavutil_VERSION_RELEASE@;
+{$IFEND}
+
+{$@DEFINE_HAVE_SWSCALE@ HaveSWScale}
+{$IF Defined(HaveSWScale) and Defined(IncludeConstants)}
+  sw__scale = 'libswscale';
+  LIBSWSCALE_VERSION_MAJOR   = @libswscale_VERSION_MAJOR@;
+  LIBSWSCALE_VERSION_MINOR   = @libswscale_VERSION_MINOR@;
+  LIBSWSCALE_VERSION_RELEASE = @libswscale_VERSION_RELEASE@;
+{$IFEND}
+
+{$@DEFINE_HAVE_PROJECTM@ HaveProjectM}
+{$IF Defined(HaveProjectM) and Defined(IncludeConstants)}
+  ProjectM_DataDir = '@libprojectM_DATADIR@';
+  PROJECTM_VERSION_MAJOR   = @libprojectM_VERSION_MAJOR@;
+  PROJECTM_VERSION_MINOR   = @libprojectM_VERSION_MINOR@;
+  PROJECTM_VERSION_RELEASE = @libprojectM_VERSION_RELEASE@;
+{$IFEND}
+
+{$@DEFINE_HAVE_PORTAUDIO@ HavePortaudio}
+{$IF Defined(HavePortaudio) and Defined(IncludeConstants)}
+  PORTAUDIO_VERSION_MAJOR   = @portaudio_VERSION_MAJOR@;
+  PORTAUDIO_VERSION_MINOR   = @portaudio_VERSION_MINOR@;
+  PORTAUDIO_VERSION_RELEASE = @portaudio_VERSION_RELEASE@;
+{$IFEND}
+
+{$@DEFINE_HAVE_LIBPCRE@ HaveLibPcre}
+{$IF Defined(HaveLibPcre) and Defined(IncludeConstants)}
+  LIBPCRE_LIBDIR   = '@libpcre_LIBDIR@';
+{$IFEND}
+
+{$@DEFINE_HAVE_PORTMIXER@ HavePortmixer}
diff --git a/songmanagement/src/encoding/Auto.inc b/songmanagement/src/encoding/Auto.inc
new file mode 100644
index 00000000..f404c2f6
--- /dev/null
+++ b/songmanagement/src/encoding/Auto.inc
@@ -0,0 +1,137 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+// Auto
+// try to match the w3c regex and decode as unicode on match and as fallback if not match
+// (copied from http://www.w3.org/International/questions/qa-forms-utf-8.en.php)
+//
+// m/\A(
+//    [\x09\x0A\x0D\x20-\x7E]            # ASCII
+//  | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
+//  |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
+//  | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
+//  |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
+//  |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
+//  | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
+//  |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
+// )*\z/x
+
+type
+  TEncoderAuto = class(TEncoder)
+  public
+    function GetName(): AnsiString; override;
+    function Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean; override;
+    function Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean; override;
+
+    constructor Create(const UTF8Encoder, FallbackEncoder: IEncoder);
+
+  private
+    FallbackEncoder: IEncoder;
+    UTF8Encoder: IEncoder;
+    Regex: PPCRE;
+    RegexExtra: PPCREExtra;
+  end;
+
+function PCREGetMem(Size: SizeInt): Pointer; cdecl;
+begin
+  GetMem(Result, Size);
+end;
+
+procedure PCREFreeMem(P: Pointer); cdecl;
+begin
+  FreeMem(P);
+end;
+
+// NOTICE: Log.LogError/ConsoleWriteLn/DebugWriteLn are initialized yet
+procedure ShowError(const msg: string);
+begin
+  {$IFDEF CONSOLE}
+  WriteLn('ERROR: ', msg);
+  {$ENDIF}
+end;
+
+constructor TEncoderAuto.Create(const UTF8Encoder, FallbackEncoder: IEncoder);
+var
+  Error: PChar;
+  ErrorOffset: Integer;
+begin
+  inherited Create();
+  self.FallbackEncoder := FallbackEncoder;
+  self.UTF8Encoder := UTF8Encoder;
+
+  // Load and initialize PCRE Library
+  if LoadPCRE() then
+  begin
+    // compile regex
+    self.Regex := pcre_compile('\A([\x09\x0A\x0D\x20-\x7E]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*\z', 0, @Error, @ErrorOffset, nil);
+
+    if self.Regex = Nil then
+    begin
+      ShowError(Format('UTF8 Regex compilation failed: %s at %d', [Error, ErrorOffset]));
+    end
+    else
+    begin
+      // if compiled successfull, try to get more informations the speed up the matching
+      self.RegexExtra := pcre_study(self.Regex, 0, @Error);
+
+      if Error <> Nil then
+      begin
+        ShowError('UTF8 Regex study failed: ' + Error);
+      end;
+    end;
+  end
+  else
+  begin
+    ShowError('pcre not loaded. utf-8 autodetection will not work.');
+  end;
+end;
+
+function TEncoderAuto.GetName(): AnsiString;
+begin
+  Result := 'Auto';
+end;
+
+function TEncoderAuto.Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean;
+var
+  RegexResults: Integer;
+begin
+  if (self.Regex <> Nil) then
+  begin
+    RegexResults := pcre_exec(Regex, RegexExtra, PChar(InStr), Length(InStr), 0, 0, Nil, 0);
+
+    if RegexResults >= 0 then
+    begin
+      Result := UTF8Encoder.Decode(InStr, OutStr);
+      Exit;
+    end;
+  end;
+
+  Result := FallbackEncoder.Decode(InStr, OutStr);
+end;
+
+function TEncoderAuto.Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean;
+begin
+  Result := UTF8Encoder.Encode(InStr, OutStr);
+end;
diff --git a/songmanagement/src/encoding/CP1250.inc b/songmanagement/src/encoding/CP1250.inc
new file mode 100644
index 00000000..5628156e
--- /dev/null
+++ b/songmanagement/src/encoding/CP1250.inc
@@ -0,0 +1,236 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+{*
+ * Windows-1250 Central/Eastern Europe
+ * (used by Ultrastar)
+ *}
+
+type
+  TEncoderCP1250 = class(TSingleByteEncoder)
+  public
+    function GetName(): AnsiString; override;
+    function DecodeChar(InChr: AnsiChar; out OutChr: UCS4Char): boolean; override;
+    function EncodeChar(InChr: UCS4Char; out OutChr: AnsiChar): boolean; override;
+  end;
+
+function TEncoderCP1250.GetName(): AnsiString;
+begin
+  Result := 'CP1250';
+end;
+
+const
+  // Positions marked as #0 are invalid.
+  CP1250Table: array[128..255] of UCS4Char = (
+    { $80 }
+    $20AC,     0, $201A,     0, $201E, $2026, $2020, $2021,
+        0, $2030, $0160, $2039, $015A, $0164, $017D, $0179,
+    { $90 }
+        0, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+        0, $2122, $0161, $203A, $015B, $0165, $017E, $017A,
+    { $A0 }
+    $00A0, $02C7, $02D8, $0141, $00A4, $0104, $00A6, $00A7,
+    $00A8, $00A9, $015E, $00AB, $00AC, $00AD, $00AE, $017B,
+    { $B0 }
+    $00B0, $00B1, $02DB, $0142, $00B4, $00B5, $00B6, $00B7,
+    $00B8, $0105, $015F, $00BB, $013D, $02DD, $013E, $017C,
+    { $C0 }
+    $0154, $00C1, $00C2, $0102, $00C4, $0139, $0106, $00C7,
+    $010C, $00C9, $0118, $00CB, $011A, $00CD, $00CE, $010E,
+    { $D0 }
+    $0110, $0143, $0147, $00D3, $00D4, $0150, $00D6, $00D7,
+    $0158, $016E, $00DA, $0170, $00DC, $00DD, $0162, $00DF,
+    { $E0 }
+    $0155, $00E1, $00E2, $0103, $00E4, $013A, $0107, $00E7,
+    $010D, $00E9, $0119, $00EB, $011B, $00ED, $00EE, $010F,
+    { $F0 }
+    $0111, $0144, $0148, $00F3, $00F4, $0151, $00F6, $00F7,
+    $0159, $016F, $00FA, $0171, $00FC, $00FD, $0163, $02D9
+  );
+
+function TEncoderCP1250.DecodeChar(InChr: AnsiChar; out OutChr: UCS4Char): boolean;
+begin
+  Result := true;
+  if (InChr < #128) then
+    OutChr := UCS4Char(Ord(InChr)) // use Ord() to avoid automatic conversion
+  else
+  begin
+    OutChr := CP1250Table[Ord(InChr)];
+    if (OutChr = 0) then
+    begin
+      Result := false;
+      OutChr := Ord(ERROR_CHAR);
+    end;
+  end;
+end;
+
+function TEncoderCP1250.EncodeChar(InChr: UCS4Char; out OutChr: AnsiChar): boolean;
+begin
+  if (InChr < 128) then
+  begin
+    OutChr := AnsiChar(Ord(InChr));
+    Result := true;
+  end
+  else
+  begin
+    case InChr of
+        $20AC: OutChr := #128;
+        // invalid: #129
+        $201A: OutChr := #130;
+        // invalid: #131
+        $201E: OutChr := #132;
+        $2026: OutChr := #133;
+        $2020: OutChr := #134;
+        $2021: OutChr := #135;
+        // invalid: #136
+        $2030: OutChr := #137;
+        $0160: OutChr := #138;
+        $2039: OutChr := #139;
+        $015A: OutChr := #140;
+        $0164: OutChr := #141;
+        $017D: OutChr := #142;
+        $0179: OutChr := #143;
+        // invalid: #144
+        $2018: OutChr := #145;
+        $2019: OutChr := #146;
+        $201C: OutChr := #147;
+        $201D: OutChr := #148;
+        $2022: OutChr := #149;
+        $2013: OutChr := #150;
+        $2014: OutChr := #151;
+        // invalid: #152
+        $2122: OutChr := #153;
+        $0161: OutChr := #154;
+        $203A: OutChr := #155;
+        $015B: OutChr := #156;
+        $0165: OutChr := #157;
+        $017E: OutChr := #158;
+        $017A: OutChr := #159;
+        $00A0: OutChr := #160;
+        $02C7: OutChr := #161;
+        $02D8: OutChr := #162;
+        $0141: OutChr := #163;
+        $00A4: OutChr := #164;
+        $0104: OutChr := #165;
+        $00A6: OutChr := #166;
+        $00A7: OutChr := #167;
+        $00A8: OutChr := #168;
+        $00A9: OutChr := #169;
+        $015E: OutChr := #170;
+        $00AB: OutChr := #171;
+        $00AC: OutChr := #172;
+        $00AD: OutChr := #173;
+        $00AE: OutChr := #174;
+        $017B: OutChr := #175;
+        $00B0: OutChr := #176;
+        $00B1: OutChr := #177;
+        $02DB: OutChr := #178;
+        $0142: OutChr := #179;
+        $00B4: OutChr := #180;
+        $00B5: OutChr := #181;
+        $00B6: OutChr := #182;
+        $00B7: OutChr := #183;
+        $00B8: OutChr := #184;
+        $0105: OutChr := #185;
+        $015F: OutChr := #186;
+        $00BB: OutChr := #187;
+        $013D: OutChr := #188;
+        $02DD: OutChr := #189;
+        $013E: OutChr := #190;
+        $017C: OutChr := #191;
+        $0154: OutChr := #192;
+        $00C1: OutChr := #193;
+        $00C2: OutChr := #194;
+        $0102: OutChr := #195;
+        $00C4: OutChr := #196;
+        $0139: OutChr := #197;
+        $0106: OutChr := #198;
+        $00C7: OutChr := #199;
+        $010C: OutChr := #200;
+        $00C9: OutChr := #201;
+        $0118: OutChr := #202;
+        $00CB: OutChr := #203;
+        $011A: OutChr := #204;
+        $00CD: OutChr := #205;
+        $00CE: OutChr := #206;
+        $010E: OutChr := #207;
+        $0110: OutChr := #208;
+        $0143: OutChr := #209;
+        $0147: OutChr := #210;
+        $00D3: OutChr := #211;
+        $00D4: OutChr := #212;
+        $0150: OutChr := #213;
+        $00D6: OutChr := #214;
+        $00D7: OutChr := #215;
+        $0158: OutChr := #216;
+        $016E: OutChr := #217;
+        $00DA: OutChr := #218;
+        $0170: OutChr := #219;
+        $00DC: OutChr := #220;
+        $00DD: OutChr := #221;
+        $0162: OutChr := #222;
+        $00DF: OutChr := #223;
+        $0155: OutChr := #224;
+        $00E1: OutChr := #225;
+        $00E2: OutChr := #226;
+        $0103: OutChr := #227;
+        $00E4: OutChr := #228;
+        $013A: OutChr := #229;
+        $0107: OutChr := #230;
+        $00E7: OutChr := #231;
+        $010D: OutChr := #232;
+        $00E9: OutChr := #233;
+        $0119: OutChr := #234;
+        $00EB: OutChr := #235;
+        $011B: OutChr := #236;
+        $00ED: OutChr := #237;
+        $00EE: OutChr := #238;
+        $010F: OutChr := #239;
+        $0111: OutChr := #240;
+        $0144: OutChr := #241;
+        $0148: OutChr := #242;
+        $00F3: OutChr := #243;
+        $00F4: OutChr := #244;
+        $0151: OutChr := #245;
+        $00F6: OutChr := #246;
+        $00F7: OutChr := #247;
+        $0159: OutChr := #248;
+        $016F: OutChr := #249;
+        $00FA: OutChr := #250;
+        $0171: OutChr := #251;
+        $00FC: OutChr := #252;
+        $00FD: OutChr := #253;
+        $0163: OutChr := #254;
+        $02D9: OutChr := #255;
+      else begin
+        OutChr := ERROR_CHAR;
+        Result := false;
+        Exit;
+      end;
+    end;
+    Result := true;
+  end;
+end;
+
diff --git a/songmanagement/src/encoding/CP1252.inc b/songmanagement/src/encoding/CP1252.inc
new file mode 100644
index 00000000..f7d3f8ea
--- /dev/null
+++ b/songmanagement/src/encoding/CP1252.inc
@@ -0,0 +1,122 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+{*
+ * Windows-1252 Western Europe
+ * (used by UltraStar Deluxe < 1.1)
+ *}
+
+type
+  TEncoderCP1252 = class(TSingleByteEncoder)
+  public
+    function GetName(): AnsiString; override;
+    function DecodeChar(InChr: AnsiChar; out OutChr: UCS4Char): boolean; override;
+    function EncodeChar(InChr: UCS4Char; out OutChr: AnsiChar): boolean; override;
+  end;
+
+function TEncoderCP1252.GetName(): AnsiString;
+begin
+  Result := 'CP1252';
+end;
+
+const
+  // Positions marked as #0 are invalid.
+  CP1252Table: array[128..159] of UCS4Char = (
+    { $80 }
+    $20AC,     0, $201A, $0192, $201E, $2026, $2020, $2021,
+    $02C6, $2030, $0160, $2039, $0152,     0, $017D,     0,
+    { $90 }
+        0, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+    $02DC, $2122, $0161, $203A, $0153,     0, $017E, $0178
+  );
+
+function TEncoderCP1252.DecodeChar(InChr: AnsiChar; out OutChr: UCS4Char): boolean;
+begin
+  Result := true;
+  if (InChr < #128) or (InChr >= #160) then
+    OutChr := UCS4Char(Ord(InChr)) // use Ord() to avoid automatic conversion
+  else
+  begin
+    OutChr := CP1252Table[Ord(InChr)];
+    if (OutChr = 0) then
+    begin
+      Result := false;
+      OutChr := Ord(ERROR_CHAR);
+    end;
+  end;
+end;
+
+function TEncoderCP1252.EncodeChar(InChr: UCS4Char; out OutChr: AnsiChar): boolean;
+begin
+  if (InChr < 128) or ((InChr >= 160) and (InChr <= 255)) then
+  begin
+    OutChr := AnsiChar(Ord(InChr));
+    Result := true;
+  end
+  else
+  begin
+    case InChr of
+      $20AC: OutChr := #128;
+      // invalid: #129
+      $201A: OutChr := #130;
+      $0192: OutChr := #131;
+      $201E: OutChr := #132;
+      $2026: OutChr := #133;
+      $2020: OutChr := #134;
+      $2021: OutChr := #135;
+      $02C6: OutChr := #136;
+      $2030: OutChr := #137;
+      $0160: OutChr := #138;
+      $2039: OutChr := #139;
+      $0152: OutChr := #140;
+      // invalid: #141
+      $017D: OutChr := #142;
+      // invalid: #143
+      // invalid: #144
+      $2018: OutChr := #145;
+      $2019: OutChr := #146;
+      $201C: OutChr := #147;
+      $201D: OutChr := #148;
+      $2022: OutChr := #149;
+      $2013: OutChr := #150;
+      $2014: OutChr := #151;
+      $02DC: OutChr := #152;
+      $2122: OutChr := #153;
+      $0161: OutChr := #154;
+      $203A: OutChr := #155;
+      $0153: OutChr := #156;
+      // invalid: #157
+      $017E: OutChr := #158;
+      $0178: OutChr := #159;
+      else begin
+        OutChr := ERROR_CHAR;
+        Result := false;
+        Exit;
+      end;
+    end;
+    Result := true;
+  end;
+end;
+
diff --git a/songmanagement/src/encoding/Locale.inc b/songmanagement/src/encoding/Locale.inc
new file mode 100644
index 00000000..a3cdcebc
--- /dev/null
+++ b/songmanagement/src/encoding/Locale.inc
@@ -0,0 +1,55 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+{*
+ * Locale
+ *}
+
+type
+  TEncoderLocale = class(TEncoder)
+  public
+    function GetName(): AnsiString; override;
+    function Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean; override;
+    function Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean; override;
+  end;
+
+function TEncoderLocale.GetName(): AnsiString;
+begin
+  Result := 'LOCALE';
+end;
+
+function TEncoderLocale.Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean;
+begin
+  OutStr := WideStringToUCS4String(InStr); // use implicit conversion
+  Result := true;
+end;
+
+function TEncoderLocale.Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean;
+begin
+  OutStr := UCS4StringToWideString(InStr); // use implicit conversion
+  // any way to check for errors?
+  Result := true;
+end;
+
diff --git a/songmanagement/src/encoding/UTF8.inc b/songmanagement/src/encoding/UTF8.inc
new file mode 100644
index 00000000..43eacfbd
--- /dev/null
+++ b/songmanagement/src/encoding/UTF8.inc
@@ -0,0 +1,70 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+{*
+ * UTF-8
+ *}
+
+type
+  TEncoderUTF8 = class(TEncoder)
+  public
+    function GetName(): AnsiString; override;
+    function Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean; override;
+    function Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean; override;
+  end;
+
+function TEncoderUTF8.GetName(): AnsiString;
+begin
+  Result := 'UTF8';
+end;
+
+function TEncoderUTF8.Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean;
+var
+  I: integer;
+  StrPtr: PAnsiChar;
+begin
+  // UTF8Decode() may crash with FPC < 2.2.2 if the input string is not UTF-8
+  // encoded. Newer versions do not crash but do not signal errors either.
+  // So let's implement this stuff again.
+  Result := true;
+  SetLength(OutStr, Length(InStr)+1);
+  I := 0;
+  StrPtr := PChar(InStr);
+  while (StrPtr^ <> #0) do
+  begin
+    if (not NextCharUTF8(StrPtr, OutStr[I])) then
+      Result := false;;
+    Inc(I);
+  end;
+  SetLength(OutStr, I+1);
+  OutStr[High(OutStr)] := 0;
+end;
+
+function TEncoderUTF8.Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean;
+begin
+  OutStr := UCS4ToUTF8String(InStr);
+  Result := true;
+end;
+
diff --git a/songmanagement/src/lib/FreeImage/FreeBitmap.pas b/songmanagement/src/lib/FreeImage/FreeBitmap.pas
new file mode 100644
index 00000000..d32fb5cb
--- /dev/null
+++ b/songmanagement/src/lib/FreeImage/FreeBitmap.pas
@@ -0,0 +1,1742 @@
+unit FreeBitmap;
+
+// ==========================================================
+//
+// Delphi wrapper for FreeImage 3
+//
+// Design and implementation by
+// - Anatoliy Pulyaevskiy (xvel84@rambler.ru)
+//
+// Contributors:
+// - Enzo Costantini (enzocostantini@libero.it)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+//
+// ==========================================================
+//
+// From begining all code of this file is based on C++ wrapper to
+// FreeImage - FreeImagePlus.
+//
+// ==========================================================
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+interface
+
+uses
+  SysUtils, Classes, Windows, FreeImage;
+
+type
+  { TFreeObject }
+
+  TFreeObject = class(TObject)
+  public
+    function IsValid: Boolean; virtual;
+  end;
+
+  { TFreeTag }
+
+  TFreeTag = class(TFreeObject)
+  private
+    // fields
+    FTag: PFITAG;
+
+    // getters & setters
+    function GetCount: Cardinal;
+    function GetDescription: string;
+    function GetID: Word;
+    function GetKey: string;
+    function GetLength: Cardinal;
+    function GetTagType: FREE_IMAGE_MDTYPE;
+    function GetValue: Pointer;
+    procedure SetCount(const Value: Cardinal);
+    procedure SetDescription(const Value: string);
+    procedure SetID(const Value: Word);
+    procedure SetKey(const Value: string);
+    procedure SetLength(const Value: Cardinal);
+    procedure SetTagType(const Value: FREE_IMAGE_MDTYPE);
+    procedure SetValue(const Value: Pointer);
+  public
+    // construction & destruction
+    constructor Create(ATag: PFITAG = nil); virtual;
+    destructor Destroy; override;
+
+    // methods
+    function Clone: TFreeTag;
+    function IsValid: Boolean; override;
+    function ToString(Model: FREE_IMAGE_MDMODEL; Make: PChar = nil): string;
+
+    // properties
+    property Key: string read GetKey write SetKey;
+    property Description: string read GetDescription write SetDescription;
+    property ID: Word read GetID write SetID;
+    property TagType: FREE_IMAGE_MDTYPE read GetTagType write SetTagType;
+    property Count: Cardinal read GetCount write SetCount;
+    property Length: Cardinal read GetLength write SetLength;
+    property Value: Pointer read GetValue write SetValue;
+    property Tag: PFITAG read FTag;
+  end;
+
+  { forward declarations }
+
+  TFreeBitmap = class;
+  TFreeMemoryIO = class;
+
+  { TFreeBitmap }
+
+  TFreeBitmapChangingEvent = procedure(Sender: TFreeBitmap; var OldDib, NewDib: PFIBITMAP; var Handled: Boolean) of object;
+
+  TFreeBitmap = class(TFreeObject)
+  private
+    // fields
+    FDib: PFIBITMAP;
+    FOnChange: TNotifyEvent;
+    FOnChanging: TFreeBitmapChangingEvent;
+
+    procedure SetDib(Value: PFIBITMAP);
+  protected
+    function DoChanging(var OldDib, NewDib: PFIBITMAP): Boolean; dynamic;
+    function Replace(NewDib: PFIBITMAP): Boolean; dynamic;
+  public
+    constructor Create(ImageType: FREE_IMAGE_TYPE = FIT_BITMAP; Width: Integer = 0; Height: Integer = 0; Bpp: Integer = 0);
+    destructor Destroy; override;
+    function SetSize(ImageType: FREE_IMAGE_TYPE; Width, Height, Bpp: Integer; RedMask: Cardinal = 0; GreenMask: Cardinal = 0; BlueMask: Cardinal = 0): Boolean;
+    procedure Change; dynamic;
+    procedure Assign(Source: TFreeBitmap);
+    function CopySubImage(Left, Top, Right, Bottom: Integer; Dest: TFreeBitmap): Boolean;
+    function PasteSubImage(Src: TFreeBitmap; Left, Top: Integer; Alpha: Integer = 256): Boolean;
+    procedure Clear; virtual;
+    function Load(const FileName: string; Flag: Integer = 0): Boolean;
+    function LoadU(const FileName: WideString; Flag: Integer = 0): Boolean;
+    function LoadFromHandle(IO: PFreeImageIO; Handle: fi_handle; Flag: Integer = 0): Boolean;
+    function LoadFromMemory(MemIO: TFreeMemoryIO; Flag: Integer = 0): Boolean;
+    function LoadFromStream(Stream: TStream; Flag: Integer = 0): Boolean;
+    // save functions
+    function CanSave(fif: FREE_IMAGE_FORMAT): Boolean;
+    function Save(const FileName: string; Flag: Integer = 0): Boolean;
+    function SaveU(const FileName: WideString; Flag: Integer = 0): Boolean;
+    function SaveToHandle(fif: FREE_IMAGE_FORMAT; IO: PFreeImageIO; Handle: fi_handle; Flag: Integer = 0): Boolean;
+    function SaveToMemory(fif: FREE_IMAGE_FORMAT; MemIO: TFreeMemoryIO; Flag: Integer = 0): Boolean;
+    function SaveToStream(fif: FREE_IMAGE_FORMAT; Stream: TStream; Flag: Integer = 0): Boolean;
+    // image information
+    function GetImageType: FREE_IMAGE_TYPE;
+    function GetWidth: Integer;
+    function GetHeight: Integer;
+    function GetScanWidth: Integer;
+    function IsValid: Boolean; override;
+    function GetInfo: PBitmapInfo;
+    function GetInfoHeader: PBitmapInfoHeader;
+    function GetImageSize: Cardinal;
+    function GetBitsPerPixel: Integer;
+    function GetLine: Integer;
+    function GetHorizontalResolution: Double;
+    function GetVerticalResolution: Double;
+    procedure SetHorizontalResolution(Value: Double);
+    procedure SetVerticalResolution(Value: Double);
+    // palette operations
+    function GetPalette: PRGBQUAD;
+    function GetPaletteSize: Integer;
+    function GetColorsUsed: Integer;
+    function GetColorType: FREE_IMAGE_COLOR_TYPE;
+    function IsGrayScale: Boolean;
+    // pixels access
+    function AccessPixels: PByte;
+    function GetScanLine(ScanLine: Integer): PByte;
+    function GetPixelIndex(X, Y: Cardinal; var Value: PByte): Boolean;
+    function GetPixelColor(X, Y: Cardinal; Value: PRGBQUAD): Boolean;
+    function SetPixelIndex(X, Y: Cardinal; Value: PByte): Boolean;
+    function SetPixelColor(X, Y: Cardinal; Value: PRGBQUAD): Boolean;
+    // convertion
+    function ConvertToStandardType(ScaleLinear: Boolean): Boolean;
+    function ConvertToType(ImageType: FREE_IMAGE_TYPE; ScaleLinear: Boolean): Boolean;
+    function Threshold(T: Byte): Boolean;
+    function ConvertTo4Bits: Boolean;
+    function ConvertTo8Bits: Boolean;
+    function ConvertTo16Bits555: Boolean;
+    function ConvertTo16Bits565: Boolean;
+    function ConvertTo24Bits: Boolean;
+    function ConvertTo32Bits: Boolean;
+    function ConvertToGrayscale: Boolean;
+    function ColorQuantize(Algorithm: FREE_IMAGE_QUANTIZE): Boolean;
+    function Dither(Algorithm: FREE_IMAGE_DITHER): Boolean;
+    function ConvertToRGBF: Boolean;
+    function ToneMapping(TMO: FREE_IMAGE_TMO; FirstParam, SecondParam: Double): Boolean;
+    // transparency
+    function IsTransparent: Boolean;
+    function GetTransparencyCount: Cardinal;
+    function GetTransparencyTable: PByte;
+    procedure SetTransparencyTable(Table: PByte; Count: Integer);
+    function HasFileBkColor: Boolean;
+    function GetFileBkColor(var BkColor: PRGBQuad): Boolean;
+    function SetFileBkColor(BkColor: PRGBQuad): Boolean;
+    // channel processing routines
+    function GetChannel(Bitmap: TFreeBitmap; Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+    function SetChannel(Bitmap: TFreeBitmap; Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+    function SplitChannels(RedChannel, GreenChannel, BlueChannel: TFreeBitmap): Boolean;
+    function CombineChannels(Red, Green, Blue: TFreeBitmap): Boolean;
+    // rotation and flipping
+    function RotateEx(Angle, XShift, YShift, XOrigin, YOrigin: Double; UseMask: Boolean): Boolean;
+    function Rotate(Angle: Double): Boolean;
+    function FlipHorizontal: Boolean;
+    function FlipVertical: Boolean;
+    // color manipulation routines
+    function Invert: Boolean;
+    function AdjustCurve(Lut: PByte; Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+    function AdjustGamma(Gamma: Double): Boolean;
+    function AdjustBrightness(Percentage: Double): Boolean;
+    function AdjustContrast(Percentage: Double): Boolean;
+    function GetHistogram(Histo: PDWORD; Channel: FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK): Boolean;
+    // upsampling / downsampling
+    procedure MakeThumbnail(const Width, Height: Integer; DestBitmap: TFreeBitmap);
+    function Rescale(NewWidth, NewHeight: Integer; Filter: FREE_IMAGE_FILTER; Dest: TFreeBitmap = nil): Boolean;
+    // metadata routines
+    function FindFirstMetadata(Model: FREE_IMAGE_MDMODEL; var Tag: TFreeTag): PFIMETADATA;
+    function FindNextMetadata(MDHandle: PFIMETADATA; var Tag: TFreeTag): Boolean;
+    procedure FindCloseMetadata(MDHandle: PFIMETADATA);
+    function SetMetadata(Model: FREE_IMAGE_MDMODEL; const Key: string; Tag: TFreeTag): Boolean;
+    function GetMetadata(Model: FREE_IMAGE_MDMODEL; const Key: string; var Tag: TFreeTag): Boolean;
+    function GetMetadataCount(Model: FREE_IMAGE_MDMODEL): Cardinal;
+
+    // properties
+    property Dib: PFIBITMAP read FDib write SetDib;
+    property OnChange: TNotifyEvent read FOnChange write FOnChange;
+    property OnChanging: TFreeBitmapChangingEvent read FOnChanging write FOnChanging;
+  end;
+  
+  { TFreeWinBitmap }
+
+
+  { TFreeMemoryIO }
+
+  TFreeMemoryIO = class(TFreeObject)
+  private
+    FHMem: PFIMEMORY;
+  public
+    // construction and destruction
+    constructor Create(Data: PByte = nil; SizeInBytes: DWORD = 0);
+    destructor Destroy; override;
+
+    function GetFileType: FREE_IMAGE_FORMAT;
+    function Read(fif: FREE_IMAGE_FORMAT; Flag: Integer = 0): PFIBITMAP;
+    function Write(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; Flag: Integer = 0): Boolean;
+    function Tell: Longint;
+    function Seek(Offset: Longint; Origin: Word): Boolean;
+    function Acquire(var Data: PByte; var SizeInBytes: DWORD): Boolean;
+    // overriden methods
+    function IsValid: Boolean; override;
+  end;
+
+  { TFreeMultiBitmap }
+
+  TFreeMultiBitmap = class(TFreeObject)
+  private
+    FMPage: PFIMULTIBITMAP;
+    FMemoryCache: Boolean;
+  public
+    // constructor and destructor
+    constructor Create(KeepCacheInMemory: Boolean = False);
+    destructor Destroy; override;
+
+    // methods
+    function Open(const FileName: string; CreateNew, ReadOnly: Boolean; Flags: Integer = 0): Boolean;
+    function Close(Flags: Integer = 0): Boolean;
+    function GetPageCount: Integer;
+    procedure AppendPage(Bitmap: TFreeBitmap);
+    procedure InsertPage(Page: Integer; Bitmap: TFreeBitmap);
+    procedure DeletePage(Page: Integer);
+    function MovePage(Target, Source: Integer): Boolean;
+    procedure LockPage(Page: Integer; DestBitmap: TFreeBitmap);
+    procedure UnlockPage(Bitmap: TFreeBitmap; Changed: Boolean);
+    function GetLockedPageNumbers(var Pages: Integer; var Count: Integer): Boolean;    
+    // overriden methods
+    function IsValid: Boolean; override;
+
+    // properties
+    // change of this property influences only on the next opening of a file
+    property MemoryCache: Boolean read FMemoryCache write FMemoryCache;
+  end;
+
+implementation
+
+const
+  ThumbSize = 150;
+
+// marker used for clipboard copy / paste
+
+procedure SetFreeImageMarker(bmih: PBitmapInfoHeader; dib: PFIBITMAP);
+begin
+  // Windows constants goes from 0L to 5L
+	// Add $FF to avoid conflicts
+	bmih.biCompression := $FF + FreeImage_GetImageType(dib);
+end;
+
+function GetFreeImageMarker(bmih: PBitmapInfoHeader): FREE_IMAGE_TYPE;
+begin
+  Result := FREE_IMAGE_TYPE(bmih.biCompression - $FF);
+end;
+
+{ TFreePersistent }
+
+function TFreeObject.IsValid: Boolean;
+begin
+  Result := False
+end;
+
+{ TFreeBitmap }
+
+function TFreeBitmap.AccessPixels: PByte;
+begin
+  Result := FreeImage_GetBits(FDib)
+end;
+
+function TFreeBitmap.AdjustBrightness(Percentage: Double): Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Result := FreeImage_AdjustBrightness(FDib, Percentage);
+    Change;
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.AdjustContrast(Percentage: Double): Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Result := FreeImage_AdjustContrast(FDib, Percentage);
+    Change;
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.AdjustCurve(Lut: PByte;
+  Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Result := FreeImage_AdjustCurve(FDib, Lut, Channel);
+    Change;
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.AdjustGamma(Gamma: Double): Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Result := FreeImage_AdjustGamma(FDib, Gamma);
+    Change;
+  end
+  else
+    Result := False
+end;
+
+procedure TFreeBitmap.Assign(Source: TFreeBitmap);
+var
+  SourceBmp: TFreeBitmap;
+  Clone: PFIBITMAP;
+begin
+  if Source = nil then
+  begin
+    Clear;
+    Exit;
+  end;
+  
+  if Source is TFreeBitmap then
+  begin
+    SourceBmp := TFreeBitmap(Source);
+    if SourceBmp <> Self then
+    begin
+      if SourceBmp.IsValid then
+      begin
+        Clone := FreeImage_Clone(SourceBmp.FDib);
+        Replace(Clone);
+      end
+      else
+        Clear;
+    end;
+  end;
+end;
+
+function TFreeBitmap.CanSave(fif: FREE_IMAGE_FORMAT): Boolean;
+var
+  ImageType: FREE_IMAGE_TYPE;
+  Bpp: Word;
+begin
+  Result := False;
+  if not IsValid then Exit;
+
+  if fif <> FIF_UNKNOWN then
+  begin
+    // check that the dib can be saved in this format
+    ImageType := FreeImage_GetImageType(FDib);
+    if ImageType = FIT_BITMAP then
+    begin
+      // standard bitmap type
+      Bpp := FreeImage_GetBPP(FDib);
+      Result := FreeImage_FIFSupportsWriting(fif)
+                and FreeImage_FIFSupportsExportBPP(fif, Bpp);
+    end
+    else // special bitmap type
+      Result := FreeImage_FIFSupportsExportType(fif, ImageType);
+  end;
+end;
+
+procedure TFreeBitmap.Change;
+begin
+  if Assigned(FOnChange) then FOnChange(Self)
+end;
+
+procedure TFreeBitmap.Clear;
+begin
+  if FDib <> nil then
+  begin
+    FreeImage_Unload(FDib);
+    FDib := nil;
+    Change;
+  end;
+end;
+
+function TFreeBitmap.ColorQuantize(
+  Algorithm: FREE_IMAGE_QUANTIZE): Boolean;
+var
+  dib8: PFIBITMAP;
+begin
+  if FDib <> nil then
+  begin
+    dib8 := FreeImage_ColorQuantize(FDib, Algorithm);
+    Result := Replace(dib8);
+  end
+  else
+    Result := False;
+end;
+
+function TFreeBitmap.CombineChannels(Red, Green,
+  Blue: TFreeBitmap): Boolean;
+var
+  Width, Height: Integer;
+begin
+  if FDib = nil then
+  begin
+    Width := Red.GetWidth;
+    Height := Red.GetHeight;
+    FDib := FreeImage_Allocate(Width, Height, 24, FI_RGBA_RED_MASK,
+            FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+  end;
+
+  if FDib <> nil then
+  begin
+    Result := FreeImage_SetChannel(FDib, Red.FDib, FICC_RED) and
+              FreeImage_SetChannel(FDib, Green.FDib, FICC_GREEN) and
+              FreeImage_SetChannel(FDib, Blue.FDib, FICC_BLUE);
+
+    Change
+  end
+  else
+    Result := False;
+end;
+
+function TFreeBitmap.ConvertTo16Bits555: Boolean;
+var
+  dib16_555: PFIBITMAP;
+begin
+  if FDib <> nil then
+  begin
+    dib16_555 := FreeImage_ConvertTo16Bits555(FDib);
+    Result := Replace(dib16_555);
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.ConvertTo16Bits565: Boolean;
+var
+  dib16_565: PFIBITMAP;
+begin
+  if FDib <> nil then
+  begin
+    dib16_565 := FreeImage_ConvertTo16Bits565(FDib);
+    Result := Replace(dib16_565);
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.ConvertTo24Bits: Boolean;
+var
+  dibRGB: PFIBITMAP;
+begin
+  if FDib <> nil then
+  begin
+    dibRGB := FreeImage_ConvertTo24Bits(FDib);
+    Result := Replace(dibRGB);
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.ConvertTo32Bits: Boolean;
+var
+  dib32: PFIBITMAP;
+begin
+  if FDib <> nil then
+  begin
+    dib32 := FreeImage_ConvertTo32Bits(FDib);
+    Result := Replace(dib32);
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.ConvertTo4Bits: Boolean;
+var
+  dib4: PFIBITMAP;
+begin
+  Result := False;
+  if IsValid then
+  begin
+    dib4 := FreeImage_ConvertTo4Bits(FDib);
+    Result := Replace(dib4);
+  end;
+end;
+
+function TFreeBitmap.ConvertTo8Bits: Boolean;
+var
+  dib8: PFIBITMAP;
+begin
+  if FDib <> nil then
+  begin
+    dib8 := FreeImage_ConvertTo8Bits(FDib);
+    Result := Replace(dib8);
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.ConvertToGrayscale: Boolean;
+var
+  dib8: PFIBITMAP;
+begin
+  Result := False;
+
+  if IsValid then
+  begin
+    dib8 := FreeImage_ConvertToGreyscale(FDib);
+    Result := Replace(dib8);
+  end
+end;
+
+function TFreeBitmap.ConvertToRGBF: Boolean;
+var
+  ImageType: FREE_IMAGE_TYPE;
+  NewDib: PFIBITMAP;
+begin
+  Result := False;
+  if not IsValid then Exit;
+
+  ImageType := GetImageType;
+
+  if (ImageType = FIT_BITMAP) then
+  begin
+    if GetBitsPerPixel < 24 then
+      if not ConvertTo24Bits then
+        Exit
+  end;
+  NewDib := FreeImage_ConvertToRGBF(FDib);
+  Result := Replace(NewDib);
+end;
+
+function TFreeBitmap.ConvertToStandardType(ScaleLinear: Boolean): Boolean;
+var
+  dibStandard: PFIBITMAP;
+begin
+  if IsValid then
+  begin
+    dibStandard := FreeImage_ConvertToStandardType(FDib, ScaleLinear);
+    Result := Replace(dibStandard);
+  end
+  else
+    Result := False;
+end;
+
+function TFreeBitmap.ConvertToType(ImageType: FREE_IMAGE_TYPE;
+  ScaleLinear: Boolean): Boolean;
+var
+  dib: PFIBITMAP;
+begin
+  if FDib <> nil then
+  begin
+    dib := FreeImage_ConvertToType(FDib, ImageType, ScaleLinear);
+    Result := Replace(dib)
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.CopySubImage(Left, Top, Right, Bottom: Integer;
+  Dest: TFreeBitmap): Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Dest.FDib := FreeImage_Copy(FDib, Left, Top, Right, Bottom);
+    Result := Dest.IsValid;
+  end else
+    Result := False;
+end;
+
+constructor TFreeBitmap.Create(ImageType: FREE_IMAGE_TYPE; Width, Height,
+  Bpp: Integer);
+begin
+  inherited Create;
+
+  FDib := nil;
+  if (Width > 0) and (Height > 0) and (Bpp > 0) then
+    SetSize(ImageType, Width, Height, Bpp);
+end;
+
+destructor TFreeBitmap.Destroy;
+begin
+  if FDib <> nil then
+    FreeImage_Unload(FDib);
+  inherited;
+end;
+
+function TFreeBitmap.Dither(Algorithm: FREE_IMAGE_DITHER): Boolean;
+var
+  dib: PFIBITMAP;
+begin
+  if FDib <> nil then
+  begin
+    dib := FreeImage_Dither(FDib, Algorithm);
+    Result := Replace(dib);
+  end
+  else
+    Result := False;
+end;
+
+function TFreeBitmap.DoChanging(var OldDib, NewDib: PFIBITMAP): Boolean;
+begin
+  Result := False;
+  if (OldDib <> NewDib) and Assigned(FOnChanging) then
+    FOnChanging(Self, OldDib, NewDib, Result);
+end;
+
+procedure TFreeBitmap.FindCloseMetadata(MDHandle: PFIMETADATA);
+begin
+  FreeImage_FindCloseMetadata(MDHandle);
+end;
+
+function TFreeBitmap.FindFirstMetadata(Model: FREE_IMAGE_MDMODEL;
+  var Tag: TFreeTag): PFIMETADATA;
+begin
+  Result := FreeImage_FindFirstMetadata(Model, FDib, Tag.FTag);
+end;
+
+function TFreeBitmap.FindNextMetadata(MDHandle: PFIMETADATA;
+  var Tag: TFreeTag): Boolean;
+begin
+  Result := FreeImage_FindNextMetadata(MDHandle, Tag.FTag);
+end;
+
+function TFreeBitmap.FlipHorizontal: Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Result := FreeImage_FlipHorizontal(FDib);
+    Change;
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.FlipVertical: Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Result := FreeImage_FlipVertical(FDib);
+    Change;
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.GetBitsPerPixel: Integer;
+begin
+  Result := FreeImage_GetBPP(FDib)
+end;
+
+function TFreeBitmap.GetChannel(Bitmap: TFreeBitmap;
+  Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Bitmap.Dib := FreeImage_GetChannel(FDib, Channel);
+    Result := Bitmap.IsValid;
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.GetColorsUsed: Integer;
+begin
+  Result := FreeImage_GetColorsUsed(FDib)
+end;
+
+function TFreeBitmap.GetColorType: FREE_IMAGE_COLOR_TYPE;
+begin
+  Result := FreeImage_GetColorType(FDib);
+end;
+
+function TFreeBitmap.GetFileBkColor(var BkColor: PRGBQuad): Boolean;
+begin
+  Result := FreeImage_GetBackgroundColor(FDib, BkColor)
+end;
+
+function TFreeBitmap.GetHeight: Integer;
+begin
+  Result := FreeImage_GetHeight(FDib)
+end;
+
+function TFreeBitmap.GetHistogram(Histo: PDWORD;
+  Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+begin
+  if FDib <> nil then
+    Result := FreeImage_GetHistogram(FDib, Histo, Channel)
+  else
+    Result := False
+end;
+
+function TFreeBitmap.GetHorizontalResolution: Double;
+begin
+  Result := FreeImage_GetDotsPerMeterX(FDib) / 100
+end;
+
+function TFreeBitmap.GetImageSize: Cardinal;
+begin
+  Result := FreeImage_GetDIBSize(FDib);
+end;
+
+function TFreeBitmap.GetImageType: FREE_IMAGE_TYPE;
+begin
+  Result := FreeImage_GetImageType(FDib);
+end;
+
+function TFreeBitmap.GetInfo: PBitmapInfo;
+begin
+  Result := FreeImage_GetInfo(FDib^)
+end;
+
+function TFreeBitmap.GetInfoHeader: PBITMAPINFOHEADER;
+begin
+  Result := FreeImage_GetInfoHeader(FDib)
+end;
+
+function TFreeBitmap.GetLine: Integer;
+begin
+  Result := FreeImage_GetLine(FDib)
+end;
+
+function TFreeBitmap.GetMetadata(Model: FREE_IMAGE_MDMODEL;
+  const Key: string; var Tag: TFreeTag): Boolean;
+begin
+  Result := FreeImage_GetMetaData(Model, FDib, PChar(Key), Tag.FTag);
+end;
+
+function TFreeBitmap.GetMetadataCount(Model: FREE_IMAGE_MDMODEL): Cardinal;
+begin
+  Result := FreeImage_GetMetadataCount(Model, FDib);
+end;
+
+function TFreeBitmap.GetPalette: PRGBQUAD;
+begin
+  Result := FreeImage_GetPalette(FDib)
+end;
+
+function TFreeBitmap.GetPaletteSize: Integer;
+begin
+  Result := FreeImage_GetColorsUsed(FDib) * SizeOf(RGBQUAD)
+end;
+
+function TFreeBitmap.GetPixelColor(X, Y: Cardinal; Value: PRGBQUAD): Boolean;
+begin
+  Result := FreeImage_GetPixelColor(FDib, X, Y, Value)
+end;
+
+function TFreeBitmap.GetPixelIndex(X, Y: Cardinal;
+  var Value: PByte): Boolean;
+begin
+  Result := FreeImage_GetPixelIndex(FDib, X, Y, Value)
+end;
+
+function TFreeBitmap.GetScanLine(ScanLine: Integer): PByte;
+var
+  H: Integer;
+begin
+  H := FreeImage_GetHeight(FDib);
+  if ScanLine < H then
+    Result := FreeImage_GetScanLine(FDib, ScanLine)
+  else
+    Result := nil;
+end;
+
+function TFreeBitmap.GetScanWidth: Integer;
+begin
+  Result := FreeImage_GetPitch(FDib)
+end;
+
+function TFreeBitmap.GetTransparencyCount: Cardinal;
+begin
+  Result := FreeImage_GetTransparencyCount(FDib)
+end;
+
+function TFreeBitmap.GetTransparencyTable: PByte;
+begin
+  Result := FreeImage_GetTransparencyTable(FDib)
+end;
+
+function TFreeBitmap.GetVerticalResolution: Double;
+begin
+  Result := FreeImage_GetDotsPerMeterY(Fdib) / 100
+end;
+
+function TFreeBitmap.GetWidth: Integer;
+begin
+  Result := FreeImage_GetWidth(FDib)
+end;
+
+function TFreeBitmap.HasFileBkColor: Boolean;
+begin
+  Result := FreeImage_HasBackgroundColor(FDib)
+end;
+
+function TFreeBitmap.Invert: Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Result := FreeImage_Invert(FDib);
+    Change;
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.IsGrayScale: Boolean;
+begin
+  Result := (FreeImage_GetBPP(FDib) = 8)
+            and (FreeImage_GetColorType(FDib) = FIC_PALETTE); 
+end;
+
+function TFreeBitmap.IsTransparent: Boolean;
+begin
+  Result := FreeImage_IsTransparent(FDib);
+end;
+
+function TFreeBitmap.IsValid: Boolean;
+begin
+  Result := FDib <> nil
+end;
+
+function TFreeBitmap.Load(const FileName: string; Flag: Integer): Boolean;
+var
+  fif: FREE_IMAGE_FORMAT;
+begin
+
+  // check the file signature and get its format
+  fif := FreeImage_GetFileType(PChar(Filename), 0);
+  if fif = FIF_UNKNOWN then
+    // no signature?
+    // try to guess the file format from the file extention
+    fif := FreeImage_GetFIFFromFilename(PChar(FileName));
+
+    // check that the plugin has reading capabilities ...
+    if (fif <> FIF_UNKNOWN) and FreeImage_FIFSupportsReading(FIF) then
+    begin
+      // free the previous dib
+      if FDib <> nil then
+        FreeImage_Unload(dib);
+
+      // load the file
+      FDib := FreeImage_Load(fif, PChar(FileName), Flag);
+
+      Change;
+      Result := IsValid;
+    end else
+      Result := False;
+end;
+
+function TFreeBitmap.LoadFromHandle(IO: PFreeImageIO; Handle: fi_handle;
+  Flag: Integer): Boolean;
+var
+  fif: FREE_IMAGE_FORMAT;
+begin
+  // check the file signature and get its format
+  fif := FreeImage_GetFileTypeFromHandle(IO, Handle, 16);
+  if (fif <> FIF_UNKNOWN) and FreeImage_FIFSupportsReading(fif) then
+  begin
+    // free the previous dib
+    if FDib <> nil then
+      FreeImage_Unload(FDib);
+
+    // load the file
+    FDib := FreeImage_LoadFromHandle(fif, IO, Handle, Flag);
+
+    Change;
+    Result := IsValid;
+  end else
+    Result := False;
+end;
+
+function TFreeBitmap.LoadFromMemory(MemIO: TFreeMemoryIO;
+  Flag: Integer): Boolean;
+var
+  fif: FREE_IMAGE_FORMAT;
+begin
+
+  // check the file signature and get its format
+  fif := MemIO.GetFileType;
+  if (fif <> FIF_UNKNOWN) and FreeImage_FIFSupportsReading(fif) then
+  begin
+    // free the previous dib
+    if FDib <> nil then
+      FreeImage_Unload(FDib);
+
+    // load the file
+    FDib := MemIO.Read(fif, Flag);
+
+    Result := IsValid;
+    Change;
+  end else
+    Result := False;
+end;
+
+function TFreeBitmap.LoadFromStream(Stream: TStream;
+  Flag: Integer): Boolean;
+var
+  MemIO: TFreeMemoryIO;
+  Data: PByte;
+  MemStream: TMemoryStream;
+  Size: Cardinal;
+begin
+  Size := Stream.Size;
+
+  MemStream := TMemoryStream.Create;
+  try
+    MemStream.CopyFrom(Stream, Size);
+    Data := MemStream.Memory;
+
+    MemIO := TFreeMemoryIO.Create(Data, Size);
+    try
+      Result := LoadFromMemory(MemIO);
+    finally
+      MemIO.Free;
+    end;
+  finally
+    MemStream.Free;
+  end;
+end;
+
+function TFreeBitmap.LoadU(const FileName: WideString;
+  Flag: Integer): Boolean;
+var
+  fif: FREE_IMAGE_FORMAT;
+begin
+
+  // check the file signature and get its format
+  fif := FreeImage_GetFileTypeU(PWideChar(Filename), 0);
+  if fif = FIF_UNKNOWN then
+    // no signature?
+    // try to guess the file format from the file extention
+    fif := FreeImage_GetFIFFromFilenameU(PWideChar(FileName));
+
+    // check that the plugin has reading capabilities ...
+    if (fif <> FIF_UNKNOWN) and FreeImage_FIFSupportsReading(FIF) then
+    begin
+      // free the previous dib
+      if FDib <> nil then
+        FreeImage_Unload(dib);
+
+      // load the file
+      FDib := FreeImage_LoadU(fif, PWideChar(FileName), Flag);
+
+      Change;
+      Result := IsValid;
+    end else
+      Result := False;
+end;
+
+procedure TFreeBitmap.MakeThumbnail(const Width, Height: Integer;
+  DestBitmap: TFreeBitmap);
+type
+  PRGB24 = ^TRGB24;
+  TRGB24 = packed record
+    B: Byte;
+    G: Byte;
+    R: Byte;
+  end;
+var
+  x, y, ix, iy: integer;
+  x1, x2, x3: integer;
+
+  xscale, yscale: single;
+  iRed, iGrn, iBlu, iRatio: Longword;
+  p, c1, c2, c3, c4, c5: TRGB24;
+  pt, pt1: PRGB24;
+  iSrc, iDst, s1: integer;
+  i, j, r, g, b, tmpY: integer;
+
+  RowDest, RowSource, RowSourceStart: integer;
+  w, h: Integer;
+  dxmin, dymin: integer;
+  ny1, ny2, ny3: integer;
+  dx, dy: integer;
+  lutX, lutY: array of integer;
+
+  SrcBmp, DestBmp: PFIBITMAP;
+begin
+  if not IsValid then Exit;
+
+  if (GetWidth <= ThumbSize) and (GetHeight <= ThumbSize) then
+  begin
+    DestBitmap.Assign(Self);
+    Exit;
+  end;
+
+  w := Width;
+  h := Height;
+
+  // prepare bitmaps
+  if GetBitsPerPixel <> 24 then
+    SrcBmp := FreeImage_ConvertTo24Bits(FDib)
+  else
+    SrcBmp := FDib;
+  DestBmp := FreeImage_Allocate(w, h, 24);
+  Assert(DestBmp <> nil, 'TFreeBitmap.MakeThumbnail error');
+
+{  iDst := (w * 24 + 31) and not 31;
+  iDst := iDst div 8; //BytesPerScanline
+  iSrc := (GetWidth * 24 + 31) and not 31;
+  iSrc := iSrc div 8;
+}
+  // BytesPerScanline
+  iDst := FreeImage_GetPitch(DestBmp);
+  iSrc := FreeImage_GetPitch(SrcBmp);
+
+  xscale := 1 / (w / FreeImage_GetWidth(SrcBmp));
+  yscale := 1 / (h / FreeImage_GetHeight(SrcBmp));
+
+  // X lookup table
+  SetLength(lutX, w);
+  x1 := 0;
+  x2 := trunc(xscale);
+  for x := 0 to w - 1 do
+  begin
+    lutX[x] := x2 - x1;
+    x1 := x2;
+    x2 := trunc((x + 2) * xscale);
+  end;
+
+  // Y lookup table
+  SetLength(lutY, h);
+  x1 := 0;
+  x2 := trunc(yscale);
+  for x := 0 to h - 1 do
+  begin
+    lutY[x] := x2 - x1;
+    x1 := x2;
+    x2 := trunc((x + 2) * yscale);
+  end;
+
+  Dec(w);
+  Dec(h);
+  RowDest := integer(FreeImage_GetScanLine(DestBmp, 0));
+  RowSourceStart := integer(FreeImage_GetScanLine(SrcBmp, 0));
+  RowSource := RowSourceStart;
+
+  for y := 0 to h do
+  // resampling
+  begin
+    dy := lutY[y];
+    x1 := 0;
+    x3 := 0;
+    for x := 0 to w do  // loop through row
+    begin
+      dx:= lutX[x];
+      iRed:= 0;
+      iGrn:= 0;
+      iBlu:= 0;
+      RowSource := RowSourceStart;
+      for iy := 1 to dy do
+      begin
+        pt := PRGB24(RowSource + x1);
+        for ix := 1 to dx do
+        begin
+          iRed := iRed + pt.R;
+          iGrn := iGrn + pt.G;
+          iBlu := iBlu + pt.B;
+          inc(pt);
+        end;
+        RowSource := RowSource + iSrc;
+      end;
+      iRatio := 65535 div (dx * dy);
+      pt1 := PRGB24(RowDest + x3);
+      pt1.R := (iRed * iRatio) shr 16;
+      pt1.G := (iGrn * iRatio) shr 16;
+      pt1.B := (iBlu * iRatio) shr 16;
+      x1 := x1 + 3 * dx;
+      inc(x3,3);
+    end;
+    RowDest := RowDest + iDst;
+    RowSourceStart := RowSource;
+  end; // resampling
+
+  if FreeImage_GetHeight(DestBmp) >= 3 then
+  // Sharpening...
+  begin
+    s1 := integer(FreeImage_GetScanLine(DestBmp, 0));
+    iDst := integer(FreeImage_GetScanLine(DestBmp, 1)) - s1;
+    ny1 := Integer(s1);
+    ny2 := ny1 + iDst;
+    ny3 := ny2 + iDst;
+    for y := 1 to FreeImage_GetHeight(DestBmp) - 2 do
+    begin
+      for x := 0 to FreeImage_GetWidth(DestBmp) - 3 do
+      begin
+        x1 := x * 3;
+        x2 := x1 + 3;
+        x3 := x1 + 6;
+
+        c1 := pRGB24(ny1 + x1)^;
+        c2 := pRGB24(ny1 + x3)^;
+        c3 := pRGB24(ny2 + x2)^;
+        c4 := pRGB24(ny3 + x1)^;
+        c5 := pRGB24(ny3 + x3)^;
+
+        r := (c1.R + c2.R + (c3.R * -12) + c4.R + c5.R) div -8;
+        g := (c1.G + c2.G + (c3.G * -12) + c4.G + c5.G) div -8;
+        b := (c1.B + c2.B + (c3.B * -12) + c4.B + c5.B) div -8;
+
+        if r < 0 then r := 0 else if r > 255 then r := 255;
+        if g < 0 then g := 0 else if g > 255 then g := 255;
+        if b < 0 then b := 0 else if b > 255 then b := 255;
+
+        pt1 := pRGB24(ny2 + x2);
+        pt1.R := r;
+        pt1.G := g;
+        pt1.B := b;
+      end;
+      inc(ny1, iDst);
+      inc(ny2, iDst);
+      inc(ny3, iDst);
+    end;
+  end; // sharpening
+
+  if SrcBmp <> FDib then
+    FreeImage_Unload(SrcBmp);
+  DestBitmap.Replace(DestBmp);
+end;
+
+function TFreeBitmap.PasteSubImage(Src: TFreeBitmap; Left, Top,
+  Alpha: Integer): Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Result := FreeImage_Paste(FDib, Src.Dib, Left, Top, Alpha);
+    Change;
+  end else
+    Result := False;
+end;
+
+function TFreeBitmap.Replace(NewDib: PFIBITMAP): Boolean;
+begin
+  Result := False;
+  if NewDib = nil then Exit;
+
+  if not DoChanging(FDib, NewDib) and IsValid then
+    FreeImage_Unload(FDib);
+
+  FDib := NewDib;
+  Result := True;
+  Change;
+end;
+
+function TFreeBitmap.Rescale(NewWidth, NewHeight: Integer;
+  Filter: FREE_IMAGE_FILTER; Dest: TFreeBitmap): Boolean;
+var
+  Bpp: Integer;
+  DstDib: PFIBITMAP;
+begin
+  Result := False;
+
+  if FDib <> nil then
+  begin
+    Bpp := FreeImage_GetBPP(FDib);
+
+    if Bpp < 8 then
+      if not ConvertToGrayscale then Exit
+    else
+    if Bpp = 16 then
+    // convert to 24-bit
+      if not ConvertTo24Bits then Exit;
+
+    // perform upsampling / downsampling
+    DstDib := FreeImage_Rescale(FDib, NewWidth, NewHeight, Filter);
+    if Dest = nil then
+      Result := Replace(DstDib)
+    else
+      Result := Dest.Replace(DstDib)
+  end
+end;
+
+function TFreeBitmap.Rotate(Angle: Double): Boolean;
+var
+  Bpp: Integer;
+  Rotated: PFIBITMAP;
+begin
+  Result := False;
+  if IsValid then
+  begin
+    Bpp := FreeImage_GetBPP(FDib);
+    if Bpp in [1, 8, 24, 32] then
+    begin
+      Rotated := FreeImage_RotateClassic(FDib, Angle);
+      Result := Replace(Rotated);
+    end
+  end;
+end;
+
+function TFreeBitmap.RotateEx(Angle, XShift, YShift, XOrigin,
+  YOrigin: Double; UseMask: Boolean): Boolean;
+var
+  Rotated: PFIBITMAP;
+begin
+  Result := False;
+  if FDib <> nil then
+  begin
+    if FreeImage_GetBPP(FDib) >= 8 then
+    begin
+      Rotated := FreeImage_RotateEx(FDib, Angle, XShift, YShift, XOrigin, YOrigin, UseMask);
+      Result := Replace(Rotated);
+    end
+  end;
+end;
+
+function TFreeBitmap.Save(const FileName: string; Flag: Integer): Boolean;
+var
+  fif: FREE_IMAGE_FORMAT;
+begin
+  Result := False;
+
+  // try to guess the file format from the file extension
+  fif := FreeImage_GetFIFFromFilename(PChar(Filename));
+  if CanSave(fif) then
+    Result := FreeImage_Save(fif, FDib, PChar(FileName), Flag);
+end;
+
+function TFreeBitmap.SaveToHandle(fif: FREE_IMAGE_FORMAT; IO: PFreeImageIO;
+  Handle: fi_handle; Flag: Integer): Boolean;
+begin
+  Result := False;
+  if CanSave(fif) then
+    Result := FreeImage_SaveToHandle(fif, FDib, IO, Handle, Flag)
+end;
+
+function TFreeBitmap.SaveToMemory(fif: FREE_IMAGE_FORMAT;
+  MemIO: TFreeMemoryIO; Flag: Integer): Boolean;
+begin
+  Result := False;
+
+  if CanSave(fif) then
+    Result := MemIO.Write(fif, FDib, Flag)
+end;
+
+function TFreeBitmap.SaveToStream(fif: FREE_IMAGE_FORMAT; Stream: TStream;
+  Flag: Integer): Boolean;
+var
+  MemIO: TFreeMemoryIO;
+  Data: PByte;
+  Size: Cardinal;
+begin
+  MemIO := TFreeMemoryIO.Create;
+  try
+    Result := SaveToMemory(fif, MemIO, Flag);
+    if Result then
+    begin
+      MemIO.Acquire(Data, Size);
+      Stream.WriteBuffer(Data^, Size);
+    end;
+  finally
+    MemIO.Free;
+  end;
+end;
+
+function TFreeBitmap.SaveU(const FileName: WideString;
+  Flag: Integer): Boolean;
+var
+  fif: FREE_IMAGE_FORMAT;
+begin
+  Result := False;
+
+  // try to guess the file format from the file extension
+  fif := FreeImage_GetFIFFromFilenameU(PWideChar(Filename));
+  if CanSave(fif) then
+    Result := FreeImage_SaveU(fif, FDib, PWideChar(FileName), Flag);
+end;
+
+function TFreeBitmap.SetChannel(Bitmap: TFreeBitmap;
+  Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+begin
+  if FDib <> nil then
+  begin
+    Result := FreeImage_SetChannel(FDib, Bitmap.FDib, Channel);
+    Change;
+  end
+  else
+    Result := False
+end;
+
+procedure TFreeBitmap.SetDib(Value: PFIBITMAP);
+begin
+  Replace(Value);
+end;
+
+function TFreeBitmap.SetFileBkColor(BkColor: PRGBQuad): Boolean;
+begin
+  Result := FreeImage_SetBackgroundColor(FDib, BkColor);
+  Change;
+end;
+
+procedure TFreeBitmap.SetHorizontalResolution(Value: Double);
+begin
+  if IsValid then
+  begin
+    FreeImage_SetDotsPerMeterX(FDib, Trunc(Value * 100 + 0.5));
+    Change;
+  end;
+end;
+
+function TFreeBitmap.SetMetadata(Model: FREE_IMAGE_MDMODEL;
+  const Key: string; Tag: TFreeTag): Boolean;
+begin
+  Result := FreeImage_SetMetadata(Model, FDib, PChar(Key), Tag.Tag);
+end;
+
+function TFreeBitmap.SetPixelColor(X, Y: Cardinal;
+  Value: PRGBQUAD): Boolean;
+begin
+  Result := FreeImage_SetPixelColor(FDib, X, Y, Value);
+  Change;
+end;
+
+function TFreeBitmap.SetPixelIndex(X, Y: Cardinal; Value: PByte): Boolean;
+begin
+  Result := FreeImage_SetPixelIndex(FDib, X, Y, Value);
+  Change;
+end;
+
+function TFreeBitmap.SetSize(ImageType: FREE_IMAGE_TYPE; Width, Height,
+  Bpp: Integer; RedMask, GreenMask, BlueMask: Cardinal): Boolean;
+var
+  Pal: PRGBQuad;
+  I: Cardinal;
+begin
+  Result := False;
+
+  if FDib <> nil then
+    FreeImage_Unload(FDib);
+
+  FDib := FreeImage_Allocate(Width, Height, Bpp, RedMask, GreenMask, BlueMask);
+  if FDib = nil then Exit;
+
+  if ImageType = FIT_BITMAP then
+  case Bpp of
+    1, 4, 8:
+    begin
+      Pal := FreeImage_GetPalette(FDib);
+      for I := 0 to FreeImage_GetColorsUsed(FDib) - 1 do
+      begin
+        Pal.rgbBlue := I;
+        Pal.rgbGreen := I;
+        Pal.rgbRed := I;
+        Inc(Pal, SizeOf(RGBQUAD));
+      end;
+    end;
+  end;
+
+  Result := True;
+  Change;
+end;
+
+procedure TFreeBitmap.SetTransparencyTable(Table: PByte; Count: Integer);
+begin
+  FreeImage_SetTransparencyTable(FDib, Table, Count);
+  Change;
+end;
+
+procedure TFreeBitmap.SetVerticalResolution(Value: Double);
+begin
+  if IsValid then
+  begin
+    FreeImage_SetDotsPerMeterY(FDib, Trunc(Value * 100 + 0.5));
+    Change;
+  end;
+end;
+
+function TFreeBitmap.SplitChannels(RedChannel, GreenChannel,
+  BlueChannel: TFreeBitmap): Boolean;
+begin
+  if FDib <> nil then
+  begin
+    RedChannel.FDib := FreeImage_GetChannel(FDib, FICC_RED);
+    GreenChannel.FDib := FreeImage_GetChannel(FDib, FICC_GREEN);
+    BlueChannel.FDib := FreeImage_GetChannel(FDib, FICC_BLUE);
+    Result := RedChannel.IsValid and GreenChannel.IsValid and BlueChannel.IsValid;
+  end
+  else
+    Result := False  
+end;
+
+function TFreeBitmap.Threshold(T: Byte): Boolean;
+var
+  dib1: PFIBITMAP;
+begin
+  if FDib <> nil then
+  begin
+    dib1 := FreeImage_Threshold(FDib, T);
+    Result := Replace(dib1);
+  end
+  else
+    Result := False
+end;
+
+function TFreeBitmap.ToneMapping(TMO: FREE_IMAGE_TMO; FirstParam,
+  SecondParam: Double): Boolean;
+var
+  NewDib: PFIBITMAP;
+begin
+  Result := False;
+  if not IsValid then Exit;
+
+  NewDib := FreeImage_ToneMapping(Fdib, TMO, FirstParam, SecondParam);
+  Result := Replace(NewDib);
+end;
+
+
+{ TFreeMultiBitmap }
+
+procedure TFreeMultiBitmap.AppendPage(Bitmap: TFreeBitmap);
+begin
+  if IsValid then
+    FreeImage_AppendPage(FMPage, Bitmap.FDib);
+end;
+
+function TFreeMultiBitmap.Close(Flags: Integer): Boolean;
+begin
+  Result := FreeImage_CloseMultiBitmap(FMPage, Flags);
+  FMPage := nil;
+end;
+
+constructor TFreeMultiBitmap.Create(KeepCacheInMemory: Boolean);
+begin
+  inherited Create;
+  FMemoryCache := KeepCacheInMemory;
+end;
+
+procedure TFreeMultiBitmap.DeletePage(Page: Integer);
+begin
+  if IsValid then
+    FreeImage_DeletePage(FMPage, Page);
+end;
+
+destructor TFreeMultiBitmap.Destroy;
+begin
+  if FMPage <> nil then Close;
+  inherited;
+end;
+
+function TFreeMultiBitmap.GetLockedPageNumbers(var Pages,
+  Count: Integer): Boolean;
+begin
+  Result := False;
+  if not IsValid then Exit;
+  Result := FreeImage_GetLockedPageNumbers(FMPage, Pages, Count)
+end;
+
+function TFreeMultiBitmap.GetPageCount: Integer;
+begin
+  Result := 0;
+  if IsValid then
+    Result := FreeImage_GetPageCount(FMPage)
+end;
+
+procedure TFreeMultiBitmap.InsertPage(Page: Integer; Bitmap: TFreeBitmap);
+begin
+  if IsValid then
+    FreeImage_InsertPage(FMPage, Page, Bitmap.FDib);
+end;
+
+function TFreeMultiBitmap.IsValid: Boolean;
+begin
+  Result := FMPage <> nil
+end;
+
+procedure TFreeMultiBitmap.LockPage(Page: Integer; DestBitmap: TFreeBitmap);
+begin
+  if not IsValid then Exit;
+
+  if Assigned(DestBitmap) then
+  begin
+    DestBitmap.Replace(FreeImage_LockPage(FMPage, Page));
+  end;
+end;
+
+function TFreeMultiBitmap.MovePage(Target, Source: Integer): Boolean;
+begin
+  Result := False;
+  if not IsValid then Exit;
+  Result := FreeImage_MovePage(FMPage, Target, Source);
+end;
+
+function TFreeMultiBitmap.Open(const FileName: string; CreateNew,
+  ReadOnly: Boolean; Flags: Integer): Boolean;
+var
+  fif: FREE_IMAGE_FORMAT;
+begin
+  Result := False;
+
+  // try to guess the file format from the filename
+  fif := FreeImage_GetFIFFromFilename(PChar(FileName));
+
+  // check for supported file types
+  if (fif <> FIF_UNKNOWN) and (not fif in [FIF_TIFF, FIF_ICO, FIF_GIF]) then
+    Exit;
+
+  // open the stream
+  FMPage := FreeImage_OpenMultiBitmap(fif, PChar(FileName), CreateNew, ReadOnly, FMemoryCache, Flags);
+
+  Result := FMPage <> nil;  
+end;
+
+procedure TFreeMultiBitmap.UnlockPage(Bitmap: TFreeBitmap;
+  Changed: Boolean);
+begin
+  if IsValid then
+  begin
+    FreeImage_UnlockPage(FMPage, Bitmap.FDib, Changed);
+    // clear the image so that it becomes invalid.
+    // don't use Bitmap.Clear method because it calls FreeImage_Unload
+    // just clear the pointer
+    Bitmap.FDib := nil;
+    Bitmap.Change;
+  end;
+end;
+
+{ TFreeMemoryIO }
+
+function TFreeMemoryIO.Acquire(var Data: PByte;
+  var SizeInBytes: DWORD): Boolean;
+begin
+  Result := FreeImage_AcquireMemory(FHMem, Data, SizeInBytes);
+end;
+
+constructor TFreeMemoryIO.Create(Data: PByte; SizeInBytes: DWORD);
+begin
+  inherited Create;
+  FHMem := FreeImage_OpenMemory(Data, SizeInBytes);
+end;
+
+destructor TFreeMemoryIO.Destroy;
+begin
+  FreeImage_CloseMemory(FHMem);
+  inherited;
+end;
+
+function TFreeMemoryIO.GetFileType: FREE_IMAGE_FORMAT;
+begin
+  Result := FreeImage_GetFileTypeFromMemory(FHMem);
+end;
+
+function TFreeMemoryIO.IsValid: Boolean;
+begin
+  Result := FHMem <> nil
+end;
+
+function TFreeMemoryIO.Read(fif: FREE_IMAGE_FORMAT;
+  Flag: Integer): PFIBITMAP;
+begin
+  Result := FreeImage_LoadFromMemory(fif, FHMem, Flag)
+end;
+
+function TFreeMemoryIO.Seek(Offset: Longint; Origin: Word): Boolean;
+begin
+  Result := FreeImage_SeekMemory(FHMem, Offset, Origin)
+end;
+
+function TFreeMemoryIO.Tell: Longint;
+begin
+  Result := FreeImage_TellMemory(FHMem)
+end;
+
+function TFreeMemoryIO.Write(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP;
+  Flag: Integer): Boolean;
+begin
+  Result := FreeImage_SaveToMemory(fif, dib, FHMem, Flag)
+end;
+
+{ TFreeTag }
+
+function TFreeTag.Clone: TFreeTag;
+var
+  CloneTag: PFITAG;
+begin
+  Result := nil;
+  if not IsValid then Exit;
+
+  CloneTag := FreeImage_CloneTag(FTag);
+  Result := TFreeTag.Create(CloneTag);
+end;
+
+constructor TFreeTag.Create(ATag: PFITAG);
+begin
+  inherited Create;
+
+  if ATag <> nil then
+    FTag := ATag
+  else
+    FTag := FreeImage_CreateTag;
+end;
+
+destructor TFreeTag.Destroy;
+begin
+  if IsValid then
+    FreeImage_DeleteTag(FTag);
+    
+  inherited;
+end;
+
+function TFreeTag.GetCount: Cardinal;
+begin
+  Result := 0;
+  if not IsValid then Exit;
+
+  Result := FreeImage_GetTagCount(FTag);
+end;
+
+function TFreeTag.GetDescription: string;
+begin
+  Result := '';
+  if not IsValid then Exit;
+
+  Result := FreeImage_GetTagDescription(FTag);
+end;
+
+function TFreeTag.GetID: Word;
+begin
+  Result := 0;
+  if not IsValid then Exit;
+
+  Result := FreeImage_GetTagID(FTag);
+end;
+
+function TFreeTag.GetKey: string;
+begin
+  Result := '';
+  if not IsValid then Exit;
+
+  Result := FreeImage_GetTagKey(FTag);
+end;
+
+function TFreeTag.GetLength: Cardinal;
+begin
+  Result := 0;
+  if not IsValid then Exit;
+
+  Result := FreeImage_GetTagLength(FTag);
+end;
+
+function TFreeTag.GetTagType: FREE_IMAGE_MDTYPE;
+begin
+  Result := FIDT_NOTYPE;
+  if not IsValid then Exit;
+
+  Result := FreeImage_GetTagType(FTag);
+end;
+
+function TFreeTag.GetValue: Pointer;
+begin
+  Result := nil;
+  if not IsValid then Exit;
+
+  Result := FreeImage_GetTagValue(FTag);
+end;
+
+function TFreeTag.IsValid: Boolean;
+begin
+  Result := FTag <> nil;
+end;
+
+procedure TFreeTag.SetCount(const Value: Cardinal);
+begin
+  if IsValid then
+    FreeImage_SetTagCount(FTag, Value);
+end;
+
+procedure TFreeTag.SetDescription(const Value: string);
+begin
+  if IsValid then
+    FreeImage_SetTagDescription(FTag, PChar(Value));
+end;
+
+procedure TFreeTag.SetID(const Value: Word);
+begin
+  if IsValid then
+    FreeImage_SetTagID(FTag, Value);
+end;
+
+procedure TFreeTag.SetKey(const Value: string);
+begin
+  if IsValid then
+    FreeImage_SetTagKey(FTag, PChar(Value));
+end;
+
+procedure TFreeTag.SetLength(const Value: Cardinal);
+begin
+  if IsValid then
+    FreeImage_SetTagLength(FTag, Value);
+end;
+
+procedure TFreeTag.SetTagType(const Value: FREE_IMAGE_MDTYPE);
+begin
+  if IsValid then
+    FreeImage_SetTagType(FTag, Value);
+end;
+
+procedure TFreeTag.SetValue(const Value: Pointer);
+begin
+  if IsValid then
+    FreeImage_SetTagValue(FTag, Value);
+end;
+
+function TFreeTag.ToString(Model: FREE_IMAGE_MDMODEL; Make: PChar): string;
+begin
+  Result := FreeImage_TagToString(Model, FTag, Make);
+end;
+
+end.
diff --git a/songmanagement/src/lib/FreeImage/FreeImage.pas b/songmanagement/src/lib/FreeImage/FreeImage.pas
new file mode 100644
index 00000000..69c0a0d1
--- /dev/null
+++ b/songmanagement/src/lib/FreeImage/FreeImage.pas
@@ -0,0 +1,771 @@
+unit FreeImage;
+
+{$I switches.inc}
+
+
+// ==========================================================
+// Delphi wrapper for FreeImage 3
+// 
+// Design and implementation by
+// - Simon Beavis
+// - Peter Bystr�m
+// - Anatoliy Pulyaevskiy (xvel84@rambler.ru)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+interface
+
+uses
+  {$IFDEF MSWINDOWS}
+  Windows,
+  {$ENDIF}
+  ctypes;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF MSWINDOWS}
+  {$DEFINE DLL_STDCALL}
+{$ELSE}
+  {$DEFINE DLL_CDECL}
+{$ENDIF}
+
+const
+{$IF Defined(MSWINDOWS)}
+  FIDLL = 'freeimage.dll';
+{$ELSEIF Defined(DARWIN)}
+  FIDLL = 'libfreeimage.dylib';
+{$ELSEIF Defined(UNIX)}
+  FIDLL = 'libfreeimage.so';
+{$IFEND}
+
+{$IFNDEF MSWINDOWS}
+type
+  // define portable types for 32-bit / 64-bit OS
+  BOOL  = cint32;
+  BYTE  = cuint8;
+  WORD  = cuint16;
+  DWORD = cuint32;
+  LONG  = cint32;
+{$ENDIF}
+
+// --------------------------------------------------------------------------
+// Bitmap types -------------------------------------------------------------
+// --------------------------------------------------------------------------
+
+type
+  FIBITMAP = record
+    data : Pointer;
+  end;
+  PFIBITMAP = ^FIBITMAP;
+
+  FIMULTIBITMAP = record
+    data : Pointer;
+  end;
+  PFIMULTIBITMAP = ^FIMULTIBITMAP;
+
+// --------------------------------------------------------------------------
+// Indexes for byte arrays, masks and shifts for treating pixels as words ---
+// These coincide with the order of RGBQUAD and RGBTRIPLE -------------------
+// Little Endian (x86 / MS Windows, Linux) : BGR(A) order -------------------
+// --------------------------------------------------------------------------
+
+const
+  FI_RGBA_RED         = 2;
+  FI_RGBA_GREEN       = 1;
+  FI_RGBA_BLUE        = 0;
+  FI_RGBA_ALPHA       = 3;
+  FI_RGBA_RED_MASK    = $00FF0000;
+  FI_RGBA_GREEN_MASK  = $0000FF00;
+  FI_RGBA_BLUE_MASK   = $000000FF;
+  FI_RGBA_ALPHA_MASK  = $FF000000;
+  FI_RGBA_RED_SHIFT   = 16;
+  FI_RGBA_GREEN_SHIFT = 8;
+  FI_RGBA_BLUE_SHIFT  = 0;
+  FI_RGBA_ALPHA_SHIFT = 24;
+
+// --------------------------------------------------------------------------
+// The 16bit macros only include masks and shifts, --------------------------
+// since each color element is not byte aligned -----------------------------
+// --------------------------------------------------------------------------
+
+const
+  FI16_555_RED_MASK     = $7C00;
+  FI16_555_GREEN_MASK   = $03E0;
+  FI16_555_BLUE_MASK    = $001F;
+  FI16_555_RED_SHIFT    = 10;
+  FI16_555_GREEN_SHIFT  = 5;
+  FI16_555_BLUE_SHIFT   = 0;
+  FI16_565_RED_MASK     = $F800;
+  FI16_565_GREEN_MASK   = $07E0;
+  FI16_565_BLUE_MASK    = $001F;
+  FI16_565_RED_SHIFT    = 11;
+  FI16_565_GREEN_SHIFT  = 5;
+  FI16_565_BLUE_SHIFT   = 0;
+
+// --------------------------------------------------------------------------
+// ICC profile support ------------------------------------------------------
+// --------------------------------------------------------------------------
+
+const
+  FIICC_DEFAULT = $0;
+  FIICC_COLOR_IS_CMYK   = $1;
+
+type
+  FIICCPROFILE = record
+    flags : WORD;   // info flag
+    size : DWORD;   // profile's size measured in bytes
+    data : Pointer; // points to a block of contiguous memory containing the profile
+  end;
+  PFIICCPROFILE = ^FIICCPROFILE;
+
+// --------------------------------------------------------------------------
+// Important enums ----------------------------------------------------------
+// --------------------------------------------------------------------------
+
+type
+  FREE_IMAGE_FORMAT         = cint;
+  FREE_IMAGE_TYPE           = cint;
+  FREE_IMAGE_COLOR_TYPE     = cint;
+  FREE_IMAGE_QUANTIZE       = cint;
+  FREE_IMAGE_DITHER         = cint;
+  FREE_IMAGE_FILTER         = cint;
+  FREE_IMAGE_COLOR_CHANNEL  = cint;
+  FREE_IMAGE_MDTYPE         = cint;
+  FREE_IMAGE_MDMODEL        = cint;
+  FREE_IMAGE_JPEG_OPERATION = cint;
+  FREE_IMAGE_TMO            = cint;
+
+const
+  // I/O image format identifiers.
+  FIF_UNKNOWN = FREE_IMAGE_FORMAT(-1);
+  FIF_BMP     = FREE_IMAGE_FORMAT(0);
+  FIF_ICO     = FREE_IMAGE_FORMAT(1);
+  FIF_JPEG    = FREE_IMAGE_FORMAT(2);
+  FIF_JNG     = FREE_IMAGE_FORMAT(3);
+  FIF_KOALA   = FREE_IMAGE_FORMAT(4);
+  FIF_LBM     = FREE_IMAGE_FORMAT(5);
+  FIF_IFF     = FIF_LBM;
+  FIF_MNG     = FREE_IMAGE_FORMAT(6);
+  FIF_PBM     = FREE_IMAGE_FORMAT(7);
+  FIF_PBMRAW  = FREE_IMAGE_FORMAT(8);
+  FIF_PCD     = FREE_IMAGE_FORMAT(9);
+  FIF_PCX     = FREE_IMAGE_FORMAT(10);
+  FIF_PGM     = FREE_IMAGE_FORMAT(11);
+  FIF_PGMRAW  = FREE_IMAGE_FORMAT(12);
+  FIF_PNG     = FREE_IMAGE_FORMAT(13);
+  FIF_PPM     = FREE_IMAGE_FORMAT(14);
+  FIF_PPMRAW  = FREE_IMAGE_FORMAT(15);
+  FIF_RAS     = FREE_IMAGE_FORMAT(16);
+  FIF_TARGA   = FREE_IMAGE_FORMAT(17);
+  FIF_TIFF    = FREE_IMAGE_FORMAT(18);
+  FIF_WBMP    = FREE_IMAGE_FORMAT(19);
+  FIF_PSD     = FREE_IMAGE_FORMAT(20);
+  FIF_CUT     = FREE_IMAGE_FORMAT(21);
+  FIF_XBM     = FREE_IMAGE_FORMAT(22);
+  FIF_XPM     = FREE_IMAGE_FORMAT(23);
+  FIF_DDS     = FREE_IMAGE_FORMAT(24);
+  FIF_GIF     = FREE_IMAGE_FORMAT(25);
+  FIF_HDR     = FREE_IMAGE_FORMAT(26);
+  FIF_FAXG3   = FREE_IMAGE_FORMAT(27);
+  FIF_SGI     = FREE_IMAGE_FORMAT(28);  
+
+  // Image type used in FreeImage.
+  FIT_UNKNOWN = FREE_IMAGE_TYPE(0);  // unknown type
+  FIT_BITMAP  = FREE_IMAGE_TYPE(1);  // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit
+  FIT_UINT16  = FREE_IMAGE_TYPE(2);  // array of unsigned short: unsigned 16-bit
+  FIT_INT16   = FREE_IMAGE_TYPE(3);  // array of short: signed 16-bit
+  FIT_UINT32  = FREE_IMAGE_TYPE(4);  // array of unsigned long: unsigned 32-bit
+  FIT_INT32   = FREE_IMAGE_TYPE(5);  // array of long: signed 32-bit
+  FIT_FLOAT   = FREE_IMAGE_TYPE(6);  // array of float: 32-bit IEEE floating point
+  FIT_DOUBLE  = FREE_IMAGE_TYPE(7);  // array of double: 64-bit IEEE floating point
+  FIT_COMPLEX = FREE_IMAGE_TYPE(8);  // array of FICOMPLEX: 2 x 64-bit IEEE floating point
+  FIT_RGB16   = FREE_IMAGE_TYPE(9);  // 48-bit RGB image: 3 x 16-bit
+  FIT_RGBA16  = FREE_IMAGE_TYPE(10); // 64-bit RGBA image: 4 x 16-bit
+  FIT_RGBF    = FREE_IMAGE_TYPE(11); // 96-bit RGB float image: 3 x 32-bit IEEE floating point
+  FIT_RGBAF   = FREE_IMAGE_TYPE(12); // 128-bit RGBA float image: 4 x 32-bit IEEE floating point
+
+  // Image color type used in FreeImage.
+  FIC_MINISWHITE = FREE_IMAGE_COLOR_TYPE(0); // min value is white
+  FIC_MINISBLACK = FREE_IMAGE_COLOR_TYPE(1); // min value is black
+  FIC_RGB        = FREE_IMAGE_COLOR_TYPE(2); // RGB color model
+  FIC_PALETTE    = FREE_IMAGE_COLOR_TYPE(3); // color map indexed
+  FIC_RGBALPHA   = FREE_IMAGE_COLOR_TYPE(4); // RGB color model with alpha channel
+  FIC_CMYK       = FREE_IMAGE_COLOR_TYPE(5); // CMYK color model
+
+  // Color quantization algorithms. Constants used in FreeImage_ColorQuantize.
+  FIQ_WUQUANT = FREE_IMAGE_QUANTIZE(0); // Xiaolin Wu color quantization algorithm
+  FIQ_NNQUANT = FREE_IMAGE_QUANTIZE(1); // NeuQuant neural-net quantization algorithm by Anthony Dekker
+
+  // Dithering algorithms. Constants used FreeImage_Dither.
+  FID_FS            = FREE_IMAGE_DITHER(0); // Floyd & Steinberg error diffusion
+  FID_BAYER4x4      = FREE_IMAGE_DITHER(1); // Bayer ordered dispersed dot dithering (order 2 dithering matrix)
+  FID_BAYER8x8      = FREE_IMAGE_DITHER(2); // Bayer ordered dispersed dot dithering (order 3 dithering matrix)
+  FID_CLUSTER6x6    = FREE_IMAGE_DITHER(3); // Ordered clustered dot dithering (order 3 - 6x6 matrix)
+  FID_CLUSTER8x8    = FREE_IMAGE_DITHER(4); // Ordered clustered dot dithering (order 4 - 8x8 matrix)
+  FID_CLUSTER16x16  = FREE_IMAGE_DITHER(5); // Ordered clustered dot dithering (order 8 - 16x16 matrix)
+
+  // Lossless JPEG transformations Constants used in FreeImage_JPEGTransform
+  FIJPEG_OP_NONE        = FREE_IMAGE_JPEG_OPERATION(0); // no transformation
+  FIJPEG_OP_FLIP_H      = FREE_IMAGE_JPEG_OPERATION(1); // horizontal flip
+  FIJPEG_OP_FLIP_V      = FREE_IMAGE_JPEG_OPERATION(2); // vertical flip
+  FIJPEG_OP_TRANSPOSE   = FREE_IMAGE_JPEG_OPERATION(3); // transpose across UL-to-LR axis
+  FIJPEG_OP_TRANSVERSE  = FREE_IMAGE_JPEG_OPERATION(4); // transpose across UR-to-LL axis
+  FIJPEG_OP_ROTATE_90   = FREE_IMAGE_JPEG_OPERATION(5); // 90-degree clockwise rotation
+  FIJPEG_OP_ROTATE_180  = FREE_IMAGE_JPEG_OPERATION(6); // 180-degree rotation
+  FIJPEG_OP_ROTATE_270  = FREE_IMAGE_JPEG_OPERATION(7); // 270-degree clockwise (or 90 ccw)
+
+  // Tone mapping operators. Constants used in FreeImage_ToneMapping.
+  FITMO_DRAGO03    = FREE_IMAGE_TMO(0); // Adaptive logarithmic mapping (F. Drago, 2003)
+  FITMO_REINHARD05 = FREE_IMAGE_TMO(1); // Dynamic range reduction inspired by photoreceptor physiology (E. Reinhard, 2005)
+
+  // Upsampling / downsampling filters. Constants used in FreeImage_Rescale.
+  FILTER_BOX        = FREE_IMAGE_FILTER(0); // Box, pulse, Fourier window, 1st order (constant) b-spline
+  FILTER_BICUBIC    = FREE_IMAGE_FILTER(1); // Mitchell & Netravali's two-param cubic filter
+  FILTER_BILINEAR   = FREE_IMAGE_FILTER(2); // Bilinear filter
+  FILTER_BSPLINE    = FREE_IMAGE_FILTER(3); // 4th order (cubic) b-spline
+  FILTER_CATMULLROM = FREE_IMAGE_FILTER(4); // Catmull-Rom spline, Overhauser spline
+  FILTER_LANCZOS3   = FREE_IMAGE_FILTER(5); // Lanczos3 filter
+
+  // Color channels. Constants used in color manipulation routines.
+  FICC_RGB   = FREE_IMAGE_COLOR_CHANNEL(0); // Use red, green and blue channels
+  FICC_RED   = FREE_IMAGE_COLOR_CHANNEL(1); // Use red channel
+  FICC_GREEN = FREE_IMAGE_COLOR_CHANNEL(2); // Use green channel
+  FICC_BLUE  = FREE_IMAGE_COLOR_CHANNEL(3); // Use blue channel
+  FICC_ALPHA = FREE_IMAGE_COLOR_CHANNEL(4); // Use alpha channel
+  FICC_BLACK = FREE_IMAGE_COLOR_CHANNEL(5); // Use black channel
+  FICC_REAL  = FREE_IMAGE_COLOR_CHANNEL(6); // Complex images: use real part
+  FICC_IMAG  = FREE_IMAGE_COLOR_CHANNEL(7); // Complex images: use imaginary part
+  FICC_MAG   = FREE_IMAGE_COLOR_CHANNEL(8); // Complex images: use magnitude
+  FICC_PHASE = FREE_IMAGE_COLOR_CHANNEL(9);     // Complex images: use phase
+
+  // Tag data type information (based on TIFF specifications)
+  FIDT_NOTYPE    = FREE_IMAGE_MDTYPE(0);  // placeholder
+  FIDT_BYTE      = FREE_IMAGE_MDTYPE(1);  // 8-bit unsigned integer
+  FIDT_ASCII     = FREE_IMAGE_MDTYPE(2);  // 8-bit bytes w/ last byte null
+  FIDT_SHORT     = FREE_IMAGE_MDTYPE(3);  // 16-bit unsigned integer
+  FIDT_LONG      = FREE_IMAGE_MDTYPE(4);  // 32-bit unsigned integer
+  FIDT_RATIONAL  = FREE_IMAGE_MDTYPE(5);  // 64-bit unsigned fraction
+  FIDT_SBYTE     = FREE_IMAGE_MDTYPE(6);  // 8-bit signed integer
+  FIDT_UNDEFINED = FREE_IMAGE_MDTYPE(7);  // 8-bit untyped data
+  FIDT_SSHORT    = FREE_IMAGE_MDTYPE(8);  // 16-bit signed integer
+  FIDT_SLONG     = FREE_IMAGE_MDTYPE(9);  // 32-bit signed integer
+  FIDT_SRATIONAL = FREE_IMAGE_MDTYPE(10); // 64-bit signed fraction
+  FIDT_FLOAT     = FREE_IMAGE_MDTYPE(11); // 32-bit IEEE floating point
+  FIDT_DOUBLE    = FREE_IMAGE_MDTYPE(12); // 64-bit IEEE floating point
+  FIDT_IFD       = FREE_IMAGE_MDTYPE(13); // 32-bit unsigned integer (offset)
+  FIDT_PALETTE   = FREE_IMAGE_MDTYPE(14); // 32-bit RGBQUAD
+
+  // Metadata models supported by FreeImage
+  FIMD_NODATA         = FREE_IMAGE_MDMODEL(-1);
+  FIMD_COMMENTS       = FREE_IMAGE_MDMODEL(0);  // single comment or keywords
+  FIMD_EXIF_MAIN      = FREE_IMAGE_MDMODEL(1);  // Exif-TIFF metadata
+  FIMD_EXIF_EXIF      = FREE_IMAGE_MDMODEL(2);  // Exif-specific metadata
+  FIMD_EXIF_GPS       = FREE_IMAGE_MDMODEL(3);  // Exif GPS metadata
+  FIMD_EXIF_MAKERNOTE = FREE_IMAGE_MDMODEL(4);  // Exif maker note metadata
+  FIMD_EXIF_INTEROP   = FREE_IMAGE_MDMODEL(5);  // Exif interoperability metadata
+  FIMD_IPTC           = FREE_IMAGE_MDMODEL(6);  // IPTC/NAA metadata
+  FIMD_XMP            = FREE_IMAGE_MDMODEL(7);  // Abobe XMP metadata
+  FIMD_GEOTIFF        = FREE_IMAGE_MDMODEL(8);  // GeoTIFF metadata (to be implemented)
+  FIMD_ANIMATION      = FREE_IMAGE_MDMODEL(9);  // Animation metadata
+  FIMD_CUSTOM         = FREE_IMAGE_MDMODEL(10); // Used to attach other metadata types to a dib
+
+//{$endif}
+
+type
+  // Handle to a metadata model
+  FIMETADATA = record
+    data: Pointer;
+  end;
+  PFIMETADATA = ^FIMETADATA;
+
+  // Handle to a metadata tag
+  FITAG = record
+    data: Pointer;
+  end;
+  PFITAG = ^FITAG;
+
+// --------------------------------------------------------------------------
+// File IO routines ---------------------------------------------------------
+// --------------------------------------------------------------------------
+
+type
+  FI_Handle = Pointer;
+
+  FI_ReadProc = function(buffer : pointer; size : cuint; count : cuint; handle : fi_handle) : cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_WriteProc = function(buffer : pointer; size, count : cuint; handle : FI_Handle) : cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_SeekProc = function(handle : fi_handle; offset : clong; origin : cint) : cint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_TellProc = function(handle : fi_handle) : clong; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+
+  FreeImageIO = packed record
+    read_proc : FI_ReadProc;     // pointer to the function used to read data
+    write_proc: FI_WriteProc;    // pointer to the function used to write data
+    seek_proc : FI_SeekProc;     // pointer to the function used to seek
+    tell_proc : FI_TellProc;     // pointer to the function used to aquire the current position
+  end;
+  PFreeImageIO = ^FreeImageIO;
+
+  // Handle to a memory I/O stream
+  FIMEMORY = record
+    data: Pointer;
+  end;
+  PFIMEMORY = ^FIMEMORY;
+
+const
+  // constants used in FreeImage_Seek for Origin parameter
+  SEEK_SET = 0;
+  SEEK_CUR = 1;
+  SEEK_END = 2;
+
+// --------------------------------------------------------------------------
+// Plugin routines ----------------------------------------------------------
+// --------------------------------------------------------------------------
+
+type
+  PPluginStruct = ^PluginStruct;
+
+  FI_InitProc = procedure(Plugin: PPluginStruct; Format_ID: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_FormatProc = function: PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_DescriptionProc = function: PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_ExtensionListProc = function: PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_RegExprProc = function: PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_OpenProc = function(IO: PFreeImageIO; Handle: FI_Handle; Read: BOOL): Pointer; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_CloseProc = procedure(IO: PFreeImageIO; Handle: FI_Handle; Data: Pointer); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_PageCountProc = function(IO: PFreeImageIO; Handle: FI_Handle; Data: Pointer): cint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_PageCapabilityProc = function(IO: PFreeImageIO; Handle: FI_Handle; Data: Pointer): cint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_LoadProc = function(IO: PFreeImageIO; Handle: FI_Handle; Page, Flags: cint; data: pointer): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_SaveProc = function(IO: PFreeImageIO; Dib: PFIBITMAP; Handle: FI_Handle; Page, Flags: cint; Data: Pointer): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_ValidateProc = function(IO: PFreeImageIO; Handle: FI_Handle): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_MimeProc = function: PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_SupportsExportBPPProc = function(Bpp: cint): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_SupportsExportTypeProc = function(AType: FREE_IMAGE_TYPE): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+  FI_SupportsICCProfilesProc = function: BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+
+  PluginStruct = record
+    format_proc: FI_FormatProc;
+    description_proc: FI_DescriptionProc;
+    extension_proc: FI_ExtensionListProc;
+    regexpr_proc: FI_RegExprProc;
+    open_proc: FI_OpenProc;
+    close_proc: FI_CloseProc;
+    pagecount_proc: FI_PageCountProc;
+    pagecapability_proc: FI_PageCapabilityProc;
+    load_proc: FI_LoadProc;
+    save_proc: FI_SaveProc;
+    validate_proc: FI_ValidateProc;
+    mime_proc: FI_MimeProc;
+    supports_export_bpp_proc: FI_SupportsExportBPPProc;
+    supports_export_type_proc: FI_SupportsExportTypeProc;
+    supports_icc_profiles_proc: FI_SupportsICCProfilesProc;
+  end;
+
+// --------------------------------------------------------------------------
+// Load/Save flag constants -------------------------------------------------
+// --------------------------------------------------------------------------
+
+const
+  BMP_DEFAULT         = 0;
+  BMP_SAVE_RLE        = 1;
+  CUT_DEFAULT         = 0;
+  DDS_DEFAULT         = 0;
+  FAXG3_DEFAULT       = 0;
+  GIF_DEFAULT         = 0;
+  ICO_DEFAULT         = 0;
+  ICO_MAKEALPHA       = 0;     // convert to 32bpp and create an alpha channel from the AND-mask when loading
+  IFF_DEFAULT         = 0;
+  JPEG_DEFAULT        = 0;
+  JPEG_FAST           = 1;
+  JPEG_ACCURATE       = 2;
+  JPEG_QUALITYSUPERB  = $0080;
+  JPEG_QUALITYGOOD    = $0100;
+  JPEG_QUALITYNORMAL  = $0200;
+  JPEG_QUALITYAVERAGE = $0400;
+  JPEG_QUALITYBAD     = $0800;
+  JPEG_CMYK           = $1000; // load separated CMYK "as is" (use | to combine with other flags)
+  KOALA_DEFAULT       = 0;
+  LBM_DEFAULT         = 0;
+  MNG_DEFAULT         = 0;
+  PCD_DEFAULT         = 0;
+  PCD_BASE            = 1;     // load the bitmap sized 768 x 512
+  PCD_BASEDIV4        = 2;     // load the bitmap sized 384 x 256
+  PCD_BASEDIV16       = 3;     // load the bitmap sized 192 x 128
+  PCX_DEFAULT         = 0;
+  PNG_DEFAULT         = 0;
+  PNG_IGNOREGAMMA     = 1;     // avoid gamma correction
+  PNM_DEFAULT         = 0;
+  PNM_SAVE_RAW        = 0;     // If set the writer saves in RAW format (i.e. P4, P5 or P6)
+  PNM_SAVE_ASCII      = 1;     // If set the writer saves in ASCII format (i.e. P1, P2 or P3)
+  PSD_DEFAULT         = 0;
+  RAS_DEFAULT         = 0;
+  SGI_DEFAULT         = 0;
+  TARGA_DEFAULT       = 0;
+  TARGA_LOAD_RGB888   = 1;     // If set the loader converts RGB555 and ARGB8888 -> RGB888.
+  TIFF_DEFAULT        = 0;
+  TIFF_CMYK           = $0001; // reads/stores tags for separated CMYK (use | to combine with compression flags)
+  TIFF_PACKBITS       = $0100; // save using PACKBITS compression
+  TIFF_DEFLATE        = $0200; // save using DEFLATE compression
+  TIFF_ADOBE_DEFLATE  = $0400; // save using ADOBE DEFLATE compression
+  TIFF_NONE           = $0800; // save without any compression
+  TIFF_CCITTFAX       = $1000; // save using CCITT Group 3 fax encoding
+  TIFF_CCITTFAX4      = $2000; // save using CCITT Group 4 fax encoding
+  TIFF_LZW            = $4000; // save using LZW compression
+  TIFF_JPEG           = $8000; // save using JPEG compression
+  WBMP_DEFAULT        = 0;
+  XBM_DEFAULT         = 0;
+  XPM_DEFAULT         = 0;
+
+// --------------------------------------------------------------------------
+// Init/Error routines ------------------------------------------------------
+// --------------------------------------------------------------------------
+
+procedure FreeImage_Initialise(load_local_plugins_only : BOOL = False); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_DeInitialise; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Version routines ---------------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetVersion : PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetCopyrightMessage : PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Message output functions -------------------------------------------------
+// --------------------------------------------------------------------------
+
+procedure FreeImage_OutPutMessageProc(fif: cint; fmt: PChar); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+type FreeImage_OutputMessageFunction = function(fif: FREE_IMAGE_FORMAT; msg: PChar): pointer; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF}
+procedure FreeImage_SetOutputMessage(omf: FreeImage_OutputMessageFunction); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Allocate/Unload routines -------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_Allocate(width, height, bpp: cint; red_mask: cuint = 0; green_mask: cuint = 0; blue_mask: cuint = 0): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_AllocateT(Atype: FREE_IMAGE_TYPE; Width, Height: cint; bpp: cint = 8; red_mask: cuint = 0; green_mask: cuint = 0; blue_mask: cuint = 0): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_Clone(dib: PFIBITMAP): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_Unload(dib: PFIBITMAP); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Load / Save routines -----------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_Load(fif: FREE_IMAGE_FORMAT; const filename: PChar; flags: cint = 0): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_LoadU(fif: FREE_IMAGE_FORMAT; const filename: PWideChar; flags: cint = 0): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_LoadFromHandle(fif: FREE_IMAGE_FORMAT; io: PFreeImageIO; handle: fi_handle; flags: cint = 0): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_Save(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; filename: PChar; flags: cint = 0): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SaveU(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; const filename: PWideChar; flags: cint = 0): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SaveToHandle(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; io : PFreeImageIO; handle : fi_handle; flags : cint = 0) : BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Memory I/O stream routines -----------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_OpenMemory(data: PByte = nil; size_in_bytes: DWORD = 0): PFIMEMORY; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_CloseMemory(stream: PFIMEMORY); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_LoadFromMemory(fif: FREE_IMAGE_FORMAT; stream: PFIMEMORY; flags: cint = 0): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SaveToMemory(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; stream: PFIMEMORY; flags: cint = 0): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_TellMemory(stream: PFIMEMORY): clong; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SeekMemory(stream: PFIMEMORY; offset: clong; origin: cint): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_AcquireMemory(stream: PFIMEMORY; var data: PByte; var size_in_bytes: DWORD): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Plugin Interface ---------------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_RegisterLocalPlugin(proc_address: FI_InitProc; format, description, extension, regexpr: PChar): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_RegisterExternalPlugin(path, format, description, extension, regexpr: PChar): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFIFCount: cint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_SetPluginEnabled(fif: FREE_IMAGE_FORMAT; enable: BOOL); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_IsPluginEnabled(fif: FREE_IMAGE_FORMAT): cint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFIFFromFormat(const format: PChar): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFIFFromMime(const format: PChar): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFormatFromFIF(fif: FREE_IMAGE_FORMAT): PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFIFExtensionList(fif: FREE_IMAGE_FORMAT): PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFIFDescription(fif: FREE_IMAGE_FORMAT): PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFIFRegExpr(fif: FREE_IMAGE_FORMAT): PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFIFFromFilename(const fname: PChar): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFIFFromFilenameU(const fname:PWideChar): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_FIFSupportsReading(fif: FREE_IMAGE_FORMAT): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_FIFSupportsWriting(fif: FREE_IMAGE_FORMAT): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_FIFSupportsExportBPP(fif: FREE_IMAGE_FORMAT; bpp: cint): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_FIFSupportsICCProfiles(fif: FREE_IMAGE_FORMAT): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_FIFSupportsExportType(fif: FREE_IMAGE_FORMAT; image_type: FREE_IMAGE_TYPE): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Multipaging interface ----------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_OpenMultiBitmap(fif: FREE_IMAGE_FORMAT; filename: PChar; create_new, read_only, keep_cache_in_memory: BOOL; flags: cint = 0): PFIMULTIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_CloseMultiBitmap(bitmap: PFIMULTIBITMAP; flags: cint = 0): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetPageCount(bitmap: PFIMULTIBITMAP): cint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_AppendPage(bitmap: PFIMULTIBITMAP; data: PFIBITMAP); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_InsertPage(bitmap: PFIMULTIBITMAP; page: cint; data: PFIBITMAP); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_DeletePage(bitmap: PFIMULTIBITMAP; page: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_LockPage(bitmap: PFIMULTIBITMAP; page: cint): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_UnlockPage(bitmap: PFIMULTIBITMAP; page: PFIBITMAP; changed: BOOL); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_MovePage(bitmap: PFIMULTIBITMAP; target, source: cint): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetLockedPageNumbers(bitmap: PFIMULTIBITMAP; var pages: cint; var count : cint): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Filetype request routines ------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetFileType(const filename: PChar; size: cint): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFileTypeU(const filename: PWideChar; size: cint): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFileTypeFromHandle(io: PFreeImageIO; handle: FI_Handle; size: cint = 0): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetFileTypeFromMemory(stream: PFIMEMORY; size: cint = 0): FREE_IMAGE_FORMAT; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL; 
+
+// --------------------------------------------------------------------------
+// ImageType request routine ------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetImageType(dib: PFIBITMAP): FREE_IMAGE_TYPE; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// FreeImage helper routines ------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_IsLittleEndian: BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_LookupX11Color(const szColor: PChar; var nRed, nGreen, nBlue: PByte): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_LookupSVGColor(const szColor: PChar; var nRed, nGreen, nBlue: PByte): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Pixels access routines ---------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetBits(dib: PFIBITMAP): PByte; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetScanLine(dib: PFIBITMAP; scanline: cint): PByte; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_GetPixelIndex(dib: PFIBITMAP; X, Y: cuint; Value: PByte): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetPixelColor(dib: PFIBITMAP; X, Y: cuint; Value: PRGBQuad): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetPixelIndex(dib: PFIBITMAP; X, Y: cuint; Value: PByte): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetPixelColor(dib: PFIBITMAP; X, Y: cuint; Value: PRGBQuad): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// DIB info routines --------------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetColorsUsed(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetBPP(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetWidth(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetHeight(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetLine(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetPitch(dib : PFIBITMAP) : cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetDIBSize(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetPalette(dib: PFIBITMAP): PRGBQUAD; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_GetDotsPerMeterX(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetDotsPerMeterY(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_SetDotsPerMeterX(dib: PFIBITMAP; res: cuint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_SetDotsPerMeterY(dib: PFIBITMAP; res: cuint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_GetInfoHeader(dib: PFIBITMAP): PBITMAPINFOHEADER; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetInfo(var dib: FIBITMAP): PBITMAPINFO; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetColorType(dib: PFIBITMAP): FREE_IMAGE_COLOR_TYPE; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_GetRedMask(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetGreenMask(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetBlueMask(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_GetTransparencyCount(dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetTransparencyTable(dib: PFIBITMAP): PByte; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_SetTransparent(dib: PFIBITMAP; enabled: BOOL); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_SetTransparencyTable(dib: PFIBITMAP; table: PByte; count: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_IsTransparent(dib: PFIBITMAP): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_HasBackgroundColor(dib: PFIBITMAP): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetBackgroundColor(dib: PFIBITMAP; var bkcolor: PRGBQUAD): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetBackgroundColor(dib: PFIBITMAP; bkcolor: PRGBQUAD): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// ICC profile routines -----------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetICCProfile(var dib: FIBITMAP): PFIICCPROFILE; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_CreateICCProfile(var dib: FIBITMAP; data: Pointer; size: clong): PFIICCPROFILE; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_DestroyICCProfile(var dib : FIBITMAP); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Line conversion routines -------------------------------------------------
+// --------------------------------------------------------------------------
+
+procedure FreeImage_ConvertLine1To4(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine8To4(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQuad);  {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16To4_555(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16To4_565(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine24To4(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine32To4(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+procedure FreeImage_ConvertLine1To8(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine4To8(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16To8_555(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16To8_565(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine24To8(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine32To8(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+procedure FreeImage_ConvertLine1To16_555(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine4To16_555(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine8To16_555(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16_565_To16_555(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine24To16_555(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine32To16_555(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+procedure FreeImage_ConvertLine1To16_565(target, source : PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine4To16_565(target, source : PBYTE; width_in_pixels : cint; palette : PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine8To16_565(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16_555_To16_565(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine24To16_565(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine32To16_565(target, source : PBYTE; width_in_pixels : cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+procedure FreeImage_ConvertLine1To24(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine4To24(target, source : PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine8To24(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16To24_555(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16To24_565(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine32To24(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+procedure FreeImage_ConvertLine1To32(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine4To32(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine8To32(target, source: PBYTE; width_in_pixels: cint; palette: PRGBQUAD); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16To32_555(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine16To32_565(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertLine24To32(target, source: PBYTE; width_in_pixels: cint); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Smart conversion routines ------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_ConvertTo4Bits(dib: PFIBITMAP): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ConvertTo8Bits(dib: PFIBITMAP): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ConvertToGreyscale(dib: PFIBITMAP): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ConvertTo16Bits555(dib: PFIBITMAP): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ConvertTo16Bits565(dib: PFIBITMAP): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ConvertTo24Bits(dib: PFIBITMAP): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ConvertTo32Bits(dib: PFIBITMAP): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ColorQuantize(dib: PFIBITMAP; quantize: FREE_IMAGE_QUANTIZE): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ColorQuantizeEx(dib: PFIBITMAP; quantize: FREE_IMAGE_QUANTIZE = FIQ_WUQUANT; PaletteSize: cint = 256; ReserveSize: cint = 0; ReservePalette: PRGBQuad = nil): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_Threshold(dib: PFIBITMAP; T: Byte): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_Dither(dib: PFIBITMAP; algorithm: FREE_IMAGE_DITHER): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_ConvertFromRawBits(bits: PBYTE; width, height, pitch: cint; bpp, red_mask, green_mask, blue_mask: cuint; topdown: BOOL): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_ConvertToRawBits(bits: PBYTE; dib: PFIBITMAP; pitch: cint; bpp, red_mask, green_mask, blue_mask: cuint; topdown: BOOL); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_ConvertToRGBF(dib: PFIBITMAP): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_ConvertToStandardType(src: PFIBITMAP; scale_linear: BOOL = True): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ConvertToType(src: PFIBITMAP; dst_type: FREE_IMAGE_TYPE; scale_linear: BOOL = True): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// tone mapping operators
+function FreeImage_ToneMapping(dib: PFIBITMAP; tmo: FREE_IMAGE_TMO; first_param: cdouble = 0; second_param: cdouble = 0): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_TmoDrago03(src: PFIBITMAP; gamma: cdouble = 2.2; exposure: cdouble = 0): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_TmoReinhard05(src: PFIBITMAP; intensity: cdouble = 0; contrast: cdouble = 0): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// ZLib interface -----------------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_ZLibCompress(target: PBYTE; target_size: DWORD; source: PBYTE; source_size: DWORD): DWORD; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ZLibUncompress(target: PBYTE; target_size: DWORD; source: PBYTE; source_size: DWORD): DWORD; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_ZLibGZip(target: PBYTE; target_size: DWORD; source: PBYTE; source_size: DWORD): DWORD; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ZLibGUnzip(target: PBYTE; target_size: DWORD; source: PBYTE; source_size: DWORD): DWORD; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_ZLibCRC32(crc: DWORD; source: PByte; source_size: DWORD): DWORD; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Metadata routines --------------------------------------------------------
+// --------------------------------------------------------------------------
+
+// tag creation / destruction
+function FreeImage_CreateTag: PFITAG; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_DeleteTag(tag: PFITAG); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_CloneTag(tag: PFITAG): PFITAG; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// tag getters and setters
+function FreeImage_GetTagKey(tag: PFITAG): PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetTagDescription(tag: PFITAG): PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetTagID(tag: PFITAG): Word; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetTagType(tag: PFITAG): FREE_IMAGE_MDTYPE; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetTagCount(tag: PFITAG): DWORD; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetTagLength(tag: PFITAG): DWORD; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetTagValue(tag: PFITAG): Pointer; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+function FreeImage_SetTagKey(tag: PFITAG; const key: PChar): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetTagDescription(tag: PFITAG; const description: PChar): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetTagID(tag: PFITAG; id: Word): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetTagType(tag: PFITAG; atype: FREE_IMAGE_MDTYPE): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetTagCount(tag: PFITAG; count: DWORD): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetTagLength(tag: PFITAG; length: DWORD): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetTagValue(tag: PFITAG; const value: Pointer): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// iterator
+function FreeImage_FindFirstMetadata(model: FREE_IMAGE_MDMODEL; dib: PFIBITMAP; var tag: PFITAG): PFIMETADATA; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_FindNextMetadata(mdhandle: PFIMETADATA; var tag: PFITAG): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+procedure FreeImage_FindCloseMetadata(mdhandle: PFIMETADATA); {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// metadata setter and getter
+function FreeImage_SetMetadata(model: FREE_IMAGE_MDMODEL; dib: PFIBITMAP; const key: PChar; tag: PFITAG): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetMetadata(model: FREE_IMAGE_MDMODEL; dib: PFIBITMAP; const key: PChar; var tag: PFITAG): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// helpers
+function FreeImage_GetMetadataCount(model: FREE_IMAGE_MDMODEL; dib: PFIBITMAP): cuint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// tag to C string conversion
+function FreeImage_TagToString(model: FREE_IMAGE_MDMODEL; tag: PFITAG; Make: PChar = nil): PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// --------------------------------------------------------------------------
+// Image manipulation toolkit -----------------------------------------------
+// --------------------------------------------------------------------------
+
+// rotation and flipping
+function FreeImage_RotateClassic(dib: PFIBITMAP; angle: cdouble): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_RotateEx(dib: PFIBITMAP; angle, x_shift, y_shift, x_origin, y_origin: cdouble; use_mask: BOOL): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_FlipHorizontal(dib: PFIBITMAP): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_FlipVertical(dib: PFIBITMAP): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_JPEGTransform(const src_file: PChar; const dst_file: PChar; operation: FREE_IMAGE_JPEG_OPERATION; perfect: BOOL = False): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// upsampling / downsampling
+function FreeImage_Rescale(dib: PFIBITMAP; dst_width, dst_height: cint; filter: FREE_IMAGE_FILTER): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_MakeThumbnail(dib: PFIBITMAP; max_pixel_size: cint; convert:BOOL = TRUE): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// color manipulation routines (point operations)
+function FreeImage_AdjustCurve(dib: PFIBITMAP; LUT: PBYTE; channel: FREE_IMAGE_COLOR_CHANNEL): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_AdjustGamma(dib: PFIBITMAP; gamma: cdouble): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_AdjustBrightness(dib: PFIBITMAP; percentage: cdouble): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_AdjustContrast(dib: PFIBITMAP; percentage: cdouble): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_Invert(dib: PFIBITMAP): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetHistogram(dib: PFIBITMAP; histo: PDWORD; channel: FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// channel processing routines
+function FreeImage_GetChannel(dib: PFIBITMAP; channel: FREE_IMAGE_COLOR_CHANNEL): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetChannel(dib, dib8: PFIBITMAP; channel: FREE_IMAGE_COLOR_CHANNEL): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_GetComplexChannel(src: PFIBITMAP; channel: FREE_IMAGE_COLOR_CHANNEL): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_SetComplexChannel(src: PFIBITMAP; channel: FREE_IMAGE_COLOR_CHANNEL): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+
+// copy / paste / composite routines
+
+function FreeImage_Copy(dib: PFIBITMAP; left, top, right, bottom: cint): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_Paste(dst, src: PFIBITMAP; left, top, alpha: cint): BOOL; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+function FreeImage_Composite(fg: PFIBITMAP; useFileBkg: BOOL = False; appBkColor: PRGBQUAD = nil; bg: PFIBITMAP = nil): PFIBITMAP; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external FIDLL;
+  
+{$MINENUMSIZE 1}
+implementation
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/JEDI-SDL-README.txt b/songmanagement/src/lib/JEDI-SDL/JEDI-SDL-README.txt
new file mode 100644
index 00000000..8e0d25f9
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/JEDI-SDL-README.txt
@@ -0,0 +1,244 @@
+This is the based on the SDL ( http://www.libsdl.org ) headers, and has been converted, comments and all, to the Pascal unit called sdl.pas.
+Other conversions that have also been done are SDL_Mixer.h, SDL_Net.h, SDL_Image.h, SDL_ttf, SMPEG.h, SDL_sound and the SFont library, 
+which are all included in this distribution.
+
+It allows you to access all the functions within the SDL libraries under Windows, Linux and FreeBSD, so you can write cross-platform games or multimedia applications.
+
+Installation Instructions
+-------------------------
+Windows - We now have a semi-automated setup under Windows ( thanks to David House and the Jedi JCL team ). 
+           Once you have extracted the zip file, simply double click on the "JEDISDLWin32Installer.exe" to have the correct paths added to your respective 
+           IDEs. All IDEs from Delphi 4 - 7 are supported and it also adds a link to the .CHM help file under the Tools menu.
+
+Linux - Alternatively if you use Linux or want to to manually install the paths, then make sure you read the "Getting Started.html" file ( ideal for those who are new to JEDI-SDL ) and is now included as a guide to help getting everything setup for smooth compilation.
+
+Also included is a guide of how to use Sourceforge using TortoiseCVS under Windows ( Linux guide is under development ).
+Both documents can be found in the "documentation" directory.
+
+
+Release History
+---------------
+1.0  :   Yeah!! The Official v1.0 Release of JEDI-SDL!!
+           JEDI-SDL now updated to SDL v1.2.11, SDL_Image v1.2.5, SDL_Mixer v1.2.7, SDL_Net v1.2.6 & SDL_ttf v2.0.8
+           Added Improved FreePascal, TMT Pascal and GnuPascal support as well as maintaining Delphi/Kylix support.
+           Fixed Various bugs as pointed out on the JEDI-SDL mailing list.
+           Added SDL_GL_STEREO, SDL_GL_MULTISAMPLEBUFFERS, SDL_GL_MULTISAMPLESAMPLES
+
+Now works on MacOS X and a MacOS X disk image is available for download.
+
+// DLL/Shared object functions
+function SDL_LoadObject( const sofile : PChar ) : Pointer;
+
+function SDL_LoadFunction( handle : Pointer; const name : PChar ) : Pointer;
+
+procedure SDL_UnloadObject( handle : Pointer );
+
+//Added function to create RWops from const memory: SDL_RWFromConstMem()
+function SDL_RWFromConstMem(const mem: Pointer; size: Integer) : PSDL_RWops;
+
+//Added support for environment variables SDL_VIDEO_WINDOW_POS and SDL_VIDEO_CENTERED on Windows
+
+           New Units :
+           -----------
+           sdl_cpuinfo.pas - ported SDL_cpuinfo.h so Now you can test for Specific CPU types.
+           sdlinput.pas    - Input wrapper class
+           sdlwindow.pas   - Window wrapper class
+           sdltruetypefont.pas - True Type Font wrapper class
+           tcputils.pas - SDL_Net utility functions
+           sdlweb.pas - SDL_Net Web class
+           sdlwebhttp.pas - SDL_Net http protocol wrapper class
+           sdlwebftp.pas - SDL_Net ftp protocol wrapper class
+
+           New 2D Demos :
+           --------------
+
+
+           New 3D Demos :
+           --------------
+
+
+           Other New Stuff :
+           -----------------
+
+
+
+0.5  :   The JEDI-SDL project is now also set up on Sourceforge ( http://sf.net/projects/jedi-sdl/ ) so the latest code is available from there.
+           Improved FreePascal support has been added.
+           Various bug fixes as pointed out on the JEDI-SDL mailing list.
+           SDL_Mixer has been updated to version 1.2.1 and includes an Effects API.
+           Demo directories are now split into 2D and 3D related sub-directories.
+           There are now both Kylix ( K prefix )  and Delphi ( D prefix ) project groups for all the demos. 
+           They can be found in Demos and the 2D and 3D directories.
+
+           New Units
+           ---------
+           SDLStreams.pas - Chris Bruner has created a wrapper that uses Streams to load BMPs
+           SDLUtils.pas - Pascal only version of some Utility functions
+           SDLi386Utils.pas - Intel Assembler versions of the SDLUtils.pas functions.
+           SDL_ttf.pas - Port of the SDL True Type font support unit.
+           SDL_Sound.pas - Port of the SDL Sound library ( untested ).
+
+           New 2D Demos :
+           --------------
+           Pan and Zoom Demo - How to Pan and Zoom an SDL surface.
+           Isometric Demo - I ported my old DelphiX isometric demo over to SDL.
+           TestTimer demo - Shows hows how to use AddTimer and RemoveTimer.
+           MpegPlayer - I have updated and improved Anders Ohlsson's CLX MPegPlayer and component and it now works 
+           and installs into D4, D5, D6, D7, K1, K2 & K3.
+           Showfont - Demo to show how to us SDL_ttf.dll
+           SmpegPlayer - is a console MPEG player that use smpeg and SDL_Mixer
+
+           New 3D Demos :
+           --------------
+           DeathTruckTion 1.1 - A slightly updated version of this fully functional 3D network game.
+           TerrainDemo - Terrain demo ported from the book "OpenGL Game programming" by Hawkins and Astle.
+           TestGL - the standard SDL/OpenGL Test demo. Shows how to mix 2D and 3D rendering using OpenGL.
+           glfont - Demo to show how to us SDL_ttf with OpenGL. 
+           Particle Engine - Ariel's OpenGL Particle Engine.
+           Picking - Phil Freeman's Picking Demo
+           Motion Blur - Phil Freeman's Motion Blur Demo
+           Dynamic Light - Phil Freeman's Dynamic Light Demo
+           Environment Map - Phil Freeman's Environment Map Demo
+           GLMovie - is an MPEG Player that uses OpenGL to render the movie.
+           NeHe - Quite a few more NeHe demos are now included.
+
+           New Network Demos :
+           -------------------
+           There are now 3 SDL_Net Server demos and 4 SDL_Client demos as submitted by Dean Ellis.
+
+
+Beta 4 : The JEDI-SDL home page is now located @ http://www.delphi-jedi.org/Jedi:TEAM_SDL_HOME
+         All Demos ( including OpenGL Demos ) now compile under both Kylix and Delphi.
+         I have added quite a few more OpenGL examples, we are now up to Nehe tutorial 12.
+         All OpenGL demos also show how to handle Window resizing. 
+         Included an OpenGL demo called Puntos by Gustavo Maximo.
+         Ported Jan Horn's OpenGL MetaBalls and also SkyBox demo to SDL.
+         Ported Ilkka Tuomioja's OpenGL Quake 2 Model Viewer/Animator to SDL. 
+         NOTE : All OpenGL demos require OpenGL12.pas which can be found at...
+         http://www.lischke-online.de/Graphics.html#OpenGL12
+         I also fixed a conversion bug to do with SDL_MustLock and also a conversion omission to do with various events.
+         Fixed a conversion bug with SDL_CDOpen ( as suggested on the mailing list ).
+         Added the GetPixel and PuxPixel functions to the SDLUtils.pas file.
+         Jason Farmer has donated SFont, a simple, yet effective Font library he converted for JEDI-SDL.
+         It contains 4 Demos show how to best use it.
+         Added TUInt8Array and PUIntArray to SDL.pas after suggestions from Matthias Thoma and Eric Grange.
+         In the file area of the JEDI-SDL mailing list ( http://groups.yahoo.com/group/JEDI-SDL/files/DTTSrc/ there 
+         is a fully functional 3D network game called DeathTruckTion v1.0 written by the TNTeam that makes use of 
+         JEDI-SDL and is just too big to include with this distribution but is well worth looking at as it works under Windows and Linux!         
+         Gustavo Maxima is working on translating the JEDI-SDL Documentation to Spanish and Portugese.
+         The Mouse Demo has now been speeded up considerably and it is very responsive now.
+         Dean Ellis will provide steps on how to compile the demos using the Free Pascal compiler.
+         Jason Farmer and I are working on a series of Tutorials that should hopefully be out soon.
+         David Aclan has donated a SMpeg component that should work under Kylix.
+         R�bert Kisn�meth, has been hard at work, and has donated some new demos he has created with a SpriteEngine ( which he also donated ).
+         He has also donated a couple of games called BlitzBomber and Oxygene ( which uses the SpriteEngine ) and added a couple of useful 
+         functions to SDLUtils.pas.
+         The Functions added are SDL_FlipV, SDL_FlipH, SDL_NewPutPixel ( assembler version ), SDL_AddPixel, SDL_SubPixel, SDL_DrawLine, SDL_AddLine,
+         SDL_SubLine, SDL_AddSurface, SDL_SubSurface, SDL_MonoSurface & SDL_TexturedSurface.
+         He has also donated a Font Blitting class and demo called SDL_MonoFonts which supports alignment like Left, Right and Center.
+         He and Thomas are also working on a GUI library.
+         Jason Farmer has donated a set of Image Filtering functions which add quite a few interesting effects. Check the SDL_Filter sub-directory for more 
+         info.
+         Christian Hackbart also donated an OpenGL BlockOut clone.
+         
+
+Beta 3 : I have added conversions for SDL_env.h, SDL_Mixer.h and SDL_Net.h while Matthias Thoma has added conversions for SDL_Image.h and SMPEG.h.
+         This version is also SDL version 1.2.0 compliant.
+         This release also adds demos for the SDL_Image, SDL_Mixer and SDL_Net libraries.
+         There are now also some OpenGL demos that make some use of SDL as well as a demo on how to use the Mouse with Clickable regions.
+         A conversion bug, that was pointed out by Clem Vasseur, has also been fixed.
+         There is now a mailing list that has been set up at http://groups.yahoo.com/group/JEDI-SDL/join/ so we can all learn from each other how to use
+         these libraries.
+         Demos have not been unified into single .dpr files for each demo, thus showing how you would write a crossplatform game using only 1 .dpr file.
+         There is also a documentation directory that is currently in HTML format. All code examples in the documentation have been converted to Object 
+         Pascal but are untested.
+         I Also fixed a few conversion bugs which I came across while converting the documentation.
+
+Beta 2 : I have added  conversions for SDL_active.h, SDL_thread.h, SDL_mutex.h and 
+         SDL_error.h, Matthias Thoma has added Linux Support and JEDI compliancy so these 
+         units and examples are now x-platform and x-compiler compilable.
+         I also added Tom Jones' SDLUtils.pas file;
+         Matthias also cleaned up the 2 new demos and made them work on both Linux and 
+         Windows.
+
+Beta 1 : Initial Release;
+
+
+There are now 5 examples included with this JEDI-SDL distribution. 
+1. Is the TestWin application, which is based on the testwin application that comes with the SDL SDK, only my version has a gui front end to the options available and has been compiled under Delphi 4.03. It should be compatible with Delphi 3.0 onwards ( though Delphi 2 compatibility has not been tested ).
+
+2. A Plasma example which was converted from one found on the Demos page of the SDL site.
+
+3. A Voxel terrain following demo, which was converted from one found on the Demos page of the SDL site. This one should be of interest to others as it shows how to handle keyboard events when using SDL.
+
+4. A Mouse handling demo that shows how to use transparency and clickable regions.
+
+5. A Space Invaders style game called Aliens which shows the use of SDL, SDL_Image and SDL_Mixer. This game shows how to handle sound, keyboards and some basic collision detection. It is a conversion of one found on the SDL Demos page.
+
+There are also 14 OpenGL demos that are based on the NeHe tutorials <nehe.gamedev.net>. The other 3 OpenGL demos are Jan Horns' OpenGL demo, A Quake 2 Model viewer that I ported and a Demo by Gustavo Maxima called Puntos.
+
+If writing your own, just make sure that the SDL.pas file is in your projects path for compiling and that the SDL.dll file is in your path when running the compiled app.
+
+Please test these units and report problems to the JEDI-SDL mailing list @ http://groups.yahoo.com/group/JEDI-SDL/ outlining steps under which the error occurred. If you convert any more demos please send them to me so that I can  
+include them in the ditribution for others to learn from. 
+
+Also if you are using these Units to write any games 
+please let me know about it so that I can post the information to the http://www.DelphiGamer.com site.
+
+The plan is to have this unit JEDI certified at some point so that it can be included on the Delphi and Kylix CDs, so all feedback is greatly welcomed.
+
+Compilers supported     Tested
+-------------------     ------
+Delphi                   Yes
+Kylix                    Yes
+FreePascal               Yes
+TMT Pascal compiler      Not Yet.
+Virtual Pascal           No
+Gnu Pascal               No
+
+
+
+Credits
+-------
+Matthias Thoma <ma.thoma@gmx.de> for is endless help with my conversion bugs.
+Jason Farmer <jason@cerebral-bicycle.co.uk> for donating the SFont Font Library.
+Gustavo Maximo <gmaximo@secretariaplus.com> for the Puntos OpenGL Demo and work he is doing on the documentation
+R�bert Kisn�meth <mikrobi@freemail.hu> for his numerous contributions
+Chris Bruner <cryst@golden.net> for testing under Kylix
+August Logan Bear Jr.<augustjr@columbus.rr.com> for testing under Kylix
+Dean Ellis<dean_ellis@yahoo.com> for FreePascal Compiler compatability testing and SDL_Net demos and testing
+David House<david@dahsoftware.com> for Windows Insaller and testing.
+Romi Kuntsman<romik12345@lycos.co.uk> for helping out on some OpenGL issues.
+Everyone on the JEDI-SDL <http://groups.yahoo.com/group/JEDI-SDL/join/> mailing list for their feedback and support.
+Everyone on the Delphi-JEDI <http://groups.yahoo.com/group/Delphi-JEDI/join/> mailing for answering my conversion questions.
+Tom Jones for inspiring this conversion.
+
+The JEDI-SDL Home page can be found @ http://www.delphi-jedi.org/Jedi:TEAM_SDL_HOME
+
+The JEDI-SDL source code archive can be found @ http://www.sf.net/projects/jedi-sdl/
+
+The JEDI-SDL mailing list can be found @ http://groups.yahoo.com/group/JEDI-SDL/join/
+
+The Latest Stable Release version of the JEDI-SDL.zip file can always be found on the Delphi-JEDI site <http://www.delphi-jedi.org/Jedi:TEAM_SDL_HOME>
+
+The Latest Alpha/Unstable version can always be grabbed from the SourceForge CVS http://sourceforge.net/cvs/?group_id=43805
+
+
+Sincerely,
+
+
+
+Dominique Louis
+Delphi Game Developer.
+*********************************************************
+**  To Do Nothing is to Collaborate with the oppressor **
+**  -------------------------------------------------- **
+*********************************************************
+=========================================================
+From . . . . . . . : Dominique Louis
+Email. . . . . . . : Dominique@SavageSoftware.com.au
+Company. . . . . . : Savage Software Solutions
+Delphi Games Site. : http://www.DelphiGamer.com
+Delphi JEDI Site . : http://www.delphi-jedi.org
+=========================================================
+
diff --git a/songmanagement/src/lib/JEDI-SDL/OpenGL-Set8087CW.patch b/songmanagement/src/lib/JEDI-SDL/OpenGL-Set8087CW.patch
new file mode 100644
index 00000000..e08ca63e
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/OpenGL-Set8087CW.patch
@@ -0,0 +1,16 @@
+Index: OpenGL/Pas/gl.pas
+===================================================================
+--- OpenGL/Pas/gl.pas	(revision 961)
++++ OpenGL/Pas/gl.pas	(working copy)
+@@ -2287,9 +2287,9 @@
+ end;
+ 
+ initialization
+-  {$ifdef x86}
++  {$IF Defined(CPU386) or Defined(CPUI386) or Defined(CPUX86_64)}
+   Set8087CW($133F);
+-  {$endif x86}
++  {$IFEND}
+ 
+   LoadOpenGL( GLLibName );
+ 
diff --git a/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/geometry.pas b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/geometry.pas
new file mode 100644
index 00000000..166ec811
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/geometry.pas
@@ -0,0 +1,1994 @@
+unit geometry;
+{
+  $Id: geometry.pas,v 1.1 2004/03/30 21:53:54 savage Exp $
+  
+}
+
+// This unit contains many needed types, functions and procedures for
+// quaternion, vector and matrix arithmetics. It is specifically designed
+// for geometric calculations within R3 (affine vector space)
+// and R4 (homogeneous vector space).
+//
+// Note: The terms 'affine' or 'affine coordinates' are not really correct here
+//       because an 'affine transformation' describes generally a transformation which leads
+//       to a uniquely solvable system of equations and has nothing to do with the dimensionality
+//       of a vector. One could use 'projective coordinates' but this is also not really correct
+//       and since I haven't found a better name (or even any correct one), 'affine' is as good
+//       as any other one.
+//
+// Identifiers containing no dimensionality (like affine or homogeneous)
+// and no datatype (integer..extended) are supposed as R4 representation
+// with 'single' floating point type (examples are TVector, TMatrix,
+// and TQuaternion). The default data type is 'single' ('GLFloat' for OpenGL)
+// and used in all routines (except conversions and trigonometric functions).
+//
+// Routines with an open array as argument can either take Func([1,2,3,4,..]) or Func(Vect).
+// The latter is prefered, since no extra stack operations is required.
+// Note: Be careful while passing open array elements! If you pass more elements
+//       than there's room in the result the behaviour will be unpredictable.
+//
+// If not otherwise stated, all angles are given in radians
+// (instead of degrees). Use RadToDeg or DegToRad to convert between them.
+//
+// Geometry.pas was assembled from different sources (like GraphicGems)
+// and relevant books or based on self written code, respectivly.
+//
+// Note: Some aspects need to be considered when using Delphi and pure
+//       assembler code. Delphi ensures that the direction flag is always
+//       cleared while entering a function and expects it cleared on return.
+//       This is in particular important in routines with (CPU) string commands (MOVSD etc.)
+//       The registers EDI, ESI and EBX (as well as the stack management
+//       registers EBP and ESP) must not be changed! EAX, ECX and EDX are
+//       freely available and mostly used for parameter.
+//
+// Version 2.5
+// last change : 04. January 2000
+//
+// (c) Copyright 1999, Dipl. Ing. Mike Lischke (public@lischke-online.de)
+{
+  $Log: geometry.pas,v $
+  Revision 1.1  2004/03/30 21:53:54  savage
+  Moved to it's own folder.
+
+  Revision 1.1  2004/02/05 00:08:19  savage
+  Module 1.0 release
+
+  
+}
+
+interface
+
+{$I jedi-sdl.inc}
+
+type
+  // data types needed for 3D graphics calculation,
+  // included are 'C like' aliases for each type (to be
+  // conformal with OpenGL types)
+
+  PByte = ^Byte;
+  PWord = ^Word;
+  PInteger = ^Integer;
+  PFloat = ^Single;
+  PDouble = ^Double;
+  PExtended = ^Extended;
+  PPointer = ^Pointer;
+
+  // types to specify continous streams of a specific type
+  // switch off range checking to access values beyond the limits
+  PByteVector = ^TByteVector;
+  PByteArray = PByteVector;
+  TByteVector = array[0..0] of Byte;
+
+  PWordVector = ^TWordVector;
+  PWordArray = PWordVector;  // note: there's a same named type in SysUtils
+  TWordVector = array[0..0] of Word;
+
+  PIntegerVector = ^TIntegerVector;
+  PIntegerArray = PIntegerVector;
+  TIntegerVector = array[0..0] of Integer;
+
+  PFloatVector = ^TFloatVector;
+  PFloatArray = PFloatVector;
+  TFloatVector = array[0..0] of Single;
+
+  PDoubleVector = ^TDoubleVector;
+  PDoubleArray = PDoubleVector;
+  TDoubleVector = array[0..0] of Double;
+
+  PExtendedVector = ^TExtendedVector;
+  PExtendedArray = PExtendedVector;
+  TExtendedVector = array[0..0] of Extended;
+
+  PPointerVector = ^TPointerVector;
+  PPointerArray = PPointerVector;
+  TPointerVector = array[0..0] of Pointer;
+
+  PCardinalVector = ^TCardinalVector;
+  PCardinalArray = PCardinalVector;
+  TCardinalVector = array[0..0] of Cardinal;
+
+  // common vector and matrix types with predefined limits
+  // indices correspond like: x -> 0
+  //                          y -> 1
+  //                          z -> 2
+  //                          w -> 3
+
+  PHomogeneousByteVector = ^THomogeneousByteVector;
+  THomogeneousByteVector = array[0..3] of Byte;
+  TVector4b = THomogeneousByteVector;
+
+  PHomogeneousWordVector = ^THomogeneousWordVector;
+  THomogeneousWordVector = array[0..3] of Word;
+  TVector4w = THomogeneousWordVector;
+
+  PHomogeneousIntVector = ^THomogeneousIntVector;
+  THomogeneousIntVector = array[0..3] of Integer;
+  TVector4i = THomogeneousIntVector;
+
+  PHomogeneousFltVector = ^THomogeneousFltVector;
+  THomogeneousFltVector = array[0..3] of Single;
+  TVector4f = THomogeneousFltVector;
+
+  PHomogeneousDblVector = ^THomogeneousDblVector;
+  THomogeneousDblVector = array[0..3] of Double;
+  TVector4d = THomogeneousDblVector;
+
+  PHomogeneousExtVector = ^THomogeneousExtVector;
+  THomogeneousExtVector = array[0..3] of Extended;
+  TVector4e = THomogeneousExtVector;
+
+  PHomogeneousPtrVector = ^THomogeneousPtrVector;
+  THomogeneousPtrVector = array[0..3] of Pointer;
+  TVector4p = THomogeneousPtrVector;
+
+  PAffineByteVector = ^TAffineByteVector;
+  TAffineByteVector = array[0..2] of Byte;
+  TVector3b = TAffineByteVector;
+
+  PAffineWordVector = ^TAffineWordVector;
+  TAffineWordVector = array[0..2] of Word;
+  TVector3w = TAffineWordVector;
+
+  PAffineIntVector = ^TAffineIntVector;
+  TAffineIntVector = array[0..2] of Integer;
+  TVector3i = TAffineIntVector;
+
+  PAffineFltVector = ^TAffineFltVector;
+  TAffineFltVector = array[0..2] of Single;
+  TVector3f = TAffineFltVector;
+
+  PAffineDblVector = ^TAffineDblVector;
+  TAffineDblVector = array[0..2] of Double;
+  TVector3d = TAffineDblVector;
+
+  PAffineExtVector = ^TAffineExtVector;
+  TAffineExtVector = array[0..2] of Extended;
+  TVector3e = TAffineExtVector;
+
+  PAffinePtrVector = ^TAffinePtrVector;
+  TAffinePtrVector = array[0..2] of Pointer;
+  TVector3p = TAffinePtrVector;
+
+  // some simplified names
+  PVector = ^TVector;
+  TVector = THomogeneousFltVector;
+
+  PHomogeneousVector = ^THomogeneousVector;
+  THomogeneousVector = THomogeneousFltVector;
+
+  PAffineVector = ^TAffineVector;
+  TAffineVector = TAffineFltVector;
+
+  // arrays of vectors
+  PVectorArray = ^TVectorArray;
+  TVectorArray = array[0..0] of TAffineVector;
+
+  // matrices
+  THomogeneousByteMatrix = array[0..3] of THomogeneousByteVector;
+  TMatrix4b = THomogeneousByteMatrix;
+
+  THomogeneousWordMatrix = array[0..3] of THomogeneousWordVector;
+  TMatrix4w = THomogeneousWordMatrix;
+
+  THomogeneousIntMatrix = array[0..3] of THomogeneousIntVector;
+  TMatrix4i = THomogeneousIntMatrix;
+
+  THomogeneousFltMatrix  = array[0..3] of THomogeneousFltVector;
+  TMatrix4f = THomogeneousFltMatrix;
+
+  THomogeneousDblMatrix = array[0..3] of THomogeneousDblVector;
+  TMatrix4d = THomogeneousDblMatrix;
+
+  THomogeneousExtMatrix = array[0..3] of THomogeneousExtVector;
+  TMatrix4e = THomogeneousExtMatrix;
+
+  TAffineByteMatrix = array[0..2] of TAffineByteVector;
+  TMatrix3b = TAffineByteMatrix;
+
+  TAffineWordMatrix = array[0..2] of TAffineWordVector;
+  TMatrix3w = TAffineWordMatrix;
+
+  TAffineIntMatrix = array[0..2] of TAffineIntVector;
+  TMatrix3i = TAffineIntMatrix;
+
+  TAffineFltMatrix = array[0..2] of TAffineFltVector;
+  TMatrix3f = TAffineFltMatrix;
+
+  TAffineDblMatrix = array[0..2] of TAffineDblVector;
+  TMatrix3d = TAffineDblMatrix;
+
+  TAffineExtMatrix = array[0..2] of TAffineExtVector;
+  TMatrix3e = TAffineExtMatrix;
+
+  // some simplified names
+  PMatrix = ^TMatrix;
+  TMatrix = THomogeneousFltMatrix;
+
+  PHomogeneousMatrix = ^THomogeneousMatrix;
+  THomogeneousMatrix = THomogeneousFltMatrix;
+
+  PAffineMatrix = ^TAffineMatrix;
+  TAffineMatrix = TAffineFltMatrix;
+
+  // q = ([x, y, z], w)
+  TQuaternion = record
+    case Integer of
+      0:
+        (ImagPart: TAffineVector;
+         RealPart: Single);
+      1:
+        (Vector: TVector4f);
+  end;
+
+  TRectangle = record
+    Left,
+    Top,
+    Width,
+    Height: Integer;
+  end;
+
+  TTransType = (ttScaleX, ttScaleY, ttScaleZ,
+                ttShearXY, ttShearXZ, ttShearYZ,
+                ttRotateX, ttRotateY, ttRotateZ,
+                ttTranslateX, ttTranslateY, ttTranslateZ,
+                ttPerspectiveX, ttPerspectiveY, ttPerspectiveZ, ttPerspectiveW);
+
+  // used to describe a sequence of transformations in following order:
+  // [Sx][Sy][Sz][ShearXY][ShearXZ][ShearZY][Rx][Ry][Rz][Tx][Ty][Tz][P(x,y,z,w)]
+  // constants are declared for easier access (see MatrixDecompose below)
+  TTransformations  = array[TTransType] of Single;
+
+
+const
+  // useful constants
+
+  // standard vectors
+  XVector: TAffineVector = (1, 0, 0);
+  YVector: TAffineVector = (0, 1, 0);
+  ZVector: TAffineVector = (0, 0, 1);
+  NullVector: TAffineVector = (0, 0, 0);
+
+  IdentityMatrix: TMatrix = ((1, 0, 0, 0),
+                             (0, 1, 0, 0),
+                             (0, 0, 1, 0),
+                             (0, 0, 0, 1));
+  EmptyMatrix: TMatrix = ((0, 0, 0, 0),
+                          (0, 0, 0, 0),
+                          (0, 0, 0, 0),
+                          (0, 0, 0, 0));
+  // some very small numbers
+  EPSILON  = 1e-100;
+  EPSILON2 = 1e-50;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+// vector functions
+function  VectorAdd(V1, V2: TVector): TVector;
+function  VectorAffineAdd(V1, V2: TAffineVector): TAffineVector;
+function  VectorAffineCombine(V1, V2: TAffineVector; F1, F2: Single): TAffineVector;
+function  VectorAffineDotProduct(V1, V2: TAffineVector): Single;
+function  VectorAffineLerp(V1, V2: TAffineVector; t: Single): TAffineVector;
+function  VectorAffineSubtract(V1, V2: TAffineVector): TAffineVector;
+function  VectorAngle(V1, V2: TAffineVector): Single;
+function  VectorCombine(V1, V2: TVector; F1, F2: Single): TVector;
+function  VectorCrossProduct(V1, V2: TAffineVector): TAffineVector;
+function  VectorDotProduct(V1, V2: TVector): Single;
+function  VectorLength(V: array of Single): Single;
+function  VectorLerp(V1, V2: TVector; t: Single): TVector;
+procedure VectorNegate(V: array of Single);
+function  VectorNorm(V: array of Single): Single;
+function  VectorNormalize(V: array of Single): Single;
+function  VectorPerpendicular(V, N: TAffineVector): TAffineVector;
+function  VectorReflect(V, N: TAffineVector): TAffineVector;
+procedure VectorRotate(var Vector: TVector4f; Axis: TVector3f; Angle: Single);
+procedure VectorScale(V: array of Single; Factor: Single);
+function  VectorSubtract(V1, V2: TVector): TVector;
+
+// matrix functions
+function  CreateRotationMatrixX(Sine, Cosine: Single): TMatrix;
+function  CreateRotationMatrixY(Sine, Cosine: Single): TMatrix;
+function  CreateRotationMatrixZ(Sine, Cosine: Single): TMatrix;
+function  CreateScaleMatrix(V: TAffineVector): TMatrix;
+function  CreateTranslationMatrix(V: TVector): TMatrix;
+procedure MatrixAdjoint(var M: TMatrix);
+function  MatrixAffineDeterminant(M: TAffineMatrix): Single;
+procedure MatrixAffineTranspose(var M: TAffineMatrix);
+function  MatrixDeterminant(M: TMatrix): Single;
+procedure MatrixInvert(var M: TMatrix);
+function  MatrixMultiply(M1, M2: TMatrix): TMatrix;
+procedure MatrixScale(var M: TMatrix; Factor: Single);
+procedure MatrixTranspose(var M: TMatrix);
+
+// quaternion functions
+function  QuaternionConjugate(Q: TQuaternion): TQuaternion;
+function  QuaternionFromPoints(V1, V2: TAffineVector): TQuaternion;
+function  QuaternionMultiply(qL, qR: TQuaternion): TQuaternion;
+function  QuaternionSlerp(QStart, QEnd: TQuaternion; Spin: Integer; t: Single): TQuaternion;
+function  QuaternionToMatrix(Q: TQuaternion): TMatrix;
+procedure QuaternionToPoints(Q: TQuaternion; var ArcFrom, ArcTo: TAffineVector);
+
+// mixed functions
+function  ConvertRotation(Angles: TAffineVector): TVector;
+function  CreateRotationMatrix(Axis: TVector3f; Angle: Single): TMatrix;
+function  MatrixDecompose(M: TMatrix; var Tran: TTransformations): Boolean;
+function  VectorAffineTransform(V: TAffineVector; M: TAffineMatrix): TAffineVector;
+function  VectorTransform(V: TVector4f; M: TMatrix): TVector4f; overload;
+function  VectorTransform(V: TVector3f; M: TMatrix): TVector3f; overload;
+
+// miscellaneous functions
+function  MakeAffineDblVector(V: array of Double): TAffineDblVector;
+function  MakeDblVector(V: array of Double): THomogeneousDblVector;
+function  MakeAffineVector(V: array of Single): TAffineVector;
+function  MakeQuaternion(Imag: array of Single; Real: Single): TQuaternion;
+function  MakeVector(V: array of Single): TVector;
+function  PointInPolygon(xp, yp : array of Single; x, y: Single): Boolean;
+function  VectorAffineDblToFlt(V: TAffineDblVector): TAffineVector;
+function  VectorDblToFlt(V: THomogeneousDblVector): THomogeneousVector;
+function  VectorAffineFltToDbl(V: TAffineVector): TAffineDblVector;
+function  VectorFltToDbl(V: TVector): THomogeneousDblVector;
+
+// trigonometric functions
+function  ArcCos(X: Extended): Extended;
+function  ArcSin(X: Extended): Extended;
+function  ArcTan2(Y, X: Extended): Extended;
+function  CoTan(X: Extended): Extended;
+function  DegToRad(Degrees: Extended): Extended;
+function  RadToDeg(Radians: Extended): Extended;
+procedure SinCos(Theta: Extended; var Sin, Cos: Extended);
+function  Tan(X: Extended): Extended;
+
+// coordinate system manipulation functions
+function Turn(Matrix: TMatrix; Angle: Single): TMatrix; overload;
+function Turn(Matrix: TMatrix; MasterUp: TAffineVector; Angle: Single): TMatrix; overload;
+function Pitch(Matrix: TMatrix; Angle: Single): TMatrix; overload;
+function Pitch(Matrix: TMatrix; MasterRight: TAffineVector; Angle: Single): TMatrix; overload;
+function Roll(Matrix: TMatrix; Angle: Single): TMatrix; overload;
+function Roll(Matrix: TMatrix; MasterDirection: TAffineVector; Angle: Single): TMatrix; overload;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+implementation
+
+const
+  // FPU status flags (high order byte)
+  C0 = 1;
+  C1 = 2;
+  C2 = 4;
+  C3 = $40;
+
+  // to be used as descriptive indices
+  X = 0;
+  Y = 1;
+  Z = 2;
+  W = 3;
+
+//----------------- trigonometric helper functions ---------------------------------------------------------------------
+
+function DegToRad(Degrees: Extended): Extended;
+
+begin
+  Result := Degrees * (PI / 180);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function RadToDeg(Radians: Extended): Extended;
+
+begin
+  Result := Radians * (180 / PI);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure SinCos(Theta: Extended; var Sin, Cos: Extended); assembler; register;
+
+// calculates sine and cosine from the given angle Theta
+// EAX contains address of Sin
+// EDX contains address of Cos
+// Theta is passed over the stack
+
+asm
+              FLD  Theta
+              FSINCOS
+              FSTP TBYTE PTR [EDX]    // cosine
+              FSTP TBYTE PTR [EAX]    // sine
+              FWAIT
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function ArcCos(X: Extended): Extended;
+
+begin
+  Result := ArcTan2(Sqrt(1 - X * X), X);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function ArcSin(X: Extended): Extended;
+
+begin
+  Result := ArcTan2(X, Sqrt(1 - X * X))
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function ArcTan2(Y, X: Extended): Extended;
+
+asm
+              FLD  Y
+              FLD  X
+              FPATAN
+              FWAIT
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function Tan(X: Extended): Extended;
+
+asm
+              FLD  X
+              FPTAN
+              FSTP ST(0)      // FPTAN pushes 1.0 after result
+              FWAIT
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function CoTan(X: Extended): Extended;
+
+asm
+              FLD  X
+              FPTAN
+              FDIVRP
+              FWAIT
+end;
+
+//----------------- miscellaneous vector functions ---------------------------------------------------------------------
+
+function MakeAffineDblVector(V: array of Double): TAffineDblVector; assembler;
+
+// creates a vector from given values
+// EAX contains address of V
+// ECX contains address to result vector
+// EDX contains highest index of V
+
+asm
+              PUSH EDI
+              PUSH ESI
+              MOV EDI, ECX
+              MOV ESI, EAX
+              MOV ECX, EDX
+              ADD ECX, 2
+              REP MOVSD
+              POP ESI
+              POP EDI
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function MakeDblVector(V: array of Double): THomogeneousDblVector; assembler;
+
+// creates a vector from given values
+// EAX contains address of V
+// ECX contains address to result vector
+// EDX contains highest index of V
+
+asm
+              PUSH EDI
+              PUSH ESI
+              MOV EDI, ECX
+              MOV ESI, EAX
+              MOV ECX, EDX
+              ADD ECX, 2
+              REP MOVSD
+              POP ESI
+              POP EDI
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function MakeAffineVector(V: array of Single): TAffineVector; assembler;
+
+// creates a vector from given values
+// EAX contains address of V
+// ECX contains address to result vector
+// EDX contains highest index of V
+
+asm
+              PUSH EDI
+              PUSH ESI
+              MOV EDI, ECX
+              MOV ESI, EAX
+              MOV ECX, EDX
+              INC ECX
+              CMP ECX, 3
+              JB  @@1
+              MOV ECX, 3
+@@1:          REP MOVSD                     // copy given values
+              MOV ECX, 2
+              SUB ECX, EDX                   // determine missing entries
+              JS  @@Finish
+              XOR EAX, EAX
+              REP STOSD                     // set remaining fields to 0
+@@Finish:     POP ESI
+              POP EDI
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function MakeQuaternion(Imag: array of Single; Real: Single): TQuaternion; assembler;
+
+// creates a quaternion from the given values
+// EAX contains address of Imag
+// ECX contains address to result vector
+// EDX contains highest index of Imag
+// Real part is passed on the stack
+
+asm
+              PUSH EDI
+              PUSH ESI
+              MOV EDI, ECX
+              MOV ESI, EAX
+              MOV ECX, EDX
+              INC ECX
+              REP MOVSD
+              MOV EAX, [Real]
+              MOV [EDI], EAX
+              POP ESI
+              POP EDI
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function MakeVector(V: array of Single): TVector; assembler;
+
+// creates a vector from given values
+// EAX contains address of V
+// ECX contains address to result vector
+// EDX contains highest index of V
+
+asm
+              PUSH EDI
+              PUSH ESI
+              MOV EDI, ECX
+              MOV ESI, EAX
+              MOV ECX, EDX
+              INC ECX
+              CMP ECX, 4
+              JB  @@1
+              MOV ECX, 4
+@@1:          REP MOVSD                     // copy given values
+              MOV ECX, 3
+              SUB ECX, EDX                   // determine missing entries
+              JS  @@Finish
+              XOR EAX, EAX
+              REP STOSD                     // set remaining fields to 0
+@@Finish:     POP ESI
+              POP EDI
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorLength(V: array of Single): Single; assembler;
+
+// calculates the length of a vector following the equation: sqrt(x * x + y * y + ...)
+// Note: The parameter of this function is declared as open array. Thus
+// there's no restriction about the number of the components of the vector.
+//
+// EAX contains address of V
+// EDX contains the highest index of V
+// the result is returned in ST(0)
+
+asm
+              FLDZ                           // initialize sum
+@@Loop:       FLD  DWORD PTR [EAX  +  4 * EDX] // load a component
+              FMUL ST, ST
+              FADDP
+              SUB  EDX, 1
+              JNL  @@Loop
+              FSQRT
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAngle(V1, V2: TAffineVector): Single; assembler;
+
+// calculates the cosine of the angle between Vector1 and Vector2
+// Result = DotProduct(V1, V2) / (Length(V1) * Length(V2))
+//
+// EAX contains address of Vector1
+// EDX contains address of Vector2
+
+asm
+              FLD DWORD PTR [EAX]           // V1[0]
+              FLD ST                        // double V1[0]
+              FMUL ST, ST                   // V1[0]^2 (prep. for divisor)
+              FLD DWORD PTR [EDX]           // V2[0]
+              FMUL ST(2), ST                // ST(2) := V1[0] * V2[0]
+              FMUL ST, ST                   // V2[0]^2 (prep. for divisor)
+              FLD DWORD PTR [EAX + 4]       // V1[1]
+              FLD ST                        // double V1[1]
+              FMUL ST, ST                   // ST(0) := V1[1]^2
+              FADDP ST(3), ST               // ST(2) := V1[0]^2 + V1[1] *  * 2
+              FLD DWORD PTR [EDX + 4]       // V2[1]
+              FMUL ST(1), ST                // ST(1) := V1[1] * V2[1]
+              FMUL ST, ST                   // ST(0) := V2[1]^2
+              FADDP ST(2), ST               // ST(1) := V2[0]^2 + V2[1]^2
+              FADDP ST(3), ST               // ST(2) := V1[0] * V2[0] + V1[1] * V2[1]
+              FLD DWORD PTR [EAX + 8]       // load V2[1]
+              FLD ST                        // same calcs go here
+              FMUL ST, ST                   // (compare above)
+              FADDP ST(3), ST
+              FLD DWORD PTR [EDX + 8]
+              FMUL ST(1), ST
+              FMUL ST, ST
+              FADDP ST(2), ST
+              FADDP ST(3), ST
+              FMULP                         // ST(0) := (V1[0]^2 + V1[1]^2 + V1[2]) *
+                                            //          (V2[0]^2 + V2[1]^2 + V2[2])
+              FSQRT                         // sqrt(ST(0))
+              FDIVP                         // ST(0) := Result := ST(1) / ST(0)
+  // the result is expected in ST(0), if it's invalid, an error is raised
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorNorm(V: array of Single): Single; assembler; register;
+
+// calculates norm of a vector which is defined as norm = x * x + y * y + ...
+// EAX contains address of V
+// EDX contains highest index in V
+// result is passed in ST(0)
+
+asm
+              FLDZ                           // initialize sum
+@@Loop:       FLD  DWORD PTR [EAX + 4 * EDX] // load a component
+              FMUL ST, ST                    // make square
+              FADDP                          // add previous calculated sum
+              SUB  EDX, 1
+              JNL  @@Loop
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorNormalize(V: array of Single): Single; assembler; register;
+
+// transforms a vector to unit length and return length
+// EAX contains address of V
+// EDX contains the highest index in V
+// return former length of V in ST
+
+asm
+              PUSH EBX
+              MOV ECX, EDX                  // save size of V
+              CALL VectorLength             // calculate length of vector
+              FTST                          // test if length = 0
+              MOV EBX, EAX                  // save parameter address
+              FSTSW AX                      // get test result
+              TEST AH, C3                   // check the test result
+              JNZ @@Finish
+              SUB EBX, 4                    // simplyfied address calculation
+              INC ECX
+              FLD1                          // calculate reciprocal of length
+              FDIV ST, ST(1)
+@@1:          FLD ST                        // double reciprocal
+              FMUL DWORD PTR [EBX + 4 * ECX] // scale component
+              WAIT
+              FSTP DWORD PTR [EBX + 4 * ECX] // store result
+              LOOP @@1
+              FSTP ST                       // remove reciprocal from FPU stack
+@@Finish:     POP EBX
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAffineSubtract(V1, V2: TAffineVector): TAffineVector; assembler; register;
+
+// returns v1 minus v2
+// EAX contains address of V1
+// EDX contains address of V2
+// ECX contains address of the result
+
+asm
+  {Result[X] := V1[X]-V2[X];
+  Result[Y] := V1[Y]-V2[Y];
+  Result[Z] := V1[Z]-V2[Z];}
+
+                   FLD DWORD PTR [EAX]
+                   FSUB DWORD PTR [EDX]
+                   FSTP DWORD PTR [ECX]
+                   FLD DWORD PTR [EAX + 4]
+                   FSUB DWORD PTR [EDX + 4]
+                   FSTP DWORD PTR [ECX + 4]
+                   FLD DWORD PTR [EAX + 8]
+                   FSUB DWORD PTR [EDX + 8]
+                   FSTP DWORD PTR [ECX + 8]
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorReflect(V, N: TAffineVector): TAffineVector; assembler; register;
+
+// reflects vector V against N (assumes N is normalized)
+// EAX contains address of V
+// EDX contains address of N
+// ECX contains address of the result
+
+//var Dot : Single;
+
+asm
+   {Dot := VectorAffineDotProduct(V, N);
+   Result[X] := V[X]-2 * Dot * N[X];
+   Result[Y] := V[Y]-2 * Dot * N[Y];
+   Result[Z] := V[Z]-2 * Dot * N[Z];}
+
+                   CALL VectorAffineDotProduct   // dot is now in ST(0)
+                   FCHS                          // -dot
+                   FADD ST, ST                   // -dot * 2
+                   FLD DWORD PTR [EDX]           // ST := N[X]
+                   FMUL ST, ST(1)                // ST := -2 * dot * N[X]
+                   FADD DWORD PTR[EAX]           // ST := V[X] - 2 * dot * N[X]
+                   FSTP DWORD PTR [ECX]          // store result
+                   FLD DWORD PTR [EDX + 4]       // etc.
+                   FMUL ST, ST(1)
+                   FADD DWORD PTR[EAX + 4]
+                   FSTP DWORD PTR [ECX + 4]
+                   FLD DWORD PTR [EDX + 8]
+                   FMUL ST, ST(1)
+                   FADD DWORD PTR[EAX + 8]
+                   FSTP DWORD PTR [ECX + 8]
+                   FSTP ST                       // clean FPU stack
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure VectorRotate(var Vector: TVector4f; Axis: TVector3f; Angle: Single);
+
+// rotates Vector about Axis with Angle radiants
+
+var RotMatrix : TMatrix4f;
+
+begin
+  RotMatrix := CreateRotationMatrix(Axis, Angle);
+  Vector := VectorTransform(Vector, RotMatrix);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure VectorScale(V: array of Single; Factor: Single); assembler; register;
+
+// returns a vector scaled by a factor
+// EAX contains address of V
+// EDX contains highest index in V
+// Factor is located on the stack
+
+asm
+  {for I := Low(V) to High(V) do V[I] := V[I] * Factor;}
+
+              FLD DWORD PTR [Factor]        // load factor
+@@Loop:       FLD DWORD PTR [EAX + 4 * EDX] // load a component
+              FMUL ST, ST(1)                // multiply it with the factor
+              WAIT
+              FSTP DWORD PTR [EAX + 4 * EDX] // store the result
+              DEC EDX                       // do the entire array
+              JNS @@Loop
+              FSTP ST(0)                    // clean the FPU stack
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure VectorNegate(V: array of Single); assembler; register;
+
+// returns a negated vector
+// EAX contains address of V
+// EDX contains highest index in V
+
+asm
+  {V[X] := -V[X];
+  V[Y] := -V[Y];
+  V[Z] := -V[Z];}
+
+@@Loop:       FLD DWORD PTR [EAX + 4 * EDX]
+              FCHS
+              WAIT
+              FSTP DWORD PTR [EAX + 4 * EDX]
+              DEC EDX
+              JNS @@Loop
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAdd(V1, V2: TVector): TVector; register;
+
+// returns the sum of two vectors
+
+begin
+  Result[X] := V1[X] + V2[X];
+  Result[Y] := V1[Y] + V2[Y];
+  Result[Z] := V1[Z] + V2[Z];
+  Result[W] := V1[W] + V2[W];
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAffineAdd(V1, V2: TAffineVector): TAffineVector; register;
+
+// returns the sum of two vectors
+
+begin
+  Result[X] := V1[X] + V2[X];
+  Result[Y] := V1[Y] + V2[Y];
+  Result[Z] := V1[Z] + V2[Z];
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorSubtract(V1, V2: TVector): TVector; register;
+
+// returns the difference of two vectors
+
+begin
+  Result[X] := V1[X] - V2[X];
+  Result[Y] := V1[Y] - V2[Y];
+  Result[Z] := V1[Z] - V2[Z];
+  Result[W] := V1[W] - V2[W];
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorDotProduct(V1, V2: TVector): Single; register;
+
+begin
+  Result := V1[X] * V2[X] + V1[Y] * V2[Y] + V1[Z] * V2[Z] + V1[W] * V2[W];
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAffineDotProduct(V1, V2: TAffineVector): Single; assembler; register;
+
+// calculates the dot product between V1 and V2
+// EAX contains address of V1
+// EDX contains address of V2
+// result is stored in ST(0)
+
+asm
+  //Result := V1[X] * V2[X] + V1[Y] * V2[Y] + V1[Z] * V2[Z];
+
+                   FLD DWORD PTR [EAX]
+                   FMUL DWORD PTR [EDX]
+                   FLD DWORD PTR [EAX + 4]
+                   FMUL DWORD PTR [EDX + 4]
+                   FADDP
+                   FLD DWORD PTR [EAX + 8]
+                   FMUL DWORD PTR [EDX + 8]
+                   FADDP
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorCrossProduct(V1, V2: TAffineVector): TAffineVector;
+
+// calculates the cross product between vector 1 and 2, Temp is necessary because
+// either V1 or V2 could also be the result vector
+//
+// EAX contains address of V1
+// EDX contains address of V2
+// ECX contains address of result
+
+var Temp: TAffineVector;
+
+asm
+  {Temp[X] := V1[Y] * V2[Z]-V1[Z] * V2[Y];
+  Temp[Y] := V1[Z] * V2[X]-V1[X] * V2[Z];
+  Temp[Z] := V1[X] * V2[Y]-V1[Y] * V2[X];
+  Result := Temp;}
+
+              PUSH EBX                      // save EBX, must be restored to original value
+              LEA EBX, [Temp]
+              FLD DWORD PTR [EDX + 8]       // first load both vectors onto FPU register stack
+              FLD DWORD PTR [EDX + 4]
+              FLD DWORD PTR [EDX + 0]
+              FLD DWORD PTR [EAX + 8]
+              FLD DWORD PTR [EAX + 4]
+              FLD DWORD PTR [EAX + 0]
+
+              FLD ST(1)                     // ST(0) := V1[Y]
+              FMUL ST, ST(6)                // ST(0) := V1[Y] * V2[Z]
+              FLD ST(3)                     // ST(0) := V1[Z]
+              FMUL ST, ST(6)                // ST(0) := V1[Z] * V2[Y]
+              FSUBP ST(1), ST               // ST(0) := ST(1)-ST(0)
+              FSTP DWORD [EBX]              // Temp[X] := ST(0)
+              FLD ST(2)                     // ST(0) := V1[Z]
+              FMUL ST, ST(4)                // ST(0) := V1[Z] * V2[X]
+              FLD ST(1)                     // ST(0) := V1[X]
+              FMUL ST, ST(7)                // ST(0) := V1[X] * V2[Z]
+              FSUBP ST(1), ST               // ST(0) := ST(1)-ST(0)
+              FSTP DWORD [EBX + 4]          // Temp[Y] := ST(0)
+              FLD ST                        // ST(0) := V1[X]
+              FMUL ST, ST(5)                // ST(0) := V1[X] * V2[Y]
+              FLD ST(2)                     // ST(0) := V1[Y]
+              FMUL ST, ST(5)                // ST(0) := V1[Y] * V2[X]
+              FSUBP ST(1), ST               // ST(0) := ST(1)-ST(0)
+              FSTP DWORD [EBX + 8]          // Temp[Z] := ST(0)
+              FSTP ST(0)                    // clear FPU register stack
+              FSTP ST(0)
+              FSTP ST(0)
+              FSTP ST(0)
+              FSTP ST(0)
+              FSTP ST(0)
+              MOV EAX, [EBX]                // copy Temp to Result
+              MOV [ECX], EAX
+              MOV EAX, [EBX + 4]
+              MOV [ECX + 4], EAX
+              MOV EAX, [EBX + 8]
+              MOV [ECX + 8], EAX
+              POP EBX
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorPerpendicular(V, N: TAffineVector): TAffineVector;
+
+// calculates a vector perpendicular to N (N is assumed to be of unit length)
+// subtract out any component parallel to N
+
+var Dot: Single;
+
+begin
+   Dot := VectorAffineDotProduct(V, N);
+   Result[X] := V[X]-Dot * N[X];
+   Result[Y] := V[Y]-Dot * N[Y];
+   Result[Z] := V[Z]-Dot * N[Z];
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorTransform(V: TVector4f; M: TMatrix): TVector4f; register;
+
+// transforms a homogeneous vector by multiplying it with a matrix
+
+var TV: TVector4f;
+
+begin
+  TV[X] := V[X] * M[X, X] + V[Y] * M[Y, X] + V[Z] * M[Z, X] + V[W] * M[W, X];
+  TV[Y] := V[X] * M[X, Y] + V[Y] * M[Y, Y] + V[Z] * M[Z, Y] + V[W] * M[W, Y];
+  TV[Z] := V[X] * M[X, Z] + V[Y] * M[Y, Z] + V[Z] * M[Z, Z] + V[W] * M[W, Z];
+  TV[W] := V[X] * M[X, W] + V[Y] * M[Y, W] + V[Z] * M[Z, W] + V[W] * M[W, W];
+  Result := TV
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function  VectorTransform(V: TVector3f; M: TMatrix): TVector3f;
+
+// transforms an affine vector by multiplying it with a (homogeneous) matrix
+
+var TV: TVector3f;
+
+begin
+  TV[X] := V[X] * M[X, X] + V[Y] * M[Y, X] + V[Z] * M[Z, X] + M[W, X];
+  TV[Y] := V[X] * M[X, Y] + V[Y] * M[Y, Y] + V[Z] * M[Z, Y] + M[W, Y];
+  TV[Z] := V[X] * M[X, Z] + V[Y] * M[Y, Z] + V[Z] * M[Z, Z] + M[W, Z];
+  Result := TV;
+end;
+
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAffineTransform(V: TAffineVector; M: TAffineMatrix): TAffineVector; register;
+
+// transforms an affine vector by multiplying it with a matrix
+
+var TV: TAffineVector;
+
+begin
+  TV[X] := V[X] * M[X, X] + V[Y] * M[Y, X] + V[Z] * M[Z, X];
+  TV[Y] := V[X] * M[X, Y] + V[Y] * M[Y, Y] + V[Z] * M[Z, Y];
+  TV[Z] := V[X] * M[X, Z] + V[Y] * M[Y, Z] + V[Z] * M[Z, Z];
+  Result := TV;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function PointInPolygon(xp, yp : array of Single; x, y: Single): Boolean;
+
+// The code below is from Wm. Randolph Franklin <wrf@ecse.rpi.edu>
+// with some minor modifications for speed.  It returns 1 for strictly
+// interior points, 0 for strictly exterior, and 0 or 1 for points on
+// the boundary.
+// This code is not yet tested!
+
+var I, J: Integer;
+
+begin
+  Result := False;
+  if High(XP) <> High(YP) then Exit;
+  J := High(XP);
+  for I := 0 to High(XP) do
+  begin
+    if ((((yp[I] <= y) and (y < yp[J])) or ((yp[J] <= y) and (y < yp[I]))) and
+        (x < (xp[J] - xp[I]) * (y - yp[I]) / (yp[J] - yp[I]) + xp[I]))
+    then Result := not Result;
+    J := I + 1;
+  end;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function QuaternionConjugate(Q: TQuaternion): TQuaternion; assembler;
+
+// returns the conjugate of a quaternion
+// EAX contains address of Q
+// EDX contains address of result
+
+asm
+              FLD DWORD PTR [EAX]
+              FCHS
+              WAIT
+              FSTP DWORD PTR [EDX]
+              FLD DWORD PTR [EAX + 4]
+              FCHS
+              WAIT
+              FSTP DWORD PTR [EDX + 4]
+              FLD DWORD PTR [EAX + 8]
+              FCHS
+              WAIT
+              FSTP DWORD PTR [EDX + 8]
+              MOV EAX, [EAX + 12]
+              MOV [EDX + 12], EAX
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function QuaternionFromPoints(V1, V2: TAffineVector): TQuaternion; assembler;
+
+// constructs a unit quaternion from two points on unit sphere
+// EAX contains address of V1
+// ECX contains address to result
+// EDX contains address of V2
+
+asm
+  {Result.ImagPart := VectorCrossProduct(V1, V2);
+   Result.RealPart :=  Sqrt((VectorAffineDotProduct(V1, V2) + 1)/2);}
+
+              PUSH EAX
+              CALL VectorCrossProduct       // determine axis to rotate about
+              POP EAX
+              FLD1                          // prepare next calculation
+              Call VectorAffineDotProduct   // calculate cos(angle between V1 and V2)
+              FADD ST, ST(1)                // transform angle to angle/2 by: cos(a/2)=sqrt((1 + cos(a))/2)
+              FXCH ST(1)
+              FADD ST, ST
+              FDIVP ST(1), ST
+              FSQRT
+              FSTP DWORD PTR [ECX + 12]     // Result.RealPart := ST(0)
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function QuaternionMultiply(qL, qR: TQuaternion): TQuaternion;
+
+// Returns quaternion product qL * qR.  Note: order is important!
+// To combine rotations, use the product QuaternionMuliply(qSecond, qFirst),
+// which gives the effect of rotating by qFirst then qSecond.
+
+var Temp : TQuaternion;
+
+begin
+  Temp.RealPart := qL.RealPart * qR.RealPart - qL.ImagPart[X] * qR.ImagPart[X] -
+                   qL.ImagPart[Y] * qR.ImagPart[Y] - qL.ImagPart[Z] * qR.ImagPart[Z];
+  Temp.ImagPart[X] := qL.RealPart * qR.ImagPart[X] + qL.ImagPart[X] * qR.RealPart +
+                      qL.ImagPart[Y] * qR.ImagPart[Z] - qL.ImagPart[Z] * qR.ImagPart[Y];
+  Temp.ImagPart[Y] := qL.RealPart * qR.ImagPart[Y] + qL.ImagPart[Y] * qR.RealPart +
+                      qL.ImagPart[Z] * qR.ImagPart[X] - qL.ImagPart[X] * qR.ImagPart[Z];
+  Temp.ImagPart[Z] := qL.RealPart * qR.ImagPart[Z] + qL.ImagPart[Z] * qR.RealPart +
+                      qL.ImagPart[X] * qR.ImagPart[Y] - qL.ImagPart[Y] * qR.ImagPart[X];
+  Result := Temp;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function QuaternionToMatrix(Q: TQuaternion): TMatrix;
+
+// Constructs rotation matrix from (possibly non-unit) quaternion.
+// Assumes matrix is used to multiply column vector on the left:
+// vnew = mat vold.  Works correctly for right-handed coordinate system
+// and right-handed rotations.
+
+// Essentially, this function is the same as CreateRotationMatrix and you can consider it as
+// being for reference here.
+
+{var Norm, S,
+    XS, YS, ZS,
+    WX, WY, WZ,
+    XX, XY, XZ,
+    YY, YZ, ZZ   : Single;
+
+begin
+  Norm := Q.Vector[X] * Q.Vector[X] + Q.Vector[Y] * Q.Vector[Y] + Q.Vector[Z] * Q.Vector[Z] + Q.RealPart * Q.RealPart;
+  if Norm > 0 then S := 2 / Norm
+              else S := 0;
+
+  XS := Q.Vector[X] * S;   YS := Q.Vector[Y] * S;   ZS := Q.Vector[Z] * S;
+  WX := Q.RealPart * XS;   WY := Q.RealPart * YS;   WZ := Q.RealPart * ZS;
+  XX := Q.Vector[X] * XS;  XY := Q.Vector[X] * YS;  XZ := Q.Vector[X] * ZS;
+  YY := Q.Vector[Y] * YS;  YZ := Q.Vector[Y] * ZS;  ZZ := Q.Vector[Z] * ZS;
+
+  Result[X, X] := 1 - (YY + ZZ); Result[Y, X] := XY + WZ;       Result[Z, X] := XZ - WY;       Result[W, X] := 0;
+  Result[X, Y] := XY - WZ;       Result[Y, Y] := 1 - (XX + ZZ); Result[Z, Y] := YZ + WX;       Result[W, Y] := 0;
+  Result[X, Z] := XZ + WY;       Result[Y, Z] := YZ - WX;       Result[Z, Z] := 1 - (XX + YY); Result[W, Z] := 0;
+  Result[X, W] := 0;             Result[Y, W] := 0;             Result[Z, W] := 0;             Result[W, W] := 1;}
+
+var
+  V: TAffineVector;
+  SinA, CosA,
+  A, B, C: Extended;
+
+begin
+  V := Q.ImagPart;
+  VectorNormalize(V);
+  SinCos(Q.RealPart / 2, SinA, CosA);
+  A := V[X] * SinA;
+  B := V[Y] * SinA;
+  C := V[Z] * SinA;
+
+  Result := IdentityMatrix;
+  Result[X, X] := 1 - 2 * B * B - 2 * C * C;
+  Result[X, Y] := 2 * A * B - 2 * CosA * C;
+  Result[X, Z] := 2 * A * C + 2 * CosA * B;
+
+  Result[Y, X] := 2 * A * B + 2 * CosA * C;
+  Result[Y, Y] := 1 - 2 * A * A - 2 * C * C;
+  Result[Y, Z] := 2 * B * C - 2 * CosA * A;
+
+  Result[Z, X] := 2 * A * C - 2 * CosA * B;
+  Result[Z, Y] := 2 * B * C + 2 * CosA * A;
+  Result[Z, Z] := 1 - 2 * A * A - 2 * B * B;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure QuaternionToPoints(Q: TQuaternion; var ArcFrom, ArcTo: TAffineVector); register;
+
+// converts a unit quaternion into two points on a unit sphere
+
+var S: Single;
+
+begin
+  S := Sqrt(Q.ImagPart[X] * Q.ImagPart[X] + Q.ImagPart[Y] * Q.ImagPart[Y]);
+  if S = 0 then ArcFrom := MakeAffineVector([0, 1, 0])
+           else ArcFrom := MakeAffineVector([-Q.ImagPart[Y] / S, Q.ImagPart[X] / S, 0]);
+  ArcTo[X] := Q.RealPart * ArcFrom[X] - Q.ImagPart[Z] * ArcFrom[Y];
+  ArcTo[Y] := Q.RealPart * ArcFrom[Y] + Q.ImagPart[Z] * ArcFrom[X];
+  ArcTo[Z] := Q.ImagPart[X] * ArcFrom[Y] - Q.ImagPart[Y] * ArcFrom[X];
+  if Q.RealPart < 0 then ArcFrom := MakeAffineVector([-ArcFrom[X], -ArcFrom[Y], 0]);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function MatrixAffineDeterminant(M: TAffineMatrix): Single; register;
+
+// determinant of a 3x3 matrix
+
+begin
+  Result := M[X, X] * (M[Y, Y] * M[Z, Z] - M[Z, Y] * M[Y, Z]) -
+            M[X, Y] * (M[Y, X] * M[Z, Z] - M[Z, X] * M[Y, Z]) +
+            M[X, Z] * (M[Y, X] * M[Z, Y] - M[Z, X] * M[Y, Y]);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function MatrixDetInternal(a1, a2, a3, b1, b2, b3, c1, c2, c3: Single): Single;
+
+// internal version for the determinant of a 3x3 matrix
+
+begin
+  Result := a1 * (b2 * c3 - b3 * c2) -
+            b1 * (a2 * c3 - a3 * c2) +
+            c1 * (a2 * b3 - a3 * b2);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure MatrixAdjoint(var M: TMatrix); register;
+
+// Adjoint of a 4x4 matrix - used in the computation of the inverse
+// of a 4x4 matrix
+
+var a1, a2, a3, a4,
+    b1, b2, b3, b4,
+    c1, c2, c3, c4,
+    d1, d2, d3, d4: Single;
+
+
+begin
+    a1 :=  M[X, X]; b1 :=  M[X, Y];
+    c1 :=  M[X, Z]; d1 :=  M[X, W];
+    a2 :=  M[Y, X]; b2 :=  M[Y, Y];
+    c2 :=  M[Y, Z]; d2 :=  M[Y, W];
+    a3 :=  M[Z, X]; b3 :=  M[Z, Y];
+    c3 :=  M[Z, Z]; d3 :=  M[Z, W];
+    a4 :=  M[W, X]; b4 :=  M[W, Y];
+    c4 :=  M[W, Z]; d4 :=  M[W, W];
+
+    // row column labeling reversed since we transpose rows & columns
+    M[X, X] :=  MatrixDetInternal(b2, b3, b4, c2, c3, c4, d2, d3, d4);
+    M[Y, X] := -MatrixDetInternal(a2, a3, a4, c2, c3, c4, d2, d3, d4);
+    M[Z, X] :=  MatrixDetInternal(a2, a3, a4, b2, b3, b4, d2, d3, d4);
+    M[W, X] := -MatrixDetInternal(a2, a3, a4, b2, b3, b4, c2, c3, c4);
+
+    M[X, Y] := -MatrixDetInternal(b1, b3, b4, c1, c3, c4, d1, d3, d4);
+    M[Y, Y] :=  MatrixDetInternal(a1, a3, a4, c1, c3, c4, d1, d3, d4);
+    M[Z, Y] := -MatrixDetInternal(a1, a3, a4, b1, b3, b4, d1, d3, d4);
+    M[W, Y] :=  MatrixDetInternal(a1, a3, a4, b1, b3, b4, c1, c3, c4);
+
+    M[X, Z] :=  MatrixDetInternal(b1, b2, b4, c1, c2, c4, d1, d2, d4);
+    M[Y, Z] := -MatrixDetInternal(a1, a2, a4, c1, c2, c4, d1, d2, d4);
+    M[Z, Z] :=  MatrixDetInternal(a1, a2, a4, b1, b2, b4, d1, d2, d4);
+    M[W, Z] := -MatrixDetInternal(a1, a2, a4, b1, b2, b4, c1, c2, c4);
+
+    M[X, W] := -MatrixDetInternal(b1, b2, b3, c1, c2, c3, d1, d2, d3);
+    M[Y, W] :=  MatrixDetInternal(a1, a2, a3, c1, c2, c3, d1, d2, d3);
+    M[Z, W] := -MatrixDetInternal(a1, a2, a3, b1, b2, b3, d1, d2, d3);
+    M[W, W] :=  MatrixDetInternal(a1, a2, a3, b1, b2, b3, c1, c2, c3);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function MatrixDeterminant(M: TMatrix): Single; register;
+
+// Determinant of a 4x4 matrix
+
+var a1, a2, a3, a4,
+    b1, b2, b3, b4,
+    c1, c2, c3, c4,
+    d1, d2, d3, d4  : Single;
+
+begin
+  a1 := M[X, X];  b1 := M[X, Y];  c1 := M[X, Z];  d1 := M[X, W];
+  a2 := M[Y, X];  b2 := M[Y, Y];  c2 := M[Y, Z];  d2 := M[Y, W];
+  a3 := M[Z, X];  b3 := M[Z, Y];  c3 := M[Z, Z];  d3 := M[Z, W];
+  a4 := M[W, X];  b4 := M[W, Y];  c4 := M[W, Z];  d4 := M[W, W];
+
+  Result := a1 * MatrixDetInternal(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
+            b1 * MatrixDetInternal(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
+            c1 * MatrixDetInternal(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
+            d1 * MatrixDetInternal(a2, a3, a4, b2, b3, b4, c2, c3, c4);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure MatrixScale(var M: TMatrix; Factor: Single); register;
+
+// multiplies all elements of a 4x4 matrix with a factor
+
+var I, J: Integer;
+
+begin
+  for I := 0 to 3 do
+    for J := 0 to 3 do M[I, J] := M[I, J] * Factor;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure MatrixInvert(var M: TMatrix); register;
+
+// finds the inverse of a 4x4 matrix
+
+var Det: Single;
+
+begin
+  Det := MatrixDeterminant(M);
+  if Abs(Det) < EPSILON then M := IdentityMatrix
+                        else
+  begin
+    MatrixAdjoint(M);
+    MatrixScale(M, 1 / Det);
+  end;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure MatrixTranspose(var M: TMatrix); register;
+
+// computes transpose of 4x4 matrix
+
+var I, J: Integer;
+    TM: TMatrix;
+
+begin
+  for I := 0 to 3 do
+    for J := 0 to 3 do TM[J, I] := M[I, J];
+  M := TM;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+procedure MatrixAffineTranspose(var M: TAffineMatrix); register;
+
+// computes transpose of 3x3 matrix
+
+var I, J: Integer;
+    TM: TAffineMatrix;
+
+begin
+  for I := 0 to 2 do
+    for J := 0 to 2 do TM[J, I] := M[I, J];
+  M := TM;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function MatrixMultiply(M1, M2: TMatrix): TMatrix; register;
+
+// multiplies two 4x4 matrices
+
+var I, J: Integer;
+    TM: TMatrix;
+
+begin
+  for I := 0 to 3 do
+    for J := 0 to 3 do
+      TM[I, J] := M1[I, X] * M2[X, J] +
+                  M1[I, Y] * M2[Y, J] +
+                  M1[I, Z] * M2[Z, J] +
+                  M1[I, W] * M2[W, J];
+  Result := TM;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function CreateRotationMatrix(Axis: TVector3f; Angle: Single): TMatrix; register;
+
+// Creates a rotation matrix along the given Axis by the given Angle in radians.
+
+var cosine,
+    sine,
+    Len,
+    one_minus_cosine: Extended;
+
+begin
+  SinCos(Angle, Sine, Cosine);
+  one_minus_cosine := 1 - cosine;
+  Len := VectorNormalize(Axis);
+
+  if Len = 0 then Result := IdentityMatrix
+             else
+  begin
+    Result[X, X] := (one_minus_cosine * Sqr(Axis[0])) + Cosine;
+    Result[X, Y] := (one_minus_cosine * Axis[0] * Axis[1]) - (Axis[2] * Sine);
+    Result[X, Z] := (one_minus_cosine * Axis[2] * Axis[0]) + (Axis[1] * Sine);
+    Result[X, W] := 0;
+
+    Result[Y, X] := (one_minus_cosine * Axis[0] * Axis[1]) + (Axis[2] * Sine);
+    Result[Y, Y] := (one_minus_cosine * Sqr(Axis[1])) + Cosine;
+    Result[Y, Z] := (one_minus_cosine * Axis[1] * Axis[2]) - (Axis[0] * Sine);
+    Result[Y, W] := 0;
+
+    Result[Z, X] := (one_minus_cosine * Axis[2] * Axis[0]) - (Axis[1] * Sine);
+    Result[Z, Y] := (one_minus_cosine * Axis[1] * Axis[2]) + (Axis[0] * Sine);
+    Result[Z, Z] := (one_minus_cosine * Sqr(Axis[2])) + Cosine;
+    Result[Z, W] := 0;
+
+    Result[W, X] := 0;
+    Result[W, Y] := 0;
+    Result[W, Z] := 0;
+    Result[W, W] := 1;
+  end;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function ConvertRotation(Angles: TAffineVector): TVector; register;
+
+{ Turn a triplet of rotations about x, y, and z (in that order) into an
+   equivalent rotation around a single axis (all in radians).
+
+   Rotation of the Angle t about the axis (X, Y, Z) is given by:
+
+     | X^2 + (1-X^2) Cos(t),    XY(1-Cos(t))  +  Z Sin(t), XZ(1-Cos(t))-Y Sin(t) |
+ M = | XY(1-Cos(t))-Z Sin(t), Y^2 + (1-Y^2) Cos(t),      YZ(1-Cos(t)) + X Sin(t) |
+     | XZ(1-Cos(t)) + Y Sin(t), YZ(1-Cos(t))-X Sin(t),   Z^2 + (1-Z^2) Cos(t)    |
+
+   Rotation about the three axes (Angles a1, a2, a3) can be represented as
+   the product of the individual rotation matrices:
+
+      | 1  0       0       | | Cos(a2) 0 -Sin(a2) | |  Cos(a3) Sin(a3) 0 |
+      | 0  Cos(a1) Sin(a1) | * | 0       1  0       | * | -Sin(a3) Cos(a3) 0 |
+      | 0 -Sin(a1) Cos(a1) | | Sin(a2) 0  Cos(a2) | |  0       0       1 |
+	     Mx                       My                     Mz
+
+   We now want to solve for X, Y, Z, and t given 9 equations in 4 unknowns.
+   Using the diagonal elements of the two matrices, we get:
+
+      X^2 + (1-X^2) Cos(t) = M[0][0]
+      Y^2 + (1-Y^2) Cos(t) = M[1][1]
+      Z^2 + (1-Z^2) Cos(t) = M[2][2]
+
+   Adding the three equations, we get:
+
+      X^2  +  Y^2  +  Z^2 - (M[0][0]  +  M[1][1]  +  M[2][2]) =
+	 - (3 - X^2 - Y^2 - Z^2) Cos(t)
+
+   Since (X^2  +  Y^2  +  Z^2) = 1, we can rewrite as:
+
+      Cos(t) = (1 - (M[0][0]  +  M[1][1]  +  M[2][2])) / 2
+
+   Solving for t, we get:
+
+      t = Acos(((M[0][0]  +  M[1][1]  +  M[2][2]) - 1) / 2)
+
+    We can substitute t into the equations for X^2, Y^2, and Z^2 above
+    to get the values for X, Y, and Z.  To find the proper signs we note
+    that:
+
+	2 X Sin(t) = M[1][2] - M[2][1]
+	2 Y Sin(t) = M[2][0] - M[0][2]
+	2 Z Sin(t) = M[0][1] - M[1][0]
+}
+
+var Axis1, Axis2: TVector3f;
+    M, M1, M2: TMatrix;
+    cost, cost1,
+    sint,
+    s1, s2, s3: Single;
+    I: Integer;
+
+
+begin
+  // see if we are only rotating about a single Axis
+  if Abs(Angles[X]) < EPSILON then
+  begin
+    if Abs(Angles[Y]) < EPSILON then
+    begin
+      Result := MakeVector([0, 0, 1, Angles[Z]]);
+      Exit;
+    end
+    else
+      if Abs(Angles[Z]) < EPSILON then
+      begin
+        Result := MakeVector([0, 1, 0, Angles[Y]]);
+        Exit;
+      end
+   end
+   else
+     if (Abs(Angles[Y]) < EPSILON) and
+        (Abs(Angles[Z]) < EPSILON) then
+     begin
+       Result := MakeVector([1, 0, 0, Angles[X]]);
+       Exit;
+     end;
+
+  // make the rotation matrix
+  Axis1 := MakeAffineVector([1, 0, 0]);
+  M := CreateRotationMatrix(Axis1, Angles[X]);
+
+  Axis2 := MakeAffineVector([0, 1, 0]);
+  M2 := CreateRotationMatrix(Axis2, Angles[Y]);
+  M1 := MatrixMultiply(M, M2);
+
+  Axis2 := MakeAffineVector([0, 0, 1]);
+  M2 := CreateRotationMatrix(Axis2, Angles[Z]);
+  M := MatrixMultiply(M1, M2);
+
+  cost := ((M[X, X] + M[Y, Y] + M[Z, Z])-1) / 2;
+  if cost < -1 then cost := -1
+               else
+    if cost > 1 - EPSILON then
+    begin
+      // Bad Angle - this would cause a crash
+      Result := MakeVector([1, 0, 0, 0]);
+      Exit;
+    end;
+
+  cost1 := 1 - cost;
+  Result := Makevector([Sqrt((M[X, X]-cost) / cost1),
+                      Sqrt((M[Y, Y]-cost) / cost1),
+                      sqrt((M[Z, Z]-cost) / cost1),
+                      arccos(cost)]);
+
+  sint := 2 * Sqrt(1 - cost * cost); // This is actually 2 Sin(t)
+
+  // Determine the proper signs
+  for I := 0 to 7 do
+  begin
+    if (I and 1) > 1 then s1 := -1 else s1 := 1;
+    if (I and 2) > 1 then s2 := -1 else s2 := 1;
+    if (I and 4) > 1 then s3 := -1 else s3 := 1;
+    if (Abs(s1 * Result[X] * sint-M[Y, Z] + M[Z, Y]) < EPSILON2) and
+       (Abs(s2 * Result[Y] * sint-M[Z, X] + M[X, Z]) < EPSILON2) and
+       (Abs(s3 * Result[Z] * sint-M[X, Y] + M[Y, X]) < EPSILON2) then
+        begin
+          // We found the right combination of signs
+          Result[X] := Result[X] * s1;
+          Result[Y] := Result[Y] * s2;
+          Result[Z] := Result[Z] * s3;
+          Exit;
+        end;
+  end;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function CreateRotationMatrixX(Sine, Cosine: Single): TMatrix; register;
+
+// creates matrix for rotation about x-axis
+
+begin
+  Result := EmptyMatrix;
+  Result[X, X] := 1;
+  Result[Y, Y] := Cosine;
+  Result[Y, Z] := Sine;
+  Result[Z, Y] := -Sine;
+  Result[Z, Z] := Cosine;
+  Result[W, W] := 1;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function CreateRotationMatrixY(Sine, Cosine: Single): TMatrix; register;
+
+// creates matrix for rotation about y-axis
+
+begin
+  Result := EmptyMatrix;
+  Result[X, X] := Cosine;
+  Result[X, Z] := -Sine;
+  Result[Y, Y] := 1;
+  Result[Z, X] := Sine;
+  Result[Z, Z] := Cosine;
+  Result[W, W] := 1;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function CreateRotationMatrixZ(Sine, Cosine: Single): TMatrix; register;
+
+// creates matrix for rotation about z-axis
+
+begin
+  Result := EmptyMatrix;
+  Result[X, X] := Cosine;
+  Result[X, Y] := Sine;
+  Result[Y, X] := -Sine;
+  Result[Y, Y] := Cosine;
+  Result[Z, Z] := 1;
+  Result[W, W] := 1;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function CreateScaleMatrix(V: TAffineVector): TMatrix; register;
+
+// creates scaling matrix
+
+begin
+  Result := IdentityMatrix;
+  Result[X, X] := V[X];
+  Result[Y, Y] := V[Y];
+  Result[Z, Z] := V[Z];
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function CreateTranslationMatrix(V: TVector): TMatrix; register;
+
+// creates translation matrix
+
+begin
+  Result := IdentityMatrix;
+  Result[W, X] := V[X];
+  Result[W, Y] := V[Y];
+  Result[W, Z] := V[Z];
+  Result[W, W] := V[W];
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function Lerp(Start, Stop, t: Single): Single;
+
+// calculates linear interpolation between start and stop at point t
+
+begin
+  Result := Start + (Stop - Start) * t;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAffineLerp(V1, V2: TAffineVector; t: Single): TAffineVector;
+
+// calculates linear interpolation between vector1 and vector2 at point t
+
+begin
+  Result[X] := Lerp(V1[X], V2[X], t);
+  Result[Y] := Lerp(V1[Y], V2[Y], t);
+  Result[Z] := Lerp(V1[Z], V2[Z], t);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorLerp(V1, V2: TVector; t: Single): TVector;
+
+// calculates linear interpolation between vector1 and vector2 at point t
+
+begin
+  Result[X] := Lerp(V1[X], V2[X], t);
+  Result[Y] := Lerp(V1[Y], V2[Y], t);
+  Result[Z] := Lerp(V1[Z], V2[Z], t);
+  Result[W] := Lerp(V1[W], V2[W], t);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function QuaternionSlerp(QStart, QEnd: TQuaternion; Spin: Integer; t: Single): TQuaternion;
+
+// spherical linear interpolation of unit quaternions with spins
+// QStart, QEnd - start and end unit quaternions
+// t            - interpolation parameter (0 to 1)
+// Spin         - number of extra spin rotations to involve
+
+var beta,                   // complementary interp parameter
+    theta,                  // Angle between A and B
+    sint, cost,             // sine, cosine of theta
+    phi: Single;            // theta plus spins
+    bflip: Boolean;         // use negativ t?
+
+
+begin
+  // cosine theta
+  cost := VectorAngle(QStart.ImagPart, QEnd.ImagPart);
+
+  // if QEnd is on opposite hemisphere from QStart, use -QEnd instead
+  if cost < 0 then
+  begin
+    cost := -cost;
+    bflip := True;
+  end
+  else bflip := False;
+
+  // if QEnd is (within precision limits) the same as QStart,
+  // just linear interpolate between QStart and QEnd.
+  // Can't do spins, since we don't know what direction to spin.
+
+  if (1 - cost) < EPSILON then beta := 1 - t
+                          else
+  begin
+    // normal case
+    theta := arccos(cost);
+    phi := theta + Spin * Pi;
+    sint := sin(theta);
+    beta := sin(theta - t * phi) / sint;
+    t := sin(t * phi) / sint;
+  end;
+
+  if bflip then t := -t;
+
+  // interpolate
+  Result.ImagPart[X] := beta * QStart.ImagPart[X] + t * QEnd.ImagPart[X];
+  Result.ImagPart[Y] := beta * QStart.ImagPart[Y] + t * QEnd.ImagPart[Y];
+  Result.ImagPart[Z] := beta * QStart.ImagPart[Z] + t * QEnd.ImagPart[Z];
+  Result.RealPart := beta * QStart.RealPart + t * QEnd.RealPart;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAffineCombine(V1, V2: TAffineVector; F1, F2: Single): TAffineVector;
+
+// makes a linear combination of two vectors and return the result
+
+begin
+  Result[X] := (F1 * V1[X]) + (F2 * V2[X]);
+  Result[Y] := (F1 * V1[Y]) + (F2 * V2[Y]);
+  Result[Z] := (F1 * V1[Z]) + (F2 * V2[Z]);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorCombine(V1, V2: TVector; F1, F2: Single): TVector;
+
+// makes a linear combination of two vectors and return the result
+
+begin
+  Result[X] := (F1 * V1[X]) + (F2 * V2[X]);
+  Result[Y] := (F1 * V1[Y]) + (F2 * V2[Y]);
+  Result[Z] := (F1 * V1[Z]) + (F2 * V2[Z]);
+  Result[W] := (F1 * V1[W]) + (F2 * V2[W]);
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function MatrixDecompose(M: TMatrix; var Tran: TTransformations): Boolean; register;
+
+// Author: Spencer W. Thomas, University of Michigan
+//
+// MatrixDecompose - Decompose a non-degenerated 4x4 transformation matrix into
+// the sequence of transformations that produced it.
+//
+// The coefficient of each transformation is returned in the corresponding
+// element of the vector Tran.
+//
+// Returns true upon success, false if the matrix is singular.
+
+var I, J: Integer;
+    LocMat,
+    pmat,
+    invpmat,
+    tinvpmat: TMatrix;
+    prhs,
+    psol: TVector;
+    Row: array[0..2] of TAffineVector;
+
+begin
+  Result := False;
+  locmat := M;
+  // normalize the matrix
+  if locmat[W, W] = 0 then Exit;
+  for I := 0 to 3 do
+    for J := 0 to 3 do
+      locmat[I, J] := locmat[I, J] / locmat[W, W];
+
+  // pmat is used to solve for perspective, but it also provides
+  // an easy way to test for singularity of the upper 3x3 component.
+
+  pmat := locmat;
+  for I := 0 to 2 do pmat[I, W] := 0;
+  pmat[W, W] := 1;
+
+  if MatrixDeterminant(pmat) = 0 then Exit;
+
+  // First, isolate perspective.  This is the messiest.
+  if (locmat[X, W] <> 0) or
+     (locmat[Y, W] <> 0) or
+     (locmat[Z, W] <> 0) then
+  begin
+    // prhs is the right hand side of the equation.
+    prhs[X] := locmat[X, W];
+    prhs[Y] := locmat[Y, W];
+    prhs[Z] := locmat[Z, W];
+    prhs[W] := locmat[W, W];
+
+    // Solve the equation by inverting pmat and multiplying
+    // prhs by the inverse.  (This is the easiest way, not
+    // necessarily the best.)
+
+    invpmat := pmat;
+    MatrixInvert(invpmat);
+    MatrixTranspose(invpmat);
+    psol := VectorTransform(prhs, tinvpmat);
+
+    // stuff the answer away
+    Tran[ttPerspectiveX] := psol[X];
+    Tran[ttPerspectiveY] := psol[Y];
+    Tran[ttPerspectiveZ] := psol[Z];
+    Tran[ttPerspectiveW] := psol[W];
+
+    // clear the perspective partition
+    locmat[X, W] := 0;
+    locmat[Y, W] := 0;
+    locmat[Z, W] := 0;
+    locmat[W, W] := 1;
+  end
+  else
+  begin
+    // no perspective
+    Tran[ttPerspectiveX] := 0;
+    Tran[ttPerspectiveY] := 0;
+    Tran[ttPerspectiveZ] := 0;
+    Tran[ttPerspectiveW] := 0;
+  end;
+
+  // next take care of translation (easy)
+  for I := 0 to 2 do
+  begin
+    Tran[TTransType(Ord(ttTranslateX) + I)] := locmat[W, I];
+    locmat[W, I] := 0;
+  end;
+
+  // now get scale and shear
+  for I := 0 to 2 do
+  begin
+    row[I, X] := locmat[I, X];
+    row[I, Y] := locmat[I, Y];
+    row[I, Z] := locmat[I, Z];
+  end;
+
+  // compute X scale factor and normalize first row
+  Tran[ttScaleX] := Sqr(VectorNormalize(row[0])); // ml: calculation optimized
+
+  // compute XY shear factor and make 2nd row orthogonal to 1st
+  Tran[ttShearXY] := VectorAffineDotProduct(row[0], row[1]);
+  row[1] := VectorAffineCombine(row[1], row[0], 1, -Tran[ttShearXY]);
+
+  // now, compute Y scale and normalize 2nd row
+  Tran[ttScaleY] := Sqr(VectorNormalize(row[1])); // ml: calculation optimized
+  Tran[ttShearXY] := Tran[ttShearXY]/Tran[ttScaleY];
+
+  // compute XZ and YZ shears, orthogonalize 3rd row
+  Tran[ttShearXZ] := VectorAffineDotProduct(row[0], row[2]);
+  row[2] := VectorAffineCombine(row[2], row[0], 1, -Tran[ttShearXZ]);
+  Tran[ttShearYZ] := VectorAffineDotProduct(row[1], row[2]);
+  row[2] := VectorAffineCombine(row[2], row[1], 1, -Tran[ttShearYZ]);
+
+  // next, get Z scale and normalize 3rd row
+  Tran[ttScaleZ] := Sqr(VectorNormalize(row[1])); // (ML) calc. optimized
+  Tran[ttShearXZ] := Tran[ttShearXZ] / tran[ttScaleZ];
+  Tran[ttShearYZ] := Tran[ttShearYZ] / Tran[ttScaleZ];
+
+  // At this point, the matrix (in rows[]) is orthonormal.
+  // Check for a coordinate system flip.  If the determinant
+  // is -1, then negate the matrix and the scaling factors.
+  if VectorAffineDotProduct(row[0], VectorCrossProduct(row[1], row[2])) < 0 then
+    for I := 0 to 2 do
+    begin
+      Tran[TTransType(Ord(ttScaleX) + I)] := -Tran[TTransType(Ord(ttScaleX) + I)];
+      row[I, X] := -row[I, X];
+      row[I, Y] := -row[I, Y];
+      row[I, Z] := -row[I, Z];
+    end;
+
+  // now, get the rotations out, as described in the gem
+  Tran[ttRotateY] := arcsin(-row[0, Z]);
+  if cos(Tran[ttRotateY]) <> 0 then
+  begin
+    Tran[ttRotateX] := arctan2(row[1, Z], row[2, Z]);
+    Tran[ttRotateZ] := arctan2(row[0, Y], row[0, X]);
+  end
+  else
+  begin
+    tran[ttRotateX] := arctan2(row[1, X], row[1, Y]);
+    tran[ttRotateZ] := 0;
+  end;
+  // All done!
+  Result := True;
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorDblToFlt(V: THomogeneousDblVector): THomogeneousVector; assembler;
+
+// converts a vector containing double sized values into a vector with single sized values
+
+asm
+              FLD  QWORD PTR [EAX]
+              FSTP DWORD PTR [EDX]
+              FLD  QWORD PTR [EAX + 8]
+              FSTP DWORD PTR [EDX + 4]
+              FLD  QWORD PTR [EAX + 16]
+              FSTP DWORD PTR [EDX + 8]
+              FLD  QWORD PTR [EAX + 24]
+              FSTP DWORD PTR [EDX + 12]
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAffineDblToFlt(V: TAffineDblVector): TAffineVector; assembler;
+
+// converts a vector containing double sized values into a vector with single sized values
+
+asm
+              FLD  QWORD PTR [EAX]
+              FSTP DWORD PTR [EDX]
+              FLD  QWORD PTR [EAX + 8]
+              FSTP DWORD PTR [EDX + 4]
+              FLD  QWORD PTR [EAX + 16]
+              FSTP DWORD PTR [EDX + 8]
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorAffineFltToDbl(V: TAffineVector): TAffineDblVector; assembler;
+
+// converts a vector containing single sized values into a vector with double sized values
+
+asm
+              FLD  DWORD PTR [EAX]
+              FSTP QWORD PTR [EDX]
+              FLD  DWORD PTR [EAX + 8]
+              FSTP QWORD PTR [EDX + 4]
+              FLD  DWORD PTR [EAX + 16]
+              FSTP QWORD PTR [EDX + 8]
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function VectorFltToDbl(V: TVector): THomogeneousDblVector; assembler;
+
+// converts a vector containing single sized values into a vector with double sized values
+
+asm
+              FLD  DWORD PTR [EAX]
+              FSTP QWORD PTR [EDX]
+              FLD  DWORD PTR [EAX + 8]
+              FSTP QWORD PTR [EDX + 4]
+              FLD  DWORD PTR [EAX + 16]
+              FSTP QWORD PTR [EDX + 8]
+              FLD  DWORD PTR [EAX + 24]
+              FSTP QWORD PTR [EDX + 12]
+end;
+
+//----------------- coordinate system manipulation functions -----------------------------------------------------------
+
+function Turn(Matrix: TMatrix; Angle: Single): TMatrix;
+
+// rotates the given coordinate system (represented by the matrix) around its Y-axis
+
+begin
+  Result := MatrixMultiply(Matrix, CreateRotationMatrix(MakeAffineVector(Matrix[1]), Angle));
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function Turn(Matrix: TMatrix; MasterUp: TAffineVector; Angle: Single): TMatrix;
+
+// rotates the given coordinate system (represented by the matrix) around MasterUp
+
+begin
+  Result := MatrixMultiply(Matrix, CreateRotationMatrix(MasterUp, Angle));
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function Pitch(Matrix: TMatrix; Angle: Single): TMatrix;
+
+// rotates the given coordinate system (represented by the matrix) around its X-axis
+
+begin
+  Result := MatrixMultiply(Matrix, CreateRotationMatrix(MakeAffineVector(Matrix[0]), Angle));
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function Pitch(Matrix: TMatrix; MasterRight: TAffineVector; Angle: Single): TMatrix; overload;
+
+// rotates the given coordinate system (represented by the matrix) around MasterRight
+
+begin
+  Result := MatrixMultiply(Matrix, CreateRotationMatrix(MasterRight, Angle));
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function Roll(Matrix: TMatrix; Angle: Single): TMatrix;
+
+// rotates the given coordinate system (represented by the matrix) around its Z-axis
+
+begin
+  Result := MatrixMultiply(Matrix, CreateRotationMatrix(MakeAffineVector(Matrix[2]), Angle));
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+function Roll(Matrix: TMatrix; MasterDirection: TAffineVector; Angle: Single): TMatrix; overload;
+
+// rotates the given coordinate system (represented by the matrix) around MasterDirection
+
+begin
+  Result := MatrixMultiply(Matrix, CreateRotationMatrix(MasterDirection, Angle));
+end;
+
+//----------------------------------------------------------------------------------------------------------------------
+
+end.
+
+
diff --git a/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas
new file mode 100644
index 00000000..d1231cdd
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas
@@ -0,0 +1,2301 @@
+unit gl;
+{
+  $Id: gl.pas,v 1.5 2007/05/20 20:28:31 savage Exp $
+
+  Adaption of the delphi3d.net OpenGL units to FreePascal
+  Sebastian Guenther (sg@freepascal.org) in 2002
+  These units are free to use
+}
+
+(*++ BUILD Version: 0004    // Increment this if a change has global effects
+
+Copyright (c) 1985-96, Microsoft Corporation
+
+Module Name:
+
+    gl.h
+
+Abstract:
+
+    Procedure declarations, constant definitions and macros for the OpenGL
+    component.
+
+--*)
+
+(*
+** Copyright 1996 Silicon Graphics, Inc.
+** All Rights Reserved.
+**
+** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
+** the contents of this file may not be disclosed to third parties, copied or
+** duplicated in any form, in whole or in part, without the prior written
+** permission of Silicon Graphics, Inc.
+**
+** RESTRICTED RIGHTS LEGEND:
+** Use, duplication or disclosure by the Government is subject to restrictions
+** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
+** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
+** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
+** rights reserved under the Copyright Laws of the United States.
+*)
+
+{******************************************************************************}
+{                                                                              }
+{ Converted to Delphi by Tom Nuydens (tom@delphi3d.net)                        }
+{ For the latest updates, visit Delphi3D: http://www.delphi3d.net              }
+{                                                                              }
+{ Modified for Delphi/Kylix and FreePascal                                     }
+{    by Dominique Louis ( Dominique@Savagesoftware.com.au)                     }
+{ For the latest updates, visit JEDI-SDL : http://www.sf.net/projects/jedi-sdl }
+{                                                                              }
+{******************************************************************************}
+
+{
+  $Log: gl.pas,v $
+  Revision 1.5  2007/05/20 20:28:31  savage
+  Initial Changes to Handle 64 Bits
+
+  Revision 1.4  2006/11/20 21:20:59  savage
+  Updated to work in MacOS X
+
+  Revision 1.3  2005/05/22 18:52:09  savage
+  Changes as suggested by Michalis Kamburelis. Thanks again.
+
+  Revision 1.2  2004/08/14 22:54:30  savage
+  Updated so that Library name defines are correctly defined for MacOS X.
+
+  Revision 1.1  2004/03/30 21:53:54  savage
+  Moved to it's own folder.
+
+  Revision 1.4  2004/02/20 17:09:55  savage
+  Code tidied up in gl, glu and glut, while extensions in glext.pas are now loaded using SDL_GL_GetProcAddress, thus making it more cross-platform compatible, but now more tied to SDL.
+
+  Revision 1.3  2004/02/14 00:23:39  savage
+  As UNIX is defined in jedi-sdl.inc this will be used to check linux compatability as well. Units have been changed to reflect this change.
+
+  Revision 1.2  2004/02/14 00:09:18  savage
+  Changed uses to now make use of moduleloader.pas rather than dllfuncs.pas
+
+  Revision 1.1  2004/02/05 00:08:19  savage
+  Module 1.0 release
+
+  Revision 1.6  2003/06/02 12:32:12  savage
+  Modified Sources to avoid warnings with Delphi by moving CVS Logging to the top of the header files. Hopefully CVS Logging still works.
+
+}
+
+interface
+
+{$I jedi-sdl.inc}
+
+uses
+{$IFDEF __GPC__}
+  system,
+  gpc,
+{$ENDIF}
+
+{$IFDEF WINDOWS}
+  Windows,
+{$ENDIF}
+  moduleloader;
+
+
+var
+  LibGL: TModuleHandle;
+
+type
+  GLenum     = Cardinal;      PGLenum     = ^GLenum;
+  GLboolean  = Byte;          PGLboolean  = ^GLboolean;
+  GLbitfield = Cardinal;      PGLbitfield = ^GLbitfield;
+  GLbyte     = ShortInt;      PGLbyte     = ^GLbyte;
+  GLshort    = SmallInt;      PGLshort    = ^GLshort;
+  GLint      = Integer;       PGLint      = ^GLint;
+  GLsizei    = Integer;       PGLsizei    = ^GLsizei;
+  GLubyte    = Byte;          PGLubyte    = ^GLubyte;
+  GLushort   = Word;          PGLushort   = ^GLushort;
+  GLuint     = Cardinal;      PGLuint     = ^GLuint;
+  GLfloat    = Single;        PGLfloat    = ^GLfloat;
+  GLclampf   = Single;        PGLclampf   = ^GLclampf;
+  GLdouble   = Double;        PGLdouble   = ^GLdouble;
+  GLclampd   = Double;        PGLclampd   = ^GLclampd;
+{ GLvoid     = void; }        PGLvoid     = Pointer;
+
+{******************************************************************************}
+
+const
+{$IFDEF WINDOWS}
+  GLLibName = 'OpenGL32.dll';
+{$ENDIF}
+
+{$IFDEF UNIX}
+{$IFDEF DARWIN}
+  GLLibName = '/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib';
+{$ELSE}
+  GLLibName = 'libGL.so.1';
+{$ENDIF}
+{$ENDIF}
+
+  // Version
+  GL_VERSION_1_1                    = 1;
+
+  // AccumOp
+  GL_ACCUM                          = $0100;
+  GL_LOAD                           = $0101;
+  GL_RETURN                         = $0102;
+  GL_MULT                           = $0103;
+  GL_ADD                            = $0104;
+
+  // AlphaFunction
+  GL_NEVER                          = $0200;
+  GL_LESS                           = $0201;
+  GL_EQUAL                          = $0202;
+  GL_LEQUAL                         = $0203;
+  GL_GREATER                        = $0204;
+  GL_NOTEQUAL                       = $0205;
+  GL_GEQUAL                         = $0206;
+  GL_ALWAYS                         = $0207;
+
+  // AttribMask
+  GL_CURRENT_BIT                    = $00000001;
+  GL_POINT_BIT                      = $00000002;
+  GL_LINE_BIT                       = $00000004;
+  GL_POLYGON_BIT                    = $00000008;
+  GL_POLYGON_STIPPLE_BIT            = $00000010;
+  GL_PIXEL_MODE_BIT                 = $00000020;
+  GL_LIGHTING_BIT                   = $00000040;
+  GL_FOG_BIT                        = $00000080;
+  GL_DEPTH_BUFFER_BIT               = $00000100;
+  GL_ACCUM_BUFFER_BIT               = $00000200;
+  GL_STENCIL_BUFFER_BIT             = $00000400;
+  GL_VIEWPORT_BIT                   = $00000800;
+  GL_TRANSFORM_BIT                  = $00001000;
+  GL_ENABLE_BIT                     = $00002000;
+  GL_COLOR_BUFFER_BIT               = $00004000;
+  GL_HINT_BIT                       = $00008000;
+  GL_EVAL_BIT                       = $00010000;
+  GL_LIST_BIT                       = $00020000;
+  GL_TEXTURE_BIT                    = $00040000;
+  GL_SCISSOR_BIT                    = $00080000;
+  GL_ALL_ATTRIB_BITS                = $000FFFFF;
+
+  // BeginMode
+  GL_POINTS                         = $0000;
+  GL_LINES                          = $0001;
+  GL_LINE_LOOP                      = $0002;
+  GL_LINE_STRIP                     = $0003;
+  GL_TRIANGLES                      = $0004;
+  GL_TRIANGLE_STRIP                 = $0005;
+  GL_TRIANGLE_FAN                   = $0006;
+  GL_QUADS                          = $0007;
+  GL_QUAD_STRIP                     = $0008;
+  GL_POLYGON                        = $0009;
+
+  // BlendingFactorDest
+  GL_ZERO                           = 0;
+  GL_ONE                            = 1;
+  GL_SRC_COLOR                      = $0300;
+  GL_ONE_MINUS_SRC_COLOR            = $0301;
+  GL_SRC_ALPHA                      = $0302;
+  GL_ONE_MINUS_SRC_ALPHA            = $0303;
+  GL_DST_ALPHA                      = $0304;
+  GL_ONE_MINUS_DST_ALPHA            = $0305;
+
+  // BlendingFactorSrc
+  //      GL_ZERO
+  //      GL_ONE
+  GL_DST_COLOR                      = $0306;
+  GL_ONE_MINUS_DST_COLOR            = $0307;
+  GL_SRC_ALPHA_SATURATE             = $0308;
+  //      GL_SRC_ALPHA
+  //      GL_ONE_MINUS_SRC_ALPHA
+  //      GL_DST_ALPHA
+  //      GL_ONE_MINUS_DST_ALPHA
+
+  // Boolean
+  GL_TRUE                           = 1;
+  GL_FALSE                          = 0;
+
+  // ClearBufferMask
+  //      GL_COLOR_BUFFER_BIT
+  //      GL_ACCUM_BUFFER_BIT
+  //      GL_STENCIL_BUFFER_BIT
+  //      GL_DEPTH_BUFFER_BIT
+
+  // ClientArrayType
+  //      GL_VERTEX_ARRAY
+  //      GL_NORMAL_ARRAY
+  //      GL_COLOR_ARRAY
+  //      GL_INDEX_ARRAY
+  //      GL_TEXTURE_COORD_ARRAY
+  //      GL_EDGE_FLAG_ARRAY
+
+  // ClipPlaneName
+  GL_CLIP_PLANE0                    = $3000;
+  GL_CLIP_PLANE1                    = $3001;
+  GL_CLIP_PLANE2                    = $3002;
+  GL_CLIP_PLANE3                    = $3003;
+  GL_CLIP_PLANE4                    = $3004;
+  GL_CLIP_PLANE5                    = $3005;
+
+  // ColorMaterialFace
+  //      GL_FRONT
+  //      GL_BACK
+  //      GL_FRONT_AND_BACK
+
+  // ColorMaterialParameter
+  //      GL_AMBIENT
+  //      GL_DIFFUSE
+  //      GL_SPECULAR
+  //      GL_EMISSION
+  //      GL_AMBIENT_AND_DIFFUSE
+
+  // ColorPointerType
+  //      GL_BYTE
+  //      GL_UNSIGNED_BYTE
+  //      GL_SHORT
+  //      GL_UNSIGNED_SHORT
+  //      GL_INT
+  //      GL_UNSIGNED_INT
+  //      GL_FLOAT
+  //      GL_DOUBLE
+
+  // CullFaceMode
+  //      GL_FRONT
+  //      GL_BACK
+  //      GL_FRONT_AND_BACK
+
+  // DataType
+  GL_BYTE                           = $1400;
+  GL_UNSIGNED_BYTE                  = $1401;
+  GL_SHORT                          = $1402;
+  GL_UNSIGNED_SHORT                 = $1403;
+  GL_INT                            = $1404;
+  GL_UNSIGNED_INT                   = $1405;
+  GL_FLOAT                          = $1406;
+  GL_2_BYTES                        = $1407;
+  GL_3_BYTES                        = $1408;
+  GL_4_BYTES                        = $1409;
+  GL_DOUBLE                         = $140A;
+
+  // DepthFunction
+  //      GL_NEVER
+  //      GL_LESS
+  //      GL_EQUAL
+  //      GL_LEQUAL
+  //      GL_GREATER
+  //      GL_NOTEQUAL
+  //      GL_GEQUAL
+  //      GL_ALWAYS
+
+  // DrawBufferMode
+  GL_NONE                           = 0;
+  GL_FRONT_LEFT                     = $0400;
+  GL_FRONT_RIGHT                    = $0401;
+  GL_BACK_LEFT                      = $0402;
+  GL_BACK_RIGHT                     = $0403;
+  GL_FRONT                          = $0404;
+  GL_BACK                           = $0405;
+  GL_LEFT                           = $0406;
+  GL_RIGHT                          = $0407;
+  GL_FRONT_AND_BACK                 = $0408;
+  GL_AUX0                           = $0409;
+  GL_AUX1                           = $040A;
+  GL_AUX2                           = $040B;
+  GL_AUX3                           = $040C;
+
+  // Enable
+  //      GL_FOG
+  //      GL_LIGHTING
+  //      GL_TEXTURE_1D
+  //      GL_TEXTURE_2D
+  //      GL_LINE_STIPPLE
+  //      GL_POLYGON_STIPPLE
+  //      GL_CULL_FACE
+  //      GL_ALPHA_TEST
+  //      GL_BLEND
+  //      GL_INDEX_LOGIC_OP
+  //      GL_COLOR_LOGIC_OP
+  //      GL_DITHER
+  //      GL_STENCIL_TEST
+  //      GL_DEPTH_TEST
+  //      GL_CLIP_PLANE0
+  //      GL_CLIP_PLANE1
+  //      GL_CLIP_PLANE2
+  //      GL_CLIP_PLANE3
+  //      GL_CLIP_PLANE4
+  //      GL_CLIP_PLANE5
+  //      GL_LIGHT0
+  //      GL_LIGHT1
+  //      GL_LIGHT2
+  //      GL_LIGHT3
+  //      GL_LIGHT4
+  //      GL_LIGHT5
+  //      GL_LIGHT6
+  //      GL_LIGHT7
+  //      GL_TEXTURE_GEN_S
+  //      GL_TEXTURE_GEN_T
+  //      GL_TEXTURE_GEN_R
+  //      GL_TEXTURE_GEN_Q
+  //      GL_MAP1_VERTEX_3
+  //      GL_MAP1_VERTEX_4
+  //      GL_MAP1_COLOR_4
+  //      GL_MAP1_INDEX
+  //      GL_MAP1_NORMAL
+  //      GL_MAP1_TEXTURE_COORD_1
+  //      GL_MAP1_TEXTURE_COORD_2
+  //      GL_MAP1_TEXTURE_COORD_3
+  //      GL_MAP1_TEXTURE_COORD_4
+  //      GL_MAP2_VERTEX_3
+  //      GL_MAP2_VERTEX_4
+  //      GL_MAP2_COLOR_4
+  //      GL_MAP2_INDEX
+  //      GL_MAP2_NORMAL
+  //      GL_MAP2_TEXTURE_COORD_1
+  //      GL_MAP2_TEXTURE_COORD_2
+  //      GL_MAP2_TEXTURE_COORD_3
+  //      GL_MAP2_TEXTURE_COORD_4
+  //      GL_POINT_SMOOTH
+  //      GL_LINE_SMOOTH
+  //      GL_POLYGON_SMOOTH
+  //      GL_SCISSOR_TEST
+  //      GL_COLOR_MATERIAL
+  //      GL_NORMALIZE
+  //      GL_AUTO_NORMAL
+  //      GL_VERTEX_ARRAY
+  //      GL_NORMAL_ARRAY
+  //      GL_COLOR_ARRAY
+  //      GL_INDEX_ARRAY
+  //      GL_TEXTURE_COORD_ARRAY
+  //      GL_EDGE_FLAG_ARRAY
+  //      GL_POLYGON_OFFSET_POINT
+  //      GL_POLYGON_OFFSET_LINE
+  //      GL_POLYGON_OFFSET_FILL
+
+  // ErrorCode
+  GL_NO_ERROR                       = 0;
+  GL_INVALID_ENUM                   = $0500;
+  GL_INVALID_VALUE                  = $0501;
+  GL_INVALID_OPERATION              = $0502;
+  GL_STACK_OVERFLOW                 = $0503;
+  GL_STACK_UNDERFLOW                = $0504;
+  GL_OUT_OF_MEMORY                  = $0505;
+
+  // FeedBackMode
+  GL_2D                             = $0600;
+  GL_3D                             = $0601;
+  GL_3D_COLOR                       = $0602;
+  GL_3D_COLOR_TEXTURE               = $0603;
+  GL_4D_COLOR_TEXTURE               = $0604;
+
+  // FeedBackToken
+  GL_PASS_THROUGH_TOKEN             = $0700;
+  GL_POINT_TOKEN                    = $0701;
+  GL_LINE_TOKEN                     = $0702;
+  GL_POLYGON_TOKEN                  = $0703;
+  GL_BITMAP_TOKEN                   = $0704;
+  GL_DRAW_PIXEL_TOKEN               = $0705;
+  GL_COPY_PIXEL_TOKEN               = $0706;
+  GL_LINE_RESET_TOKEN               = $0707;
+
+  // FogMode
+  //      GL_LINEAR
+  GL_EXP                            = $0800;
+  GL_EXP2                           = $0801;
+
+  // FogParameter
+  //      GL_FOG_COLOR
+  //      GL_FOG_DENSITY
+  //      GL_FOG_END
+  //      GL_FOG_INDEX
+  //      GL_FOG_MODE
+  //      GL_FOG_START
+
+  // FrontFaceDirection
+  GL_CW                             = $0900;
+  GL_CCW                            = $0901;
+
+  // GetMapTarget
+  GL_COEFF                          = $0A00;
+  GL_ORDER                          = $0A01;
+  GL_DOMAIN                         = $0A02;
+
+  // GetPixelMap
+  //      GL_PIXEL_MAP_I_TO_I 
+  //      GL_PIXEL_MAP_S_TO_S 
+  //      GL_PIXEL_MAP_I_TO_R 
+  //      GL_PIXEL_MAP_I_TO_G 
+  //      GL_PIXEL_MAP_I_TO_B 
+  //      GL_PIXEL_MAP_I_TO_A
+  //      GL_PIXEL_MAP_R_TO_R
+  //      GL_PIXEL_MAP_G_TO_G 
+  //      GL_PIXEL_MAP_B_TO_B 
+  //      GL_PIXEL_MAP_A_TO_A 
+
+  // GetPointerTarget 
+  //      GL_VERTEX_ARRAY_POINTER 
+  //      GL_NORMAL_ARRAY_POINTER 
+  //      GL_COLOR_ARRAY_POINTER 
+  //      GL_INDEX_ARRAY_POINTER 
+  //      GL_TEXTURE_COORD_ARRAY_POINTER 
+  //      GL_EDGE_FLAG_ARRAY_POINTER 
+
+  // GetTarget 
+  GL_CURRENT_COLOR                  = $0B00;
+  GL_CURRENT_INDEX                  = $0B01;
+  GL_CURRENT_NORMAL                 = $0B02;
+  GL_CURRENT_TEXTURE_COORDS         = $0B03;
+  GL_CURRENT_RASTER_COLOR           = $0B04;
+  GL_CURRENT_RASTER_INDEX           = $0B05;
+  GL_CURRENT_RASTER_TEXTURE_COORDS  = $0B06;
+  GL_CURRENT_RASTER_POSITION        = $0B07;
+  GL_CURRENT_RASTER_POSITION_VALID  = $0B08;
+  GL_CURRENT_RASTER_DISTANCE        = $0B09;
+  GL_POINT_SMOOTH                   = $0B10;
+  GL_POINT_SIZE                     = $0B11;
+  GL_POINT_SIZE_RANGE               = $0B12;
+  GL_POINT_SIZE_GRANULARITY         = $0B13;
+  GL_LINE_SMOOTH                    = $0B20;
+  GL_LINE_WIDTH                     = $0B21;
+  GL_LINE_WIDTH_RANGE               = $0B22;
+  GL_LINE_WIDTH_GRANULARITY         = $0B23;
+  GL_LINE_STIPPLE                   = $0B24;
+  GL_LINE_STIPPLE_PATTERN           = $0B25;
+  GL_LINE_STIPPLE_REPEAT            = $0B26;
+  GL_LIST_MODE                      = $0B30;
+  GL_MAX_LIST_NESTING               = $0B31;
+  GL_LIST_BASE                      = $0B32;
+  GL_LIST_INDEX                     = $0B33;
+  GL_POLYGON_MODE                   = $0B40;
+  GL_POLYGON_SMOOTH                 = $0B41;
+  GL_POLYGON_STIPPLE                = $0B42;
+  GL_EDGE_FLAG                      = $0B43;
+  GL_CULL_FACE                      = $0B44;
+  GL_CULL_FACE_MODE                 = $0B45;
+  GL_FRONT_FACE                     = $0B46;
+  GL_LIGHTING                       = $0B50;
+  GL_LIGHT_MODEL_LOCAL_VIEWER       = $0B51;
+  GL_LIGHT_MODEL_TWO_SIDE           = $0B52;
+  GL_LIGHT_MODEL_AMBIENT            = $0B53;
+  GL_SHADE_MODEL                    = $0B54;
+  GL_COLOR_MATERIAL_FACE            = $0B55;
+  GL_COLOR_MATERIAL_PARAMETER       = $0B56;
+  GL_COLOR_MATERIAL                 = $0B57;
+  GL_FOG                            = $0B60;
+  GL_FOG_INDEX                      = $0B61;
+  GL_FOG_DENSITY                    = $0B62;
+  GL_FOG_START                      = $0B63;
+  GL_FOG_END                        = $0B64;
+  GL_FOG_MODE                       = $0B65;
+  GL_FOG_COLOR                      = $0B66;
+  GL_DEPTH_RANGE                    = $0B70;
+  GL_DEPTH_TEST                     = $0B71;
+  GL_DEPTH_WRITEMASK                = $0B72;
+  GL_DEPTH_CLEAR_VALUE              = $0B73;
+  GL_DEPTH_FUNC                     = $0B74;
+  GL_ACCUM_CLEAR_VALUE              = $0B80;
+  GL_STENCIL_TEST                   = $0B90;
+  GL_STENCIL_CLEAR_VALUE            = $0B91;
+  GL_STENCIL_FUNC                   = $0B92;
+  GL_STENCIL_VALUE_MASK             = $0B93;
+  GL_STENCIL_FAIL                   = $0B94;
+  GL_STENCIL_PASS_DEPTH_FAIL        = $0B95;
+  GL_STENCIL_PASS_DEPTH_PASS        = $0B96;
+  GL_STENCIL_REF                    = $0B97;
+  GL_STENCIL_WRITEMASK              = $0B98;
+  GL_MATRIX_MODE                    = $0BA0;
+  GL_NORMALIZE                      = $0BA1;
+  GL_VIEWPORT                       = $0BA2;
+  GL_MODELVIEW_STACK_DEPTH          = $0BA3;
+  GL_PROJECTION_STACK_DEPTH         = $0BA4;
+  GL_TEXTURE_STACK_DEPTH            = $0BA5;
+  GL_MODELVIEW_MATRIX               = $0BA6;
+  GL_PROJECTION_MATRIX              = $0BA7;
+  GL_TEXTURE_MATRIX                 = $0BA8;
+  GL_ATTRIB_STACK_DEPTH             = $0BB0;
+  GL_CLIENT_ATTRIB_STACK_DEPTH      = $0BB1;
+  GL_ALPHA_TEST                     = $0BC0;
+  GL_ALPHA_TEST_FUNC                = $0BC1;
+  GL_ALPHA_TEST_REF                 = $0BC2;
+  GL_DITHER                         = $0BD0;
+  GL_BLEND_DST                      = $0BE0;
+  GL_BLEND_SRC                      = $0BE1;
+  GL_BLEND                          = $0BE2;
+  GL_LOGIC_OP_MODE                  = $0BF0;
+  GL_INDEX_LOGIC_OP                 = $0BF1;
+  GL_COLOR_LOGIC_OP                 = $0BF2;
+  GL_AUX_BUFFERS                    = $0C00;
+  GL_DRAW_BUFFER                    = $0C01;
+  GL_READ_BUFFER                    = $0C02;
+  GL_SCISSOR_BOX                    = $0C10;
+  GL_SCISSOR_TEST                   = $0C11;
+  GL_INDEX_CLEAR_VALUE              = $0C20;
+  GL_INDEX_WRITEMASK                = $0C21;
+  GL_COLOR_CLEAR_VALUE              = $0C22;
+  GL_COLOR_WRITEMASK                = $0C23;
+  GL_INDEX_MODE                     = $0C30;
+  GL_RGBA_MODE                      = $0C31;
+  GL_DOUBLEBUFFER                   = $0C32;
+  GL_STEREO                         = $0C33;
+  GL_RENDER_MODE                    = $0C40;
+  GL_PERSPECTIVE_CORRECTION_HINT    = $0C50;
+  GL_POINT_SMOOTH_HINT              = $0C51;
+  GL_LINE_SMOOTH_HINT               = $0C52;
+  GL_POLYGON_SMOOTH_HINT            = $0C53;
+  GL_FOG_HINT                       = $0C54;
+  GL_TEXTURE_GEN_S                  = $0C60;
+  GL_TEXTURE_GEN_T                  = $0C61;
+  GL_TEXTURE_GEN_R                  = $0C62;
+  GL_TEXTURE_GEN_Q                  = $0C63;
+  GL_PIXEL_MAP_I_TO_I               = $0C70;
+  GL_PIXEL_MAP_S_TO_S               = $0C71;
+  GL_PIXEL_MAP_I_TO_R               = $0C72;
+  GL_PIXEL_MAP_I_TO_G               = $0C73;
+  GL_PIXEL_MAP_I_TO_B               = $0C74;
+  GL_PIXEL_MAP_I_TO_A               = $0C75;
+  GL_PIXEL_MAP_R_TO_R               = $0C76;
+  GL_PIXEL_MAP_G_TO_G               = $0C77;
+  GL_PIXEL_MAP_B_TO_B               = $0C78;
+  GL_PIXEL_MAP_A_TO_A               = $0C79;
+  GL_PIXEL_MAP_I_TO_I_SIZE          = $0CB0;
+  GL_PIXEL_MAP_S_TO_S_SIZE          = $0CB1;
+  GL_PIXEL_MAP_I_TO_R_SIZE          = $0CB2;
+  GL_PIXEL_MAP_I_TO_G_SIZE          = $0CB3;
+  GL_PIXEL_MAP_I_TO_B_SIZE          = $0CB4;
+  GL_PIXEL_MAP_I_TO_A_SIZE          = $0CB5;
+  GL_PIXEL_MAP_R_TO_R_SIZE          = $0CB6;
+  GL_PIXEL_MAP_G_TO_G_SIZE          = $0CB7;
+  GL_PIXEL_MAP_B_TO_B_SIZE          = $0CB8;
+  GL_PIXEL_MAP_A_TO_A_SIZE          = $0CB9;
+  GL_UNPACK_SWAP_BYTES              = $0CF0;
+  GL_UNPACK_LSB_FIRST               = $0CF1;
+  GL_UNPACK_ROW_LENGTH              = $0CF2;
+  GL_UNPACK_SKIP_ROWS               = $0CF3;
+  GL_UNPACK_SKIP_PIXELS             = $0CF4;
+  GL_UNPACK_ALIGNMENT               = $0CF5;
+  GL_PACK_SWAP_BYTES                = $0D00;
+  GL_PACK_LSB_FIRST                 = $0D01;
+  GL_PACK_ROW_LENGTH                = $0D02;
+  GL_PACK_SKIP_ROWS                 = $0D03;
+  GL_PACK_SKIP_PIXELS               = $0D04;
+  GL_PACK_ALIGNMENT                 = $0D05;
+  GL_MAP_COLOR                      = $0D10;
+  GL_MAP_STENCIL                    = $0D11;
+  GL_INDEX_SHIFT                    = $0D12;
+  GL_INDEX_OFFSET                   = $0D13;
+  GL_RED_SCALE                      = $0D14;
+  GL_RED_BIAS                       = $0D15;
+  GL_ZOOM_X                         = $0D16;
+  GL_ZOOM_Y                         = $0D17;
+  GL_GREEN_SCALE                    = $0D18;
+  GL_GREEN_BIAS                     = $0D19;
+  GL_BLUE_SCALE                     = $0D1A;
+  GL_BLUE_BIAS                      = $0D1B;
+  GL_ALPHA_SCALE                    = $0D1C;
+  GL_ALPHA_BIAS                     = $0D1D;
+  GL_DEPTH_SCALE                    = $0D1E;
+  GL_DEPTH_BIAS                     = $0D1F;
+  GL_MAX_EVAL_ORDER                 = $0D30;
+  GL_MAX_LIGHTS                     = $0D31;
+  GL_MAX_CLIP_PLANES                = $0D32;
+  GL_MAX_TEXTURE_SIZE               = $0D33;
+  GL_MAX_PIXEL_MAP_TABLE            = $0D34;
+  GL_MAX_ATTRIB_STACK_DEPTH         = $0D35;
+  GL_MAX_MODELVIEW_STACK_DEPTH      = $0D36;
+  GL_MAX_NAME_STACK_DEPTH           = $0D37;
+  GL_MAX_PROJECTION_STACK_DEPTH     = $0D38;
+  GL_MAX_TEXTURE_STACK_DEPTH        = $0D39;
+  GL_MAX_VIEWPORT_DIMS              = $0D3A;
+  GL_MAX_CLIENT_ATTRIB_STACK_DEPTH  = $0D3B;
+  GL_SUBPIXEL_BITS                  = $0D50;
+  GL_INDEX_BITS                     = $0D51;
+  GL_RED_BITS                       = $0D52;
+  GL_GREEN_BITS                     = $0D53;
+  GL_BLUE_BITS                      = $0D54;
+  GL_ALPHA_BITS                     = $0D55;
+  GL_DEPTH_BITS                     = $0D56;
+  GL_STENCIL_BITS                   = $0D57;
+  GL_ACCUM_RED_BITS                 = $0D58;
+  GL_ACCUM_GREEN_BITS               = $0D59;
+  GL_ACCUM_BLUE_BITS                = $0D5A;
+  GL_ACCUM_ALPHA_BITS               = $0D5B;
+  GL_NAME_STACK_DEPTH               = $0D70;
+  GL_AUTO_NORMAL                    = $0D80;
+  GL_MAP1_COLOR_4                   = $0D90;
+  GL_MAP1_INDEX                     = $0D91;
+  GL_MAP1_NORMAL                    = $0D92;
+  GL_MAP1_TEXTURE_COORD_1           = $0D93;
+  GL_MAP1_TEXTURE_COORD_2           = $0D94;
+  GL_MAP1_TEXTURE_COORD_3           = $0D95;
+  GL_MAP1_TEXTURE_COORD_4           = $0D96;
+  GL_MAP1_VERTEX_3                  = $0D97;
+  GL_MAP1_VERTEX_4                  = $0D98;
+  GL_MAP2_COLOR_4                   = $0DB0;
+  GL_MAP2_INDEX                     = $0DB1;
+  GL_MAP2_NORMAL                    = $0DB2;
+  GL_MAP2_TEXTURE_COORD_1           = $0DB3;
+  GL_MAP2_TEXTURE_COORD_2           = $0DB4;
+  GL_MAP2_TEXTURE_COORD_3           = $0DB5;
+  GL_MAP2_TEXTURE_COORD_4           = $0DB6;
+  GL_MAP2_VERTEX_3                  = $0DB7;
+  GL_MAP2_VERTEX_4                  = $0DB8;
+  GL_MAP1_GRID_DOMAIN               = $0DD0;
+  GL_MAP1_GRID_SEGMENTS             = $0DD1;
+  GL_MAP2_GRID_DOMAIN               = $0DD2;
+  GL_MAP2_GRID_SEGMENTS             = $0DD3;
+  GL_TEXTURE_1D                     = $0DE0;
+  GL_TEXTURE_2D                     = $0DE1;
+  GL_FEEDBACK_BUFFER_POINTER        = $0DF0;
+  GL_FEEDBACK_BUFFER_SIZE           = $0DF1;
+  GL_FEEDBACK_BUFFER_TYPE           = $0DF2;
+  GL_SELECTION_BUFFER_POINTER       = $0DF3;
+  GL_SELECTION_BUFFER_SIZE          = $0DF4;
+  //      GL_TEXTURE_BINDING_1D
+  //      GL_TEXTURE_BINDING_2D 
+  //      GL_VERTEX_ARRAY 
+  //      GL_NORMAL_ARRAY 
+  //      GL_COLOR_ARRAY 
+  //      GL_INDEX_ARRAY 
+  //      GL_TEXTURE_COORD_ARRAY 
+  //      GL_EDGE_FLAG_ARRAY
+  //      GL_VERTEX_ARRAY_SIZE
+  //      GL_VERTEX_ARRAY_TYPE 
+  //      GL_VERTEX_ARRAY_STRIDE 
+  //      GL_NORMAL_ARRAY_TYPE 
+  //      GL_NORMAL_ARRAY_STRIDE 
+  //      GL_COLOR_ARRAY_SIZE 
+  //      GL_COLOR_ARRAY_TYPE 
+  //      GL_COLOR_ARRAY_STRIDE 
+  //      GL_INDEX_ARRAY_TYPE 
+  //      GL_INDEX_ARRAY_STRIDE 
+  //      GL_TEXTURE_COORD_ARRAY_SIZE 
+  //      GL_TEXTURE_COORD_ARRAY_TYPE 
+  //      GL_TEXTURE_COORD_ARRAY_STRIDE 
+  //      GL_EDGE_FLAG_ARRAY_STRIDE 
+  //      GL_POLYGON_OFFSET_FACTOR 
+  //      GL_POLYGON_OFFSET_UNITS 
+
+  // GetTextureParameter 
+  //      GL_TEXTURE_MAG_FILTER 
+  //      GL_TEXTURE_MIN_FILTER 
+  //      GL_TEXTURE_WRAP_S
+  //      GL_TEXTURE_WRAP_T
+  GL_TEXTURE_WIDTH                  = $1000;
+  GL_TEXTURE_HEIGHT                 = $1001;
+  GL_TEXTURE_INTERNAL_FORMAT        = $1003;
+  GL_TEXTURE_BORDER_COLOR           = $1004;
+  GL_TEXTURE_BORDER                 = $1005;
+  //      GL_TEXTURE_RED_SIZE
+  //      GL_TEXTURE_GREEN_SIZE
+  //      GL_TEXTURE_BLUE_SIZE
+  //      GL_TEXTURE_ALPHA_SIZE
+  //      GL_TEXTURE_LUMINANCE_SIZE
+  //      GL_TEXTURE_INTENSITY_SIZE
+  //      GL_TEXTURE_PRIORITY
+  //      GL_TEXTURE_RESIDENT
+
+  // HintMode
+  GL_DONT_CARE                      = $1100;
+  GL_FASTEST                        = $1101;
+  GL_NICEST                         = $1102;
+
+  // HintTarget
+  //      GL_PERSPECTIVE_CORRECTION_HINT
+  //      GL_POINT_SMOOTH_HINT
+  //      GL_LINE_SMOOTH_HINT
+  //      GL_POLYGON_SMOOTH_HINT
+  //      GL_FOG_HINT
+
+  // IndexPointerType
+  //      GL_SHORT
+  //      GL_INT
+  //      GL_FLOAT
+  //      GL_DOUBLE
+
+  // LightModelParameter
+  //      GL_LIGHT_MODEL_AMBIENT
+  //      GL_LIGHT_MODEL_LOCAL_VIEWER
+  //      GL_LIGHT_MODEL_TWO_SIDE
+
+  // LightName
+  GL_LIGHT0                         = $4000;
+  GL_LIGHT1                         = $4001;
+  GL_LIGHT2                         = $4002;
+  GL_LIGHT3                         = $4003;
+  GL_LIGHT4                         = $4004;
+  GL_LIGHT5                         = $4005;
+  GL_LIGHT6                         = $4006;
+  GL_LIGHT7                         = $4007;
+
+  // LightParameter
+  GL_AMBIENT                        = $1200;
+  GL_DIFFUSE                        = $1201;
+  GL_SPECULAR                       = $1202;
+  GL_POSITION                       = $1203;
+  GL_SPOT_DIRECTION                 = $1204;
+  GL_SPOT_EXPONENT                  = $1205;
+  GL_SPOT_CUTOFF                    = $1206;
+  GL_CONSTANT_ATTENUATION           = $1207;
+  GL_LINEAR_ATTENUATION             = $1208;
+  GL_QUADRATIC_ATTENUATION          = $1209;
+
+  // InterleavedArrays
+  //      GL_V2F
+  //      GL_V3F
+  //      GL_C4UB_V2F
+  //      GL_C4UB_V3F
+  //      GL_C3F_V3F
+  //      GL_N3F_V3F
+  //      GL_C4F_N3F_V3F
+  //      GL_T2F_V3F
+  //      GL_T4F_V4F
+  //      GL_T2F_C4UB_V3F
+  //      GL_T2F_C3F_V3F
+  //      GL_T2F_N3F_V3F
+  //      GL_T2F_C4F_N3F_V3F
+  //      GL_T4F_C4F_N3F_V4F
+
+  // ListMode
+  GL_COMPILE                        = $1300;
+  GL_COMPILE_AND_EXECUTE            = $1301;
+
+  // ListNameType
+  //      GL_BYTE
+  //      GL_UNSIGNED_BYTE
+  //      GL_SHORT
+  //      GL_UNSIGNED_SHORT
+  //      GL_INT
+  //      GL_UNSIGNED_INT
+  //      GL_FLOAT
+  //      GL_2_BYTES
+  //      GL_3_BYTES
+  //      GL_4_BYTES
+
+  // LogicOp
+  GL_CLEAR                          = $1500;
+  GL_AND                            = $1501;
+  GL_AND_REVERSE                    = $1502;
+  GL_COPY                           = $1503;
+  GL_AND_INVERTED                   = $1504;
+  GL_NOOP                           = $1505;
+  GL_XOR                            = $1506;
+  GL_OR                             = $1507;
+  GL_NOR                            = $1508;
+  GL_EQUIV                          = $1509;
+  GL_INVERT                         = $150A;
+  GL_OR_REVERSE                     = $150B;
+  GL_COPY_INVERTED                  = $150C;
+  GL_OR_INVERTED                    = $150D;
+  GL_NAND                           = $150E;
+  GL_SET                            = $150F;
+
+  // MapTarget
+  //      GL_MAP1_COLOR_4
+  //      GL_MAP1_INDEX
+  //      GL_MAP1_NORMAL
+  //      GL_MAP1_TEXTURE_COORD_1
+  //      GL_MAP1_TEXTURE_COORD_2
+  //      GL_MAP1_TEXTURE_COORD_3
+  //      GL_MAP1_TEXTURE_COORD_4
+  //      GL_MAP1_VERTEX_3
+  //      GL_MAP1_VERTEX_4
+  //      GL_MAP2_COLOR_4
+  //      GL_MAP2_INDEX
+  //      GL_MAP2_NORMAL
+  //      GL_MAP2_TEXTURE_COORD_1
+  //      GL_MAP2_TEXTURE_COORD_2
+  //      GL_MAP2_TEXTURE_COORD_3
+  //      GL_MAP2_TEXTURE_COORD_4
+  //      GL_MAP2_VERTEX_3
+  //      GL_MAP2_VERTEX_4
+
+  // MaterialFace
+  //      GL_FRONT
+  //      GL_BACK
+  //      GL_FRONT_AND_BACK
+
+  // MaterialParameter
+  GL_EMISSION                       = $1600;
+  GL_SHININESS                      = $1601;
+  GL_AMBIENT_AND_DIFFUSE            = $1602;
+  GL_COLOR_INDEXES                  = $1603;
+  //      GL_AMBIENT
+  //      GL_DIFFUSE
+  //      GL_SPECULAR
+
+  // MatrixMode
+  GL_MODELVIEW                      = $1700;
+  GL_PROJECTION                     = $1701;
+  GL_TEXTURE                        = $1702;
+
+  // MeshMode1
+  //      GL_POINT
+  //      GL_LINE
+
+  // MeshMode2
+  //      GL_POINT
+  //      GL_LINE
+  //      GL_FILL
+
+  // NormalPointerType
+  //      GL_BYTE
+  //      GL_SHORT
+  //      GL_INT
+  //      GL_FLOAT
+  //      GL_DOUBLE
+
+  // PixelCopyType
+  GL_COLOR                          = $1800;
+  GL_DEPTH                          = $1801;
+  GL_STENCIL                        = $1802;
+
+  // PixelFormat
+  GL_COLOR_INDEX                    = $1900;
+  GL_STENCIL_INDEX                  = $1901;
+  GL_DEPTH_COMPONENT                = $1902;
+  GL_RED                            = $1903;
+  GL_GREEN                          = $1904;
+  GL_BLUE                           = $1905;
+  GL_ALPHA                          = $1906;
+  GL_RGB                            = $1907;
+  GL_RGBA                           = $1908;
+  GL_LUMINANCE                      = $1909;
+  GL_LUMINANCE_ALPHA                = $190A;
+
+  // PixelMap
+  //      GL_PIXEL_MAP_I_TO_I
+  //      GL_PIXEL_MAP_S_TO_S
+  //      GL_PIXEL_MAP_I_TO_R
+  //      GL_PIXEL_MAP_I_TO_G
+  //      GL_PIXEL_MAP_I_TO_B
+  //      GL_PIXEL_MAP_I_TO_A
+  //      GL_PIXEL_MAP_R_TO_R
+  //      GL_PIXEL_MAP_G_TO_G
+  //      GL_PIXEL_MAP_B_TO_B
+  //      GL_PIXEL_MAP_A_TO_A
+
+  // PixelStore
+  //      GL_UNPACK_SWAP_BYTES
+  //      GL_UNPACK_LSB_FIRST
+  //      GL_UNPACK_ROW_LENGTH
+  //      GL_UNPACK_SKIP_ROWS
+  //      GL_UNPACK_SKIP_PIXELS
+  //      GL_UNPACK_ALIGNMENT
+  //      GL_PACK_SWAP_BYTES
+  //      GL_PACK_LSB_FIRST
+  //      GL_PACK_ROW_LENGTH
+  //      GL_PACK_SKIP_ROWS
+  //      GL_PACK_SKIP_PIXELS
+  //      GL_PACK_ALIGNMENT
+
+  // PixelTransfer
+  //      GL_MAP_COLOR
+  //      GL_MAP_STENCIL
+  //      GL_INDEX_SHIFT
+  //      GL_INDEX_OFFSET
+  //      GL_RED_SCALE
+  //      GL_RED_BIAS
+  //      GL_GREEN_SCALE
+  //      GL_GREEN_BIAS
+  //      GL_BLUE_SCALE
+  //      GL_BLUE_BIAS
+  //      GL_ALPHA_SCALE
+  //      GL_ALPHA_BIAS
+  //      GL_DEPTH_SCALE
+  //      GL_DEPTH_BIAS
+
+  // PixelType
+  GL_BITMAP                         = $1A00;
+  //      GL_BYTE
+  //      GL_UNSIGNED_BYTE
+  //      GL_SHORT
+  //      GL_UNSIGNED_SHORT
+  //      GL_INT
+  //      GL_UNSIGNED_INT
+  //      GL_FLOAT
+
+  // PolygonMode
+  GL_POINT                          = $1B00;
+  GL_LINE                           = $1B01;
+  GL_FILL                           = $1B02;
+
+  // ReadBufferMode
+  //      GL_FRONT_LEFT
+  //      GL_FRONT_RIGHT
+  //      GL_BACK_LEFT
+  //      GL_BACK_RIGHT
+  //      GL_FRONT
+  //      GL_BACK
+  //      GL_LEFT
+  //      GL_RIGHT
+  //      GL_AUX0
+  //      GL_AUX1
+  //      GL_AUX2
+  //      GL_AUX3
+
+  // RenderingMode
+  GL_RENDER                         = $1C00;
+  GL_FEEDBACK                       = $1C01;
+  GL_SELECT                         = $1C02;
+
+  // ShadingModel
+  GL_FLAT                           = $1D00;
+  GL_SMOOTH                         = $1D01;
+
+  // StencilFunction
+  //      GL_NEVER
+  //      GL_LESS
+  //      GL_EQUAL
+  //      GL_LEQUAL
+  //      GL_GREATER
+  //      GL_NOTEQUAL
+  //      GL_GEQUAL
+  //      GL_ALWAYS
+
+  // StencilOp
+  //      GL_ZERO
+  GL_KEEP                           = $1E00;
+  GL_REPLACE                        = $1E01;
+  GL_INCR                           = $1E02;
+  GL_DECR                           = $1E03;
+  //      GL_INVERT
+
+  // StringName
+  GL_VENDOR                         = $1F00;
+  GL_RENDERER                       = $1F01;
+  GL_VERSION                        = $1F02;
+  GL_EXTENSIONS                     = $1F03;
+
+  // TextureCoordName
+  GL_S                              = $2000;
+  GL_T                              = $2001;
+  GL_R                              = $2002;
+  GL_Q                              = $2003;
+
+  // TexCoordPointerType
+  //      GL_SHORT
+  //      GL_INT
+  //      GL_FLOAT
+  //      GL_DOUBLE
+
+  // TextureEnvMode
+  GL_MODULATE                       = $2100;
+  GL_DECAL                          = $2101;
+  //      GL_BLEND
+  //      GL_REPLACE
+
+  // TextureEnvParameter
+  GL_TEXTURE_ENV_MODE               = $2200;
+  GL_TEXTURE_ENV_COLOR              = $2201;
+
+  // TextureEnvTarget
+  GL_TEXTURE_ENV                    = $2300;
+
+  // TextureGenMode
+  GL_EYE_LINEAR                     = $2400;
+  GL_OBJECT_LINEAR                  = $2401;
+  GL_SPHERE_MAP                     = $2402;
+
+  // TextureGenParameter
+  GL_TEXTURE_GEN_MODE               = $2500;
+  GL_OBJECT_PLANE                   = $2501;
+  GL_EYE_PLANE                      = $2502;
+
+  // TextureMagFilter
+  GL_NEAREST                        = $2600;
+  GL_LINEAR                         = $2601;
+
+  // TextureMinFilter
+  //      GL_NEAREST
+  //      GL_LINEAR
+  GL_NEAREST_MIPMAP_NEAREST         = $2700;
+  GL_LINEAR_MIPMAP_NEAREST          = $2701;
+  GL_NEAREST_MIPMAP_LINEAR          = $2702;
+  GL_LINEAR_MIPMAP_LINEAR           = $2703;
+
+  // TextureParameterName
+  GL_TEXTURE_MAG_FILTER             = $2800;
+  GL_TEXTURE_MIN_FILTER             = $2801;
+  GL_TEXTURE_WRAP_S                 = $2802;
+  GL_TEXTURE_WRAP_T                 = $2803;
+  //      GL_TEXTURE_BORDER_COLOR
+  //      GL_TEXTURE_PRIORITY
+
+  // TextureTarget
+  //      GL_TEXTURE_1D
+  //      GL_TEXTURE_2D
+  //      GL_PROXY_TEXTURE_1D
+  //      GL_PROXY_TEXTURE_2D
+
+  // TextureWrapMode
+  GL_CLAMP                          = $2900;
+  GL_REPEAT                         = $2901;
+
+  // VertexPointerType
+  //      GL_SHORT
+  //      GL_INT
+  //      GL_FLOAT
+  //      GL_DOUBLE
+
+  // ClientAttribMask
+  GL_CLIENT_PIXEL_STORE_BIT         = $00000001;
+  GL_CLIENT_VERTEX_ARRAY_BIT        = $00000002;
+  GL_CLIENT_ALL_ATTRIB_BITS         = $FFFFFFFF;
+
+  // polygon_offset
+  GL_POLYGON_OFFSET_FACTOR          = $8038;
+  GL_POLYGON_OFFSET_UNITS           = $2A00;
+  GL_POLYGON_OFFSET_POINT           = $2A01;
+  GL_POLYGON_OFFSET_LINE            = $2A02;
+  GL_POLYGON_OFFSET_FILL            = $8037;
+
+  // texture
+  GL_ALPHA4                         = $803B;
+  GL_ALPHA8                         = $803C;
+  GL_ALPHA12                        = $803D;
+  GL_ALPHA16                        = $803E;
+  GL_LUMINANCE4                     = $803F;
+  GL_LUMINANCE8                     = $8040;
+  GL_LUMINANCE12                    = $8041;
+  GL_LUMINANCE16                    = $8042;
+  GL_LUMINANCE4_ALPHA4              = $8043;
+  GL_LUMINANCE6_ALPHA2              = $8044;
+  GL_LUMINANCE8_ALPHA8              = $8045;
+  GL_LUMINANCE12_ALPHA4             = $8046;
+  GL_LUMINANCE12_ALPHA12            = $8047;
+  GL_LUMINANCE16_ALPHA16            = $8048;
+  GL_INTENSITY                      = $8049;
+  GL_INTENSITY4                     = $804A;
+  GL_INTENSITY8                     = $804B;
+  GL_INTENSITY12                    = $804C;
+  GL_INTENSITY16                    = $804D;
+  GL_R3_G3_B2                       = $2A10;
+  GL_RGB4                           = $804F;
+  GL_RGB5                           = $8050;
+  GL_RGB8                           = $8051;
+  GL_RGB10                          = $8052;
+  GL_RGB12                          = $8053;
+  GL_RGB16                          = $8054;
+  GL_RGBA2                          = $8055;
+  GL_RGBA4                          = $8056;
+  GL_RGB5_A1                        = $8057;
+  GL_RGBA8                          = $8058;
+  GL_RGB10_A2                       = $8059;
+  GL_RGBA12                         = $805A;
+  GL_RGBA16                         = $805B;
+  GL_TEXTURE_RED_SIZE               = $805C;
+  GL_TEXTURE_GREEN_SIZE             = $805D;
+  GL_TEXTURE_BLUE_SIZE              = $805E;
+  GL_TEXTURE_ALPHA_SIZE             = $805F;
+  GL_TEXTURE_LUMINANCE_SIZE         = $8060;
+  GL_TEXTURE_INTENSITY_SIZE         = $8061;
+  GL_PROXY_TEXTURE_1D               = $8063;
+  GL_PROXY_TEXTURE_2D               = $8064;
+
+  // texture_object
+  GL_TEXTURE_PRIORITY               = $8066;
+  GL_TEXTURE_RESIDENT               = $8067;
+  GL_TEXTURE_BINDING_1D             = $8068;
+  GL_TEXTURE_BINDING_2D             = $8069;
+
+  // vertex_array
+  GL_VERTEX_ARRAY                   = $8074;
+  GL_NORMAL_ARRAY                   = $8075;
+  GL_COLOR_ARRAY                    = $8076;
+  GL_INDEX_ARRAY                    = $8077;
+  GL_TEXTURE_COORD_ARRAY            = $8078;
+  GL_EDGE_FLAG_ARRAY                = $8079;
+  GL_VERTEX_ARRAY_SIZE              = $807A;
+  GL_VERTEX_ARRAY_TYPE              = $807B;
+  GL_VERTEX_ARRAY_STRIDE            = $807C;
+  GL_NORMAL_ARRAY_TYPE              = $807E;
+  GL_NORMAL_ARRAY_STRIDE            = $807F;
+  GL_COLOR_ARRAY_SIZE               = $8081;
+  GL_COLOR_ARRAY_TYPE               = $8082;
+  GL_COLOR_ARRAY_STRIDE             = $8083;
+  GL_INDEX_ARRAY_TYPE               = $8085;
+  GL_INDEX_ARRAY_STRIDE             = $8086;
+  GL_TEXTURE_COORD_ARRAY_SIZE       = $8088;
+  GL_TEXTURE_COORD_ARRAY_TYPE       = $8089;
+  GL_TEXTURE_COORD_ARRAY_STRIDE     = $808A;
+  GL_EDGE_FLAG_ARRAY_STRIDE         = $808C;
+  GL_VERTEX_ARRAY_POINTER           = $808E;
+  GL_NORMAL_ARRAY_POINTER           = $808F;
+  GL_COLOR_ARRAY_POINTER            = $8090;
+  GL_INDEX_ARRAY_POINTER            = $8091;
+  GL_TEXTURE_COORD_ARRAY_POINTER    = $8092;
+  GL_EDGE_FLAG_ARRAY_POINTER        = $8093;
+  GL_V2F                            = $2A20;
+  GL_V3F                            = $2A21;
+  GL_C4UB_V2F                       = $2A22;
+  GL_C4UB_V3F                       = $2A23;
+  GL_C3F_V3F                        = $2A24;
+  GL_N3F_V3F                        = $2A25;
+  GL_C4F_N3F_V3F                    = $2A26;
+  GL_T2F_V3F                        = $2A27;
+  GL_T4F_V4F                        = $2A28;
+  GL_T2F_C4UB_V3F                   = $2A29;
+  GL_T2F_C3F_V3F                    = $2A2A;
+  GL_T2F_N3F_V3F                    = $2A2B;
+  GL_T2F_C4F_N3F_V3F                = $2A2C;
+  GL_T4F_C4F_N3F_V4F                = $2A2D;
+
+  // Extensions
+  GL_EXT_vertex_array               = 1;
+  GL_WIN_swap_hint                  = 1;
+  GL_EXT_bgra                       = 1;
+  GL_EXT_paletted_texture           = 1;
+
+  // EXT_vertex_array
+  GL_VERTEX_ARRAY_EXT               = $8074;
+  GL_NORMAL_ARRAY_EXT               = $8075;
+  GL_COLOR_ARRAY_EXT                = $8076;
+  GL_INDEX_ARRAY_EXT                = $8077;
+  GL_TEXTURE_COORD_ARRAY_EXT        = $8078;
+  GL_EDGE_FLAG_ARRAY_EXT            = $8079;
+  GL_VERTEX_ARRAY_SIZE_EXT          = $807A;
+  GL_VERTEX_ARRAY_TYPE_EXT          = $807B;
+  GL_VERTEX_ARRAY_STRIDE_EXT        = $807C;
+  GL_VERTEX_ARRAY_COUNT_EXT         = $807D;
+  GL_NORMAL_ARRAY_TYPE_EXT          = $807E;
+  GL_NORMAL_ARRAY_STRIDE_EXT        = $807F;
+  GL_NORMAL_ARRAY_COUNT_EXT         = $8080;
+  GL_COLOR_ARRAY_SIZE_EXT           = $8081;
+  GL_COLOR_ARRAY_TYPE_EXT           = $8082;
+  GL_COLOR_ARRAY_STRIDE_EXT         = $8083;
+  GL_COLOR_ARRAY_COUNT_EXT          = $8084;
+  GL_INDEX_ARRAY_TYPE_EXT           = $8085;
+  GL_INDEX_ARRAY_STRIDE_EXT         = $8086;
+  GL_INDEX_ARRAY_COUNT_EXT          = $8087;
+  GL_TEXTURE_COORD_ARRAY_SIZE_EXT   = $8088;
+  GL_TEXTURE_COORD_ARRAY_TYPE_EXT   = $8089;
+  GL_TEXTURE_COORD_ARRAY_STRIDE_EXT = $808A;
+  GL_TEXTURE_COORD_ARRAY_COUNT_EXT  = $808B;
+  GL_EDGE_FLAG_ARRAY_STRIDE_EXT     = $808C;
+  GL_EDGE_FLAG_ARRAY_COUNT_EXT      = $808D;
+  GL_VERTEX_ARRAY_POINTER_EXT       = $808E;
+  GL_NORMAL_ARRAY_POINTER_EXT       = $808F;
+  GL_COLOR_ARRAY_POINTER_EXT        = $8090;
+  GL_INDEX_ARRAY_POINTER_EXT        = $8091;
+  GL_TEXTURE_COORD_ARRAY_POINTER_EXT = $8092;
+  GL_EDGE_FLAG_ARRAY_POINTER_EXT    = $8093;
+  GL_DOUBLE_EXT                     = GL_DOUBLE;
+
+  // EXT_bgra 
+  GL_BGR_EXT                        = $80E0;
+  GL_BGRA_EXT                       = $80E1;
+
+  // EXT_paletted_texture
+
+  // These must match the GL_COLOR_TABLE_*_SGI enumerants
+  GL_COLOR_TABLE_FORMAT_EXT         = $80D8;
+  GL_COLOR_TABLE_WIDTH_EXT          = $80D9;
+  GL_COLOR_TABLE_RED_SIZE_EXT       = $80DA;
+  GL_COLOR_TABLE_GREEN_SIZE_EXT     = $80DB;
+  GL_COLOR_TABLE_BLUE_SIZE_EXT      = $80DC;
+  GL_COLOR_TABLE_ALPHA_SIZE_EXT     = $80DD;
+  GL_COLOR_TABLE_LUMINANCE_SIZE_EXT = $80DE;
+  GL_COLOR_TABLE_INTENSITY_SIZE_EXT = $80DF;
+
+  GL_COLOR_INDEX1_EXT               = $80E2;
+  GL_COLOR_INDEX2_EXT               = $80E3;
+  GL_COLOR_INDEX4_EXT               = $80E4;
+  GL_COLOR_INDEX8_EXT               = $80E5;
+  GL_COLOR_INDEX12_EXT              = $80E6;
+  GL_COLOR_INDEX16_EXT              = $80E7;
+
+  // For compatibility with OpenGL v1.0
+  GL_LOGIC_OP                       = GL_INDEX_LOGIC_OP;
+  GL_TEXTURE_COMPONENTS             = GL_TEXTURE_INTERNAL_FORMAT;
+
+{******************************************************************************}
+
+var
+  glAccum: procedure(op: GLenum; value: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAlphaFunc: procedure(func: GLenum; ref: GLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAreTexturesResident: function (n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glArrayElement: procedure(i: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBegin: procedure(mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindTexture: procedure(target: GLenum; texture: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBitmap: procedure (width, height: GLsizei; xorig, yorig: GLfloat; xmove, ymove: GLfloat; const bitmap: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBlendFunc: procedure(sfactor, dfactor: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCallList: procedure(list: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCallLists: procedure(n: GLsizei; atype: GLenum; const lists: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClear: procedure(mask: GLbitfield); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClearAccum: procedure(red, green, blue, alpha: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClearColor: procedure(red, green, blue, alpha: GLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClearDepth: procedure(depth: GLclampd); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClearIndex: procedure(c: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClearStencil: procedure(s: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClipPlane: procedure(plane: GLenum; const equation: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3b: procedure(red, green, blue: GLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3bv: procedure(const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3d: procedure(red, green, blue: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3f: procedure(red, green, blue: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3i: procedure(red, green, blue: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3s: procedure(red, green, blue: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3ub: procedure(red, green, blue: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3ubv: procedure(const v: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3ui: procedure(red, green, blue: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3uiv: procedure(const v: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3us: procedure(red, green, blue: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3usv: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4b: procedure(red, green, blue, alpha: GLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4bv: procedure(const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4d: procedure(red, green, blue, alpha: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4f: procedure(red, green, blue, alpha: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4i: procedure(red, green, blue, alpha: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4s: procedure(red, green, blue, alpha: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4ub: procedure(red, green, blue, alpha: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4ubv: procedure(const v: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4ui: procedure(red, green, blue, alpha: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4uiv: procedure(const v: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4us: procedure(red, green, blue, alpha: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4usv: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorMask: procedure(red, green, blue, alpha: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorMaterial: procedure(face, mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyPixels: procedure(x, y: GLint; width, height: GLsizei; atype: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyTexImage1D: procedure (target: GLenum; level: GLint; internalFormat: GLenum; x, y: GLint; width: GLsizei; border: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyTexImage2D: procedure(target: GLenum; level: GLint; internalFormat: GLenum; x, y: GLint; width, height: GLsizei; border: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyTexSubImage1D: procedure(target: GLenum; level, xoffset, x, y: GLint; width: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyTexSubImage2D: procedure(target: GLenum; level, xoffset, yoffset, x, y: GLint; width, height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCullFace: procedure(mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteLists: procedure(list: GLuint; range: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteTextures: procedure(n: GLsizei; const textures: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDepthFunc: procedure(func: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDepthMask: procedure(flag: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDepthRange: procedure(zNear, zFar: GLclampd); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDisable: procedure(cap: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDisableClientState: procedure(aarray: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawArrays: procedure(mode: GLenum; first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawBuffer: procedure(mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawElements: procedure(mode: GLenum; count: GLsizei; atype: GLenum; const indices: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawPixels: procedure(width, height: GLsizei; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEdgeFlag: procedure(flag: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEdgeFlagPointer: procedure(stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEdgeFlagv: procedure(const flag: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEnable: procedure(cap: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEnableClientState: procedure(aarray: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEnd: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEndList: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord1d: procedure(u: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord1dv: procedure(const u: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord1f: procedure(u: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord1fv: procedure(const u: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord2d: procedure(u, v: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord2dv: procedure(const u: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord2f: procedure(u, v: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord2fv: procedure(const u: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalMesh1: procedure(mode: GLenum; i1, i2: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalMesh2: procedure(mode: GLenum; i1, i2, j1, j2: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalPoint1: procedure(i: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalPoint2: procedure(i, j: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFeedbackBuffer: procedure(size: GLsizei; atype: GLenum; buffer: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFinish: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFlush: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogfv: procedure(pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogi: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogiv: procedure(pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFrontFace: procedure(mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFrustum: procedure(left, right, bottom, top, zNear, zFar: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenLists: function(range: GLsizei): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenTextures: procedure(n: GLsizei; textures: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetBooleanv: procedure(pname: GLenum; params: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetClipPlane: procedure(plane: GLenum; equation: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetDoublev: procedure(pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetError: function: GLenum; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetFloatv: procedure(pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetIntegerv: procedure(pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetLightfv: procedure(light, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetLightiv: procedure(light, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapdv: procedure(target, query: GLenum; v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapfv: procedure(target, query: GLenum; v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapiv: procedure(target, query: GLenum; v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMaterialfv: procedure(face, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMaterialiv: procedure(face, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPixelMapfv: procedure(map: GLenum; values: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPixelMapuiv: procedure(map: GLenum; values: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPixelMapusv: procedure(map: GLenum; values: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPointerv: procedure(pname: GLenum; params: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPolygonStipple: procedure(mask: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetString: function(name: GLenum): PChar; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexEnvfv: procedure(target, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexEnviv: procedure(target, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexGendv: procedure(coord, pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexGenfv: procedure(coord, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexGeniv: procedure(coord, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexImage: procedure(target: GLenum; level: GLint; format: GLenum; atype: GLenum; pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexLevelParameterfv: procedure(target: GLenum; level: GLint; pname: GLenum; params: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexLevelParameteriv: procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexParameterfv: procedure(target, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexParameteriv: procedure(target, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glHint: procedure(target, mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexMask: procedure(mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexPointer: procedure(atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexd: procedure(c: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexdv: procedure(const c: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexf: procedure(c: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexfv: procedure(const c: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexi: procedure(c: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexiv: procedure(const c: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexs: procedure(c: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexsv: procedure(const c: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexub: procedure(c: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexubv: procedure(const c: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glInitNames: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glInterleavedArrays: procedure(format: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsEnabled: function(cap: GLenum): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsList: function(list: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsTexture: function(texture: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightModelf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightModelfv: procedure(pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightModeli: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightModeliv: procedure(pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightf: procedure(light, pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightfv: procedure(light, pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLighti: procedure(light, pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightiv: procedure(light, pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLineStipple: procedure(factor: GLint; pattern: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLineWidth: procedure(width: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glListBase: procedure(base: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadIdentity: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadMatrixd: procedure(const m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadMatrixf: procedure(const m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadName: procedure(name: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLogicOp: procedure(opcode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMap1d: procedure(target: GLenum; u1, u2: GLdouble; stride, order: GLint; const points: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMap1f: procedure(target: GLenum; u1, u2: GLfloat; stride, order: GLint; const points: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMap2d: procedure(target: GLenum; u1, u2: GLdouble; ustride, uorder: GLint; v1, v2: GLdouble; vstride, vorder: GLint; const points: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMap2f: procedure(target: GLenum; u1, u2: GLfloat; ustride, uorder: GLint; v1, v2: GLfloat; vstride, vorder: GLint; const points: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapGrid1d: procedure(un: GLint; u1, u2: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapGrid1f: procedure(un: GLint; u1, u2: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapGrid2d: procedure(un: GLint; u1, u2: GLdouble; vn: GLint; v1, v2: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapGrid2f: procedure(un: GLint; u1, u2: GLfloat; vn: GLint; v1, v2: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMaterialf: procedure(face, pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMaterialfv: procedure(face, pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMateriali: procedure(face, pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMaterialiv: procedure(face, pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMatrixMode: procedure(mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultMatrixd: procedure(const m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultMatrixf: procedure(const m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNewList: procedure(list: GLuint; mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3b: procedure(nx, ny, nz: GLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3bv: procedure(const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3d: procedure(nx, ny, nz: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3f: procedure(nx, ny, nz: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3i: procedure(nx, ny, nz: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3s: procedure(nx, ny, nz: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalPointer: procedure(atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glOrtho: procedure(left, right, bottom, top, zNear, zFar: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPassThrough: procedure(token: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelMapfv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelMapuiv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelMapusv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelStoref: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelStorei: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelTransferf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelTransferi: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelZoom: procedure(xfactor, yfactor: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPointSize: procedure(size: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPolygonMode: procedure(face, mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPolygonOffset: procedure(factor, units: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPolygonStipple: procedure(const mask: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPopAttrib: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPopClientAttrib: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPopMatrix: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPopName: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPrioritizeTextures: procedure(n: GLsizei; const textures: PGLuint; const priorities: PGLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPushAttrib: procedure(mask: GLbitfield); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPushClientAttrib: procedure(mask: GLbitfield); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPushMatrix: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPushName: procedure(name: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos2d: procedure(x, y: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos2dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos2f: procedure(x, y: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos2fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos2i: procedure(x, y: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos2iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos2s: procedure(x, y: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos2sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos3d: procedure(x, y, z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos3dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos3f: procedure(x, y, z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos3fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos3i: procedure(x, y, z: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos3iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos3s: procedure(x, y, z: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos3sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos4d: procedure(x, y, z, w: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos4dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos4f: procedure(x, y, z, w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos4fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos4i: procedure(x, y, z, w: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos4iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos4s: procedure(x, y, z, w: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRasterPos4sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReadBuffer: procedure(mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReadPixels: procedure(x, y: GLint; width, height: GLsizei; format, atype: GLenum; pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRectd: procedure(x1, y1, x2, y2: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRectdv: procedure(const v1: PGLdouble; const v2: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRectf: procedure(x1, y1, x2, y2: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRectfv: procedure(const v1: PGLfloat; const v2: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRecti: procedure(x1, y1, x2, y2: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRectiv: procedure(const v1: PGLint; const v2: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRects: procedure(x1, y1, x2, y2: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRectsv: procedure(const v1: PGLshort; const v2: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRenderMode: function(mode: GLint): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRotated: procedure(angle, x, y, z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRotatef: procedure(angle, x, y, z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glScaled: procedure(x, y, z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glScalef: procedure(x, y, z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glScissor: procedure(x, y: GLint; width, height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSelectBuffer: procedure(size: GLsizei; buffer: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glShadeModel: procedure(mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilFunc: procedure(func: GLenum; ref: GLint; mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilMask: procedure(mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilOp: procedure(fail, zfail, zpass: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1d: procedure(s: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1f: procedure(s: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1i: procedure(s: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1s: procedure(s: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2d: procedure(s, t: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2f: procedure(s, t: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2i: procedure(s, t: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2s: procedure(s, t: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3d: procedure(s, t, r: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3f: procedure(s, t, r: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3i: procedure(s, t, r: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3s: procedure(s, t, r: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4d: procedure(s, t, r, q: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4f: procedure(s, t, r, q: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4i: procedure(s, t, r, q: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4s: procedure(s, t, r, q: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoordPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexEnvf: procedure(target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexEnvfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexEnvi: procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexEnviv: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGend: procedure(coord: GLenum; pname: GLenum; param: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGendv: procedure(coord: GLenum; pname: GLenum; const params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGenf: procedure(coord: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGenfv: procedure(coord: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGeni: procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGeniv: procedure(coord: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexImage1D: procedure(target: GLenum; level, internalformat: GLint; width: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexImage2D: procedure(target: GLenum; level, internalformat: GLint; width, height: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexParameterf: procedure(target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexParameterfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexParameteri: procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexParameteriv: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexSubImage1D: procedure(target: GLenum; level, xoffset: GLint; width: GLsizei; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexSubImage2D: procedure(target: GLenum; level, xoffset, yoffset: GLint; width, height: GLsizei; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTranslated: procedure(x, y, z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTranslatef: procedure(x, y, z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex2d: procedure(x, y: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex2dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex2f: procedure(x, y: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex2fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex2i: procedure(x, y: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex2iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex2s: procedure(x, y: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex2sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3d: procedure(x, y, z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3f: procedure(x, y, z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3i: procedure(x, y, z: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3s: procedure(x, y, z: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4d: procedure(x, y, z, w: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4f: procedure(x, y, z, w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4i: procedure(x, y, z, w: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4s: procedure(x, y, z, w: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glViewport: procedure(x, y: GLint; width, height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  {$IFDEF WINDOWS}
+  ChoosePixelFormat: function(DC: HDC; p2: PPixelFormatDescriptor): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  {$ENDIF}
+
+type
+  // EXT_vertex_array
+  PFNGLARRAYELEMENTEXTPROC = procedure(i: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLDRAWARRAYSEXTPROC = procedure(mode: GLenum; first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLVERTEXPOINTEREXTPROC = procedure(size: GLint; atype: GLenum;
+                                        stride, count: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLNORMALPOINTEREXTPROC = procedure(atype: GLenum; stride, count: GLsizei;
+                                        const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLCOLORPOINTEREXTPROC = procedure(size: GLint; atype: GLenum; stride, count: GLsizei;
+                                       const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLINDEXPOINTEREXTPROC = procedure(atype: GLenum; stride, count: GLsizei;
+                                       const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLTEXCOORDPOINTEREXTPROC = procedure(size: GLint; atype: GLenum;
+                                          stride, count: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLEDGEFLAGPOINTEREXTPROC = procedure(stride, count: GLsizei;
+                                          const pointer: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLGETPOINTERVEXTPROC = procedure(pname: GLenum; params: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLARRAYELEMENTARRAYEXTPROC = procedure(mode: GLenum; count: GLsizei;
+                                            const pi: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+  // WIN_swap_hint
+  PFNGLADDSWAPHINTRECTWINPROC = procedure(x, y: GLint; width, height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+  // EXT_paletted_texture
+  PFNGLCOLORTABLEEXTPROC = procedure(target, internalFormat: GLenum; width: GLsizei;
+                                     format, atype: GLenum; const data: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLCOLORSUBTABLEEXTPROC = procedure(target: GLenum; start, count: GLsizei;
+                                        format, atype: GLenum; const data: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLGETCOLORTABLEEXTPROC = procedure(target, format, atype: GLenum; data: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLGETCOLORTABLEPARAMETERIVEXTPROC = procedure(target, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  PFNGLGETCOLORTABLEPARAMETERFVEXTPROC = procedure(target, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+procedure LoadOpenGL( const dll: PChar );
+procedure FreeOpenGL;
+
+implementation
+
+procedure FreeOpenGL;
+begin
+
+  @glAccum := nil;
+  @glAlphaFunc := nil;
+  @glAreTexturesResident := nil;
+  @glArrayElement := nil;
+  @glBegin := nil;
+  @glBindTexture := nil;
+  @glBitmap := nil;
+  @glBlendFunc := nil;
+  @glCallList := nil;
+  @glCallLists := nil;
+  @glClear := nil;
+  @glClearAccum := nil;
+  @glClearColor := nil;
+  @glClearDepth := nil;
+  @glClearIndex := nil;
+  @glClearStencil := nil;
+  @glClipPlane := nil;
+  @glColor3b := nil;
+  @glColor3bv := nil;
+  @glColor3d := nil;
+  @glColor3dv := nil;
+  @glColor3f := nil;
+  @glColor3fv := nil;
+  @glColor3i := nil;
+  @glColor3iv := nil;
+  @glColor3s := nil;
+  @glColor3sv := nil;
+  @glColor3ub := nil;
+  @glColor3ubv := nil;
+  @glColor3ui := nil;
+  @glColor3uiv := nil;
+  @glColor3us := nil;
+  @glColor3usv := nil;
+  @glColor4b := nil;
+  @glColor4bv := nil;
+  @glColor4d := nil;
+  @glColor4dv := nil;
+  @glColor4f := nil;
+  @glColor4fv := nil;
+  @glColor4i := nil;
+  @glColor4iv := nil;
+  @glColor4s := nil;
+  @glColor4sv := nil;
+  @glColor4ub := nil;
+  @glColor4ubv := nil;
+  @glColor4ui := nil;
+  @glColor4uiv := nil;
+  @glColor4us := nil;
+  @glColor4usv := nil;
+  @glColorMask := nil;
+  @glColorMaterial := nil;
+  @glColorPointer := nil;
+  @glCopyPixels := nil;
+  @glCopyTexImage1D := nil;
+  @glCopyTexImage2D := nil;
+  @glCopyTexSubImage1D := nil;
+  @glCopyTexSubImage2D := nil;
+  @glCullFace := nil;
+  @glDeleteLists := nil;
+  @glDeleteTextures := nil;
+  @glDepthFunc := nil;
+  @glDepthMask := nil;
+  @glDepthRange := nil;
+  @glDisable := nil;
+  @glDisableClientState := nil;
+  @glDrawArrays := nil;
+  @glDrawBuffer := nil;
+  @glDrawElements := nil;
+  @glDrawPixels := nil;
+  @glEdgeFlag := nil;
+  @glEdgeFlagPointer := nil;
+  @glEdgeFlagv := nil;
+  @glEnable := nil;
+  @glEnableClientState := nil;
+  @glEnd := nil;
+  @glEndList := nil;
+  @glEvalCoord1d := nil;
+  @glEvalCoord1dv := nil;
+  @glEvalCoord1f := nil;
+  @glEvalCoord1fv := nil;
+  @glEvalCoord2d := nil;
+  @glEvalCoord2dv := nil;
+  @glEvalCoord2f := nil;
+  @glEvalCoord2fv := nil;
+  @glEvalMesh1 := nil;
+  @glEvalMesh2 := nil;
+  @glEvalPoint1 := nil;
+  @glEvalPoint2 := nil;
+  @glFeedbackBuffer := nil;
+  @glFinish := nil;
+  @glFlush := nil;
+  @glFogf := nil;
+  @glFogfv := nil;
+  @glFogi := nil;
+  @glFogiv := nil;
+  @glFrontFace := nil;
+  @glFrustum := nil;
+  @glGenLists := nil;
+  @glGenTextures := nil;
+  @glGetBooleanv := nil;
+  @glGetClipPlane := nil;
+  @glGetDoublev := nil;
+  @glGetError := nil;
+  @glGetFloatv := nil;
+  @glGetIntegerv := nil;
+  @glGetLightfv := nil;
+  @glGetLightiv := nil;
+  @glGetMapdv := nil;
+  @glGetMapfv := nil;
+  @glGetMapiv := nil;
+  @glGetMaterialfv := nil;
+  @glGetMaterialiv := nil;
+  @glGetPixelMapfv := nil;
+  @glGetPixelMapuiv := nil;
+  @glGetPixelMapusv := nil;
+  @glGetPointerv := nil;
+  @glGetPolygonStipple := nil;
+  @glGetString := nil;
+  @glGetTexEnvfv := nil;
+  @glGetTexEnviv := nil;
+  @glGetTexGendv := nil;
+  @glGetTexGenfv := nil;
+  @glGetTexGeniv := nil;
+  @glGetTexImage := nil;
+  @glGetTexLevelParameterfv := nil;
+  @glGetTexLevelParameteriv := nil;
+  @glGetTexParameterfv := nil;
+  @glGetTexParameteriv := nil;
+  @glHint := nil;
+  @glIndexMask := nil;
+  @glIndexPointer := nil;
+  @glIndexd := nil;
+  @glIndexdv := nil;
+  @glIndexf := nil;
+  @glIndexfv := nil;
+  @glIndexi := nil;
+  @glIndexiv := nil;
+  @glIndexs := nil;
+  @glIndexsv := nil;
+  @glIndexub := nil;
+  @glIndexubv := nil;
+  @glInitNames := nil;
+  @glInterleavedArrays := nil;
+  @glIsEnabled := nil;
+  @glIsList := nil;
+  @glIsTexture := nil;
+  @glLightModelf := nil;
+  @glLightModelfv := nil;
+  @glLightModeli := nil;
+  @glLightModeliv := nil;
+  @glLightf := nil;
+  @glLightfv := nil;
+  @glLighti := nil;
+  @glLightiv := nil;
+  @glLineStipple := nil;
+  @glLineWidth := nil;
+  @glListBase := nil;
+  @glLoadIdentity := nil;
+  @glLoadMatrixd := nil;
+  @glLoadMatrixf := nil;
+  @glLoadName := nil;
+  @glLogicOp := nil;
+  @glMap1d := nil;
+  @glMap1f := nil;
+  @glMap2d := nil;
+  @glMap2f := nil;
+  @glMapGrid1d := nil;
+  @glMapGrid1f := nil;
+  @glMapGrid2d := nil;
+  @glMapGrid2f := nil;
+  @glMaterialf := nil;
+  @glMaterialfv := nil;
+  @glMateriali := nil;
+  @glMaterialiv := nil;
+  @glMatrixMode := nil;
+  @glMultMatrixd := nil;
+  @glMultMatrixf := nil;
+  @glNewList := nil;
+  @glNormal3b := nil;
+  @glNormal3bv := nil;
+  @glNormal3d := nil;
+  @glNormal3dv := nil;
+  @glNormal3f := nil;
+  @glNormal3fv := nil;
+  @glNormal3i := nil;
+  @glNormal3iv := nil;
+  @glNormal3s := nil;
+  @glNormal3sv := nil;
+  @glNormalPointer := nil;
+  @glOrtho := nil;
+  @glPassThrough := nil;
+  @glPixelMapfv := nil;
+  @glPixelMapuiv := nil;
+  @glPixelMapusv := nil;
+  @glPixelStoref := nil;
+  @glPixelStorei := nil;
+  @glPixelTransferf := nil;
+  @glPixelTransferi := nil;
+  @glPixelZoom := nil;
+  @glPointSize := nil;
+  @glPolygonMode := nil;
+  @glPolygonOffset := nil;
+  @glPolygonStipple := nil;
+  @glPopAttrib := nil;
+  @glPopClientAttrib := nil;
+  @glPopMatrix := nil;
+  @glPopName := nil;
+  @glPrioritizeTextures := nil;
+  @glPushAttrib := nil;
+  @glPushClientAttrib := nil;
+  @glPushMatrix := nil;
+  @glPushName := nil;
+  @glRasterPos2d := nil;
+  @glRasterPos2dv := nil;
+  @glRasterPos2f := nil;
+  @glRasterPos2fv := nil;
+  @glRasterPos2i := nil;
+  @glRasterPos2iv := nil;
+  @glRasterPos2s := nil;
+  @glRasterPos2sv := nil;
+  @glRasterPos3d := nil;
+  @glRasterPos3dv := nil;
+  @glRasterPos3f := nil;
+  @glRasterPos3fv := nil;
+  @glRasterPos3i := nil;
+  @glRasterPos3iv := nil;
+  @glRasterPos3s := nil;
+  @glRasterPos3sv := nil;
+  @glRasterPos4d := nil;
+  @glRasterPos4dv := nil;
+  @glRasterPos4f := nil;
+  @glRasterPos4fv := nil;
+  @glRasterPos4i := nil;
+  @glRasterPos4iv := nil;
+  @glRasterPos4s := nil;
+  @glRasterPos4sv := nil;
+  @glReadBuffer := nil;
+  @glReadPixels := nil;
+  @glRectd := nil;
+  @glRectdv := nil;
+  @glRectf := nil;
+  @glRectfv := nil;
+  @glRecti := nil;
+  @glRectiv := nil;
+  @glRects := nil;
+  @glRectsv := nil;
+  @glRenderMode := nil;
+  @glRotated := nil;
+  @glRotatef := nil;
+  @glScaled := nil;
+  @glScalef := nil;
+  @glScissor := nil;
+  @glSelectBuffer := nil;
+  @glShadeModel := nil;
+  @glStencilFunc := nil;
+  @glStencilMask := nil;
+  @glStencilOp := nil;
+  @glTexCoord1d := nil;
+  @glTexCoord1dv := nil;
+  @glTexCoord1f := nil;
+  @glTexCoord1fv := nil;
+  @glTexCoord1i := nil;
+  @glTexCoord1iv := nil;
+  @glTexCoord1s := nil;
+  @glTexCoord1sv := nil;
+  @glTexCoord2d := nil;
+  @glTexCoord2dv := nil;
+  @glTexCoord2f := nil;
+  @glTexCoord2fv := nil;
+  @glTexCoord2i := nil;
+  @glTexCoord2iv := nil;
+  @glTexCoord2s := nil;
+  @glTexCoord2sv := nil;
+  @glTexCoord3d := nil;
+  @glTexCoord3dv := nil;
+  @glTexCoord3f := nil;
+  @glTexCoord3fv := nil;
+  @glTexCoord3i := nil;
+  @glTexCoord3iv := nil;
+  @glTexCoord3s := nil;
+  @glTexCoord3sv := nil;
+  @glTexCoord4d := nil;
+  @glTexCoord4dv := nil;
+  @glTexCoord4f := nil;
+  @glTexCoord4fv := nil;
+  @glTexCoord4i := nil;
+  @glTexCoord4iv := nil;
+  @glTexCoord4s := nil;
+  @glTexCoord4sv := nil;
+  @glTexCoordPointer := nil;
+  @glTexEnvf := nil;
+  @glTexEnvfv := nil;
+  @glTexEnvi := nil;
+  @glTexEnviv := nil;
+  @glTexGend := nil;
+  @glTexGendv := nil;
+  @glTexGenf := nil;
+  @glTexGenfv := nil;
+  @glTexGeni := nil;
+  @glTexGeniv := nil;
+  @glTexImage1D := nil;
+  @glTexImage2D := nil;
+  @glTexParameterf := nil;
+  @glTexParameterfv := nil;
+  @glTexParameteri := nil;
+  @glTexParameteriv := nil;
+  @glTexSubImage1D := nil;
+  @glTexSubImage2D := nil;
+  @glTranslated := nil;
+  @glTranslatef := nil;
+  @glVertex2d := nil;
+  @glVertex2dv := nil;
+  @glVertex2f := nil;
+  @glVertex2fv := nil;
+  @glVertex2i := nil;
+  @glVertex2iv := nil;
+  @glVertex2s := nil;
+  @glVertex2sv := nil;
+  @glVertex3d := nil;
+  @glVertex3dv := nil;
+  @glVertex3f := nil;
+  @glVertex3fv := nil;
+  @glVertex3i := nil;
+  @glVertex3iv := nil;
+  @glVertex3s := nil;
+  @glVertex3sv := nil;
+  @glVertex4d := nil;
+  @glVertex4dv := nil;
+  @glVertex4f := nil;
+  @glVertex4fv := nil;
+  @glVertex4i := nil;
+  @glVertex4iv := nil;
+  @glVertex4s := nil;
+  @glVertex4sv := nil;
+  @glVertexPointer := nil;
+  @glViewport := nil;
+  {$IFDEF WINDOWS}
+  @ChoosePixelFormat := nil;
+  {$ENDIF}
+
+  UnLoadModule(LibGL);
+
+end;
+
+procedure LoadOpenGL(const dll: PChar);
+begin
+
+  FreeOpenGL;
+
+  if LoadModule( LibGL, dll ) then
+  begin
+    @glAccum := GetModuleSymbol(LibGL, 'glAccum');
+    @glAlphaFunc := GetModuleSymbol(LibGL, 'glAlphaFunc');
+    @glAreTexturesResident := GetModuleSymbol(LibGL, 'glAreTexturesResident');
+    @glArrayElement := GetModuleSymbol(LibGL, 'glArrayElement');
+    @glBegin := GetModuleSymbol(LibGL, 'glBegin');
+    @glBindTexture := GetModuleSymbol(LibGL, 'glBindTexture');
+    @glBitmap := GetModuleSymbol(LibGL, 'glBitmap');
+    @glBlendFunc := GetModuleSymbol(LibGL, 'glBlendFunc');
+    @glCallList := GetModuleSymbol(LibGL, 'glCallList');
+    @glCallLists := GetModuleSymbol(LibGL, 'glCallLists');
+    @glClear := GetModuleSymbol(LibGL, 'glClear');
+    @glClearAccum := GetModuleSymbol(LibGL, 'glClearAccum');
+    @glClearColor := GetModuleSymbol(LibGL, 'glClearColor');
+    @glClearDepth := GetModuleSymbol(LibGL, 'glClearDepth');
+    @glClearIndex := GetModuleSymbol(LibGL, 'glClearIndex');
+    @glClearStencil := GetModuleSymbol(LibGL, 'glClearStencil');
+    @glClipPlane := GetModuleSymbol(LibGL, 'glClipPlane');
+    @glColor3b := GetModuleSymbol(LibGL, 'glColor3b');
+    @glColor3bv := GetModuleSymbol(LibGL, 'glColor3bv');
+    @glColor3d := GetModuleSymbol(LibGL, 'glColor3d');
+    @glColor3dv := GetModuleSymbol(LibGL, 'glColor3dv');
+    @glColor3f := GetModuleSymbol(LibGL, 'glColor3f');
+    @glColor3fv := GetModuleSymbol(LibGL, 'glColor3fv');
+    @glColor3i := GetModuleSymbol(LibGL, 'glColor3i');
+    @glColor3iv := GetModuleSymbol(LibGL, 'glColor3iv');
+    @glColor3s := GetModuleSymbol(LibGL, 'glColor3s');
+    @glColor3sv := GetModuleSymbol(LibGL, 'glColor3sv');
+    @glColor3ub := GetModuleSymbol(LibGL, 'glColor3ub');
+    @glColor3ubv := GetModuleSymbol(LibGL, 'glColor3ubv');
+    @glColor3ui := GetModuleSymbol(LibGL, 'glColor3ui');
+    @glColor3uiv := GetModuleSymbol(LibGL, 'glColor3uiv');
+    @glColor3us := GetModuleSymbol(LibGL, 'glColor3us');
+    @glColor3usv := GetModuleSymbol(LibGL, 'glColor3usv');
+    @glColor4b := GetModuleSymbol(LibGL, 'glColor4b');
+    @glColor4bv := GetModuleSymbol(LibGL, 'glColor4bv');
+    @glColor4d := GetModuleSymbol(LibGL, 'glColor4d');
+    @glColor4dv := GetModuleSymbol(LibGL, 'glColor4dv');
+    @glColor4f := GetModuleSymbol(LibGL, 'glColor4f');
+    @glColor4fv := GetModuleSymbol(LibGL, 'glColor4fv');
+    @glColor4i := GetModuleSymbol(LibGL, 'glColor4i');
+    @glColor4iv := GetModuleSymbol(LibGL, 'glColor4iv');
+    @glColor4s := GetModuleSymbol(LibGL, 'glColor4s');
+    @glColor4sv := GetModuleSymbol(LibGL, 'glColor4sv');
+    @glColor4ub := GetModuleSymbol(LibGL, 'glColor4ub');
+    @glColor4ubv := GetModuleSymbol(LibGL, 'glColor4ubv');
+    @glColor4ui := GetModuleSymbol(LibGL, 'glColor4ui');
+    @glColor4uiv := GetModuleSymbol(LibGL, 'glColor4uiv');
+    @glColor4us := GetModuleSymbol(LibGL, 'glColor4us');
+    @glColor4usv := GetModuleSymbol(LibGL, 'glColor4usv');
+    @glColorMask := GetModuleSymbol(LibGL, 'glColorMask');
+    @glColorMaterial := GetModuleSymbol(LibGL, 'glColorMaterial');
+    @glColorPointer := GetModuleSymbol(LibGL, 'glColorPointer');
+    @glCopyPixels := GetModuleSymbol(LibGL, 'glCopyPixels');
+    @glCopyTexImage1D := GetModuleSymbol(LibGL, 'glCopyTexImage1D');
+    @glCopyTexImage2D := GetModuleSymbol(LibGL, 'glCopyTexImage2D');
+    @glCopyTexSubImage1D := GetModuleSymbol(LibGL, 'glCopyTexSubImage1D');
+    @glCopyTexSubImage2D := GetModuleSymbol(LibGL, 'glCopyTexSubImage2D');
+    @glCullFace := GetModuleSymbol(LibGL, 'glCullFace');
+    @glDeleteLists := GetModuleSymbol(LibGL, 'glDeleteLists');
+    @glDeleteTextures := GetModuleSymbol(LibGL, 'glDeleteTextures');
+    @glDepthFunc := GetModuleSymbol(LibGL, 'glDepthFunc');
+    @glDepthMask := GetModuleSymbol(LibGL, 'glDepthMask');
+    @glDepthRange := GetModuleSymbol(LibGL, 'glDepthRange');
+    @glDisable := GetModuleSymbol(LibGL, 'glDisable');
+    @glDisableClientState := GetModuleSymbol(LibGL, 'glDisableClientState');
+    @glDrawArrays := GetModuleSymbol(LibGL, 'glDrawArrays');
+    @glDrawBuffer := GetModuleSymbol(LibGL, 'glDrawBuffer');
+    @glDrawElements := GetModuleSymbol(LibGL, 'glDrawElements');
+    @glDrawPixels := GetModuleSymbol(LibGL, 'glDrawPixels');
+    @glEdgeFlag := GetModuleSymbol(LibGL, 'glEdgeFlag');
+    @glEdgeFlagPointer := GetModuleSymbol(LibGL, 'glEdgeFlagPointer');
+    @glEdgeFlagv := GetModuleSymbol(LibGL, 'glEdgeFlagv');
+    @glEnable := GetModuleSymbol(LibGL, 'glEnable');
+    @glEnableClientState := GetModuleSymbol(LibGL, 'glEnableClientState');
+    @glEnd := GetModuleSymbol(LibGL, 'glEnd');
+    @glEndList := GetModuleSymbol(LibGL, 'glEndList');
+    @glEvalCoord1d := GetModuleSymbol(LibGL, 'glEvalCoord1d');
+    @glEvalCoord1dv := GetModuleSymbol(LibGL, 'glEvalCoord1dv');
+    @glEvalCoord1f := GetModuleSymbol(LibGL, 'glEvalCoord1f');
+    @glEvalCoord1fv := GetModuleSymbol(LibGL, 'glEvalCoord1fv');
+    @glEvalCoord2d := GetModuleSymbol(LibGL, 'glEvalCoord2d');
+    @glEvalCoord2dv := GetModuleSymbol(LibGL, 'glEvalCoord2dv');
+    @glEvalCoord2f := GetModuleSymbol(LibGL, 'glEvalCoord2f');
+    @glEvalCoord2fv := GetModuleSymbol(LibGL, 'glEvalCoord2fv');
+    @glEvalMesh1 := GetModuleSymbol(LibGL, 'glEvalMesh1');
+    @glEvalMesh2 := GetModuleSymbol(LibGL, 'glEvalMesh2');
+    @glEvalPoint1 := GetModuleSymbol(LibGL, 'glEvalPoint1');
+    @glEvalPoint2 := GetModuleSymbol(LibGL, 'glEvalPoint2');
+    @glFeedbackBuffer := GetModuleSymbol(LibGL, 'glFeedbackBuffer');
+    @glFinish := GetModuleSymbol(LibGL, 'glFinish');
+    @glFlush := GetModuleSymbol(LibGL, 'glFlush');
+    @glFogf := GetModuleSymbol(LibGL, 'glFogf');
+    @glFogfv := GetModuleSymbol(LibGL, 'glFogfv');
+    @glFogi := GetModuleSymbol(LibGL, 'glFogi');
+    @glFogiv := GetModuleSymbol(LibGL, 'glFogiv');
+    @glFrontFace := GetModuleSymbol(LibGL, 'glFrontFace');
+    @glFrustum := GetModuleSymbol(LibGL, 'glFrustum');
+    @glGenLists := GetModuleSymbol(LibGL, 'glGenLists');
+    @glGenTextures := GetModuleSymbol(LibGL, 'glGenTextures');
+    @glGetBooleanv := GetModuleSymbol(LibGL, 'glGetBooleanv');
+    @glGetClipPlane := GetModuleSymbol(LibGL, 'glGetClipPlane');
+    @glGetDoublev := GetModuleSymbol(LibGL, 'glGetDoublev');
+    @glGetError := GetModuleSymbol(LibGL, 'glGetError');
+    @glGetFloatv := GetModuleSymbol(LibGL, 'glGetFloatv');
+    @glGetIntegerv := GetModuleSymbol(LibGL, 'glGetIntegerv');
+    @glGetLightfv := GetModuleSymbol(LibGL, 'glGetLightfv');
+    @glGetLightiv := GetModuleSymbol(LibGL, 'glGetLightiv');
+    @glGetMapdv := GetModuleSymbol(LibGL, 'glGetMapdv');
+    @glGetMapfv := GetModuleSymbol(LibGL, 'glGetMapfv');
+    @glGetMapiv := GetModuleSymbol(LibGL, 'glGetMapiv');
+    @glGetMaterialfv := GetModuleSymbol(LibGL, 'glGetMaterialfv');
+    @glGetMaterialiv := GetModuleSymbol(LibGL, 'glGetMaterialiv');
+    @glGetPixelMapfv := GetModuleSymbol(LibGL, 'glGetPixelMapfv');
+    @glGetPixelMapuiv := GetModuleSymbol(LibGL, 'glGetPixelMapuiv');
+    @glGetPixelMapusv := GetModuleSymbol(LibGL, 'glGetPixelMapusv');
+    @glGetPointerv := GetModuleSymbol(LibGL, 'glGetPointerv');
+    @glGetPolygonStipple := GetModuleSymbol(LibGL, 'glGetPolygonStipple');
+    @glGetString := GetModuleSymbol(LibGL, 'glGetString');
+    @glGetTexEnvfv := GetModuleSymbol(LibGL, 'glGetTexEnvfv');
+    @glGetTexEnviv := GetModuleSymbol(LibGL, 'glGetTexEnviv');
+    @glGetTexGendv := GetModuleSymbol(LibGL, 'glGetTexGendv');
+    @glGetTexGenfv := GetModuleSymbol(LibGL, 'glGetTexGenfv');
+    @glGetTexGeniv := GetModuleSymbol(LibGL, 'glGetTexGeniv');
+    @glGetTexImage := GetModuleSymbol(LibGL, 'glGetTexImage');
+    @glGetTexLevelParameterfv := GetModuleSymbol(LibGL, 'glGetTexLevelParameterfv');
+    @glGetTexLevelParameteriv := GetModuleSymbol(LibGL, 'glGetTexLevelParameteriv');
+    @glGetTexParameterfv := GetModuleSymbol(LibGL, 'glGetTexParameterfv');
+    @glGetTexParameteriv := GetModuleSymbol(LibGL, 'glGetTexParameteriv');
+    @glHint := GetModuleSymbol(LibGL, 'glHint');
+    @glIndexMask := GetModuleSymbol(LibGL, 'glIndexMask');
+    @glIndexPointer := GetModuleSymbol(LibGL, 'glIndexPointer');
+    @glIndexd := GetModuleSymbol(LibGL, 'glIndexd');
+    @glIndexdv := GetModuleSymbol(LibGL, 'glIndexdv');
+    @glIndexf := GetModuleSymbol(LibGL, 'glIndexf');
+    @glIndexfv := GetModuleSymbol(LibGL, 'glIndexfv');
+    @glIndexi := GetModuleSymbol(LibGL, 'glIndexi');
+    @glIndexiv := GetModuleSymbol(LibGL, 'glIndexiv');
+    @glIndexs := GetModuleSymbol(LibGL, 'glIndexs');
+    @glIndexsv := GetModuleSymbol(LibGL, 'glIndexsv');
+    @glIndexub := GetModuleSymbol(LibGL, 'glIndexub');
+    @glIndexubv := GetModuleSymbol(LibGL, 'glIndexubv');
+    @glInitNames := GetModuleSymbol(LibGL, 'glInitNames');
+    @glInterleavedArrays := GetModuleSymbol(LibGL, 'glInterleavedArrays');
+    @glIsEnabled := GetModuleSymbol(LibGL, 'glIsEnabled');
+    @glIsList := GetModuleSymbol(LibGL, 'glIsList');
+    @glIsTexture := GetModuleSymbol(LibGL, 'glIsTexture');
+    @glLightModelf := GetModuleSymbol(LibGL, 'glLightModelf');
+    @glLightModelfv := GetModuleSymbol(LibGL, 'glLightModelfv');
+    @glLightModeli := GetModuleSymbol(LibGL, 'glLightModeli');
+    @glLightModeliv := GetModuleSymbol(LibGL, 'glLightModeliv');
+    @glLightf := GetModuleSymbol(LibGL, 'glLightf');
+    @glLightfv := GetModuleSymbol(LibGL, 'glLightfv');
+    @glLighti := GetModuleSymbol(LibGL, 'glLighti');
+    @glLightiv := GetModuleSymbol(LibGL, 'glLightiv');
+    @glLineStipple := GetModuleSymbol(LibGL, 'glLineStipple');
+    @glLineWidth := GetModuleSymbol(LibGL, 'glLineWidth');
+    @glListBase := GetModuleSymbol(LibGL, 'glListBase');
+    @glLoadIdentity := GetModuleSymbol(LibGL, 'glLoadIdentity');
+    @glLoadMatrixd := GetModuleSymbol(LibGL, 'glLoadMatrixd');
+    @glLoadMatrixf := GetModuleSymbol(LibGL, 'glLoadMatrixf');
+    @glLoadName := GetModuleSymbol(LibGL, 'glLoadName');
+    @glLogicOp := GetModuleSymbol(LibGL, 'glLogicOp');
+    @glMap1d := GetModuleSymbol(LibGL, 'glMap1d');
+    @glMap1f := GetModuleSymbol(LibGL, 'glMap1f');
+    @glMap2d := GetModuleSymbol(LibGL, 'glMap2d');
+    @glMap2f := GetModuleSymbol(LibGL, 'glMap2f');
+    @glMapGrid1d := GetModuleSymbol(LibGL, 'glMapGrid1d');
+    @glMapGrid1f := GetModuleSymbol(LibGL, 'glMapGrid1f');
+    @glMapGrid2d := GetModuleSymbol(LibGL, 'glMapGrid2d');
+    @glMapGrid2f := GetModuleSymbol(LibGL, 'glMapGrid2f');
+    @glMaterialf := GetModuleSymbol(LibGL, 'glMaterialf');
+    @glMaterialfv := GetModuleSymbol(LibGL, 'glMaterialfv');
+    @glMateriali := GetModuleSymbol(LibGL, 'glMateriali');
+    @glMaterialiv := GetModuleSymbol(LibGL, 'glMaterialiv');
+    @glMatrixMode := GetModuleSymbol(LibGL, 'glMatrixMode');
+    @glMultMatrixd := GetModuleSymbol(LibGL, 'glMultMatrixd');
+    @glMultMatrixf := GetModuleSymbol(LibGL, 'glMultMatrixf');
+    @glNewList := GetModuleSymbol(LibGL, 'glNewList');
+    @glNormal3b := GetModuleSymbol(LibGL, 'glNormal3b');
+    @glNormal3bv := GetModuleSymbol(LibGL, 'glNormal3bv');
+    @glNormal3d := GetModuleSymbol(LibGL, 'glNormal3d');
+    @glNormal3dv := GetModuleSymbol(LibGL, 'glNormal3dv');
+    @glNormal3f := GetModuleSymbol(LibGL, 'glNormal3f');
+    @glNormal3fv := GetModuleSymbol(LibGL, 'glNormal3fv');
+    @glNormal3i := GetModuleSymbol(LibGL, 'glNormal3i');
+    @glNormal3iv := GetModuleSymbol(LibGL, 'glNormal3iv');
+    @glNormal3s := GetModuleSymbol(LibGL, 'glNormal3s');
+    @glNormal3sv := GetModuleSymbol(LibGL, 'glNormal3sv');
+    @glNormalPointer := GetModuleSymbol(LibGL, 'glNormalPointer');
+    @glOrtho := GetModuleSymbol(LibGL, 'glOrtho');
+    @glPassThrough := GetModuleSymbol(LibGL, 'glPassThrough');
+    @glPixelMapfv := GetModuleSymbol(LibGL, 'glPixelMapfv');
+    @glPixelMapuiv := GetModuleSymbol(LibGL, 'glPixelMapuiv');
+    @glPixelMapusv := GetModuleSymbol(LibGL, 'glPixelMapusv');
+    @glPixelStoref := GetModuleSymbol(LibGL, 'glPixelStoref');
+    @glPixelStorei := GetModuleSymbol(LibGL, 'glPixelStorei');
+    @glPixelTransferf := GetModuleSymbol(LibGL, 'glPixelTransferf');
+    @glPixelTransferi := GetModuleSymbol(LibGL, 'glPixelTransferi');
+    @glPixelZoom := GetModuleSymbol(LibGL, 'glPixelZoom');
+    @glPointSize := GetModuleSymbol(LibGL, 'glPointSize');
+    @glPolygonMode := GetModuleSymbol(LibGL, 'glPolygonMode');
+    @glPolygonOffset := GetModuleSymbol(LibGL, 'glPolygonOffset');
+    @glPolygonStipple := GetModuleSymbol(LibGL, 'glPolygonStipple');
+    @glPopAttrib := GetModuleSymbol(LibGL, 'glPopAttrib');
+    @glPopClientAttrib := GetModuleSymbol(LibGL, 'glPopClientAttrib');
+    @glPopMatrix := GetModuleSymbol(LibGL, 'glPopMatrix');
+    @glPopName := GetModuleSymbol(LibGL, 'glPopName');
+    @glPrioritizeTextures := GetModuleSymbol(LibGL, 'glPrioritizeTextures');
+    @glPushAttrib := GetModuleSymbol(LibGL, 'glPushAttrib');
+    @glPushClientAttrib := GetModuleSymbol(LibGL, 'glPushClientAttrib');
+    @glPushMatrix := GetModuleSymbol(LibGL, 'glPushMatrix');
+    @glPushName := GetModuleSymbol(LibGL, 'glPushName');
+    @glRasterPos2d := GetModuleSymbol(LibGL, 'glRasterPos2d');
+    @glRasterPos2dv := GetModuleSymbol(LibGL, 'glRasterPos2dv');
+    @glRasterPos2f := GetModuleSymbol(LibGL, 'glRasterPos2f');
+    @glRasterPos2fv := GetModuleSymbol(LibGL, 'glRasterPos2fv');
+    @glRasterPos2i := GetModuleSymbol(LibGL, 'glRasterPos2i');
+    @glRasterPos2iv := GetModuleSymbol(LibGL, 'glRasterPos2iv');
+    @glRasterPos2s := GetModuleSymbol(LibGL, 'glRasterPos2s');
+    @glRasterPos2sv := GetModuleSymbol(LibGL, 'glRasterPos2sv');
+    @glRasterPos3d := GetModuleSymbol(LibGL, 'glRasterPos3d');
+    @glRasterPos3dv := GetModuleSymbol(LibGL, 'glRasterPos3dv');
+    @glRasterPos3f := GetModuleSymbol(LibGL, 'glRasterPos3f');
+    @glRasterPos3fv := GetModuleSymbol(LibGL, 'glRasterPos3fv');
+    @glRasterPos3i := GetModuleSymbol(LibGL, 'glRasterPos3i');
+    @glRasterPos3iv := GetModuleSymbol(LibGL, 'glRasterPos3iv');
+    @glRasterPos3s := GetModuleSymbol(LibGL, 'glRasterPos3s');
+    @glRasterPos3sv := GetModuleSymbol(LibGL, 'glRasterPos3sv');
+    @glRasterPos4d := GetModuleSymbol(LibGL, 'glRasterPos4d');
+    @glRasterPos4dv := GetModuleSymbol(LibGL, 'glRasterPos4dv');
+    @glRasterPos4f := GetModuleSymbol(LibGL, 'glRasterPos4f');
+    @glRasterPos4fv := GetModuleSymbol(LibGL, 'glRasterPos4fv');
+    @glRasterPos4i := GetModuleSymbol(LibGL, 'glRasterPos4i');
+    @glRasterPos4iv := GetModuleSymbol(LibGL, 'glRasterPos4iv');
+    @glRasterPos4s := GetModuleSymbol(LibGL, 'glRasterPos4s');
+    @glRasterPos4sv := GetModuleSymbol(LibGL, 'glRasterPos4sv');
+    @glReadBuffer := GetModuleSymbol(LibGL, 'glReadBuffer');
+    @glReadPixels := GetModuleSymbol(LibGL, 'glReadPixels');
+    @glRectd := GetModuleSymbol(LibGL, 'glRectd');
+    @glRectdv := GetModuleSymbol(LibGL, 'glRectdv');
+    @glRectf := GetModuleSymbol(LibGL, 'glRectf');
+    @glRectfv := GetModuleSymbol(LibGL, 'glRectfv');
+    @glRecti := GetModuleSymbol(LibGL, 'glRecti');
+    @glRectiv := GetModuleSymbol(LibGL, 'glRectiv');
+    @glRects := GetModuleSymbol(LibGL, 'glRects');
+    @glRectsv := GetModuleSymbol(LibGL, 'glRectsv');
+    @glRenderMode := GetModuleSymbol(LibGL, 'glRenderMode');
+    @glRotated := GetModuleSymbol(LibGL, 'glRotated');
+    @glRotatef := GetModuleSymbol(LibGL, 'glRotatef');
+    @glScaled := GetModuleSymbol(LibGL, 'glScaled');
+    @glScalef := GetModuleSymbol(LibGL, 'glScalef');
+    @glScissor := GetModuleSymbol(LibGL, 'glScissor');
+    @glSelectBuffer := GetModuleSymbol(LibGL, 'glSelectBuffer');
+    @glShadeModel := GetModuleSymbol(LibGL, 'glShadeModel');
+    @glStencilFunc := GetModuleSymbol(LibGL, 'glStencilFunc');
+    @glStencilMask := GetModuleSymbol(LibGL, 'glStencilMask');
+    @glStencilOp := GetModuleSymbol(LibGL, 'glStencilOp');
+    @glTexCoord1d := GetModuleSymbol(LibGL, 'glTexCoord1d');
+    @glTexCoord1dv := GetModuleSymbol(LibGL, 'glTexCoord1dv');
+    @glTexCoord1f := GetModuleSymbol(LibGL, 'glTexCoord1f');
+    @glTexCoord1fv := GetModuleSymbol(LibGL, 'glTexCoord1fv');
+    @glTexCoord1i := GetModuleSymbol(LibGL, 'glTexCoord1i');
+    @glTexCoord1iv := GetModuleSymbol(LibGL, 'glTexCoord1iv');
+    @glTexCoord1s := GetModuleSymbol(LibGL, 'glTexCoord1s');
+    @glTexCoord1sv := GetModuleSymbol(LibGL, 'glTexCoord1sv');
+    @glTexCoord2d := GetModuleSymbol(LibGL, 'glTexCoord2d');
+    @glTexCoord2dv := GetModuleSymbol(LibGL, 'glTexCoord2dv');
+    @glTexCoord2f := GetModuleSymbol(LibGL, 'glTexCoord2f');
+    @glTexCoord2fv := GetModuleSymbol(LibGL, 'glTexCoord2fv');
+    @glTexCoord2i := GetModuleSymbol(LibGL, 'glTexCoord2i');
+    @glTexCoord2iv := GetModuleSymbol(LibGL, 'glTexCoord2iv');
+    @glTexCoord2s := GetModuleSymbol(LibGL, 'glTexCoord2s');
+    @glTexCoord2sv := GetModuleSymbol(LibGL, 'glTexCoord2sv');
+    @glTexCoord3d := GetModuleSymbol(LibGL, 'glTexCoord3d');
+    @glTexCoord3dv := GetModuleSymbol(LibGL, 'glTexCoord3dv');
+    @glTexCoord3f := GetModuleSymbol(LibGL, 'glTexCoord3f');
+    @glTexCoord3fv := GetModuleSymbol(LibGL, 'glTexCoord3fv');
+    @glTexCoord3i := GetModuleSymbol(LibGL, 'glTexCoord3i');
+    @glTexCoord3iv := GetModuleSymbol(LibGL, 'glTexCoord3iv');
+    @glTexCoord3s := GetModuleSymbol(LibGL, 'glTexCoord3s');
+    @glTexCoord3sv := GetModuleSymbol(LibGL, 'glTexCoord3sv');
+    @glTexCoord4d := GetModuleSymbol(LibGL, 'glTexCoord4d');
+    @glTexCoord4dv := GetModuleSymbol(LibGL, 'glTexCoord4dv');
+    @glTexCoord4f := GetModuleSymbol(LibGL, 'glTexCoord4f');
+    @glTexCoord4fv := GetModuleSymbol(LibGL, 'glTexCoord4fv');
+    @glTexCoord4i := GetModuleSymbol(LibGL, 'glTexCoord4i');
+    @glTexCoord4iv := GetModuleSymbol(LibGL, 'glTexCoord4iv');
+    @glTexCoord4s := GetModuleSymbol(LibGL, 'glTexCoord4s');
+    @glTexCoord4sv := GetModuleSymbol(LibGL, 'glTexCoord4sv');
+    @glTexCoordPointer := GetModuleSymbol(LibGL, 'glTexCoordPointer');
+    @glTexEnvf := GetModuleSymbol(LibGL, 'glTexEnvf');
+    @glTexEnvfv := GetModuleSymbol(LibGL, 'glTexEnvfv');
+    @glTexEnvi := GetModuleSymbol(LibGL, 'glTexEnvi');
+    @glTexEnviv := GetModuleSymbol(LibGL, 'glTexEnviv');
+    @glTexGend := GetModuleSymbol(LibGL, 'glTexGend');
+    @glTexGendv := GetModuleSymbol(LibGL, 'glTexGendv');
+    @glTexGenf := GetModuleSymbol(LibGL, 'glTexGenf');
+    @glTexGenfv := GetModuleSymbol(LibGL, 'glTexGenfv');
+    @glTexGeni := GetModuleSymbol(LibGL, 'glTexGeni');
+    @glTexGeniv := GetModuleSymbol(LibGL, 'glTexGeniv');
+    @glTexImage1D := GetModuleSymbol(LibGL, 'glTexImage1D');
+    @glTexImage2D := GetModuleSymbol(LibGL, 'glTexImage2D');
+    @glTexParameterf := GetModuleSymbol(LibGL, 'glTexParameterf');
+    @glTexParameterfv := GetModuleSymbol(LibGL, 'glTexParameterfv');
+    @glTexParameteri := GetModuleSymbol(LibGL, 'glTexParameteri');
+    @glTexParameteriv := GetModuleSymbol(LibGL, 'glTexParameteriv');
+    @glTexSubImage1D := GetModuleSymbol(LibGL, 'glTexSubImage1D');
+    @glTexSubImage2D := GetModuleSymbol(LibGL, 'glTexSubImage2D');
+    @glTranslated := GetModuleSymbol(LibGL, 'glTranslated');
+    @glTranslatef := GetModuleSymbol(LibGL, 'glTranslatef');
+    @glVertex2d := GetModuleSymbol(LibGL, 'glVertex2d');
+    @glVertex2dv := GetModuleSymbol(LibGL, 'glVertex2dv');
+    @glVertex2f := GetModuleSymbol(LibGL, 'glVertex2f');
+    @glVertex2fv := GetModuleSymbol(LibGL, 'glVertex2fv');
+    @glVertex2i := GetModuleSymbol(LibGL, 'glVertex2i');
+    @glVertex2iv := GetModuleSymbol(LibGL, 'glVertex2iv');
+    @glVertex2s := GetModuleSymbol(LibGL, 'glVertex2s');
+    @glVertex2sv := GetModuleSymbol(LibGL, 'glVertex2sv');
+    @glVertex3d := GetModuleSymbol(LibGL, 'glVertex3d');
+    @glVertex3dv := GetModuleSymbol(LibGL, 'glVertex3dv');
+    @glVertex3f := GetModuleSymbol(LibGL, 'glVertex3f');
+    @glVertex3fv := GetModuleSymbol(LibGL, 'glVertex3fv');
+    @glVertex3i := GetModuleSymbol(LibGL, 'glVertex3i');
+    @glVertex3iv := GetModuleSymbol(LibGL, 'glVertex3iv');
+    @glVertex3s := GetModuleSymbol(LibGL, 'glVertex3s');
+    @glVertex3sv := GetModuleSymbol(LibGL, 'glVertex3sv');
+    @glVertex4d := GetModuleSymbol(LibGL, 'glVertex4d');
+    @glVertex4dv := GetModuleSymbol(LibGL, 'glVertex4dv');
+    @glVertex4f := GetModuleSymbol(LibGL, 'glVertex4f');
+    @glVertex4fv := GetModuleSymbol(LibGL, 'glVertex4fv');
+    @glVertex4i := GetModuleSymbol(LibGL, 'glVertex4i');
+    @glVertex4iv := GetModuleSymbol(LibGL, 'glVertex4iv');
+    @glVertex4s := GetModuleSymbol(LibGL, 'glVertex4s');
+    @glVertex4sv := GetModuleSymbol(LibGL, 'glVertex4sv');
+    @glVertexPointer := GetModuleSymbol(LibGL, 'glVertexPointer');
+    @glViewport := GetModuleSymbol(LibGL, 'glViewport');
+
+    {$IFDEF WINDOWS}
+    @ChoosePixelFormat := GetModuleSymbol(LibGL, 'ChoosePixelFormat');
+    if not Assigned(ChoosePixelFormat) then
+      {$IFNDEF FPC}@{$ENDIF}ChoosePixelFormat := @Windows.ChoosePixelFormat;
+    {$ENDIF}
+  end;
+end;
+
+initialization
+  {$IF Defined(CPU386) or Defined(CPUI386) or Defined(CPUX86_64)}
+  Set8087CW($133F);
+  {$IFEND}
+
+  LoadOpenGL( GLLibName );
+
+finalization
+
+  FreeOpenGL;
+
+end.
+
diff --git a/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glext.pas b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glext.pas
new file mode 100644
index 00000000..871247a9
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glext.pas
@@ -0,0 +1,9579 @@
+unit glext;
+{
+  $Id: glext.pas,v 1.6 2007/05/20 20:28:31 savage Exp $
+  
+}
+(**************************************************
+ *        OpenGL extension loading library        *
+ * Generated by MetaGLext, written by Tom Nuydens *
+ *  (tom@delphi3d.net -- http://www.delphi3d.net  *
+ **************************************************)
+
+{
+  $Log: glext.pas,v $
+  Revision 1.6  2007/05/20 20:28:31  savage
+  Initial Changes to Handle 64 Bits
+
+  Revision 1.5  2006/01/11 22:39:02  drellis
+  Updated to Support Up to OpenGL 2.0
+
+  Revision 1.4  2005/01/05 00:28:40  savage
+  Forgot to wrap a couple of Load_WGL function calls with an IFDEF WIN32. Fixed so now compiles under Linux as well.
+
+  Revision 1.3  2004/08/24 19:33:06  savage
+  Removed declarations of SDL_GL_GetProcAddress as the correct ones are in sdl.pas.
+
+  Revision 1.2  2004/08/09 00:38:01  savage
+  Updated to Tom's latest version. May contains bugs, but I hope not.
+
+  Revision 1.1  2004/03/30 21:53:54  savage
+  Moved to it's own folder.
+
+  Revision 1.6  2004/03/28 00:28:43  savage
+  Fixed some glSecondaryColor definitions...
+
+  Revision 1.5  2004/02/20 17:18:16  savage
+  Forgot to prefix function pointer with @ for FPC and other Pascal compilers.
+
+  Revision 1.4  2004/02/20 17:09:55  savage
+  Code tidied up in gl, glu and glut, while extensions in glext.pas are now loaded using SDL_GL_GetProcAddress, thus making it more cross-platform compatible, but now more tied to SDL.
+
+  Revision 1.3  2004/02/14 22:36:29  savage
+  Fixed inconsistencies of using LoadLibrary and LoadModule.
+  Now all units make use of LoadModule rather than LoadLibrary and other dynamic proc procedures.
+
+  Revision 1.2  2004/02/14 00:09:19  savage
+  Changed uses to now make use of moduleloader.pas rather than dllfuncs.pas
+
+  Revision 1.1  2004/02/05 00:08:19  savage
+  Module 1.0 release
+
+  Revision 1.7  2003/06/02 12:32:13  savage
+  Modified Sources to avoid warnings with Delphi by moving CVS Logging to the top of the header files. Hopefully CVS Logging still works.
+
+}
+
+interface
+
+{$I jedi-sdl.inc}
+
+uses
+  SysUtils,
+{$IFDEF __GPC__}
+  gpc,
+{$ENDIF}
+
+{$IFDEF WINDOWS}
+  Windows,
+{$ENDIF}
+  moduleloader,
+  gl;
+
+// Test if the given extension name is present in the given extension string.
+function glext_ExtensionSupported(const extension: PChar; const searchIn: PChar): Boolean;
+
+// Load a Specific Extension
+function glext_LoadExtension(ext: String): Boolean;
+// Some types that were introduced by extensions:
+type
+  GLintptrARB = Integer;
+  PGLintptrARB = ^GLintptrARB;
+
+  GLsizeiptrARB = Integer;
+  PGLsizeiptrARB = ^GLsizeiptrARB;
+
+  GLcharARB = Char;
+  PGLcharARB = ^GLcharARB;
+
+  GLhandleARB = Cardinal;
+  PGLhandleARB = ^GLhandleARB;
+
+  GLintptr = Integer;
+  PGLintptr = ^GLintptr;
+
+  GLsizeiptr = Integer;
+  PGLsizeiptr = ^GLsizeiptr;
+
+  GLchar = Char;
+  PGLchar = ^GLchar;
+
+//***** GL_version_1_2 *****//
+const
+  GL_UNSIGNED_BYTE_3_3_2 = $8032;
+  GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
+  GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
+  GL_UNSIGNED_INT_8_8_8_8 = $8035;
+  GL_UNSIGNED_INT_10_10_10_2 = $8036;
+  GL_RESCALE_NORMAL = $803A;
+  GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
+  GL_UNSIGNED_SHORT_5_6_5 = $8363;
+  GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
+  GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
+  GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
+  GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
+  GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
+  GL_BGR = $80E0;
+  GL_BGRA = $80E1;
+  GL_MAX_ELEMENTS_VERTICES = $80E8;
+  GL_MAX_ELEMENTS_INDICES = $80E9;
+  GL_CLAMP_TO_EDGE = $812F;
+  GL_TEXTURE_MIN_LOD = $813A;
+  GL_TEXTURE_MAX_LOD = $813B;
+  GL_TEXTURE_BASE_LEVEL = $813C;
+  GL_TEXTURE_MAX_LEVEL = $813D;
+  GL_LIGHT_MODEL_COLOR_CONTROL = $81F8;
+  GL_SINGLE_COLOR = $81F9;
+  GL_SEPARATE_SPECULAR_COLOR = $81FA;
+  GL_SMOOTH_POINT_SIZE_RANGE = $0B12;
+  GL_SMOOTH_POINT_SIZE_GRANULARITY = $0B13;
+  GL_SMOOTH_LINE_WIDTH_RANGE = $0B22;
+  GL_SMOOTH_LINE_WIDTH_GRANULARITY = $0B23;
+  GL_ALIASED_POINT_SIZE_RANGE = $846D;
+  GL_ALIASED_LINE_WIDTH_RANGE = $846E;
+  GL_PACK_SKIP_IMAGES = $806B;
+  GL_PACK_IMAGE_HEIGHT = $806C;
+  GL_UNPACK_SKIP_IMAGES = $806D;
+  GL_UNPACK_IMAGE_HEIGHT = $806E;
+  GL_TEXTURE_3D = $806F;
+  GL_PROXY_TEXTURE_3D = $8070;
+  GL_TEXTURE_DEPTH = $8071;
+  GL_TEXTURE_WRAP_R = $8072;
+  GL_MAX_3D_TEXTURE_SIZE = $8073;
+var
+  glDrawRangeElements: procedure(mode: GLenum; start: GLuint; _end: GLuint; count: GLsizei; _type: GLenum; const indices: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexImage3D: procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexSubImage3D: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyTexSubImage3D: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; x: GLint; y: GLint; width: GLsizei; height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_version_1_2: Boolean;
+
+//***** GL_ARB_imaging *****//
+const
+  GL_CONSTANT_COLOR = $8001;
+  GL_ONE_MINUS_CONSTANT_COLOR = $8002;
+  GL_CONSTANT_ALPHA = $8003;
+  GL_ONE_MINUS_CONSTANT_ALPHA = $8004;
+  GL_BLEND_COLOR = $8005;
+  GL_FUNC_ADD = $8006;
+  GL_MIN = $8007;
+  GL_MAX = $8008;
+  GL_BLEND_EQUATION = $8009;
+  GL_FUNC_SUBTRACT = $800A;
+  GL_FUNC_REVERSE_SUBTRACT = $800B;
+  GL_CONVOLUTION_1D = $8010;
+  GL_CONVOLUTION_2D = $8011;
+  GL_SEPARABLE_2D = $8012;
+  GL_CONVOLUTION_BORDER_MODE = $8013;
+  GL_CONVOLUTION_FILTER_SCALE = $8014;
+  GL_CONVOLUTION_FILTER_BIAS = $8015;
+  GL_REDUCE = $8016;
+  GL_CONVOLUTION_FORMAT = $8017;
+  GL_CONVOLUTION_WIDTH = $8018;
+  GL_CONVOLUTION_HEIGHT = $8019;
+  GL_MAX_CONVOLUTION_WIDTH = $801A;
+  GL_MAX_CONVOLUTION_HEIGHT = $801B;
+  GL_POST_CONVOLUTION_RED_SCALE = $801C;
+  GL_POST_CONVOLUTION_GREEN_SCALE = $801D;
+  GL_POST_CONVOLUTION_BLUE_SCALE = $801E;
+  GL_POST_CONVOLUTION_ALPHA_SCALE = $801F;
+  GL_POST_CONVOLUTION_RED_BIAS = $8020;
+  GL_POST_CONVOLUTION_GREEN_BIAS = $8021;
+  GL_POST_CONVOLUTION_BLUE_BIAS = $8022;
+  GL_POST_CONVOLUTION_ALPHA_BIAS = $8023;
+  GL_HISTOGRAM = $8024;
+  GL_PROXY_HISTOGRAM = $8025;
+  GL_HISTOGRAM_WIDTH = $8026;
+  GL_HISTOGRAM_FORMAT = $8027;
+  GL_HISTOGRAM_RED_SIZE = $8028;
+  GL_HISTOGRAM_GREEN_SIZE = $8029;
+  GL_HISTOGRAM_BLUE_SIZE = $802A;
+  GL_HISTOGRAM_ALPHA_SIZE = $802B;
+  GL_HISTOGRAM_LUMINANCE_SIZE = $802C;
+  GL_HISTOGRAM_SINK = $802D;
+  GL_MINMAX = $802E;
+  GL_MINMAX_FORMAT = $802F;
+  GL_MINMAX_SINK = $8030;
+  GL_TABLE_TOO_LARGE = $8031;
+  GL_COLOR_MATRIX = $80B1;
+  GL_COLOR_MATRIX_STACK_DEPTH = $80B2;
+  GL_MAX_COLOR_MATRIX_STACK_DEPTH = $80B3;
+  GL_POST_COLOR_MATRIX_RED_SCALE = $80B4;
+  GL_POST_COLOR_MATRIX_GREEN_SCALE = $80B5;
+  GL_POST_COLOR_MATRIX_BLUE_SCALE = $80B6;
+  GL_POST_COLOR_MATRIX_ALPHA_SCALE = $80B7;
+  GL_POST_COLOR_MATRIX_RED_BIAS = $80B8;
+  GL_POST_COLOR_MATRIX_GREEN_BIAS = $80B9;
+  GL_POST_COLOR_MATRIX_BLUE_BIAS = $80BA;
+  GL_POST_COLOR_MATIX_ALPHA_BIAS = $80BB;
+  GL_COLOR_TABLE = $80D0;
+  GL_POST_CONVOLUTION_COLOR_TABLE = $80D1;
+  GL_POST_COLOR_MATRIX_COLOR_TABLE = $80D2;
+  GL_PROXY_COLOR_TABLE = $80D3;
+  GL_PROXY_POST_CONVOLUTION_COLOR_TABLE = $80D4;
+  GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE = $80D5;
+  GL_COLOR_TABLE_SCALE = $80D6;
+  GL_COLOR_TABLE_BIAS = $80D7;
+  GL_COLOR_TABLE_FORMAT = $80D8;
+  GL_COLOR_TABLE_WIDTH = $80D9;
+  GL_COLOR_TABLE_RED_SIZE = $80DA;
+  GL_COLOR_TABLE_GREEN_SIZE = $80DB;
+  GL_COLOR_TABLE_BLUE_SIZE = $80DC;
+  GL_COLOR_TABLE_ALPHA_SIZE = $80DD;
+  GL_COLOR_TABLE_LUMINANCE_SIZE = $80DE;
+  GL_COLOR_TABLE_INTENSITY_SIZE = $80DF;
+  GL_IGNORE_BORDER = $8150;
+  GL_CONSTANT_BORDER = $8151;
+  GL_WRAP_BORDER = $8152;
+  GL_REPLICATE_BORDER = $8153;
+  GL_CONVOLUTION_BORDER_COLOR = $8154;
+var
+  glColorTable: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const table: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorTableParameterfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorTableParameteriv: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyColorTable: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetColorTable: procedure(target: GLenum; format: GLenum; _type: GLenum; table: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetColorTableParameterfv: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetColorTableParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorSubTable: procedure(target: GLenum; start: GLsizei; count: GLsizei; format: GLenum; _type: GLenum; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyColorSubTable: procedure(target: GLenum; start: GLsizei; x: GLint; y: GLint; width: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionFilter1D: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const image: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionFilter2D: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const image: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionParameterf: procedure(target: GLenum; pname: GLenum; params: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionParameterfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionParameteri: procedure(target: GLenum; pname: GLenum; params: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionParameteriv: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyConvolutionFilter1D: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyConvolutionFilter2D: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei; height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetConvolutionFilter: procedure(target: GLenum; format: GLenum; _type: GLenum; image: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetConvolutionParameterfv: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetConvolutionParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetSeparableFilter: procedure(target: GLenum; format: GLenum; _type: GLenum; row: PGLvoid; column: PGLvoid; span: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSeparableFilter2D: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const row: PGLvoid; const column: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetHistogram: procedure(target: GLenum; reset: GLboolean; format: GLenum; _type: GLenum; values: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetHistogramParameterfv: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetHistogramParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMinmax: procedure(target: GLenum; reset: GLboolean; format: GLenum; _type: GLenum; values: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMinmaxParameterfv: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMinmaxParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glHistogram: procedure(target: GLenum; width: GLsizei; internalformat: GLenum; sink: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMinmax: procedure(target: GLenum; internalformat: GLenum; sink: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glResetHistogram: procedure(target: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glResetMinmax: procedure(target: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBlendEquation: procedure(mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBlendColor: procedure(red: GLclampf; green: GLclampf; blue: GLclampf; alpha: GLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_imaging: Boolean;
+
+//***** GL_version_1_3 *****//
+const
+  GL_TEXTURE0 = $84C0;
+  GL_TEXTURE1 = $84C1;
+  GL_TEXTURE2 = $84C2;
+  GL_TEXTURE3 = $84C3;
+  GL_TEXTURE4 = $84C4;
+  GL_TEXTURE5 = $84C5;
+  GL_TEXTURE6 = $84C6;
+  GL_TEXTURE7 = $84C7;
+  GL_TEXTURE8 = $84C8;
+  GL_TEXTURE9 = $84C9;
+  GL_TEXTURE10 = $84CA;
+  GL_TEXTURE11 = $84CB;
+  GL_TEXTURE12 = $84CC;
+  GL_TEXTURE13 = $84CD;
+  GL_TEXTURE14 = $84CE;
+  GL_TEXTURE15 = $84CF;
+  GL_TEXTURE16 = $84D0;
+  GL_TEXTURE17 = $84D1;
+  GL_TEXTURE18 = $84D2;
+  GL_TEXTURE19 = $84D3;
+  GL_TEXTURE20 = $84D4;
+  GL_TEXTURE21 = $84D5;
+  GL_TEXTURE22 = $84D6;
+  GL_TEXTURE23 = $84D7;
+  GL_TEXTURE24 = $84D8;
+  GL_TEXTURE25 = $84D9;
+  GL_TEXTURE26 = $84DA;
+  GL_TEXTURE27 = $84DB;
+  GL_TEXTURE28 = $84DC;
+  GL_TEXTURE29 = $84DD;
+  GL_TEXTURE30 = $84DE;
+  GL_TEXTURE31 = $84DF;
+  GL_ACTIVE_TEXTURE = $84E0;
+  GL_CLIENT_ACTIVE_TEXTURE = $84E1;
+  GL_MAX_TEXTURE_UNITS = $84E2;
+  GL_TRANSPOSE_MODELVIEW_MATRIX = $84E3;
+  GL_TRANSPOSE_PROJECTION_MATRIX = $84E4;
+  GL_TRANSPOSE_TEXTURE_MATRIX = $84E5;
+  GL_TRANSPOSE_COLOR_MATRIX = $84E6;
+  GL_MULTISAMPLE = $809D;
+  GL_SAMPLE_ALPHA_TO_COVERAGE = $809E;
+  GL_SAMPLE_ALPHA_TO_ONE = $809F;
+  GL_SAMPLE_COVERAGE = $80A0;
+  GL_SAMPLE_BUFFERS = $80A8;
+  GL_SAMPLES = $80A9;
+  GL_SAMPLE_COVERAGE_VALUE = $80AA;
+  GL_SAMPLE_COVERAGE_INVERT = $80AB;
+  GL_MULTISAMPLE_BIT = $20000000;
+  GL_NORMAL_MAP = $8511;
+  GL_REFLECTION_MAP = $8512;
+  GL_TEXTURE_CUBE_MAP = $8513;
+  GL_TEXTURE_BINDING_CUBE_MAP = $8514;
+  GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
+  GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
+  GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
+  GL_PROXY_TEXTURE_CUBE_MAP = $851B;
+  GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
+  GL_COMPRESSED_ALPHA = $84E9;
+  GL_COMPRESSED_LUMINANCE = $84EA;
+  GL_COMPRESSED_LUMINANCE_ALPHA = $84EB;
+  GL_COMPRESSED_INTENSITY = $84EC;
+  GL_COMPRESSED_RGB = $84ED;
+  GL_COMPRESSED_RGBA = $84EE;
+  GL_TEXTURE_COMPRESSION_HINT = $84EF;
+  GL_TEXTURE_COMPRESSED_IMAGE_SIZE = $86A0;
+  GL_TEXTURE_COMPRESSED = $86A1;
+  GL_NUM_COMPRESSED_TEXTURE_FORMATS = $86A2;
+  GL_COMPRESSED_TEXTURE_FORMATS = $86A3;
+  GL_CLAMP_TO_BORDER = $812D;
+  GL_CLAMP_TO_BORDER_SGIS = $812D;
+  GL_COMBINE = $8570;
+  GL_COMBINE_RGB = $8571;
+  GL_COMBINE_ALPHA = $8572;
+  GL_SOURCE0_RGB = $8580;
+  GL_SOURCE1_RGB = $8581;
+  GL_SOURCE2_RGB = $8582;
+  GL_SOURCE0_ALPHA = $8588;
+  GL_SOURCE1_ALPHA = $8589;
+  GL_SOURCE2_ALPHA = $858A;
+  GL_OPERAND0_RGB = $8590;
+  GL_OPERAND1_RGB = $8591;
+  GL_OPERAND2_RGB = $8592;
+  GL_OPERAND0_ALPHA = $8598;
+  GL_OPERAND1_ALPHA = $8599;
+  GL_OPERAND2_ALPHA = $859A;
+  GL_RGB_SCALE = $8573;
+  GL_ADD_SIGNED = $8574;
+  GL_INTERPOLATE = $8575;
+  GL_SUBTRACT = $84E7;
+  GL_CONSTANT = $8576;
+  GL_PRIMARY_COLOR = $8577;
+  GL_PREVIOUS = $8578;
+  GL_DOT3_RGB = $86AE;
+  GL_DOT3_RGBA = $86AF;
+var
+  glActiveTexture: procedure(texture: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClientActiveTexture: procedure(texture: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1d: procedure(target: GLenum; s: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1dv: procedure(target: GLenum; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1f: procedure(target: GLenum; s: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1fv: procedure(target: GLenum; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1i: procedure(target: GLenum; s: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1iv: procedure(target: GLenum; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1s: procedure(target: GLenum; s: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1sv: procedure(target: GLenum; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2d: procedure(target: GLenum; s: GLdouble; t: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2dv: procedure(target: GLenum; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2f: procedure(target: GLenum; s: GLfloat; t: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2fv: procedure(target: GLenum; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2i: procedure(target: GLenum; s: GLint; t: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2iv: procedure(target: GLenum; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2s: procedure(target: GLenum; s: GLshort; t: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2sv: procedure(target: GLenum; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3d: procedure(target: GLenum; s: GLdouble; t: GLdouble; r: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3dv: procedure(target: GLenum; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3f: procedure(target: GLenum; s: GLfloat; t: GLfloat; r: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3fv: procedure(target: GLenum; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3i: procedure(target: GLenum; s: GLint; t: GLint; r: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3iv: procedure(target: GLenum; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3s: procedure(target: GLenum; s: GLshort; t: GLshort; r: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3sv: procedure(target: GLenum; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4d: procedure(target: GLenum; s: GLdouble; t: GLdouble; r: GLdouble; q: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4dv: procedure(target: GLenum; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4f: procedure(target: GLenum; s: GLfloat; t: GLfloat; r: GLfloat; q: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4fv: procedure(target: GLenum; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4i: procedure(target: GLenum; s: GLint; t: GLint; r: GLint; q: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4iv: procedure(target: GLenum; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4s: procedure(target: GLenum; s: GLshort; t: GLshort; r: GLshort; q: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4sv: procedure(target: GLenum; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadTransposeMatrixf: procedure(const m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadTransposeMatrixd: procedure(const m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultTransposeMatrixf: procedure(const m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultTransposeMatrixd: procedure(const m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSampleCoverage: procedure(value: GLclampf; invert: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexImage3D: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexImage2D: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexImage1D: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexSubImage3D: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexSubImage2D: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexSubImage1D: procedure(target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetCompressedTexImage: procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_version_1_3: Boolean;
+
+//***** GL_ARB_multitexture *****//
+const
+  GL_TEXTURE0_ARB = $84C0;
+  GL_TEXTURE1_ARB = $84C1;
+  GL_TEXTURE2_ARB = $84C2;
+  GL_TEXTURE3_ARB = $84C3;
+  GL_TEXTURE4_ARB = $84C4;
+  GL_TEXTURE5_ARB = $84C5;
+  GL_TEXTURE6_ARB = $84C6;
+  GL_TEXTURE7_ARB = $84C7;
+  GL_TEXTURE8_ARB = $84C8;
+  GL_TEXTURE9_ARB = $84C9;
+  GL_TEXTURE10_ARB = $84CA;
+  GL_TEXTURE11_ARB = $84CB;
+  GL_TEXTURE12_ARB = $84CC;
+  GL_TEXTURE13_ARB = $84CD;
+  GL_TEXTURE14_ARB = $84CE;
+  GL_TEXTURE15_ARB = $84CF;
+  GL_TEXTURE16_ARB = $84D0;
+  GL_TEXTURE17_ARB = $84D1;
+  GL_TEXTURE18_ARB = $84D2;
+  GL_TEXTURE19_ARB = $84D3;
+  GL_TEXTURE20_ARB = $84D4;
+  GL_TEXTURE21_ARB = $84D5;
+  GL_TEXTURE22_ARB = $84D6;
+  GL_TEXTURE23_ARB = $84D7;
+  GL_TEXTURE24_ARB = $84D8;
+  GL_TEXTURE25_ARB = $84D9;
+  GL_TEXTURE26_ARB = $84DA;
+  GL_TEXTURE27_ARB = $84DB;
+  GL_TEXTURE28_ARB = $84DC;
+  GL_TEXTURE29_ARB = $84DD;
+  GL_TEXTURE30_ARB = $84DE;
+  GL_TEXTURE31_ARB = $84DF;
+  GL_ACTIVE_TEXTURE_ARB = $84E0;
+  GL_CLIENT_ACTIVE_TEXTURE_ARB = $84E1;
+  GL_MAX_TEXTURE_UNITS_ARB = $84E2;
+var
+  glActiveTextureARB: procedure(texture: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClientActiveTextureARB: procedure(texture: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1dARB: procedure(target: GLenum; s: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1dvARB: procedure(target: GLenum; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1fARB: procedure(target: GLenum; s: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1fvARB: procedure(target: GLenum; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1iARB: procedure(target: GLenum; s: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1ivARB: procedure(target: GLenum; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1sARB: procedure(target: GLenum; s: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1svARB: procedure(target: GLenum; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2dARB: procedure(target: GLenum; s: GLdouble; t: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2dvARB: procedure(target: GLenum; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2fARB: procedure(target: GLenum; s: GLfloat; t: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2fvARB: procedure(target: GLenum; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2iARB: procedure(target: GLenum; s: GLint; t: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2ivARB: procedure(target: GLenum; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2sARB: procedure(target: GLenum; s: GLshort; t: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2svARB: procedure(target: GLenum; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3dARB: procedure(target: GLenum; s: GLdouble; t: GLdouble; r: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3dvARB: procedure(target: GLenum; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3fARB: procedure(target: GLenum; s: GLfloat; t: GLfloat; r: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3fvARB: procedure(target: GLenum; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3iARB: procedure(target: GLenum; s: GLint; t: GLint; r: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3ivARB: procedure(target: GLenum; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3sARB: procedure(target: GLenum; s: GLshort; t: GLshort; r: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3svARB: procedure(target: GLenum; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4dARB: procedure(target: GLenum; s: GLdouble; t: GLdouble; r: GLdouble; q: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4dvARB: procedure(target: GLenum; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4fARB: procedure(target: GLenum; s: GLfloat; t: GLfloat; r: GLfloat; q: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4fvARB: procedure(target: GLenum; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4iARB: procedure(target: GLenum; s: GLint; t: GLint; r: GLint; q: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4ivARB: procedure(target: GLenum; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4sARB: procedure(target: GLenum; s: GLshort; t: GLshort; r: GLshort; q: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4svARB: procedure(target: GLenum; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_multitexture: Boolean;
+
+//***** GL_ARB_transpose_matrix *****//
+const
+  GL_TRANSPOSE_MODELVIEW_MATRIX_ARB = $84E3;
+  GL_TRANSPOSE_PROJECTION_MATRIX_ARB = $84E4;
+  GL_TRANSPOSE_TEXTURE_MATRIX_ARB = $84E5;
+  GL_TRANSPOSE_COLOR_MATRIX_ARB = $84E6;
+var
+  glLoadTransposeMatrixfARB: procedure(m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadTransposeMatrixdARB: procedure(m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultTransposeMatrixfARB: procedure(m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultTransposeMatrixdARB: procedure(m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_transpose_matrix: Boolean;
+
+//***** GL_ARB_multisample *****//
+const
+  WGL_SAMPLE_BUFFERS_ARB = $2041;
+  WGL_SAMPLES_ARB = $2042;
+  GL_MULTISAMPLE_ARB = $809D;
+  GL_SAMPLE_ALPHA_TO_COVERAGE_ARB = $809E;
+  GL_SAMPLE_ALPHA_TO_ONE_ARB = $809F;
+  GL_SAMPLE_COVERAGE_ARB = $80A0;
+  GL_MULTISAMPLE_BIT_ARB = $20000000;
+  GL_SAMPLE_BUFFERS_ARB = $80A8;
+  GL_SAMPLES_ARB = $80A9;
+  GL_SAMPLE_COVERAGE_VALUE_ARB = $80AA;
+  GL_SAMPLE_COVERAGE_INVERT_ARB = $80AB;
+var
+  glSampleCoverageARB: procedure(value: GLclampf; invert: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_multisample: Boolean;
+
+//***** GL_ARB_texture_env_add *****//
+
+function Load_GL_ARB_texture_env_add: Boolean;
+
+{$IFDEF WINDOWS}
+//***** WGL_ARB_extensions_string *****//
+var
+  wglGetExtensionsStringARB: function(hdc: HDC): Pchar; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_ARB_extensions_string: Boolean;
+
+//***** WGL_ARB_buffer_region *****//
+const
+  WGL_FRONT_COLOR_BUFFER_BIT_ARB = $0001;
+  WGL_BACK_COLOR_BUFFER_BIT_ARB = $0002;
+  WGL_DEPTH_BUFFER_BIT_ARB = $0004;
+  WGL_STENCIL_BUFFER_BIT_ARB = $0008;
+var
+  wglCreateBufferRegionARB: function(hDC: HDC; iLayerPlane: GLint; uType: GLuint): THandle; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglDeleteBufferRegionARB: procedure(hRegion: THandle); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglSaveBufferRegionARB: function(hRegion: THandle; x: GLint; y: GLint; width: GLint; height: GLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglRestoreBufferRegionARB: function(hRegion: THandle; x: GLint; y: GLint; width: GLint; height: GLint; xSrc: GLint; ySrc: GLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_ARB_buffer_region: Boolean;
+{$ENDIF}
+
+//***** GL_ARB_texture_cube_map *****//
+const
+  GL_NORMAL_MAP_ARB = $8511;
+  GL_REFLECTION_MAP_ARB = $8512;
+  GL_TEXTURE_CUBE_MAP_ARB = $8513;
+  GL_TEXTURE_BINDING_CUBE_MAP_ARB = $8514;
+  GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB = $8515;
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB = $8516;
+  GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB = $8517;
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB = $8518;
+  GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB = $8519;
+  GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB = $851A;
+  GL_PROXY_TEXTURE_CUBE_MAP_ARB = $851B;
+  GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB = $851C;
+
+function Load_GL_ARB_texture_cube_map: Boolean;
+
+//***** GL_ARB_depth_texture *****//
+const
+  GL_DEPTH_COMPONENT16_ARB = $81A5;
+  GL_DEPTH_COMPONENT24_ARB = $81A6;
+  GL_DEPTH_COMPONENT32_ARB = $81A7;
+  GL_TEXTURE_DEPTH_SIZE_ARB = $884A;
+  GL_DEPTH_TEXTURE_MODE_ARB = $884B;
+
+function Load_GL_ARB_depth_texture: Boolean;
+
+//***** GL_ARB_point_parameters *****//
+const
+  GL_POINT_SIZE_MIN_ARB = $8126;
+  GL_POINT_SIZE_MAX_ARB = $8127;
+  GL_POINT_FADE_THRESHOLD_SIZE_ARB = $8128;
+  GL_POINT_DISTANCE_ATTENUATION_ARB = $8129;
+var
+  glPointParameterfARB: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPointParameterfvARB: procedure(pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_point_parameters: Boolean;
+
+//***** GL_ARB_shadow *****//
+const
+  GL_TEXTURE_COMPARE_MODE_ARB = $884C;
+  GL_TEXTURE_COMPARE_FUNC_ARB = $884D;
+  GL_COMPARE_R_TO_TEXTURE_ARB = $884E;
+
+function Load_GL_ARB_shadow: Boolean;
+
+//***** GL_ARB_shadow_ambient *****//
+const
+  GL_TEXTURE_COMPARE_FAIL_VALUE_ARB = $80BF;
+
+function Load_GL_ARB_shadow_ambient: Boolean;
+
+//***** GL_ARB_texture_border_clamp *****//
+const
+  GL_CLAMP_TO_BORDER_ARB = $812D;
+
+function Load_GL_ARB_texture_border_clamp: Boolean;
+
+//***** GL_ARB_texture_compression *****//
+const
+  GL_COMPRESSED_ALPHA_ARB = $84E9;
+  GL_COMPRESSED_LUMINANCE_ARB = $84EA;
+  GL_COMPRESSED_LUMINANCE_ALPHA_ARB = $84EB;
+  GL_COMPRESSED_INTENSITY_ARB = $84EC;
+  GL_COMPRESSED_RGB_ARB = $84ED;
+  GL_COMPRESSED_RGBA_ARB = $84EE;
+  GL_TEXTURE_COMPRESSION_HINT_ARB = $84EF;
+  GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB = $86A0;
+  GL_TEXTURE_COMPRESSED_ARB = $86A1;
+  GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB = $86A2;
+  GL_COMPRESSED_TEXTURE_FORMATS_ARB = $86A3;
+var
+  glCompressedTexImage3DARB: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexImage2DARB: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexImage1DARB: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexSubImage3DARB: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexSubImage2DARB: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompressedTexSubImage1DARB: procedure(target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetCompressedTexImageARB: procedure(target: GLenum; lod: GLint; img: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_texture_compression: Boolean;
+
+//***** GL_ARB_texture_env_combine *****//
+const
+  GL_COMBINE_ARB = $8570;
+  GL_COMBINE_RGB_ARB = $8571;
+  GL_COMBINE_ALPHA_ARB = $8572;
+  GL_SOURCE0_RGB_ARB = $8580;
+  GL_SOURCE1_RGB_ARB = $8581;
+  GL_SOURCE2_RGB_ARB = $8582;
+  GL_SOURCE0_ALPHA_ARB = $8588;
+  GL_SOURCE1_ALPHA_ARB = $8589;
+  GL_SOURCE2_ALPHA_ARB = $858A;
+  GL_OPERAND0_RGB_ARB = $8590;
+  GL_OPERAND1_RGB_ARB = $8591;
+  GL_OPERAND2_RGB_ARB = $8592;
+  GL_OPERAND0_ALPHA_ARB = $8598;
+  GL_OPERAND1_ALPHA_ARB = $8599;
+  GL_OPERAND2_ALPHA_ARB = $859A;
+  GL_RGB_SCALE_ARB = $8573;
+  GL_ADD_SIGNED_ARB = $8574;
+  GL_INTERPOLATE_ARB = $8575;
+  GL_SUBTRACT_ARB = $84E7;
+  GL_CONSTANT_ARB = $8576;
+  GL_PRIMARY_COLOR_ARB = $8577;
+  GL_PREVIOUS_ARB = $8578;
+
+function Load_GL_ARB_texture_env_combine: Boolean;
+
+//***** GL_ARB_texture_env_crossbar *****//
+
+function Load_GL_ARB_texture_env_crossbar: Boolean;
+
+//***** GL_ARB_texture_env_dot3 *****//
+const
+  GL_DOT3_RGB_ARB = $86AE;
+  GL_DOT3_RGBA_ARB = $86AF;
+
+function Load_GL_ARB_texture_env_dot3: Boolean;
+
+//***** GL_ARB_texture_mirrored_repeat *****//
+const
+  GL_MIRRORED_REPEAT_ARB = $8370;
+
+function Load_GL_ARB_texture_mirrored_repeat: Boolean;
+
+//***** GL_ARB_vertex_blend *****//
+const
+  GL_MAX_VERTEX_UNITS_ARB = $86A4;
+  GL_ACTIVE_VERTEX_UNITS_ARB = $86A5;
+  GL_WEIGHT_SUM_UNITY_ARB = $86A6;
+  GL_VERTEX_BLEND_ARB = $86A7;
+  GL_MODELVIEW0_ARB = $1700;
+  GL_MODELVIEW1_ARB = $850A;
+  GL_MODELVIEW2_ARB = $8722;
+  GL_MODELVIEW3_ARB = $8723;
+  GL_MODELVIEW4_ARB = $8724;
+  GL_MODELVIEW5_ARB = $8725;
+  GL_MODELVIEW6_ARB = $8726;
+  GL_MODELVIEW7_ARB = $8727;
+  GL_MODELVIEW8_ARB = $8728;
+  GL_MODELVIEW9_ARB = $8729;
+  GL_MODELVIEW10_ARB = $872A;
+  GL_MODELVIEW11_ARB = $872B;
+  GL_MODELVIEW12_ARB = $872C;
+  GL_MODELVIEW13_ARB = $872D;
+  GL_MODELVIEW14_ARB = $872E;
+  GL_MODELVIEW15_ARB = $872F;
+  GL_MODELVIEW16_ARB = $8730;
+  GL_MODELVIEW17_ARB = $8731;
+  GL_MODELVIEW18_ARB = $8732;
+  GL_MODELVIEW19_ARB = $8733;
+  GL_MODELVIEW20_ARB = $8734;
+  GL_MODELVIEW21_ARB = $8735;
+  GL_MODELVIEW22_ARB = $8736;
+  GL_MODELVIEW23_ARB = $8737;
+  GL_MODELVIEW24_ARB = $8738;
+  GL_MODELVIEW25_ARB = $8739;
+  GL_MODELVIEW26_ARB = $873A;
+  GL_MODELVIEW27_ARB = $873B;
+  GL_MODELVIEW28_ARB = $873C;
+  GL_MODELVIEW29_ARB = $873D;
+  GL_MODELVIEW30_ARB = $873E;
+  GL_MODELVIEW31_ARB = $873F;
+  GL_CURRENT_WEIGHT_ARB = $86A8;
+  GL_WEIGHT_ARRAY_TYPE_ARB = $86A9;
+  GL_WEIGHT_ARRAY_STRIDE_ARB = $86AA;
+  GL_WEIGHT_ARRAY_SIZE_ARB = $86AB;
+  GL_WEIGHT_ARRAY_POINTER_ARB = $86AC;
+  GL_WEIGHT_ARRAY_ARB = $86AD;
+var
+  glWeightbvARB: procedure(size: GLint; weights: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWeightsvARB: procedure(size: GLint; weights: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWeightivARB: procedure(size: GLint; weights: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWeightfvARB: procedure(size: GLint; weights: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWeightdvARB: procedure(size: GLint; weights: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWeightvARB: procedure(size: GLint; weights: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWeightubvARB: procedure(size: GLint; weights: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWeightusvARB: procedure(size: GLint; weights: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWeightuivARB: procedure(size: GLint; weights: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWeightPointerARB: procedure(size: GLint; _type: GLenum; stride: GLsizei; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexBlendARB: procedure(count: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_vertex_blend: Boolean;
+
+//***** GL_ARB_vertex_program *****//
+const
+  GL_VERTEX_PROGRAM_ARB = $8620;
+  GL_VERTEX_PROGRAM_POINT_SIZE_ARB = $8642;
+  GL_VERTEX_PROGRAM_TWO_SIDE_ARB = $8643;
+  GL_COLOR_SUM_ARB = $8458;
+  GL_PROGRAM_FORMAT_ASCII_ARB = $8875;
+  GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB = $8622;
+  GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB = $8623;
+  GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB = $8624;
+  GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB = $8625;
+  GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB = $886A;
+  GL_CURRENT_VERTEX_ATTRIB_ARB = $8626;
+  GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB = $8645;
+  GL_PROGRAM_LENGTH_ARB = $8627;
+  GL_PROGRAM_FORMAT_ARB = $8876;
+  GL_PROGRAM_BINDING_ARB = $8677;
+  GL_PROGRAM_INSTRUCTIONS_ARB = $88A0;
+  GL_MAX_PROGRAM_INSTRUCTIONS_ARB = $88A1;
+  GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB = $88A2;
+  GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB = $88A3;
+  GL_PROGRAM_TEMPORARIES_ARB = $88A4;
+  GL_MAX_PROGRAM_TEMPORARIES_ARB = $88A5;
+  GL_PROGRAM_NATIVE_TEMPORARIES_ARB = $88A6;
+  GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB = $88A7;
+  GL_PROGRAM_PARAMETERS_ARB = $88A8;
+  GL_MAX_PROGRAM_PARAMETERS_ARB = $88A9;
+  GL_PROGRAM_NATIVE_PARAMETERS_ARB = $88AA;
+  GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB = $88AB;
+  GL_PROGRAM_ATTRIBS_ARB = $88AC;
+  GL_MAX_PROGRAM_ATTRIBS_ARB = $88AD;
+  GL_PROGRAM_NATIVE_ATTRIBS_ARB = $88AE;
+  GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB = $88AF;
+  GL_PROGRAM_ADDRESS_REGISTERS_ARB = $88B0;
+  GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB = $88B1;
+  GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB = $88B2;
+  GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB = $88B3;
+  GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB = $88B4;
+  GL_MAX_PROGRAM_ENV_PARAMETERS_ARB = $88B5;
+  GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB = $88B6;
+  GL_PROGRAM_STRING_ARB = $8628;
+  GL_PROGRAM_ERROR_POSITION_ARB = $864B;
+  GL_CURRENT_MATRIX_ARB = $8641;
+  GL_TRANSPOSE_CURRENT_MATRIX_ARB = $88B7;
+  GL_CURRENT_MATRIX_STACK_DEPTH_ARB = $8640;
+  GL_MAX_VERTEX_ATTRIBS_ARB = $8869;
+  GL_MAX_PROGRAM_MATRICES_ARB = $862F;
+  GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB = $862E;
+  GL_PROGRAM_ERROR_STRING_ARB = $8874;
+  GL_MATRIX0_ARB = $88C0;
+  GL_MATRIX1_ARB = $88C1;
+  GL_MATRIX2_ARB = $88C2;
+  GL_MATRIX3_ARB = $88C3;
+  GL_MATRIX4_ARB = $88C4;
+  GL_MATRIX5_ARB = $88C5;
+  GL_MATRIX6_ARB = $88C6;
+  GL_MATRIX7_ARB = $88C7;
+  GL_MATRIX8_ARB = $88C8;
+  GL_MATRIX9_ARB = $88C9;
+  GL_MATRIX10_ARB = $88CA;
+  GL_MATRIX11_ARB = $88CB;
+  GL_MATRIX12_ARB = $88CC;
+  GL_MATRIX13_ARB = $88CD;
+  GL_MATRIX14_ARB = $88CE;
+  GL_MATRIX15_ARB = $88CF;
+  GL_MATRIX16_ARB = $88D0;
+  GL_MATRIX17_ARB = $88D1;
+  GL_MATRIX18_ARB = $88D2;
+  GL_MATRIX19_ARB = $88D3;
+  GL_MATRIX20_ARB = $88D4;
+  GL_MATRIX21_ARB = $88D5;
+  GL_MATRIX22_ARB = $88D6;
+  GL_MATRIX23_ARB = $88D7;
+  GL_MATRIX24_ARB = $88D8;
+  GL_MATRIX25_ARB = $88D9;
+  GL_MATRIX26_ARB = $88DA;
+  GL_MATRIX27_ARB = $88DB;
+  GL_MATRIX28_ARB = $88DC;
+  GL_MATRIX29_ARB = $88DD;
+  GL_MATRIX30_ARB = $88DE;
+  GL_MATRIX31_ARB = $88DF;
+var
+  glVertexAttrib1sARB: procedure(index: GLuint; x: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1fARB: procedure(index: GLuint; x: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1dARB: procedure(index: GLuint; x: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2sARB: procedure(index: GLuint; x: GLshort; y: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2fARB: procedure(index: GLuint; x: GLfloat; y: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2dARB: procedure(index: GLuint; x: GLdouble; y: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3sARB: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3fARB: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3dARB: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4sARB: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort; w: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4fARB: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4dARB: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4NubARB: procedure(index: GLuint; x: GLubyte; y: GLubyte; z: GLubyte; w: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1svARB: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1fvARB: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1dvARB: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2svARB: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2fvARB: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2dvARB: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3svARB: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3fvARB: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3dvARB: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4bvARB: procedure(index: GLuint; const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4svARB: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4ivARB: procedure(index: GLuint; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4ubvARB: procedure(index: GLuint; const v: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4usvARB: procedure(index: GLuint; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4uivARB: procedure(index: GLuint; const v: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4fvARB: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4dvARB: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4NbvARB: procedure(index: GLuint; const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4NsvARB: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4NivARB: procedure(index: GLuint; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4NubvARB: procedure(index: GLuint; const v: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4NusvARB: procedure(index: GLuint; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4NuivARB: procedure(index: GLuint; const v: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribPointerARB: procedure(index: GLuint; size: GLint; _type: GLenum; normalized: GLboolean; stride: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEnableVertexAttribArrayARB: procedure(index: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDisableVertexAttribArrayARB: procedure(index: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramStringARB: procedure(target: GLenum; format: GLenum; len: GLsizei; const _string: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindProgramARB: procedure(target: GLenum; _program: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteProgramsARB: procedure(n: GLsizei; const programs: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenProgramsARB: procedure(n: GLsizei; programs: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramEnvParameter4dARB: procedure(target: GLenum; index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramEnvParameter4dvARB: procedure(target: GLenum; index: GLuint; const params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramEnvParameter4fARB: procedure(target: GLenum; index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramEnvParameter4fvARB: procedure(target: GLenum; index: GLuint; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramLocalParameter4dARB: procedure(target: GLenum; index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramLocalParameter4dvARB: procedure(target: GLenum; index: GLuint; const params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramLocalParameter4fARB: procedure(target: GLenum; index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramLocalParameter4fvARB: procedure(target: GLenum; index: GLuint; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramEnvParameterdvARB: procedure(target: GLenum; index: GLuint; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramEnvParameterfvARB: procedure(target: GLenum; index: GLuint; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramLocalParameterdvARB: procedure(target: GLenum; index: GLuint; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramLocalParameterfvARB: procedure(target: GLenum; index: GLuint; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramivARB: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramStringARB: procedure(target: GLenum; pname: GLenum; _string: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribdvARB: procedure(index: GLuint; pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribfvARB: procedure(index: GLuint; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribivARB: procedure(index: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribPointervARB: procedure(index: GLuint; pname: GLenum; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsProgramARB: function(_program: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_vertex_program: Boolean;
+
+//***** GL_ARB_window_pos *****//
+var
+  glWindowPos2dARB: procedure(x: GLdouble; y: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2fARB: procedure(x: GLfloat; y: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2iARB: procedure(x: GLint; y: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2sARB: procedure(x: GLshort; y: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2dvARB: procedure(const p: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2fvARB: procedure(const p: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2ivARB: procedure(const p: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2svARB: procedure(const p: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3dARB: procedure(x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3fARB: procedure(x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3iARB: procedure(x: GLint; y: GLint; z: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3sARB: procedure(x: GLshort; y: GLshort; z: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3dvARB: procedure(const p: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3fvARB: procedure(const p: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3ivARB: procedure(const p: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3svARB: procedure(const p: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_window_pos: Boolean;
+
+//***** GL_EXT_422_pixels *****//
+const
+  GL_422_EXT = $80CC;
+  GL_422_REV_EXT = $80CD;
+  GL_422_AVERAGE_EXT = $80CE;
+  GL_422_REV_AVERAGE_EXT = $80CF;
+
+function Load_GL_EXT_422_pixels: Boolean;
+
+//***** GL_EXT_abgr *****//
+const
+  GL_ABGR_EXT = $8000;
+
+function Load_GL_EXT_abgr: Boolean;
+
+//***** GL_EXT_bgra *****//
+const
+  GL_BGR_EXT = $80E0;
+  GL_BGRA_EXT = $80E1;
+
+function Load_GL_EXT_bgra: Boolean;
+
+//***** GL_EXT_blend_color *****//
+const
+  GL_CONSTANT_COLOR_EXT = $8001;
+  GL_ONE_MINUS_CONSTANT_COLOR_EXT = $8002;
+  GL_CONSTANT_ALPHA_EXT = $8003;
+  GL_ONE_MINUS_CONSTANT_ALPHA_EXT = $8004;
+  GL_BLEND_COLOR_EXT = $8005;
+var
+  glBlendColorEXT: procedure(red: GLclampf; green: GLclampf; blue: GLclampf; alpha: GLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_blend_color: Boolean;
+
+//***** GL_EXT_blend_func_separate *****//
+const
+  GL_BLEND_DST_RGB_EXT = $80C8;
+  GL_BLEND_SRC_RGB_EXT = $80C9;
+  GL_BLEND_DST_ALPHA_EXT = $80CA;
+  GL_BLEND_SRC_ALPHA_EXT = $80CB;
+var
+  glBlendFuncSeparateEXT: procedure(sfactorRGB: GLenum; dfactorRGB: GLenum; sfactorAlpha: GLenum; dfactorAlpha: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_blend_func_separate: Boolean;
+
+//***** GL_EXT_blend_logic_op *****//
+
+function Load_GL_EXT_blend_logic_op: Boolean;
+
+//***** GL_EXT_blend_minmax *****//
+const
+  GL_FUNC_ADD_EXT = $8006;
+  GL_MIN_EXT = $8007;
+  GL_MAX_EXT = $8008;
+  GL_BLEND_EQUATION_EXT = $8009;
+var
+  glBlendEquationEXT: procedure(mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_blend_minmax: Boolean;
+
+//***** GL_EXT_blend_subtract *****//
+const
+  GL_FUNC_SUBTRACT_EXT = $800A;
+  GL_FUNC_REVERSE_SUBTRACT_EXT = $800B;
+
+function Load_GL_EXT_blend_subtract: Boolean;
+
+//***** GL_EXT_clip_volume_hint *****//
+const
+  GL_CLIP_VOLUME_CLIPPING_HINT_EXT = $80F0;
+
+function Load_GL_EXT_clip_volume_hint: Boolean;
+
+//***** GL_EXT_color_subtable *****//
+var
+  glColorSubTableEXT: procedure(target: GLenum; start: GLsizei; count: GLsizei; format: GLenum; _type: GLenum; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyColorSubTableEXT: procedure(target: GLenum; start: GLsizei; x: GLint; y: GLint; width: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_color_subtable: Boolean;
+
+//***** GL_EXT_compiled_vertex_array *****//
+const
+  GL_ARRAY_ELEMENT_LOCK_FIRST_EXT = $81A8;
+  GL_ARRAY_ELEMENT_LOCK_COUNT_EXT = $81A9;
+var
+  glLockArraysEXT: procedure(first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUnlockArraysEXT: procedure(); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_compiled_vertex_array: Boolean;
+
+//***** GL_EXT_convolution *****//
+const
+  GL_CONVOLUTION_1D_EXT = $8010;
+  GL_CONVOLUTION_2D_EXT = $8011;
+  GL_SEPARABLE_2D_EXT = $8012;
+  GL_CONVOLUTION_BORDER_MODE_EXT = $8013;
+  GL_CONVOLUTION_FILTER_SCALE_EXT = $8014;
+  GL_CONVOLUTION_FILTER_BIAS_EXT = $8015;
+  GL_REDUCE_EXT = $8016;
+  GL_CONVOLUTION_FORMAT_EXT = $8017;
+  GL_CONVOLUTION_WIDTH_EXT = $8018;
+  GL_CONVOLUTION_HEIGHT_EXT = $8019;
+  GL_MAX_CONVOLUTION_WIDTH_EXT = $801A;
+  GL_MAX_CONVOLUTION_HEIGHT_EXT = $801B;
+  GL_POST_CONVOLUTION_RED_SCALE_EXT = $801C;
+  GL_POST_CONVOLUTION_GREEN_SCALE_EXT = $801D;
+  GL_POST_CONVOLUTION_BLUE_SCALE_EXT = $801E;
+  GL_POST_CONVOLUTION_ALPHA_SCALE_EXT = $801F;
+  GL_POST_CONVOLUTION_RED_BIAS_EXT = $8020;
+  GL_POST_CONVOLUTION_GREEN_BIAS_EXT = $8021;
+  GL_POST_CONVOLUTION_BLUE_BIAS_EXT = $8022;
+  GL_POST_CONVOLUTION_ALPHA_BIAS_EXT = $8023;
+var
+  glConvolutionFilter1DEXT: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const image: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionFilter2DEXT: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const image: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyConvolutionFilter1DEXT: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyConvolutionFilter2DEXT: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei; height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetConvolutionFilterEXT: procedure(target: GLenum; format: GLenum; _type: GLenum; image: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSeparableFilter2DEXT: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const row: PGLvoid; const column: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetSeparableFilterEXT: procedure(target: GLenum; format: GLenum; _type: GLenum; row: PGLvoid; column: PGLvoid; span: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionParameteriEXT: procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionParameterivEXT: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionParameterfEXT: procedure(target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glConvolutionParameterfvEXT: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetConvolutionParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetConvolutionParameterfvEXT: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_convolution: Boolean;
+
+//***** GL_EXT_histogram *****//
+const
+  GL_HISTOGRAM_EXT = $8024;
+  GL_PROXY_HISTOGRAM_EXT = $8025;
+  GL_HISTOGRAM_WIDTH_EXT = $8026;
+  GL_HISTOGRAM_FORMAT_EXT = $8027;
+  GL_HISTOGRAM_RED_SIZE_EXT = $8028;
+  GL_HISTOGRAM_GREEN_SIZE_EXT = $8029;
+  GL_HISTOGRAM_BLUE_SIZE_EXT = $802A;
+  GL_HISTOGRAM_ALPHA_SIZE_EXT = $802B;
+  GL_HISTOGRAM_LUMINANCE_SIZE_EXT = $802C;
+  GL_HISTOGRAM_SINK_EXT = $802D;
+  GL_MINMAX_EXT = $802E;
+  GL_MINMAX_FORMAT_EXT = $802F;
+  GL_MINMAX_SINK_EXT = $8030;
+var
+  glHistogramEXT: procedure(target: GLenum; width: GLsizei; internalformat: GLenum; sink: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glResetHistogramEXT: procedure(target: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetHistogramEXT: procedure(target: GLenum; reset: GLboolean; format: GLenum; _type: GLenum; values: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetHistogramParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetHistogramParameterfvEXT: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMinmaxEXT: procedure(target: GLenum; internalformat: GLenum; sink: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glResetMinmaxEXT: procedure(target: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMinmaxEXT: procedure(target: GLenum; reset: GLboolean; format: GLenum; _type: GLenum; values: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMinmaxParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMinmaxParameterfvEXT: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_histogram: Boolean;
+
+//***** GL_EXT_multi_draw_arrays *****//
+var
+  glMultiDrawArraysEXT: procedure(mode: GLenum; first: PGLint; count: PGLsizei; primcount: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiDrawElementsEXT: procedure(mode: GLenum; count: PGLsizei; _type: GLenum; const indices: PGLvoid; primcount: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_multi_draw_arrays: Boolean;
+
+//***** GL_EXT_packed_pixels *****//
+const
+  GL_UNSIGNED_BYTE_3_3_2_EXT = $8032;
+  GL_UNSIGNED_SHORT_4_4_4_4_EXT = $8033;
+  GL_UNSIGNED_SHORT_5_5_5_1_EXT = $8034;
+  GL_UNSIGNED_INT_8_8_8_8_EXT = $8035;
+  GL_UNSIGNED_INT_10_10_10_2_EXT = $8036;
+
+function Load_GL_EXT_packed_pixels: Boolean;
+
+//***** GL_EXT_paletted_texture *****//
+const
+  GL_COLOR_INDEX1_EXT = $80E2;
+  GL_COLOR_INDEX2_EXT = $80E3;
+  GL_COLOR_INDEX4_EXT = $80E4;
+  GL_COLOR_INDEX8_EXT = $80E5;
+  GL_COLOR_INDEX12_EXT = $80E6;
+  GL_COLOR_INDEX16_EXT = $80E7;
+  GL_COLOR_TABLE_FORMAT_EXT = $80D8;
+  GL_COLOR_TABLE_WIDTH_EXT = $80D9;
+  GL_COLOR_TABLE_RED_SIZE_EXT = $80DA;
+  GL_COLOR_TABLE_GREEN_SIZE_EXT = $80DB;
+  GL_COLOR_TABLE_BLUE_SIZE_EXT = $80DC;
+  GL_COLOR_TABLE_ALPHA_SIZE_EXT = $80DD;
+  GL_COLOR_TABLE_LUMINANCE_SIZE_EXT = $80DE;
+  GL_COLOR_TABLE_INTENSITY_SIZE_EXT = $80DF;
+  GL_TEXTURE_INDEX_SIZE_EXT = $80ED;
+  GL_TEXTURE_1D = $0DE0;
+  GL_TEXTURE_2D = $0DE1;
+  GL_TEXTURE_3D_EXT = $806F;
+  // GL_TEXTURE_CUBE_MAP_ARB  { already defined }
+  GL_PROXY_TEXTURE_1D = $8063;
+  GL_PROXY_TEXTURE_2D = $8064;
+  GL_PROXY_TEXTURE_3D_EXT = $8070;
+  // GL_PROXY_TEXTURE_CUBE_MAP_ARB  { already defined }
+  // GL_TEXTURE_1D  { already defined }
+  // GL_TEXTURE_2D  { already defined }
+  // GL_TEXTURE_3D_EXT  { already defined }
+  // GL_TEXTURE_CUBE_MAP_ARB  { already defined }
+var
+  glColorTableEXT: procedure(target: GLenum; internalFormat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  // glColorSubTableEXT  { already defined }
+  glGetColorTableEXT: procedure(target: GLenum; format: GLenum; _type: GLenum; data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetColorTableParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetColorTableParameterfvEXT: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_paletted_texture: Boolean;
+
+//***** GL_EXT_point_parameters *****//
+const
+  GL_POINT_SIZE_MIN_EXT = $8126;
+  GL_POINT_SIZE_MAX_EXT = $8127;
+  GL_POINT_FADE_THRESHOLD_SIZE_EXT = $8128;
+  GL_DISTANCE_ATTENUATION_EXT = $8129;
+var
+  glPointParameterfEXT: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPointParameterfvEXT: procedure(pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_point_parameters: Boolean;
+
+//***** GL_EXT_polygon_offset *****//
+const
+  GL_POLYGON_OFFSET_EXT = $8037;
+  GL_POLYGON_OFFSET_FACTOR_EXT = $8038;
+  GL_POLYGON_OFFSET_BIAS_EXT = $8039;
+var
+  glPolygonOffsetEXT: procedure(factor: GLfloat; bias: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_polygon_offset: Boolean;
+
+//***** GL_EXT_separate_specular_color *****//
+const
+  GL_LIGHT_MODEL_COLOR_CONTROL_EXT = $81F8;
+  GL_SINGLE_COLOR_EXT = $81F9;
+  GL_SEPARATE_SPECULAR_COLOR_EXT = $81FA;
+
+function Load_GL_EXT_separate_specular_color: Boolean;
+
+//***** GL_EXT_shadow_funcs *****//
+
+function Load_GL_EXT_shadow_funcs: Boolean;
+
+//***** GL_EXT_shared_texture_palette *****//
+const
+  GL_SHARED_TEXTURE_PALETTE_EXT = $81FB;
+
+function Load_GL_EXT_shared_texture_palette: Boolean;
+
+//***** GL_EXT_stencil_two_side *****//
+const
+  GL_STENCIL_TEST_TWO_SIDE_EXT = $8910;
+  GL_ACTIVE_STENCIL_FACE_EXT = $8911;
+var
+  glActiveStencilFaceEXT: procedure(face: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_stencil_two_side: Boolean;
+
+//***** GL_EXT_stencil_wrap *****//
+const
+  GL_INCR_WRAP_EXT = $8507;
+  GL_DECR_WRAP_EXT = $8508;
+
+function Load_GL_EXT_stencil_wrap: Boolean;
+
+//***** GL_EXT_subtexture *****//
+var
+  glTexSubImage1DEXT: procedure(target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexSubImage2DEXT: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexSubImage3DEXT: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_subtexture: Boolean;
+
+//***** GL_EXT_texture3D *****//
+const
+  GL_PACK_SKIP_IMAGES_EXT = $806B;
+  GL_PACK_IMAGE_HEIGHT_EXT = $806C;
+  GL_UNPACK_SKIP_IMAGES_EXT = $806D;
+  GL_UNPACK_IMAGE_HEIGHT_EXT = $806E;
+  // GL_TEXTURE_3D_EXT  { already defined }
+  // GL_PROXY_TEXTURE_3D_EXT  { already defined }
+  GL_TEXTURE_DEPTH_EXT = $8071;
+  GL_TEXTURE_WRAP_R_EXT = $8072;
+  GL_MAX_3D_TEXTURE_SIZE_EXT = $8073;
+var
+  glTexImage3DEXT: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_texture3D: Boolean;
+
+//***** GL_EXT_texture_compression_s3tc *****//
+const
+  GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
+  GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
+  GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
+  GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
+
+function Load_GL_EXT_texture_compression_s3tc: Boolean;
+
+//***** GL_EXT_texture_env_add *****//
+
+function Load_GL_EXT_texture_env_add: Boolean;
+
+//***** GL_EXT_texture_env_combine *****//
+const
+  GL_COMBINE_EXT = $8570;
+  GL_COMBINE_RGB_EXT = $8571;
+  GL_COMBINE_ALPHA_EXT = $8572;
+  GL_SOURCE0_RGB_EXT = $8580;
+  GL_SOURCE1_RGB_EXT = $8581;
+  GL_SOURCE2_RGB_EXT = $8582;
+  GL_SOURCE0_ALPHA_EXT = $8588;
+  GL_SOURCE1_ALPHA_EXT = $8589;
+  GL_SOURCE2_ALPHA_EXT = $858A;
+  GL_OPERAND0_RGB_EXT = $8590;
+  GL_OPERAND1_RGB_EXT = $8591;
+  GL_OPERAND2_RGB_EXT = $8592;
+  GL_OPERAND0_ALPHA_EXT = $8598;
+  GL_OPERAND1_ALPHA_EXT = $8599;
+  GL_OPERAND2_ALPHA_EXT = $859A;
+  GL_RGB_SCALE_EXT = $8573;
+  GL_ADD_SIGNED_EXT = $8574;
+  GL_INTERPOLATE_EXT = $8575;
+  GL_CONSTANT_EXT = $8576;
+  GL_PRIMARY_COLOR_EXT = $8577;
+  GL_PREVIOUS_EXT = $8578;
+
+function Load_GL_EXT_texture_env_combine: Boolean;
+
+//***** GL_EXT_texture_env_dot3 *****//
+const
+  GL_DOT3_RGB_EXT = $8740;
+  GL_DOT3_RGBA_EXT = $8741;
+
+function Load_GL_EXT_texture_env_dot3: Boolean;
+
+//***** GL_EXT_texture_filter_anisotropic *****//
+const
+  GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
+  GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
+
+function Load_GL_EXT_texture_filter_anisotropic: Boolean;
+
+//***** GL_EXT_texture_lod_bias *****//
+const
+  GL_TEXTURE_FILTER_CONTROL_EXT = $8500;
+  GL_TEXTURE_LOD_BIAS_EXT = $8501;
+  GL_MAX_TEXTURE_LOD_BIAS_EXT = $84FD;
+
+function Load_GL_EXT_texture_lod_bias: Boolean;
+
+//***** GL_EXT_texture_object *****//
+const
+  GL_TEXTURE_PRIORITY_EXT = $8066;
+  GL_TEXTURE_RESIDENT_EXT = $8067;
+  GL_TEXTURE_1D_BINDING_EXT = $8068;
+  GL_TEXTURE_2D_BINDING_EXT = $8069;
+  GL_TEXTURE_3D_BINDING_EXT = $806A;
+var
+  glGenTexturesEXT: procedure(n: GLsizei; textures: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteTexturesEXT: procedure(n: GLsizei; const textures: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindTextureEXT: procedure(target: GLenum; texture: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPrioritizeTexturesEXT: procedure(n: GLsizei; const textures: PGLuint; const priorities: PGLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAreTexturesResidentEXT: function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsTextureEXT: function(texture: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_texture_object: Boolean;
+
+//***** GL_EXT_vertex_array *****//
+const
+  GL_VERTEX_ARRAY_EXT = $8074;
+  GL_NORMAL_ARRAY_EXT = $8075;
+  GL_COLOR_ARRAY_EXT = $8076;
+  GL_INDEX_ARRAY_EXT = $8077;
+  GL_TEXTURE_COORD_ARRAY_EXT = $8078;
+  GL_EDGE_FLAG_ARRAY_EXT = $8079;
+  GL_DOUBLE_EXT = $140A;
+  GL_VERTEX_ARRAY_SIZE_EXT = $807A;
+  GL_VERTEX_ARRAY_TYPE_EXT = $807B;
+  GL_VERTEX_ARRAY_STRIDE_EXT = $807C;
+  GL_VERTEX_ARRAY_COUNT_EXT = $807D;
+  GL_NORMAL_ARRAY_TYPE_EXT = $807E;
+  GL_NORMAL_ARRAY_STRIDE_EXT = $807F;
+  GL_NORMAL_ARRAY_COUNT_EXT = $8080;
+  GL_COLOR_ARRAY_SIZE_EXT = $8081;
+  GL_COLOR_ARRAY_TYPE_EXT = $8082;
+  GL_COLOR_ARRAY_STRIDE_EXT = $8083;
+  GL_COLOR_ARRAY_COUNT_EXT = $8084;
+  GL_INDEX_ARRAY_TYPE_EXT = $8085;
+  GL_INDEX_ARRAY_STRIDE_EXT = $8086;
+  GL_INDEX_ARRAY_COUNT_EXT = $8087;
+  GL_TEXTURE_COORD_ARRAY_SIZE_EXT = $8088;
+  GL_TEXTURE_COORD_ARRAY_TYPE_EXT = $8089;
+  GL_TEXTURE_COORD_ARRAY_STRIDE_EXT = $808A;
+  GL_TEXTURE_COORD_ARRAY_COUNT_EXT = $808B;
+  GL_EDGE_FLAG_ARRAY_STRIDE_EXT = $808C;
+  GL_EDGE_FLAG_ARRAY_COUNT_EXT = $808D;
+  GL_VERTEX_ARRAY_POINTER_EXT = $808E;
+  GL_NORMAL_ARRAY_POINTER_EXT = $808F;
+  GL_COLOR_ARRAY_POINTER_EXT = $8090;
+  GL_INDEX_ARRAY_POINTER_EXT = $8091;
+  GL_TEXTURE_COORD_ARRAY_POINTER_EXT = $8092;
+  GL_EDGE_FLAG_ARRAY_POINTER_EXT = $8093;
+var
+  glArrayElementEXT: procedure(i: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawArraysEXT: procedure(mode: GLenum; first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalPointerEXT: procedure(_type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexPointerEXT: procedure(_type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoordPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEdgeFlagPointerEXT: procedure(stride: GLsizei; count: GLsizei; const pointer: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPointervEXT: procedure(pname: GLenum; params: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_vertex_array: Boolean;
+
+//***** GL_EXT_vertex_shader *****//
+const
+  GL_VERTEX_SHADER_EXT = $8780;
+  GL_VARIANT_VALUE_EXT = $87E4;
+  GL_VARIANT_DATATYPE_EXT = $87E5;
+  GL_VARIANT_ARRAY_STRIDE_EXT = $87E6;
+  GL_VARIANT_ARRAY_TYPE_EXT = $87E7;
+  GL_VARIANT_ARRAY_EXT = $87E8;
+  GL_VARIANT_ARRAY_POINTER_EXT = $87E9;
+  GL_INVARIANT_VALUE_EXT = $87EA;
+  GL_INVARIANT_DATATYPE_EXT = $87EB;
+  GL_LOCAL_CONSTANT_VALUE_EXT = $87EC;
+  GL_LOCAL_CONSTANT_DATATYPE_EXT = $87ED;
+  GL_OP_INDEX_EXT = $8782;
+  GL_OP_NEGATE_EXT = $8783;
+  GL_OP_DOT3_EXT = $8784;
+  GL_OP_DOT4_EXT = $8785;
+  GL_OP_MUL_EXT = $8786;
+  GL_OP_ADD_EXT = $8787;
+  GL_OP_MADD_EXT = $8788;
+  GL_OP_FRAC_EXT = $8789;
+  GL_OP_MAX_EXT = $878A;
+  GL_OP_MIN_EXT = $878B;
+  GL_OP_SET_GE_EXT = $878C;
+  GL_OP_SET_LT_EXT = $878D;
+  GL_OP_CLAMP_EXT = $878E;
+  GL_OP_FLOOR_EXT = $878F;
+  GL_OP_ROUND_EXT = $8790;
+  GL_OP_EXP_BASE_2_EXT = $8791;
+  GL_OP_LOG_BASE_2_EXT = $8792;
+  GL_OP_POWER_EXT = $8793;
+  GL_OP_RECIP_EXT = $8794;
+  GL_OP_RECIP_SQRT_EXT = $8795;
+  GL_OP_SUB_EXT = $8796;
+  GL_OP_CROSS_PRODUCT_EXT = $8797;
+  GL_OP_MULTIPLY_MATRIX_EXT = $8798;
+  GL_OP_MOV_EXT = $8799;
+  GL_OUTPUT_VERTEX_EXT = $879A;
+  GL_OUTPUT_COLOR0_EXT = $879B;
+  GL_OUTPUT_COLOR1_EXT = $879C;
+  GL_OUTPUT_TEXTURE_COORD0_EXT = $879D;
+  GL_OUTPUT_TEXTURE_COORD1_EXT = $879E;
+  GL_OUTPUT_TEXTURE_COORD2_EXT = $879F;
+  GL_OUTPUT_TEXTURE_COORD3_EXT = $87A0;
+  GL_OUTPUT_TEXTURE_COORD4_EXT = $87A1;
+  GL_OUTPUT_TEXTURE_COORD5_EXT = $87A2;
+  GL_OUTPUT_TEXTURE_COORD6_EXT = $87A3;
+  GL_OUTPUT_TEXTURE_COORD7_EXT = $87A4;
+  GL_OUTPUT_TEXTURE_COORD8_EXT = $87A5;
+  GL_OUTPUT_TEXTURE_COORD9_EXT = $87A6;
+  GL_OUTPUT_TEXTURE_COORD10_EXT = $87A7;
+  GL_OUTPUT_TEXTURE_COORD11_EXT = $87A8;
+  GL_OUTPUT_TEXTURE_COORD12_EXT = $87A9;
+  GL_OUTPUT_TEXTURE_COORD13_EXT = $87AA;
+  GL_OUTPUT_TEXTURE_COORD14_EXT = $87AB;
+  GL_OUTPUT_TEXTURE_COORD15_EXT = $87AC;
+  GL_OUTPUT_TEXTURE_COORD16_EXT = $87AD;
+  GL_OUTPUT_TEXTURE_COORD17_EXT = $87AE;
+  GL_OUTPUT_TEXTURE_COORD18_EXT = $87AF;
+  GL_OUTPUT_TEXTURE_COORD19_EXT = $87B0;
+  GL_OUTPUT_TEXTURE_COORD20_EXT = $87B1;
+  GL_OUTPUT_TEXTURE_COORD21_EXT = $87B2;
+  GL_OUTPUT_TEXTURE_COORD22_EXT = $87B3;
+  GL_OUTPUT_TEXTURE_COORD23_EXT = $87B4;
+  GL_OUTPUT_TEXTURE_COORD24_EXT = $87B5;
+  GL_OUTPUT_TEXTURE_COORD25_EXT = $87B6;
+  GL_OUTPUT_TEXTURE_COORD26_EXT = $87B7;
+  GL_OUTPUT_TEXTURE_COORD27_EXT = $87B8;
+  GL_OUTPUT_TEXTURE_COORD28_EXT = $87B9;
+  GL_OUTPUT_TEXTURE_COORD29_EXT = $87BA;
+  GL_OUTPUT_TEXTURE_COORD30_EXT = $87BB;
+  GL_OUTPUT_TEXTURE_COORD31_EXT = $87BC;
+  GL_OUTPUT_FOG_EXT = $87BD;
+  GL_SCALAR_EXT = $87BE;
+  GL_VECTOR_EXT = $87BF;
+  GL_MATRIX_EXT = $87C0;
+  GL_VARIANT_EXT = $87C1;
+  GL_INVARIANT_EXT = $87C2;
+  GL_LOCAL_CONSTANT_EXT = $87C3;
+  GL_LOCAL_EXT = $87C4;
+  GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT = $87C5;
+  GL_MAX_VERTEX_SHADER_VARIANTS_EXT = $87C6;
+  GL_MAX_VERTEX_SHADER_INVARIANTS_EXT = $87C7;
+  GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT = $87C8;
+  GL_MAX_VERTEX_SHADER_LOCALS_EXT = $87C9;
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT = $87CA;
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT = $87CB;
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT = $87CC;
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT = $87CD;
+  GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT = $87CE;
+  GL_VERTEX_SHADER_INSTRUCTIONS_EXT = $87CF;
+  GL_VERTEX_SHADER_VARIANTS_EXT = $87D0;
+  GL_VERTEX_SHADER_INVARIANTS_EXT = $87D1;
+  GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT = $87D2;
+  GL_VERTEX_SHADER_LOCALS_EXT = $87D3;
+  GL_VERTEX_SHADER_BINDING_EXT = $8781;
+  GL_VERTEX_SHADER_OPTIMIZED_EXT = $87D4;
+  GL_X_EXT = $87D5;
+  GL_Y_EXT = $87D6;
+  GL_Z_EXT = $87D7;
+  GL_W_EXT = $87D8;
+  GL_NEGATIVE_X_EXT = $87D9;
+  GL_NEGATIVE_Y_EXT = $87DA;
+  GL_NEGATIVE_Z_EXT = $87DB;
+  GL_NEGATIVE_W_EXT = $87DC;
+  GL_ZERO_EXT = $87DD;
+  GL_ONE_EXT = $87DE;
+  GL_NEGATIVE_ONE_EXT = $87DF;
+  GL_NORMALIZED_RANGE_EXT = $87E0;
+  GL_FULL_RANGE_EXT = $87E1;
+  GL_CURRENT_VERTEX_EXT = $87E2;
+  GL_MVP_MATRIX_EXT = $87E3;
+var
+  glBeginVertexShaderEXT: procedure(); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEndVertexShaderEXT: procedure(); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindVertexShaderEXT: procedure(id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenVertexShadersEXT: function(range: GLuint): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteVertexShaderEXT: procedure(id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glShaderOp1EXT: procedure(op: GLenum; res: GLuint; arg1: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glShaderOp2EXT: procedure(op: GLenum; res: GLuint; arg1: GLuint; arg2: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glShaderOp3EXT: procedure(op: GLenum; res: GLuint; arg1: GLuint; arg2: GLuint; arg3: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSwizzleEXT: procedure(res: GLuint; _in: GLuint; outX: GLenum; outY: GLenum; outZ: GLenum; outW: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWriteMaskEXT: procedure(res: GLuint; _in: GLuint; outX: GLenum; outY: GLenum; outZ: GLenum; outW: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glInsertComponentEXT: procedure(res: GLuint; src: GLuint; num: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glExtractComponentEXT: procedure(res: GLuint; src: GLuint; num: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenSymbolsEXT: function(datatype: GLenum; storagetype: GLenum; range: GLenum; components: GLuint): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSetInvariantEXT: procedure(id: GLuint; _type: GLenum; addr: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSetLocalConstantEXT: procedure(id: GLuint; _type: GLenum; addr: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantbvEXT: procedure(id: GLuint; addr: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantsvEXT: procedure(id: GLuint; addr: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantivEXT: procedure(id: GLuint; addr: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantfvEXT: procedure(id: GLuint; addr: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantdvEXT: procedure(id: GLuint; addr: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantubvEXT: procedure(id: GLuint; addr: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantusvEXT: procedure(id: GLuint; addr: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantuivEXT: procedure(id: GLuint; addr: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantPointerEXT: procedure(id: GLuint; _type: GLenum; stride: GLuint; addr: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEnableVariantClientStateEXT: procedure(id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDisableVariantClientStateEXT: procedure(id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindLightParameterEXT: function(light: GLenum; value: GLenum): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindMaterialParameterEXT: function(face: GLenum; value: GLenum): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindTexGenParameterEXT: function(_unit: GLenum; coord: GLenum; value: GLenum): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindTextureUnitParameterEXT: function(_unit: GLenum; value: GLenum): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindParameterEXT: function(value: GLenum): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsVariantEnabledEXT: function(id: GLuint; cap: GLenum): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVariantBooleanvEXT: procedure(id: GLuint; value: GLenum; data: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVariantIntegervEXT: procedure(id: GLuint; value: GLenum; data: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVariantFloatvEXT: procedure(id: GLuint; value: GLenum; data: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVariantPointervEXT: procedure(id: GLuint; value: GLenum; data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetInvariantBooleanvEXT: procedure(id: GLuint; value: GLenum; data: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetInvariantIntegervEXT: procedure(id: GLuint; value: GLenum; data: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetInvariantFloatvEXT: procedure(id: GLuint; value: GLenum; data: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetLocalConstantBooleanvEXT: procedure(id: GLuint; value: GLenum; data: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetLocalConstantIntegervEXT: procedure(id: GLuint; value: GLenum; data: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetLocalConstantFloatvEXT: procedure(id: GLuint; value: GLenum; data: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_vertex_shader: Boolean;
+
+//***** GL_EXT_vertex_weighting *****//
+const
+  GL_VERTEX_WEIGHTING_EXT = $8509;
+  GL_MODELVIEW0_EXT = $1700;
+  GL_MODELVIEW1_EXT = $850A;
+  GL_MODELVIEW0_MATRIX_EXT = $0BA6;
+  GL_MODELVIEW1_MATRIX_EXT = $8506;
+  GL_CURRENT_VERTEX_WEIGHT_EXT = $850B;
+  GL_VERTEX_WEIGHT_ARRAY_EXT = $850C;
+  GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT = $850D;
+  GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT = $850E;
+  GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT = $850F;
+  GL_MODELVIEW0_STACK_DEPTH_EXT = $0BA3;
+  GL_MODELVIEW1_STACK_DEPTH_EXT = $8502;
+  GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT = $8510;
+var
+  glVertexWeightfEXT: procedure(weight: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexWeightfvEXT: procedure(weight: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexWeightPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_vertex_weighting: Boolean;
+
+//***** GL_HP_occlusion_test *****//
+const
+  GL_OCCLUSION_TEST_HP = $8165;
+  GL_OCCLUSION_TEST_RESULT_HP = $8166;
+
+function Load_GL_HP_occlusion_test: Boolean;
+
+//***** GL_NV_blend_square *****//
+
+function Load_GL_NV_blend_square: Boolean;
+
+//***** GL_NV_copy_depth_to_color *****//
+const
+  GL_DEPTH_STENCIL_TO_RGBA_NV = $886E;
+  GL_DEPTH_STENCIL_TO_BGRA_NV = $886F;
+
+function Load_GL_NV_copy_depth_to_color: Boolean;
+
+//***** GL_NV_depth_clamp *****//
+const
+  GL_DEPTH_CLAMP_NV = $864F;
+
+function Load_GL_NV_depth_clamp: Boolean;
+
+//***** GL_NV_evaluators *****//
+const
+  GL_EVAL_2D_NV = $86C0;
+  GL_EVAL_TRIANGULAR_2D_NV = $86C1;
+  GL_MAP_TESSELLATION_NV = $86C2;
+  GL_MAP_ATTRIB_U_ORDER_NV = $86C3;
+  GL_MAP_ATTRIB_V_ORDER_NV = $86C4;
+  GL_EVAL_FRACTIONAL_TESSELLATION_NV = $86C5;
+  GL_EVAL_VERTEX_ATTRIB0_NV = $86C6;
+  GL_EVAL_VERTEX_ATTRIB1_NV = $86C7;
+  GL_EVAL_VERTEX_ATTRIB2_NV = $86C8;
+  GL_EVAL_VERTEX_ATTRIB3_NV = $86C9;
+  GL_EVAL_VERTEX_ATTRIB4_NV = $86CA;
+  GL_EVAL_VERTEX_ATTRIB5_NV = $86CB;
+  GL_EVAL_VERTEX_ATTRIB6_NV = $86CC;
+  GL_EVAL_VERTEX_ATTRIB7_NV = $86CD;
+  GL_EVAL_VERTEX_ATTRIB8_NV = $86CE;
+  GL_EVAL_VERTEX_ATTRIB9_NV = $86CF;
+  GL_EVAL_VERTEX_ATTRIB10_NV = $86D0;
+  GL_EVAL_VERTEX_ATTRIB11_NV = $86D1;
+  GL_EVAL_VERTEX_ATTRIB12_NV = $86D2;
+  GL_EVAL_VERTEX_ATTRIB13_NV = $86D3;
+  GL_EVAL_VERTEX_ATTRIB14_NV = $86D4;
+  GL_EVAL_VERTEX_ATTRIB15_NV = $86D5;
+  GL_MAX_MAP_TESSELLATION_NV = $86D6;
+  GL_MAX_RATIONAL_EVAL_ORDER_NV = $86D7;
+var
+  glMapControlPointsNV: procedure(target: GLenum; index: GLuint; _type: GLenum; ustride: GLsizei; vstride: GLsizei; uorder: GLint; vorder: GLint; _packed: GLboolean; const points: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapParameterivNV: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapParameterfvNV: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapControlPointsNV: procedure(target: GLenum; index: GLuint; _type: GLenum; ustride: GLsizei; vstride: GLsizei; _packed: GLboolean; points: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapParameterivNV: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapParameterfvNV: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapAttribParameterivNV: procedure(target: GLenum; index: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapAttribParameterfvNV: procedure(target: GLenum; index: GLuint; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalMapsNV: procedure(target: GLenum; mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_evaluators: Boolean;
+
+//***** GL_NV_fence *****//
+const
+  GL_ALL_COMPLETED_NV = $84F2;
+  GL_FENCE_STATUS_NV = $84F3;
+  GL_FENCE_CONDITION_NV = $84F4;
+var
+  glGenFencesNV: procedure(n: GLsizei; fences: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteFencesNV: procedure(n: GLsizei; const fences: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSetFenceNV: procedure(fence: GLuint; condition: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTestFenceNV: function(fence: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFinishFenceNV: procedure(fence: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsFenceNV: function(fence: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetFenceivNV: procedure(fence: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_fence: Boolean;
+
+//***** GL_NV_fog_distance *****//
+const
+  GL_FOG_DISTANCE_MODE_NV = $855A;
+  GL_EYE_RADIAL_NV = $855B;
+  GL_EYE_PLANE_ABSOLUTE_NV = $855C;
+
+function Load_GL_NV_fog_distance: Boolean;
+
+//***** GL_NV_light_max_exponent *****//
+const
+  GL_MAX_SHININESS_NV = $8504;
+  GL_MAX_SPOT_EXPONENT_NV = $8505;
+
+function Load_GL_NV_light_max_exponent: Boolean;
+
+//***** GL_NV_multisample_filter_hint *****//
+const
+  GL_MULTISAMPLE_FILTER_HINT_NV = $8534;
+
+function Load_GL_NV_multisample_filter_hint: Boolean;
+
+//***** GL_NV_occlusion_query *****//
+  // GL_OCCLUSION_TEST_HP  { already defined }
+  // GL_OCCLUSION_TEST_RESULT_HP  { already defined }
+const
+  GL_PIXEL_COUNTER_BITS_NV = $8864;
+  GL_CURRENT_OCCLUSION_QUERY_ID_NV = $8865;
+  GL_PIXEL_COUNT_NV = $8866;
+  GL_PIXEL_COUNT_AVAILABLE_NV = $8867;
+var
+  glGenOcclusionQueriesNV: procedure(n: GLsizei; ids: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteOcclusionQueriesNV: procedure(n: GLsizei; const ids: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsOcclusionQueryNV: function(id: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBeginOcclusionQueryNV: procedure(id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEndOcclusionQueryNV: procedure(); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetOcclusionQueryivNV: procedure(id: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetOcclusionQueryuivNV: procedure(id: GLuint; pname: GLenum; params: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_occlusion_query: Boolean;
+
+//***** GL_NV_packed_depth_stencil *****//
+const
+  GL_DEPTH_STENCIL_NV = $84F9;
+  GL_UNSIGNED_INT_24_8_NV = $84FA;
+
+function Load_GL_NV_packed_depth_stencil: Boolean;
+
+//***** GL_NV_point_sprite *****//
+const
+  GL_POINT_SPRITE_NV = $8861;
+  GL_COORD_REPLACE_NV = $8862;
+  GL_POINT_SPRITE_R_MODE_NV = $8863;
+var
+  glPointParameteriNV: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPointParameterivNV: procedure(pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_point_sprite: Boolean;
+
+//***** GL_NV_register_combiners *****//
+const
+  GL_REGISTER_COMBINERS_NV = $8522;
+  GL_COMBINER0_NV = $8550;
+  GL_COMBINER1_NV = $8551;
+  GL_COMBINER2_NV = $8552;
+  GL_COMBINER3_NV = $8553;
+  GL_COMBINER4_NV = $8554;
+  GL_COMBINER5_NV = $8555;
+  GL_COMBINER6_NV = $8556;
+  GL_COMBINER7_NV = $8557;
+  GL_VARIABLE_A_NV = $8523;
+  GL_VARIABLE_B_NV = $8524;
+  GL_VARIABLE_C_NV = $8525;
+  GL_VARIABLE_D_NV = $8526;
+  GL_VARIABLE_E_NV = $8527;
+  GL_VARIABLE_F_NV = $8528;
+  GL_VARIABLE_G_NV = $8529;
+  GL_CONSTANT_COLOR0_NV = $852A;
+  GL_CONSTANT_COLOR1_NV = $852B;
+  GL_PRIMARY_COLOR_NV = $852C;
+  GL_SECONDARY_COLOR_NV = $852D;
+  GL_SPARE0_NV = $852E;
+  GL_SPARE1_NV = $852F;
+  GL_UNSIGNED_IDENTITY_NV = $8536;
+  GL_UNSIGNED_INVERT_NV = $8537;
+  GL_EXPAND_NORMAL_NV = $8538;
+  GL_EXPAND_NEGATE_NV = $8539;
+  GL_HALF_BIAS_NORMAL_NV = $853A;
+  GL_HALF_BIAS_NEGATE_NV = $853B;
+  GL_SIGNED_IDENTITY_NV = $853C;
+  GL_SIGNED_NEGATE_NV = $853D;
+  GL_E_TIMES_F_NV = $8531;
+  GL_SPARE0_PLUS_SECONDARY_COLOR_NV = $8532;
+  GL_SCALE_BY_TWO_NV = $853E;
+  GL_SCALE_BY_FOUR_NV = $853F;
+  GL_SCALE_BY_ONE_HALF_NV = $8540;
+  GL_BIAS_BY_NEGATIVE_ONE_HALF_NV = $8541;
+  GL_DISCARD_NV = $8530;
+  GL_COMBINER_INPUT_NV = $8542;
+  GL_COMBINER_MAPPING_NV = $8543;
+  GL_COMBINER_COMPONENT_USAGE_NV = $8544;
+  GL_COMBINER_AB_DOT_PRODUCT_NV = $8545;
+  GL_COMBINER_CD_DOT_PRODUCT_NV = $8546;
+  GL_COMBINER_MUX_SUM_NV = $8547;
+  GL_COMBINER_SCALE_NV = $8548;
+  GL_COMBINER_BIAS_NV = $8549;
+  GL_COMBINER_AB_OUTPUT_NV = $854A;
+  GL_COMBINER_CD_OUTPUT_NV = $854B;
+  GL_COMBINER_SUM_OUTPUT_NV = $854C;
+  GL_NUM_GENERAL_COMBINERS_NV = $854E;
+  GL_COLOR_SUM_CLAMP_NV = $854F;
+  GL_MAX_GENERAL_COMBINERS_NV = $854D;
+var
+  glCombinerParameterfvNV: procedure(pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCombinerParameterivNV: procedure(pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCombinerParameterfNV: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCombinerParameteriNV: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCombinerInputNV: procedure(stage: GLenum; portion: GLenum; variable: GLenum; input: GLenum; mapping: GLenum; componentUsage: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCombinerOutputNV: procedure(stage: GLenum; portion: GLenum; abOutput: GLenum; cdOutput: GLenum; sumOutput: GLenum; scale: GLenum; bias: GLenum; abDotProduct: GLboolean; cdDotProduct: GLboolean; muxSum: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFinalCombinerInputNV: procedure(variable: GLenum; input: GLenum; mapping: GLenum; componentUsage: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetCombinerInputParameterfvNV: procedure(stage: GLenum; portion: GLenum; variable: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetCombinerInputParameterivNV: procedure(stage: GLenum; portion: GLenum; variable: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetCombinerOutputParameterfvNV: procedure(stage: GLenum; portion: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetCombinerOutputParameterivNV: procedure(stage: GLenum; portion: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetFinalCombinerInputParameterfvNV: procedure(variable: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetFinalCombinerInputParameterivNV: procedure(variable: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_register_combiners: Boolean;
+
+//***** GL_NV_register_combiners2 *****//
+const
+  GL_PER_STAGE_CONSTANTS_NV = $8535;
+var
+  glCombinerStageParameterfvNV: procedure(stage: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetCombinerStageParameterfvNV: procedure(stage: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_register_combiners2: Boolean;
+
+//***** GL_NV_texgen_emboss *****//
+const
+  GL_EMBOSS_MAP_NV = $855F;
+  GL_EMBOSS_LIGHT_NV = $855D;
+  GL_EMBOSS_CONSTANT_NV = $855E;
+
+function Load_GL_NV_texgen_emboss: Boolean;
+
+//***** GL_NV_texgen_reflection *****//
+const
+  GL_NORMAL_MAP_NV = $8511;
+  GL_REFLECTION_MAP_NV = $8512;
+
+function Load_GL_NV_texgen_reflection: Boolean;
+
+//***** GL_NV_texture_compression_vtc *****//
+  // GL_COMPRESSED_RGB_S3TC_DXT1_EXT  { already defined }
+  // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  { already defined }
+  // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  { already defined }
+  // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  { already defined }
+
+function Load_GL_NV_texture_compression_vtc: Boolean;
+
+//***** GL_NV_texture_env_combine4 *****//
+const
+  GL_COMBINE4_NV = $8503;
+  GL_SOURCE3_RGB_NV = $8583;
+  GL_SOURCE3_ALPHA_NV = $858B;
+  GL_OPERAND3_RGB_NV = $8593;
+  GL_OPERAND3_ALPHA_NV = $859B;
+
+function Load_GL_NV_texture_env_combine4: Boolean;
+
+//***** GL_NV_texture_rectangle *****//
+const
+  GL_TEXTURE_RECTANGLE_NV = $84F5;
+  GL_TEXTURE_BINDING_RECTANGLE_NV = $84F6;
+  GL_PROXY_TEXTURE_RECTANGLE_NV = $84F7;
+  GL_MAX_RECTANGLE_TEXTURE_SIZE_NV = $84F8;
+
+function Load_GL_NV_texture_rectangle: Boolean;
+
+//***** GL_NV_texture_shader *****//
+const
+  GL_TEXTURE_SHADER_NV = $86DE;
+  GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV = $86D9;
+  GL_SHADER_OPERATION_NV = $86DF;
+  GL_CULL_MODES_NV = $86E0;
+  GL_OFFSET_TEXTURE_MATRIX_NV = $86E1;
+  GL_OFFSET_TEXTURE_SCALE_NV = $86E2;
+  GL_OFFSET_TEXTURE_BIAS_NV = $86E3;
+  GL_PREVIOUS_TEXTURE_INPUT_NV = $86E4;
+  GL_CONST_EYE_NV = $86E5;
+  GL_SHADER_CONSISTENT_NV = $86DD;
+  GL_PASS_THROUGH_NV = $86E6;
+  GL_CULL_FRAGMENT_NV = $86E7;
+  GL_OFFSET_TEXTURE_2D_NV = $86E8;
+  GL_OFFSET_TEXTURE_RECTANGLE_NV = $864C;
+  GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV = $864D;
+  GL_DEPENDENT_AR_TEXTURE_2D_NV = $86E9;
+  GL_DEPENDENT_GB_TEXTURE_2D_NV = $86EA;
+  GL_DOT_PRODUCT_NV = $86EC;
+  GL_DOT_PRODUCT_DEPTH_REPLACE_NV = $86ED;
+  GL_DOT_PRODUCT_TEXTURE_2D_NV = $86EE;
+  GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV = $864E;
+  GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV = $86F0;
+  GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV = $86F1;
+  GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV = $86F2;
+  GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV = $86F3;
+  GL_HILO_NV = $86F4;
+  GL_DSDT_NV = $86F5;
+  GL_DSDT_MAG_NV = $86F6;
+  GL_DSDT_MAG_VIB_NV = $86F7;
+  GL_UNSIGNED_INT_S8_S8_8_8_NV = $86DA;
+  GL_UNSIGNED_INT_8_8_S8_S8_REV_NV = $86DB;
+  GL_SIGNED_RGBA_NV = $86FB;
+  GL_SIGNED_RGBA8_NV = $86FC;
+  GL_SIGNED_RGB_NV = $86FE;
+  GL_SIGNED_RGB8_NV = $86FF;
+  GL_SIGNED_LUMINANCE_NV = $8701;
+  GL_SIGNED_LUMINANCE8_NV = $8702;
+  GL_SIGNED_LUMINANCE_ALPHA_NV = $8703;
+  GL_SIGNED_LUMINANCE8_ALPHA8_NV = $8704;
+  GL_SIGNED_ALPHA_NV = $8705;
+  GL_SIGNED_ALPHA8_NV = $8706;
+  GL_SIGNED_INTENSITY_NV = $8707;
+  GL_SIGNED_INTENSITY8_NV = $8708;
+  GL_SIGNED_RGB_UNSIGNED_ALPHA_NV = $870C;
+  GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV = $870D;
+  GL_HILO16_NV = $86F8;
+  GL_SIGNED_HILO_NV = $86F9;
+  GL_SIGNED_HILO16_NV = $86FA;
+  GL_DSDT8_NV = $8709;
+  GL_DSDT8_MAG8_NV = $870A;
+  GL_DSDT_MAG_INTENSITY_NV = $86DC;
+  GL_DSDT8_MAG8_INTENSITY8_NV = $870B;
+  GL_HI_SCALE_NV = $870E;
+  GL_LO_SCALE_NV = $870F;
+  GL_DS_SCALE_NV = $8710;
+  GL_DT_SCALE_NV = $8711;
+  GL_MAGNITUDE_SCALE_NV = $8712;
+  GL_VIBRANCE_SCALE_NV = $8713;
+  GL_HI_BIAS_NV = $8714;
+  GL_LO_BIAS_NV = $8715;
+  GL_DS_BIAS_NV = $8716;
+  GL_DT_BIAS_NV = $8717;
+  GL_MAGNITUDE_BIAS_NV = $8718;
+  GL_VIBRANCE_BIAS_NV = $8719;
+  GL_TEXTURE_BORDER_VALUES_NV = $871A;
+  GL_TEXTURE_HI_SIZE_NV = $871B;
+  GL_TEXTURE_LO_SIZE_NV = $871C;
+  GL_TEXTURE_DS_SIZE_NV = $871D;
+  GL_TEXTURE_DT_SIZE_NV = $871E;
+  GL_TEXTURE_MAG_SIZE_NV = $871F;
+
+function Load_GL_NV_texture_shader: Boolean;
+
+//***** GL_NV_texture_shader2 *****//
+const
+  GL_DOT_PRODUCT_TEXTURE_3D_NV = $86EF;
+  // GL_HILO_NV  { already defined }
+  // GL_DSDT_NV  { already defined }
+  // GL_DSDT_MAG_NV  { already defined }
+  // GL_DSDT_MAG_VIB_NV  { already defined }
+  // GL_UNSIGNED_INT_S8_S8_8_8_NV  { already defined }
+  // GL_UNSIGNED_INT_8_8_S8_S8_REV_NV  { already defined }
+  // GL_SIGNED_RGBA_NV  { already defined }
+  // GL_SIGNED_RGBA8_NV  { already defined }
+  // GL_SIGNED_RGB_NV  { already defined }
+  // GL_SIGNED_RGB8_NV  { already defined }
+  // GL_SIGNED_LUMINANCE_NV  { already defined }
+  // GL_SIGNED_LUMINANCE8_NV  { already defined }
+  // GL_SIGNED_LUMINANCE_ALPHA_NV  { already defined }
+  // GL_SIGNED_LUMINANCE8_ALPHA8_NV  { already defined }
+  // GL_SIGNED_ALPHA_NV  { already defined }
+  // GL_SIGNED_ALPHA8_NV  { already defined }
+  // GL_SIGNED_INTENSITY_NV  { already defined }
+  // GL_SIGNED_INTENSITY8_NV  { already defined }
+  // GL_SIGNED_RGB_UNSIGNED_ALPHA_NV  { already defined }
+  // GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV  { already defined }
+  // GL_HILO16_NV  { already defined }
+  // GL_SIGNED_HILO_NV  { already defined }
+  // GL_SIGNED_HILO16_NV  { already defined }
+  // GL_DSDT8_NV  { already defined }
+  // GL_DSDT8_MAG8_NV  { already defined }
+  // GL_DSDT_MAG_INTENSITY_NV  { already defined }
+  // GL_DSDT8_MAG8_INTENSITY8_NV  { already defined }
+
+function Load_GL_NV_texture_shader2: Boolean;
+
+//***** GL_NV_texture_shader3 *****//
+const
+  GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV = $8850;
+  GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV = $8851;
+  GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV = $8852;
+  GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV = $8853;
+  GL_OFFSET_HILO_TEXTURE_2D_NV = $8854;
+  GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV = $8855;
+  GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV = $8856;
+  GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV = $8857;
+  GL_DEPENDENT_HILO_TEXTURE_2D_NV = $8858;
+  GL_DEPENDENT_RGB_TEXTURE_3D_NV = $8859;
+  GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV = $885A;
+  GL_DOT_PRODUCT_PASS_THROUGH_NV = $885B;
+  GL_DOT_PRODUCT_TEXTURE_1D_NV = $885C;
+  GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV = $885D;
+  GL_HILO8_NV = $885E;
+  GL_SIGNED_HILO8_NV = $885F;
+  GL_FORCE_BLUE_TO_ONE_NV = $8860;
+
+function Load_GL_NV_texture_shader3: Boolean;
+
+//***** GL_NV_vertex_array_range *****//
+const
+  GL_VERTEX_ARRAY_RANGE_NV = $851D;
+  GL_VERTEX_ARRAY_RANGE_LENGTH_NV = $851E;
+  GL_VERTEX_ARRAY_RANGE_VALID_NV = $851F;
+  GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV = $8520;
+  GL_VERTEX_ARRAY_RANGE_POINTER_NV = $8521;
+var
+  glVertexArrayRangeNV: procedure(length: GLsizei; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFlushVertexArrayRangeNV: procedure(); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+{$IFDEF WINDOWS}
+  wglAllocateMemoryNV: function(size: GLsizei; readFrequency: GLfloat; writeFrequency: GLfloat; priority: GLfloat): PGLvoid; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglFreeMemoryNV: procedure(pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+{$ENDIF}
+
+function Load_GL_NV_vertex_array_range: Boolean;
+
+//***** GL_NV_vertex_array_range2 *****//
+const
+  GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV = $8533;
+
+function Load_GL_NV_vertex_array_range2: Boolean;
+
+//***** GL_NV_vertex_program *****//
+const
+  GL_VERTEX_PROGRAM_NV = $8620;
+  GL_VERTEX_PROGRAM_POINT_SIZE_NV = $8642;
+  GL_VERTEX_PROGRAM_TWO_SIDE_NV = $8643;
+  GL_VERTEX_STATE_PROGRAM_NV = $8621;
+  GL_ATTRIB_ARRAY_SIZE_NV = $8623;
+  GL_ATTRIB_ARRAY_STRIDE_NV = $8624;
+  GL_ATTRIB_ARRAY_TYPE_NV = $8625;
+  GL_CURRENT_ATTRIB_NV = $8626;
+  GL_PROGRAM_PARAMETER_NV = $8644;
+  GL_ATTRIB_ARRAY_POINTER_NV = $8645;
+  GL_PROGRAM_TARGET_NV = $8646;
+  GL_PROGRAM_LENGTH_NV = $8627;
+  GL_PROGRAM_RESIDENT_NV = $8647;
+  GL_PROGRAM_STRING_NV = $8628;
+  GL_TRACK_MATRIX_NV = $8648;
+  GL_TRACK_MATRIX_TRANSFORM_NV = $8649;
+  GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV = $862E;
+  GL_MAX_TRACK_MATRICES_NV = $862F;
+  GL_CURRENT_MATRIX_STACK_DEPTH_NV = $8640;
+  GL_CURRENT_MATRIX_NV = $8641;
+  GL_VERTEX_PROGRAM_BINDING_NV = $864A;
+  GL_PROGRAM_ERROR_POSITION_NV = $864B;
+  GL_MODELVIEW_PROJECTION_NV = $8629;
+  GL_MATRIX0_NV = $8630;
+  GL_MATRIX1_NV = $8631;
+  GL_MATRIX2_NV = $8632;
+  GL_MATRIX3_NV = $8633;
+  GL_MATRIX4_NV = $8634;
+  GL_MATRIX5_NV = $8635;
+  GL_MATRIX6_NV = $8636;
+  GL_MATRIX7_NV = $8637;
+  GL_IDENTITY_NV = $862A;
+  GL_INVERSE_NV = $862B;
+  GL_TRANSPOSE_NV = $862C;
+  GL_INVERSE_TRANSPOSE_NV = $862D;
+  GL_VERTEX_ATTRIB_ARRAY0_NV = $8650;
+  GL_VERTEX_ATTRIB_ARRAY1_NV = $8651;
+  GL_VERTEX_ATTRIB_ARRAY2_NV = $8652;
+  GL_VERTEX_ATTRIB_ARRAY3_NV = $8653;
+  GL_VERTEX_ATTRIB_ARRAY4_NV = $8654;
+  GL_VERTEX_ATTRIB_ARRAY5_NV = $8655;
+  GL_VERTEX_ATTRIB_ARRAY6_NV = $8656;
+  GL_VERTEX_ATTRIB_ARRAY7_NV = $8657;
+  GL_VERTEX_ATTRIB_ARRAY8_NV = $8658;
+  GL_VERTEX_ATTRIB_ARRAY9_NV = $8659;
+  GL_VERTEX_ATTRIB_ARRAY10_NV = $865A;
+  GL_VERTEX_ATTRIB_ARRAY11_NV = $865B;
+  GL_VERTEX_ATTRIB_ARRAY12_NV = $865C;
+  GL_VERTEX_ATTRIB_ARRAY13_NV = $865D;
+  GL_VERTEX_ATTRIB_ARRAY14_NV = $865E;
+  GL_VERTEX_ATTRIB_ARRAY15_NV = $865F;
+  GL_MAP1_VERTEX_ATTRIB0_4_NV = $8660;
+  GL_MAP1_VERTEX_ATTRIB1_4_NV = $8661;
+  GL_MAP1_VERTEX_ATTRIB2_4_NV = $8662;
+  GL_MAP1_VERTEX_ATTRIB3_4_NV = $8663;
+  GL_MAP1_VERTEX_ATTRIB4_4_NV = $8664;
+  GL_MAP1_VERTEX_ATTRIB5_4_NV = $8665;
+  GL_MAP1_VERTEX_ATTRIB6_4_NV = $8666;
+  GL_MAP1_VERTEX_ATTRIB7_4_NV = $8667;
+  GL_MAP1_VERTEX_ATTRIB8_4_NV = $8668;
+  GL_MAP1_VERTEX_ATTRIB9_4_NV = $8669;
+  GL_MAP1_VERTEX_ATTRIB10_4_NV = $866A;
+  GL_MAP1_VERTEX_ATTRIB11_4_NV = $866B;
+  GL_MAP1_VERTEX_ATTRIB12_4_NV = $866C;
+  GL_MAP1_VERTEX_ATTRIB13_4_NV = $866D;
+  GL_MAP1_VERTEX_ATTRIB14_4_NV = $866E;
+  GL_MAP1_VERTEX_ATTRIB15_4_NV = $866F;
+  GL_MAP2_VERTEX_ATTRIB0_4_NV = $8670;
+  GL_MAP2_VERTEX_ATTRIB1_4_NV = $8671;
+  GL_MAP2_VERTEX_ATTRIB2_4_NV = $8672;
+  GL_MAP2_VERTEX_ATTRIB3_4_NV = $8673;
+  GL_MAP2_VERTEX_ATTRIB4_4_NV = $8674;
+  GL_MAP2_VERTEX_ATTRIB5_4_NV = $8675;
+  GL_MAP2_VERTEX_ATTRIB6_4_NV = $8676;
+  GL_MAP2_VERTEX_ATTRIB7_4_NV = $8677;
+  GL_MAP2_VERTEX_ATTRIB8_4_NV = $8678;
+  GL_MAP2_VERTEX_ATTRIB9_4_NV = $8679;
+  GL_MAP2_VERTEX_ATTRIB10_4_NV = $867A;
+  GL_MAP2_VERTEX_ATTRIB11_4_NV = $867B;
+  GL_MAP2_VERTEX_ATTRIB12_4_NV = $867C;
+  GL_MAP2_VERTEX_ATTRIB13_4_NV = $867D;
+  GL_MAP2_VERTEX_ATTRIB14_4_NV = $867E;
+  GL_MAP2_VERTEX_ATTRIB15_4_NV = $867F;
+var
+  glBindProgramNV: procedure(target: GLenum; id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteProgramsNV: procedure(n: GLsizei; const ids: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glExecuteProgramNV: procedure(target: GLenum; id: GLuint; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenProgramsNV: procedure(n: GLsizei; ids: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAreProgramsResidentNV: function(n: GLsizei; const ids: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRequestResidentProgramsNV: procedure(n: GLsizei; ids: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramParameterfvNV: procedure(target: GLenum; index: GLuint; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramParameterdvNV: procedure(target: GLenum; index: GLuint; pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramivNV: procedure(id: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramStringNV: procedure(id: GLuint; pname: GLenum; _program: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTrackMatrixivNV: procedure(target: GLenum; address: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribdvNV: procedure(index: GLuint; pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribfvNV: procedure(index: GLuint; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribivNV: procedure(index: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribPointervNV: procedure(index: GLuint; pname: GLenum; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsProgramNV: function(id: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadProgramNV: procedure(target: GLenum; id: GLuint; len: GLsizei; const _program: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramParameter4fNV: procedure(target: GLenum; index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramParameter4fvNV: procedure(target: GLenum; index: GLuint; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramParameters4dvNV: procedure(target: GLenum; index: GLuint; num: GLuint; const params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramParameters4fvNV: procedure(target: GLenum; index: GLuint; num: GLuint; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTrackMatrixNV: procedure(target: GLenum; address: GLuint; matrix: GLenum; transform: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribPointerNV: procedure(index: GLuint; size: GLint; _type: GLenum; stride: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1sNV: procedure(index: GLuint; x: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1fNV: procedure(index: GLuint; x: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1dNV: procedure(index: GLuint; x: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2sNV: procedure(index: GLuint; x: GLshort; y: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2fNV: procedure(index: GLuint; x: GLfloat; y: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2dNV: procedure(index: GLuint; x: GLdouble; y: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3sNV: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3fNV: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3dNV: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4sNV: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort; w: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4fNV: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4dNV: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4ubNV: procedure(index: GLuint; x: GLubyte; y: GLubyte; z: GLubyte; w: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1svNV: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1fvNV: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1dvNV: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2svNV: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2fvNV: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2dvNV: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3svNV: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3fvNV: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3dvNV: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4svNV: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4fvNV: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4dvNV: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4ubvNV: procedure(index: GLuint; const v: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs1svNV: procedure(index: GLuint; n: GLsizei; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs1fvNV: procedure(index: GLuint; n: GLsizei; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs1dvNV: procedure(index: GLuint; n: GLsizei; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs2svNV: procedure(index: GLuint; n: GLsizei; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs2fvNV: procedure(index: GLuint; n: GLsizei; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs2dvNV: procedure(index: GLuint; n: GLsizei; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs3svNV: procedure(index: GLuint; n: GLsizei; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs3fvNV: procedure(index: GLuint; n: GLsizei; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs3dvNV: procedure(index: GLuint; n: GLsizei; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs4svNV: procedure(index: GLuint; n: GLsizei; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs4fvNV: procedure(index: GLuint; n: GLsizei; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs4dvNV: procedure(index: GLuint; n: GLsizei; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs4ubvNV: procedure(index: GLuint; n: GLsizei; const v: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_vertex_program: Boolean;
+
+//***** GL_NV_vertex_program1_1 *****//
+
+function Load_GL_NV_vertex_program1_1: Boolean;
+
+//***** GL_ATI_element_array *****//
+const
+  GL_ELEMENT_ARRAY_ATI = $8768;
+  GL_ELEMENT_ARRAY_TYPE_ATI = $8769;
+  GL_ELEMENT_ARRAY_POINTER_ATI = $876A;
+var
+  glElementPointerATI: procedure(_type: GLenum; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawElementArrayATI: procedure(mode: GLenum; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawRangeElementArrayATI: procedure(mode: GLenum; start: GLuint; _end: GLuint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_element_array: Boolean;
+
+//***** GL_ATI_envmap_bumpmap *****//
+const
+  GL_BUMP_ROT_MATRIX_ATI = $8775;
+  GL_BUMP_ROT_MATRIX_SIZE_ATI = $8776;
+  GL_BUMP_NUM_TEX_UNITS_ATI = $8777;
+  GL_BUMP_TEX_UNITS_ATI = $8778;
+  GL_DUDV_ATI = $8779;
+  GL_DU8DV8_ATI = $877A;
+  GL_BUMP_ENVMAP_ATI = $877B;
+  GL_BUMP_TARGET_ATI = $877C;
+var
+  glTexBumpParameterivATI: procedure(pname: GLenum; param: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexBumpParameterfvATI: procedure(pname: GLenum; param: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexBumpParameterivATI: procedure(pname: GLenum; param: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexBumpParameterfvATI: procedure(pname: GLenum; param: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_envmap_bumpmap: Boolean;
+
+//***** GL_ATI_fragment_shader *****//
+const
+  GL_FRAGMENT_SHADER_ATI = $8920;
+  GL_REG_0_ATI = $8921;
+  GL_REG_1_ATI = $8922;
+  GL_REG_2_ATI = $8923;
+  GL_REG_3_ATI = $8924;
+  GL_REG_4_ATI = $8925;
+  GL_REG_5_ATI = $8926;
+  GL_CON_0_ATI = $8941;
+  GL_CON_1_ATI = $8942;
+  GL_CON_2_ATI = $8943;
+  GL_CON_3_ATI = $8944;
+  GL_CON_4_ATI = $8945;
+  GL_CON_5_ATI = $8946;
+  GL_CON_6_ATI = $8947;
+  GL_CON_7_ATI = $8948;
+  GL_MOV_ATI = $8961;
+  GL_ADD_ATI = $8963;
+  GL_MUL_ATI = $8964;
+  GL_SUB_ATI = $8965;
+  GL_DOT3_ATI = $8966;
+  GL_DOT4_ATI = $8967;
+  GL_MAD_ATI = $8968;
+  GL_LERP_ATI = $8969;
+  GL_CND_ATI = $896A;
+  GL_CND0_ATI = $896B;
+  GL_DOT2_ADD_ATI = $896C;
+  GL_SECONDARY_INTERPOLATOR_ATI = $896D;
+  GL_SWIZZLE_STR_ATI = $8976;
+  GL_SWIZZLE_STQ_ATI = $8977;
+  GL_SWIZZLE_STR_DR_ATI = $8978;
+  GL_SWIZZLE_STQ_DQ_ATI = $8979;
+  GL_RED_BIT_ATI = $0001;
+  GL_GREEN_BIT_ATI = $0002;
+  GL_BLUE_BIT_ATI = $0004;
+  GL_2X_BIT_ATI = $0001;
+  GL_4X_BIT_ATI = $0002;
+  GL_8X_BIT_ATI = $0004;
+  GL_HALF_BIT_ATI = $0008;
+  GL_QUARTER_BIT_ATI = $0010;
+  GL_EIGHTH_BIT_ATI = $0020;
+  GL_SATURATE_BIT_ATI = $0040;
+  // GL_2X_BIT_ATI  { already defined }
+  GL_COMP_BIT_ATI = $0002;
+  GL_NEGATE_BIT_ATI = $0004;
+  GL_BIAS_BIT_ATI = $0008;
+var
+  glGenFragmentShadersATI: function(range: GLuint): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindFragmentShaderATI: procedure(id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteFragmentShaderATI: procedure(id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBeginFragmentShaderATI: procedure(); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEndFragmentShaderATI: procedure(); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPassTexCoordATI: procedure(dst: GLuint; coord: GLuint; swizzle: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSampleMapATI: procedure(dst: GLuint; interp: GLuint; swizzle: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorFragmentOp1ATI: procedure(op: GLenum; dst: GLuint; dstMask: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorFragmentOp2ATI: procedure(op: GLenum; dst: GLuint; dstMask: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint; arg2: GLuint; arg2Rep: GLuint; arg2Mod: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorFragmentOp3ATI: procedure(op: GLenum; dst: GLuint; dstMask: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint; arg2: GLuint; arg2Rep: GLuint; arg2Mod: GLuint; arg3: GLuint; arg3Rep: GLuint; arg3Mod: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAlphaFragmentOp1ATI: procedure(op: GLenum; dst: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAlphaFragmentOp2ATI: procedure(op: GLenum; dst: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint; arg2: GLuint; arg2Rep: GLuint; arg2Mod: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAlphaFragmentOp3ATI: procedure(op: GLenum; dst: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint; arg2: GLuint; arg2Rep: GLuint; arg2Mod: GLuint; arg3: GLuint; arg3Rep: GLuint; arg3Mod: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSetFragmentShaderConstantATI: procedure(dst: GLuint; const value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_fragment_shader: Boolean;
+
+//***** GL_ATI_pn_triangles *****//
+const
+  GL_PN_TRIANGLES_ATI = $87F0;
+  GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI = $87F1;
+  GL_PN_TRIANGLES_POINT_MODE_ATI = $87F2;
+  GL_PN_TRIANGLES_NORMAL_MODE_ATI = $87F3;
+  GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI = $87F4;
+  GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI = $87F5;
+  GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI = $87F6;
+  GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI = $87F7;
+  GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI = $87F8;
+var
+  glPNTrianglesiATI: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPNTrianglesfATI: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_pn_triangles: Boolean;
+
+//***** GL_ATI_texture_mirror_once *****//
+const
+  GL_MIRROR_CLAMP_ATI = $8742;
+  GL_MIRROR_CLAMP_TO_EDGE_ATI = $8743;
+
+function Load_GL_ATI_texture_mirror_once: Boolean;
+
+//***** GL_ATI_vertex_array_object *****//
+const
+  GL_STATIC_ATI = $8760;
+  GL_DYNAMIC_ATI = $8761;
+  GL_PRESERVE_ATI = $8762;
+  GL_DISCARD_ATI = $8763;
+  GL_OBJECT_BUFFER_SIZE_ATI = $8764;
+  GL_OBJECT_BUFFER_USAGE_ATI = $8765;
+  GL_ARRAY_OBJECT_BUFFER_ATI = $8766;
+  GL_ARRAY_OBJECT_OFFSET_ATI = $8767;
+var
+  glNewObjectBufferATI: function(size: GLsizei; const pointer: PGLvoid; usage: GLenum): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsObjectBufferATI: function(buffer: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUpdateObjectBufferATI: procedure(buffer: GLuint; offset: GLuint; size: GLsizei; const pointer: PGLvoid; preserve: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetObjectBufferfvATI: procedure(buffer: GLuint; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetObjectBufferivATI: procedure(buffer: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteObjectBufferATI: procedure(buffer: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glArrayObjectATI: procedure(_array: GLenum; size: GLint; _type: GLenum; stride: GLsizei; buffer: GLuint; offset: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetArrayObjectfvATI: procedure(_array: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetArrayObjectivATI: procedure(_array: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVariantArrayObjectATI: procedure(id: GLuint; _type: GLenum; stride: GLsizei; buffer: GLuint; offset: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVariantArrayObjectfvATI: procedure(id: GLuint; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVariantArrayObjectivATI: procedure(id: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_vertex_array_object: Boolean;
+
+//***** GL_ATI_vertex_streams *****//
+const
+  GL_MAX_VERTEX_STREAMS_ATI = $876B;
+  GL_VERTEX_STREAM0_ATI = $876C;
+  GL_VERTEX_STREAM1_ATI = $876D;
+  GL_VERTEX_STREAM2_ATI = $876E;
+  GL_VERTEX_STREAM3_ATI = $876F;
+  GL_VERTEX_STREAM4_ATI = $8770;
+  GL_VERTEX_STREAM5_ATI = $8771;
+  GL_VERTEX_STREAM6_ATI = $8772;
+  GL_VERTEX_STREAM7_ATI = $8773;
+  GL_VERTEX_SOURCE_ATI = $8774;
+var
+  glVertexStream1s: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream1i: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream1f: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream1d: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream1sv: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream1iv: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream1fv: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream1dv: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream2s: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream2i: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream2f: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream2d: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream2sv: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream2iv: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream2fv: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream2dv: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream3s: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream3i: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream3f: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream3d: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream3sv: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream3iv: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream3fv: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream3dv: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream4s: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream4i: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream4f: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream4d: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream4sv: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream4iv: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream4fv: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexStream4dv: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3b: procedure(stream: GLenum; coords: GLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3s: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3i: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3f: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3d: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3bv: procedure(stream: GLenum; coords: GLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3sv: procedure(stream: GLenum; coords: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3iv: procedure(stream: GLenum; coords: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3fv: procedure(stream: GLenum; coords: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalStream3dv: procedure(stream: GLenum; coords: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClientActiveVertexStream: procedure(stream: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexBlendEnvi: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexBlendEnvf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_vertex_streams: Boolean;
+
+{$IFDEF WINDOWS}
+//***** WGL_I3D_image_buffer *****//
+const
+  WGL_IMAGE_BUFFER_MIN_ACCESS_I3D = $0001;
+  WGL_IMAGE_BUFFER_LOCK_I3D = $0002;
+var
+  wglCreateImageBufferI3D: function(hDC: HDC; dwSize: DWORD; uFlags: UINT): PGLvoid; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglDestroyImageBufferI3D: function(hDC: HDC; pAddress: PGLvoid): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglAssociateImageBufferEventsI3D: function(hdc: HDC; pEvent: PHandle; pAddress: PGLvoid; pSize: PDWORD; count: UINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglReleaseImageBufferEventsI3D: function(hdc: HDC; pAddress: PGLvoid; count: UINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_I3D_image_buffer: Boolean;
+
+//***** WGL_I3D_swap_frame_lock *****//
+var
+  wglEnableFrameLockI3D: function(): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglDisableFrameLockI3D: function(): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglIsEnabledFrameLockI3D: function(pFlag: PBOOL): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglQueryFrameLockMasterI3D: function(pFlag: PBOOL): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_I3D_swap_frame_lock: Boolean;
+
+//***** WGL_I3D_swap_frame_usage *****//
+var
+  wglGetFrameUsageI3D: function(pUsage: PGLfloat): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglBeginFrameTrackingI3D: function(): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglEndFrameTrackingI3D: function(): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglQueryFrameTrackingI3D: function(pFrameCount: PDWORD; pMissedFrames: PDWORD; pLastMissedUsage: PGLfloat): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_I3D_swap_frame_usage: Boolean;
+{$ENDIF}
+
+//***** GL_3DFX_texture_compression_FXT1 *****//
+const
+  GL_COMPRESSED_RGB_FXT1_3DFX = $86B0;
+  GL_COMPRESSED_RGBA_FXT1_3DFX = $86B1;
+
+function Load_GL_3DFX_texture_compression_FXT1: Boolean;
+
+//***** GL_IBM_cull_vertex *****//
+const
+  GL_CULL_VERTEX_IBM = $1928A;
+
+function Load_GL_IBM_cull_vertex: Boolean;
+
+//***** GL_IBM_multimode_draw_arrays *****//
+var
+  glMultiModeDrawArraysIBM: procedure(mode: PGLenum; first: PGLint; count: PGLsizei; primcount: GLsizei; modestride: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiModeDrawElementsIBM: procedure(mode: PGLenum; count: PGLsizei; _type: GLenum; const indices: PGLvoid; primcount: GLsizei; modestride: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_IBM_multimode_draw_arrays: Boolean;
+
+//***** GL_IBM_raster_pos_clip *****//
+const
+  GL_RASTER_POSITION_UNCLIPPED_IBM = $19262;
+
+function Load_GL_IBM_raster_pos_clip: Boolean;
+
+//***** GL_IBM_texture_mirrored_repeat *****//
+const
+  GL_MIRRORED_REPEAT_IBM = $8370;
+
+function Load_GL_IBM_texture_mirrored_repeat: Boolean;
+
+//***** GL_IBM_vertex_array_lists *****//
+const
+  GL_VERTEX_ARRAY_LIST_IBM = $1929E;
+  GL_NORMAL_ARRAY_LIST_IBM = $1929F;
+  GL_COLOR_ARRAY_LIST_IBM = $192A0;
+  GL_INDEX_ARRAY_LIST_IBM = $192A1;
+  GL_TEXTURE_COORD_ARRAY_LIST_IBM = $192A2;
+  GL_EDGE_FLAG_ARRAY_LIST_IBM = $192A3;
+  GL_FOG_COORDINATE_ARRAY_LIST_IBM = $192A4;
+  GL_SECONDARY_COLOR_ARRAY_LIST_IBM = $192A5;
+  GL_VERTEX_ARRAY_LIST_STRIDE_IBM = $192A8;
+  GL_NORMAL_ARRAY_LIST_STRIDE_IBM = $192A9;
+  GL_COLOR_ARRAY_LIST_STRIDE_IBM = $192AA;
+  GL_INDEX_ARRAY_LIST_STRIDE_IBM = $192AB;
+  GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM = $192AC;
+  GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM = $192AD;
+  GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM = $192AE;
+  GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM = $192AF;
+var
+  glColorPointerListIBM: procedure(size: GLint; _type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColorPointerListIBM: procedure(size: GLint; _type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEdgeFlagPointerListIBM: procedure(stride: GLint; const pointer: PGLboolean; ptrstride: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoordPointerListIBM: procedure(_type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalPointerListIBM: procedure(_type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoordPointerListIBM: procedure(size: GLint; _type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexPointerListIBM: procedure(size: GLint; _type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_IBM_vertex_array_lists: Boolean;
+
+//***** GL_MESA_resize_buffers *****//
+var
+  glResizeBuffersMESA: procedure(); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_MESA_resize_buffers: Boolean;
+
+//***** GL_MESA_window_pos *****//
+var
+  glWindowPos2dMESA: procedure(x: GLdouble; y: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2fMESA: procedure(x: GLfloat; y: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2iMESA: procedure(x: GLint; y: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2sMESA: procedure(x: GLshort; y: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2ivMESA: procedure(const p: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2svMESA: procedure(const p: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2fvMESA: procedure(const p: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2dvMESA: procedure(const p: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3iMESA: procedure(x: GLint; y: GLint; z: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3sMESA: procedure(x: GLshort; y: GLshort; z: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3fMESA: procedure(x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3dMESA: procedure(x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3ivMESA: procedure(const p: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3svMESA: procedure(const p: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3fvMESA: procedure(const p: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3dvMESA: procedure(const p: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos4iMESA: procedure(x: GLint; y: GLint; z: GLint; w: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos4sMESA: procedure(x: GLshort; y: GLshort; z: GLshort; w: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos4fMESA: procedure(x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos4dMESA: procedure(x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos4ivMESA: procedure(const p: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos4svMESA: procedure(const p: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos4fvMESA: procedure(const p: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos4dvMESA: procedure(const p: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_MESA_window_pos: Boolean;
+
+//***** GL_OML_interlace *****//
+const
+  GL_INTERLACE_OML = $8980;
+  GL_INTERLACE_READ_OML = $8981;
+
+function Load_GL_OML_interlace: Boolean;
+
+//***** GL_OML_resample *****//
+const
+  GL_PACK_RESAMPLE_OML = $8984;
+  GL_UNPACK_RESAMPLE_OML = $8985;
+  GL_RESAMPLE_REPLICATE_OML = $8986;
+  GL_RESAMPLE_ZERO_FILL_OML = $8987;
+  GL_RESAMPLE_AVERAGE_OML = $8988;
+  GL_RESAMPLE_DECIMATE_OML = $8989;
+  // GL_RESAMPLE_AVERAGE_OML  { already defined }
+
+function Load_GL_OML_resample: Boolean;
+
+//***** GL_OML_subsample *****//
+const
+  GL_FORMAT_SUBSAMPLE_24_24_OML = $8982;
+  GL_FORMAT_SUBSAMPLE_244_244_OML = $8983;
+
+function Load_GL_OML_subsample: Boolean;
+
+//***** GL_SGIS_generate_mipmap *****//
+const
+  GL_GENERATE_MIPMAP_SGIS = $8191;
+  GL_GENERATE_MIPMAP_HINT_SGIS = $8192;
+
+function Load_GL_SGIS_generate_mipmap: Boolean;
+
+//***** GL_SGIS_multisample *****//
+const
+  GLX_SAMPLE_BUFFERS_SGIS = $186A0;
+  GLX_SAMPLES_SGIS = $186A1;
+  GL_MULTISAMPLE_SGIS = $809D;
+  GL_SAMPLE_ALPHA_TO_MASK_SGIS = $809E;
+  GL_SAMPLE_ALPHA_TO_ONE_SGIS = $809F;
+  GL_SAMPLE_MASK_SGIS = $80A0;
+  GL_MULTISAMPLE_BIT_EXT = $20000000;
+  GL_1PASS_SGIS = $80A1;
+  GL_2PASS_0_SGIS = $80A2;
+  GL_2PASS_1_SGIS = $80A3;
+  GL_4PASS_0_SGIS = $80A4;
+  GL_4PASS_1_SGIS = $80A5;
+  GL_4PASS_2_SGIS = $80A6;
+  GL_4PASS_3_SGIS = $80A7;
+  GL_SAMPLE_BUFFERS_SGIS = $80A8;
+  GL_SAMPLES_SGIS = $80A9;
+  GL_SAMPLE_MASK_VALUE_SGIS = $80AA;
+  GL_SAMPLE_MASK_INVERT_SGIS = $80AB;
+  GL_SAMPLE_PATTERN_SGIS = $80AC;
+var
+  glSampleMaskSGIS: procedure(value: GLclampf; invert: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSamplePatternSGIS: procedure(pattern: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_SGIS_multisample: Boolean;
+
+//***** GL_SGIS_pixel_texture *****//
+const
+  GL_PIXEL_TEXTURE_SGIS = $8353;
+  GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS = $8354;
+  GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS = $8355;
+  GL_PIXEL_GROUP_COLOR_SGIS = $8356;
+var
+  glPixelTexGenParameteriSGIS: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelTexGenParameterfSGIS: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPixelTexGenParameterivSGIS: procedure(pname: GLenum; params: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPixelTexGenParameterfvSGIS: procedure(pname: GLenum; params: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_SGIS_pixel_texture: Boolean;
+
+//***** GL_SGIS_texture_border_clamp *****//
+  // GL_CLAMP_TO_BORDER_SGIS  { already defined }
+
+function Load_GL_SGIS_texture_border_clamp: Boolean;
+
+//***** GL_SGIS_texture_color_mask *****//
+const
+  GL_TEXTURE_COLOR_WRITEMASK_SGIS = $81EF;
+var
+  glTextureColorMaskSGIS: procedure(r: GLboolean; g: GLboolean; b: GLboolean; a: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_SGIS_texture_color_mask: Boolean;
+
+//***** GL_SGIS_texture_edge_clamp *****//
+const
+  GL_CLAMP_TO_EDGE_SGIS = $812F;
+
+function Load_GL_SGIS_texture_edge_clamp: Boolean;
+
+//***** GL_SGIS_texture_lod *****//
+const
+  GL_TEXTURE_MIN_LOD_SGIS = $813A;
+  GL_TEXTURE_MAX_LOD_SGIS = $813B;
+  GL_TEXTURE_BASE_LEVEL_SGIS = $813C;
+  GL_TEXTURE_MAX_LEVEL_SGIS = $813D;
+
+function Load_GL_SGIS_texture_lod: Boolean;
+
+//***** GL_SGIS_depth_texture *****//
+const
+  GL_DEPTH_COMPONENT16_SGIX = $81A5;
+  GL_DEPTH_COMPONENT24_SGIX = $81A6;
+  GL_DEPTH_COMPONENT32_SGIX = $81A7;
+
+function Load_GL_SGIS_depth_texture: Boolean;
+
+//***** GL_SGIX_fog_offset *****//
+const
+  GL_FOG_OFFSET_SGIX = $8198;
+  GL_FOG_OFFSET_VALUE_SGIX = $8199;
+
+function Load_GL_SGIX_fog_offset: Boolean;
+
+//***** GL_SGIX_interlace *****//
+const
+  GL_INTERLACE_SGIX = $8094;
+
+function Load_GL_SGIX_interlace: Boolean;
+
+//***** GL_SGIX_shadow_ambient *****//
+const
+  GL_SHADOW_AMBIENT_SGIX = $80BF;
+
+function Load_GL_SGIX_shadow_ambient: Boolean;
+
+//***** GL_SGI_color_matrix *****//
+const
+  GL_COLOR_MATRIX_SGI = $80B1;
+  GL_COLOR_MATRIX_STACK_DEPTH_SGI = $80B2;
+  GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI = $80B3;
+  GL_POST_COLOR_MATRIX_RED_SCALE_SGI = $80B4;
+  GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI = $80B5;
+  GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI = $80B6;
+  GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI = $80B7;
+  GL_POST_COLOR_MATRIX_RED_BIAS_SGI = $80B8;
+  GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI = $80B9;
+  GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI = $80BA;
+  GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI = $80BB;
+
+function Load_GL_SGI_color_matrix: Boolean;
+
+//***** GL_SGI_color_table *****//
+const
+  GL_COLOR_TABLE_SGI = $80D0;
+  GL_POST_CONVOLUTION_COLOR_TABLE_SGI = $80D1;
+  GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI = $80D2;
+  GL_PROXY_COLOR_TABLE_SGI = $80D3;
+  GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI = $80D4;
+  GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI = $80D5;
+  GL_COLOR_TABLE_SCALE_SGI = $80D6;
+  GL_COLOR_TABLE_BIAS_SGI = $80D7;
+  GL_COLOR_TABLE_FORMAT_SGI = $80D8;
+  GL_COLOR_TABLE_WIDTH_SGI = $80D9;
+  GL_COLOR_TABLE_RED_SIZE_SGI = $80DA;
+  GL_COLOR_TABLE_GREEN_SIZE_SGI = $80DB;
+  GL_COLOR_TABLE_BLUE_SIZE_SGI = $80DC;
+  GL_COLOR_TABLE_ALPHA_SIZE_SGI = $80DD;
+  GL_COLOR_TABLE_LUMINANCE_SIZE_SGI = $80DE;
+  GL_COLOR_TABLE_INTENSITY_SIZE_SGI = $80DF;
+var
+  glColorTableSGI: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const table: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyColorTableSGI: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorTableParameterivSGI: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorTableParameterfvSGI: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetColorTableSGI: procedure(target: GLenum; format: GLenum; _type: GLenum; table: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetColorTableParameterivSGI: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetColorTableParameterfvSGI: procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_SGI_color_table: Boolean;
+
+//***** GL_SGI_texture_color_table *****//
+const
+  GL_TEXTURE_COLOR_TABLE_SGI = $80BC;
+  GL_PROXY_TEXTURE_COLOR_TABLE_SGI = $80BD;
+
+function Load_GL_SGI_texture_color_table: Boolean;
+
+//***** GL_SUN_vertex *****//
+var
+  glColor4ubVertex2fSUN: procedure(r: GLubyte; g: GLubyte; b: GLubyte; a: GLubyte; x: GLfloat; y: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4ubVertex2fvSUN: procedure(const c: PGLubyte; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4ubVertex3fSUN: procedure(r: GLubyte; g: GLubyte; b: GLubyte; a: GLubyte; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4ubVertex3fvSUN: procedure(const c: PGLubyte; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3fVertex3fSUN: procedure(r: GLfloat; g: GLfloat; b: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3fVertex3fvSUN: procedure(const c: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3fVertex3fSUN: procedure(nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3fVertex3fvSUN: procedure(const n: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4fNormal3fVertex3fSUN: procedure(r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4fNormal3fVertex3fvSUN: procedure(const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fVertex3fSUN: procedure(s: GLfloat; t: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fVertex3fvSUN: procedure(const tc: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4fVertex4fSUN: procedure(s: GLfloat; t: GLfloat; p: GLfloat; q: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4fVertex4fvSUN: procedure(const tc: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fColor4ubVertex3fSUN: procedure(s: GLfloat; t: GLfloat; r: GLubyte; g: GLubyte; b: GLubyte; a: GLubyte; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fColor4ubVertex3fvSUN: procedure(const tc: PGLfloat; const c: PGLubyte; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fColor3fVertex3fSUN: procedure(s: GLfloat; t: GLfloat; r: GLfloat; g: GLfloat; b: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fColor3fVertex3fvSUN: procedure(const tc: PGLfloat; const c: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fNormal3fVertex3fSUN: procedure(s: GLfloat; t: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fNormal3fVertex3fvSUN: procedure(const tc: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fColor4fNormal3fVertex3fSUN: procedure(s: GLfloat; t: GLfloat; r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2fColor4fNormal3fVertex3fvSUN: procedure(const tc: PGLfloat; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4fColor4fNormal3fVertex4fSUN: procedure(s: GLfloat; t: GLfloat; p: GLfloat; q: GLfloat; r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4fColor4fNormal3fVertex4fvSUN: procedure(const tc: PGLfloat; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiVertex3fSUN: procedure(rc: GLuint; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiVertex3fvSUN: procedure(const rc: PGLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiColor4ubVertex3fSUN: procedure(rc: GLuint; r: GLubyte; g: GLubyte; b: GLubyte; a: GLubyte; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiColor4ubVertex3fvSUN: procedure(const rc: PGLuint; const c: PGLubyte; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiColor3fVertex3fSUN: procedure(rc: GLuint; r: GLfloat; g: GLfloat; b: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiColor3fVertex3fvSUN: procedure(const rc: PGLuint; const c: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiNormal3fVertex3fSUN: procedure(rc: GLuint; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiNormal3fVertex3fvSUN: procedure(const rc: PGLuint; const n: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiColor4fNormal3fVertex3fSUN: procedure(rc: GLuint; r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiColor4fNormal3fVertex3fvSUN: procedure(const rc: PGLuint; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiTexCoord2fVertex3fSUN: procedure(rc: GLuint; s: GLfloat; t: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiTexCoord2fVertex3fvSUN: procedure(const rc: PGLuint; const tc: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN: procedure(rc: GLuint; s: GLfloat; t: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN: procedure(const rc: PGLuint; const tc: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN: procedure(rc: GLuint; s: GLfloat; t: GLfloat; r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN: procedure(const rc: PGLuint; const tc: PGLfloat; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_SUN_vertex: Boolean;
+
+//***** GL_ARB_fragment_program *****//
+const
+  GL_FRAGMENT_PROGRAM_ARB = $8804;
+  // GL_PROGRAM_FORMAT_ASCII_ARB  { already defined }
+  // GL_PROGRAM_LENGTH_ARB  { already defined }
+  // GL_PROGRAM_FORMAT_ARB  { already defined }
+  // GL_PROGRAM_BINDING_ARB  { already defined }
+  // GL_PROGRAM_INSTRUCTIONS_ARB  { already defined }
+  // GL_MAX_PROGRAM_INSTRUCTIONS_ARB  { already defined }
+  // GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB  { already defined }
+  // GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB  { already defined }
+  // GL_PROGRAM_TEMPORARIES_ARB  { already defined }
+  // GL_MAX_PROGRAM_TEMPORARIES_ARB  { already defined }
+  // GL_PROGRAM_NATIVE_TEMPORARIES_ARB  { already defined }
+  // GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB  { already defined }
+  // GL_PROGRAM_PARAMETERS_ARB  { already defined }
+  // GL_MAX_PROGRAM_PARAMETERS_ARB  { already defined }
+  // GL_PROGRAM_NATIVE_PARAMETERS_ARB  { already defined }
+  // GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB  { already defined }
+  // GL_PROGRAM_ATTRIBS_ARB  { already defined }
+  // GL_MAX_PROGRAM_ATTRIBS_ARB  { already defined }
+  // GL_PROGRAM_NATIVE_ATTRIBS_ARB  { already defined }
+  // GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB  { already defined }
+  // GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB  { already defined }
+  // GL_MAX_PROGRAM_ENV_PARAMETERS_ARB  { already defined }
+  // GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB  { already defined }
+  GL_PROGRAM_ALU_INSTRUCTIONS_ARB = $8805;
+  GL_PROGRAM_TEX_INSTRUCTIONS_ARB = $8806;
+  GL_PROGRAM_TEX_INDIRECTIONS_ARB = $8807;
+  GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB = $8808;
+  GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB = $8809;
+  GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB = $880A;
+  GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB = $880B;
+  GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB = $880C;
+  GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB = $880D;
+  GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB = $880E;
+  GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB = $880F;
+  GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB = $8810;
+  // GL_PROGRAM_STRING_ARB  { already defined }
+  // GL_PROGRAM_ERROR_POSITION_ARB  { already defined }
+  // GL_CURRENT_MATRIX_ARB  { already defined }
+  // GL_TRANSPOSE_CURRENT_MATRIX_ARB  { already defined }
+  // GL_CURRENT_MATRIX_STACK_DEPTH_ARB  { already defined }
+  // GL_MAX_PROGRAM_MATRICES_ARB  { already defined }
+  // GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB  { already defined }
+  GL_MAX_TEXTURE_COORDS_ARB = $8871;
+  GL_MAX_TEXTURE_IMAGE_UNITS_ARB = $8872;
+  // GL_PROGRAM_ERROR_STRING_ARB  { already defined }
+  // GL_MATRIX0_ARB  { already defined }
+  // GL_MATRIX1_ARB  { already defined }
+  // GL_MATRIX2_ARB  { already defined }
+  // GL_MATRIX3_ARB  { already defined }
+  // GL_MATRIX4_ARB  { already defined }
+  // GL_MATRIX5_ARB  { already defined }
+  // GL_MATRIX6_ARB  { already defined }
+  // GL_MATRIX7_ARB  { already defined }
+  // GL_MATRIX8_ARB  { already defined }
+  // GL_MATRIX9_ARB  { already defined }
+  // GL_MATRIX10_ARB  { already defined }
+  // GL_MATRIX11_ARB  { already defined }
+  // GL_MATRIX12_ARB  { already defined }
+  // GL_MATRIX13_ARB  { already defined }
+  // GL_MATRIX14_ARB  { already defined }
+  // GL_MATRIX15_ARB  { already defined }
+  // GL_MATRIX16_ARB  { already defined }
+  // GL_MATRIX17_ARB  { already defined }
+  // GL_MATRIX18_ARB  { already defined }
+  // GL_MATRIX19_ARB  { already defined }
+  // GL_MATRIX20_ARB  { already defined }
+  // GL_MATRIX21_ARB  { already defined }
+  // GL_MATRIX22_ARB  { already defined }
+  // GL_MATRIX23_ARB  { already defined }
+  // GL_MATRIX24_ARB  { already defined }
+  // GL_MATRIX25_ARB  { already defined }
+  // GL_MATRIX26_ARB  { already defined }
+  // GL_MATRIX27_ARB  { already defined }
+  // GL_MATRIX28_ARB  { already defined }
+  // GL_MATRIX29_ARB  { already defined }
+  // GL_MATRIX30_ARB  { already defined }
+  // GL_MATRIX31_ARB  { already defined }
+  // glProgramStringARB  { already defined }
+  // glBindProgramARB  { already defined }
+  // glDeleteProgramsARB  { already defined }
+  // glGenProgramsARB  { already defined }
+  // glProgramEnvParameter4dARB  { already defined }
+  // glProgramEnvParameter4dvARB  { already defined }
+  // glProgramEnvParameter4fARB  { already defined }
+  // glProgramEnvParameter4fvARB  { already defined }
+  // glProgramLocalParameter4dARB  { already defined }
+  // glProgramLocalParameter4dvARB  { already defined }
+  // glProgramLocalParameter4fARB  { already defined }
+  // glProgramLocalParameter4fvARB  { already defined }
+  // glGetProgramEnvParameterdvARB  { already defined }
+  // glGetProgramEnvParameterfvARB  { already defined }
+  // glGetProgramLocalParameterdvARB  { already defined }
+  // glGetProgramLocalParameterfvARB  { already defined }
+  // glGetProgramivARB  { already defined }
+  // glGetProgramStringARB  { already defined }
+  // glIsProgramARB  { already defined }
+
+function Load_GL_ARB_fragment_program: Boolean;
+
+//***** GL_ATI_text_fragment_shader *****//
+const
+  GL_TEXT_FRAGMENT_SHADER_ATI = $8200;
+
+function Load_GL_ATI_text_fragment_shader: Boolean;
+
+//***** GL_APPLE_client_storage *****//
+const
+  GL_UNPACK_CLIENT_STORAGE_APPLE = $85B2;
+
+function Load_GL_APPLE_client_storage: Boolean;
+
+//***** GL_APPLE_element_array *****//
+const
+  GL_ELEMENT_ARRAY_APPLE = $8768;
+  GL_ELEMENT_ARRAY_TYPE_APPLE = $8769;
+  GL_ELEMENT_ARRAY_POINTER_APPLE = $876A;
+var
+  glElementPointerAPPLE: procedure(_type: GLenum; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawElementArrayAPPLE: procedure(mode: GLenum; first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawRangeElementArrayAPPLE: procedure(mode: GLenum; start: GLuint; _end: GLuint; first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiDrawElementArrayAPPLE: procedure(mode: GLenum; const first: PGLint; const count: PGLsizei; primcount: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiDrawRangeElementArrayAPPLE: procedure(mode: GLenum; start: GLuint; _end: GLuint; const first: PGLint; const count: PGLsizei; primcount: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_APPLE_element_array: Boolean;
+
+//***** GL_APPLE_fence *****//
+const
+  GL_DRAW_PIXELS_APPLE = $8A0A;
+  GL_FENCE_APPLE = $8A0B;
+var
+  glGenFencesAPPLE: procedure(n: GLsizei; fences: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteFencesAPPLE: procedure(n: GLsizei; const fences: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSetFenceAPPLE: procedure(fence: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsFenceAPPLE: function(fence: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTestFenceAPPLE: function(fence: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFinishFenceAPPLE: procedure(fence: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTestObjectAPPLE: function(_object: GLenum; name: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFinishObjectAPPLE: procedure(_object: GLenum; name: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_APPLE_fence: Boolean;
+
+//***** GL_APPLE_vertex_array_object *****//
+const
+  GL_VERTEX_ARRAY_BINDING_APPLE = $85B5;
+var
+  glBindVertexArrayAPPLE: procedure(_array: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteVertexArraysAPPLE: procedure(n: GLsizei; const arrays: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenVertexArraysAPPLE: procedure(n: GLsizei; const arrays: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsVertexArrayAPPLE: function(_array: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_APPLE_vertex_array_object: Boolean;
+
+//***** GL_APPLE_vertex_array_range *****//
+const
+  GL_VERTEX_ARRAY_RANGE_APPLE = $851D;
+  GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE = $851E;
+  GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE = $8520;
+  GL_VERTEX_ARRAY_RANGE_POINTER_APPLE = $8521;
+  GL_VERTEX_ARRAY_STORAGE_HINT_APPLE = $851F;
+  GL_STORAGE_CACHED_APPLE = $85BE;
+  GL_STORAGE_SHARED_APPLE = $85BF;
+var
+  glVertexArrayRangeAPPLE: procedure(length: GLsizei; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFlushVertexArrayRangeAPPLE: procedure(length: GLsizei; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexArrayParameteriAPPLE: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_APPLE_vertex_array_range: Boolean;
+
+{$IFDEF WINDOWS}
+//***** WGL_ARB_pixel_format *****//
+const
+  WGL_NUMBER_PIXEL_FORMATS_ARB = $2000;
+  WGL_DRAW_TO_WINDOW_ARB = $2001;
+  WGL_DRAW_TO_BITMAP_ARB = $2002;
+  WGL_ACCELERATION_ARB = $2003;
+  WGL_NEED_PALETTE_ARB = $2004;
+  WGL_NEED_SYSTEM_PALETTE_ARB = $2005;
+  WGL_SWAP_LAYER_BUFFERS_ARB = $2006;
+  WGL_SWAP_METHOD_ARB = $2007;
+  WGL_NUMBER_OVERLAYS_ARB = $2008;
+  WGL_NUMBER_UNDERLAYS_ARB = $2009;
+  WGL_TRANSPARENT_ARB = $200A;
+  WGL_TRANSPARENT_RED_VALUE_ARB = $2037;
+  WGL_TRANSPARENT_GREEN_VALUE_ARB = $2038;
+  WGL_TRANSPARENT_BLUE_VALUE_ARB = $2039;
+  WGL_TRANSPARENT_ALPHA_VALUE_ARB = $203A;
+  WGL_TRANSPARENT_INDEX_VALUE_ARB = $203B;
+  WGL_SHARE_DEPTH_ARB = $200C;
+  WGL_SHARE_STENCIL_ARB = $200D;
+  WGL_SHARE_ACCUM_ARB = $200E;
+  WGL_SUPPORT_GDI_ARB = $200F;
+  WGL_SUPPORT_OPENGL_ARB = $2010;
+  WGL_DOUBLE_BUFFER_ARB = $2011;
+  WGL_STEREO_ARB = $2012;
+  WGL_PIXEL_TYPE_ARB = $2013;
+  WGL_COLOR_BITS_ARB = $2014;
+  WGL_RED_BITS_ARB = $2015;
+  WGL_RED_SHIFT_ARB = $2016;
+  WGL_GREEN_BITS_ARB = $2017;
+  WGL_GREEN_SHIFT_ARB = $2018;
+  WGL_BLUE_BITS_ARB = $2019;
+  WGL_BLUE_SHIFT_ARB = $201A;
+  WGL_ALPHA_BITS_ARB = $201B;
+  WGL_ALPHA_SHIFT_ARB = $201C;
+  WGL_ACCUM_BITS_ARB = $201D;
+  WGL_ACCUM_RED_BITS_ARB = $201E;
+  WGL_ACCUM_GREEN_BITS_ARB = $201F;
+  WGL_ACCUM_BLUE_BITS_ARB = $2020;
+  WGL_ACCUM_ALPHA_BITS_ARB = $2021;
+  WGL_DEPTH_BITS_ARB = $2022;
+  WGL_STENCIL_BITS_ARB = $2023;
+  WGL_AUX_BUFFERS_ARB = $2024;
+  WGL_NO_ACCELERATION_ARB = $2025;
+  WGL_GENERIC_ACCELERATION_ARB = $2026;
+  WGL_FULL_ACCELERATION_ARB = $2027;
+  WGL_SWAP_EXCHANGE_ARB = $2028;
+  WGL_SWAP_COPY_ARB = $2029;
+  WGL_SWAP_UNDEFINED_ARB = $202A;
+  WGL_TYPE_RGBA_ARB = $202B;
+  WGL_TYPE_COLORINDEX_ARB = $202C;
+var
+  wglGetPixelFormatAttribivARB: function(hdc: HDC; iPixelFormat: GLint; iLayerPlane: GLint; nAttributes: GLuint; const piAttributes: PGLint; piValues: PGLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetPixelFormatAttribfvARB: function(hdc: HDC; iPixelFormat: GLint; iLayerPlane: GLint; nAttributes: GLuint; const piAttributes: PGLint; pfValues: PGLfloat): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglChoosePixelFormatARB: function(hdc: HDC; const piAttribIList: PGLint; const pfAttribFList: PGLfloat; nMaxFormats: GLuint; piFormats: PGLint; nNumFormats: PGLuint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_ARB_pixel_format: Boolean;
+
+//***** WGL_ARB_make_current_read *****//
+const
+  WGL_ERROR_INVALID_PIXEL_TYPE_ARB = $2043;
+  WGL_ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB = $2054;
+var
+  wglMakeContextCurrentARB: function(hDrawDC: HDC; hReadDC: HDC; hglrc: HGLRC): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetCurrentReadDCARB: function(): HDC; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_ARB_make_current_read: Boolean;
+
+//***** WGL_ARB_pbuffer *****//
+const
+  WGL_DRAW_TO_PBUFFER_ARB = $202D;
+  // WGL_DRAW_TO_PBUFFER_ARB  { already defined }
+  WGL_MAX_PBUFFER_PIXELS_ARB = $202E;
+  WGL_MAX_PBUFFER_WIDTH_ARB = $202F;
+  WGL_MAX_PBUFFER_HEIGHT_ARB = $2030;
+  WGL_PBUFFER_LARGEST_ARB = $2033;
+  WGL_PBUFFER_WIDTH_ARB = $2034;
+  WGL_PBUFFER_HEIGHT_ARB = $2035;
+  WGL_PBUFFER_LOST_ARB = $2036;
+var
+  wglCreatePbufferARB: function(hDC: HDC; iPixelFormat: GLint; iWidth: GLint; iHeight: GLint; const piAttribList: PGLint): THandle; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetPbufferDCARB: function(hPbuffer: THandle): HDC; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglReleasePbufferDCARB: function(hPbuffer: THandle; hDC: HDC): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglDestroyPbufferARB: function(hPbuffer: THandle): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglQueryPbufferARB: function(hPbuffer: THandle; iAttribute: GLint; piValue: PGLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_ARB_pbuffer: Boolean;
+
+//***** WGL_EXT_swap_control *****//
+var
+  wglSwapIntervalEXT: function(interval: GLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetSwapIntervalEXT: function(): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_EXT_swap_control: Boolean;
+
+//***** WGL_ARB_render_texture *****//
+const
+  WGL_BIND_TO_TEXTURE_RGB_ARB = $2070;
+  WGL_BIND_TO_TEXTURE_RGBA_ARB = $2071;
+  WGL_TEXTURE_FORMAT_ARB = $2072;
+  WGL_TEXTURE_TARGET_ARB = $2073;
+  WGL_MIPMAP_TEXTURE_ARB = $2074;
+  WGL_TEXTURE_RGB_ARB = $2075;
+  WGL_TEXTURE_RGBA_ARB = $2076;
+  WGL_NO_TEXTURE_ARB = $2077;
+  WGL_TEXTURE_CUBE_MAP_ARB = $2078;
+  WGL_TEXTURE_1D_ARB = $2079;
+  WGL_TEXTURE_2D_ARB = $207A;
+  // WGL_NO_TEXTURE_ARB  { already defined }
+  WGL_MIPMAP_LEVEL_ARB = $207B;
+  WGL_CUBE_MAP_FACE_ARB = $207C;
+  WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB = $207D;
+  WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB = $207E;
+  WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB = $207F;
+  WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB = $2080;
+  WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB = $2081;
+  WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB = $2082;
+  WGL_FRONT_LEFT_ARB = $2083;
+  WGL_FRONT_RIGHT_ARB = $2084;
+  WGL_BACK_LEFT_ARB = $2085;
+  WGL_BACK_RIGHT_ARB = $2086;
+  WGL_AUX0_ARB = $2087;
+  WGL_AUX1_ARB = $2088;
+  WGL_AUX2_ARB = $2089;
+  WGL_AUX3_ARB = $208A;
+  WGL_AUX4_ARB = $208B;
+  WGL_AUX5_ARB = $208C;
+  WGL_AUX6_ARB = $208D;
+  WGL_AUX7_ARB = $208E;
+  WGL_AUX8_ARB = $208F;
+  WGL_AUX9_ARB = $2090;
+var
+  wglBindTexImageARB: function(hPbuffer: THandle; iBuffer: GLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglReleaseTexImageARB: function(hPbuffer: THandle; iBuffer: GLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglSetPbufferAttribARB: function(hPbuffer: THandle; const piAttribList: PGLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_ARB_render_texture: Boolean;
+
+//***** WGL_EXT_extensions_string *****//
+var
+  wglGetExtensionsStringEXT: function(): Pchar; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_EXT_extensions_string: Boolean;
+
+//***** WGL_EXT_make_current_read *****//
+var
+  wglMakeContextCurrentEXT: function(hDrawDC: HDC; hReadDC: HDC; hglrc: HGLRC): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetCurrentReadDCEXT: function(): HDC; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_EXT_make_current_read: Boolean;
+
+//***** WGL_EXT_pbuffer *****//
+const
+  WGL_DRAW_TO_PBUFFER_EXT = $202D;
+  WGL_MAX_PBUFFER_PIXELS_EXT = $202E;
+  WGL_MAX_PBUFFER_WIDTH_EXT = $202F;
+  WGL_MAX_PBUFFER_HEIGHT_EXT = $2030;
+  WGL_OPTIMAL_PBUFFER_WIDTH_EXT = $2031;
+  WGL_OPTIMAL_PBUFFER_HEIGHT_EXT = $2032;
+  WGL_PBUFFER_LARGEST_EXT = $2033;
+  WGL_PBUFFER_WIDTH_EXT = $2034;
+  WGL_PBUFFER_HEIGHT_EXT = $2035;
+var
+  wglCreatePbufferEXT: function(hDC: HDC; iPixelFormat: GLint; iWidth: GLint; iHeight: GLint; const piAttribList: PGLint): THandle; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetPbufferDCEXT: function(hPbuffer: THandle): HDC; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglReleasePbufferDCEXT: function(hPbuffer: THandle; hDC: HDC): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglDestroyPbufferEXT: function(hPbuffer: THandle): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglQueryPbufferEXT: function(hPbuffer: THandle; iAttribute: GLint; piValue: PGLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_EXT_pbuffer: Boolean;
+
+//***** WGL_EXT_pixel_format *****//
+const
+  WGL_NUMBER_PIXEL_FORMATS_EXT = $2000;
+  WGL_DRAW_TO_WINDOW_EXT = $2001;
+  WGL_DRAW_TO_BITMAP_EXT = $2002;
+  WGL_ACCELERATION_EXT = $2003;
+  WGL_NEED_PALETTE_EXT = $2004;
+  WGL_NEED_SYSTEM_PALETTE_EXT = $2005;
+  WGL_SWAP_LAYER_BUFFERS_EXT = $2006;
+  WGL_SWAP_METHOD_EXT = $2007;
+  WGL_NUMBER_OVERLAYS_EXT = $2008;
+  WGL_NUMBER_UNDERLAYS_EXT = $2009;
+  WGL_TRANSPARENT_EXT = $200A;
+  WGL_TRANSPARENT_VALUE_EXT = $200B;
+  WGL_SHARE_DEPTH_EXT = $200C;
+  WGL_SHARE_STENCIL_EXT = $200D;
+  WGL_SHARE_ACCUM_EXT = $200E;
+  WGL_SUPPORT_GDI_EXT = $200F;
+  WGL_SUPPORT_OPENGL_EXT = $2010;
+  WGL_DOUBLE_BUFFER_EXT = $2011;
+  WGL_STEREO_EXT = $2012;
+  WGL_PIXEL_TYPE_EXT = $2013;
+  WGL_COLOR_BITS_EXT = $2014;
+  WGL_RED_BITS_EXT = $2015;
+  WGL_RED_SHIFT_EXT = $2016;
+  WGL_GREEN_BITS_EXT = $2017;
+  WGL_GREEN_SHIFT_EXT = $2018;
+  WGL_BLUE_BITS_EXT = $2019;
+  WGL_BLUE_SHIFT_EXT = $201A;
+  WGL_ALPHA_BITS_EXT = $201B;
+  WGL_ALPHA_SHIFT_EXT = $201C;
+  WGL_ACCUM_BITS_EXT = $201D;
+  WGL_ACCUM_RED_BITS_EXT = $201E;
+  WGL_ACCUM_GREEN_BITS_EXT = $201F;
+  WGL_ACCUM_BLUE_BITS_EXT = $2020;
+  WGL_ACCUM_ALPHA_BITS_EXT = $2021;
+  WGL_DEPTH_BITS_EXT = $2022;
+  WGL_STENCIL_BITS_EXT = $2023;
+  WGL_AUX_BUFFERS_EXT = $2024;
+  WGL_NO_ACCELERATION_EXT = $2025;
+  WGL_GENERIC_ACCELERATION_EXT = $2026;
+  WGL_FULL_ACCELERATION_EXT = $2027;
+  WGL_SWAP_EXCHANGE_EXT = $2028;
+  WGL_SWAP_COPY_EXT = $2029;
+  WGL_SWAP_UNDEFINED_EXT = $202A;
+  WGL_TYPE_RGBA_EXT = $202B;
+  WGL_TYPE_COLORINDEX_EXT = $202C;
+var
+  wglGetPixelFormatAttribivEXT: function(hdc: HDC; iPixelFormat: GLint; iLayerPlane: GLint; nAttributes: GLuint; piAttributes: PGLint; piValues: PGLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetPixelFormatAttribfvEXT: function(hdc: HDC; iPixelFormat: GLint; iLayerPlane: GLint; nAttributes: GLuint; piAttributes: PGLint; pfValues: PGLfloat): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglChoosePixelFormatEXT: function(hdc: HDC; const piAttribIList: PGLint; const pfAttribFList: PGLfloat; nMaxFormats: GLuint; piFormats: PGLint; nNumFormats: PGLuint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_EXT_pixel_format: Boolean;
+
+//***** WGL_I3D_digital_video_control *****//
+const
+  WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D = $2050;
+  WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D = $2051;
+  WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D = $2052;
+  WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D = $2053;
+var
+  wglGetDigitalVideoParametersI3D: function(hDC: HDC; iAttribute: GLint; piValue: PGLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglSetDigitalVideoParametersI3D: function(hDC: HDC; iAttribute: GLint; const piValue: PGLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_I3D_digital_video_control: Boolean;
+
+//***** WGL_I3D_gamma *****//
+const
+  WGL_GAMMA_TABLE_SIZE_I3D = $204E;
+  WGL_GAMMA_EXCLUDE_DESKTOP_I3D = $204F;
+  // WGL_GAMMA_EXCLUDE_DESKTOP_I3D  { already defined }
+var
+  wglGetGammaTableParametersI3D: function(hDC: HDC; iAttribute: GLint; piValue: PGLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglSetGammaTableParametersI3D: function(hDC: HDC; iAttribute: GLint; const piValue: PGLint): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetGammaTableI3D: function(hDC: HDC; iEntries: GLint; puRed: PGLUSHORT; puGreen: PGLUSHORT; puBlue: PGLUSHORT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglSetGammaTableI3D: function(hDC: HDC; iEntries: GLint; const puRed: PGLUSHORT; const puGreen: PGLUSHORT; const puBlue: PGLUSHORT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_I3D_gamma: Boolean;
+
+//***** WGL_I3D_genlock *****//
+const
+  WGL_GENLOCK_SOURCE_MULTIVIEW_I3D = $2044;
+  WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D = $2045;
+  WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D = $2046;
+  WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D = $2047;
+  WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D = $2048;
+  WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D = $2049;
+  WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D = $204A;
+  WGL_GENLOCK_SOURCE_EDGE_RISING_I3D = $204B;
+  WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D = $204C;
+var
+  wglEnableGenlockI3D: function(hDC: HDC): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglDisableGenlockI3D: function(hDC: HDC): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglIsEnabledGenlockI3D: function(hDC: HDC; pFlag: PBOOL): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGenlockSourceI3D: function(hDC: HDC; uSource: GLUINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetGenlockSourceI3D: function(hDC: HDC; uSource: PGLUINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGenlockSourceEdgeI3D: function(hDC: HDC; uEdge: GLUINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetGenlockSourceEdgeI3D: function(hDC: HDC; uEdge: PGLUINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGenlockSampleRateI3D: function(hDC: HDC; uRate: GLUINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetGenlockSampleRateI3D: function(hDC: HDC; uRate: PGLUINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGenlockSourceDelayI3D: function(hDC: HDC; uDelay: GLUINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglGetGenlockSourceDelayI3D: function(hDC: HDC; uDelay: PGLUINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  wglQueryGenlockMaxSourceDelayI3D: function(hDC: HDC; uMaxLineDelay: PGLUINT; uMaxPixelDelay: PGLUINT): BOOL; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_WGL_I3D_genlock: Boolean;
+{$ENDIF}
+
+//***** GL_ARB_matrix_palette *****//
+const
+  GL_MATRIX_PALETTE_ARB = $8840;
+  GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB = $8841;
+  GL_MAX_PALETTE_MATRICES_ARB = $8842;
+  GL_CURRENT_PALETTE_MATRIX_ARB = $8843;
+  GL_MATRIX_INDEX_ARRAY_ARB = $8844;
+  GL_CURRENT_MATRIX_INDEX_ARB = $8845;
+  GL_MATRIX_INDEX_ARRAY_SIZE_ARB = $8846;
+  GL_MATRIX_INDEX_ARRAY_TYPE_ARB = $8847;
+  GL_MATRIX_INDEX_ARRAY_STRIDE_ARB = $8848;
+  GL_MATRIX_INDEX_ARRAY_POINTER_ARB = $8849;
+var
+  glCurrentPaletteMatrixARB: procedure(index: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMatrixIndexubvARB: procedure(size: GLint; indices: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMatrixIndexusvARB: procedure(size: GLint; indices: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMatrixIndexuivARB: procedure(size: GLint; indices: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMatrixIndexPointerARB: procedure(size: GLint; _type: GLenum; stride: GLsizei; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_matrix_palette: Boolean;
+
+//***** GL_NV_element_array *****//
+const
+  GL_ELEMENT_ARRAY_TYPE_NV = $8769;
+  GL_ELEMENT_ARRAY_POINTER_NV = $876A;
+var
+  glElementPointerNV: procedure(_type: GLenum; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawElementArrayNV: procedure(mode: GLenum; first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawRangeElementArrayNV: procedure(mode: GLenum; start: GLuint; _end: GLuint; first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiDrawElementArrayNV: procedure(mode: GLenum; const first: PGLint; const count: PGLsizei; primcount: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiDrawRangeElementArrayNV: procedure(mode: GLenum; start: GLuint; _end: GLuint; const first: PGLint; const count: PGLsizei; primcount: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_element_array: Boolean;
+
+//***** GL_NV_float_buffer *****//
+const
+  GL_FLOAT_R_NV = $8880;
+  GL_FLOAT_RG_NV = $8881;
+  GL_FLOAT_RGB_NV = $8882;
+  GL_FLOAT_RGBA_NV = $8883;
+  GL_FLOAT_R16_NV = $8884;
+  GL_FLOAT_R32_NV = $8885;
+  GL_FLOAT_RG16_NV = $8886;
+  GL_FLOAT_RG32_NV = $8887;
+  GL_FLOAT_RGB16_NV = $8888;
+  GL_FLOAT_RGB32_NV = $8889;
+  GL_FLOAT_RGBA16_NV = $888A;
+  GL_FLOAT_RGBA32_NV = $888B;
+  GL_TEXTURE_FLOAT_COMPONENTS_NV = $888C;
+  GL_FLOAT_CLEAR_COLOR_VALUE_NV = $888D;
+  GL_FLOAT_RGBA_MODE_NV = $888E;
+{$IFDEF WINDOWS}
+  WGL_FLOAT_COMPONENTS_NV = $20B0;
+  WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV = $20B1;
+  WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV = $20B2;
+  WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV = $20B3;
+  WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV = $20B4;
+  WGL_TEXTURE_FLOAT_R_NV = $20B5;
+  WGL_TEXTURE_FLOAT_RG_NV = $20B6;
+  WGL_TEXTURE_FLOAT_RGB_NV = $20B7;
+  WGL_TEXTURE_FLOAT_RGBA_NV = $20B8;
+{$ENDIF}
+
+function Load_GL_NV_float_buffer: Boolean;
+
+//***** GL_NV_fragment_program *****//
+const
+  GL_FRAGMENT_PROGRAM_NV = $8870;
+  GL_MAX_TEXTURE_COORDS_NV = $8871;
+  GL_MAX_TEXTURE_IMAGE_UNITS_NV = $8872;
+  GL_FRAGMENT_PROGRAM_BINDING_NV = $8873;
+  GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV = $8868;
+  GL_PROGRAM_ERROR_STRING_NV = $8874;
+var
+  glProgramNamedParameter4fNV: procedure(id: GLuint; len: GLsizei; const name: PGLubyte; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glProgramNamedParameter4dNV: procedure(id: GLuint; len: GLsizei; const name: PGLubyte; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramNamedParameterfvNV: procedure(id: GLuint; len: GLsizei; const name: PGLubyte; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramNamedParameterdvNV: procedure(id: GLuint; len: GLsizei; const name: PGLubyte; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  // glProgramLocalParameter4dARB  { already defined }
+  // glProgramLocalParameter4dvARB  { already defined }
+  // glProgramLocalParameter4fARB  { already defined }
+  // glProgramLocalParameter4fvARB  { already defined }
+  // glGetProgramLocalParameterdvARB  { already defined }
+  // glGetProgramLocalParameterfvARB  { already defined }
+
+function Load_GL_NV_fragment_program: Boolean;
+
+//***** GL_NV_primitive_restart *****//
+const
+  GL_PRIMITIVE_RESTART_NV = $8558;
+  GL_PRIMITIVE_RESTART_INDEX_NV = $8559;
+var
+  glPrimitiveRestartNV: procedure(); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPrimitiveRestartIndexNV: procedure(index: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_primitive_restart: Boolean;
+
+//***** GL_NV_vertex_program2 *****//
+
+function Load_GL_NV_vertex_program2: Boolean;
+
+{$IFDEF WINDOWS}
+//***** WGL_NV_render_texture_rectangle *****//
+const
+  WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV = $20A0;
+  WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV = $20A1;
+  WGL_TEXTURE_RECTANGLE_NV = $20A2;
+
+function Load_WGL_NV_render_texture_rectangle: Boolean;
+{$ENDIF}
+
+//***** GL_NV_pixel_data_range *****//
+const
+  GL_WRITE_PIXEL_DATA_RANGE_NV = $8878;
+  GL_READ_PIXEL_DATA_RANGE_NV = $8879;
+  GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV = $887A;
+  GL_READ_PIXEL_DATA_RANGE_LENGTH_NV = $887B;
+  GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV = $887C;
+  GL_READ_PIXEL_DATA_RANGE_POINTER_NV = $887D;
+var
+  glPixelDataRangeNV: procedure(target: GLenum; length: GLsizei; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFlushPixelDataRangeNV: procedure(target: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  // wglAllocateMemoryNV  { already defined }
+  // wglFreeMemoryNV  { already defined }
+
+function Load_GL_NV_pixel_data_range: Boolean;
+
+//***** GL_EXT_texture_rectangle *****//
+const
+  GL_TEXTURE_RECTANGLE_EXT = $84F5;
+  GL_TEXTURE_BINDING_RECTANGLE_EXT = $84F6;
+  GL_PROXY_TEXTURE_RECTANGLE_EXT = $84F7;
+  GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT = $84F8;
+
+function Load_GL_EXT_texture_rectangle: Boolean;
+
+//***** GL_S3_s3tc *****//
+const
+  GL_RGB_S3TC = $83A0;
+  GL_RGB4_S3TC = $83A1;
+  GL_RGBA_S3TC = $83A2;
+  GL_RGBA4_S3TC = $83A3;
+
+function Load_GL_S3_s3tc: Boolean;
+
+//***** GL_ATI_draw_buffers *****//
+const
+  GL_MAX_DRAW_BUFFERS_ATI = $8824;
+  GL_DRAW_BUFFER0_ATI = $8825;
+  GL_DRAW_BUFFER1_ATI = $8826;
+  GL_DRAW_BUFFER2_ATI = $8827;
+  GL_DRAW_BUFFER3_ATI = $8828;
+  GL_DRAW_BUFFER4_ATI = $8829;
+  GL_DRAW_BUFFER5_ATI = $882A;
+  GL_DRAW_BUFFER6_ATI = $882B;
+  GL_DRAW_BUFFER7_ATI = $882C;
+  GL_DRAW_BUFFER8_ATI = $882D;
+  GL_DRAW_BUFFER9_ATI = $882E;
+  GL_DRAW_BUFFER10_ATI = $882F;
+  GL_DRAW_BUFFER11_ATI = $8830;
+  GL_DRAW_BUFFER12_ATI = $8831;
+  GL_DRAW_BUFFER13_ATI = $8832;
+  GL_DRAW_BUFFER14_ATI = $8833;
+  GL_DRAW_BUFFER15_ATI = $8834;
+var
+  glDrawBuffersATI: procedure(n: GLsizei; const bufs: PGLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_draw_buffers: Boolean;
+
+{$IFDEF WINDOWS}
+//***** WGL_ATI_pixel_format_float *****//
+const
+  WGL_RGBA_FLOAT_MODE_ATI = $8820;
+  WGL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI = $8835;
+  WGL_TYPE_RGBA_FLOAT_ATI = $21A0;
+
+function Load_WGL_ATI_pixel_format_float: Boolean;
+{$ENDIF}
+
+//***** GL_ATI_texture_env_combine3 *****//
+const
+  GL_MODULATE_ADD_ATI = $8744;
+  GL_MODULATE_SIGNED_ADD_ATI = $8745;
+  GL_MODULATE_SUBTRACT_ATI = $8746;
+
+function Load_GL_ATI_texture_env_combine3: Boolean;
+
+//***** GL_ATI_texture_float *****//
+const
+  GL_RGBA_FLOAT32_ATI = $8814;
+  GL_RGB_FLOAT32_ATI = $8815;
+  GL_ALPHA_FLOAT32_ATI = $8816;
+  GL_INTENSITY_FLOAT32_ATI = $8817;
+  GL_LUMINANCE_FLOAT32_ATI = $8818;
+  GL_LUMINANCE_ALPHA_FLOAT32_ATI = $8819;
+  GL_RGBA_FLOAT16_ATI = $881A;
+  GL_RGB_FLOAT16_ATI = $881B;
+  GL_ALPHA_FLOAT16_ATI = $881C;
+  GL_INTENSITY_FLOAT16_ATI = $881D;
+  GL_LUMINANCE_FLOAT16_ATI = $881E;
+  GL_LUMINANCE_ALPHA_FLOAT16_ATI = $881F;
+
+function Load_GL_ATI_texture_float: Boolean;
+
+//***** GL_NV_texture_expand_normal *****//
+const
+  GL_TEXTURE_UNSIGNED_REMAP_MODE_NV = $888F;
+
+function Load_GL_NV_texture_expand_normal: Boolean;
+
+//***** GL_NV_half_float *****//
+const
+  GL_HALF_FLOAT_NV = $140B;
+var
+  glVertex2hNV: procedure(x: GLushort; y: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex2hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3hNV: procedure(x: GLushort; y: GLushort; z: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex3hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4hNV: procedure(x: GLushort; y: GLushort; z: GLushort; w: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertex4hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3hNV: procedure(nx: GLushort; ny: GLushort; nz: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3hNV: procedure(red: GLushort; green: GLushort; blue: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor3hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4hNV: procedure(red: GLushort; green: GLushort; blue: GLushort; alpha: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColor4hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1hNV: procedure(s: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord1hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2hNV: procedure(s: GLushort; t: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord2hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3hNV: procedure(s: GLushort; t: GLushort; r: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord3hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4hNV: procedure(s: GLushort; t: GLushort; r: GLushort; q: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexCoord4hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1hNV: procedure(target: GLenum; s: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord1hvNV: procedure(target: GLenum; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2hNV: procedure(target: GLenum; s: GLushort; t: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord2hvNV: procedure(target: GLenum; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3hNV: procedure(target: GLenum; s: GLushort; t: GLushort; r: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord3hvNV: procedure(target: GLenum; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4hNV: procedure(target: GLenum; s: GLushort; t: GLushort; r: GLushort; q: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiTexCoord4hvNV: procedure(target: GLenum; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoordhNV: procedure(fog: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoordhvNV: procedure(const fog: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3hNV: procedure(red: GLushort; green: GLushort; blue: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3hvNV: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexWeighthNV: procedure(weight: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexWeighthvNV: procedure(const weight: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1hNV: procedure(index: GLuint; x: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1hvNV: procedure(index: GLuint; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2hNV: procedure(index: GLuint; x: GLushort; y: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2hvNV: procedure(index: GLuint; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3hNV: procedure(index: GLuint; x: GLushort; y: GLushort; z: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3hvNV: procedure(index: GLuint; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4hNV: procedure(index: GLuint; x: GLushort; y: GLushort; z: GLushort; w: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4hvNV: procedure(index: GLuint; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs1hvNV: procedure(index: GLuint; n: GLsizei; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs2hvNV: procedure(index: GLuint; n: GLsizei; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs3hvNV: procedure(index: GLuint; n: GLsizei; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribs4hvNV: procedure(index: GLuint; n: GLsizei; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_NV_half_float: Boolean;
+
+//***** GL_ATI_map_object_buffer *****//
+var
+  glMapObjectBufferATI: function(buffer: GLuint): PGLvoid; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUnmapObjectBufferATI: procedure(buffer: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_map_object_buffer: Boolean;
+
+//***** GL_ATI_separate_stencil *****//
+const
+  GL_KEEP = $1E00;
+  GL_ZERO = $0000;
+  GL_REPLACE = $1E01;
+  GL_INCR = $1E02;
+  GL_DECR = $1E03;
+  GL_INVERT = $150A;
+  GL_NEVER = $0200;
+  GL_LESS = $0201;
+  GL_LEQUAL = $0203;
+  GL_GREATER = $0204;
+  GL_GEQUAL = $0206;
+  GL_EQUAL = $0202;
+  GL_NOTEQUAL = $0205;
+  GL_ALWAYS = $0207;
+  GL_FRONT = $0404;
+  GL_BACK = $0405;
+  GL_FRONT_AND_BACK = $0408;
+  GL_STENCIL_BACK_FUNC_ATI = $8800;
+  GL_STENCIL_BACK_FAIL_ATI = $8801;
+  GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI = $8802;
+  GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI = $8803;
+var
+  glStencilOpSeparateATI: procedure(face: GLenum; sfail: GLenum; dpfail: GLenum; dppass: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilFuncSeparateATI: procedure(frontfunc: GLenum; backfunc: GLenum; ref: GLint; mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_separate_stencil: Boolean;
+
+//***** GL_ATI_vertex_attrib_array_object *****//
+var
+  glVertexAttribArrayObjectATI: procedure(index: GLuint; size: GLint; _type: GLenum; normalized: GLboolean; stride: GLsizei; buffer: GLuint; offset: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribArrayObjectfvATI: procedure(index: GLuint; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribArrayObjectivATI: procedure(index: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ATI_vertex_attrib_array_object: Boolean;
+
+//***** GL_ARB_vertex_buffer_object *****//
+const
+  GL_ARRAY_BUFFER_ARB = $8892;
+  GL_ELEMENT_ARRAY_BUFFER_ARB = $8893;
+  GL_ARRAY_BUFFER_BINDING_ARB = $8894;
+  GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB = $8895;
+  GL_VERTEX_ARRAY_BUFFER_BINDING_ARB = $8896;
+  GL_NORMAL_ARRAY_BUFFER_BINDING_ARB = $8897;
+  GL_COLOR_ARRAY_BUFFER_BINDING_ARB = $8898;
+  GL_INDEX_ARRAY_BUFFER_BINDING_ARB = $8899;
+  GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB = $889A;
+  GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB = $889B;
+  GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB = $889C;
+  GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB = $889D;
+  GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB = $889E;
+  GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB = $889F;
+  GL_STREAM_DRAW_ARB = $88E0;
+  GL_STREAM_READ_ARB = $88E1;
+  GL_STREAM_COPY_ARB = $88E2;
+  GL_STATIC_DRAW_ARB = $88E4;
+  GL_STATIC_READ_ARB = $88E5;
+  GL_STATIC_COPY_ARB = $88E6;
+  GL_DYNAMIC_DRAW_ARB = $88E8;
+  GL_DYNAMIC_READ_ARB = $88E9;
+  GL_DYNAMIC_COPY_ARB = $88EA;
+  GL_READ_ONLY_ARB = $88B8;
+  GL_WRITE_ONLY_ARB = $88B9;
+  GL_READ_WRITE_ARB = $88BA;
+  GL_BUFFER_SIZE_ARB = $8764;
+  GL_BUFFER_USAGE_ARB = $8765;
+  GL_BUFFER_ACCESS_ARB = $88BB;
+  GL_BUFFER_MAPPED_ARB = $88BC;
+  GL_BUFFER_MAP_POINTER_ARB = $88BD;
+var
+  glBindBufferARB: procedure(target: GLenum; buffer: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteBuffersARB: procedure(n: GLsizei; const buffers: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenBuffersARB: procedure(n: GLsizei; buffers: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsBufferARB: function(buffer: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBufferDataARB: procedure(target: GLenum; size: GLsizeiptrARB; const data: PGLvoid; usage: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBufferSubDataARB: procedure(target: GLenum; offset: GLintptrARB; size: GLsizeiptrARB; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetBufferSubDataARB: procedure(target: GLenum; offset: GLintptrARB; size: GLsizeiptrARB; data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapBufferARB: function(target: GLenum; access: GLenum): PGLvoid; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUnmapBufferARB: function(target: GLenum): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetBufferParameterivARB: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetBufferPointervARB: procedure(target: GLenum; pname: GLenum; params: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_vertex_buffer_object: Boolean;
+
+//***** GL_ARB_occlusion_query *****//
+const
+  GL_SAMPLES_PASSED_ARB = $8914;
+  GL_QUERY_COUNTER_BITS_ARB = $8864;
+  GL_CURRENT_QUERY_ARB = $8865;
+  GL_QUERY_RESULT_ARB = $8866;
+  GL_QUERY_RESULT_AVAILABLE_ARB = $8867;
+var
+  glGenQueriesARB: procedure(n: GLsizei; ids: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteQueriesARB: procedure(n: GLsizei; const ids: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsQueryARB: function(id: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBeginQueryARB: procedure(target: GLenum; id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEndQueryARB: procedure(target: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetQueryivARB: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetQueryObjectivARB: procedure(id: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetQueryObjectuivARB: procedure(id: GLuint; pname: GLenum; params: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_occlusion_query: Boolean;
+
+//***** GL_ARB_shader_objects *****//
+const
+  GL_PROGRAM_OBJECT_ARB = $8B40;
+  GL_OBJECT_TYPE_ARB = $8B4E;
+  GL_OBJECT_SUBTYPE_ARB = $8B4F;
+  GL_OBJECT_DELETE_STATUS_ARB = $8B80;
+  GL_OBJECT_COMPILE_STATUS_ARB = $8B81;
+  GL_OBJECT_LINK_STATUS_ARB = $8B82;
+  GL_OBJECT_VALIDATE_STATUS_ARB = $8B83;
+  GL_OBJECT_INFO_LOG_LENGTH_ARB = $8B84;
+  GL_OBJECT_ATTACHED_OBJECTS_ARB = $8B85;
+  GL_OBJECT_ACTIVE_UNIFORMS_ARB = $8B86;
+  GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB = $8B87;
+  GL_OBJECT_SHADER_SOURCE_LENGTH_ARB = $8B88;
+  GL_SHADER_OBJECT_ARB = $8B48;
+  GL_FLOAT = $1406;
+  GL_FLOAT_VEC2_ARB = $8B50;
+  GL_FLOAT_VEC3_ARB = $8B51;
+  GL_FLOAT_VEC4_ARB = $8B52;
+  GL_INT = $1404;
+  GL_INT_VEC2_ARB = $8B53;
+  GL_INT_VEC3_ARB = $8B54;
+  GL_INT_VEC4_ARB = $8B55;
+  GL_BOOL_ARB = $8B56;
+  GL_BOOL_VEC2_ARB = $8B57;
+  GL_BOOL_VEC3_ARB = $8B58;
+  GL_BOOL_VEC4_ARB = $8B59;
+  GL_FLOAT_MAT2_ARB = $8B5A;
+  GL_FLOAT_MAT3_ARB = $8B5B;
+  GL_FLOAT_MAT4_ARB = $8B5C;
+var
+  glDeleteObjectARB: procedure(obj: GLhandleARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetHandleARB: function(pname: GLenum): GLhandleARB; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDetachObjectARB: procedure(containerObj: GLhandleARB; attachedObj: GLhandleARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCreateShaderObjectARB: function(shaderType: GLenum): GLhandleARB; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glShaderSourceARB: procedure(shaderObj: GLhandleARB; count: GLsizei; const _string: PGLvoid; const length: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompileShaderARB: procedure(shaderObj: GLhandleARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCreateProgramObjectARB: function(): GLhandleARB; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAttachObjectARB: procedure(containerObj: GLhandleARB; obj: GLhandleARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLinkProgramARB: procedure(programObj: GLhandleARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUseProgramObjectARB: procedure(programObj: GLhandleARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glValidateProgramARB: procedure(programObj: GLhandleARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform1fARB: procedure(location: GLint; v0: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform2fARB: procedure(location: GLint; v0: GLfloat; v1: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform3fARB: procedure(location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform4fARB: procedure(location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat; v3: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform1iARB: procedure(location: GLint; v0: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform2iARB: procedure(location: GLint; v0: GLint; v1: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform3iARB: procedure(location: GLint; v0: GLint; v1: GLint; v2: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform4iARB: procedure(location: GLint; v0: GLint; v1: GLint; v2: GLint; v3: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform1fvARB: procedure(location: GLint; count: GLsizei; value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform2fvARB: procedure(location: GLint; count: GLsizei; value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform3fvARB: procedure(location: GLint; count: GLsizei; value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform4fvARB: procedure(location: GLint; count: GLsizei; value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform1ivARB: procedure(location: GLint; count: GLsizei; value: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform2ivARB: procedure(location: GLint; count: GLsizei; value: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform3ivARB: procedure(location: GLint; count: GLsizei; value: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform4ivARB: procedure(location: GLint; count: GLsizei; value: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniformMatrix2fvARB: procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniformMatrix3fvARB: procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniformMatrix4fvARB: procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetObjectParameterfvARB: procedure(obj: GLhandleARB; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetObjectParameterivARB: procedure(obj: GLhandleARB; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetInfoLogARB: procedure(obj: GLhandleARB; maxLength: GLsizei; length: PGLsizei; infoLog: PGLcharARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetAttachedObjectsARB: procedure(containerObj: GLhandleARB; maxCount: GLsizei; count: PGLsizei; obj: PGLhandleARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetUniformLocationARB: function(programObj: GLhandleARB; const name: PGLcharARB): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetActiveUniformARB: procedure(programObj: GLhandleARB; index: GLuint; maxLength: GLsizei; length: PGLsizei; size: PGLint; _type: PGLenum; name: PGLcharARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetUniformfvARB: procedure(programObj: GLhandleARB; location: GLint; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetUniformivARB: procedure(programObj: GLhandleARB; location: GLint; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetShaderSourceARB: procedure(obj: GLhandleARB; maxLength: GLsizei; length: PGLsizei; source: PGLcharARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_shader_objects: Boolean;
+
+//***** GL_ARB_vertex_shader *****//
+const
+  GL_VERTEX_SHADER_ARB = $8B31;
+  GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB = $8B4A;
+  GL_MAX_VARYING_FLOATS_ARB = $8B4B;
+  // GL_MAX_VERTEX_ATTRIBS_ARB  { already defined }
+  // GL_MAX_TEXTURE_IMAGE_UNITS_ARB  { already defined }
+  GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB = $8B4C;
+  GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB = $8B4D;
+  // GL_MAX_TEXTURE_COORDS_ARB  { already defined }
+  // GL_VERTEX_PROGRAM_POINT_SIZE_ARB  { already defined }
+  // GL_VERTEX_PROGRAM_TWO_SIDE_ARB  { already defined }
+  // GL_OBJECT_TYPE_ARB  { already defined }
+  // GL_OBJECT_SUBTYPE_ARB  { already defined }
+  GL_OBJECT_ACTIVE_ATTRIBUTES_ARB = $8B89;
+  GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB = $8B8A;
+  // GL_SHADER_OBJECT_ARB  { already defined }
+  // GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB  { already defined }
+  // GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB  { already defined }
+  // GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB  { already defined }
+  // GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB  { already defined }
+  // GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB  { already defined }
+  // GL_CURRENT_VERTEX_ATTRIB_ARB  { already defined }
+  // GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB  { already defined }
+  // GL_FLOAT  { already defined }
+  // GL_FLOAT_VEC2_ARB  { already defined }
+  // GL_FLOAT_VEC3_ARB  { already defined }
+  // GL_FLOAT_VEC4_ARB  { already defined }
+  // GL_FLOAT_MAT2_ARB  { already defined }
+  // GL_FLOAT_MAT3_ARB  { already defined }
+  // GL_FLOAT_MAT4_ARB  { already defined }
+  // glVertexAttrib1fARB  { already defined }
+  // glVertexAttrib1sARB  { already defined }
+  // glVertexAttrib1dARB  { already defined }
+  // glVertexAttrib2fARB  { already defined }
+  // glVertexAttrib2sARB  { already defined }
+  // glVertexAttrib2dARB  { already defined }
+  // glVertexAttrib3fARB  { already defined }
+  // glVertexAttrib3sARB  { already defined }
+  // glVertexAttrib3dARB  { already defined }
+  // glVertexAttrib4fARB  { already defined }
+  // glVertexAttrib4sARB  { already defined }
+  // glVertexAttrib4dARB  { already defined }
+  // glVertexAttrib4NubARB  { already defined }
+  // glVertexAttrib1fvARB  { already defined }
+  // glVertexAttrib1svARB  { already defined }
+  // glVertexAttrib1dvARB  { already defined }
+  // glVertexAttrib2fvARB  { already defined }
+  // glVertexAttrib2svARB  { already defined }
+  // glVertexAttrib2dvARB  { already defined }
+  // glVertexAttrib3fvARB  { already defined }
+  // glVertexAttrib3svARB  { already defined }
+  // glVertexAttrib3dvARB  { already defined }
+  // glVertexAttrib4fvARB  { already defined }
+  // glVertexAttrib4svARB  { already defined }
+  // glVertexAttrib4dvARB  { already defined }
+  // glVertexAttrib4ivARB  { already defined }
+  // glVertexAttrib4bvARB  { already defined }
+  // glVertexAttrib4ubvARB  { already defined }
+  // glVertexAttrib4usvARB  { already defined }
+  // glVertexAttrib4uivARB  { already defined }
+  // glVertexAttrib4NbvARB  { already defined }
+  // glVertexAttrib4NsvARB  { already defined }
+  // glVertexAttrib4NivARB  { already defined }
+  // glVertexAttrib4NubvARB  { already defined }
+  // glVertexAttrib4NusvARB  { already defined }
+  // glVertexAttrib4NuivARB  { already defined }
+  // glVertexAttribPointerARB  { already defined }
+  // glEnableVertexAttribArrayARB  { already defined }
+  // glDisableVertexAttribArrayARB  { already defined }
+var
+  glBindAttribLocationARB: procedure(programObj: GLhandleARB; index: GLuint; const name: PGLcharARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetActiveAttribARB: procedure(programObj: GLhandleARB; index: GLuint; maxLength: GLsizei; length: PGLsizei; size: PGLint; _type: PGLenum; name: PGLcharARB); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetAttribLocationARB: function(programObj: GLhandleARB; const name: PGLcharARB): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  // glGetVertexAttribdvARB  { already defined }
+  // glGetVertexAttribfvARB  { already defined }
+  // glGetVertexAttribivARB  { already defined }
+  // glGetVertexAttribPointervARB  { already defined }
+
+function Load_GL_ARB_vertex_shader: Boolean;
+
+//***** GL_ARB_fragment_shader *****//
+const
+  GL_FRAGMENT_SHADER_ARB = $8B30;
+  GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB = $8B49;
+  // GL_MAX_TEXTURE_COORDS_ARB  { already defined }
+  // GL_MAX_TEXTURE_IMAGE_UNITS_ARB  { already defined }
+  // GL_OBJECT_TYPE_ARB  { already defined }
+  // GL_OBJECT_SUBTYPE_ARB  { already defined }
+  // GL_SHADER_OBJECT_ARB  { already defined }
+
+function Load_GL_ARB_fragment_shader: Boolean;
+
+//***** GL_ARB_shading_language_100 *****//
+
+function Load_GL_ARB_shading_language_100: Boolean;
+
+//***** GL_ARB_texture_non_power_of_two *****//
+
+function Load_GL_ARB_texture_non_power_of_two: Boolean;
+
+//***** GL_ARB_point_sprite *****//
+const
+  GL_POINT_SPRITE_ARB = $8861;
+  GL_COORD_REPLACE_ARB = $8862;
+
+function Load_GL_ARB_point_sprite: Boolean;
+
+//***** GL_EXT_depth_bounds_test *****//
+const
+  GL_DEPTH_BOUNDS_TEST_EXT = $8890;
+  GL_DEPTH_BOUNDS_EXT = $8891;
+var
+  glDepthBoundsEXT: procedure(zmin: GLclampd; zmax: GLclampd); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_depth_bounds_test: Boolean;
+
+//***** GL_EXT_secondary_color *****//
+const
+  GL_COLOR_SUM_EXT = $8458;
+  GL_CURRENT_SECONDARY_COLOR_EXT = $8459;
+  GL_SECONDARY_COLOR_ARRAY_SIZE_EXT = $845A;
+  GL_SECONDARY_COLOR_ARRAY_TYPE_EXT = $845B;
+  GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT = $845C;
+  GL_SECONDARY_COLOR_ARRAY_POINTER_EXT = $845D;
+  GL_SECONDARY_COLOR_ARRAY_EXT = $845E;
+var
+  glSecondaryColor3bEXT: procedure(r: GLbyte; g: GLbyte; b: GLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3sEXT: procedure(r: GLshort; g: GLshort; b: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3iEXT: procedure(r: GLint; g: GLint; b: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3fEXT: procedure(r: GLfloat; g: GLfloat; b: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3dEXT: procedure(r: GLdouble; g: GLdouble; b: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3ubEXT: procedure(r: GLubyte; g: GLubyte; b: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3usEXT: procedure(r: GLushort; g: GLushort; b: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3uiEXT: procedure(r: GLuint; g: GLuint; b: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3bvEXT: procedure(components: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3svEXT: procedure(components: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3ivEXT: procedure(components: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3fvEXT: procedure(components: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3dvEXT: procedure(components: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3ubvEXT: procedure(components: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3usvEXT: procedure(components: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3uivEXT: procedure(components: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColorPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_secondary_color: Boolean;
+
+//***** GL_EXT_texture_mirror_clamp *****//
+const
+  GL_MIRROR_CLAMP_EXT = $8742;
+  GL_MIRROR_CLAMP_TO_EDGE_EXT = $8743;
+  GL_MIRROR_CLAMP_TO_BORDER_EXT = $8912;
+
+function Load_GL_EXT_texture_mirror_clamp: Boolean;
+
+//***** GL_EXT_blend_equation_separate *****//
+const
+  GL_BLEND_EQUATION_RGB_EXT = $8009;
+  GL_BLEND_EQUATION_ALPHA_EXT = $883D;
+var
+  glBlendEquationSeparateEXT: procedure(modeRGB: GLenum; modeAlpha: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_blend_equation_separate: Boolean;
+
+//***** GL_MESA_pack_invert *****//
+const
+  GL_PACK_INVERT_MESA = $8758;
+
+function Load_GL_MESA_pack_invert: Boolean;
+
+//***** GL_MESA_ycbcr_texture *****//
+const
+  GL_YCBCR_MESA = $8757;
+  GL_UNSIGNED_SHORT_8_8_MESA = $85BA;
+  GL_UNSIGNED_SHORT_8_8_REV_MESA = $85BB;
+
+function Load_GL_MESA_ycbcr_texture: Boolean;
+
+//***** GL_ARB_fragment_program_shadow *****//
+
+function Load_GL_ARB_fragment_program_shadow: Boolean;
+
+//***** GL_EXT_fog_coord *****//
+const
+  GL_FOG_COORDINATE_SOURCE_EXT = $8450;
+  GL_FOG_COORDINATE_EXT = $8451;
+  GL_FRAGMENT_DEPTH_EXT = $8452;
+  GL_CURRENT_FOG_COORDINATE_EXT = $8453;
+  GL_FOG_COORDINATE_ARRAY_TYPE_EXT = $8454;
+  GL_FOG_COORDINATE_ARRAY_STRIDE_EXT = $8455;
+  GL_FOG_COORDINATE_ARRAY_POINTER_EXT = $8456;
+  GL_FOG_COORDINATE_ARRAY_EXT = $8457;
+var
+  glFogCoordfEXT: procedure(coord: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoorddEXT: procedure(coord: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoordfvEXT: procedure(coord: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoorddvEXT: procedure(coord: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoordPointerEXT: procedure(_type: GLenum; stride: GLsizei; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_fog_coord: Boolean;
+
+//***** GL_NV_fragment_program_option *****//
+
+function Load_GL_NV_fragment_program_option: Boolean;
+
+//***** GL_EXT_pixel_buffer_object *****//
+const
+  GL_PIXEL_PACK_BUFFER_EXT = $88EB;
+  GL_PIXEL_UNPACK_BUFFER_EXT = $88EC;
+  GL_PIXEL_PACK_BUFFER_BINDING_EXT = $88ED;
+  GL_PIXEL_UNPACK_BUFFER_BINDING_EXT = $88EF;
+
+function Load_GL_EXT_pixel_buffer_object: Boolean;
+
+//***** GL_NV_fragment_program2 *****//
+const
+  GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV = $88F4;
+  GL_MAX_PROGRAM_CALL_DEPTH_NV = $88F5;
+  GL_MAX_PROGRAM_IF_DEPTH_NV = $88F6;
+  GL_MAX_PROGRAM_LOOP_DEPTH_NV = $88F7;
+  GL_MAX_PROGRAM_LOOP_COUNT_NV = $88F8;
+
+function Load_GL_NV_fragment_program2: Boolean;
+
+//***** GL_NV_vertex_program2_option *****//
+  // GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV  { already defined }
+  // GL_MAX_PROGRAM_CALL_DEPTH_NV  { already defined }
+
+function Load_GL_NV_vertex_program2_option: Boolean;
+
+//***** GL_NV_vertex_program3 *****//
+  // GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB  { already defined }
+
+function Load_GL_NV_vertex_program3: Boolean;
+
+//***** GL_ARB_draw_buffers *****//
+const
+  GL_MAX_DRAW_BUFFERS_ARB = $8824;
+  GL_DRAW_BUFFER0_ARB = $8825;
+  GL_DRAW_BUFFER1_ARB = $8826;
+  GL_DRAW_BUFFER2_ARB = $8827;
+  GL_DRAW_BUFFER3_ARB = $8828;
+  GL_DRAW_BUFFER4_ARB = $8829;
+  GL_DRAW_BUFFER5_ARB = $882A;
+  GL_DRAW_BUFFER6_ARB = $882B;
+  GL_DRAW_BUFFER7_ARB = $882C;
+  GL_DRAW_BUFFER8_ARB = $882D;
+  GL_DRAW_BUFFER9_ARB = $882E;
+  GL_DRAW_BUFFER10_ARB = $882F;
+  GL_DRAW_BUFFER11_ARB = $8830;
+  GL_DRAW_BUFFER12_ARB = $8831;
+  GL_DRAW_BUFFER13_ARB = $8832;
+  GL_DRAW_BUFFER14_ARB = $8833;
+  GL_DRAW_BUFFER15_ARB = $8834;
+var
+  glDrawBuffersARB: procedure(n: GLsizei; const bufs: PGLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_draw_buffers: Boolean;
+
+//***** GL_ARB_texture_rectangle *****//
+const
+  GL_TEXTURE_RECTANGLE_ARB = $84F5;
+  GL_TEXTURE_BINDING_RECTANGLE_ARB = $84F6;
+  GL_PROXY_TEXTURE_RECTANGLE_ARB = $84F7;
+  GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB = $84F8;
+
+function Load_GL_ARB_texture_rectangle: Boolean;
+
+//***** GL_ARB_color_buffer_float *****//
+const
+  GL_RGBA_FLOAT_MODE_ARB = $8820;
+  GL_CLAMP_VERTEX_COLOR_ARB = $891A;
+  GL_CLAMP_FRAGMENT_COLOR_ARB = $891B;
+  GL_CLAMP_READ_COLOR_ARB = $891C;
+  GL_FIXED_ONLY_ARB = $891D;
+  WGL_TYPE_RGBA_FLOAT_ARB = $21A0;
+var
+  glClampColorARB: procedure(target: GLenum; clamp: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_ARB_color_buffer_float: Boolean;
+
+//***** GL_ARB_half_float_pixel *****//
+const
+  GL_HALF_FLOAT_ARB = $140B;
+
+function Load_GL_ARB_half_float_pixel: Boolean;
+
+//***** GL_ARB_texture_float *****//
+const
+  GL_TEXTURE_RED_TYPE_ARB = $8C10;
+  GL_TEXTURE_GREEN_TYPE_ARB = $8C11;
+  GL_TEXTURE_BLUE_TYPE_ARB = $8C12;
+  GL_TEXTURE_ALPHA_TYPE_ARB = $8C13;
+  GL_TEXTURE_LUMINANCE_TYPE_ARB = $8C14;
+  GL_TEXTURE_INTENSITY_TYPE_ARB = $8C15;
+  GL_TEXTURE_DEPTH_TYPE_ARB = $8C16;
+  GL_UNSIGNED_NORMALIZED_ARB = $8C17;
+  GL_RGBA32F_ARB = $8814;
+  GL_RGB32F_ARB = $8815;
+  GL_ALPHA32F_ARB = $8816;
+  GL_INTENSITY32F_ARB = $8817;
+  GL_LUMINANCE32F_ARB = $8818;
+  GL_LUMINANCE_ALPHA32F_ARB = $8819;
+  GL_RGBA16F_ARB = $881A;
+  GL_RGB16F_ARB = $881B;
+  GL_ALPHA16F_ARB = $881C;
+  GL_INTENSITY16F_ARB = $881D;
+  GL_LUMINANCE16F_ARB = $881E;
+  GL_LUMINANCE_ALPHA16F_ARB = $881F;
+
+function Load_GL_ARB_texture_float: Boolean;
+
+//***** GL_EXT_texture_compression_dxt1 *****//
+  // GL_COMPRESSED_RGB_S3TC_DXT1_EXT  { already defined }
+  // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  { already defined }
+
+function Load_GL_EXT_texture_compression_dxt1: Boolean;
+
+//***** GL_ARB_pixel_buffer_object *****//
+const
+  GL_PIXEL_PACK_BUFFER_ARB = $88EB;
+  GL_PIXEL_UNPACK_BUFFER_ARB = $88EC;
+  GL_PIXEL_PACK_BUFFER_BINDING_ARB = $88ED;
+  GL_PIXEL_UNPACK_BUFFER_BINDING_ARB = $88EF;
+
+function Load_GL_ARB_pixel_buffer_object: Boolean;
+
+//***** GL_EXT_framebuffer_object *****//
+const
+  GL_FRAMEBUFFER_EXT = $8D40;
+  GL_RENDERBUFFER_EXT = $8D41;
+  GL_STENCIL_INDEX_EXT = $8D45;
+  GL_STENCIL_INDEX1_EXT = $8D46;
+  GL_STENCIL_INDEX4_EXT = $8D47;
+  GL_STENCIL_INDEX8_EXT = $8D48;
+  GL_STENCIL_INDEX16_EXT = $8D49;
+  GL_RENDERBUFFER_WIDTH_EXT = $8D42;
+  GL_RENDERBUFFER_HEIGHT_EXT = $8D43;
+  GL_RENDERBUFFER_INTERNAL_FORMAT_EXT = $8D44;
+  GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT = $8CD0;
+  GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT = $8CD1;
+  GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT = $8CD2;
+  GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT = $8CD3;
+  GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT = $8CD4;
+  GL_COLOR_ATTACHMENT0_EXT = $8CE0;
+  GL_COLOR_ATTACHMENT1_EXT = $8CE1;
+  GL_COLOR_ATTACHMENT2_EXT = $8CE2;
+  GL_COLOR_ATTACHMENT3_EXT = $8CE3;
+  GL_COLOR_ATTACHMENT4_EXT = $8CE4;
+  GL_COLOR_ATTACHMENT5_EXT = $8CE5;
+  GL_COLOR_ATTACHMENT6_EXT = $8CE6;
+  GL_COLOR_ATTACHMENT7_EXT = $8CE7;
+  GL_COLOR_ATTACHMENT8_EXT = $8CE8;
+  GL_COLOR_ATTACHMENT9_EXT = $8CE9;
+  GL_COLOR_ATTACHMENT10_EXT = $8CEA;
+  GL_COLOR_ATTACHMENT11_EXT = $8CEB;
+  GL_COLOR_ATTACHMENT12_EXT = $8CEC;
+  GL_COLOR_ATTACHMENT13_EXT = $8CED;
+  GL_COLOR_ATTACHMENT14_EXT = $8CEE;
+  GL_COLOR_ATTACHMENT15_EXT = $8CEF;
+  GL_DEPTH_ATTACHMENT_EXT = $8D00;
+  GL_STENCIL_ATTACHMENT_EXT = $8D20;
+  GL_FRAMEBUFFER_COMPLETE_EXT = $8CD5;
+  GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT = $8CD6;
+  GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT = $8CD7;
+  GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT = $8CD8;
+  GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT = $8CD9;
+  GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT = $8CDA;
+  GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT = $8CDB;
+  GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT = $8CDC;
+  GL_FRAMEBUFFER_UNSUPPORTED_EXT = $8CDD;
+  GL_FRAMEBUFFER_STATUS_ERROR_EXT = $8CDE;
+  GL_FRAMEBUFFER_BINDING_EXT = $8CA6;
+  GL_RENDERBUFFER_BINDING_EXT = $8CA7;
+  GL_MAX_COLOR_ATTACHMENTS_EXT = $8CDF;
+  GL_MAX_RENDERBUFFER_SIZE_EXT = $84E8;
+  GL_INVALID_FRAMEBUFFER_OPERATION_EXT = $0506;
+var
+  glIsRenderbufferEXT: function(renderbuffer: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindRenderbufferEXT: procedure(target: GLenum; renderbuffer: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteRenderbuffersEXT: procedure(n: GLsizei; const renderbuffers: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenRenderbuffersEXT: procedure(n: GLsizei; renderbuffers: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glRenderbufferStorageEXT: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetRenderbufferParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsFramebufferEXT: function(framebuffer: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindFramebufferEXT: procedure(target: GLenum; framebuffer: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteFramebuffersEXT: procedure(n: GLsizei; const framebuffers: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenFramebuffersEXT: procedure(n: GLsizei; framebuffers: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCheckFramebufferStatusEXT: function(target: GLenum): GLenum; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFramebufferTexture1DEXT: procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFramebufferTexture2DEXT: procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFramebufferTexture3DEXT: procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint; zoffset: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFramebufferRenderbufferEXT: procedure(target: GLenum; attachment: GLenum; renderbuffertarget: GLenum; renderbuffer: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetFramebufferAttachmentParameterivEXT: procedure(target: GLenum; attachment: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenerateMipmapEXT: procedure(target: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_EXT_framebuffer_object: Boolean;
+
+//***** GL_version_1_4 *****//
+const
+  GL_BLEND_DST_RGB = $80C8;
+  GL_BLEND_SRC_RGB = $80C9;
+  GL_BLEND_DST_ALPHA = $80CA;
+  GL_BLEND_SRC_ALPHA = $80CB;
+  GL_POINT_SIZE_MIN = $8126;
+  GL_POINT_SIZE_MAX = $8127;
+  GL_POINT_FADE_THRESHOLD_SIZE = $8128;
+  GL_POINT_DISTANCE_ATTENUATION = $8129;
+  GL_GENERATE_MIPMAP = $8191;
+  GL_GENERATE_MIPMAP_HINT = $8192;
+  GL_DEPTH_COMPONENT16 = $81A5;
+  GL_DEPTH_COMPONENT24 = $81A6;
+  GL_DEPTH_COMPONENT32 = $81A7;
+  GL_MIRRORED_REPEAT = $8370;
+  GL_FOG_COORDINATE_SOURCE = $8450;
+  GL_FOG_COORDINATE = $8451;
+  GL_FRAGMENT_DEPTH = $8452;
+  GL_CURRENT_FOG_COORDINATE = $8453;
+  GL_FOG_COORDINATE_ARRAY_TYPE = $8454;
+  GL_FOG_COORDINATE_ARRAY_STRIDE = $8455;
+  GL_FOG_COORDINATE_ARRAY_POINTER = $8456;
+  GL_FOG_COORDINATE_ARRAY = $8457;
+  GL_COLOR_SUM = $8458;
+  GL_CURRENT_SECONDARY_COLOR = $8459;
+  GL_SECONDARY_COLOR_ARRAY_SIZE = $845A;
+  GL_SECONDARY_COLOR_ARRAY_TYPE = $845B;
+  GL_SECONDARY_COLOR_ARRAY_STRIDE = $845C;
+  GL_SECONDARY_COLOR_ARRAY_POINTER = $845D;
+  GL_SECONDARY_COLOR_ARRAY = $845E;
+  GL_MAX_TEXTURE_LOD_BIAS = $84FD;
+  GL_TEXTURE_FILTER_CONTROL = $8500;
+  GL_TEXTURE_LOD_BIAS = $8501;
+  GL_INCR_WRAP = $8507;
+  GL_DECR_WRAP = $8508;
+  GL_TEXTURE_DEPTH_SIZE = $884A;
+  GL_DEPTH_TEXTURE_MODE = $884B;
+  GL_TEXTURE_COMPARE_MODE = $884C;
+  GL_TEXTURE_COMPARE_FUNC = $884D;
+  GL_COMPARE_R_TO_TEXTURE = $884E;
+var
+  glBlendFuncSeparate: procedure(sfactorRGB: GLenum; dfactorRGB: GLenum; sfactorAlpha: GLenum; dfactorAlpha: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoordf: procedure(coord: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoordfv: procedure(const coord: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoordd: procedure(coord: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoorddv: procedure(const coord: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogCoordPointer: procedure(_type: GLenum; stride: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiDrawArrays: procedure(mode: GLenum; first: PGLint; count: PGLsizei; primcount: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultiDrawElements: procedure(mode: GLenum; const count: PGLsizei; _type: GLenum; const indices: PGLvoid; primcount: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPointParameterf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPointParameterfv: procedure(pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPointParameteri: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPointParameteriv: procedure(pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3b: procedure(red: GLbyte; green: GLbyte; blue: GLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3bv: procedure(const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3d: procedure(red: GLdouble; green: GLdouble; blue: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3f: procedure(red: GLfloat; green: GLfloat; blue: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3i: procedure(red: GLint; green: GLint; blue: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3s: procedure(red: GLshort; green: GLshort; blue: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3ub: procedure(red: GLubyte; green: GLubyte; blue: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3ubv: procedure(const v: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3ui: procedure(red: GLuint; green: GLuint; blue: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3uiv: procedure(const v: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3us: procedure(red: GLushort; green: GLushort; blue: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColor3usv: procedure(const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSecondaryColorPointer: procedure(size: GLint; _type: GLenum; stride: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2d: procedure(x: GLdouble; y: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2f: procedure(x: GLfloat; y: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2i: procedure(x: GLint; y: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2s: procedure(x: GLshort; y: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos2sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3d: procedure(x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3f: procedure(x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3i: procedure(x: GLint; y: GLint; z: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3s: procedure(x: GLshort; y: GLshort; z: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glWindowPos3sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_version_1_4: Boolean;
+
+//***** GL_version_1_5 *****//
+const
+  GL_BUFFER_SIZE = $8764;
+  GL_BUFFER_USAGE = $8765;
+  GL_QUERY_COUNTER_BITS = $8864;
+  GL_CURRENT_QUERY = $8865;
+  GL_QUERY_RESULT = $8866;
+  GL_QUERY_RESULT_AVAILABLE = $8867;
+  GL_ARRAY_BUFFER = $8892;
+  GL_ELEMENT_ARRAY_BUFFER = $8893;
+  GL_ARRAY_BUFFER_BINDING = $8894;
+  GL_ELEMENT_ARRAY_BUFFER_BINDING = $8895;
+  GL_VERTEX_ARRAY_BUFFER_BINDING = $8896;
+  GL_NORMAL_ARRAY_BUFFER_BINDING = $8897;
+  GL_COLOR_ARRAY_BUFFER_BINDING = $8898;
+  GL_INDEX_ARRAY_BUFFER_BINDING = $8899;
+  GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING = $889A;
+  GL_EDGE_FLAG_ARRAY_BUFFER_BINDING = $889B;
+  GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING = $889C;
+  GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING = $889D;
+  GL_WEIGHT_ARRAY_BUFFER_BINDING = $889E;
+  GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = $889F;
+  GL_READ_ONLY = $88B8;
+  GL_WRITE_ONLY = $88B9;
+  GL_READ_WRITE = $88BA;
+  GL_BUFFER_ACCESS = $88BB;
+  GL_BUFFER_MAPPED = $88BC;
+  GL_BUFFER_MAP_POINTER = $88BD;
+  GL_STREAM_DRAW = $88E0;
+  GL_STREAM_READ = $88E1;
+  GL_STREAM_COPY = $88E2;
+  GL_STATIC_DRAW = $88E4;
+  GL_STATIC_READ = $88E5;
+  GL_STATIC_COPY = $88E6;
+  GL_DYNAMIC_DRAW = $88E8;
+  GL_DYNAMIC_READ = $88E9;
+  GL_DYNAMIC_COPY = $88EA;
+  GL_SAMPLES_PASSED = $8914;
+  GL_FOG_COORD_SRC = $8450;
+  GL_FOG_COORD = $8451;
+  GL_CURRENT_FOG_COORD = $8453;
+  GL_FOG_COORD_ARRAY_TYPE = $8454;
+  GL_FOG_COORD_ARRAY_STRIDE = $8455;
+  GL_FOG_COORD_ARRAY_POINTER = $8456;
+  GL_FOG_COORD_ARRAY = $8457;
+  GL_FOG_COORD_ARRAY_BUFFER_BINDING = $889D;
+  GL_SRC0_RGB = $8580;
+  GL_SRC1_RGB = $8581;
+  GL_SRC2_RGB = $8582;
+  GL_SRC0_ALPHA = $8588;
+  GL_SRC1_ALPHA = $8589;
+  GL_SRC2_ALPHA = $858A;
+var
+  glGenQueries: procedure(n: GLsizei; ids: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteQueries: procedure(n: GLsizei; const ids: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsQuery: function(id: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBeginQuery: procedure(target: GLenum; id: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEndQuery: procedure(target: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetQueryiv: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetQueryObjectiv: procedure(id: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetQueryObjectuiv: procedure(id: GLuint; pname: GLenum; params: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindBuffer: procedure(target: GLenum; buffer: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteBuffers: procedure(n: GLsizei; const buffers: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenBuffers: procedure(n: GLsizei; buffers: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsBuffer: function(buffer: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBufferData: procedure(target: GLenum; size: GLsizeiptr; const data: PGLvoid; usage: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBufferSubData: procedure(target: GLenum; offset: GLintptr; size: GLsizeiptr; const data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetBufferSubData: procedure(target: GLenum; offset: GLintptr; size: GLsizeiptr; data: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapBuffer: function(target: GLenum; access: GLenum): PGLvoid; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUnmapBuffer: function(target: GLenum): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetBufferParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetBufferPointerv: procedure(target: GLenum; pname: GLenum; params: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_version_1_5: Boolean;
+
+//***** GL_version_2_0 *****//
+const
+  GL_BLEND_EQUATION_RGB = $8009;
+  GL_VERTEX_ATTRIB_ARRAY_ENABLED = $8622;
+  GL_VERTEX_ATTRIB_ARRAY_SIZE = $8623;
+  GL_VERTEX_ATTRIB_ARRAY_STRIDE = $8624;
+  GL_VERTEX_ATTRIB_ARRAY_TYPE = $8625;
+  GL_CURRENT_VERTEX_ATTRIB = $8626;
+  GL_VERTEX_PROGRAM_POINT_SIZE = $8642;
+  GL_VERTEX_PROGRAM_TWO_SIDE = $8643;
+  GL_VERTEX_ATTRIB_ARRAY_POINTER = $8645;
+  GL_STENCIL_BACK_FUNC = $8800;
+  GL_STENCIL_BACK_FAIL = $8801;
+  GL_STENCIL_BACK_PASS_DEPTH_FAIL = $8802;
+  GL_STENCIL_BACK_PASS_DEPTH_PASS = $8803;
+  GL_MAX_DRAW_BUFFERS = $8824;
+  GL_DRAW_BUFFER0 = $8825;
+  GL_DRAW_BUFFER1 = $8826;
+  GL_DRAW_BUFFER2 = $8827;
+  GL_DRAW_BUFFER3 = $8828;
+  GL_DRAW_BUFFER4 = $8829;
+  GL_DRAW_BUFFER5 = $882A;
+  GL_DRAW_BUFFER6 = $882B;
+  GL_DRAW_BUFFER7 = $882C;
+  GL_DRAW_BUFFER8 = $882D;
+  GL_DRAW_BUFFER9 = $882E;
+  GL_DRAW_BUFFER10 = $882F;
+  GL_DRAW_BUFFER11 = $8830;
+  GL_DRAW_BUFFER12 = $8831;
+  GL_DRAW_BUFFER13 = $8832;
+  GL_DRAW_BUFFER14 = $8833;
+  GL_DRAW_BUFFER15 = $8834;
+  GL_BLEND_EQUATION_ALPHA = $883D;
+  GL_POINT_SPRITE = $8861;
+  GL_COORD_REPLACE = $8862;
+  GL_MAX_VERTEX_ATTRIBS = $8869;
+  GL_VERTEX_ATTRIB_ARRAY_NORMALIZED = $886A;
+  GL_MAX_TEXTURE_COORDS = $8871;
+  GL_MAX_TEXTURE_IMAGE_UNITS = $8872;
+  GL_FRAGMENT_SHADER = $8B30;
+  GL_VERTEX_SHADER = $8B31;
+  GL_MAX_FRAGMENT_UNIFORM_COMPONENTS = $8B49;
+  GL_MAX_VERTEX_UNIFORM_COMPONENTS = $8B4A;
+  GL_MAX_VARYING_FLOATS = $8B4B;
+  GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = $8B4C;
+  GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = $8B4D;
+  GL_SHADER_TYPE = $8B4F;
+  GL_FLOAT_VEC2 = $8B50;
+  GL_FLOAT_VEC3 = $8B51;
+  GL_FLOAT_VEC4 = $8B52;
+  GL_INT_VEC2 = $8B53;
+  GL_INT_VEC3 = $8B54;
+  GL_INT_VEC4 = $8B55;
+  GL_BOOL = $8B56;
+  GL_BOOL_VEC2 = $8B57;
+  GL_BOOL_VEC3 = $8B58;
+  GL_BOOL_VEC4 = $8B59;
+  GL_FLOAT_MAT2 = $8B5A;
+  GL_FLOAT_MAT3 = $8B5B;
+  GL_FLOAT_MAT4 = $8B5C;
+  GL_SAMPLER_1D = $8B5D;
+  GL_SAMPLER_2D = $8B5E;
+  GL_SAMPLER_3D = $8B5F;
+  GL_SAMPLER_CUBE = $8B60;
+  GL_SAMPLER_1D_SHADOW = $8B61;
+  GL_SAMPLER_2D_SHADOW = $8B62;
+  GL_DELETE_STATUS = $8B80;
+  GL_COMPILE_STATUS = $8B81;
+  GL_LINK_STATUS = $8B82;
+  GL_VALIDATE_STATUS = $8B83;
+  GL_INFO_LOG_LENGTH = $8B84;
+  GL_ATTACHED_SHADERS = $8B85;
+  GL_ACTIVE_UNIFORMS = $8B86;
+  GL_ACTIVE_UNIFORM_MAX_LENGTH = $8B87;
+  GL_SHADER_SOURCE_LENGTH = $8B88;
+  GL_ACTIVE_ATTRIBUTES = $8B89;
+  GL_ACTIVE_ATTRIBUTE_MAX_LENGTH = $8B8A;
+  GL_FRAGMENT_SHADER_DERIVATIVE_HINT = $8B8B;
+  GL_SHADING_LANGUAGE_VERSION = $8B8C;
+  GL_CURRENT_PROGRAM = $8B8D;
+  GL_POINT_SPRITE_COORD_ORIGIN = $8CA0;
+  GL_LOWER_LEFT = $8CA1;
+  GL_UPPER_LEFT = $8CA2;
+  GL_STENCIL_BACK_REF = $8CA3;
+  GL_STENCIL_BACK_VALUE_MASK = $8CA4;
+  GL_STENCIL_BACK_WRITEMASK = $8CA5;
+var
+  glBlendEquationSeparate: procedure(modeRGB: GLenum; modeAlpha: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawBuffers: procedure(n: GLsizei; const bufs: PGLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilOpSeparate: procedure(face: GLenum; sfail: GLenum; dpfail: GLenum; dppass: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilFuncSeparate: procedure(frontfunc: GLenum; backfunc: GLenum; ref: GLint; mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilMaskSeparate: procedure(face: GLenum; mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAttachShader: procedure(_program: GLuint; shader: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBindAttribLocation: procedure(_program: GLuint; index: GLuint; const name: PGLchar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCompileShader: procedure(shader: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCreateProgram: function(): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCreateShader: function(_type: GLenum): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteProgram: procedure(_program: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteShader: procedure(shader: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDetachShader: procedure(_program: GLuint; shader: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDisableVertexAttribArray: procedure(index: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEnableVertexAttribArray: procedure(index: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetActiveAttrib: procedure(_program: GLuint; index: GLuint; bufSize: GLsizei; length: PGLsizei; size: PGLint; _type: PGLenum; name: PGLchar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetActiveUniform: procedure(_program: GLuint; index: GLuint; bufSize: GLsizei; length: PGLsizei; size: PGLint; _type: PGLenum; name: PGLchar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetAttachedShaders: procedure(_program: GLuint; maxCount: GLsizei; count: PGLsizei; obj: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetAttribLocation: function(_program: GLuint; const name: PGLchar): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramiv: procedure(_program: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetProgramInfoLog: procedure(_program: GLuint; bufSize: GLsizei; length: PGLsizei; infoLog: PGLchar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetShaderiv: procedure(shader: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetShaderInfoLog: procedure(shader: GLuint; bufSize: GLsizei; length: PGLsizei; infoLog: PGLchar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetShaderSource: procedure(shader: GLuint; bufSize: GLsizei; length: PGLsizei; source: PGLchar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetUniformLocation: function(_program: GLuint; const name: PGLchar): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetUniformfv: procedure(_program: GLuint; location: GLint; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetUniformiv: procedure(_program: GLuint; location: GLint; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribdv: procedure(index: GLuint; pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribfv: procedure(index: GLuint; pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribiv: procedure(index: GLuint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetVertexAttribPointerv: procedure(index: GLuint; pname: GLenum; pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsProgram: function(_program: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsShader: function(shader: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLinkProgram: procedure(_program: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glShaderSource: procedure(shader: GLuint; count: GLsizei; const _string: PGLchar; const length: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUseProgram: procedure(_program: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform1f: procedure(location: GLint; v0: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform2f: procedure(location: GLint; v0: GLfloat; v1: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform3f: procedure(location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform4f: procedure(location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat; v3: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform1i: procedure(location: GLint; v0: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform2i: procedure(location: GLint; v0: GLint; v1: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform3i: procedure(location: GLint; v0: GLint; v1: GLint; v2: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform4i: procedure(location: GLint; v0: GLint; v1: GLint; v2: GLint; v3: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform1fv: procedure(location: GLint; count: GLsizei; const value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform2fv: procedure(location: GLint; count: GLsizei; const value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform3fv: procedure(location: GLint; count: GLsizei; const value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform4fv: procedure(location: GLint; count: GLsizei; const value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform1iv: procedure(location: GLint; count: GLsizei; const value: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform2iv: procedure(location: GLint; count: GLsizei; const value: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform3iv: procedure(location: GLint; count: GLsizei; const value: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniform4iv: procedure(location: GLint; count: GLsizei; const value: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniformMatrix2fv: procedure(location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniformMatrix3fv: procedure(location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glUniformMatrix4fv: procedure(location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glValidateProgram: procedure(_program: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1d: procedure(index: GLuint; x: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1dv: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1f: procedure(index: GLuint; x: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1fv: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1s: procedure(index: GLuint; x: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib1sv: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2d: procedure(index: GLuint; x: GLdouble; y: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2dv: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2f: procedure(index: GLuint; x: GLfloat; y: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2fv: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2s: procedure(index: GLuint; x: GLshort; y: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib2sv: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3d: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3dv: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3f: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3fv: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3s: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib3sv: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4Nbv: procedure(index: GLuint; const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4Niv: procedure(index: GLuint; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4Nsv: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4Nub: procedure(index: GLuint; x: GLubyte; y: GLubyte; z: GLubyte; w: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4Nubv: procedure(index: GLuint; const v: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4Nuiv: procedure(index: GLuint; const v: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4Nusv: procedure(index: GLuint; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4bv: procedure(index: GLuint; const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4d: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4dv: procedure(index: GLuint; const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4f: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4fv: procedure(index: GLuint; const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4iv: procedure(index: GLuint; const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4s: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort; w: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4sv: procedure(index: GLuint; const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4ubv: procedure(index: GLuint; const v: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4uiv: procedure(index: GLuint; const v: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttrib4usv: procedure(index: GLuint; const v: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexAttribPointer: procedure(index: GLuint; size: GLint; _type: GLenum; normalized: GLboolean; stride: GLsizei; const pointer: PGLvoid); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+function Load_GL_version_2_0: Boolean;
+
+implementation
+
+uses
+  sdl;
+
+function glext_ExtensionSupported(const extension: PChar; const searchIn: PChar): Boolean;
+var
+  extensions: PChar;
+  start: PChar;
+  where, terminator: PChar;
+begin
+
+  if (Pos(' ', extension) <> 0) or (extension = '') then
+  begin
+    Result := false;
+    Exit;
+  end;
+
+  if searchIn = '' then
+    extensions := glGetString(GL_EXTENSIONS)
+  else
+    //StrLCopy(extensions, searchIn, StrLen(searchIn) + 1);
+    extensions := searchIn;
+  start := extensions;
+  while true do
+  begin
+    where := StrPos(start, extension);
+    if where = nil then
+      Break;
+    terminator := where + Length(extension);
+    if (where = start) or ((where - 1)^ = ' ') then
+    begin
+      if (terminator^ = ' ') or (terminator^ = #0) then
+      begin
+	Result := true;
+	Exit;
+      end;
+    end;
+    start := terminator;
+  end;
+  Result := false;
+
+end;
+
+function Load_GL_version_1_2: Boolean;
+{var
+  extstring : PChar;}
+begin
+
+  Result := FALSE;
+  //extstring := glGetString( GL_EXTENSIONS );
+
+  @glCopyTexSubImage3D := SDL_GL_GetProcAddress('glCopyTexSubImage3D');
+  if not Assigned(glCopyTexSubImage3D) then Exit;
+  @glDrawRangeElements := SDL_GL_GetProcAddress('glDrawRangeElements');
+  if not Assigned(glDrawRangeElements) then Exit;
+  @glTexImage3D := SDL_GL_GetProcAddress('glTexImage3D');
+  if not Assigned(glTexImage3D) then Exit;
+  @glTexSubImage3D := SDL_GL_GetProcAddress('glTexSubImage3D');
+  if not Assigned(glTexSubImage3D) then Exit;
+    
+  Result := TRUE;
+
+end;
+
+function Load_GL_ARB_imaging: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_imaging', extstring) then
+  begin
+    @glColorTable := SDL_GL_GetProcAddress('glColorTable');
+    if not Assigned(glColorTable) then Exit;
+    @glColorTableParameterfv := SDL_GL_GetProcAddress('glColorTableParameterfv');
+    if not Assigned(glColorTableParameterfv) then Exit;
+    @glColorTableParameteriv := SDL_GL_GetProcAddress('glColorTableParameteriv');
+    if not Assigned(glColorTableParameteriv) then Exit;
+    @glCopyColorTable := SDL_GL_GetProcAddress('glCopyColorTable');
+    if not Assigned(glCopyColorTable) then Exit;
+    @glGetColorTable := SDL_GL_GetProcAddress('glGetColorTable');
+    if not Assigned(glGetColorTable) then Exit;
+    @glGetColorTableParameterfv := SDL_GL_GetProcAddress('glGetColorTableParameterfv');
+    if not Assigned(glGetColorTableParameterfv) then Exit;
+    @glGetColorTableParameteriv := SDL_GL_GetProcAddress('glGetColorTableParameteriv');
+    if not Assigned(glGetColorTableParameteriv) then Exit;
+    @glColorSubTable := SDL_GL_GetProcAddress('glColorSubTable');
+    if not Assigned(glColorSubTable) then Exit;
+    @glCopyColorSubTable := SDL_GL_GetProcAddress('glCopyColorSubTable');
+    if not Assigned(glCopyColorSubTable) then Exit;
+    @glConvolutionFilter1D := SDL_GL_GetProcAddress('glConvolutionFilter1D');
+    if not Assigned(glConvolutionFilter1D) then Exit;
+    @glConvolutionFilter2D := SDL_GL_GetProcAddress('glConvolutionFilter2D');
+    if not Assigned(glConvolutionFilter2D) then Exit;
+    @glConvolutionParameterf := SDL_GL_GetProcAddress('glConvolutionParameterf');
+    if not Assigned(glConvolutionParameterf) then Exit;
+    @glConvolutionParameterfv := SDL_GL_GetProcAddress('glConvolutionParameterfv');
+    if not Assigned(glConvolutionParameterfv) then Exit;
+    @glConvolutionParameteri := SDL_GL_GetProcAddress('glConvolutionParameteri');
+    if not Assigned(glConvolutionParameteri) then Exit;
+    @glConvolutionParameteriv := SDL_GL_GetProcAddress('glConvolutionParameteriv');
+    if not Assigned(glConvolutionParameteriv) then Exit;
+    @glCopyConvolutionFilter1D := SDL_GL_GetProcAddress('glCopyConvolutionFilter1D');
+    if not Assigned(glCopyConvolutionFilter1D) then Exit;
+    @glCopyConvolutionFilter2D := SDL_GL_GetProcAddress('glCopyConvolutionFilter2D');
+    if not Assigned(glCopyConvolutionFilter2D) then Exit;
+    @glGetConvolutionFilter := SDL_GL_GetProcAddress('glGetConvolutionFilter');
+    if not Assigned(glGetConvolutionFilter) then Exit;
+    @glGetConvolutionParameterfv := SDL_GL_GetProcAddress('glGetConvolutionParameterfv');
+    if not Assigned(glGetConvolutionParameterfv) then Exit;
+    @glGetConvolutionParameteriv := SDL_GL_GetProcAddress('glGetConvolutionParameteriv');
+    if not Assigned(glGetConvolutionParameteriv) then Exit;
+    @glGetSeparableFilter := SDL_GL_GetProcAddress('glGetSeparableFilter');
+    if not Assigned(glGetSeparableFilter) then Exit;
+    @glSeparableFilter2D := SDL_GL_GetProcAddress('glSeparableFilter2D');
+    if not Assigned(glSeparableFilter2D) then Exit;
+    @glGetHistogram := SDL_GL_GetProcAddress('glGetHistogram');
+    if not Assigned(glGetHistogram) then Exit;
+    @glGetHistogramParameterfv := SDL_GL_GetProcAddress('glGetHistogramParameterfv');
+    if not Assigned(glGetHistogramParameterfv) then Exit;
+    @glGetHistogramParameteriv := SDL_GL_GetProcAddress('glGetHistogramParameteriv');
+    if not Assigned(glGetHistogramParameteriv) then Exit;
+    @glGetMinmax := SDL_GL_GetProcAddress('glGetMinmax');
+    if not Assigned(glGetMinmax) then Exit;
+    @glGetMinmaxParameterfv := SDL_GL_GetProcAddress('glGetMinmaxParameterfv');
+    if not Assigned(glGetMinmaxParameterfv) then Exit;
+    @glGetMinmaxParameteriv := SDL_GL_GetProcAddress('glGetMinmaxParameteriv');
+    if not Assigned(glGetMinmaxParameteriv) then Exit;
+    @glHistogram := SDL_GL_GetProcAddress('glHistogram');
+    if not Assigned(glHistogram) then Exit;
+    @glMinmax := SDL_GL_GetProcAddress('glMinmax');
+    if not Assigned(glMinmax) then Exit;
+    @glResetHistogram := SDL_GL_GetProcAddress('glResetHistogram');
+    if not Assigned(glResetHistogram) then Exit;
+    @glResetMinmax := SDL_GL_GetProcAddress('glResetMinmax');
+    if not Assigned(glResetMinmax) then Exit;
+    @glBlendEquation := SDL_GL_GetProcAddress('glBlendEquation');
+    if not Assigned(glBlendEquation) then Exit;
+    @glBlendColor := SDL_GL_GetProcAddress('glBlendColor');
+    if not Assigned(glBlendColor) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_version_1_3: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+    @glActiveTexture := SDL_GL_GetProcAddress('glActiveTexture');
+    if not Assigned(glActiveTexture) then Exit;
+    @glClientActiveTexture := SDL_GL_GetProcAddress('glClientActiveTexture');
+    if not Assigned(glClientActiveTexture) then Exit;
+    @glMultiTexCoord1d := SDL_GL_GetProcAddress('glMultiTexCoord1d');
+    if not Assigned(glMultiTexCoord1d) then Exit;
+    @glMultiTexCoord1dv := SDL_GL_GetProcAddress('glMultiTexCoord1dv');
+    if not Assigned(glMultiTexCoord1dv) then Exit;
+    @glMultiTexCoord1f := SDL_GL_GetProcAddress('glMultiTexCoord1f');
+    if not Assigned(glMultiTexCoord1f) then Exit;
+    @glMultiTexCoord1fv := SDL_GL_GetProcAddress('glMultiTexCoord1fv');
+    if not Assigned(glMultiTexCoord1fv) then Exit;
+    @glMultiTexCoord1i := SDL_GL_GetProcAddress('glMultiTexCoord1i');
+    if not Assigned(glMultiTexCoord1i) then Exit;
+    @glMultiTexCoord1iv := SDL_GL_GetProcAddress('glMultiTexCoord1iv');
+    if not Assigned(glMultiTexCoord1iv) then Exit;
+    @glMultiTexCoord1s := SDL_GL_GetProcAddress('glMultiTexCoord1s');
+    if not Assigned(glMultiTexCoord1s) then Exit;
+    @glMultiTexCoord1sv := SDL_GL_GetProcAddress('glMultiTexCoord1sv');
+    if not Assigned(glMultiTexCoord1sv) then Exit;
+    @glMultiTexCoord2d := SDL_GL_GetProcAddress('glMultiTexCoord2d');
+    if not Assigned(glMultiTexCoord2d) then Exit;
+    @glMultiTexCoord2dv := SDL_GL_GetProcAddress('glMultiTexCoord2dv');
+    if not Assigned(glMultiTexCoord2dv) then Exit;
+    @glMultiTexCoord2f := SDL_GL_GetProcAddress('glMultiTexCoord2f');
+    if not Assigned(glMultiTexCoord2f) then Exit;
+    @glMultiTexCoord2fv := SDL_GL_GetProcAddress('glMultiTexCoord2fv');
+    if not Assigned(glMultiTexCoord2fv) then Exit;
+    @glMultiTexCoord2i := SDL_GL_GetProcAddress('glMultiTexCoord2i');
+    if not Assigned(glMultiTexCoord2i) then Exit;
+    @glMultiTexCoord2iv := SDL_GL_GetProcAddress('glMultiTexCoord2iv');
+    if not Assigned(glMultiTexCoord2iv) then Exit;
+    @glMultiTexCoord2s := SDL_GL_GetProcAddress('glMultiTexCoord2s');
+    if not Assigned(glMultiTexCoord2s) then Exit;
+    @glMultiTexCoord2sv := SDL_GL_GetProcAddress('glMultiTexCoord2sv');
+    if not Assigned(glMultiTexCoord2sv) then Exit;
+    @glMultiTexCoord3d := SDL_GL_GetProcAddress('glMultiTexCoord3d');
+    if not Assigned(glMultiTexCoord3d) then Exit;
+    @glMultiTexCoord3dv := SDL_GL_GetProcAddress('glMultiTexCoord3dv');
+    if not Assigned(glMultiTexCoord3dv) then Exit;
+    @glMultiTexCoord3f := SDL_GL_GetProcAddress('glMultiTexCoord3f');
+    if not Assigned(glMultiTexCoord3f) then Exit;
+    @glMultiTexCoord3fv := SDL_GL_GetProcAddress('glMultiTexCoord3fv');
+    if not Assigned(glMultiTexCoord3fv) then Exit;
+    @glMultiTexCoord3i := SDL_GL_GetProcAddress('glMultiTexCoord3i');
+    if not Assigned(glMultiTexCoord3i) then Exit;
+    @glMultiTexCoord3iv := SDL_GL_GetProcAddress('glMultiTexCoord3iv');
+    if not Assigned(glMultiTexCoord3iv) then Exit;
+    @glMultiTexCoord3s := SDL_GL_GetProcAddress('glMultiTexCoord3s');
+    if not Assigned(glMultiTexCoord3s) then Exit;
+    @glMultiTexCoord3sv := SDL_GL_GetProcAddress('glMultiTexCoord3sv');
+    if not Assigned(glMultiTexCoord3sv) then Exit;
+    @glMultiTexCoord4d := SDL_GL_GetProcAddress('glMultiTexCoord4d');
+    if not Assigned(glMultiTexCoord4d) then Exit;
+    @glMultiTexCoord4dv := SDL_GL_GetProcAddress('glMultiTexCoord4dv');
+    if not Assigned(glMultiTexCoord4dv) then Exit;
+    @glMultiTexCoord4f := SDL_GL_GetProcAddress('glMultiTexCoord4f');
+    if not Assigned(glMultiTexCoord4f) then Exit;
+    @glMultiTexCoord4fv := SDL_GL_GetProcAddress('glMultiTexCoord4fv');
+    if not Assigned(glMultiTexCoord4fv) then Exit;
+    @glMultiTexCoord4i := SDL_GL_GetProcAddress('glMultiTexCoord4i');
+    if not Assigned(glMultiTexCoord4i) then Exit;
+    @glMultiTexCoord4iv := SDL_GL_GetProcAddress('glMultiTexCoord4iv');
+    if not Assigned(glMultiTexCoord4iv) then Exit;
+    @glMultiTexCoord4s := SDL_GL_GetProcAddress('glMultiTexCoord4s');
+    if not Assigned(glMultiTexCoord4s) then Exit;
+    @glMultiTexCoord4sv := SDL_GL_GetProcAddress('glMultiTexCoord4sv');
+    if not Assigned(glMultiTexCoord4sv) then Exit;
+    @glLoadTransposeMatrixf := SDL_GL_GetProcAddress('glLoadTransposeMatrixf');
+    if not Assigned(glLoadTransposeMatrixf) then Exit;
+    @glLoadTransposeMatrixd := SDL_GL_GetProcAddress('glLoadTransposeMatrixd');
+    if not Assigned(glLoadTransposeMatrixd) then Exit;
+    @glMultTransposeMatrixf := SDL_GL_GetProcAddress('glMultTransposeMatrixf');
+    if not Assigned(glMultTransposeMatrixf) then Exit;
+    @glMultTransposeMatrixd := SDL_GL_GetProcAddress('glMultTransposeMatrixd');
+    if not Assigned(glMultTransposeMatrixd) then Exit;
+    @glSampleCoverage := SDL_GL_GetProcAddress('glSampleCoverage');
+    if not Assigned(glSampleCoverage) then Exit;
+    @glCompressedTexImage3D := SDL_GL_GetProcAddress('glCompressedTexImage3D');
+    if not Assigned(glCompressedTexImage3D) then Exit;
+    @glCompressedTexImage2D := SDL_GL_GetProcAddress('glCompressedTexImage2D');
+    if not Assigned(glCompressedTexImage2D) then Exit;
+    @glCompressedTexImage1D := SDL_GL_GetProcAddress('glCompressedTexImage1D');
+    if not Assigned(glCompressedTexImage1D) then Exit;
+    @glCompressedTexSubImage3D := SDL_GL_GetProcAddress('glCompressedTexSubImage3D');
+    if not Assigned(glCompressedTexSubImage3D) then Exit;
+    @glCompressedTexSubImage2D := SDL_GL_GetProcAddress('glCompressedTexSubImage2D');
+    if not Assigned(glCompressedTexSubImage2D) then Exit;
+    @glCompressedTexSubImage1D := SDL_GL_GetProcAddress('glCompressedTexSubImage1D');
+    if not Assigned(glCompressedTexSubImage1D) then Exit;
+    @glGetCompressedTexImage := SDL_GL_GetProcAddress('glGetCompressedTexImage');
+    if not Assigned(glGetCompressedTexImage) then Exit;
+    Result := TRUE;
+
+end;
+
+function Load_GL_ARB_multitexture: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_multitexture', extstring) then
+  begin
+    @glActiveTextureARB := SDL_GL_GetProcAddress('glActiveTextureARB');
+    if not Assigned(glActiveTextureARB) then Exit;
+    @glClientActiveTextureARB := SDL_GL_GetProcAddress('glClientActiveTextureARB');
+    if not Assigned(glClientActiveTextureARB) then Exit;
+    @glMultiTexCoord1dARB := SDL_GL_GetProcAddress('glMultiTexCoord1dARB');
+    if not Assigned(glMultiTexCoord1dARB) then Exit;
+    @glMultiTexCoord1dvARB := SDL_GL_GetProcAddress('glMultiTexCoord1dvARB');
+    if not Assigned(glMultiTexCoord1dvARB) then Exit;
+    @glMultiTexCoord1fARB := SDL_GL_GetProcAddress('glMultiTexCoord1fARB');
+    if not Assigned(glMultiTexCoord1fARB) then Exit;
+    @glMultiTexCoord1fvARB := SDL_GL_GetProcAddress('glMultiTexCoord1fvARB');
+    if not Assigned(glMultiTexCoord1fvARB) then Exit;
+    @glMultiTexCoord1iARB := SDL_GL_GetProcAddress('glMultiTexCoord1iARB');
+    if not Assigned(glMultiTexCoord1iARB) then Exit;
+    @glMultiTexCoord1ivARB := SDL_GL_GetProcAddress('glMultiTexCoord1ivARB');
+    if not Assigned(glMultiTexCoord1ivARB) then Exit;
+    @glMultiTexCoord1sARB := SDL_GL_GetProcAddress('glMultiTexCoord1sARB');
+    if not Assigned(glMultiTexCoord1sARB) then Exit;
+    @glMultiTexCoord1svARB := SDL_GL_GetProcAddress('glMultiTexCoord1svARB');
+    if not Assigned(glMultiTexCoord1svARB) then Exit;
+    @glMultiTexCoord2dARB := SDL_GL_GetProcAddress('glMultiTexCoord2dARB');
+    if not Assigned(glMultiTexCoord2dARB) then Exit;
+    @glMultiTexCoord2dvARB := SDL_GL_GetProcAddress('glMultiTexCoord2dvARB');
+    if not Assigned(glMultiTexCoord2dvARB) then Exit;
+    @glMultiTexCoord2fARB := SDL_GL_GetProcAddress('glMultiTexCoord2fARB');
+    if not Assigned(glMultiTexCoord2fARB) then Exit;
+    @glMultiTexCoord2fvARB := SDL_GL_GetProcAddress('glMultiTexCoord2fvARB');
+    if not Assigned(glMultiTexCoord2fvARB) then Exit;
+    @glMultiTexCoord2iARB := SDL_GL_GetProcAddress('glMultiTexCoord2iARB');
+    if not Assigned(glMultiTexCoord2iARB) then Exit;
+    @glMultiTexCoord2ivARB := SDL_GL_GetProcAddress('glMultiTexCoord2ivARB');
+    if not Assigned(glMultiTexCoord2ivARB) then Exit;
+    @glMultiTexCoord2sARB := SDL_GL_GetProcAddress('glMultiTexCoord2sARB');
+    if not Assigned(glMultiTexCoord2sARB) then Exit;
+    @glMultiTexCoord2svARB := SDL_GL_GetProcAddress('glMultiTexCoord2svARB');
+    if not Assigned(glMultiTexCoord2svARB) then Exit;
+    @glMultiTexCoord3dARB := SDL_GL_GetProcAddress('glMultiTexCoord3dARB');
+    if not Assigned(glMultiTexCoord3dARB) then Exit;
+    @glMultiTexCoord3dvARB := SDL_GL_GetProcAddress('glMultiTexCoord3dvARB');
+    if not Assigned(glMultiTexCoord3dvARB) then Exit;
+    @glMultiTexCoord3fARB := SDL_GL_GetProcAddress('glMultiTexCoord3fARB');
+    if not Assigned(glMultiTexCoord3fARB) then Exit;
+    @glMultiTexCoord3fvARB := SDL_GL_GetProcAddress('glMultiTexCoord3fvARB');
+    if not Assigned(glMultiTexCoord3fvARB) then Exit;
+    @glMultiTexCoord3iARB := SDL_GL_GetProcAddress('glMultiTexCoord3iARB');
+    if not Assigned(glMultiTexCoord3iARB) then Exit;
+    @glMultiTexCoord3ivARB := SDL_GL_GetProcAddress('glMultiTexCoord3ivARB');
+    if not Assigned(glMultiTexCoord3ivARB) then Exit;
+    @glMultiTexCoord3sARB := SDL_GL_GetProcAddress('glMultiTexCoord3sARB');
+    if not Assigned(glMultiTexCoord3sARB) then Exit;
+    @glMultiTexCoord3svARB := SDL_GL_GetProcAddress('glMultiTexCoord3svARB');
+    if not Assigned(glMultiTexCoord3svARB) then Exit;
+    @glMultiTexCoord4dARB := SDL_GL_GetProcAddress('glMultiTexCoord4dARB');
+    if not Assigned(glMultiTexCoord4dARB) then Exit;
+    @glMultiTexCoord4dvARB := SDL_GL_GetProcAddress('glMultiTexCoord4dvARB');
+    if not Assigned(glMultiTexCoord4dvARB) then Exit;
+    @glMultiTexCoord4fARB := SDL_GL_GetProcAddress('glMultiTexCoord4fARB');
+    if not Assigned(glMultiTexCoord4fARB) then Exit;
+    @glMultiTexCoord4fvARB := SDL_GL_GetProcAddress('glMultiTexCoord4fvARB');
+    if not Assigned(glMultiTexCoord4fvARB) then Exit;
+    @glMultiTexCoord4iARB := SDL_GL_GetProcAddress('glMultiTexCoord4iARB');
+    if not Assigned(glMultiTexCoord4iARB) then Exit;
+    @glMultiTexCoord4ivARB := SDL_GL_GetProcAddress('glMultiTexCoord4ivARB');
+    if not Assigned(glMultiTexCoord4ivARB) then Exit;
+    @glMultiTexCoord4sARB := SDL_GL_GetProcAddress('glMultiTexCoord4sARB');
+    if not Assigned(glMultiTexCoord4sARB) then Exit;
+    @glMultiTexCoord4svARB := SDL_GL_GetProcAddress('glMultiTexCoord4svARB');
+    if not Assigned(glMultiTexCoord4svARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_transpose_matrix: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_transpose_matrix', extstring) then
+  begin
+    @glLoadTransposeMatrixfARB := SDL_GL_GetProcAddress('glLoadTransposeMatrixfARB');
+    if not Assigned(glLoadTransposeMatrixfARB) then Exit;
+    @glLoadTransposeMatrixdARB := SDL_GL_GetProcAddress('glLoadTransposeMatrixdARB');
+    if not Assigned(glLoadTransposeMatrixdARB) then Exit;
+    @glMultTransposeMatrixfARB := SDL_GL_GetProcAddress('glMultTransposeMatrixfARB');
+    if not Assigned(glMultTransposeMatrixfARB) then Exit;
+    @glMultTransposeMatrixdARB := SDL_GL_GetProcAddress('glMultTransposeMatrixdARB');
+    if not Assigned(glMultTransposeMatrixdARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_multisample: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_multisample', extstring) then
+  begin
+    @glSampleCoverageARB := SDL_GL_GetProcAddress('glSampleCoverageARB');
+    if not Assigned(glSampleCoverageARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_env_add: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_texture_env_add', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+{$IFDEF WINDOWS}
+function Load_WGL_ARB_extensions_string: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_ARB_extensions_string', extstring) then
+  begin
+    @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+    if not Assigned(wglGetExtensionsStringARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_ARB_buffer_region: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_ARB_buffer_region', extstring) then
+  begin
+    @wglCreateBufferRegionARB := SDL_GL_GetProcAddress('wglCreateBufferRegionARB');
+    if not Assigned(wglCreateBufferRegionARB) then Exit;
+    @wglDeleteBufferRegionARB := SDL_GL_GetProcAddress('wglDeleteBufferRegionARB');
+    if not Assigned(wglDeleteBufferRegionARB) then Exit;
+    @wglSaveBufferRegionARB := SDL_GL_GetProcAddress('wglSaveBufferRegionARB');
+    if not Assigned(wglSaveBufferRegionARB) then Exit;
+    @wglRestoreBufferRegionARB := SDL_GL_GetProcAddress('wglRestoreBufferRegionARB');
+    if not Assigned(wglRestoreBufferRegionARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+{$ENDIF}
+
+function Load_GL_ARB_texture_cube_map: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_texture_cube_map', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_depth_texture: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_depth_texture', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_point_parameters: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_point_parameters', extstring) then
+  begin
+    @glPointParameterfARB := SDL_GL_GetProcAddress('glPointParameterfARB');
+    if not Assigned(glPointParameterfARB) then Exit;
+    @glPointParameterfvARB := SDL_GL_GetProcAddress('glPointParameterfvARB');
+    if not Assigned(glPointParameterfvARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_shadow: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_shadow', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_shadow_ambient: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_shadow_ambient', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_border_clamp: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_texture_border_clamp', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_compression: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_texture_compression', extstring) then
+  begin
+    @glCompressedTexImage3DARB := SDL_GL_GetProcAddress('glCompressedTexImage3DARB');
+    if not Assigned(glCompressedTexImage3DARB) then Exit;
+    @glCompressedTexImage2DARB := SDL_GL_GetProcAddress('glCompressedTexImage2DARB');
+    if not Assigned(glCompressedTexImage2DARB) then Exit;
+    @glCompressedTexImage1DARB := SDL_GL_GetProcAddress('glCompressedTexImage1DARB');
+    if not Assigned(glCompressedTexImage1DARB) then Exit;
+    @glCompressedTexSubImage3DARB := SDL_GL_GetProcAddress('glCompressedTexSubImage3DARB');
+    if not Assigned(glCompressedTexSubImage3DARB) then Exit;
+    @glCompressedTexSubImage2DARB := SDL_GL_GetProcAddress('glCompressedTexSubImage2DARB');
+    if not Assigned(glCompressedTexSubImage2DARB) then Exit;
+    @glCompressedTexSubImage1DARB := SDL_GL_GetProcAddress('glCompressedTexSubImage1DARB');
+    if not Assigned(glCompressedTexSubImage1DARB) then Exit;
+    @glGetCompressedTexImageARB := SDL_GL_GetProcAddress('glGetCompressedTexImageARB');
+    if not Assigned(glGetCompressedTexImageARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_env_combine: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_texture_env_combine', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_env_crossbar: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_texture_env_crossbar', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_env_dot3: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_texture_env_dot3', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_mirrored_repeat: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_texture_mirrored_repeat', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_vertex_blend: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_vertex_blend', extstring) then
+  begin
+    @glWeightbvARB := SDL_GL_GetProcAddress('glWeightbvARB');
+    if not Assigned(glWeightbvARB) then Exit;
+    @glWeightsvARB := SDL_GL_GetProcAddress('glWeightsvARB');
+    if not Assigned(glWeightsvARB) then Exit;
+    @glWeightivARB := SDL_GL_GetProcAddress('glWeightivARB');
+    if not Assigned(glWeightivARB) then Exit;
+    @glWeightfvARB := SDL_GL_GetProcAddress('glWeightfvARB');
+    if not Assigned(glWeightfvARB) then Exit;
+    @glWeightdvARB := SDL_GL_GetProcAddress('glWeightdvARB');
+    if not Assigned(glWeightdvARB) then Exit;
+    @glWeightvARB := SDL_GL_GetProcAddress('glWeightvARB');
+    if not Assigned(glWeightvARB) then Exit;
+    @glWeightubvARB := SDL_GL_GetProcAddress('glWeightubvARB');
+    if not Assigned(glWeightubvARB) then Exit;
+    @glWeightusvARB := SDL_GL_GetProcAddress('glWeightusvARB');
+    if not Assigned(glWeightusvARB) then Exit;
+    @glWeightuivARB := SDL_GL_GetProcAddress('glWeightuivARB');
+    if not Assigned(glWeightuivARB) then Exit;
+    @glWeightPointerARB := SDL_GL_GetProcAddress('glWeightPointerARB');
+    if not Assigned(glWeightPointerARB) then Exit;
+    @glVertexBlendARB := SDL_GL_GetProcAddress('glVertexBlendARB');
+    if not Assigned(glVertexBlendARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_vertex_program: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_vertex_program', extstring) then
+  begin
+    @glVertexAttrib1sARB := SDL_GL_GetProcAddress('glVertexAttrib1sARB');
+    if not Assigned(glVertexAttrib1sARB) then Exit;
+    @glVertexAttrib1fARB := SDL_GL_GetProcAddress('glVertexAttrib1fARB');
+    if not Assigned(glVertexAttrib1fARB) then Exit;
+    @glVertexAttrib1dARB := SDL_GL_GetProcAddress('glVertexAttrib1dARB');
+    if not Assigned(glVertexAttrib1dARB) then Exit;
+    @glVertexAttrib2sARB := SDL_GL_GetProcAddress('glVertexAttrib2sARB');
+    if not Assigned(glVertexAttrib2sARB) then Exit;
+    @glVertexAttrib2fARB := SDL_GL_GetProcAddress('glVertexAttrib2fARB');
+    if not Assigned(glVertexAttrib2fARB) then Exit;
+    @glVertexAttrib2dARB := SDL_GL_GetProcAddress('glVertexAttrib2dARB');
+    if not Assigned(glVertexAttrib2dARB) then Exit;
+    @glVertexAttrib3sARB := SDL_GL_GetProcAddress('glVertexAttrib3sARB');
+    if not Assigned(glVertexAttrib3sARB) then Exit;
+    @glVertexAttrib3fARB := SDL_GL_GetProcAddress('glVertexAttrib3fARB');
+    if not Assigned(glVertexAttrib3fARB) then Exit;
+    @glVertexAttrib3dARB := SDL_GL_GetProcAddress('glVertexAttrib3dARB');
+    if not Assigned(glVertexAttrib3dARB) then Exit;
+    @glVertexAttrib4sARB := SDL_GL_GetProcAddress('glVertexAttrib4sARB');
+    if not Assigned(glVertexAttrib4sARB) then Exit;
+    @glVertexAttrib4fARB := SDL_GL_GetProcAddress('glVertexAttrib4fARB');
+    if not Assigned(glVertexAttrib4fARB) then Exit;
+    @glVertexAttrib4dARB := SDL_GL_GetProcAddress('glVertexAttrib4dARB');
+    if not Assigned(glVertexAttrib4dARB) then Exit;
+    @glVertexAttrib4NubARB := SDL_GL_GetProcAddress('glVertexAttrib4NubARB');
+    if not Assigned(glVertexAttrib4NubARB) then Exit;
+    @glVertexAttrib1svARB := SDL_GL_GetProcAddress('glVertexAttrib1svARB');
+    if not Assigned(glVertexAttrib1svARB) then Exit;
+    @glVertexAttrib1fvARB := SDL_GL_GetProcAddress('glVertexAttrib1fvARB');
+    if not Assigned(glVertexAttrib1fvARB) then Exit;
+    @glVertexAttrib1dvARB := SDL_GL_GetProcAddress('glVertexAttrib1dvARB');
+    if not Assigned(glVertexAttrib1dvARB) then Exit;
+    @glVertexAttrib2svARB := SDL_GL_GetProcAddress('glVertexAttrib2svARB');
+    if not Assigned(glVertexAttrib2svARB) then Exit;
+    @glVertexAttrib2fvARB := SDL_GL_GetProcAddress('glVertexAttrib2fvARB');
+    if not Assigned(glVertexAttrib2fvARB) then Exit;
+    @glVertexAttrib2dvARB := SDL_GL_GetProcAddress('glVertexAttrib2dvARB');
+    if not Assigned(glVertexAttrib2dvARB) then Exit;
+    @glVertexAttrib3svARB := SDL_GL_GetProcAddress('glVertexAttrib3svARB');
+    if not Assigned(glVertexAttrib3svARB) then Exit;
+    @glVertexAttrib3fvARB := SDL_GL_GetProcAddress('glVertexAttrib3fvARB');
+    if not Assigned(glVertexAttrib3fvARB) then Exit;
+    @glVertexAttrib3dvARB := SDL_GL_GetProcAddress('glVertexAttrib3dvARB');
+    if not Assigned(glVertexAttrib3dvARB) then Exit;
+    @glVertexAttrib4bvARB := SDL_GL_GetProcAddress('glVertexAttrib4bvARB');
+    if not Assigned(glVertexAttrib4bvARB) then Exit;
+    @glVertexAttrib4svARB := SDL_GL_GetProcAddress('glVertexAttrib4svARB');
+    if not Assigned(glVertexAttrib4svARB) then Exit;
+    @glVertexAttrib4ivARB := SDL_GL_GetProcAddress('glVertexAttrib4ivARB');
+    if not Assigned(glVertexAttrib4ivARB) then Exit;
+    @glVertexAttrib4ubvARB := SDL_GL_GetProcAddress('glVertexAttrib4ubvARB');
+    if not Assigned(glVertexAttrib4ubvARB) then Exit;
+    @glVertexAttrib4usvARB := SDL_GL_GetProcAddress('glVertexAttrib4usvARB');
+    if not Assigned(glVertexAttrib4usvARB) then Exit;
+    @glVertexAttrib4uivARB := SDL_GL_GetProcAddress('glVertexAttrib4uivARB');
+    if not Assigned(glVertexAttrib4uivARB) then Exit;
+    @glVertexAttrib4fvARB := SDL_GL_GetProcAddress('glVertexAttrib4fvARB');
+    if not Assigned(glVertexAttrib4fvARB) then Exit;
+    @glVertexAttrib4dvARB := SDL_GL_GetProcAddress('glVertexAttrib4dvARB');
+    if not Assigned(glVertexAttrib4dvARB) then Exit;
+    @glVertexAttrib4NbvARB := SDL_GL_GetProcAddress('glVertexAttrib4NbvARB');
+    if not Assigned(glVertexAttrib4NbvARB) then Exit;
+    @glVertexAttrib4NsvARB := SDL_GL_GetProcAddress('glVertexAttrib4NsvARB');
+    if not Assigned(glVertexAttrib4NsvARB) then Exit;
+    @glVertexAttrib4NivARB := SDL_GL_GetProcAddress('glVertexAttrib4NivARB');
+    if not Assigned(glVertexAttrib4NivARB) then Exit;
+    @glVertexAttrib4NubvARB := SDL_GL_GetProcAddress('glVertexAttrib4NubvARB');
+    if not Assigned(glVertexAttrib4NubvARB) then Exit;
+    @glVertexAttrib4NusvARB := SDL_GL_GetProcAddress('glVertexAttrib4NusvARB');
+    if not Assigned(glVertexAttrib4NusvARB) then Exit;
+    @glVertexAttrib4NuivARB := SDL_GL_GetProcAddress('glVertexAttrib4NuivARB');
+    if not Assigned(glVertexAttrib4NuivARB) then Exit;
+    @glVertexAttribPointerARB := SDL_GL_GetProcAddress('glVertexAttribPointerARB');
+    if not Assigned(glVertexAttribPointerARB) then Exit;
+    @glEnableVertexAttribArrayARB := SDL_GL_GetProcAddress('glEnableVertexAttribArrayARB');
+    if not Assigned(glEnableVertexAttribArrayARB) then Exit;
+    @glDisableVertexAttribArrayARB := SDL_GL_GetProcAddress('glDisableVertexAttribArrayARB');
+    if not Assigned(glDisableVertexAttribArrayARB) then Exit;
+    @glProgramStringARB := SDL_GL_GetProcAddress('glProgramStringARB');
+    if not Assigned(glProgramStringARB) then Exit;
+    @glBindProgramARB := SDL_GL_GetProcAddress('glBindProgramARB');
+    if not Assigned(glBindProgramARB) then Exit;
+    @glDeleteProgramsARB := SDL_GL_GetProcAddress('glDeleteProgramsARB');
+    if not Assigned(glDeleteProgramsARB) then Exit;
+    @glGenProgramsARB := SDL_GL_GetProcAddress('glGenProgramsARB');
+    if not Assigned(glGenProgramsARB) then Exit;
+    @glProgramEnvParameter4dARB := SDL_GL_GetProcAddress('glProgramEnvParameter4dARB');
+    if not Assigned(glProgramEnvParameter4dARB) then Exit;
+    @glProgramEnvParameter4dvARB := SDL_GL_GetProcAddress('glProgramEnvParameter4dvARB');
+    if not Assigned(glProgramEnvParameter4dvARB) then Exit;
+    @glProgramEnvParameter4fARB := SDL_GL_GetProcAddress('glProgramEnvParameter4fARB');
+    if not Assigned(glProgramEnvParameter4fARB) then Exit;
+    @glProgramEnvParameter4fvARB := SDL_GL_GetProcAddress('glProgramEnvParameter4fvARB');
+    if not Assigned(glProgramEnvParameter4fvARB) then Exit;
+    @glProgramLocalParameter4dARB := SDL_GL_GetProcAddress('glProgramLocalParameter4dARB');
+    if not Assigned(glProgramLocalParameter4dARB) then Exit;
+    @glProgramLocalParameter4dvARB := SDL_GL_GetProcAddress('glProgramLocalParameter4dvARB');
+    if not Assigned(glProgramLocalParameter4dvARB) then Exit;
+    @glProgramLocalParameter4fARB := SDL_GL_GetProcAddress('glProgramLocalParameter4fARB');
+    if not Assigned(glProgramLocalParameter4fARB) then Exit;
+    @glProgramLocalParameter4fvARB := SDL_GL_GetProcAddress('glProgramLocalParameter4fvARB');
+    if not Assigned(glProgramLocalParameter4fvARB) then Exit;
+    @glGetProgramEnvParameterdvARB := SDL_GL_GetProcAddress('glGetProgramEnvParameterdvARB');
+    if not Assigned(glGetProgramEnvParameterdvARB) then Exit;
+    @glGetProgramEnvParameterfvARB := SDL_GL_GetProcAddress('glGetProgramEnvParameterfvARB');
+    if not Assigned(glGetProgramEnvParameterfvARB) then Exit;
+    @glGetProgramLocalParameterdvARB := SDL_GL_GetProcAddress('glGetProgramLocalParameterdvARB');
+    if not Assigned(glGetProgramLocalParameterdvARB) then Exit;
+    @glGetProgramLocalParameterfvARB := SDL_GL_GetProcAddress('glGetProgramLocalParameterfvARB');
+    if not Assigned(glGetProgramLocalParameterfvARB) then Exit;
+    @glGetProgramivARB := SDL_GL_GetProcAddress('glGetProgramivARB');
+    if not Assigned(glGetProgramivARB) then Exit;
+    @glGetProgramStringARB := SDL_GL_GetProcAddress('glGetProgramStringARB');
+    if not Assigned(glGetProgramStringARB) then Exit;
+    @glGetVertexAttribdvARB := SDL_GL_GetProcAddress('glGetVertexAttribdvARB');
+    if not Assigned(glGetVertexAttribdvARB) then Exit;
+    @glGetVertexAttribfvARB := SDL_GL_GetProcAddress('glGetVertexAttribfvARB');
+    if not Assigned(glGetVertexAttribfvARB) then Exit;
+    @glGetVertexAttribivARB := SDL_GL_GetProcAddress('glGetVertexAttribivARB');
+    if not Assigned(glGetVertexAttribivARB) then Exit;
+    @glGetVertexAttribPointervARB := SDL_GL_GetProcAddress('glGetVertexAttribPointervARB');
+    if not Assigned(glGetVertexAttribPointervARB) then Exit;
+    @glIsProgramARB := SDL_GL_GetProcAddress('glIsProgramARB');
+    if not Assigned(glIsProgramARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_window_pos: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_window_pos', extstring) then
+  begin
+    @glWindowPos2dARB := SDL_GL_GetProcAddress('glWindowPos2dARB');
+    if not Assigned(glWindowPos2dARB) then Exit;
+    @glWindowPos2fARB := SDL_GL_GetProcAddress('glWindowPos2fARB');
+    if not Assigned(glWindowPos2fARB) then Exit;
+    @glWindowPos2iARB := SDL_GL_GetProcAddress('glWindowPos2iARB');
+    if not Assigned(glWindowPos2iARB) then Exit;
+    @glWindowPos2sARB := SDL_GL_GetProcAddress('glWindowPos2sARB');
+    if not Assigned(glWindowPos2sARB) then Exit;
+    @glWindowPos2dvARB := SDL_GL_GetProcAddress('glWindowPos2dvARB');
+    if not Assigned(glWindowPos2dvARB) then Exit;
+    @glWindowPos2fvARB := SDL_GL_GetProcAddress('glWindowPos2fvARB');
+    if not Assigned(glWindowPos2fvARB) then Exit;
+    @glWindowPos2ivARB := SDL_GL_GetProcAddress('glWindowPos2ivARB');
+    if not Assigned(glWindowPos2ivARB) then Exit;
+    @glWindowPos2svARB := SDL_GL_GetProcAddress('glWindowPos2svARB');
+    if not Assigned(glWindowPos2svARB) then Exit;
+    @glWindowPos3dARB := SDL_GL_GetProcAddress('glWindowPos3dARB');
+    if not Assigned(glWindowPos3dARB) then Exit;
+    @glWindowPos3fARB := SDL_GL_GetProcAddress('glWindowPos3fARB');
+    if not Assigned(glWindowPos3fARB) then Exit;
+    @glWindowPos3iARB := SDL_GL_GetProcAddress('glWindowPos3iARB');
+    if not Assigned(glWindowPos3iARB) then Exit;
+    @glWindowPos3sARB := SDL_GL_GetProcAddress('glWindowPos3sARB');
+    if not Assigned(glWindowPos3sARB) then Exit;
+    @glWindowPos3dvARB := SDL_GL_GetProcAddress('glWindowPos3dvARB');
+    if not Assigned(glWindowPos3dvARB) then Exit;
+    @glWindowPos3fvARB := SDL_GL_GetProcAddress('glWindowPos3fvARB');
+    if not Assigned(glWindowPos3fvARB) then Exit;
+    @glWindowPos3ivARB := SDL_GL_GetProcAddress('glWindowPos3ivARB');
+    if not Assigned(glWindowPos3ivARB) then Exit;
+    @glWindowPos3svARB := SDL_GL_GetProcAddress('glWindowPos3svARB');
+    if not Assigned(glWindowPos3svARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_422_pixels: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_422_pixels', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_abgr: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_abgr', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_bgra: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_bgra', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_blend_color: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_blend_color', extstring) then
+  begin
+    @glBlendColorEXT := SDL_GL_GetProcAddress('glBlendColorEXT');
+    if not Assigned(glBlendColorEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_blend_func_separate: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_blend_func_separate', extstring) then
+  begin
+    @glBlendFuncSeparateEXT := SDL_GL_GetProcAddress('glBlendFuncSeparateEXT');
+    if not Assigned(glBlendFuncSeparateEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_blend_logic_op: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_blend_logic_op', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_blend_minmax: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_blend_minmax', extstring) then
+  begin
+    @glBlendEquationEXT := SDL_GL_GetProcAddress('glBlendEquationEXT');
+    if not Assigned(glBlendEquationEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_blend_subtract: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_blend_subtract', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_clip_volume_hint: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_clip_volume_hint', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_color_subtable: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_color_subtable', extstring) then
+  begin
+    @glColorSubTableEXT := SDL_GL_GetProcAddress('glColorSubTableEXT');
+    if not Assigned(glColorSubTableEXT) then Exit;
+    @glCopyColorSubTableEXT := SDL_GL_GetProcAddress('glCopyColorSubTableEXT');
+    if not Assigned(glCopyColorSubTableEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_compiled_vertex_array: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_compiled_vertex_array', extstring) then
+  begin
+    @glLockArraysEXT := SDL_GL_GetProcAddress('glLockArraysEXT');
+    if not Assigned(glLockArraysEXT) then Exit;
+    @glUnlockArraysEXT := SDL_GL_GetProcAddress('glUnlockArraysEXT');
+    if not Assigned(glUnlockArraysEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_convolution: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_convolution', extstring) then
+  begin
+    @glConvolutionFilter1DEXT := SDL_GL_GetProcAddress('glConvolutionFilter1DEXT');
+    if not Assigned(glConvolutionFilter1DEXT) then Exit;
+    @glConvolutionFilter2DEXT := SDL_GL_GetProcAddress('glConvolutionFilter2DEXT');
+    if not Assigned(glConvolutionFilter2DEXT) then Exit;
+    @glCopyConvolutionFilter1DEXT := SDL_GL_GetProcAddress('glCopyConvolutionFilter1DEXT');
+    if not Assigned(glCopyConvolutionFilter1DEXT) then Exit;
+    @glCopyConvolutionFilter2DEXT := SDL_GL_GetProcAddress('glCopyConvolutionFilter2DEXT');
+    if not Assigned(glCopyConvolutionFilter2DEXT) then Exit;
+    @glGetConvolutionFilterEXT := SDL_GL_GetProcAddress('glGetConvolutionFilterEXT');
+    if not Assigned(glGetConvolutionFilterEXT) then Exit;
+    @glSeparableFilter2DEXT := SDL_GL_GetProcAddress('glSeparableFilter2DEXT');
+    if not Assigned(glSeparableFilter2DEXT) then Exit;
+    @glGetSeparableFilterEXT := SDL_GL_GetProcAddress('glGetSeparableFilterEXT');
+    if not Assigned(glGetSeparableFilterEXT) then Exit;
+    @glConvolutionParameteriEXT := SDL_GL_GetProcAddress('glConvolutionParameteriEXT');
+    if not Assigned(glConvolutionParameteriEXT) then Exit;
+    @glConvolutionParameterivEXT := SDL_GL_GetProcAddress('glConvolutionParameterivEXT');
+    if not Assigned(glConvolutionParameterivEXT) then Exit;
+    @glConvolutionParameterfEXT := SDL_GL_GetProcAddress('glConvolutionParameterfEXT');
+    if not Assigned(glConvolutionParameterfEXT) then Exit;
+    @glConvolutionParameterfvEXT := SDL_GL_GetProcAddress('glConvolutionParameterfvEXT');
+    if not Assigned(glConvolutionParameterfvEXT) then Exit;
+    @glGetConvolutionParameterivEXT := SDL_GL_GetProcAddress('glGetConvolutionParameterivEXT');
+    if not Assigned(glGetConvolutionParameterivEXT) then Exit;
+    @glGetConvolutionParameterfvEXT := SDL_GL_GetProcAddress('glGetConvolutionParameterfvEXT');
+    if not Assigned(glGetConvolutionParameterfvEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_histogram: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_histogram', extstring) then
+  begin
+    @glHistogramEXT := SDL_GL_GetProcAddress('glHistogramEXT');
+    if not Assigned(glHistogramEXT) then Exit;
+    @glResetHistogramEXT := SDL_GL_GetProcAddress('glResetHistogramEXT');
+    if not Assigned(glResetHistogramEXT) then Exit;
+    @glGetHistogramEXT := SDL_GL_GetProcAddress('glGetHistogramEXT');
+    if not Assigned(glGetHistogramEXT) then Exit;
+    @glGetHistogramParameterivEXT := SDL_GL_GetProcAddress('glGetHistogramParameterivEXT');
+    if not Assigned(glGetHistogramParameterivEXT) then Exit;
+    @glGetHistogramParameterfvEXT := SDL_GL_GetProcAddress('glGetHistogramParameterfvEXT');
+    if not Assigned(glGetHistogramParameterfvEXT) then Exit;
+    @glMinmaxEXT := SDL_GL_GetProcAddress('glMinmaxEXT');
+    if not Assigned(glMinmaxEXT) then Exit;
+    @glResetMinmaxEXT := SDL_GL_GetProcAddress('glResetMinmaxEXT');
+    if not Assigned(glResetMinmaxEXT) then Exit;
+    @glGetMinmaxEXT := SDL_GL_GetProcAddress('glGetMinmaxEXT');
+    if not Assigned(glGetMinmaxEXT) then Exit;
+    @glGetMinmaxParameterivEXT := SDL_GL_GetProcAddress('glGetMinmaxParameterivEXT');
+    if not Assigned(glGetMinmaxParameterivEXT) then Exit;
+    @glGetMinmaxParameterfvEXT := SDL_GL_GetProcAddress('glGetMinmaxParameterfvEXT');
+    if not Assigned(glGetMinmaxParameterfvEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_multi_draw_arrays: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_multi_draw_arrays', extstring) then
+  begin
+    @glMultiDrawArraysEXT := SDL_GL_GetProcAddress('glMultiDrawArraysEXT');
+    if not Assigned(glMultiDrawArraysEXT) then Exit;
+    @glMultiDrawElementsEXT := SDL_GL_GetProcAddress('glMultiDrawElementsEXT');
+    if not Assigned(glMultiDrawElementsEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_packed_pixels: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_packed_pixels', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_paletted_texture: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_paletted_texture', extstring) then
+  begin
+    @glColorTableEXT := SDL_GL_GetProcAddress('glColorTableEXT');
+    if not Assigned(glColorTableEXT) then Exit;
+    @glColorSubTableEXT := SDL_GL_GetProcAddress('glColorSubTableEXT');
+    if not Assigned(glColorSubTableEXT) then Exit;
+    @glGetColorTableEXT := SDL_GL_GetProcAddress('glGetColorTableEXT');
+    if not Assigned(glGetColorTableEXT) then Exit;
+    @glGetColorTableParameterivEXT := SDL_GL_GetProcAddress('glGetColorTableParameterivEXT');
+    if not Assigned(glGetColorTableParameterivEXT) then Exit;
+    @glGetColorTableParameterfvEXT := SDL_GL_GetProcAddress('glGetColorTableParameterfvEXT');
+    if not Assigned(glGetColorTableParameterfvEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_point_parameters: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_point_parameters', extstring) then
+  begin
+    @glPointParameterfEXT := SDL_GL_GetProcAddress('glPointParameterfEXT');
+    if not Assigned(glPointParameterfEXT) then Exit;
+    @glPointParameterfvEXT := SDL_GL_GetProcAddress('glPointParameterfvEXT');
+    if not Assigned(glPointParameterfvEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_polygon_offset: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_polygon_offset', extstring) then
+  begin
+    @glPolygonOffsetEXT := SDL_GL_GetProcAddress('glPolygonOffsetEXT');
+    if not Assigned(glPolygonOffsetEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_separate_specular_color: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_separate_specular_color', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_shadow_funcs: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_shadow_funcs', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_shared_texture_palette: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_shared_texture_palette', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_stencil_two_side: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_stencil_two_side', extstring) then
+  begin
+    @glActiveStencilFaceEXT := SDL_GL_GetProcAddress('glActiveStencilFaceEXT');
+    if not Assigned(glActiveStencilFaceEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_stencil_wrap: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_stencil_wrap', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_subtexture: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_subtexture', extstring) then
+  begin
+    @glTexSubImage1DEXT := SDL_GL_GetProcAddress('glTexSubImage1DEXT');
+    if not Assigned(glTexSubImage1DEXT) then Exit;
+    @glTexSubImage2DEXT := SDL_GL_GetProcAddress('glTexSubImage2DEXT');
+    if not Assigned(glTexSubImage2DEXT) then Exit;
+    @glTexSubImage3DEXT := SDL_GL_GetProcAddress('glTexSubImage3DEXT');
+    if not Assigned(glTexSubImage3DEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture3D: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture3D', extstring) then
+  begin
+    glTexImage3DEXT := SDL_GL_GetProcAddress('glTexImage3DEXT');
+    if not Assigned(glTexImage3DEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_compression_s3tc: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture_compression_s3tc', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_env_add: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture_env_add', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_env_combine: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture_env_combine', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_env_dot3: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture_env_dot3', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_filter_anisotropic: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture_filter_anisotropic', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_lod_bias: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture_lod_bias', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_object: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture_object', extstring) then
+  begin
+    @glGenTexturesEXT := SDL_GL_GetProcAddress('glGenTexturesEXT');
+    if not Assigned(glGenTexturesEXT) then Exit;
+    @glDeleteTexturesEXT := SDL_GL_GetProcAddress('glDeleteTexturesEXT');
+    if not Assigned(glDeleteTexturesEXT) then Exit;
+    @glBindTextureEXT := SDL_GL_GetProcAddress('glBindTextureEXT');
+    if not Assigned(glBindTextureEXT) then Exit;
+    @glPrioritizeTexturesEXT := SDL_GL_GetProcAddress('glPrioritizeTexturesEXT');
+    if not Assigned(glPrioritizeTexturesEXT) then Exit;
+    @glAreTexturesResidentEXT := SDL_GL_GetProcAddress('glAreTexturesResidentEXT');
+    if not Assigned(glAreTexturesResidentEXT) then Exit;
+    @glIsTextureEXT := SDL_GL_GetProcAddress('glIsTextureEXT');
+    if not Assigned(glIsTextureEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_vertex_array: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_vertex_array', extstring) then
+  begin
+    @glArrayElementEXT := SDL_GL_GetProcAddress('glArrayElementEXT');
+    if not Assigned(glArrayElementEXT) then Exit;
+    @glDrawArraysEXT := SDL_GL_GetProcAddress('glDrawArraysEXT');
+    if not Assigned(glDrawArraysEXT) then Exit;
+    @glVertexPointerEXT := SDL_GL_GetProcAddress('glVertexPointerEXT');
+    if not Assigned(glVertexPointerEXT) then Exit;
+    @glNormalPointerEXT := SDL_GL_GetProcAddress('glNormalPointerEXT');
+    if not Assigned(glNormalPointerEXT) then Exit;
+    @glColorPointerEXT := SDL_GL_GetProcAddress('glColorPointerEXT');
+    if not Assigned(glColorPointerEXT) then Exit;
+    @glIndexPointerEXT := SDL_GL_GetProcAddress('glIndexPointerEXT');
+    if not Assigned(glIndexPointerEXT) then Exit;
+    @glTexCoordPointerEXT := SDL_GL_GetProcAddress('glTexCoordPointerEXT');
+    if not Assigned(glTexCoordPointerEXT) then Exit;
+    @glEdgeFlagPointerEXT := SDL_GL_GetProcAddress('glEdgeFlagPointerEXT');
+    if not Assigned(glEdgeFlagPointerEXT) then Exit;
+    @glGetPointervEXT := SDL_GL_GetProcAddress('glGetPointervEXT');
+    if not Assigned(glGetPointervEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_vertex_shader: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_vertex_shader', extstring) then
+  begin
+    @glBeginVertexShaderEXT := SDL_GL_GetProcAddress('glBeginVertexShaderEXT');
+    if not Assigned(glBeginVertexShaderEXT) then Exit;
+    @glEndVertexShaderEXT := SDL_GL_GetProcAddress('glEndVertexShaderEXT');
+    if not Assigned(glEndVertexShaderEXT) then Exit;
+    @glBindVertexShaderEXT := SDL_GL_GetProcAddress('glBindVertexShaderEXT');
+    if not Assigned(glBindVertexShaderEXT) then Exit;
+    @glGenVertexShadersEXT := SDL_GL_GetProcAddress('glGenVertexShadersEXT');
+    if not Assigned(glGenVertexShadersEXT) then Exit;
+    @glDeleteVertexShaderEXT := SDL_GL_GetProcAddress('glDeleteVertexShaderEXT');
+    if not Assigned(glDeleteVertexShaderEXT) then Exit;
+    @glShaderOp1EXT := SDL_GL_GetProcAddress('glShaderOp1EXT');
+    if not Assigned(glShaderOp1EXT) then Exit;
+    @glShaderOp2EXT := SDL_GL_GetProcAddress('glShaderOp2EXT');
+    if not Assigned(glShaderOp2EXT) then Exit;
+    @glShaderOp3EXT := SDL_GL_GetProcAddress('glShaderOp3EXT');
+    if not Assigned(glShaderOp3EXT) then Exit;
+    @glSwizzleEXT := SDL_GL_GetProcAddress('glSwizzleEXT');
+    if not Assigned(glSwizzleEXT) then Exit;
+    @glWriteMaskEXT := SDL_GL_GetProcAddress('glWriteMaskEXT');
+    if not Assigned(glWriteMaskEXT) then Exit;
+    @glInsertComponentEXT := SDL_GL_GetProcAddress('glInsertComponentEXT');
+    if not Assigned(glInsertComponentEXT) then Exit;
+    @glExtractComponentEXT := SDL_GL_GetProcAddress('glExtractComponentEXT');
+    if not Assigned(glExtractComponentEXT) then Exit;
+    @glGenSymbolsEXT := SDL_GL_GetProcAddress('glGenSymbolsEXT');
+    if not Assigned(glGenSymbolsEXT) then Exit;
+    @glSetInvariantEXT := SDL_GL_GetProcAddress('glSetInvariantEXT');
+    if not Assigned(glSetInvariantEXT) then Exit;
+    @glSetLocalConstantEXT := SDL_GL_GetProcAddress('glSetLocalConstantEXT');
+    if not Assigned(glSetLocalConstantEXT) then Exit;
+    @glVariantbvEXT := SDL_GL_GetProcAddress('glVariantbvEXT');
+    if not Assigned(glVariantbvEXT) then Exit;
+    @glVariantsvEXT := SDL_GL_GetProcAddress('glVariantsvEXT');
+    if not Assigned(glVariantsvEXT) then Exit;
+    @glVariantivEXT := SDL_GL_GetProcAddress('glVariantivEXT');
+    if not Assigned(glVariantivEXT) then Exit;
+    @glVariantfvEXT := SDL_GL_GetProcAddress('glVariantfvEXT');
+    if not Assigned(glVariantfvEXT) then Exit;
+    @glVariantdvEXT := SDL_GL_GetProcAddress('glVariantdvEXT');
+    if not Assigned(glVariantdvEXT) then Exit;
+    @glVariantubvEXT := SDL_GL_GetProcAddress('glVariantubvEXT');
+    if not Assigned(glVariantubvEXT) then Exit;
+    @glVariantusvEXT := SDL_GL_GetProcAddress('glVariantusvEXT');
+    if not Assigned(glVariantusvEXT) then Exit;
+    @glVariantuivEXT := SDL_GL_GetProcAddress('glVariantuivEXT');
+    if not Assigned(glVariantuivEXT) then Exit;
+    @glVariantPointerEXT := SDL_GL_GetProcAddress('glVariantPointerEXT');
+    if not Assigned(glVariantPointerEXT) then Exit;
+    @glEnableVariantClientStateEXT := SDL_GL_GetProcAddress('glEnableVariantClientStateEXT');
+    if not Assigned(glEnableVariantClientStateEXT) then Exit;
+    @glDisableVariantClientStateEXT := SDL_GL_GetProcAddress('glDisableVariantClientStateEXT');
+    if not Assigned(glDisableVariantClientStateEXT) then Exit;
+    @glBindLightParameterEXT := SDL_GL_GetProcAddress('glBindLightParameterEXT');
+    if not Assigned(glBindLightParameterEXT) then Exit;
+    @glBindMaterialParameterEXT := SDL_GL_GetProcAddress('glBindMaterialParameterEXT');
+    if not Assigned(glBindMaterialParameterEXT) then Exit;
+    @glBindTexGenParameterEXT := SDL_GL_GetProcAddress('glBindTexGenParameterEXT');
+    if not Assigned(glBindTexGenParameterEXT) then Exit;
+    @glBindTextureUnitParameterEXT := SDL_GL_GetProcAddress('glBindTextureUnitParameterEXT');
+    if not Assigned(glBindTextureUnitParameterEXT) then Exit;
+    @glBindParameterEXT := SDL_GL_GetProcAddress('glBindParameterEXT');
+    if not Assigned(glBindParameterEXT) then Exit;
+    @glIsVariantEnabledEXT := SDL_GL_GetProcAddress('glIsVariantEnabledEXT');
+    if not Assigned(glIsVariantEnabledEXT) then Exit;
+    @glGetVariantBooleanvEXT := SDL_GL_GetProcAddress('glGetVariantBooleanvEXT');
+    if not Assigned(glGetVariantBooleanvEXT) then Exit;
+    @glGetVariantIntegervEXT := SDL_GL_GetProcAddress('glGetVariantIntegervEXT');
+    if not Assigned(glGetVariantIntegervEXT) then Exit;
+    @glGetVariantFloatvEXT := SDL_GL_GetProcAddress('glGetVariantFloatvEXT');
+    if not Assigned(glGetVariantFloatvEXT) then Exit;
+    @glGetVariantPointervEXT := SDL_GL_GetProcAddress('glGetVariantPointervEXT');
+    if not Assigned(glGetVariantPointervEXT) then Exit;
+    @glGetInvariantBooleanvEXT := SDL_GL_GetProcAddress('glGetInvariantBooleanvEXT');
+    if not Assigned(glGetInvariantBooleanvEXT) then Exit;
+    @glGetInvariantIntegervEXT := SDL_GL_GetProcAddress('glGetInvariantIntegervEXT');
+    if not Assigned(glGetInvariantIntegervEXT) then Exit;
+    @glGetInvariantFloatvEXT := SDL_GL_GetProcAddress('glGetInvariantFloatvEXT');
+    if not Assigned(glGetInvariantFloatvEXT) then Exit;
+    @glGetLocalConstantBooleanvEXT := SDL_GL_GetProcAddress('glGetLocalConstantBooleanvEXT');
+    if not Assigned(glGetLocalConstantBooleanvEXT) then Exit;
+    @glGetLocalConstantIntegervEXT := SDL_GL_GetProcAddress('glGetLocalConstantIntegervEXT');
+    if not Assigned(glGetLocalConstantIntegervEXT) then Exit;
+    @glGetLocalConstantFloatvEXT := SDL_GL_GetProcAddress('glGetLocalConstantFloatvEXT');
+    if not Assigned(glGetLocalConstantFloatvEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_vertex_weighting: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_vertex_weighting', extstring) then
+  begin
+    @glVertexWeightfEXT := SDL_GL_GetProcAddress('glVertexWeightfEXT');
+    if not Assigned(glVertexWeightfEXT) then Exit;
+    @glVertexWeightfvEXT := SDL_GL_GetProcAddress('glVertexWeightfvEXT');
+    if not Assigned(glVertexWeightfvEXT) then Exit;
+    @glVertexWeightPointerEXT := SDL_GL_GetProcAddress('glVertexWeightPointerEXT');
+    if not Assigned(glVertexWeightPointerEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_HP_occlusion_test: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_HP_occlusion_test', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_blend_square: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_blend_square', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_copy_depth_to_color: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_copy_depth_to_color', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_depth_clamp: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_depth_clamp', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_evaluators: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_evaluators', extstring) then
+  begin
+    @glMapControlPointsNV := SDL_GL_GetProcAddress('glMapControlPointsNV');
+    if not Assigned(glMapControlPointsNV) then Exit;
+    @glMapParameterivNV := SDL_GL_GetProcAddress('glMapParameterivNV');
+    if not Assigned(glMapParameterivNV) then Exit;
+    @glMapParameterfvNV := SDL_GL_GetProcAddress('glMapParameterfvNV');
+    if not Assigned(glMapParameterfvNV) then Exit;
+    @glGetMapControlPointsNV := SDL_GL_GetProcAddress('glGetMapControlPointsNV');
+    if not Assigned(glGetMapControlPointsNV) then Exit;
+    @glGetMapParameterivNV := SDL_GL_GetProcAddress('glGetMapParameterivNV');
+    if not Assigned(glGetMapParameterivNV) then Exit;
+    @glGetMapParameterfvNV := SDL_GL_GetProcAddress('glGetMapParameterfvNV');
+    if not Assigned(glGetMapParameterfvNV) then Exit;
+    @glGetMapAttribParameterivNV := SDL_GL_GetProcAddress('glGetMapAttribParameterivNV');
+    if not Assigned(glGetMapAttribParameterivNV) then Exit;
+    @glGetMapAttribParameterfvNV := SDL_GL_GetProcAddress('glGetMapAttribParameterfvNV');
+    if not Assigned(glGetMapAttribParameterfvNV) then Exit;
+    @glEvalMapsNV := SDL_GL_GetProcAddress('glEvalMapsNV');
+    if not Assigned(glEvalMapsNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_fence: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_fence', extstring) then
+  begin
+    @glGenFencesNV := SDL_GL_GetProcAddress('glGenFencesNV');
+    if not Assigned(glGenFencesNV) then Exit;
+    @glDeleteFencesNV := SDL_GL_GetProcAddress('glDeleteFencesNV');
+    if not Assigned(glDeleteFencesNV) then Exit;
+    @glSetFenceNV := SDL_GL_GetProcAddress('glSetFenceNV');
+    if not Assigned(glSetFenceNV) then Exit;
+    @glTestFenceNV := SDL_GL_GetProcAddress('glTestFenceNV');
+    if not Assigned(glTestFenceNV) then Exit;
+    @glFinishFenceNV := SDL_GL_GetProcAddress('glFinishFenceNV');
+    if not Assigned(glFinishFenceNV) then Exit;
+    @glIsFenceNV := SDL_GL_GetProcAddress('glIsFenceNV');
+    if not Assigned(glIsFenceNV) then Exit;
+    @glGetFenceivNV := SDL_GL_GetProcAddress('glGetFenceivNV');
+    if not Assigned(glGetFenceivNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_fog_distance: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_fog_distance', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_light_max_exponent: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_light_max_exponent', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_multisample_filter_hint: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_multisample_filter_hint', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_occlusion_query: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_occlusion_query', extstring) then
+  begin
+    @glGenOcclusionQueriesNV := SDL_GL_GetProcAddress('glGenOcclusionQueriesNV');
+    if not Assigned(glGenOcclusionQueriesNV) then Exit;
+    @glDeleteOcclusionQueriesNV := SDL_GL_GetProcAddress('glDeleteOcclusionQueriesNV');
+    if not Assigned(glDeleteOcclusionQueriesNV) then Exit;
+    @glIsOcclusionQueryNV := SDL_GL_GetProcAddress('glIsOcclusionQueryNV');
+    if not Assigned(glIsOcclusionQueryNV) then Exit;
+    @glBeginOcclusionQueryNV := SDL_GL_GetProcAddress('glBeginOcclusionQueryNV');
+    if not Assigned(glBeginOcclusionQueryNV) then Exit;
+    @glEndOcclusionQueryNV := SDL_GL_GetProcAddress('glEndOcclusionQueryNV');
+    if not Assigned(glEndOcclusionQueryNV) then Exit;
+    @glGetOcclusionQueryivNV := SDL_GL_GetProcAddress('glGetOcclusionQueryivNV');
+    if not Assigned(glGetOcclusionQueryivNV) then Exit;
+    @glGetOcclusionQueryuivNV := SDL_GL_GetProcAddress('glGetOcclusionQueryuivNV');
+    if not Assigned(glGetOcclusionQueryuivNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_packed_depth_stencil: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_packed_depth_stencil', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_point_sprite: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_point_sprite', extstring) then
+  begin
+    @glPointParameteriNV := SDL_GL_GetProcAddress('glPointParameteriNV');
+    if not Assigned(glPointParameteriNV) then Exit;
+    @glPointParameterivNV := SDL_GL_GetProcAddress('glPointParameterivNV');
+    if not Assigned(glPointParameterivNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_register_combiners: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_register_combiners', extstring) then
+  begin
+    @glCombinerParameterfvNV := SDL_GL_GetProcAddress('glCombinerParameterfvNV');
+    if not Assigned(glCombinerParameterfvNV) then Exit;
+    @glCombinerParameterivNV := SDL_GL_GetProcAddress('glCombinerParameterivNV');
+    if not Assigned(glCombinerParameterivNV) then Exit;
+    @glCombinerParameterfNV := SDL_GL_GetProcAddress('glCombinerParameterfNV');
+    if not Assigned(glCombinerParameterfNV) then Exit;
+    @glCombinerParameteriNV := SDL_GL_GetProcAddress('glCombinerParameteriNV');
+    if not Assigned(glCombinerParameteriNV) then Exit;
+    @glCombinerInputNV := SDL_GL_GetProcAddress('glCombinerInputNV');
+    if not Assigned(glCombinerInputNV) then Exit;
+    @glCombinerOutputNV := SDL_GL_GetProcAddress('glCombinerOutputNV');
+    if not Assigned(glCombinerOutputNV) then Exit;
+    @glFinalCombinerInputNV := SDL_GL_GetProcAddress('glFinalCombinerInputNV');
+    if not Assigned(glFinalCombinerInputNV) then Exit;
+    @glGetCombinerInputParameterfvNV := SDL_GL_GetProcAddress('glGetCombinerInputParameterfvNV');
+    if not Assigned(glGetCombinerInputParameterfvNV) then Exit;
+    @glGetCombinerInputParameterivNV := SDL_GL_GetProcAddress('glGetCombinerInputParameterivNV');
+    if not Assigned(glGetCombinerInputParameterivNV) then Exit;
+    @glGetCombinerOutputParameterfvNV := SDL_GL_GetProcAddress('glGetCombinerOutputParameterfvNV');
+    if not Assigned(glGetCombinerOutputParameterfvNV) then Exit;
+    @glGetCombinerOutputParameterivNV := SDL_GL_GetProcAddress('glGetCombinerOutputParameterivNV');
+    if not Assigned(glGetCombinerOutputParameterivNV) then Exit;
+    @glGetFinalCombinerInputParameterfvNV := SDL_GL_GetProcAddress('glGetFinalCombinerInputParameterfvNV');
+    if not Assigned(glGetFinalCombinerInputParameterfvNV) then Exit;
+    @glGetFinalCombinerInputParameterivNV := SDL_GL_GetProcAddress('glGetFinalCombinerInputParameterivNV');
+    if not Assigned(glGetFinalCombinerInputParameterivNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_register_combiners2: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_register_combiners2', extstring) then
+  begin
+    @glCombinerStageParameterfvNV := SDL_GL_GetProcAddress('glCombinerStageParameterfvNV');
+    if not Assigned(glCombinerStageParameterfvNV) then Exit;
+    @glGetCombinerStageParameterfvNV := SDL_GL_GetProcAddress('glGetCombinerStageParameterfvNV');
+    if not Assigned(glGetCombinerStageParameterfvNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_texgen_emboss: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_texgen_emboss', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_texgen_reflection: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_texgen_reflection', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_texture_compression_vtc: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_texture_compression_vtc', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_texture_env_combine4: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_texture_env_combine4', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_texture_rectangle: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_texture_rectangle', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_texture_shader: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_texture_shader', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_texture_shader2: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_texture_shader2', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_texture_shader3: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_texture_shader3', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_vertex_array_range: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_vertex_array_range', extstring) then
+  begin
+    @glVertexArrayRangeNV := SDL_GL_GetProcAddress('glVertexArrayRangeNV');
+    if not Assigned(glVertexArrayRangeNV) then Exit;
+    @glFlushVertexArrayRangeNV := SDL_GL_GetProcAddress('glFlushVertexArrayRangeNV');
+    if not Assigned(glFlushVertexArrayRangeNV) then Exit;
+    {$IFDEF WINDOWS}
+    @wglAllocateMemoryNV := SDL_GL_GetProcAddress('wglAllocateMemoryNV');
+    if not Assigned(wglAllocateMemoryNV) then Exit;
+    @wglFreeMemoryNV := SDL_GL_GetProcAddress('wglFreeMemoryNV');
+    if not Assigned(wglFreeMemoryNV) then Exit;
+    {$ENDIF}
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_vertex_array_range2: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_vertex_array_range2', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_vertex_program: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_vertex_program', extstring) then
+  begin
+    @glBindProgramNV := SDL_GL_GetProcAddress('glBindProgramNV');
+    if not Assigned(glBindProgramNV) then Exit;
+    @glDeleteProgramsNV := SDL_GL_GetProcAddress('glDeleteProgramsNV');
+    if not Assigned(glDeleteProgramsNV) then Exit;
+    @glExecuteProgramNV := SDL_GL_GetProcAddress('glExecuteProgramNV');
+    if not Assigned(glExecuteProgramNV) then Exit;
+    @glGenProgramsNV := SDL_GL_GetProcAddress('glGenProgramsNV');
+    if not Assigned(glGenProgramsNV) then Exit;
+    @glAreProgramsResidentNV := SDL_GL_GetProcAddress('glAreProgramsResidentNV');
+    if not Assigned(glAreProgramsResidentNV) then Exit;
+    @glRequestResidentProgramsNV := SDL_GL_GetProcAddress('glRequestResidentProgramsNV');
+    if not Assigned(glRequestResidentProgramsNV) then Exit;
+    @glGetProgramParameterfvNV := SDL_GL_GetProcAddress('glGetProgramParameterfvNV');
+    if not Assigned(glGetProgramParameterfvNV) then Exit;
+    @glGetProgramParameterdvNV := SDL_GL_GetProcAddress('glGetProgramParameterdvNV');
+    if not Assigned(glGetProgramParameterdvNV) then Exit;
+    @glGetProgramivNV := SDL_GL_GetProcAddress('glGetProgramivNV');
+    if not Assigned(glGetProgramivNV) then Exit;
+    @glGetProgramStringNV := SDL_GL_GetProcAddress('glGetProgramStringNV');
+    if not Assigned(glGetProgramStringNV) then Exit;
+    @glGetTrackMatrixivNV := SDL_GL_GetProcAddress('glGetTrackMatrixivNV');
+    if not Assigned(glGetTrackMatrixivNV) then Exit;
+    @glGetVertexAttribdvNV := SDL_GL_GetProcAddress('glGetVertexAttribdvNV');
+    if not Assigned(glGetVertexAttribdvNV) then Exit;
+    @glGetVertexAttribfvNV := SDL_GL_GetProcAddress('glGetVertexAttribfvNV');
+    if not Assigned(glGetVertexAttribfvNV) then Exit;
+    @glGetVertexAttribivNV := SDL_GL_GetProcAddress('glGetVertexAttribivNV');
+    if not Assigned(glGetVertexAttribivNV) then Exit;
+    @glGetVertexAttribPointervNV := SDL_GL_GetProcAddress('glGetVertexAttribPointervNV');
+    if not Assigned(glGetVertexAttribPointervNV) then Exit;
+    @glIsProgramNV := SDL_GL_GetProcAddress('glIsProgramNV');
+    if not Assigned(glIsProgramNV) then Exit;
+    @glLoadProgramNV := SDL_GL_GetProcAddress('glLoadProgramNV');
+    if not Assigned(glLoadProgramNV) then Exit;
+    @glProgramParameter4fNV := SDL_GL_GetProcAddress('glProgramParameter4fNV');
+    if not Assigned(glProgramParameter4fNV) then Exit;
+    @glProgramParameter4fvNV := SDL_GL_GetProcAddress('glProgramParameter4fvNV');
+    if not Assigned(glProgramParameter4fvNV) then Exit;
+    @glProgramParameters4dvNV := SDL_GL_GetProcAddress('glProgramParameters4dvNV');
+    if not Assigned(glProgramParameters4dvNV) then Exit;
+    @glProgramParameters4fvNV := SDL_GL_GetProcAddress('glProgramParameters4fvNV');
+    if not Assigned(glProgramParameters4fvNV) then Exit;
+    @glTrackMatrixNV := SDL_GL_GetProcAddress('glTrackMatrixNV');
+    if not Assigned(glTrackMatrixNV) then Exit;
+    @glVertexAttribPointerNV := SDL_GL_GetProcAddress('glVertexAttribPointerNV');
+    if not Assigned(glVertexAttribPointerNV) then Exit;
+    @glVertexAttrib1sNV := SDL_GL_GetProcAddress('glVertexAttrib1sNV');
+    if not Assigned(glVertexAttrib1sNV) then Exit;
+    @glVertexAttrib1fNV := SDL_GL_GetProcAddress('glVertexAttrib1fNV');
+    if not Assigned(glVertexAttrib1fNV) then Exit;
+    @glVertexAttrib1dNV := SDL_GL_GetProcAddress('glVertexAttrib1dNV');
+    if not Assigned(glVertexAttrib1dNV) then Exit;
+    @glVertexAttrib2sNV := SDL_GL_GetProcAddress('glVertexAttrib2sNV');
+    if not Assigned(glVertexAttrib2sNV) then Exit;
+    @glVertexAttrib2fNV := SDL_GL_GetProcAddress('glVertexAttrib2fNV');
+    if not Assigned(glVertexAttrib2fNV) then Exit;
+    @glVertexAttrib2dNV := SDL_GL_GetProcAddress('glVertexAttrib2dNV');
+    if not Assigned(glVertexAttrib2dNV) then Exit;
+    @glVertexAttrib3sNV := SDL_GL_GetProcAddress('glVertexAttrib3sNV');
+    if not Assigned(glVertexAttrib3sNV) then Exit;
+    @glVertexAttrib3fNV := SDL_GL_GetProcAddress('glVertexAttrib3fNV');
+    if not Assigned(glVertexAttrib3fNV) then Exit;
+    @glVertexAttrib3dNV := SDL_GL_GetProcAddress('glVertexAttrib3dNV');
+    if not Assigned(glVertexAttrib3dNV) then Exit;
+    @glVertexAttrib4sNV := SDL_GL_GetProcAddress('glVertexAttrib4sNV');
+    if not Assigned(glVertexAttrib4sNV) then Exit;
+    @glVertexAttrib4fNV := SDL_GL_GetProcAddress('glVertexAttrib4fNV');
+    if not Assigned(glVertexAttrib4fNV) then Exit;
+    @glVertexAttrib4dNV := SDL_GL_GetProcAddress('glVertexAttrib4dNV');
+    if not Assigned(glVertexAttrib4dNV) then Exit;
+    @glVertexAttrib4ubNV := SDL_GL_GetProcAddress('glVertexAttrib4ubNV');
+    if not Assigned(glVertexAttrib4ubNV) then Exit;
+    @glVertexAttrib1svNV := SDL_GL_GetProcAddress('glVertexAttrib1svNV');
+    if not Assigned(glVertexAttrib1svNV) then Exit;
+    @glVertexAttrib1fvNV := SDL_GL_GetProcAddress('glVertexAttrib1fvNV');
+    if not Assigned(glVertexAttrib1fvNV) then Exit;
+    @glVertexAttrib1dvNV := SDL_GL_GetProcAddress('glVertexAttrib1dvNV');
+    if not Assigned(glVertexAttrib1dvNV) then Exit;
+    @glVertexAttrib2svNV := SDL_GL_GetProcAddress('glVertexAttrib2svNV');
+    if not Assigned(glVertexAttrib2svNV) then Exit;
+    @glVertexAttrib2fvNV := SDL_GL_GetProcAddress('glVertexAttrib2fvNV');
+    if not Assigned(glVertexAttrib2fvNV) then Exit;
+    @glVertexAttrib2dvNV := SDL_GL_GetProcAddress('glVertexAttrib2dvNV');
+    if not Assigned(glVertexAttrib2dvNV) then Exit;
+    @glVertexAttrib3svNV := SDL_GL_GetProcAddress('glVertexAttrib3svNV');
+    if not Assigned(glVertexAttrib3svNV) then Exit;
+    @glVertexAttrib3fvNV := SDL_GL_GetProcAddress('glVertexAttrib3fvNV');
+    if not Assigned(glVertexAttrib3fvNV) then Exit;
+    @glVertexAttrib3dvNV := SDL_GL_GetProcAddress('glVertexAttrib3dvNV');
+    if not Assigned(glVertexAttrib3dvNV) then Exit;
+    @glVertexAttrib4svNV := SDL_GL_GetProcAddress('glVertexAttrib4svNV');
+    if not Assigned(glVertexAttrib4svNV) then Exit;
+    @glVertexAttrib4fvNV := SDL_GL_GetProcAddress('glVertexAttrib4fvNV');
+    if not Assigned(glVertexAttrib4fvNV) then Exit;
+    @glVertexAttrib4dvNV := SDL_GL_GetProcAddress('glVertexAttrib4dvNV');
+    if not Assigned(glVertexAttrib4dvNV) then Exit;
+    @glVertexAttrib4ubvNV := SDL_GL_GetProcAddress('glVertexAttrib4ubvNV');
+    if not Assigned(glVertexAttrib4ubvNV) then Exit;
+    @glVertexAttribs1svNV := SDL_GL_GetProcAddress('glVertexAttribs1svNV');
+    if not Assigned(glVertexAttribs1svNV) then Exit;
+    @glVertexAttribs1fvNV := SDL_GL_GetProcAddress('glVertexAttribs1fvNV');
+    if not Assigned(glVertexAttribs1fvNV) then Exit;
+    @glVertexAttribs1dvNV := SDL_GL_GetProcAddress('glVertexAttribs1dvNV');
+    if not Assigned(glVertexAttribs1dvNV) then Exit;
+    @glVertexAttribs2svNV := SDL_GL_GetProcAddress('glVertexAttribs2svNV');
+    if not Assigned(glVertexAttribs2svNV) then Exit;
+    @glVertexAttribs2fvNV := SDL_GL_GetProcAddress('glVertexAttribs2fvNV');
+    if not Assigned(glVertexAttribs2fvNV) then Exit;
+    @glVertexAttribs2dvNV := SDL_GL_GetProcAddress('glVertexAttribs2dvNV');
+    if not Assigned(glVertexAttribs2dvNV) then Exit;
+    @glVertexAttribs3svNV := SDL_GL_GetProcAddress('glVertexAttribs3svNV');
+    if not Assigned(glVertexAttribs3svNV) then Exit;
+    @glVertexAttribs3fvNV := SDL_GL_GetProcAddress('glVertexAttribs3fvNV');
+    if not Assigned(glVertexAttribs3fvNV) then Exit;
+    @glVertexAttribs3dvNV := SDL_GL_GetProcAddress('glVertexAttribs3dvNV');
+    if not Assigned(glVertexAttribs3dvNV) then Exit;
+    @glVertexAttribs4svNV := SDL_GL_GetProcAddress('glVertexAttribs4svNV');
+    if not Assigned(glVertexAttribs4svNV) then Exit;
+    @glVertexAttribs4fvNV := SDL_GL_GetProcAddress('glVertexAttribs4fvNV');
+    if not Assigned(glVertexAttribs4fvNV) then Exit;
+    @glVertexAttribs4dvNV := SDL_GL_GetProcAddress('glVertexAttribs4dvNV');
+    if not Assigned(glVertexAttribs4dvNV) then Exit;
+    @glVertexAttribs4ubvNV := SDL_GL_GetProcAddress('glVertexAttribs4ubvNV');
+    if not Assigned(glVertexAttribs4ubvNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_vertex_program1_1: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_vertex_program1_1', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_element_array: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_element_array', extstring) then
+  begin
+    @glElementPointerATI := SDL_GL_GetProcAddress('glElementPointerATI');
+    if not Assigned(glElementPointerATI) then Exit;
+    @glDrawElementArrayATI := SDL_GL_GetProcAddress('glDrawElementArrayATI');
+    if not Assigned(glDrawElementArrayATI) then Exit;
+    @glDrawRangeElementArrayATI := SDL_GL_GetProcAddress('glDrawRangeElementArrayATI');
+    if not Assigned(glDrawRangeElementArrayATI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_envmap_bumpmap: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_envmap_bumpmap', extstring) then
+  begin
+    @glTexBumpParameterivATI := SDL_GL_GetProcAddress('glTexBumpParameterivATI');
+    if not Assigned(glTexBumpParameterivATI) then Exit;
+    @glTexBumpParameterfvATI := SDL_GL_GetProcAddress('glTexBumpParameterfvATI');
+    if not Assigned(glTexBumpParameterfvATI) then Exit;
+    @glGetTexBumpParameterivATI := SDL_GL_GetProcAddress('glGetTexBumpParameterivATI');
+    if not Assigned(glGetTexBumpParameterivATI) then Exit;
+    @glGetTexBumpParameterfvATI := SDL_GL_GetProcAddress('glGetTexBumpParameterfvATI');
+    if not Assigned(glGetTexBumpParameterfvATI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_fragment_shader: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_fragment_shader', extstring) then
+  begin
+    @glGenFragmentShadersATI := SDL_GL_GetProcAddress('glGenFragmentShadersATI');
+    if not Assigned(glGenFragmentShadersATI) then Exit;
+    @glBindFragmentShaderATI := SDL_GL_GetProcAddress('glBindFragmentShaderATI');
+    if not Assigned(glBindFragmentShaderATI) then Exit;
+    @glDeleteFragmentShaderATI := SDL_GL_GetProcAddress('glDeleteFragmentShaderATI');
+    if not Assigned(glDeleteFragmentShaderATI) then Exit;
+    @glBeginFragmentShaderATI := SDL_GL_GetProcAddress('glBeginFragmentShaderATI');
+    if not Assigned(glBeginFragmentShaderATI) then Exit;
+    @glEndFragmentShaderATI := SDL_GL_GetProcAddress('glEndFragmentShaderATI');
+    if not Assigned(glEndFragmentShaderATI) then Exit;
+    @glPassTexCoordATI := SDL_GL_GetProcAddress('glPassTexCoordATI');
+    if not Assigned(glPassTexCoordATI) then Exit;
+    @glSampleMapATI := SDL_GL_GetProcAddress('glSampleMapATI');
+    if not Assigned(glSampleMapATI) then Exit;
+    @glColorFragmentOp1ATI := SDL_GL_GetProcAddress('glColorFragmentOp1ATI');
+    if not Assigned(glColorFragmentOp1ATI) then Exit;
+    @glColorFragmentOp2ATI := SDL_GL_GetProcAddress('glColorFragmentOp2ATI');
+    if not Assigned(glColorFragmentOp2ATI) then Exit;
+    @glColorFragmentOp3ATI := SDL_GL_GetProcAddress('glColorFragmentOp3ATI');
+    if not Assigned(glColorFragmentOp3ATI) then Exit;
+    @glAlphaFragmentOp1ATI := SDL_GL_GetProcAddress('glAlphaFragmentOp1ATI');
+    if not Assigned(glAlphaFragmentOp1ATI) then Exit;
+    @glAlphaFragmentOp2ATI := SDL_GL_GetProcAddress('glAlphaFragmentOp2ATI');
+    if not Assigned(glAlphaFragmentOp2ATI) then Exit;
+    @glAlphaFragmentOp3ATI := SDL_GL_GetProcAddress('glAlphaFragmentOp3ATI');
+    if not Assigned(glAlphaFragmentOp3ATI) then Exit;
+    @glSetFragmentShaderConstantATI := SDL_GL_GetProcAddress('glSetFragmentShaderConstantATI');
+    if not Assigned(glSetFragmentShaderConstantATI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_pn_triangles: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_pn_triangles', extstring) then
+  begin
+    @glPNTrianglesiATI := SDL_GL_GetProcAddress('glPNTrianglesiATI');
+    if not Assigned(glPNTrianglesiATI) then Exit;
+    @glPNTrianglesfATI := SDL_GL_GetProcAddress('glPNTrianglesfATI');
+    if not Assigned(glPNTrianglesfATI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_texture_mirror_once: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_texture_mirror_once', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_vertex_array_object: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_vertex_array_object', extstring) then
+  begin
+    @glNewObjectBufferATI := SDL_GL_GetProcAddress('glNewObjectBufferATI');
+    if not Assigned(glNewObjectBufferATI) then Exit;
+    @glIsObjectBufferATI := SDL_GL_GetProcAddress('glIsObjectBufferATI');
+    if not Assigned(glIsObjectBufferATI) then Exit;
+    @glUpdateObjectBufferATI := SDL_GL_GetProcAddress('glUpdateObjectBufferATI');
+    if not Assigned(glUpdateObjectBufferATI) then Exit;
+    @glGetObjectBufferfvATI := SDL_GL_GetProcAddress('glGetObjectBufferfvATI');
+    if not Assigned(glGetObjectBufferfvATI) then Exit;
+    @glGetObjectBufferivATI := SDL_GL_GetProcAddress('glGetObjectBufferivATI');
+    if not Assigned(glGetObjectBufferivATI) then Exit;
+    @glDeleteObjectBufferATI := SDL_GL_GetProcAddress('glDeleteObjectBufferATI');
+    if not Assigned(glDeleteObjectBufferATI) then Exit;
+    @glArrayObjectATI := SDL_GL_GetProcAddress('glArrayObjectATI');
+    if not Assigned(glArrayObjectATI) then Exit;
+    @glGetArrayObjectfvATI := SDL_GL_GetProcAddress('glGetArrayObjectfvATI');
+    if not Assigned(glGetArrayObjectfvATI) then Exit;
+    @glGetArrayObjectivATI := SDL_GL_GetProcAddress('glGetArrayObjectivATI');
+    if not Assigned(glGetArrayObjectivATI) then Exit;
+    @glVariantArrayObjectATI := SDL_GL_GetProcAddress('glVariantArrayObjectATI');
+    if not Assigned(glVariantArrayObjectATI) then Exit;
+    @glGetVariantArrayObjectfvATI := SDL_GL_GetProcAddress('glGetVariantArrayObjectfvATI');
+    if not Assigned(glGetVariantArrayObjectfvATI) then Exit;
+    @glGetVariantArrayObjectivATI := SDL_GL_GetProcAddress('glGetVariantArrayObjectivATI');
+    if not Assigned(glGetVariantArrayObjectivATI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_vertex_streams: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_vertex_streams', extstring) then
+  begin
+    @glVertexStream1s := SDL_GL_GetProcAddress('glVertexStream1s');
+    if not Assigned(glVertexStream1s) then Exit;
+    @glVertexStream1i := SDL_GL_GetProcAddress('glVertexStream1i');
+    if not Assigned(glVertexStream1i) then Exit;
+    @glVertexStream1f := SDL_GL_GetProcAddress('glVertexStream1f');
+    if not Assigned(glVertexStream1f) then Exit;
+    @glVertexStream1d := SDL_GL_GetProcAddress('glVertexStream1d');
+    if not Assigned(glVertexStream1d) then Exit;
+    @glVertexStream1sv := SDL_GL_GetProcAddress('glVertexStream1sv');
+    if not Assigned(glVertexStream1sv) then Exit;
+    @glVertexStream1iv := SDL_GL_GetProcAddress('glVertexStream1iv');
+    if not Assigned(glVertexStream1iv) then Exit;
+    @glVertexStream1fv := SDL_GL_GetProcAddress('glVertexStream1fv');
+    if not Assigned(glVertexStream1fv) then Exit;
+    @glVertexStream1dv := SDL_GL_GetProcAddress('glVertexStream1dv');
+    if not Assigned(glVertexStream1dv) then Exit;
+    @glVertexStream2s := SDL_GL_GetProcAddress('glVertexStream2s');
+    if not Assigned(glVertexStream2s) then Exit;
+    @glVertexStream2i := SDL_GL_GetProcAddress('glVertexStream2i');
+    if not Assigned(glVertexStream2i) then Exit;
+    @glVertexStream2f := SDL_GL_GetProcAddress('glVertexStream2f');
+    if not Assigned(glVertexStream2f) then Exit;
+    @glVertexStream2d := SDL_GL_GetProcAddress('glVertexStream2d');
+    if not Assigned(glVertexStream2d) then Exit;
+    @glVertexStream2sv := SDL_GL_GetProcAddress('glVertexStream2sv');
+    if not Assigned(glVertexStream2sv) then Exit;
+    @glVertexStream2iv := SDL_GL_GetProcAddress('glVertexStream2iv');
+    if not Assigned(glVertexStream2iv) then Exit;
+    @glVertexStream2fv := SDL_GL_GetProcAddress('glVertexStream2fv');
+    if not Assigned(glVertexStream2fv) then Exit;
+    @glVertexStream2dv := SDL_GL_GetProcAddress('glVertexStream2dv');
+    if not Assigned(glVertexStream2dv) then Exit;
+    @glVertexStream3s := SDL_GL_GetProcAddress('glVertexStream3s');
+    if not Assigned(glVertexStream3s) then Exit;
+    @glVertexStream3i := SDL_GL_GetProcAddress('glVertexStream3i');
+    if not Assigned(glVertexStream3i) then Exit;
+    @glVertexStream3f := SDL_GL_GetProcAddress('glVertexStream3f');
+    if not Assigned(glVertexStream3f) then Exit;
+    @glVertexStream3d := SDL_GL_GetProcAddress('glVertexStream3d');
+    if not Assigned(glVertexStream3d) then Exit;
+    @glVertexStream3sv := SDL_GL_GetProcAddress('glVertexStream3sv');
+    if not Assigned(glVertexStream3sv) then Exit;
+    @glVertexStream3iv := SDL_GL_GetProcAddress('glVertexStream3iv');
+    if not Assigned(glVertexStream3iv) then Exit;
+    @glVertexStream3fv := SDL_GL_GetProcAddress('glVertexStream3fv');
+    if not Assigned(glVertexStream3fv) then Exit;
+    @glVertexStream3dv := SDL_GL_GetProcAddress('glVertexStream3dv');
+    if not Assigned(glVertexStream3dv) then Exit;
+    @glVertexStream4s := SDL_GL_GetProcAddress('glVertexStream4s');
+    if not Assigned(glVertexStream4s) then Exit;
+    @glVertexStream4i := SDL_GL_GetProcAddress('glVertexStream4i');
+    if not Assigned(glVertexStream4i) then Exit;
+    @glVertexStream4f := SDL_GL_GetProcAddress('glVertexStream4f');
+    if not Assigned(glVertexStream4f) then Exit;
+    @glVertexStream4d := SDL_GL_GetProcAddress('glVertexStream4d');
+    if not Assigned(glVertexStream4d) then Exit;
+    @glVertexStream4sv := SDL_GL_GetProcAddress('glVertexStream4sv');
+    if not Assigned(glVertexStream4sv) then Exit;
+    @glVertexStream4iv := SDL_GL_GetProcAddress('glVertexStream4iv');
+    if not Assigned(glVertexStream4iv) then Exit;
+    @glVertexStream4fv := SDL_GL_GetProcAddress('glVertexStream4fv');
+    if not Assigned(glVertexStream4fv) then Exit;
+    @glVertexStream4dv := SDL_GL_GetProcAddress('glVertexStream4dv');
+    if not Assigned(glVertexStream4dv) then Exit;
+    @glNormalStream3b := SDL_GL_GetProcAddress('glNormalStream3b');
+    if not Assigned(glNormalStream3b) then Exit;
+    @glNormalStream3s := SDL_GL_GetProcAddress('glNormalStream3s');
+    if not Assigned(glNormalStream3s) then Exit;
+    @glNormalStream3i := SDL_GL_GetProcAddress('glNormalStream3i');
+    if not Assigned(glNormalStream3i) then Exit;
+    @glNormalStream3f := SDL_GL_GetProcAddress('glNormalStream3f');
+    if not Assigned(glNormalStream3f) then Exit;
+    @glNormalStream3d := SDL_GL_GetProcAddress('glNormalStream3d');
+    if not Assigned(glNormalStream3d) then Exit;
+    @glNormalStream3bv := SDL_GL_GetProcAddress('glNormalStream3bv');
+    if not Assigned(glNormalStream3bv) then Exit;
+    @glNormalStream3sv := SDL_GL_GetProcAddress('glNormalStream3sv');
+    if not Assigned(glNormalStream3sv) then Exit;
+    @glNormalStream3iv := SDL_GL_GetProcAddress('glNormalStream3iv');
+    if not Assigned(glNormalStream3iv) then Exit;
+    @glNormalStream3fv := SDL_GL_GetProcAddress('glNormalStream3fv');
+    if not Assigned(glNormalStream3fv) then Exit;
+    @glNormalStream3dv := SDL_GL_GetProcAddress('glNormalStream3dv');
+    if not Assigned(glNormalStream3dv) then Exit;
+    @glClientActiveVertexStream := SDL_GL_GetProcAddress('glClientActiveVertexStream');
+    if not Assigned(glClientActiveVertexStream) then Exit;
+    @glVertexBlendEnvi := SDL_GL_GetProcAddress('glVertexBlendEnvi');
+    if not Assigned(glVertexBlendEnvi) then Exit;
+    @glVertexBlendEnvf := SDL_GL_GetProcAddress('glVertexBlendEnvf');
+    if not Assigned(glVertexBlendEnvf) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+{$IFDEF WINDOWS}
+function Load_WGL_I3D_image_buffer: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_I3D_image_buffer', extstring) then
+  begin
+    @wglCreateImageBufferI3D := SDL_GL_GetProcAddress('wglCreateImageBufferI3D');
+    if not Assigned(wglCreateImageBufferI3D) then Exit;
+    @wglDestroyImageBufferI3D := SDL_GL_GetProcAddress('wglDestroyImageBufferI3D');
+    if not Assigned(wglDestroyImageBufferI3D) then Exit;
+    @wglAssociateImageBufferEventsI3D := SDL_GL_GetProcAddress('wglAssociateImageBufferEventsI3D');
+    if not Assigned(wglAssociateImageBufferEventsI3D) then Exit;
+    @wglReleaseImageBufferEventsI3D := SDL_GL_GetProcAddress('wglReleaseImageBufferEventsI3D');
+    if not Assigned(wglReleaseImageBufferEventsI3D) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_I3D_swap_frame_lock: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_I3D_swap_frame_lock', extstring) then
+  begin
+    @wglEnableFrameLockI3D := SDL_GL_GetProcAddress('wglEnableFrameLockI3D');
+    if not Assigned(wglEnableFrameLockI3D) then Exit;
+    @wglDisableFrameLockI3D := SDL_GL_GetProcAddress('wglDisableFrameLockI3D');
+    if not Assigned(wglDisableFrameLockI3D) then Exit;
+    @wglIsEnabledFrameLockI3D := SDL_GL_GetProcAddress('wglIsEnabledFrameLockI3D');
+    if not Assigned(wglIsEnabledFrameLockI3D) then Exit;
+    @wglQueryFrameLockMasterI3D := SDL_GL_GetProcAddress('wglQueryFrameLockMasterI3D');
+    if not Assigned(wglQueryFrameLockMasterI3D) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_I3D_swap_frame_usage: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_I3D_swap_frame_usage', extstring) then
+  begin
+    @wglGetFrameUsageI3D := SDL_GL_GetProcAddress('wglGetFrameUsageI3D');
+    if not Assigned(wglGetFrameUsageI3D) then Exit;
+    @wglBeginFrameTrackingI3D := SDL_GL_GetProcAddress('wglBeginFrameTrackingI3D');
+    if not Assigned(wglBeginFrameTrackingI3D) then Exit;
+    @wglEndFrameTrackingI3D := SDL_GL_GetProcAddress('wglEndFrameTrackingI3D');
+    if not Assigned(wglEndFrameTrackingI3D) then Exit;
+    @wglQueryFrameTrackingI3D := SDL_GL_GetProcAddress('wglQueryFrameTrackingI3D');
+    if not Assigned(wglQueryFrameTrackingI3D) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+{$ENDIF}
+
+function Load_GL_3DFX_texture_compression_FXT1: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_3DFX_texture_compression_FXT1', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_IBM_cull_vertex: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_IBM_cull_vertex', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_IBM_multimode_draw_arrays: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_IBM_multimode_draw_arrays', extstring) then
+  begin
+    @glMultiModeDrawArraysIBM := SDL_GL_GetProcAddress('glMultiModeDrawArraysIBM');
+    if not Assigned(glMultiModeDrawArraysIBM) then Exit;
+    @glMultiModeDrawElementsIBM := SDL_GL_GetProcAddress('glMultiModeDrawElementsIBM');
+    if not Assigned(glMultiModeDrawElementsIBM) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_IBM_raster_pos_clip: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_IBM_raster_pos_clip', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_IBM_texture_mirrored_repeat: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_IBM_texture_mirrored_repeat', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_IBM_vertex_array_lists: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_IBM_vertex_array_lists', extstring) then
+  begin
+    @glColorPointerListIBM := SDL_GL_GetProcAddress('glColorPointerListIBM');
+    if not Assigned(glColorPointerListIBM) then Exit;
+    @glSecondaryColorPointerListIBM := SDL_GL_GetProcAddress('glSecondaryColorPointerListIBM');
+    if not Assigned(glSecondaryColorPointerListIBM) then Exit;
+    @glEdgeFlagPointerListIBM := SDL_GL_GetProcAddress('glEdgeFlagPointerListIBM');
+    if not Assigned(glEdgeFlagPointerListIBM) then Exit;
+    @glFogCoordPointerListIBM := SDL_GL_GetProcAddress('glFogCoordPointerListIBM');
+    if not Assigned(glFogCoordPointerListIBM) then Exit;
+    @glNormalPointerListIBM := SDL_GL_GetProcAddress('glNormalPointerListIBM');
+    if not Assigned(glNormalPointerListIBM) then Exit;
+    @glTexCoordPointerListIBM := SDL_GL_GetProcAddress('glTexCoordPointerListIBM');
+    if not Assigned(glTexCoordPointerListIBM) then Exit;
+    @glVertexPointerListIBM := SDL_GL_GetProcAddress('glVertexPointerListIBM');
+    if not Assigned(glVertexPointerListIBM) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_MESA_resize_buffers: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_MESA_resize_buffers', extstring) then
+  begin
+    @glResizeBuffersMESA := SDL_GL_GetProcAddress('glResizeBuffersMESA');
+    if not Assigned(glResizeBuffersMESA) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_MESA_window_pos: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_MESA_window_pos', extstring) then
+  begin
+    @glWindowPos2dMESA := SDL_GL_GetProcAddress('glWindowPos2dMESA');
+    if not Assigned(glWindowPos2dMESA) then Exit;
+    @glWindowPos2fMESA := SDL_GL_GetProcAddress('glWindowPos2fMESA');
+    if not Assigned(glWindowPos2fMESA) then Exit;
+    @glWindowPos2iMESA := SDL_GL_GetProcAddress('glWindowPos2iMESA');
+    if not Assigned(glWindowPos2iMESA) then Exit;
+    @glWindowPos2sMESA := SDL_GL_GetProcAddress('glWindowPos2sMESA');
+    if not Assigned(glWindowPos2sMESA) then Exit;
+    @glWindowPos2ivMESA := SDL_GL_GetProcAddress('glWindowPos2ivMESA');
+    if not Assigned(glWindowPos2ivMESA) then Exit;
+    @glWindowPos2svMESA := SDL_GL_GetProcAddress('glWindowPos2svMESA');
+    if not Assigned(glWindowPos2svMESA) then Exit;
+    @glWindowPos2fvMESA := SDL_GL_GetProcAddress('glWindowPos2fvMESA');
+    if not Assigned(glWindowPos2fvMESA) then Exit;
+    @glWindowPos2dvMESA := SDL_GL_GetProcAddress('glWindowPos2dvMESA');
+    if not Assigned(glWindowPos2dvMESA) then Exit;
+    @glWindowPos3iMESA := SDL_GL_GetProcAddress('glWindowPos3iMESA');
+    if not Assigned(glWindowPos3iMESA) then Exit;
+    @glWindowPos3sMESA := SDL_GL_GetProcAddress('glWindowPos3sMESA');
+    if not Assigned(glWindowPos3sMESA) then Exit;
+    @glWindowPos3fMESA := SDL_GL_GetProcAddress('glWindowPos3fMESA');
+    if not Assigned(glWindowPos3fMESA) then Exit;
+    @glWindowPos3dMESA := SDL_GL_GetProcAddress('glWindowPos3dMESA');
+    if not Assigned(glWindowPos3dMESA) then Exit;
+    @glWindowPos3ivMESA := SDL_GL_GetProcAddress('glWindowPos3ivMESA');
+    if not Assigned(glWindowPos3ivMESA) then Exit;
+    @glWindowPos3svMESA := SDL_GL_GetProcAddress('glWindowPos3svMESA');
+    if not Assigned(glWindowPos3svMESA) then Exit;
+    @glWindowPos3fvMESA := SDL_GL_GetProcAddress('glWindowPos3fvMESA');
+    if not Assigned(glWindowPos3fvMESA) then Exit;
+    @glWindowPos3dvMESA := SDL_GL_GetProcAddress('glWindowPos3dvMESA');
+    if not Assigned(glWindowPos3dvMESA) then Exit;
+    @glWindowPos4iMESA := SDL_GL_GetProcAddress('glWindowPos4iMESA');
+    if not Assigned(glWindowPos4iMESA) then Exit;
+    @glWindowPos4sMESA := SDL_GL_GetProcAddress('glWindowPos4sMESA');
+    if not Assigned(glWindowPos4sMESA) then Exit;
+    @glWindowPos4fMESA := SDL_GL_GetProcAddress('glWindowPos4fMESA');
+    if not Assigned(glWindowPos4fMESA) then Exit;
+    @glWindowPos4dMESA := SDL_GL_GetProcAddress('glWindowPos4dMESA');
+    if not Assigned(glWindowPos4dMESA) then Exit;
+    @glWindowPos4ivMESA := SDL_GL_GetProcAddress('glWindowPos4ivMESA');
+    if not Assigned(glWindowPos4ivMESA) then Exit;
+    @glWindowPos4svMESA := SDL_GL_GetProcAddress('glWindowPos4svMESA');
+    if not Assigned(glWindowPos4svMESA) then Exit;
+    @glWindowPos4fvMESA := SDL_GL_GetProcAddress('glWindowPos4fvMESA');
+    if not Assigned(glWindowPos4fvMESA) then Exit;
+    @glWindowPos4dvMESA := SDL_GL_GetProcAddress('glWindowPos4dvMESA');
+    if not Assigned(glWindowPos4dvMESA) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_OML_interlace: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_OML_interlace', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_OML_resample: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_OML_resample', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_OML_subsample: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_OML_subsample', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIS_generate_mipmap: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIS_generate_mipmap', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIS_multisample: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIS_multisample', extstring) then
+  begin
+    @glSampleMaskSGIS := SDL_GL_GetProcAddress('glSampleMaskSGIS');
+    if not Assigned(glSampleMaskSGIS) then Exit;
+    @glSamplePatternSGIS := SDL_GL_GetProcAddress('glSamplePatternSGIS');
+    if not Assigned(glSamplePatternSGIS) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIS_pixel_texture: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIS_pixel_texture', extstring) then
+  begin
+    @glPixelTexGenParameteriSGIS := SDL_GL_GetProcAddress('glPixelTexGenParameteriSGIS');
+    if not Assigned(glPixelTexGenParameteriSGIS) then Exit;
+    @glPixelTexGenParameterfSGIS := SDL_GL_GetProcAddress('glPixelTexGenParameterfSGIS');
+    if not Assigned(glPixelTexGenParameterfSGIS) then Exit;
+    @glGetPixelTexGenParameterivSGIS := SDL_GL_GetProcAddress('glGetPixelTexGenParameterivSGIS');
+    if not Assigned(glGetPixelTexGenParameterivSGIS) then Exit;
+    @glGetPixelTexGenParameterfvSGIS := SDL_GL_GetProcAddress('glGetPixelTexGenParameterfvSGIS');
+    if not Assigned(glGetPixelTexGenParameterfvSGIS) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIS_texture_border_clamp: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIS_texture_border_clamp', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIS_texture_color_mask: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIS_texture_color_mask', extstring) then
+  begin
+    @glTextureColorMaskSGIS := SDL_GL_GetProcAddress('glTextureColorMaskSGIS');
+    if not Assigned(glTextureColorMaskSGIS) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIS_texture_edge_clamp: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIS_texture_edge_clamp', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIS_texture_lod: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIS_texture_lod', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIS_depth_texture: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIS_depth_texture', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIX_fog_offset: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIX_fog_offset', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIX_interlace: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIX_interlace', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGIX_shadow_ambient: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGIX_shadow_ambient', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGI_color_matrix: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGI_color_matrix', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGI_color_table: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGI_color_table', extstring) then
+  begin
+    @glColorTableSGI := SDL_GL_GetProcAddress('glColorTableSGI');
+    if not Assigned(glColorTableSGI) then Exit;
+    @glCopyColorTableSGI := SDL_GL_GetProcAddress('glCopyColorTableSGI');
+    if not Assigned(glCopyColorTableSGI) then Exit;
+    @glColorTableParameterivSGI := SDL_GL_GetProcAddress('glColorTableParameterivSGI');
+    if not Assigned(glColorTableParameterivSGI) then Exit;
+    @glColorTableParameterfvSGI := SDL_GL_GetProcAddress('glColorTableParameterfvSGI');
+    if not Assigned(glColorTableParameterfvSGI) then Exit;
+    @glGetColorTableSGI := SDL_GL_GetProcAddress('glGetColorTableSGI');
+    if not Assigned(glGetColorTableSGI) then Exit;
+    @glGetColorTableParameterivSGI := SDL_GL_GetProcAddress('glGetColorTableParameterivSGI');
+    if not Assigned(glGetColorTableParameterivSGI) then Exit;
+    @glGetColorTableParameterfvSGI := SDL_GL_GetProcAddress('glGetColorTableParameterfvSGI');
+    if not Assigned(glGetColorTableParameterfvSGI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SGI_texture_color_table: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SGI_texture_color_table', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_SUN_vertex: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_SUN_vertex', extstring) then
+  begin
+    @glColor4ubVertex2fSUN := SDL_GL_GetProcAddress('glColor4ubVertex2fSUN');
+    if not Assigned(glColor4ubVertex2fSUN) then Exit;
+    @glColor4ubVertex2fvSUN := SDL_GL_GetProcAddress('glColor4ubVertex2fvSUN');
+    if not Assigned(glColor4ubVertex2fvSUN) then Exit;
+    @glColor4ubVertex3fSUN := SDL_GL_GetProcAddress('glColor4ubVertex3fSUN');
+    if not Assigned(glColor4ubVertex3fSUN) then Exit;
+    @glColor4ubVertex3fvSUN := SDL_GL_GetProcAddress('glColor4ubVertex3fvSUN');
+    if not Assigned(glColor4ubVertex3fvSUN) then Exit;
+    @glColor3fVertex3fSUN := SDL_GL_GetProcAddress('glColor3fVertex3fSUN');
+    if not Assigned(glColor3fVertex3fSUN) then Exit;
+    @glColor3fVertex3fvSUN := SDL_GL_GetProcAddress('glColor3fVertex3fvSUN');
+    if not Assigned(glColor3fVertex3fvSUN) then Exit;
+    @glNormal3fVertex3fSUN := SDL_GL_GetProcAddress('glNormal3fVertex3fSUN');
+    if not Assigned(glNormal3fVertex3fSUN) then Exit;
+    @glNormal3fVertex3fvSUN := SDL_GL_GetProcAddress('glNormal3fVertex3fvSUN');
+    if not Assigned(glNormal3fVertex3fvSUN) then Exit;
+    @glColor4fNormal3fVertex3fSUN := SDL_GL_GetProcAddress('glColor4fNormal3fVertex3fSUN');
+    if not Assigned(glColor4fNormal3fVertex3fSUN) then Exit;
+    @glColor4fNormal3fVertex3fvSUN := SDL_GL_GetProcAddress('glColor4fNormal3fVertex3fvSUN');
+    if not Assigned(glColor4fNormal3fVertex3fvSUN) then Exit;
+    @glTexCoord2fVertex3fSUN := SDL_GL_GetProcAddress('glTexCoord2fVertex3fSUN');
+    if not Assigned(glTexCoord2fVertex3fSUN) then Exit;
+    @glTexCoord2fVertex3fvSUN := SDL_GL_GetProcAddress('glTexCoord2fVertex3fvSUN');
+    if not Assigned(glTexCoord2fVertex3fvSUN) then Exit;
+    @glTexCoord4fVertex4fSUN := SDL_GL_GetProcAddress('glTexCoord4fVertex4fSUN');
+    if not Assigned(glTexCoord4fVertex4fSUN) then Exit;
+    @glTexCoord4fVertex4fvSUN := SDL_GL_GetProcAddress('glTexCoord4fVertex4fvSUN');
+    if not Assigned(glTexCoord4fVertex4fvSUN) then Exit;
+    @glTexCoord2fColor4ubVertex3fSUN := SDL_GL_GetProcAddress('glTexCoord2fColor4ubVertex3fSUN');
+    if not Assigned(glTexCoord2fColor4ubVertex3fSUN) then Exit;
+    @glTexCoord2fColor4ubVertex3fvSUN := SDL_GL_GetProcAddress('glTexCoord2fColor4ubVertex3fvSUN');
+    if not Assigned(glTexCoord2fColor4ubVertex3fvSUN) then Exit;
+    @glTexCoord2fColor3fVertex3fSUN := SDL_GL_GetProcAddress('glTexCoord2fColor3fVertex3fSUN');
+    if not Assigned(glTexCoord2fColor3fVertex3fSUN) then Exit;
+    @glTexCoord2fColor3fVertex3fvSUN := SDL_GL_GetProcAddress('glTexCoord2fColor3fVertex3fvSUN');
+    if not Assigned(glTexCoord2fColor3fVertex3fvSUN) then Exit;
+    @glTexCoord2fNormal3fVertex3fSUN := SDL_GL_GetProcAddress('glTexCoord2fNormal3fVertex3fSUN');
+    if not Assigned(glTexCoord2fNormal3fVertex3fSUN) then Exit;
+    @glTexCoord2fNormal3fVertex3fvSUN := SDL_GL_GetProcAddress('glTexCoord2fNormal3fVertex3fvSUN');
+    if not Assigned(glTexCoord2fNormal3fVertex3fvSUN) then Exit;
+    @glTexCoord2fColor4fNormal3fVertex3fSUN := SDL_GL_GetProcAddress('glTexCoord2fColor4fNormal3fVertex3fSUN');
+    if not Assigned(glTexCoord2fColor4fNormal3fVertex3fSUN) then Exit;
+    @glTexCoord2fColor4fNormal3fVertex3fvSUN := SDL_GL_GetProcAddress('glTexCoord2fColor4fNormal3fVertex3fvSUN');
+    if not Assigned(glTexCoord2fColor4fNormal3fVertex3fvSUN) then Exit;
+    @glTexCoord4fColor4fNormal3fVertex4fSUN := SDL_GL_GetProcAddress('glTexCoord4fColor4fNormal3fVertex4fSUN');
+    if not Assigned(glTexCoord4fColor4fNormal3fVertex4fSUN) then Exit;
+    @glTexCoord4fColor4fNormal3fVertex4fvSUN := SDL_GL_GetProcAddress('glTexCoord4fColor4fNormal3fVertex4fvSUN');
+    if not Assigned(glTexCoord4fColor4fNormal3fVertex4fvSUN) then Exit;
+    @glReplacementCodeuiVertex3fSUN := SDL_GL_GetProcAddress('glReplacementCodeuiVertex3fSUN');
+    if not Assigned(glReplacementCodeuiVertex3fSUN) then Exit;
+    @glReplacementCodeuiVertex3fvSUN := SDL_GL_GetProcAddress('glReplacementCodeuiVertex3fvSUN');
+    if not Assigned(glReplacementCodeuiVertex3fvSUN) then Exit;
+    @glReplacementCodeuiColor4ubVertex3fSUN := SDL_GL_GetProcAddress('glReplacementCodeuiColor4ubVertex3fSUN');
+    if not Assigned(glReplacementCodeuiColor4ubVertex3fSUN) then Exit;
+    @glReplacementCodeuiColor4ubVertex3fvSUN := SDL_GL_GetProcAddress('glReplacementCodeuiColor4ubVertex3fvSUN');
+    if not Assigned(glReplacementCodeuiColor4ubVertex3fvSUN) then Exit;
+    @glReplacementCodeuiColor3fVertex3fSUN := SDL_GL_GetProcAddress('glReplacementCodeuiColor3fVertex3fSUN');
+    if not Assigned(glReplacementCodeuiColor3fVertex3fSUN) then Exit;
+    @glReplacementCodeuiColor3fVertex3fvSUN := SDL_GL_GetProcAddress('glReplacementCodeuiColor3fVertex3fvSUN');
+    if not Assigned(glReplacementCodeuiColor3fVertex3fvSUN) then Exit;
+    @glReplacementCodeuiNormal3fVertex3fSUN := SDL_GL_GetProcAddress('glReplacementCodeuiNormal3fVertex3fSUN');
+    if not Assigned(glReplacementCodeuiNormal3fVertex3fSUN) then Exit;
+    @glReplacementCodeuiNormal3fVertex3fvSUN := SDL_GL_GetProcAddress('glReplacementCodeuiNormal3fVertex3fvSUN');
+    if not Assigned(glReplacementCodeuiNormal3fVertex3fvSUN) then Exit;
+    @glReplacementCodeuiColor4fNormal3fVertex3fSUN := SDL_GL_GetProcAddress('glReplacementCodeuiColor4fNormal3fVertex3fSUN');
+    if not Assigned(glReplacementCodeuiColor4fNormal3fVertex3fSUN) then Exit;
+    @glReplacementCodeuiColor4fNormal3fVertex3fvSUN := SDL_GL_GetProcAddress('glReplacementCodeuiColor4fNormal3fVertex3fvSUN');
+    if not Assigned(glReplacementCodeuiColor4fNormal3fVertex3fvSUN) then Exit;
+    @glReplacementCodeuiTexCoord2fVertex3fSUN := SDL_GL_GetProcAddress('glReplacementCodeuiTexCoord2fVertex3fSUN');
+    if not Assigned(glReplacementCodeuiTexCoord2fVertex3fSUN) then Exit;
+    @glReplacementCodeuiTexCoord2fVertex3fvSUN := SDL_GL_GetProcAddress('glReplacementCodeuiTexCoord2fVertex3fvSUN');
+    if not Assigned(glReplacementCodeuiTexCoord2fVertex3fvSUN) then Exit;
+    @glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN := SDL_GL_GetProcAddress('glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN');
+    if not Assigned(glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) then Exit;
+    @glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN := SDL_GL_GetProcAddress('glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN');
+    if not Assigned(glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) then Exit;
+    @glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN := SDL_GL_GetProcAddress('glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN');
+    if not Assigned(glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) then Exit;
+    @glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN := SDL_GL_GetProcAddress('glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN');
+    if not Assigned(glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_fragment_program: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_fragment_program', extstring) then
+  begin
+    @glProgramStringARB := SDL_GL_GetProcAddress('glProgramStringARB');
+    if not Assigned(glProgramStringARB) then Exit;
+    @glBindProgramARB := SDL_GL_GetProcAddress('glBindProgramARB');
+    if not Assigned(glBindProgramARB) then Exit;
+    @glDeleteProgramsARB := SDL_GL_GetProcAddress('glDeleteProgramsARB');
+    if not Assigned(glDeleteProgramsARB) then Exit;
+    @glGenProgramsARB := SDL_GL_GetProcAddress('glGenProgramsARB');
+    if not Assigned(glGenProgramsARB) then Exit;
+    @glProgramEnvParameter4dARB := SDL_GL_GetProcAddress('glProgramEnvParameter4dARB');
+    if not Assigned(glProgramEnvParameter4dARB) then Exit;
+    @glProgramEnvParameter4dvARB := SDL_GL_GetProcAddress('glProgramEnvParameter4dvARB');
+    if not Assigned(glProgramEnvParameter4dvARB) then Exit;
+    @glProgramEnvParameter4fARB := SDL_GL_GetProcAddress('glProgramEnvParameter4fARB');
+    if not Assigned(glProgramEnvParameter4fARB) then Exit;
+    @glProgramEnvParameter4fvARB := SDL_GL_GetProcAddress('glProgramEnvParameter4fvARB');
+    if not Assigned(glProgramEnvParameter4fvARB) then Exit;
+    @glProgramLocalParameter4dARB := SDL_GL_GetProcAddress('glProgramLocalParameter4dARB');
+    if not Assigned(glProgramLocalParameter4dARB) then Exit;
+    @glProgramLocalParameter4dvARB := SDL_GL_GetProcAddress('glProgramLocalParameter4dvARB');
+    if not Assigned(glProgramLocalParameter4dvARB) then Exit;
+    @glProgramLocalParameter4fARB := SDL_GL_GetProcAddress('glProgramLocalParameter4fARB');
+    if not Assigned(glProgramLocalParameter4fARB) then Exit;
+    @glProgramLocalParameter4fvARB := SDL_GL_GetProcAddress('glProgramLocalParameter4fvARB');
+    if not Assigned(glProgramLocalParameter4fvARB) then Exit;
+    @glGetProgramEnvParameterdvARB := SDL_GL_GetProcAddress('glGetProgramEnvParameterdvARB');
+    if not Assigned(glGetProgramEnvParameterdvARB) then Exit;
+    @glGetProgramEnvParameterfvARB := SDL_GL_GetProcAddress('glGetProgramEnvParameterfvARB');
+    if not Assigned(glGetProgramEnvParameterfvARB) then Exit;
+    @glGetProgramLocalParameterdvARB := SDL_GL_GetProcAddress('glGetProgramLocalParameterdvARB');
+    if not Assigned(glGetProgramLocalParameterdvARB) then Exit;
+    @glGetProgramLocalParameterfvARB := SDL_GL_GetProcAddress('glGetProgramLocalParameterfvARB');
+    if not Assigned(glGetProgramLocalParameterfvARB) then Exit;
+    @glGetProgramivARB := SDL_GL_GetProcAddress('glGetProgramivARB');
+    if not Assigned(glGetProgramivARB) then Exit;
+    @glGetProgramStringARB := SDL_GL_GetProcAddress('glGetProgramStringARB');
+    if not Assigned(glGetProgramStringARB) then Exit;
+    @glIsProgramARB := SDL_GL_GetProcAddress('glIsProgramARB');
+    if not Assigned(glIsProgramARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_text_fragment_shader: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_text_fragment_shader', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_APPLE_client_storage: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_APPLE_client_storage', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_APPLE_element_array: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_APPLE_element_array', extstring) then
+  begin
+    @glElementPointerAPPLE := SDL_GL_GetProcAddress('glElementPointerAPPLE');
+    if not Assigned(glElementPointerAPPLE) then Exit;
+    @glDrawElementArrayAPPLE := SDL_GL_GetProcAddress('glDrawElementArrayAPPLE');
+    if not Assigned(glDrawElementArrayAPPLE) then Exit;
+    @glDrawRangeElementArrayAPPLE := SDL_GL_GetProcAddress('glDrawRangeElementArrayAPPLE');
+    if not Assigned(glDrawRangeElementArrayAPPLE) then Exit;
+    @glMultiDrawElementArrayAPPLE := SDL_GL_GetProcAddress('glMultiDrawElementArrayAPPLE');
+    if not Assigned(glMultiDrawElementArrayAPPLE) then Exit;
+    @glMultiDrawRangeElementArrayAPPLE := SDL_GL_GetProcAddress('glMultiDrawRangeElementArrayAPPLE');
+    if not Assigned(glMultiDrawRangeElementArrayAPPLE) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_APPLE_fence: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_APPLE_fence', extstring) then
+  begin
+    @glGenFencesAPPLE := SDL_GL_GetProcAddress('glGenFencesAPPLE');
+    if not Assigned(glGenFencesAPPLE) then Exit;
+    @glDeleteFencesAPPLE := SDL_GL_GetProcAddress('glDeleteFencesAPPLE');
+    if not Assigned(glDeleteFencesAPPLE) then Exit;
+    @glSetFenceAPPLE := SDL_GL_GetProcAddress('glSetFenceAPPLE');
+    if not Assigned(glSetFenceAPPLE) then Exit;
+    @glIsFenceAPPLE := SDL_GL_GetProcAddress('glIsFenceAPPLE');
+    if not Assigned(glIsFenceAPPLE) then Exit;
+    @glTestFenceAPPLE := SDL_GL_GetProcAddress('glTestFenceAPPLE');
+    if not Assigned(glTestFenceAPPLE) then Exit;
+    @glFinishFenceAPPLE := SDL_GL_GetProcAddress('glFinishFenceAPPLE');
+    if not Assigned(glFinishFenceAPPLE) then Exit;
+    @glTestObjectAPPLE := SDL_GL_GetProcAddress('glTestObjectAPPLE');
+    if not Assigned(glTestObjectAPPLE) then Exit;
+    @glFinishObjectAPPLE := SDL_GL_GetProcAddress('glFinishObjectAPPLE');
+    if not Assigned(glFinishObjectAPPLE) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_APPLE_vertex_array_object: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_APPLE_vertex_array_object', extstring) then
+  begin
+    @glBindVertexArrayAPPLE := SDL_GL_GetProcAddress('glBindVertexArrayAPPLE');
+    if not Assigned(glBindVertexArrayAPPLE) then Exit;
+    @glDeleteVertexArraysAPPLE := SDL_GL_GetProcAddress('glDeleteVertexArraysAPPLE');
+    if not Assigned(glDeleteVertexArraysAPPLE) then Exit;
+    @glGenVertexArraysAPPLE := SDL_GL_GetProcAddress('glGenVertexArraysAPPLE');
+    if not Assigned(glGenVertexArraysAPPLE) then Exit;
+    @glIsVertexArrayAPPLE := SDL_GL_GetProcAddress('glIsVertexArrayAPPLE');
+    if not Assigned(glIsVertexArrayAPPLE) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_APPLE_vertex_array_range: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_APPLE_vertex_array_range', extstring) then
+  begin
+    @glVertexArrayRangeAPPLE := SDL_GL_GetProcAddress('glVertexArrayRangeAPPLE');
+    if not Assigned(glVertexArrayRangeAPPLE) then Exit;
+    @glFlushVertexArrayRangeAPPLE := SDL_GL_GetProcAddress('glFlushVertexArrayRangeAPPLE');
+    if not Assigned(glFlushVertexArrayRangeAPPLE) then Exit;
+    @glVertexArrayParameteriAPPLE := SDL_GL_GetProcAddress('glVertexArrayParameteriAPPLE');
+    if not Assigned(glVertexArrayParameteriAPPLE) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+{$IFDEF WINDOWS}
+function Load_WGL_ARB_pixel_format: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_ARB_pixel_format', extstring) then
+  begin
+    @wglGetPixelFormatAttribivARB := SDL_GL_GetProcAddress('wglGetPixelFormatAttribivARB');
+    if not Assigned(wglGetPixelFormatAttribivARB) then Exit;
+    @wglGetPixelFormatAttribfvARB := SDL_GL_GetProcAddress('wglGetPixelFormatAttribfvARB');
+    if not Assigned(wglGetPixelFormatAttribfvARB) then Exit;
+    @wglChoosePixelFormatARB := SDL_GL_GetProcAddress('wglChoosePixelFormatARB');
+    if not Assigned(wglChoosePixelFormatARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_ARB_make_current_read: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_ARB_make_current_read', extstring) then
+  begin
+    @wglMakeContextCurrentARB := SDL_GL_GetProcAddress('wglMakeContextCurrentARB');
+    if not Assigned(wglMakeContextCurrentARB) then Exit;
+    @wglGetCurrentReadDCARB := SDL_GL_GetProcAddress('wglGetCurrentReadDCARB');
+    if not Assigned(wglGetCurrentReadDCARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_ARB_pbuffer: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_ARB_pbuffer', extstring) then
+  begin
+    @wglCreatePbufferARB := SDL_GL_GetProcAddress('wglCreatePbufferARB');
+    if not Assigned(wglCreatePbufferARB) then Exit;
+    @wglGetPbufferDCARB := SDL_GL_GetProcAddress('wglGetPbufferDCARB');
+    if not Assigned(wglGetPbufferDCARB) then Exit;
+    @wglReleasePbufferDCARB := SDL_GL_GetProcAddress('wglReleasePbufferDCARB');
+    if not Assigned(wglReleasePbufferDCARB) then Exit;
+    @wglDestroyPbufferARB := SDL_GL_GetProcAddress('wglDestroyPbufferARB');
+    if not Assigned(wglDestroyPbufferARB) then Exit;
+    @wglQueryPbufferARB := SDL_GL_GetProcAddress('wglQueryPbufferARB');
+    if not Assigned(wglQueryPbufferARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_EXT_swap_control: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_EXT_swap_control', extstring) then
+  begin
+    @wglSwapIntervalEXT := SDL_GL_GetProcAddress('wglSwapIntervalEXT');
+    if not Assigned(wglSwapIntervalEXT) then Exit;
+    @wglGetSwapIntervalEXT := SDL_GL_GetProcAddress('wglGetSwapIntervalEXT');
+    if not Assigned(wglGetSwapIntervalEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_ARB_render_texture: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_ARB_render_texture', extstring) then
+  begin
+    @wglBindTexImageARB := SDL_GL_GetProcAddress('wglBindTexImageARB');
+    if not Assigned(wglBindTexImageARB) then Exit;
+    @wglReleaseTexImageARB := SDL_GL_GetProcAddress('wglReleaseTexImageARB');
+    if not Assigned(wglReleaseTexImageARB) then Exit;
+    @wglSetPbufferAttribARB := SDL_GL_GetProcAddress('wglSetPbufferAttribARB');
+    if not Assigned(wglSetPbufferAttribARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_EXT_extensions_string: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_EXT_extensions_string', extstring) then
+  begin
+    @wglGetExtensionsStringEXT := SDL_GL_GetProcAddress('wglGetExtensionsStringEXT');
+    if not Assigned(wglGetExtensionsStringEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_EXT_make_current_read: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_EXT_make_current_read', extstring) then
+  begin
+    @wglMakeContextCurrentEXT := SDL_GL_GetProcAddress('wglMakeContextCurrentEXT');
+    if not Assigned(wglMakeContextCurrentEXT) then Exit;
+    @wglGetCurrentReadDCEXT := SDL_GL_GetProcAddress('wglGetCurrentReadDCEXT');
+    if not Assigned(wglGetCurrentReadDCEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_EXT_pbuffer: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_EXT_pbuffer', extstring) then
+  begin
+    @wglCreatePbufferEXT := SDL_GL_GetProcAddress('wglCreatePbufferEXT');
+    if not Assigned(wglCreatePbufferEXT) then Exit;
+    @wglGetPbufferDCEXT := SDL_GL_GetProcAddress('wglGetPbufferDCEXT');
+    if not Assigned(wglGetPbufferDCEXT) then Exit;
+    @wglReleasePbufferDCEXT := SDL_GL_GetProcAddress('wglReleasePbufferDCEXT');
+    if not Assigned(wglReleasePbufferDCEXT) then Exit;
+    @wglDestroyPbufferEXT := SDL_GL_GetProcAddress('wglDestroyPbufferEXT');
+    if not Assigned(wglDestroyPbufferEXT) then Exit;
+    @wglQueryPbufferEXT := SDL_GL_GetProcAddress('wglQueryPbufferEXT');
+    if not Assigned(wglQueryPbufferEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_EXT_pixel_format: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_EXT_pixel_format', extstring) then
+  begin
+    @wglGetPixelFormatAttribivEXT := SDL_GL_GetProcAddress('wglGetPixelFormatAttribivEXT');
+    if not Assigned(wglGetPixelFormatAttribivEXT) then Exit;
+    @wglGetPixelFormatAttribfvEXT := SDL_GL_GetProcAddress('wglGetPixelFormatAttribfvEXT');
+    if not Assigned(wglGetPixelFormatAttribfvEXT) then Exit;
+    @wglChoosePixelFormatEXT := SDL_GL_GetProcAddress('wglChoosePixelFormatEXT');
+    if not Assigned(wglChoosePixelFormatEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_I3D_digital_video_control: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_I3D_digital_video_control', extstring) then
+  begin
+    @wglGetDigitalVideoParametersI3D := SDL_GL_GetProcAddress('wglGetDigitalVideoParametersI3D');
+    if not Assigned(wglGetDigitalVideoParametersI3D) then Exit;
+    @wglSetDigitalVideoParametersI3D := SDL_GL_GetProcAddress('wglSetDigitalVideoParametersI3D');
+    if not Assigned(wglSetDigitalVideoParametersI3D) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_I3D_gamma: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_I3D_gamma', extstring) then
+  begin
+    @wglGetGammaTableParametersI3D := SDL_GL_GetProcAddress('wglGetGammaTableParametersI3D');
+    if not Assigned(wglGetGammaTableParametersI3D) then Exit;
+    @wglSetGammaTableParametersI3D := SDL_GL_GetProcAddress('wglSetGammaTableParametersI3D');
+    if not Assigned(wglSetGammaTableParametersI3D) then Exit;
+    @wglGetGammaTableI3D := SDL_GL_GetProcAddress('wglGetGammaTableI3D');
+    if not Assigned(wglGetGammaTableI3D) then Exit;
+    @wglSetGammaTableI3D := SDL_GL_GetProcAddress('wglSetGammaTableI3D');
+    if not Assigned(wglSetGammaTableI3D) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_WGL_I3D_genlock: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_I3D_genlock', extstring) then
+  begin
+    @wglEnableGenlockI3D := SDL_GL_GetProcAddress('wglEnableGenlockI3D');
+    if not Assigned(wglEnableGenlockI3D) then Exit;
+    @wglDisableGenlockI3D := SDL_GL_GetProcAddress('wglDisableGenlockI3D');
+    if not Assigned(wglDisableGenlockI3D) then Exit;
+    @wglIsEnabledGenlockI3D := SDL_GL_GetProcAddress('wglIsEnabledGenlockI3D');
+    if not Assigned(wglIsEnabledGenlockI3D) then Exit;
+    @wglGenlockSourceI3D := SDL_GL_GetProcAddress('wglGenlockSourceI3D');
+    if not Assigned(wglGenlockSourceI3D) then Exit;
+    @wglGetGenlockSourceI3D := SDL_GL_GetProcAddress('wglGetGenlockSourceI3D');
+    if not Assigned(wglGetGenlockSourceI3D) then Exit;
+    @wglGenlockSourceEdgeI3D := SDL_GL_GetProcAddress('wglGenlockSourceEdgeI3D');
+    if not Assigned(wglGenlockSourceEdgeI3D) then Exit;
+    @wglGetGenlockSourceEdgeI3D := SDL_GL_GetProcAddress('wglGetGenlockSourceEdgeI3D');
+    if not Assigned(wglGetGenlockSourceEdgeI3D) then Exit;
+    @wglGenlockSampleRateI3D := SDL_GL_GetProcAddress('wglGenlockSampleRateI3D');
+    if not Assigned(wglGenlockSampleRateI3D) then Exit;
+    @wglGetGenlockSampleRateI3D := SDL_GL_GetProcAddress('wglGetGenlockSampleRateI3D');
+    if not Assigned(wglGetGenlockSampleRateI3D) then Exit;
+    @wglGenlockSourceDelayI3D := SDL_GL_GetProcAddress('wglGenlockSourceDelayI3D');
+    if not Assigned(wglGenlockSourceDelayI3D) then Exit;
+    @wglGetGenlockSourceDelayI3D := SDL_GL_GetProcAddress('wglGetGenlockSourceDelayI3D');
+    if not Assigned(wglGetGenlockSourceDelayI3D) then Exit;
+    @wglQueryGenlockMaxSourceDelayI3D := SDL_GL_GetProcAddress('wglQueryGenlockMaxSourceDelayI3D');
+    if not Assigned(wglQueryGenlockMaxSourceDelayI3D) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+{$ENDIF}
+
+function Load_GL_ARB_matrix_palette: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_matrix_palette', extstring) then
+  begin
+    @glCurrentPaletteMatrixARB := SDL_GL_GetProcAddress('glCurrentPaletteMatrixARB');
+    if not Assigned(glCurrentPaletteMatrixARB) then Exit;
+    @glMatrixIndexubvARB := SDL_GL_GetProcAddress('glMatrixIndexubvARB');
+    if not Assigned(glMatrixIndexubvARB) then Exit;
+    @glMatrixIndexusvARB := SDL_GL_GetProcAddress('glMatrixIndexusvARB');
+    if not Assigned(glMatrixIndexusvARB) then Exit;
+    @glMatrixIndexuivARB := SDL_GL_GetProcAddress('glMatrixIndexuivARB');
+    if not Assigned(glMatrixIndexuivARB) then Exit;
+    @glMatrixIndexPointerARB := SDL_GL_GetProcAddress('glMatrixIndexPointerARB');
+    if not Assigned(glMatrixIndexPointerARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_element_array: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_element_array', extstring) then
+  begin
+    @glElementPointerNV := SDL_GL_GetProcAddress('glElementPointerNV');
+    if not Assigned(glElementPointerNV) then Exit;
+    @glDrawElementArrayNV := SDL_GL_GetProcAddress('glDrawElementArrayNV');
+    if not Assigned(glDrawElementArrayNV) then Exit;
+    @glDrawRangeElementArrayNV := SDL_GL_GetProcAddress('glDrawRangeElementArrayNV');
+    if not Assigned(glDrawRangeElementArrayNV) then Exit;
+    @glMultiDrawElementArrayNV := SDL_GL_GetProcAddress('glMultiDrawElementArrayNV');
+    if not Assigned(glMultiDrawElementArrayNV) then Exit;
+    @glMultiDrawRangeElementArrayNV := SDL_GL_GetProcAddress('glMultiDrawRangeElementArrayNV');
+    if not Assigned(glMultiDrawRangeElementArrayNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_float_buffer: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_float_buffer', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_fragment_program: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_fragment_program', extstring) then
+  begin
+    @glProgramNamedParameter4fNV := SDL_GL_GetProcAddress('glProgramNamedParameter4fNV');
+    if not Assigned(glProgramNamedParameter4fNV) then Exit;
+    @glProgramNamedParameter4dNV := SDL_GL_GetProcAddress('glProgramNamedParameter4dNV');
+    if not Assigned(glProgramNamedParameter4dNV) then Exit;
+    @glGetProgramNamedParameterfvNV := SDL_GL_GetProcAddress('glGetProgramNamedParameterfvNV');
+    if not Assigned(glGetProgramNamedParameterfvNV) then Exit;
+    @glGetProgramNamedParameterdvNV := SDL_GL_GetProcAddress('glGetProgramNamedParameterdvNV');
+    if not Assigned(glGetProgramNamedParameterdvNV) then Exit;
+    @glProgramLocalParameter4dARB := SDL_GL_GetProcAddress('glProgramLocalParameter4dARB');
+    if not Assigned(glProgramLocalParameter4dARB) then Exit;
+    @glProgramLocalParameter4dvARB := SDL_GL_GetProcAddress('glProgramLocalParameter4dvARB');
+    if not Assigned(glProgramLocalParameter4dvARB) then Exit;
+    @glProgramLocalParameter4fARB := SDL_GL_GetProcAddress('glProgramLocalParameter4fARB');
+    if not Assigned(glProgramLocalParameter4fARB) then Exit;
+    @glProgramLocalParameter4fvARB := SDL_GL_GetProcAddress('glProgramLocalParameter4fvARB');
+    if not Assigned(glProgramLocalParameter4fvARB) then Exit;
+    @glGetProgramLocalParameterdvARB := SDL_GL_GetProcAddress('glGetProgramLocalParameterdvARB');
+    if not Assigned(glGetProgramLocalParameterdvARB) then Exit;
+    @glGetProgramLocalParameterfvARB := SDL_GL_GetProcAddress('glGetProgramLocalParameterfvARB');
+    if not Assigned(glGetProgramLocalParameterfvARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_primitive_restart: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_primitive_restart', extstring) then
+  begin
+    @glPrimitiveRestartNV := SDL_GL_GetProcAddress('glPrimitiveRestartNV');
+    if not Assigned(glPrimitiveRestartNV) then Exit;
+    @glPrimitiveRestartIndexNV := SDL_GL_GetProcAddress('glPrimitiveRestartIndexNV');
+    if not Assigned(glPrimitiveRestartIndexNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_vertex_program2: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_vertex_program2', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+{$IFDEF WINDOWS}
+function Load_WGL_NV_render_texture_rectangle: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_NV_render_texture_rectangle', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+{$ENDIF}
+
+function Load_GL_NV_pixel_data_range: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_pixel_data_range', extstring) then
+  begin
+    @glPixelDataRangeNV := SDL_GL_GetProcAddress('glPixelDataRangeNV');
+    if not Assigned(glPixelDataRangeNV) then Exit;
+    @glFlushPixelDataRangeNV := SDL_GL_GetProcAddress('glFlushPixelDataRangeNV');
+    if not Assigned(glFlushPixelDataRangeNV) then Exit;
+    {$IFDEF WINDOWS}
+    @wglAllocateMemoryNV := SDL_GL_GetProcAddress('wglAllocateMemoryNV');
+    if not Assigned(wglAllocateMemoryNV) then Exit;
+    @wglFreeMemoryNV := SDL_GL_GetProcAddress('wglFreeMemoryNV');
+    if not Assigned(wglFreeMemoryNV) then Exit;
+    {$ENDIF}
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_rectangle: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture_rectangle', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_S3_s3tc: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_S3_s3tc', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_draw_buffers: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_draw_buffers', extstring) then
+  begin
+    @glDrawBuffersATI := SDL_GL_GetProcAddress('glDrawBuffersATI');
+    if not Assigned(glDrawBuffersATI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+{$IFDEF WINDOWS}
+function Load_WGL_ATI_pixel_format_float: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  @wglGetExtensionsStringARB := SDL_GL_GetProcAddress('wglGetExtensionsStringARB');
+  if not Assigned(wglGetExtensionsStringARB) then Exit;
+  extstring := wglGetExtensionsStringARB(wglGetCurrentDC);
+
+  if glext_ExtensionSupported('WGL_ATI_pixel_format_float', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+{$ENDIF}
+
+function Load_GL_ATI_texture_env_combine3: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_texture_env_combine3', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_texture_float: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_texture_float', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_texture_expand_normal: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_texture_expand_normal', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_half_float: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_half_float', extstring) then
+  begin
+    @glVertex2hNV := SDL_GL_GetProcAddress('glVertex2hNV');
+    if not Assigned(glVertex2hNV) then Exit;
+    @glVertex2hvNV := SDL_GL_GetProcAddress('glVertex2hvNV');
+    if not Assigned(glVertex2hvNV) then Exit;
+    @glVertex3hNV := SDL_GL_GetProcAddress('glVertex3hNV');
+    if not Assigned(glVertex3hNV) then Exit;
+    @glVertex3hvNV := SDL_GL_GetProcAddress('glVertex3hvNV');
+    if not Assigned(glVertex3hvNV) then Exit;
+    @glVertex4hNV := SDL_GL_GetProcAddress('glVertex4hNV');
+    if not Assigned(glVertex4hNV) then Exit;
+    @glVertex4hvNV := SDL_GL_GetProcAddress('glVertex4hvNV');
+    if not Assigned(glVertex4hvNV) then Exit;
+    @glNormal3hNV := SDL_GL_GetProcAddress('glNormal3hNV');
+    if not Assigned(glNormal3hNV) then Exit;
+    @glNormal3hvNV := SDL_GL_GetProcAddress('glNormal3hvNV');
+    if not Assigned(glNormal3hvNV) then Exit;
+    @glColor3hNV := SDL_GL_GetProcAddress('glColor3hNV');
+    if not Assigned(glColor3hNV) then Exit;
+    @glColor3hvNV := SDL_GL_GetProcAddress('glColor3hvNV');
+    if not Assigned(glColor3hvNV) then Exit;
+    @glColor4hNV := SDL_GL_GetProcAddress('glColor4hNV');
+    if not Assigned(glColor4hNV) then Exit;
+    @glColor4hvNV := SDL_GL_GetProcAddress('glColor4hvNV');
+    if not Assigned(glColor4hvNV) then Exit;
+    @glTexCoord1hNV := SDL_GL_GetProcAddress('glTexCoord1hNV');
+    if not Assigned(glTexCoord1hNV) then Exit;
+    @glTexCoord1hvNV := SDL_GL_GetProcAddress('glTexCoord1hvNV');
+    if not Assigned(glTexCoord1hvNV) then Exit;
+    @glTexCoord2hNV := SDL_GL_GetProcAddress('glTexCoord2hNV');
+    if not Assigned(glTexCoord2hNV) then Exit;
+    @glTexCoord2hvNV := SDL_GL_GetProcAddress('glTexCoord2hvNV');
+    if not Assigned(glTexCoord2hvNV) then Exit;
+    @glTexCoord3hNV := SDL_GL_GetProcAddress('glTexCoord3hNV');
+    if not Assigned(glTexCoord3hNV) then Exit;
+    @glTexCoord3hvNV := SDL_GL_GetProcAddress('glTexCoord3hvNV');
+    if not Assigned(glTexCoord3hvNV) then Exit;
+    @glTexCoord4hNV := SDL_GL_GetProcAddress('glTexCoord4hNV');
+    if not Assigned(glTexCoord4hNV) then Exit;
+    @glTexCoord4hvNV := SDL_GL_GetProcAddress('glTexCoord4hvNV');
+    if not Assigned(glTexCoord4hvNV) then Exit;
+    @glMultiTexCoord1hNV := SDL_GL_GetProcAddress('glMultiTexCoord1hNV');
+    if not Assigned(glMultiTexCoord1hNV) then Exit;
+    @glMultiTexCoord1hvNV := SDL_GL_GetProcAddress('glMultiTexCoord1hvNV');
+    if not Assigned(glMultiTexCoord1hvNV) then Exit;
+    @glMultiTexCoord2hNV := SDL_GL_GetProcAddress('glMultiTexCoord2hNV');
+    if not Assigned(glMultiTexCoord2hNV) then Exit;
+    @glMultiTexCoord2hvNV := SDL_GL_GetProcAddress('glMultiTexCoord2hvNV');
+    if not Assigned(glMultiTexCoord2hvNV) then Exit;
+    @glMultiTexCoord3hNV := SDL_GL_GetProcAddress('glMultiTexCoord3hNV');
+    if not Assigned(glMultiTexCoord3hNV) then Exit;
+    @glMultiTexCoord3hvNV := SDL_GL_GetProcAddress('glMultiTexCoord3hvNV');
+    if not Assigned(glMultiTexCoord3hvNV) then Exit;
+    @glMultiTexCoord4hNV := SDL_GL_GetProcAddress('glMultiTexCoord4hNV');
+    if not Assigned(glMultiTexCoord4hNV) then Exit;
+    @glMultiTexCoord4hvNV := SDL_GL_GetProcAddress('glMultiTexCoord4hvNV');
+    if not Assigned(glMultiTexCoord4hvNV) then Exit;
+    @glFogCoordhNV := SDL_GL_GetProcAddress('glFogCoordhNV');
+    if not Assigned(glFogCoordhNV) then Exit;
+    @glFogCoordhvNV := SDL_GL_GetProcAddress('glFogCoordhvNV');
+    if not Assigned(glFogCoordhvNV) then Exit;
+    @glSecondaryColor3hNV := SDL_GL_GetProcAddress('glSecondaryColor3hNV');
+    if not Assigned(glSecondaryColor3hNV) then Exit;
+    @glSecondaryColor3hvNV := SDL_GL_GetProcAddress('glSecondaryColor3hvNV');
+    if not Assigned(glSecondaryColor3hvNV) then Exit;
+    @glVertexWeighthNV := SDL_GL_GetProcAddress('glVertexWeighthNV');
+    if not Assigned(glVertexWeighthNV) then Exit;
+    @glVertexWeighthvNV := SDL_GL_GetProcAddress('glVertexWeighthvNV');
+    if not Assigned(glVertexWeighthvNV) then Exit;
+    @glVertexAttrib1hNV := SDL_GL_GetProcAddress('glVertexAttrib1hNV');
+    if not Assigned(glVertexAttrib1hNV) then Exit;
+    @glVertexAttrib1hvNV := SDL_GL_GetProcAddress('glVertexAttrib1hvNV');
+    if not Assigned(glVertexAttrib1hvNV) then Exit;
+    @glVertexAttrib2hNV := SDL_GL_GetProcAddress('glVertexAttrib2hNV');
+    if not Assigned(glVertexAttrib2hNV) then Exit;
+    @glVertexAttrib2hvNV := SDL_GL_GetProcAddress('glVertexAttrib2hvNV');
+    if not Assigned(glVertexAttrib2hvNV) then Exit;
+    @glVertexAttrib3hNV := SDL_GL_GetProcAddress('glVertexAttrib3hNV');
+    if not Assigned(glVertexAttrib3hNV) then Exit;
+    @glVertexAttrib3hvNV := SDL_GL_GetProcAddress('glVertexAttrib3hvNV');
+    if not Assigned(glVertexAttrib3hvNV) then Exit;
+    @glVertexAttrib4hNV := SDL_GL_GetProcAddress('glVertexAttrib4hNV');
+    if not Assigned(glVertexAttrib4hNV) then Exit;
+    @glVertexAttrib4hvNV := SDL_GL_GetProcAddress('glVertexAttrib4hvNV');
+    if not Assigned(glVertexAttrib4hvNV) then Exit;
+    @glVertexAttribs1hvNV := SDL_GL_GetProcAddress('glVertexAttribs1hvNV');
+    if not Assigned(glVertexAttribs1hvNV) then Exit;
+    @glVertexAttribs2hvNV := SDL_GL_GetProcAddress('glVertexAttribs2hvNV');
+    if not Assigned(glVertexAttribs2hvNV) then Exit;
+    @glVertexAttribs3hvNV := SDL_GL_GetProcAddress('glVertexAttribs3hvNV');
+    if not Assigned(glVertexAttribs3hvNV) then Exit;
+    @glVertexAttribs4hvNV := SDL_GL_GetProcAddress('glVertexAttribs4hvNV');
+    if not Assigned(glVertexAttribs4hvNV) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_map_object_buffer: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_map_object_buffer', extstring) then
+  begin
+    @glMapObjectBufferATI := SDL_GL_GetProcAddress('glMapObjectBufferATI');
+    if not Assigned(glMapObjectBufferATI) then Exit;
+    @glUnmapObjectBufferATI := SDL_GL_GetProcAddress('glUnmapObjectBufferATI');
+    if not Assigned(glUnmapObjectBufferATI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_separate_stencil: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_separate_stencil', extstring) then
+  begin
+    @glStencilOpSeparateATI := SDL_GL_GetProcAddress('glStencilOpSeparateATI');
+    if not Assigned(glStencilOpSeparateATI) then Exit;
+    @glStencilFuncSeparateATI := SDL_GL_GetProcAddress('glStencilFuncSeparateATI');
+    if not Assigned(glStencilFuncSeparateATI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ATI_vertex_attrib_array_object: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ATI_vertex_attrib_array_object', extstring) then
+  begin
+    @glVertexAttribArrayObjectATI := SDL_GL_GetProcAddress('glVertexAttribArrayObjectATI');
+    if not Assigned(glVertexAttribArrayObjectATI) then Exit;
+    @glGetVertexAttribArrayObjectfvATI := SDL_GL_GetProcAddress('glGetVertexAttribArrayObjectfvATI');
+    if not Assigned(glGetVertexAttribArrayObjectfvATI) then Exit;
+    @glGetVertexAttribArrayObjectivATI := SDL_GL_GetProcAddress('glGetVertexAttribArrayObjectivATI');
+    if not Assigned(glGetVertexAttribArrayObjectivATI) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_vertex_buffer_object: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_vertex_buffer_object', extstring) then
+  begin
+    @glBindBufferARB := SDL_GL_GetProcAddress('glBindBufferARB');
+    if not Assigned(glBindBufferARB) then Exit;
+    @glDeleteBuffersARB := SDL_GL_GetProcAddress('glDeleteBuffersARB');
+    if not Assigned(glDeleteBuffersARB) then Exit;
+    @glGenBuffersARB := SDL_GL_GetProcAddress('glGenBuffersARB');
+    if not Assigned(glGenBuffersARB) then Exit;
+    @glIsBufferARB := SDL_GL_GetProcAddress('glIsBufferARB');
+    if not Assigned(glIsBufferARB) then Exit;
+    @glBufferDataARB := SDL_GL_GetProcAddress('glBufferDataARB');
+    if not Assigned(glBufferDataARB) then Exit;
+    @glBufferSubDataARB := SDL_GL_GetProcAddress('glBufferSubDataARB');
+    if not Assigned(glBufferSubDataARB) then Exit;
+    @glGetBufferSubDataARB := SDL_GL_GetProcAddress('glGetBufferSubDataARB');
+    if not Assigned(glGetBufferSubDataARB) then Exit;
+    @glMapBufferARB := SDL_GL_GetProcAddress('glMapBufferARB');
+    if not Assigned(glMapBufferARB) then Exit;
+    @glUnmapBufferARB := SDL_GL_GetProcAddress('glUnmapBufferARB');
+    if not Assigned(glUnmapBufferARB) then Exit;
+    @glGetBufferParameterivARB := SDL_GL_GetProcAddress('glGetBufferParameterivARB');
+    if not Assigned(glGetBufferParameterivARB) then Exit;
+    @glGetBufferPointervARB := SDL_GL_GetProcAddress('glGetBufferPointervARB');
+    if not Assigned(glGetBufferPointervARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_occlusion_query: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_occlusion_query', extstring) then
+  begin
+    @glGenQueriesARB := SDL_GL_GetProcAddress('glGenQueriesARB');
+    if not Assigned(glGenQueriesARB) then Exit;
+    @glDeleteQueriesARB := SDL_GL_GetProcAddress('glDeleteQueriesARB');
+    if not Assigned(glDeleteQueriesARB) then Exit;
+    @glIsQueryARB := SDL_GL_GetProcAddress('glIsQueryARB');
+    if not Assigned(glIsQueryARB) then Exit;
+    @glBeginQueryARB := SDL_GL_GetProcAddress('glBeginQueryARB');
+    if not Assigned(glBeginQueryARB) then Exit;
+    @glEndQueryARB := SDL_GL_GetProcAddress('glEndQueryARB');
+    if not Assigned(glEndQueryARB) then Exit;
+    @glGetQueryivARB := SDL_GL_GetProcAddress('glGetQueryivARB');
+    if not Assigned(glGetQueryivARB) then Exit;
+    @glGetQueryObjectivARB := SDL_GL_GetProcAddress('glGetQueryObjectivARB');
+    if not Assigned(glGetQueryObjectivARB) then Exit;
+    @glGetQueryObjectuivARB := SDL_GL_GetProcAddress('glGetQueryObjectuivARB');
+    if not Assigned(glGetQueryObjectuivARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_shader_objects: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_shader_objects', extstring) then
+  begin
+    @glDeleteObjectARB := SDL_GL_GetProcAddress('glDeleteObjectARB');
+    if not Assigned(glDeleteObjectARB) then Exit;
+    @glGetHandleARB := SDL_GL_GetProcAddress('glGetHandleARB');
+    if not Assigned(glGetHandleARB) then Exit;
+    @glDetachObjectARB := SDL_GL_GetProcAddress('glDetachObjectARB');
+    if not Assigned(glDetachObjectARB) then Exit;
+    @glCreateShaderObjectARB := SDL_GL_GetProcAddress('glCreateShaderObjectARB');
+    if not Assigned(glCreateShaderObjectARB) then Exit;
+    @glShaderSourceARB := SDL_GL_GetProcAddress('glShaderSourceARB');
+    if not Assigned(glShaderSourceARB) then Exit;
+    @glCompileShaderARB := SDL_GL_GetProcAddress('glCompileShaderARB');
+    if not Assigned(glCompileShaderARB) then Exit;
+    @glCreateProgramObjectARB := SDL_GL_GetProcAddress('glCreateProgramObjectARB');
+    if not Assigned(glCreateProgramObjectARB) then Exit;
+    @glAttachObjectARB := SDL_GL_GetProcAddress('glAttachObjectARB');
+    if not Assigned(glAttachObjectARB) then Exit;
+    @glLinkProgramARB := SDL_GL_GetProcAddress('glLinkProgramARB');
+    if not Assigned(glLinkProgramARB) then Exit;
+    @glUseProgramObjectARB := SDL_GL_GetProcAddress('glUseProgramObjectARB');
+    if not Assigned(glUseProgramObjectARB) then Exit;
+    @glValidateProgramARB := SDL_GL_GetProcAddress('glValidateProgramARB');
+    if not Assigned(glValidateProgramARB) then Exit;
+    @glUniform1fARB := SDL_GL_GetProcAddress('glUniform1fARB');
+    if not Assigned(glUniform1fARB) then Exit;
+    @glUniform2fARB := SDL_GL_GetProcAddress('glUniform2fARB');
+    if not Assigned(glUniform2fARB) then Exit;
+    @glUniform3fARB := SDL_GL_GetProcAddress('glUniform3fARB');
+    if not Assigned(glUniform3fARB) then Exit;
+    @glUniform4fARB := SDL_GL_GetProcAddress('glUniform4fARB');
+    if not Assigned(glUniform4fARB) then Exit;
+    @glUniform1iARB := SDL_GL_GetProcAddress('glUniform1iARB');
+    if not Assigned(glUniform1iARB) then Exit;
+    @glUniform2iARB := SDL_GL_GetProcAddress('glUniform2iARB');
+    if not Assigned(glUniform2iARB) then Exit;
+    @glUniform3iARB := SDL_GL_GetProcAddress('glUniform3iARB');
+    if not Assigned(glUniform3iARB) then Exit;
+    @glUniform4iARB := SDL_GL_GetProcAddress('glUniform4iARB');
+    if not Assigned(glUniform4iARB) then Exit;
+    @glUniform1fvARB := SDL_GL_GetProcAddress('glUniform1fvARB');
+    if not Assigned(glUniform1fvARB) then Exit;
+    @glUniform2fvARB := SDL_GL_GetProcAddress('glUniform2fvARB');
+    if not Assigned(glUniform2fvARB) then Exit;
+    @glUniform3fvARB := SDL_GL_GetProcAddress('glUniform3fvARB');
+    if not Assigned(glUniform3fvARB) then Exit;
+    @glUniform4fvARB := SDL_GL_GetProcAddress('glUniform4fvARB');
+    if not Assigned(glUniform4fvARB) then Exit;
+    @glUniform1ivARB := SDL_GL_GetProcAddress('glUniform1ivARB');
+    if not Assigned(glUniform1ivARB) then Exit;
+    @glUniform2ivARB := SDL_GL_GetProcAddress('glUniform2ivARB');
+    if not Assigned(glUniform2ivARB) then Exit;
+    @glUniform3ivARB := SDL_GL_GetProcAddress('glUniform3ivARB');
+    if not Assigned(glUniform3ivARB) then Exit;
+    @glUniform4ivARB := SDL_GL_GetProcAddress('glUniform4ivARB');
+    if not Assigned(glUniform4ivARB) then Exit;
+    @glUniformMatrix2fvARB := SDL_GL_GetProcAddress('glUniformMatrix2fvARB');
+    if not Assigned(glUniformMatrix2fvARB) then Exit;
+    @glUniformMatrix3fvARB := SDL_GL_GetProcAddress('glUniformMatrix3fvARB');
+    if not Assigned(glUniformMatrix3fvARB) then Exit;
+    @glUniformMatrix4fvARB := SDL_GL_GetProcAddress('glUniformMatrix4fvARB');
+    if not Assigned(glUniformMatrix4fvARB) then Exit;
+    @glGetObjectParameterfvARB := SDL_GL_GetProcAddress('glGetObjectParameterfvARB');
+    if not Assigned(glGetObjectParameterfvARB) then Exit;
+    @glGetObjectParameterivARB := SDL_GL_GetProcAddress('glGetObjectParameterivARB');
+    if not Assigned(glGetObjectParameterivARB) then Exit;
+    @glGetInfoLogARB := SDL_GL_GetProcAddress('glGetInfoLogARB');
+    if not Assigned(glGetInfoLogARB) then Exit;
+    @glGetAttachedObjectsARB := SDL_GL_GetProcAddress('glGetAttachedObjectsARB');
+    if not Assigned(glGetAttachedObjectsARB) then Exit;
+    @glGetUniformLocationARB := SDL_GL_GetProcAddress('glGetUniformLocationARB');
+    if not Assigned(glGetUniformLocationARB) then Exit;
+    @glGetActiveUniformARB := SDL_GL_GetProcAddress('glGetActiveUniformARB');
+    if not Assigned(glGetActiveUniformARB) then Exit;
+    @glGetUniformfvARB := SDL_GL_GetProcAddress('glGetUniformfvARB');
+    if not Assigned(glGetUniformfvARB) then Exit;
+    @glGetUniformivARB := SDL_GL_GetProcAddress('glGetUniformivARB');
+    if not Assigned(glGetUniformivARB) then Exit;
+    @glGetShaderSourceARB := SDL_GL_GetProcAddress('glGetShaderSourceARB');
+    if not Assigned(glGetShaderSourceARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_vertex_shader: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_vertex_shader', extstring) then
+  begin
+    @glVertexAttrib1fARB := SDL_GL_GetProcAddress('glVertexAttrib1fARB');
+    if not Assigned(glVertexAttrib1fARB) then Exit;
+    @glVertexAttrib1sARB := SDL_GL_GetProcAddress('glVertexAttrib1sARB');
+    if not Assigned(glVertexAttrib1sARB) then Exit;
+    @glVertexAttrib1dARB := SDL_GL_GetProcAddress('glVertexAttrib1dARB');
+    if not Assigned(glVertexAttrib1dARB) then Exit;
+    @glVertexAttrib2fARB := SDL_GL_GetProcAddress('glVertexAttrib2fARB');
+    if not Assigned(glVertexAttrib2fARB) then Exit;
+    @glVertexAttrib2sARB := SDL_GL_GetProcAddress('glVertexAttrib2sARB');
+    if not Assigned(glVertexAttrib2sARB) then Exit;
+    @glVertexAttrib2dARB := SDL_GL_GetProcAddress('glVertexAttrib2dARB');
+    if not Assigned(glVertexAttrib2dARB) then Exit;
+    @glVertexAttrib3fARB := SDL_GL_GetProcAddress('glVertexAttrib3fARB');
+    if not Assigned(glVertexAttrib3fARB) then Exit;
+    @glVertexAttrib3sARB := SDL_GL_GetProcAddress('glVertexAttrib3sARB');
+    if not Assigned(glVertexAttrib3sARB) then Exit;
+    @glVertexAttrib3dARB := SDL_GL_GetProcAddress('glVertexAttrib3dARB');
+    if not Assigned(glVertexAttrib3dARB) then Exit;
+    @glVertexAttrib4fARB := SDL_GL_GetProcAddress('glVertexAttrib4fARB');
+    if not Assigned(glVertexAttrib4fARB) then Exit;
+    @glVertexAttrib4sARB := SDL_GL_GetProcAddress('glVertexAttrib4sARB');
+    if not Assigned(glVertexAttrib4sARB) then Exit;
+    @glVertexAttrib4dARB := SDL_GL_GetProcAddress('glVertexAttrib4dARB');
+    if not Assigned(glVertexAttrib4dARB) then Exit;
+    @glVertexAttrib4NubARB := SDL_GL_GetProcAddress('glVertexAttrib4NubARB');
+    if not Assigned(glVertexAttrib4NubARB) then Exit;
+    @glVertexAttrib1fvARB := SDL_GL_GetProcAddress('glVertexAttrib1fvARB');
+    if not Assigned(glVertexAttrib1fvARB) then Exit;
+    @glVertexAttrib1svARB := SDL_GL_GetProcAddress('glVertexAttrib1svARB');
+    if not Assigned(glVertexAttrib1svARB) then Exit;
+    @glVertexAttrib1dvARB := SDL_GL_GetProcAddress('glVertexAttrib1dvARB');
+    if not Assigned(glVertexAttrib1dvARB) then Exit;
+    @glVertexAttrib2fvARB := SDL_GL_GetProcAddress('glVertexAttrib2fvARB');
+    if not Assigned(glVertexAttrib2fvARB) then Exit;
+    @glVertexAttrib2svARB := SDL_GL_GetProcAddress('glVertexAttrib2svARB');
+    if not Assigned(glVertexAttrib2svARB) then Exit;
+    @glVertexAttrib2dvARB := SDL_GL_GetProcAddress('glVertexAttrib2dvARB');
+    if not Assigned(glVertexAttrib2dvARB) then Exit;
+    @glVertexAttrib3fvARB := SDL_GL_GetProcAddress('glVertexAttrib3fvARB');
+    if not Assigned(glVertexAttrib3fvARB) then Exit;
+    @glVertexAttrib3svARB := SDL_GL_GetProcAddress('glVertexAttrib3svARB');
+    if not Assigned(glVertexAttrib3svARB) then Exit;
+    @glVertexAttrib3dvARB := SDL_GL_GetProcAddress('glVertexAttrib3dvARB');
+    if not Assigned(glVertexAttrib3dvARB) then Exit;
+    @glVertexAttrib4fvARB := SDL_GL_GetProcAddress('glVertexAttrib4fvARB');
+    if not Assigned(glVertexAttrib4fvARB) then Exit;
+    @glVertexAttrib4svARB := SDL_GL_GetProcAddress('glVertexAttrib4svARB');
+    if not Assigned(glVertexAttrib4svARB) then Exit;
+    @glVertexAttrib4dvARB := SDL_GL_GetProcAddress('glVertexAttrib4dvARB');
+    if not Assigned(glVertexAttrib4dvARB) then Exit;
+    @glVertexAttrib4ivARB := SDL_GL_GetProcAddress('glVertexAttrib4ivARB');
+    if not Assigned(glVertexAttrib4ivARB) then Exit;
+    @glVertexAttrib4bvARB := SDL_GL_GetProcAddress('glVertexAttrib4bvARB');
+    if not Assigned(glVertexAttrib4bvARB) then Exit;
+    @glVertexAttrib4ubvARB := SDL_GL_GetProcAddress('glVertexAttrib4ubvARB');
+    if not Assigned(glVertexAttrib4ubvARB) then Exit;
+    @glVertexAttrib4usvARB := SDL_GL_GetProcAddress('glVertexAttrib4usvARB');
+    if not Assigned(glVertexAttrib4usvARB) then Exit;
+    @glVertexAttrib4uivARB := SDL_GL_GetProcAddress('glVertexAttrib4uivARB');
+    if not Assigned(glVertexAttrib4uivARB) then Exit;
+    @glVertexAttrib4NbvARB := SDL_GL_GetProcAddress('glVertexAttrib4NbvARB');
+    if not Assigned(glVertexAttrib4NbvARB) then Exit;
+    @glVertexAttrib4NsvARB := SDL_GL_GetProcAddress('glVertexAttrib4NsvARB');
+    if not Assigned(glVertexAttrib4NsvARB) then Exit;
+    @glVertexAttrib4NivARB := SDL_GL_GetProcAddress('glVertexAttrib4NivARB');
+    if not Assigned(glVertexAttrib4NivARB) then Exit;
+    @glVertexAttrib4NubvARB := SDL_GL_GetProcAddress('glVertexAttrib4NubvARB');
+    if not Assigned(glVertexAttrib4NubvARB) then Exit;
+    @glVertexAttrib4NusvARB := SDL_GL_GetProcAddress('glVertexAttrib4NusvARB');
+    if not Assigned(glVertexAttrib4NusvARB) then Exit;
+    @glVertexAttrib4NuivARB := SDL_GL_GetProcAddress('glVertexAttrib4NuivARB');
+    if not Assigned(glVertexAttrib4NuivARB) then Exit;
+    @glVertexAttribPointerARB := SDL_GL_GetProcAddress('glVertexAttribPointerARB');
+    if not Assigned(glVertexAttribPointerARB) then Exit;
+    @glEnableVertexAttribArrayARB := SDL_GL_GetProcAddress('glEnableVertexAttribArrayARB');
+    if not Assigned(glEnableVertexAttribArrayARB) then Exit;
+    @glDisableVertexAttribArrayARB := SDL_GL_GetProcAddress('glDisableVertexAttribArrayARB');
+    if not Assigned(glDisableVertexAttribArrayARB) then Exit;
+    @glBindAttribLocationARB := SDL_GL_GetProcAddress('glBindAttribLocationARB');
+    if not Assigned(glBindAttribLocationARB) then Exit;
+    @glGetActiveAttribARB := SDL_GL_GetProcAddress('glGetActiveAttribARB');
+    if not Assigned(glGetActiveAttribARB) then Exit;
+    @glGetAttribLocationARB := SDL_GL_GetProcAddress('glGetAttribLocationARB');
+    if not Assigned(glGetAttribLocationARB) then Exit;
+    @glGetVertexAttribdvARB := SDL_GL_GetProcAddress('glGetVertexAttribdvARB');
+    if not Assigned(glGetVertexAttribdvARB) then Exit;
+    @glGetVertexAttribfvARB := SDL_GL_GetProcAddress('glGetVertexAttribfvARB');
+    if not Assigned(glGetVertexAttribfvARB) then Exit;
+    @glGetVertexAttribivARB := SDL_GL_GetProcAddress('glGetVertexAttribivARB');
+    if not Assigned(glGetVertexAttribivARB) then Exit;
+    @glGetVertexAttribPointervARB := SDL_GL_GetProcAddress('glGetVertexAttribPointervARB');
+    if not Assigned(glGetVertexAttribPointervARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_fragment_shader: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_fragment_shader', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_shading_language_100: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_shading_language_100', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_non_power_of_two: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_texture_non_power_of_two', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_point_sprite: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_point_sprite', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_depth_bounds_test: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_depth_bounds_test', extstring) then
+  begin
+    @glDepthBoundsEXT := SDL_GL_GetProcAddress('glDepthBoundsEXT');
+    if not Assigned(glDepthBoundsEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_secondary_color: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_secondary_color', extstring) then
+  begin
+    @glSecondaryColor3bEXT := SDL_GL_GetProcAddress('glSecondaryColor3bEXT');
+    if not Assigned(glSecondaryColor3bEXT) then Exit;
+    @glSecondaryColor3sEXT := SDL_GL_GetProcAddress('glSecondaryColor3sEXT');
+    if not Assigned(glSecondaryColor3sEXT) then Exit;
+    @glSecondaryColor3iEXT := SDL_GL_GetProcAddress('glSecondaryColor3iEXT');
+    if not Assigned(glSecondaryColor3iEXT) then Exit;
+    @glSecondaryColor3fEXT := SDL_GL_GetProcAddress('glSecondaryColor3fEXT');
+    if not Assigned(glSecondaryColor3fEXT) then Exit;
+    @glSecondaryColor3dEXT := SDL_GL_GetProcAddress('glSecondaryColor3dEXT');
+    if not Assigned(glSecondaryColor3dEXT) then Exit;
+    @glSecondaryColor3ubEXT := SDL_GL_GetProcAddress('glSecondaryColor3ubEXT');
+    if not Assigned(glSecondaryColor3ubEXT) then Exit;
+    @glSecondaryColor3usEXT := SDL_GL_GetProcAddress('glSecondaryColor3usEXT');
+    if not Assigned(glSecondaryColor3usEXT) then Exit;
+    @glSecondaryColor3uiEXT := SDL_GL_GetProcAddress('glSecondaryColor3uiEXT');
+    if not Assigned(glSecondaryColor3uiEXT) then Exit;
+    @glSecondaryColor3bvEXT := SDL_GL_GetProcAddress('glSecondaryColor3bvEXT');
+    if not Assigned(glSecondaryColor3bvEXT) then Exit;
+    @glSecondaryColor3svEXT := SDL_GL_GetProcAddress('glSecondaryColor3svEXT');
+    if not Assigned(glSecondaryColor3svEXT) then Exit;
+    @glSecondaryColor3ivEXT := SDL_GL_GetProcAddress('glSecondaryColor3ivEXT');
+    if not Assigned(glSecondaryColor3ivEXT) then Exit;
+    @glSecondaryColor3fvEXT := SDL_GL_GetProcAddress('glSecondaryColor3fvEXT');
+    if not Assigned(glSecondaryColor3fvEXT) then Exit;
+    @glSecondaryColor3dvEXT := SDL_GL_GetProcAddress('glSecondaryColor3dvEXT');
+    if not Assigned(glSecondaryColor3dvEXT) then Exit;
+    @glSecondaryColor3ubvEXT := SDL_GL_GetProcAddress('glSecondaryColor3ubvEXT');
+    if not Assigned(glSecondaryColor3ubvEXT) then Exit;
+    @glSecondaryColor3usvEXT := SDL_GL_GetProcAddress('glSecondaryColor3usvEXT');
+    if not Assigned(glSecondaryColor3usvEXT) then Exit;
+    @glSecondaryColor3uivEXT := SDL_GL_GetProcAddress('glSecondaryColor3uivEXT');
+    if not Assigned(glSecondaryColor3uivEXT) then Exit;
+    @glSecondaryColorPointerEXT := SDL_GL_GetProcAddress('glSecondaryColorPointerEXT');
+    if not Assigned(glSecondaryColorPointerEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_mirror_clamp: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_texture_mirror_clamp', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_blend_equation_separate: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_blend_equation_separate', extstring) then
+  begin
+    @glBlendEquationSeparateEXT := SDL_GL_GetProcAddress('glBlendEquationSeparateEXT');
+    if not Assigned(glBlendEquationSeparateEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_MESA_pack_invert: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_MESA_pack_invert', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_MESA_ycbcr_texture: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_MESA_ycbcr_texture', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_fragment_program_shadow: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_ARB_fragment_program_shadow', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_fog_coord: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_fog_coord', extstring) then
+  begin
+    @glFogCoordfEXT := SDL_GL_GetProcAddress('glFogCoordfEXT');
+    if not Assigned(glFogCoordfEXT) then Exit;
+    @glFogCoorddEXT := SDL_GL_GetProcAddress('glFogCoorddEXT');
+    if not Assigned(glFogCoorddEXT) then Exit;
+    @glFogCoordfvEXT := SDL_GL_GetProcAddress('glFogCoordfvEXT');
+    if not Assigned(glFogCoordfvEXT) then Exit;
+    @glFogCoorddvEXT := SDL_GL_GetProcAddress('glFogCoorddvEXT');
+    if not Assigned(glFogCoorddvEXT) then Exit;
+    @glFogCoordPointerEXT := SDL_GL_GetProcAddress('glFogCoordPointerEXT');
+    if not Assigned(glFogCoordPointerEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_fragment_program_option: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_fragment_program_option', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_pixel_buffer_object: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_EXT_pixel_buffer_object', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_fragment_program2: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_fragment_program2', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_vertex_program2_option: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_vertex_program2_option', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_NV_vertex_program3: Boolean;
+var
+  extstring : PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString( GL_EXTENSIONS );
+
+  if glext_ExtensionSupported('GL_NV_vertex_program3', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_draw_buffers: Boolean;
+var
+  extstring: PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString(GL_EXTENSIONS);
+
+  if glext_ExtensionSupported('GL_ARB_draw_buffers', extstring) then
+  begin
+    glDrawBuffersARB := SDL_GL_GetProcAddress('glDrawBuffersARB');
+    if not Assigned(glDrawBuffersARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_rectangle: Boolean;
+var
+  extstring: PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString(GL_EXTENSIONS);
+
+  if glext_ExtensionSupported('GL_ARB_texture_rectangle', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_color_buffer_float: Boolean;
+var
+  extstring: PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString(GL_EXTENSIONS);
+
+  if glext_ExtensionSupported('GL_ARB_color_buffer_float', extstring) then
+  begin
+    glClampColorARB := SDL_GL_GetProcAddress('glClampColorARB');
+    if not Assigned(glClampColorARB) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_half_float_pixel: Boolean;
+var
+  extstring: PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString(GL_EXTENSIONS);
+
+  if glext_ExtensionSupported('GL_ARB_half_float_pixel', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_texture_float: Boolean;
+var
+  extstring: PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString(GL_EXTENSIONS);
+
+  if glext_ExtensionSupported('GL_ARB_texture_float', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_texture_compression_dxt1: Boolean;
+var
+  extstring: PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString(GL_EXTENSIONS);
+
+  if glext_ExtensionSupported('GL_EXT_texture_compression_dxt1', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_ARB_pixel_buffer_object: Boolean;
+var
+  extstring: PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString(GL_EXTENSIONS);
+
+  if glext_ExtensionSupported('GL_ARB_pixel_buffer_object', extstring) then
+  begin
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_EXT_framebuffer_object: Boolean;
+var
+  extstring: PChar;
+begin
+
+  Result := FALSE;
+  extstring := glGetString(GL_EXTENSIONS);
+
+  if glext_ExtensionSupported('GL_EXT_framebuffer_object', extstring) then
+  begin
+    glIsRenderbufferEXT := SDL_GL_GetProcAddress('glIsRenderbufferEXT');
+    if not Assigned(glIsRenderbufferEXT) then Exit;
+    glBindRenderbufferEXT := SDL_GL_GetProcAddress('glBindRenderbufferEXT');
+    if not Assigned(glBindRenderbufferEXT) then Exit;
+    glDeleteRenderbuffersEXT := SDL_GL_GetProcAddress('glDeleteRenderbuffersEXT');
+    if not Assigned(glDeleteRenderbuffersEXT) then Exit;
+    glGenRenderbuffersEXT := SDL_GL_GetProcAddress('glGenRenderbuffersEXT');
+    if not Assigned(glGenRenderbuffersEXT) then Exit;
+    glRenderbufferStorageEXT := SDL_GL_GetProcAddress('glRenderbufferStorageEXT');
+    if not Assigned(glRenderbufferStorageEXT) then Exit;
+    glGetRenderbufferParameterivEXT := SDL_GL_GetProcAddress('glGetRenderbufferParameterivEXT');
+    if not Assigned(glGetRenderbufferParameterivEXT) then Exit;
+    glIsFramebufferEXT := SDL_GL_GetProcAddress('glIsFramebufferEXT');
+    if not Assigned(glIsFramebufferEXT) then Exit;
+    glBindFramebufferEXT := SDL_GL_GetProcAddress('glBindFramebufferEXT');
+    if not Assigned(glBindFramebufferEXT) then Exit;
+    glDeleteFramebuffersEXT := SDL_GL_GetProcAddress('glDeleteFramebuffersEXT');
+    if not Assigned(glDeleteFramebuffersEXT) then Exit;
+    glGenFramebuffersEXT := SDL_GL_GetProcAddress('glGenFramebuffersEXT');
+    if not Assigned(glGenFramebuffersEXT) then Exit;
+    glCheckFramebufferStatusEXT := SDL_GL_GetProcAddress('glCheckFramebufferStatusEXT');
+    if not Assigned(glCheckFramebufferStatusEXT) then Exit;
+    glFramebufferTexture1DEXT := SDL_GL_GetProcAddress('glFramebufferTexture1DEXT');
+    if not Assigned(glFramebufferTexture1DEXT) then Exit;
+    glFramebufferTexture2DEXT := SDL_GL_GetProcAddress('glFramebufferTexture2DEXT');
+    if not Assigned(glFramebufferTexture2DEXT) then Exit;
+    glFramebufferTexture3DEXT := SDL_GL_GetProcAddress('glFramebufferTexture3DEXT');
+    if not Assigned(glFramebufferTexture3DEXT) then Exit;
+    glFramebufferRenderbufferEXT := SDL_GL_GetProcAddress('glFramebufferRenderbufferEXT');
+    if not Assigned(glFramebufferRenderbufferEXT) then Exit;
+    glGetFramebufferAttachmentParameterivEXT := SDL_GL_GetProcAddress('glGetFramebufferAttachmentParameterivEXT');
+    if not Assigned(glGetFramebufferAttachmentParameterivEXT) then Exit;
+    glGenerateMipmapEXT := SDL_GL_GetProcAddress('glGenerateMipmapEXT');
+    if not Assigned(glGenerateMipmapEXT) then Exit;
+    Result := TRUE;
+  end;
+
+end;
+
+function Load_GL_version_1_4: Boolean;
+var
+  extstring: String;
+begin
+
+  Result := FALSE;
+  extstring := String(PChar(glGetString(GL_EXTENSIONS)));
+
+    glBlendFuncSeparate := SDL_GL_GetProcAddress('glBlendFuncSeparate');
+    if not Assigned(glBlendFuncSeparate) then Exit;
+    glFogCoordf := SDL_GL_GetProcAddress('glFogCoordf');
+    if not Assigned(glFogCoordf) then Exit;
+    glFogCoordfv := SDL_GL_GetProcAddress('glFogCoordfv');
+    if not Assigned(glFogCoordfv) then Exit;
+    glFogCoordd := SDL_GL_GetProcAddress('glFogCoordd');
+    if not Assigned(glFogCoordd) then Exit;
+    glFogCoorddv := SDL_GL_GetProcAddress('glFogCoorddv');
+    if not Assigned(glFogCoorddv) then Exit;
+    glFogCoordPointer := SDL_GL_GetProcAddress('glFogCoordPointer');
+    if not Assigned(glFogCoordPointer) then Exit;
+    glMultiDrawArrays := SDL_GL_GetProcAddress('glMultiDrawArrays');
+    if not Assigned(glMultiDrawArrays) then Exit;
+    glMultiDrawElements := SDL_GL_GetProcAddress('glMultiDrawElements');
+    if not Assigned(glMultiDrawElements) then Exit;
+    glPointParameterf := SDL_GL_GetProcAddress('glPointParameterf');
+    if not Assigned(glPointParameterf) then Exit;
+    glPointParameterfv := SDL_GL_GetProcAddress('glPointParameterfv');
+    if not Assigned(glPointParameterfv) then Exit;
+    glPointParameteri := SDL_GL_GetProcAddress('glPointParameteri');
+    if not Assigned(glPointParameteri) then Exit;
+    glPointParameteriv := SDL_GL_GetProcAddress('glPointParameteriv');
+    if not Assigned(glPointParameteriv) then Exit;
+    glSecondaryColor3b := SDL_GL_GetProcAddress('glSecondaryColor3b');
+    if not Assigned(glSecondaryColor3b) then Exit;
+    glSecondaryColor3bv := SDL_GL_GetProcAddress('glSecondaryColor3bv');
+    if not Assigned(glSecondaryColor3bv) then Exit;
+    glSecondaryColor3d := SDL_GL_GetProcAddress('glSecondaryColor3d');
+    if not Assigned(glSecondaryColor3d) then Exit;
+    glSecondaryColor3dv := SDL_GL_GetProcAddress('glSecondaryColor3dv');
+    if not Assigned(glSecondaryColor3dv) then Exit;
+    glSecondaryColor3f := SDL_GL_GetProcAddress('glSecondaryColor3f');
+    if not Assigned(glSecondaryColor3f) then Exit;
+    glSecondaryColor3fv := SDL_GL_GetProcAddress('glSecondaryColor3fv');
+    if not Assigned(glSecondaryColor3fv) then Exit;
+    glSecondaryColor3i := SDL_GL_GetProcAddress('glSecondaryColor3i');
+    if not Assigned(glSecondaryColor3i) then Exit;
+    glSecondaryColor3iv := SDL_GL_GetProcAddress('glSecondaryColor3iv');
+    if not Assigned(glSecondaryColor3iv) then Exit;
+    glSecondaryColor3s := SDL_GL_GetProcAddress('glSecondaryColor3s');
+    if not Assigned(glSecondaryColor3s) then Exit;
+    glSecondaryColor3sv := SDL_GL_GetProcAddress('glSecondaryColor3sv');
+    if not Assigned(glSecondaryColor3sv) then Exit;
+    glSecondaryColor3ub := SDL_GL_GetProcAddress('glSecondaryColor3ub');
+    if not Assigned(glSecondaryColor3ub) then Exit;
+    glSecondaryColor3ubv := SDL_GL_GetProcAddress('glSecondaryColor3ubv');
+    if not Assigned(glSecondaryColor3ubv) then Exit;
+    glSecondaryColor3ui := SDL_GL_GetProcAddress('glSecondaryColor3ui');
+    if not Assigned(glSecondaryColor3ui) then Exit;
+    glSecondaryColor3uiv := SDL_GL_GetProcAddress('glSecondaryColor3uiv');
+    if not Assigned(glSecondaryColor3uiv) then Exit;
+    glSecondaryColor3us := SDL_GL_GetProcAddress('glSecondaryColor3us');
+    if not Assigned(glSecondaryColor3us) then Exit;
+    glSecondaryColor3usv := SDL_GL_GetProcAddress('glSecondaryColor3usv');
+    if not Assigned(glSecondaryColor3usv) then Exit;
+    glSecondaryColorPointer := SDL_GL_GetProcAddress('glSecondaryColorPointer');
+    if not Assigned(glSecondaryColorPointer) then Exit;
+    glWindowPos2d := SDL_GL_GetProcAddress('glWindowPos2d');
+    if not Assigned(glWindowPos2d) then Exit;
+    glWindowPos2dv := SDL_GL_GetProcAddress('glWindowPos2dv');
+    if not Assigned(glWindowPos2dv) then Exit;
+    glWindowPos2f := SDL_GL_GetProcAddress('glWindowPos2f');
+    if not Assigned(glWindowPos2f) then Exit;
+    glWindowPos2fv := SDL_GL_GetProcAddress('glWindowPos2fv');
+    if not Assigned(glWindowPos2fv) then Exit;
+    glWindowPos2i := SDL_GL_GetProcAddress('glWindowPos2i');
+    if not Assigned(glWindowPos2i) then Exit;
+    glWindowPos2iv := SDL_GL_GetProcAddress('glWindowPos2iv');
+    if not Assigned(glWindowPos2iv) then Exit;
+    glWindowPos2s := SDL_GL_GetProcAddress('glWindowPos2s');
+    if not Assigned(glWindowPos2s) then Exit;
+    glWindowPos2sv := SDL_GL_GetProcAddress('glWindowPos2sv');
+    if not Assigned(glWindowPos2sv) then Exit;
+    glWindowPos3d := SDL_GL_GetProcAddress('glWindowPos3d');
+    if not Assigned(glWindowPos3d) then Exit;
+    glWindowPos3dv := SDL_GL_GetProcAddress('glWindowPos3dv');
+    if not Assigned(glWindowPos3dv) then Exit;
+    glWindowPos3f := SDL_GL_GetProcAddress('glWindowPos3f');
+    if not Assigned(glWindowPos3f) then Exit;
+    glWindowPos3fv := SDL_GL_GetProcAddress('glWindowPos3fv');
+    if not Assigned(glWindowPos3fv) then Exit;
+    glWindowPos3i := SDL_GL_GetProcAddress('glWindowPos3i');
+    if not Assigned(glWindowPos3i) then Exit;
+    glWindowPos3iv := SDL_GL_GetProcAddress('glWindowPos3iv');
+    if not Assigned(glWindowPos3iv) then Exit;
+    glWindowPos3s := SDL_GL_GetProcAddress('glWindowPos3s');
+    if not Assigned(glWindowPos3s) then Exit;
+    glWindowPos3sv := SDL_GL_GetProcAddress('glWindowPos3sv');
+    if not Assigned(glWindowPos3sv) then Exit;
+    Result := TRUE;
+
+end;
+
+function Load_GL_version_1_5: Boolean;
+var
+  extstring: String;
+begin
+
+  Result := FALSE;
+  extstring := String(PChar(glGetString(GL_EXTENSIONS)));
+
+    glGenQueries := SDL_GL_GetProcAddress('glGenQueries');
+    if not Assigned(glGenQueries) then Exit;
+    glDeleteQueries := SDL_GL_GetProcAddress('glDeleteQueries');
+    if not Assigned(glDeleteQueries) then Exit;
+    glIsQuery := SDL_GL_GetProcAddress('glIsQuery');
+    if not Assigned(glIsQuery) then Exit;
+    glBeginQuery := SDL_GL_GetProcAddress('glBeginQuery');
+    if not Assigned(glBeginQuery) then Exit;
+    glEndQuery := SDL_GL_GetProcAddress('glEndQuery');
+    if not Assigned(glEndQuery) then Exit;
+    glGetQueryiv := SDL_GL_GetProcAddress('glGetQueryiv');
+    if not Assigned(glGetQueryiv) then Exit;
+    glGetQueryObjectiv := SDL_GL_GetProcAddress('glGetQueryObjectiv');
+    if not Assigned(glGetQueryObjectiv) then Exit;
+    glGetQueryObjectuiv := SDL_GL_GetProcAddress('glGetQueryObjectuiv');
+    if not Assigned(glGetQueryObjectuiv) then Exit;
+    glBindBuffer := SDL_GL_GetProcAddress('glBindBuffer');
+    if not Assigned(glBindBuffer) then Exit;
+    glDeleteBuffers := SDL_GL_GetProcAddress('glDeleteBuffers');
+    if not Assigned(glDeleteBuffers) then Exit;
+    glGenBuffers := SDL_GL_GetProcAddress('glGenBuffers');
+    if not Assigned(glGenBuffers) then Exit;
+    glIsBuffer := SDL_GL_GetProcAddress('glIsBuffer');
+    if not Assigned(glIsBuffer) then Exit;
+    glBufferData := SDL_GL_GetProcAddress('glBufferData');
+    if not Assigned(glBufferData) then Exit;
+    glBufferSubData := SDL_GL_GetProcAddress('glBufferSubData');
+    if not Assigned(glBufferSubData) then Exit;
+    glGetBufferSubData := SDL_GL_GetProcAddress('glGetBufferSubData');
+    if not Assigned(glGetBufferSubData) then Exit;
+    glMapBuffer := SDL_GL_GetProcAddress('glMapBuffer');
+    if not Assigned(glMapBuffer) then Exit;
+    glUnmapBuffer := SDL_GL_GetProcAddress('glUnmapBuffer');
+    if not Assigned(glUnmapBuffer) then Exit;
+    glGetBufferParameteriv := SDL_GL_GetProcAddress('glGetBufferParameteriv');
+    if not Assigned(glGetBufferParameteriv) then Exit;
+    glGetBufferPointerv := SDL_GL_GetProcAddress('glGetBufferPointerv');
+    if not Assigned(glGetBufferPointerv) then Exit;
+    Result := TRUE;
+
+end;
+
+function Load_GL_version_2_0: Boolean;
+var
+  extstring: String;
+begin
+
+  Result := FALSE;
+  extstring := String(PChar(glGetString(GL_EXTENSIONS)));
+
+    glBlendEquationSeparate := SDL_GL_GetProcAddress('glBlendEquationSeparate');
+    if not Assigned(glBlendEquationSeparate) then Exit;
+    glDrawBuffers := SDL_GL_GetProcAddress('glDrawBuffers');
+    if not Assigned(glDrawBuffers) then Exit;
+    glStencilOpSeparate := SDL_GL_GetProcAddress('glStencilOpSeparate');
+    if not Assigned(glStencilOpSeparate) then Exit;
+    glStencilFuncSeparate := SDL_GL_GetProcAddress('glStencilFuncSeparate');
+    if not Assigned(glStencilFuncSeparate) then Exit;
+    glStencilMaskSeparate := SDL_GL_GetProcAddress('glStencilMaskSeparate');
+    if not Assigned(glStencilMaskSeparate) then Exit;
+    glAttachShader := SDL_GL_GetProcAddress('glAttachShader');
+    if not Assigned(glAttachShader) then Exit;
+    glBindAttribLocation := SDL_GL_GetProcAddress('glBindAttribLocation');
+    if not Assigned(glBindAttribLocation) then Exit;
+    glCompileShader := SDL_GL_GetProcAddress('glCompileShader');
+    if not Assigned(glCompileShader) then Exit;
+    glCreateProgram := SDL_GL_GetProcAddress('glCreateProgram');
+    if not Assigned(glCreateProgram) then Exit;
+    glCreateShader := SDL_GL_GetProcAddress('glCreateShader');
+    if not Assigned(glCreateShader) then Exit;
+    glDeleteProgram := SDL_GL_GetProcAddress('glDeleteProgram');
+    if not Assigned(glDeleteProgram) then Exit;
+    glDeleteShader := SDL_GL_GetProcAddress('glDeleteShader');
+    if not Assigned(glDeleteShader) then Exit;
+    glDetachShader := SDL_GL_GetProcAddress('glDetachShader');
+    if not Assigned(glDetachShader) then Exit;
+    glDisableVertexAttribArray := SDL_GL_GetProcAddress('glDisableVertexAttribArray');
+    if not Assigned(glDisableVertexAttribArray) then Exit;
+    glEnableVertexAttribArray := SDL_GL_GetProcAddress('glEnableVertexAttribArray');
+    if not Assigned(glEnableVertexAttribArray) then Exit;
+    glGetActiveAttrib := SDL_GL_GetProcAddress('glGetActiveAttrib');
+    if not Assigned(glGetActiveAttrib) then Exit;
+    glGetActiveUniform := SDL_GL_GetProcAddress('glGetActiveUniform');
+    if not Assigned(glGetActiveUniform) then Exit;
+    glGetAttachedShaders := SDL_GL_GetProcAddress('glGetAttachedShaders');
+    if not Assigned(glGetAttachedShaders) then Exit;
+    glGetAttribLocation := SDL_GL_GetProcAddress('glGetAttribLocation');
+    if not Assigned(glGetAttribLocation) then Exit;
+    glGetProgramiv := SDL_GL_GetProcAddress('glGetProgramiv');
+    if not Assigned(glGetProgramiv) then Exit;
+    glGetProgramInfoLog := SDL_GL_GetProcAddress('glGetProgramInfoLog');
+    if not Assigned(glGetProgramInfoLog) then Exit;
+    glGetShaderiv := SDL_GL_GetProcAddress('glGetShaderiv');
+    if not Assigned(glGetShaderiv) then Exit;
+    glGetShaderInfoLog := SDL_GL_GetProcAddress('glGetShaderInfoLog');
+    if not Assigned(glGetShaderInfoLog) then Exit;
+    glGetShaderSource := SDL_GL_GetProcAddress('glGetShaderSource');
+    if not Assigned(glGetShaderSource) then Exit;
+    glGetUniformLocation := SDL_GL_GetProcAddress('glGetUniformLocation');
+    if not Assigned(glGetUniformLocation) then Exit;
+    glGetUniformfv := SDL_GL_GetProcAddress('glGetUniformfv');
+    if not Assigned(glGetUniformfv) then Exit;
+    glGetUniformiv := SDL_GL_GetProcAddress('glGetUniformiv');
+    if not Assigned(glGetUniformiv) then Exit;
+    glGetVertexAttribdv := SDL_GL_GetProcAddress('glGetVertexAttribdv');
+    if not Assigned(glGetVertexAttribdv) then Exit;
+    glGetVertexAttribfv := SDL_GL_GetProcAddress('glGetVertexAttribfv');
+    if not Assigned(glGetVertexAttribfv) then Exit;
+    glGetVertexAttribiv := SDL_GL_GetProcAddress('glGetVertexAttribiv');
+    if not Assigned(glGetVertexAttribiv) then Exit;
+    glGetVertexAttribPointerv := SDL_GL_GetProcAddress('glGetVertexAttribPointerv');
+    if not Assigned(glGetVertexAttribPointerv) then Exit;
+    glIsProgram := SDL_GL_GetProcAddress('glIsProgram');
+    if not Assigned(glIsProgram) then Exit;
+    glIsShader := SDL_GL_GetProcAddress('glIsShader');
+    if not Assigned(glIsShader) then Exit;
+    glLinkProgram := SDL_GL_GetProcAddress('glLinkProgram');
+    if not Assigned(glLinkProgram) then Exit;
+    glShaderSource := SDL_GL_GetProcAddress('glShaderSource');
+    if not Assigned(glShaderSource) then Exit;
+    glUseProgram := SDL_GL_GetProcAddress('glUseProgram');
+    if not Assigned(glUseProgram) then Exit;
+    glUniform1f := SDL_GL_GetProcAddress('glUniform1f');
+    if not Assigned(glUniform1f) then Exit;
+    glUniform2f := SDL_GL_GetProcAddress('glUniform2f');
+    if not Assigned(glUniform2f) then Exit;
+    glUniform3f := SDL_GL_GetProcAddress('glUniform3f');
+    if not Assigned(glUniform3f) then Exit;
+    glUniform4f := SDL_GL_GetProcAddress('glUniform4f');
+    if not Assigned(glUniform4f) then Exit;
+    glUniform1i := SDL_GL_GetProcAddress('glUniform1i');
+    if not Assigned(glUniform1i) then Exit;
+    glUniform2i := SDL_GL_GetProcAddress('glUniform2i');
+    if not Assigned(glUniform2i) then Exit;
+    glUniform3i := SDL_GL_GetProcAddress('glUniform3i');
+    if not Assigned(glUniform3i) then Exit;
+    glUniform4i := SDL_GL_GetProcAddress('glUniform4i');
+    if not Assigned(glUniform4i) then Exit;
+    glUniform1fv := SDL_GL_GetProcAddress('glUniform1fv');
+    if not Assigned(glUniform1fv) then Exit;
+    glUniform2fv := SDL_GL_GetProcAddress('glUniform2fv');
+    if not Assigned(glUniform2fv) then Exit;
+    glUniform3fv := SDL_GL_GetProcAddress('glUniform3fv');
+    if not Assigned(glUniform3fv) then Exit;
+    glUniform4fv := SDL_GL_GetProcAddress('glUniform4fv');
+    if not Assigned(glUniform4fv) then Exit;
+    glUniform1iv := SDL_GL_GetProcAddress('glUniform1iv');
+    if not Assigned(glUniform1iv) then Exit;
+    glUniform2iv := SDL_GL_GetProcAddress('glUniform2iv');
+    if not Assigned(glUniform2iv) then Exit;
+    glUniform3iv := SDL_GL_GetProcAddress('glUniform3iv');
+    if not Assigned(glUniform3iv) then Exit;
+    glUniform4iv := SDL_GL_GetProcAddress('glUniform4iv');
+    if not Assigned(glUniform4iv) then Exit;
+    glUniformMatrix2fv := SDL_GL_GetProcAddress('glUniformMatrix2fv');
+    if not Assigned(glUniformMatrix2fv) then Exit;
+    glUniformMatrix3fv := SDL_GL_GetProcAddress('glUniformMatrix3fv');
+    if not Assigned(glUniformMatrix3fv) then Exit;
+    glUniformMatrix4fv := SDL_GL_GetProcAddress('glUniformMatrix4fv');
+    if not Assigned(glUniformMatrix4fv) then Exit;
+    glValidateProgram := SDL_GL_GetProcAddress('glValidateProgram');
+    if not Assigned(glValidateProgram) then Exit;
+    glVertexAttrib1d := SDL_GL_GetProcAddress('glVertexAttrib1d');
+    if not Assigned(glVertexAttrib1d) then Exit;
+    glVertexAttrib1dv := SDL_GL_GetProcAddress('glVertexAttrib1dv');
+    if not Assigned(glVertexAttrib1dv) then Exit;
+    glVertexAttrib1f := SDL_GL_GetProcAddress('glVertexAttrib1f');
+    if not Assigned(glVertexAttrib1f) then Exit;
+    glVertexAttrib1fv := SDL_GL_GetProcAddress('glVertexAttrib1fv');
+    if not Assigned(glVertexAttrib1fv) then Exit;
+    glVertexAttrib1s := SDL_GL_GetProcAddress('glVertexAttrib1s');
+    if not Assigned(glVertexAttrib1s) then Exit;
+    glVertexAttrib1sv := SDL_GL_GetProcAddress('glVertexAttrib1sv');
+    if not Assigned(glVertexAttrib1sv) then Exit;
+    glVertexAttrib2d := SDL_GL_GetProcAddress('glVertexAttrib2d');
+    if not Assigned(glVertexAttrib2d) then Exit;
+    glVertexAttrib2dv := SDL_GL_GetProcAddress('glVertexAttrib2dv');
+    if not Assigned(glVertexAttrib2dv) then Exit;
+    glVertexAttrib2f := SDL_GL_GetProcAddress('glVertexAttrib2f');
+    if not Assigned(glVertexAttrib2f) then Exit;
+    glVertexAttrib2fv := SDL_GL_GetProcAddress('glVertexAttrib2fv');
+    if not Assigned(glVertexAttrib2fv) then Exit;
+    glVertexAttrib2s := SDL_GL_GetProcAddress('glVertexAttrib2s');
+    if not Assigned(glVertexAttrib2s) then Exit;
+    glVertexAttrib2sv := SDL_GL_GetProcAddress('glVertexAttrib2sv');
+    if not Assigned(glVertexAttrib2sv) then Exit;
+    glVertexAttrib3d := SDL_GL_GetProcAddress('glVertexAttrib3d');
+    if not Assigned(glVertexAttrib3d) then Exit;
+    glVertexAttrib3dv := SDL_GL_GetProcAddress('glVertexAttrib3dv');
+    if not Assigned(glVertexAttrib3dv) then Exit;
+    glVertexAttrib3f := SDL_GL_GetProcAddress('glVertexAttrib3f');
+    if not Assigned(glVertexAttrib3f) then Exit;
+    glVertexAttrib3fv := SDL_GL_GetProcAddress('glVertexAttrib3fv');
+    if not Assigned(glVertexAttrib3fv) then Exit;
+    glVertexAttrib3s := SDL_GL_GetProcAddress('glVertexAttrib3s');
+    if not Assigned(glVertexAttrib3s) then Exit;
+    glVertexAttrib3sv := SDL_GL_GetProcAddress('glVertexAttrib3sv');
+    if not Assigned(glVertexAttrib3sv) then Exit;
+    glVertexAttrib4Nbv := SDL_GL_GetProcAddress('glVertexAttrib4Nbv');
+    if not Assigned(glVertexAttrib4Nbv) then Exit;
+    glVertexAttrib4Niv := SDL_GL_GetProcAddress('glVertexAttrib4Niv');
+    if not Assigned(glVertexAttrib4Niv) then Exit;
+    glVertexAttrib4Nsv := SDL_GL_GetProcAddress('glVertexAttrib4Nsv');
+    if not Assigned(glVertexAttrib4Nsv) then Exit;
+    glVertexAttrib4Nub := SDL_GL_GetProcAddress('glVertexAttrib4Nub');
+    if not Assigned(glVertexAttrib4Nub) then Exit;
+    glVertexAttrib4Nubv := SDL_GL_GetProcAddress('glVertexAttrib4Nubv');
+    if not Assigned(glVertexAttrib4Nubv) then Exit;
+    glVertexAttrib4Nuiv := SDL_GL_GetProcAddress('glVertexAttrib4Nuiv');
+    if not Assigned(glVertexAttrib4Nuiv) then Exit;
+    glVertexAttrib4Nusv := SDL_GL_GetProcAddress('glVertexAttrib4Nusv');
+    if not Assigned(glVertexAttrib4Nusv) then Exit;
+    glVertexAttrib4bv := SDL_GL_GetProcAddress('glVertexAttrib4bv');
+    if not Assigned(glVertexAttrib4bv) then Exit;
+    glVertexAttrib4d := SDL_GL_GetProcAddress('glVertexAttrib4d');
+    if not Assigned(glVertexAttrib4d) then Exit;
+    glVertexAttrib4dv := SDL_GL_GetProcAddress('glVertexAttrib4dv');
+    if not Assigned(glVertexAttrib4dv) then Exit;
+    glVertexAttrib4f := SDL_GL_GetProcAddress('glVertexAttrib4f');
+    if not Assigned(glVertexAttrib4f) then Exit;
+    glVertexAttrib4fv := SDL_GL_GetProcAddress('glVertexAttrib4fv');
+    if not Assigned(glVertexAttrib4fv) then Exit;
+    glVertexAttrib4iv := SDL_GL_GetProcAddress('glVertexAttrib4iv');
+    if not Assigned(glVertexAttrib4iv) then Exit;
+    glVertexAttrib4s := SDL_GL_GetProcAddress('glVertexAttrib4s');
+    if not Assigned(glVertexAttrib4s) then Exit;
+    glVertexAttrib4sv := SDL_GL_GetProcAddress('glVertexAttrib4sv');
+    if not Assigned(glVertexAttrib4sv) then Exit;
+    glVertexAttrib4ubv := SDL_GL_GetProcAddress('glVertexAttrib4ubv');
+    if not Assigned(glVertexAttrib4ubv) then Exit;
+    glVertexAttrib4uiv := SDL_GL_GetProcAddress('glVertexAttrib4uiv');
+    if not Assigned(glVertexAttrib4uiv) then Exit;
+    glVertexAttrib4usv := SDL_GL_GetProcAddress('glVertexAttrib4usv');
+    if not Assigned(glVertexAttrib4usv) then Exit;
+    glVertexAttribPointer := SDL_GL_GetProcAddress('glVertexAttribPointer');
+    if not Assigned(glVertexAttribPointer) then Exit;
+    Result := TRUE;
+
+end;
+
+function glext_LoadExtension(ext: String): Boolean;
+begin
+
+  Result := FALSE;
+
+  if ext = 'GL_version_1_2' then Result := Load_GL_version_1_2
+  else if ext = 'GL_ARB_imaging' then Result := Load_GL_ARB_imaging
+  else if ext = 'GL_version_1_3' then Result := Load_GL_version_1_3
+  else if ext = 'GL_ARB_multitexture' then Result := Load_GL_ARB_multitexture
+  else if ext = 'GL_ARB_transpose_matrix' then Result := Load_GL_ARB_transpose_matrix
+  else if ext = 'GL_ARB_multisample' then Result := Load_GL_ARB_multisample
+  else if ext = 'GL_ARB_texture_env_add' then Result := Load_GL_ARB_texture_env_add
+  {$IFDEF WINDOWS}
+  else if ext = 'WGL_ARB_extensions_string' then Result := Load_WGL_ARB_extensions_string
+  else if ext = 'WGL_ARB_buffer_region' then Result := Load_WGL_ARB_buffer_region
+  {$ENDIF}
+  else if ext = 'GL_ARB_texture_cube_map' then Result := Load_GL_ARB_texture_cube_map
+  else if ext = 'GL_ARB_depth_texture' then Result := Load_GL_ARB_depth_texture
+  else if ext = 'GL_ARB_point_parameters' then Result := Load_GL_ARB_point_parameters
+  else if ext = 'GL_ARB_shadow' then Result := Load_GL_ARB_shadow
+  else if ext = 'GL_ARB_shadow_ambient' then Result := Load_GL_ARB_shadow_ambient
+  else if ext = 'GL_ARB_texture_border_clamp' then Result := Load_GL_ARB_texture_border_clamp
+  else if ext = 'GL_ARB_texture_compression' then Result := Load_GL_ARB_texture_compression
+  else if ext = 'GL_ARB_texture_env_combine' then Result := Load_GL_ARB_texture_env_combine
+  else if ext = 'GL_ARB_texture_env_crossbar' then Result := Load_GL_ARB_texture_env_crossbar
+  else if ext = 'GL_ARB_texture_env_dot3' then Result := Load_GL_ARB_texture_env_dot3
+  else if ext = 'GL_ARB_texture_mirrored_repeat' then Result := Load_GL_ARB_texture_mirrored_repeat
+  else if ext = 'GL_ARB_vertex_blend' then Result := Load_GL_ARB_vertex_blend
+  else if ext = 'GL_ARB_vertex_program' then Result := Load_GL_ARB_vertex_program
+  else if ext = 'GL_ARB_window_pos' then Result := Load_GL_ARB_window_pos
+  else if ext = 'GL_EXT_422_pixels' then Result := Load_GL_EXT_422_pixels
+  else if ext = 'GL_EXT_abgr' then Result := Load_GL_EXT_abgr
+  else if ext = 'GL_EXT_bgra' then Result := Load_GL_EXT_bgra
+  else if ext = 'GL_EXT_blend_color' then Result := Load_GL_EXT_blend_color
+  else if ext = 'GL_EXT_blend_func_separate' then Result := Load_GL_EXT_blend_func_separate
+  else if ext = 'GL_EXT_blend_logic_op' then Result := Load_GL_EXT_blend_logic_op
+  else if ext = 'GL_EXT_blend_minmax' then Result := Load_GL_EXT_blend_minmax
+  else if ext = 'GL_EXT_blend_subtract' then Result := Load_GL_EXT_blend_subtract
+  else if ext = 'GL_EXT_clip_volume_hint' then Result := Load_GL_EXT_clip_volume_hint
+  else if ext = 'GL_EXT_color_subtable' then Result := Load_GL_EXT_color_subtable
+  else if ext = 'GL_EXT_compiled_vertex_array' then Result := Load_GL_EXT_compiled_vertex_array
+  else if ext = 'GL_EXT_convolution' then Result := Load_GL_EXT_convolution
+  else if ext = 'GL_EXT_histogram' then Result := Load_GL_EXT_histogram
+  else if ext = 'GL_EXT_multi_draw_arrays' then Result := Load_GL_EXT_multi_draw_arrays
+  else if ext = 'GL_EXT_packed_pixels' then Result := Load_GL_EXT_packed_pixels
+  else if ext = 'GL_EXT_paletted_texture' then Result := Load_GL_EXT_paletted_texture
+  else if ext = 'GL_EXT_point_parameters' then Result := Load_GL_EXT_point_parameters
+  else if ext = 'GL_EXT_polygon_offset' then Result := Load_GL_EXT_polygon_offset
+  else if ext = 'GL_EXT_separate_specular_color' then Result := Load_GL_EXT_separate_specular_color
+  else if ext = 'GL_EXT_shadow_funcs' then Result := Load_GL_EXT_shadow_funcs
+  else if ext = 'GL_EXT_shared_texture_palette' then Result := Load_GL_EXT_shared_texture_palette
+  else if ext = 'GL_EXT_stencil_two_side' then Result := Load_GL_EXT_stencil_two_side
+  else if ext = 'GL_EXT_stencil_wrap' then Result := Load_GL_EXT_stencil_wrap
+  else if ext = 'GL_EXT_subtexture' then Result := Load_GL_EXT_subtexture
+  else if ext = 'GL_EXT_texture3D' then Result := Load_GL_EXT_texture3D
+  else if ext = 'GL_EXT_texture_compression_s3tc' then Result := Load_GL_EXT_texture_compression_s3tc
+  else if ext = 'GL_EXT_texture_env_add' then Result := Load_GL_EXT_texture_env_add
+  else if ext = 'GL_EXT_texture_env_combine' then Result := Load_GL_EXT_texture_env_combine
+  else if ext = 'GL_EXT_texture_env_dot3' then Result := Load_GL_EXT_texture_env_dot3
+  else if ext = 'GL_EXT_texture_filter_anisotropic' then Result := Load_GL_EXT_texture_filter_anisotropic
+  else if ext = 'GL_EXT_texture_lod_bias' then Result := Load_GL_EXT_texture_lod_bias
+  else if ext = 'GL_EXT_texture_object' then Result := Load_GL_EXT_texture_object
+  else if ext = 'GL_EXT_vertex_array' then Result := Load_GL_EXT_vertex_array
+  else if ext = 'GL_EXT_vertex_shader' then Result := Load_GL_EXT_vertex_shader
+  else if ext = 'GL_EXT_vertex_weighting' then Result := Load_GL_EXT_vertex_weighting
+  else if ext = 'GL_HP_occlusion_test' then Result := Load_GL_HP_occlusion_test
+  else if ext = 'GL_NV_blend_square' then Result := Load_GL_NV_blend_square
+  else if ext = 'GL_NV_copy_depth_to_color' then Result := Load_GL_NV_copy_depth_to_color
+  else if ext = 'GL_NV_depth_clamp' then Result := Load_GL_NV_depth_clamp
+  else if ext = 'GL_NV_evaluators' then Result := Load_GL_NV_evaluators
+  else if ext = 'GL_NV_fence' then Result := Load_GL_NV_fence
+  else if ext = 'GL_NV_fog_distance' then Result := Load_GL_NV_fog_distance
+  else if ext = 'GL_NV_light_max_exponent' then Result := Load_GL_NV_light_max_exponent
+  else if ext = 'GL_NV_multisample_filter_hint' then Result := Load_GL_NV_multisample_filter_hint
+  else if ext = 'GL_NV_occlusion_query' then Result := Load_GL_NV_occlusion_query
+  else if ext = 'GL_NV_packed_depth_stencil' then Result := Load_GL_NV_packed_depth_stencil
+  else if ext = 'GL_NV_point_sprite' then Result := Load_GL_NV_point_sprite
+  else if ext = 'GL_NV_register_combiners' then Result := Load_GL_NV_register_combiners
+  else if ext = 'GL_NV_register_combiners2' then Result := Load_GL_NV_register_combiners2
+  else if ext = 'GL_NV_texgen_emboss' then Result := Load_GL_NV_texgen_emboss
+  else if ext = 'GL_NV_texgen_reflection' then Result := Load_GL_NV_texgen_reflection
+  else if ext = 'GL_NV_texture_compression_vtc' then Result := Load_GL_NV_texture_compression_vtc
+  else if ext = 'GL_NV_texture_env_combine4' then Result := Load_GL_NV_texture_env_combine4
+  else if ext = 'GL_NV_texture_rectangle' then Result := Load_GL_NV_texture_rectangle
+  else if ext = 'GL_NV_texture_shader' then Result := Load_GL_NV_texture_shader
+  else if ext = 'GL_NV_texture_shader2' then Result := Load_GL_NV_texture_shader2
+  else if ext = 'GL_NV_texture_shader3' then Result := Load_GL_NV_texture_shader3
+  else if ext = 'GL_NV_vertex_array_range' then Result := Load_GL_NV_vertex_array_range
+  else if ext = 'GL_NV_vertex_array_range2' then Result := Load_GL_NV_vertex_array_range2
+  else if ext = 'GL_NV_vertex_program' then Result := Load_GL_NV_vertex_program
+  else if ext = 'GL_NV_vertex_program1_1' then Result := Load_GL_NV_vertex_program1_1
+  else if ext = 'GL_ATI_element_array' then Result := Load_GL_ATI_element_array
+  else if ext = 'GL_ATI_envmap_bumpmap' then Result := Load_GL_ATI_envmap_bumpmap
+  else if ext = 'GL_ATI_fragment_shader' then Result := Load_GL_ATI_fragment_shader
+  else if ext = 'GL_ATI_pn_triangles' then Result := Load_GL_ATI_pn_triangles
+  else if ext = 'GL_ATI_texture_mirror_once' then Result := Load_GL_ATI_texture_mirror_once
+  else if ext = 'GL_ATI_vertex_array_object' then Result := Load_GL_ATI_vertex_array_object
+  else if ext = 'GL_ATI_vertex_streams' then Result := Load_GL_ATI_vertex_streams
+  {$IFDEF WINDOWS}
+  else if ext = 'WGL_I3D_image_buffer' then Result := Load_WGL_I3D_image_buffer
+  else if ext = 'WGL_I3D_swap_frame_lock' then Result := Load_WGL_I3D_swap_frame_lock
+  else if ext = 'WGL_I3D_swap_frame_usage' then Result := Load_WGL_I3D_swap_frame_usage
+  {$ENDIF}
+  else if ext = 'GL_3DFX_texture_compression_FXT1' then Result := Load_GL_3DFX_texture_compression_FXT1
+  else if ext = 'GL_IBM_cull_vertex' then Result := Load_GL_IBM_cull_vertex
+  else if ext = 'GL_IBM_multimode_draw_arrays' then Result := Load_GL_IBM_multimode_draw_arrays
+  else if ext = 'GL_IBM_raster_pos_clip' then Result := Load_GL_IBM_raster_pos_clip
+  else if ext = 'GL_IBM_texture_mirrored_repeat' then Result := Load_GL_IBM_texture_mirrored_repeat
+  else if ext = 'GL_IBM_vertex_array_lists' then Result := Load_GL_IBM_vertex_array_lists
+  else if ext = 'GL_MESA_resize_buffers' then Result := Load_GL_MESA_resize_buffers
+  else if ext = 'GL_MESA_window_pos' then Result := Load_GL_MESA_window_pos
+  else if ext = 'GL_OML_interlace' then Result := Load_GL_OML_interlace
+  else if ext = 'GL_OML_resample' then Result := Load_GL_OML_resample
+  else if ext = 'GL_OML_subsample' then Result := Load_GL_OML_subsample
+  else if ext = 'GL_SGIS_generate_mipmap' then Result := Load_GL_SGIS_generate_mipmap
+  else if ext = 'GL_SGIS_multisample' then Result := Load_GL_SGIS_multisample
+  else if ext = 'GL_SGIS_pixel_texture' then Result := Load_GL_SGIS_pixel_texture
+  else if ext = 'GL_SGIS_texture_border_clamp' then Result := Load_GL_SGIS_texture_border_clamp
+  else if ext = 'GL_SGIS_texture_color_mask' then Result := Load_GL_SGIS_texture_color_mask
+  else if ext = 'GL_SGIS_texture_edge_clamp' then Result := Load_GL_SGIS_texture_edge_clamp
+  else if ext = 'GL_SGIS_texture_lod' then Result := Load_GL_SGIS_texture_lod
+  else if ext = 'GL_SGIS_depth_texture' then Result := Load_GL_SGIS_depth_texture
+  else if ext = 'GL_SGIX_fog_offset' then Result := Load_GL_SGIX_fog_offset
+  else if ext = 'GL_SGIX_interlace' then Result := Load_GL_SGIX_interlace
+  else if ext = 'GL_SGIX_shadow_ambient' then Result := Load_GL_SGIX_shadow_ambient
+  else if ext = 'GL_SGI_color_matrix' then Result := Load_GL_SGI_color_matrix
+  else if ext = 'GL_SGI_color_table' then Result := Load_GL_SGI_color_table
+  else if ext = 'GL_SGI_texture_color_table' then Result := Load_GL_SGI_texture_color_table
+  else if ext = 'GL_SUN_vertex' then Result := Load_GL_SUN_vertex
+  else if ext = 'GL_ARB_fragment_program' then Result := Load_GL_ARB_fragment_program
+  else if ext = 'GL_ATI_text_fragment_shader' then Result := Load_GL_ATI_text_fragment_shader
+  else if ext = 'GL_APPLE_client_storage' then Result := Load_GL_APPLE_client_storage
+  else if ext = 'GL_APPLE_element_array' then Result := Load_GL_APPLE_element_array
+  else if ext = 'GL_APPLE_fence' then Result := Load_GL_APPLE_fence
+  else if ext = 'GL_APPLE_vertex_array_object' then Result := Load_GL_APPLE_vertex_array_object
+  else if ext = 'GL_APPLE_vertex_array_range' then Result := Load_GL_APPLE_vertex_array_range
+  {$IFDEF WINDOWS}
+  else if ext = 'WGL_ARB_pixel_format' then Result := Load_WGL_ARB_pixel_format
+  else if ext = 'WGL_ARB_make_current_read' then Result := Load_WGL_ARB_make_current_read
+  else if ext = 'WGL_ARB_pbuffer' then Result := Load_WGL_ARB_pbuffer
+  else if ext = 'WGL_EXT_swap_control' then Result := Load_WGL_EXT_swap_control
+  else if ext = 'WGL_ARB_render_texture' then Result := Load_WGL_ARB_render_texture
+  else if ext = 'WGL_EXT_extensions_string' then Result := Load_WGL_EXT_extensions_string
+  else if ext = 'WGL_EXT_make_current_read' then Result := Load_WGL_EXT_make_current_read
+  else if ext = 'WGL_EXT_pbuffer' then Result := Load_WGL_EXT_pbuffer
+  else if ext = 'WGL_EXT_pixel_format' then Result := Load_WGL_EXT_pixel_format
+  else if ext = 'WGL_I3D_digital_video_control' then Result := Load_WGL_I3D_digital_video_control
+  else if ext = 'WGL_I3D_gamma' then Result := Load_WGL_I3D_gamma
+  else if ext = 'WGL_I3D_genlock' then Result := Load_WGL_I3D_genlock
+  {$ENDIF}
+  else if ext = 'GL_ARB_matrix_palette' then Result := Load_GL_ARB_matrix_palette
+  else if ext = 'GL_NV_element_array' then Result := Load_GL_NV_element_array
+  else if ext = 'GL_NV_float_buffer' then Result := Load_GL_NV_float_buffer
+  else if ext = 'GL_NV_fragment_program' then Result := Load_GL_NV_fragment_program
+  else if ext = 'GL_NV_primitive_restart' then Result := Load_GL_NV_primitive_restart
+  else if ext = 'GL_NV_vertex_program2' then Result := Load_GL_NV_vertex_program2
+  {$IFDEF WINDOWS}
+  else if ext = 'WGL_NV_render_texture_rectangle' then Result := Load_WGL_NV_render_texture_rectangle
+  {$ENDIF}
+  else if ext = 'GL_NV_pixel_data_range' then Result := Load_GL_NV_pixel_data_range
+  else if ext = 'GL_EXT_texture_rectangle' then Result := Load_GL_EXT_texture_rectangle
+  else if ext = 'GL_S3_s3tc' then Result := Load_GL_S3_s3tc
+  else if ext = 'GL_ATI_draw_buffers' then Result := Load_GL_ATI_draw_buffers
+  {$IFDEF WINDOWS}
+  else if ext = 'WGL_ATI_pixel_format_float' then Result := Load_WGL_ATI_pixel_format_float
+  {$ENDIF}
+  else if ext = 'GL_ATI_texture_env_combine3' then Result := Load_GL_ATI_texture_env_combine3
+  else if ext = 'GL_ATI_texture_float' then Result := Load_GL_ATI_texture_float
+  else if ext = 'GL_NV_texture_expand_normal' then Result := Load_GL_NV_texture_expand_normal
+  else if ext = 'GL_NV_half_float' then Result := Load_GL_NV_half_float
+  else if ext = 'GL_ATI_map_object_buffer' then Result := Load_GL_ATI_map_object_buffer
+  else if ext = 'GL_ATI_separate_stencil' then Result := Load_GL_ATI_separate_stencil
+  else if ext = 'GL_ATI_vertex_attrib_array_object' then Result := Load_GL_ATI_vertex_attrib_array_object
+  else if ext = 'GL_ARB_vertex_buffer_object' then Result := Load_GL_ARB_vertex_buffer_object
+  else if ext = 'GL_ARB_occlusion_query' then Result := Load_GL_ARB_occlusion_query
+  else if ext = 'GL_ARB_shader_objects' then Result := Load_GL_ARB_shader_objects
+  else if ext = 'GL_ARB_vertex_shader' then Result := Load_GL_ARB_vertex_shader
+  else if ext = 'GL_ARB_fragment_shader' then Result := Load_GL_ARB_fragment_shader
+  else if ext = 'GL_ARB_shading_language_100' then Result := Load_GL_ARB_shading_language_100
+  else if ext = 'GL_ARB_texture_non_power_of_two' then Result := Load_GL_ARB_texture_non_power_of_two
+  else if ext = 'GL_ARB_point_sprite' then Result := Load_GL_ARB_point_sprite
+  else if ext = 'GL_EXT_depth_bounds_test' then Result := Load_GL_EXT_depth_bounds_test
+  else if ext = 'GL_EXT_secondary_color' then Result := Load_GL_EXT_secondary_color
+  else if ext = 'GL_EXT_texture_mirror_clamp' then Result := Load_GL_EXT_texture_mirror_clamp
+  else if ext = 'GL_EXT_blend_equation_separate' then Result := Load_GL_EXT_blend_equation_separate
+  else if ext = 'GL_MESA_pack_invert' then Result := Load_GL_MESA_pack_invert
+  else if ext = 'GL_MESA_ycbcr_texture' then Result := Load_GL_MESA_ycbcr_texture
+  else if ext = 'GL_ARB_fragment_program_shadow' then Result := Load_GL_ARB_fragment_program_shadow
+  else if ext = 'GL_EXT_fog_coord' then Result := Load_GL_EXT_fog_coord
+  else if ext = 'GL_NV_fragment_program_option' then Result := Load_GL_NV_fragment_program_option
+  else if ext = 'GL_EXT_pixel_buffer_object' then Result := Load_GL_EXT_pixel_buffer_object
+  else if ext = 'GL_NV_fragment_program2' then Result := Load_GL_NV_fragment_program2
+  else if ext = 'GL_NV_vertex_program2_option' then Result := Load_GL_NV_vertex_program2_option
+  else if ext = 'GL_NV_vertex_program3' then Result := Load_GL_NV_vertex_program3
+  else if ext = 'GL_ARB_draw_buffers' then Result := Load_GL_ARB_draw_buffers
+  else if ext = 'GL_ARB_texture_rectangle' then Result := Load_GL_ARB_texture_rectangle
+  else if ext = 'GL_ARB_color_buffer_float' then Result := Load_GL_ARB_color_buffer_float
+  else if ext = 'GL_ARB_half_float_pixel' then Result := Load_GL_ARB_half_float_pixel
+  else if ext = 'GL_ARB_texture_float' then Result := Load_GL_ARB_texture_float
+  else if ext = 'GL_EXT_texture_compression_dxt1' then Result := Load_GL_EXT_texture_compression_dxt1
+  else if ext = 'GL_ARB_pixel_buffer_object' then Result := Load_GL_ARB_pixel_buffer_object
+  else if ext = 'GL_EXT_framebuffer_object' then Result := Load_GL_EXT_framebuffer_object
+  else if ext = 'GL_version_1_4' then Result := Load_GL_version_1_4
+  else if ext = 'GL_version_1_5' then Result := Load_GL_version_1_5
+  else if ext = 'GL_version_2_0' then Result := Load_GL_version_2_0
+
+end;
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas
new file mode 100644
index 00000000..876270ff
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas
@@ -0,0 +1,582 @@
+unit glu;
+{
+  $Id: glu.pas,v 1.8 2007/05/20 20:28:31 savage Exp $
+
+  Adaption of the delphi3d.net OpenGL units to FreePascal
+  Sebastian Guenther (sg@freepascal.org) in 2002
+  These units are free to use
+}
+
+(*++ BUILD Version: 0004    // Increment this if a change has global effects
+
+Copyright (c) 1985-95, Microsoft Corporation
+
+Module Name:
+
+    glu.h
+
+Abstract:
+
+    Procedure declarations, constant definitions and macros for the OpenGL
+    Utility Library.
+
+--*)
+
+(*
+** Copyright 1991-1993, Silicon Graphics, Inc.
+** All Rights Reserved.
+**
+** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
+** the contents of this file may not be disclosed to third parties, copied or
+** duplicated in any form, in whole or in part, without the prior written
+** permission of Silicon Graphics, Inc.
+**
+** RESTRICTED RIGHTS LEGEND:
+** Use, duplication or disclosure by the Government is subject to restrictions
+** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
+** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
+** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
+** rights reserved under the Copyright Laws of the United States.
+*)
+
+(*
+** Return the error string associated with a particular error code.
+** This will return 0 for an invalid error code.
+**
+** The generic function prototype that can be compiled for ANSI or Unicode
+** is defined as follows:
+**
+** LPCTSTR APIENTRY gluErrorStringWIN (GLenum errCode);
+*)
+
+{******************************************************************************}
+{                                                                              }
+{ Converted to Delphi by Tom Nuydens (tom@delphi3d.net)                        }
+{ For the latest updates, visit Delphi3D: http://www.delphi3d.net              }
+{                                                                              }
+{ Modified for Delphi/Kylix and FreePascal                                     }
+{    by Dominique Louis ( Dominique@Savagesoftware.com.au)                     }
+{ For the latest updates, visit JEDI-SDL : http://www.sf.net/projects/jedi-sdl }
+{                                                                              }
+{******************************************************************************}
+
+{
+  $Log: glu.pas,v $
+  Revision 1.8  2007/05/20 20:28:31  savage
+  Initial Changes to Handle 64 Bits
+
+  Revision 1.7  2006/11/26 16:35:49  savage
+  Messed up the last change to GLUtessCombineDataProc, had to reapply it. Thanks Michalis.
+
+  Revision 1.6  2006/11/25 23:38:02  savage
+  Changes as proposed by Michalis Kamburelis for better FPC support
+
+  Revision 1.5  2006/11/20 21:20:59  savage
+  Updated to work in MacOS X
+
+  Revision 1.4  2005/05/22 18:52:09  savage
+  Changes as suggested by Michalis Kamburelis. Thanks again.
+
+  Revision 1.3  2004/10/07 21:01:29  savage
+  Fix for FPC
+
+  Revision 1.2  2004/08/14 22:54:30  savage
+  Updated so that Library name defines are correctly defined for MacOS X.
+
+  Revision 1.1  2004/03/30 21:53:54  savage
+  Moved to it's own folder.
+
+  Revision 1.4  2004/02/20 17:09:55  savage
+  Code tidied up in gl, glu and glut, while extensions in glext.pas are now loaded using SDL_GL_GetProcAddress, thus making it more cross-platform compatible, but now more tied to SDL.
+
+  Revision 1.3  2004/02/14 00:23:39  savage
+  As UNIX is defined in jedi-sdl.inc this will be used to check linux compatability as well. Units have been changed to reflect this change.
+
+  Revision 1.2  2004/02/14 00:09:19  savage
+  Changed uses to now make use of moduleloader.pas rather than dllfuncs.pas
+
+  Revision 1.1  2004/02/05 00:08:19  savage
+  Module 1.0 release
+
+  Revision 1.4  2003/06/02 12:32:13  savage
+  Modified Sources to avoid warnings with Delphi by moving CVS Logging to the top of the header files. Hopefully CVS Logging still works.
+
+  Revision 1.3  2003/05/29 22:55:00  savage
+  Make use of new DLLFunctions
+
+  Revision 1.2  2003/05/27 09:39:53  savage
+  Added better Gnu Pascal support.
+
+  Revision 1.1  2003/05/11 13:18:03  savage
+  Newest OpenGL Headers For Delphi, Kylix and FPC
+
+  Revision 1.2  2002/10/13 14:36:47  sg
+  * Win32 fix: The OS symbol is called "Win32", not "Windows"
+
+  Revision 1.1  2002/10/13 13:57:31  sg
+  * Finally, the new units are available: Match the C headers more closely;
+    support for OpenGL extensions, and much more. Based on the Delphi units
+    by Tom Nuydens of delphi3d.net
+
+}
+
+interface
+
+{$I jedi-sdl.inc}
+
+uses
+{$IFDEF __GPC__}
+  gpc,
+{$ENDIF}
+  moduleloader,
+  gl;
+
+const
+{$IFDEF WINDOWS}
+  GLuLibName   = 'glu32.dll';
+{$ENDIF}
+
+{$IFDEF UNIX}
+{$IFDEF DARWIN}
+  GLuLibName   = '/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib';
+{$ELSE}
+  GLuLibName   = 'libGLU.so.1';
+{$ENDIF}
+{$ENDIF}
+
+type
+  TViewPortArray = array[ 0..3 ] of GLint;
+  T16dArray = array[ 0..15 ] of GLdouble;
+  TCallBack = procedure;
+  T3dArray = array[ 0..2 ] of GLdouble;
+  T4pArray = array[ 0..3 ] of Pointer;
+  T4fArray = array[ 0..3 ] of GLfloat;
+{$IFNDEF __GPC__}
+  PPointer = ^Pointer;
+{$ENDIF}
+
+var
+  gluErrorString : function( errCode : GLenum ) : PChar; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluErrorUnicodeStringEXT : function( errCode : GLenum ) : PWideChar; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluGetString : function( name : GLenum ) : PChar; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluOrtho2D   : procedure( left, right, bottom, top : GLdouble ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluPerspective : procedure( fovy, aspect, zNear, zFar : GLdouble ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluPickMatrix : procedure( x, y, width, height : GLdouble; var viewport : TViewPortArray ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluLookAt    : procedure( eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz : GLdouble ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluProject   : function( objx, objy, objz : GLdouble; var modelMatrix, projMatrix : T16dArray; var viewport : TViewPortArray; winx, winy, winz : PGLdouble ) : Integer; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluUnProject : function( winx, winy, winz : GLdouble; var modelMatrix, projMatrix : T16dArray; var viewport : TViewPortArray; objx, objy, objz : PGLdouble ) : Integer; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluScaleImage : function( format : GLenum; widthin, heightin : GLint; typein : GLenum; const datain : Pointer; widthout, heightout : GLint; typeout : GLenum; dataout : Pointer ) : Integer; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluBuild1DMipmaps : function( target : GLenum; components, width : GLint; format, atype : GLenum; const data : Pointer ) : Integer; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluBuild2DMipmaps : function( target : GLenum; components, width, height : GLint; format, atype : GLenum; const data : Pointer ) : Integer; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+
+type
+  GLUnurbs = record
+  end; PGLUnurbs = ^GLUnurbs;
+  GLUquadric = record
+  end; PGLUquadric = ^GLUquadric;
+  GLUtesselator = record
+  end; PGLUtesselator = ^GLUtesselator;
+
+  // backwards compatibility:
+  GLUnurbsObj = GLUnurbs; PGLUnurbsObj = PGLUnurbs;
+  GLUquadricObj = GLUquadric; PGLUquadricObj = PGLUquadric;
+  GLUtesselatorObj = GLUtesselator; PGLUtesselatorObj = PGLUtesselator;
+  GLUtriangulatorObj = GLUtesselator; PGLUtriangulatorObj = PGLUtesselator;
+
+var
+  gluNewQuadric : function : PGLUquadric; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluDeleteQuadric : procedure( state : PGLUquadric ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluQuadricNormals : procedure( quadObject : PGLUquadric; normals : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluQuadricTexture : procedure( quadObject : PGLUquadric; textureCoords : GLboolean ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluQuadricOrientation : procedure( quadObject : PGLUquadric; orientation : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluQuadricDrawStyle : procedure( quadObject : PGLUquadric; drawStyle : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluCylinder  : procedure( qobj : PGLUquadric; baseRadius, topRadius, height : GLdouble; slices, stacks : GLint ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluDisk      : procedure( qobj : PGLUquadric; innerRadius, outerRadius : GLdouble; slices, loops : GLint ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluPartialDisk : procedure( qobj : PGLUquadric; innerRadius, outerRadius : GLdouble; slices, loops : GLint; startAngle, sweepAngle : GLdouble ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluSphere    : procedure( qobj : PGLuquadric; radius : GLdouble; slices, stacks : GLint ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluQuadricCallback : procedure( qobj : PGLUquadric; which : GLenum; fn : TCallBack ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluNewTess   : function : PGLUtesselator; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluDeleteTess : procedure( tess : PGLUtesselator ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluTessBeginPolygon : procedure( tess : PGLUtesselator; polygon_data : Pointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluTessBeginContour : procedure( tess : PGLUtesselator ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluTessVertex : procedure( tess : PGLUtesselator; var coords : T3dArray; data : Pointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluTessEndContour : procedure( tess : PGLUtesselator ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluTessEndPolygon : procedure( tess : PGLUtesselator ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluTessProperty : procedure( tess : PGLUtesselator; which : GLenum; value : GLdouble ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluTessNormal : procedure( tess : PGLUtesselator; x, y, z : GLdouble ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluTessCallback : procedure( tess : PGLUtesselator; which : GLenum; fn : TCallBack ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluGetTessProperty : procedure( tess : PGLUtesselator; which : GLenum; value : PGLdouble ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluNewNurbsRenderer : function : PGLUnurbs; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluDeleteNurbsRenderer : procedure( nobj : PGLUnurbs ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluBeginSurface : procedure( nobj : PGLUnurbs ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluBeginCurve : procedure( nobj : PGLUnurbs ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluEndCurve  : procedure( nobj : PGLUnurbs ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluEndSurface : procedure( nobj : PGLUnurbs ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluBeginTrim : procedure( nobj : PGLUnurbs ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluEndTrim   : procedure( nobj : PGLUnurbs ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluPwlCurve  : procedure( nobj : PGLUnurbs; count : GLint; aarray : PGLfloat; stride : GLint; atype : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluNurbsCurve : procedure( nobj : PGLUnurbs; nknots : GLint; knot : PGLfloat; stride : GLint; ctlarray : PGLfloat; order : GLint; atype : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluNurbsSurface : procedure( nobj : PGLUnurbs; sknot_count : GLint; sknot : PGLfloat; tknot_count : GLint; tknot : PGLfloat; s_stride, t_stride : GLint; ctlarray : PGLfloat; sorder, torder : GLint; atype : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluLoadSamplingMatrices : procedure( nobj : PGLUnurbs; var modelMatrix, projMatrix : T16dArray; var viewport : TViewPortArray ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluNurbsProperty : procedure( nobj : PGLUnurbs; aproperty : GLenum; value : GLfloat ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluGetNurbsProperty : procedure( nobj : PGLUnurbs; aproperty : GLenum; value : PGLfloat ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluNurbsCallback : procedure( nobj : PGLUnurbs; which : GLenum; fn : TCallBack ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+
+(**** Callback function prototypes ****)
+
+type
+  // gluQuadricCallback
+  GLUquadricErrorProc = procedure( p : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+
+  // gluTessCallback
+  GLUtessBeginProc = procedure( p : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessEdgeFlagProc = procedure( p : GLboolean ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessVertexProc = procedure( p : Pointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessEndProc = procedure; {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessErrorProc = procedure( p : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessCombineProc = procedure( var p1 : T3dArray; p2 : T4pArray; p3 : T4fArray; p4 : PPointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessBeginDataProc = procedure( p1 : GLenum; p2 : Pointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessEdgeFlagDataProc = procedure( p1 : GLboolean; p2 : Pointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessVertexDataProc = procedure( p1, p2 : Pointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessEndDataProc = procedure( p : Pointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessErrorDataProc = procedure( p1 : GLenum; p2 : Pointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  GLUtessCombineDataProc = procedure( var p1 : T3dArray; var p2 : T4pArray; var p3 : T4fArray;
+    p4 : PPointer; p5 : Pointer ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+
+  // gluNurbsCallback
+  GLUnurbsErrorProc = procedure( p : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+
+
+//***           Generic constants               ****/
+
+const
+  // Version
+  GLU_VERSION_1_1 = 1;
+  GLU_VERSION_1_2 = 1;
+
+  // Errors: (return value 0 = no error)
+  GLU_INVALID_ENUM = 100900;
+  GLU_INVALID_VALUE = 100901;
+  GLU_OUT_OF_MEMORY = 100902;
+  GLU_INCOMPATIBLE_GL_VERSION = 100903;
+
+  // StringName
+  GLU_VERSION  = 100800;
+  GLU_EXTENSIONS = 100801;
+
+  // Boolean
+  GLU_TRUE     = GL_TRUE;
+  GLU_FALSE    = GL_FALSE;
+
+
+  //***           Quadric constants               ****/
+
+  // QuadricNormal
+  GLU_SMOOTH   = 100000;
+  GLU_FLAT     = 100001;
+  GLU_NONE     = 100002;
+
+  // QuadricDrawStyle
+  GLU_POINT    = 100010;
+  GLU_LINE     = 100011;
+  GLU_FILL     = 100012;
+  GLU_SILHOUETTE = 100013;
+
+  // QuadricOrientation
+  GLU_OUTSIDE  = 100020;
+  GLU_INSIDE   = 100021;
+
+  // Callback types:
+  //      GLU_ERROR       = 100103;
+
+
+  //***           Tesselation constants           ****/
+
+  GLU_TESS_MAX_COORD = 1.0E150;
+
+  // TessProperty
+  GLU_TESS_WINDING_RULE = 100140;
+  GLU_TESS_BOUNDARY_ONLY = 100141;
+  GLU_TESS_TOLERANCE = 100142;
+
+  // TessWinding
+  GLU_TESS_WINDING_ODD = 100130;
+  GLU_TESS_WINDING_NONZERO = 100131;
+  GLU_TESS_WINDING_POSITIVE = 100132;
+  GLU_TESS_WINDING_NEGATIVE = 100133;
+  GLU_TESS_WINDING_ABS_GEQ_TWO = 100134;
+
+  // TessCallback
+  GLU_TESS_BEGIN = 100100; // void (CALLBACK*)(GLenum    type)
+  GLU_TESS_VERTEX = 100101; // void (CALLBACK*)(void      *data)
+  GLU_TESS_END = 100102; // void (CALLBACK*)(void)
+  GLU_TESS_ERROR = 100103; // void (CALLBACK*)(GLenum    errno)
+  GLU_TESS_EDGE_FLAG = 100104; // void (CALLBACK*)(GLboolean boundaryEdge)
+  GLU_TESS_COMBINE = 100105; { void (CALLBACK*)(GLdouble  coords[3],
+                                                            void      *data[4],
+                                                            GLfloat   weight[4],
+                                                            void      **dataOut) }
+  GLU_TESS_BEGIN_DATA = 100106; { void (CALLBACK*)(GLenum    type,
+                                                            void      *polygon_data) }
+  GLU_TESS_VERTEX_DATA = 100107; { void (CALLBACK*)(void      *data,
+                                                            void      *polygon_data) }
+  GLU_TESS_END_DATA = 100108; // void (CALLBACK*)(void      *polygon_data)
+  GLU_TESS_ERROR_DATA = 100109; { void (CALLBACK*)(GLenum    errno,
+                                                            void      *polygon_data) }
+  GLU_TESS_EDGE_FLAG_DATA = 100110; { void (CALLBACK*)(GLboolean boundaryEdge,
+                                                            void      *polygon_data) }
+  GLU_TESS_COMBINE_DATA = 100111; { void (CALLBACK*)(GLdouble  coords[3],
+                                                            void      *data[4],
+                                                            GLfloat   weight[4],
+                                                            void      **dataOut,
+                                                            void      *polygon_data) }
+
+  // TessError
+  GLU_TESS_ERROR1 = 100151;
+  GLU_TESS_ERROR2 = 100152;
+  GLU_TESS_ERROR3 = 100153;
+  GLU_TESS_ERROR4 = 100154;
+  GLU_TESS_ERROR5 = 100155;
+  GLU_TESS_ERROR6 = 100156;
+  GLU_TESS_ERROR7 = 100157;
+  GLU_TESS_ERROR8 = 100158;
+
+  GLU_TESS_MISSING_BEGIN_POLYGON = GLU_TESS_ERROR1;
+  GLU_TESS_MISSING_BEGIN_CONTOUR = GLU_TESS_ERROR2;
+  GLU_TESS_MISSING_END_POLYGON = GLU_TESS_ERROR3;
+  GLU_TESS_MISSING_END_CONTOUR = GLU_TESS_ERROR4;
+  GLU_TESS_COORD_TOO_LARGE = GLU_TESS_ERROR5;
+  GLU_TESS_NEED_COMBINE_CALLBACK = GLU_TESS_ERROR6;
+
+  //***           NURBS constants                 ****/
+
+  // NurbsProperty
+  GLU_AUTO_LOAD_MATRIX = 100200;
+  GLU_CULLING  = 100201;
+  GLU_SAMPLING_TOLERANCE = 100203;
+  GLU_DISPLAY_MODE = 100204;
+  GLU_PARAMETRIC_TOLERANCE = 100202;
+  GLU_SAMPLING_METHOD = 100205;
+  GLU_U_STEP   = 100206;
+  GLU_V_STEP   = 100207;
+
+  // NurbsSampling
+  GLU_PATH_LENGTH = 100215;
+  GLU_PARAMETRIC_ERROR = 100216;
+  GLU_DOMAIN_DISTANCE = 100217;
+
+
+  // NurbsTrim
+  GLU_MAP1_TRIM_2 = 100210;
+  GLU_MAP1_TRIM_3 = 100211;
+
+  // NurbsDisplay
+  //      GLU_FILL                = 100012;
+  GLU_OUTLINE_POLYGON = 100240;
+  GLU_OUTLINE_PATCH = 100241;
+
+  // NurbsCallback
+  //      GLU_ERROR               = 100103;
+
+  // NurbsErrors
+  GLU_NURBS_ERROR1 = 100251;
+  GLU_NURBS_ERROR2 = 100252;
+  GLU_NURBS_ERROR3 = 100253;
+  GLU_NURBS_ERROR4 = 100254;
+  GLU_NURBS_ERROR5 = 100255;
+  GLU_NURBS_ERROR6 = 100256;
+  GLU_NURBS_ERROR7 = 100257;
+  GLU_NURBS_ERROR8 = 100258;
+  GLU_NURBS_ERROR9 = 100259;
+  GLU_NURBS_ERROR10 = 100260;
+  GLU_NURBS_ERROR11 = 100261;
+  GLU_NURBS_ERROR12 = 100262;
+  GLU_NURBS_ERROR13 = 100263;
+  GLU_NURBS_ERROR14 = 100264;
+  GLU_NURBS_ERROR15 = 100265;
+  GLU_NURBS_ERROR16 = 100266;
+  GLU_NURBS_ERROR17 = 100267;
+  GLU_NURBS_ERROR18 = 100268;
+  GLU_NURBS_ERROR19 = 100269;
+  GLU_NURBS_ERROR20 = 100270;
+  GLU_NURBS_ERROR21 = 100271;
+  GLU_NURBS_ERROR22 = 100272;
+  GLU_NURBS_ERROR23 = 100273;
+  GLU_NURBS_ERROR24 = 100274;
+  GLU_NURBS_ERROR25 = 100275;
+  GLU_NURBS_ERROR26 = 100276;
+  GLU_NURBS_ERROR27 = 100277;
+  GLU_NURBS_ERROR28 = 100278;
+  GLU_NURBS_ERROR29 = 100279;
+  GLU_NURBS_ERROR30 = 100280;
+  GLU_NURBS_ERROR31 = 100281;
+  GLU_NURBS_ERROR32 = 100282;
+  GLU_NURBS_ERROR33 = 100283;
+  GLU_NURBS_ERROR34 = 100284;
+  GLU_NURBS_ERROR35 = 100285;
+  GLU_NURBS_ERROR36 = 100286;
+  GLU_NURBS_ERROR37 = 100287;
+
+//***           Backwards compatibility for old tesselator           ****/
+
+var
+  gluBeginPolygon : procedure( tess : PGLUtesselator ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluNextContour : procedure( tess : PGLUtesselator; atype : GLenum ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+  gluEndPolygon : procedure( tess : PGLUtesselator ); {$IFDEF WINDOWS}stdcall; {$ELSE}cdecl; {$ENDIF}
+
+const
+  // Contours types -- obsolete!
+  GLU_CW       = 100120;
+  GLU_CCW      = 100121;
+  GLU_INTERIOR = 100122;
+  GLU_EXTERIOR = 100123;
+  GLU_UNKNOWN  = 100124;
+
+  // Names without "TESS_" prefix
+  GLU_BEGIN    = GLU_TESS_BEGIN;
+  GLU_VERTEX   = GLU_TESS_VERTEX;
+  GLU_END      = GLU_TESS_END;
+  GLU_ERROR    = GLU_TESS_ERROR;
+  GLU_EDGE_FLAG = GLU_TESS_EDGE_FLAG;
+
+procedure LoadGLu( const dll : PChar );
+procedure FreeGLu;
+
+implementation
+
+var
+  LibGlu       : TModuleHandle;
+
+procedure FreeGLu;
+begin
+
+  @gluErrorString := nil;
+  @gluErrorUnicodeStringEXT := nil;
+  @gluGetString := nil;
+  @gluOrtho2D := nil;
+  @gluPerspective := nil;
+  @gluPickMatrix := nil;
+  @gluLookAt := nil;
+  @gluProject := nil;
+  @gluUnProject := nil;
+  @gluScaleImage := nil;
+  @gluBuild1DMipmaps := nil;
+  @gluBuild2DMipmaps := nil;
+  @gluNewQuadric := nil;
+  @gluDeleteQuadric := nil;
+  @gluQuadricNormals := nil;
+  @gluQuadricTexture := nil;
+  @gluQuadricOrientation := nil;
+  @gluQuadricDrawStyle := nil;
+  @gluCylinder := nil;
+  @gluDisk := nil;
+  @gluPartialDisk := nil;
+  @gluSphere := nil;
+  @gluQuadricCallback := nil;
+  @gluNewTess := nil;
+  @gluDeleteTess := nil;
+  @gluTessBeginPolygon := nil;
+  @gluTessBeginContour := nil;
+  @gluTessVertex := nil;
+  @gluTessEndContour := nil;
+  @gluTessEndPolygon := nil;
+  @gluTessProperty := nil;
+  @gluTessNormal := nil;
+  @gluTessCallback := nil;
+  @gluGetTessProperty := nil;
+  @gluNewNurbsRenderer := nil;
+  @gluDeleteNurbsRenderer := nil;
+  @gluBeginSurface := nil;
+  @gluBeginCurve := nil;
+  @gluEndCurve := nil;
+  @gluEndSurface := nil;
+  @gluBeginTrim := nil;
+  @gluEndTrim := nil;
+  @gluPwlCurve := nil;
+  @gluNurbsCurve := nil;
+  @gluNurbsSurface := nil;
+  @gluLoadSamplingMatrices := nil;
+  @gluNurbsProperty := nil;
+  @gluGetNurbsProperty := nil;
+  @gluNurbsCallback := nil;
+  @gluBeginPolygon := nil;
+  @gluNextContour := nil;
+  @gluEndPolygon := nil;
+
+  UnLoadModule( LibGlu );
+
+end;
+
+procedure LoadGLu( const dll : PChar );
+begin
+
+  FreeGLu;
+
+  if LoadModule( LibGlu, dll ) then
+  begin
+    @gluErrorString := GetModuleSymbol( LibGlu, 'gluErrorString' );
+    @gluErrorUnicodeStringEXT := GetModuleSymbol( LibGlu, 'gluErrorUnicodeStringEXT' );
+    @gluGetString := GetModuleSymbol( LibGlu, 'gluGetString' );
+    @gluOrtho2D := GetModuleSymbol( LibGlu, 'gluOrtho2D' );
+    @gluPerspective := GetModuleSymbol( LibGlu, 'gluPerspective' );
+    @gluPickMatrix := GetModuleSymbol( LibGlu, 'gluPickMatrix' );
+    @gluLookAt := GetModuleSymbol( LibGlu, 'gluLookAt' );
+    @gluProject := GetModuleSymbol( LibGlu, 'gluProject' );
+    @gluUnProject := GetModuleSymbol( LibGlu, 'gluUnProject' );
+    @gluScaleImage := GetModuleSymbol( LibGlu, 'gluScaleImage' );
+    @gluBuild1DMipmaps := GetModuleSymbol( LibGlu, 'gluBuild1DMipmaps' );
+    @gluBuild2DMipmaps := GetModuleSymbol( LibGlu, 'gluBuild2DMipmaps' );
+    @gluNewQuadric := GetModuleSymbol( LibGlu, 'gluNewQuadric' );
+    @gluDeleteQuadric := GetModuleSymbol( LibGlu, 'gluDeleteQuadric' );
+    @gluQuadricNormals := GetModuleSymbol( LibGlu, 'gluQuadricNormals' );
+    @gluQuadricTexture := GetModuleSymbol( LibGlu, 'gluQuadricTexture' );
+    @gluQuadricOrientation := GetModuleSymbol( LibGlu, 'gluQuadricOrientation' );
+    @gluQuadricDrawStyle := GetModuleSymbol( LibGlu, 'gluQuadricDrawStyle' );
+    @gluCylinder := GetModuleSymbol( LibGlu, 'gluCylinder' );
+    @gluDisk := GetModuleSymbol( LibGlu, 'gluDisk' );
+    @gluPartialDisk := GetModuleSymbol( LibGlu, 'gluPartialDisk' );
+    @gluSphere := GetModuleSymbol( LibGlu, 'gluSphere' );
+    @gluQuadricCallback := GetModuleSymbol( LibGlu, 'gluQuadricCallback' );
+    @gluNewTess := GetModuleSymbol( LibGlu, 'gluNewTess' );
+    @gluDeleteTess := GetModuleSymbol( LibGlu, 'gluDeleteTess' );
+    @gluTessBeginPolygon := GetModuleSymbol( LibGlu, 'gluTessBeginPolygon' );
+    @gluTessBeginContour := GetModuleSymbol( LibGlu, 'gluTessBeginContour' );
+    @gluTessVertex := GetModuleSymbol( LibGlu, 'gluTessVertex' );
+    @gluTessEndContour := GetModuleSymbol( LibGlu, 'gluTessEndContour' );
+    @gluTessEndPolygon := GetModuleSymbol( LibGlu, 'gluTessEndPolygon' );
+    @gluTessProperty := GetModuleSymbol( LibGlu, 'gluTessProperty' );
+    @gluTessNormal := GetModuleSymbol( LibGlu, 'gluTessNormal' );
+    @gluTessCallback := GetModuleSymbol( LibGlu, 'gluTessCallback' );
+    @gluGetTessProperty := GetModuleSymbol( LibGlu, 'gluGetTessProperty' );
+    @gluNewNurbsRenderer := GetModuleSymbol( LibGlu, 'gluNewNurbsRenderer' );
+    @gluDeleteNurbsRenderer := GetModuleSymbol( LibGlu, 'gluDeleteNurbsRenderer' );
+    @gluBeginSurface := GetModuleSymbol( LibGlu, 'gluBeginSurface' );
+    @gluBeginCurve := GetModuleSymbol( LibGlu, 'gluBeginCurve' );
+    @gluEndCurve := GetModuleSymbol( LibGlu, 'gluEndCurve' );
+    @gluEndSurface := GetModuleSymbol( LibGlu, 'gluEndSurface' );
+    @gluBeginTrim := GetModuleSymbol( LibGlu, 'gluBeginTrim' );
+    @gluEndTrim := GetModuleSymbol( LibGlu, 'gluEndTrim' );
+    @gluPwlCurve := GetModuleSymbol( LibGlu, 'gluPwlCurve' );
+    @gluNurbsCurve := GetModuleSymbol( LibGlu, 'gluNurbsCurve' );
+    @gluNurbsSurface := GetModuleSymbol( LibGlu, 'gluNurbsSurface' );
+    @gluLoadSamplingMatrices := GetModuleSymbol( LibGlu, 'gluLoadSamplingMatrices' );
+    @gluNurbsProperty := GetModuleSymbol( LibGlu, 'gluNurbsProperty' );
+    @gluGetNurbsProperty := GetModuleSymbol( LibGlu, 'gluGetNurbsProperty' );
+    @gluNurbsCallback := GetModuleSymbol( LibGlu, 'gluNurbsCallback' );
+
+    @gluBeginPolygon := GetModuleSymbol( LibGlu, 'gluBeginPolygon' );
+    @gluNextContour := GetModuleSymbol( LibGlu, 'gluNextContour' );
+    @gluEndPolygon := GetModuleSymbol( LibGlu, 'gluEndPolygon' );
+  end;
+end;
+
+initialization
+
+  LoadGLu( GLuLibName );
+
+finalization
+
+  FreeGLu;
+
+end.
+
diff --git a/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glut.pas b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glut.pas
new file mode 100644
index 00000000..04f69267
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glut.pas
@@ -0,0 +1,688 @@
+unit glut;
+{
+  $Id: glut.pas,v 1.4 2007/05/20 20:28:31 savage Exp $
+
+  Adaption of the delphi3d.net OpenGL units to FreePascal
+  Sebastian Guenther (sg@freepascal.org) in 2002
+  These units are free to use
+}
+
+// Copyright (c) Mark J. Kilgard, 1994, 1995, 1996. */
+
+(* This program is freely distributable without licensing fees  and is
+   provided without guarantee or warrantee expressed or  implied. This
+   program is -not- in the public domain. *)
+
+{******************************************************************************}
+{                                                                              }
+{ Converted to Delphi by Tom Nuydens (tom@delphi3d.net)                        }
+{ For the latest updates, visit Delphi3D: http://www.delphi3d.net              }
+{                                                                              }
+{ Modified for Delphi/Kylix and FreePascal                                     }
+{    by Dominique Louis ( Dominique@Savagesoftware.com.au)                     }
+{ For the latest updates, visit JEDI-SDL : http://www.sf.net/projects/jedi-sdl }
+{                                                                              }
+{******************************************************************************}
+
+{
+  $Log: glut.pas,v $
+  Revision 1.4  2007/05/20 20:28:31  savage
+  Initial Changes to Handle 64 Bits
+
+  Revision 1.3  2006/11/20 21:20:59  savage
+  Updated to work in MacOS X
+
+  Revision 1.2  2004/08/14 22:54:30  savage
+  Updated so that Library name defines are correctly defined for MacOS X.
+
+  Revision 1.1  2004/03/30 21:53:54  savage
+  Moved to it's own folder.
+
+  Revision 1.5  2004/02/20 17:09:55  savage
+  Code tidied up in gl, glu and glut, while extensions in glext.pas are now loaded using SDL_GL_GetProcAddress, thus making it more cross-platform compatible, but now more tied to SDL.
+
+  Revision 1.4  2004/02/14 22:36:29  savage
+  Fixed inconsistencies of using LoadLibrary and LoadModule.
+  Now all units make use of LoadModule rather than LoadLibrary and other dynamic proc procedures.
+
+  Revision 1.3  2004/02/14 00:23:39  savage
+  As UNIX is defined in jedi-sdl.inc this will be used to check linux compatability as well. Units have been changed to reflect this change.
+
+  Revision 1.2  2004/02/14 00:09:19  savage
+  Changed uses to now make use of moduleloader.pas rather than dllfuncs.pas
+
+  Revision 1.1  2004/02/05 00:08:19  savage
+  Module 1.0 release
+
+  Revision 1.4  2003/06/02 12:32:13  savage
+  Modified Sources to avoid warnings with Delphi by moving CVS Logging to the top of the header files. Hopefully CVS Logging still works.
+
+}
+
+interface
+
+{$I jedi-sdl.inc}
+
+uses
+{$IFDEF __GPC__}
+  system,
+  gpc,
+{$ENDIF}
+
+{$IFDEF WINDOWS}
+  Windows,
+{$ENDIF}
+  moduleloader,
+  gl;
+
+type
+  {$IFNDEF __GPC__}
+  PInteger = ^Integer;
+  PPChar = ^PChar;
+  {$ENDIF}
+  TGlutVoidCallback = procedure; {$IFNDEF __GPC__}{$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}{$ENDIF}
+  TGlut1IntCallback = procedure(value: Integer); {$IFNDEF __GPC__}{$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}{$ENDIF}
+  TGlut2IntCallback = procedure(v1, v2: Integer); {$IFNDEF __GPC__}{$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}{$ENDIF}
+  TGlut3IntCallback = procedure(v1, v2, v3: Integer); {$IFNDEF __GPC__}{$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}{$ENDIF}
+  TGlut4IntCallback = procedure(v1, v2, v3, v4: Integer); {$IFNDEF __GPC__}{$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}{$ENDIF}
+  TGlut1Char2IntCallback = procedure(c: Byte; v1, v2: Integer); {$IFNDEF __GPC__}{$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}{$ENDIF}
+
+const
+{$IFDEF WINDOWS}
+  GlutLibName = 'glut32.dll';
+{$ENDIF}
+
+{$IFDEF UNIX}
+{$IFDEF DARWIN}
+  GlutLibName = '/System/Library/Frameworks/GLUT.framework/Libraries/libglut.dylib';
+{$ELSE}
+  GlutLibName = 'libglut.so';
+{$ENDIF}
+{$ENDIF}
+
+  GLUT_API_VERSION                = 3;
+  GLUT_XLIB_IMPLEMENTATION        = 12;
+  // Display mode bit masks.
+  GLUT_RGB                        = 0;
+  GLUT_RGBA                       = GLUT_RGB;
+  GLUT_INDEX                      = 1;
+  GLUT_SINGLE                     = 0;
+  GLUT_DOUBLE                     = 2;
+  GLUT_ACCUM                      = 4;
+  GLUT_ALPHA                      = 8;
+  GLUT_DEPTH                      = 16;
+  GLUT_STENCIL                    = 32;
+  GLUT_MULTISAMPLE                = 128;
+  GLUT_STEREO                     = 256;
+  GLUT_LUMINANCE                  = 512;
+
+  // Mouse buttons.
+  GLUT_LEFT_BUTTON                = 0;
+  GLUT_MIDDLE_BUTTON              = 1;
+  GLUT_RIGHT_BUTTON               = 2;
+
+  // Mouse button state.
+  GLUT_DOWN                       = 0;
+  GLUT_UP                         = 1;
+
+  // function keys
+  GLUT_KEY_F1                     = 1;
+  GLUT_KEY_F2                     = 2;
+  GLUT_KEY_F3                     = 3;
+  GLUT_KEY_F4                     = 4;
+  GLUT_KEY_F5                     = 5;
+  GLUT_KEY_F6                     = 6;
+  GLUT_KEY_F7                     = 7;
+  GLUT_KEY_F8                     = 8;
+  GLUT_KEY_F9                     = 9;
+  GLUT_KEY_F10                    = 10;
+  GLUT_KEY_F11                    = 11;
+  GLUT_KEY_F12                    = 12;
+  // directional keys
+  GLUT_KEY_LEFT                   = 100;
+  GLUT_KEY_UP                     = 101;
+  GLUT_KEY_RIGHT                  = 102;
+  GLUT_KEY_DOWN                   = 103;
+  GLUT_KEY_PAGE_UP                = 104;
+  GLUT_KEY_PAGE_DOWN              = 105;
+  GLUT_KEY_HOME                   = 106;
+  GLUT_KEY_END                    = 107;
+  GLUT_KEY_INSERT                 = 108;
+
+  // Entry/exit  state.
+  GLUT_LEFT                       = 0;
+  GLUT_ENTERED                    = 1;
+
+  // Menu usage state.
+  GLUT_MENU_NOT_IN_USE            = 0;
+  GLUT_MENU_IN_USE                = 1;
+
+  // Visibility  state.
+  GLUT_NOT_VISIBLE                = 0;
+  GLUT_VISIBLE                    = 1;
+
+  // Window status  state.
+  GLUT_HIDDEN                     = 0;
+  GLUT_FULLY_RETAINED             = 1;
+  GLUT_PARTIALLY_RETAINED         = 2;
+  GLUT_FULLY_COVERED              = 3;
+
+  // Color index component selection values.
+  GLUT_RED                        = 0;
+  GLUT_GREEN                      = 1;
+  GLUT_BLUE                       = 2;
+
+  // Layers for use.
+  GLUT_NORMAL                     = 0;
+  GLUT_OVERLAY                    = 1;
+
+  // Stroke font constants (use these in GLUT program).
+  GLUT_STROKE_ROMAN		  = Pointer(0);
+  GLUT_STROKE_MONO_ROMAN	  = Pointer(1);
+
+  // Bitmap font constants (use these in GLUT program).
+  GLUT_BITMAP_9_BY_15		  = Pointer(2);
+  GLUT_BITMAP_8_BY_13		  = Pointer(3);
+  GLUT_BITMAP_TIMES_ROMAN_10	  = Pointer(4);
+  GLUT_BITMAP_TIMES_ROMAN_24	  = Pointer(5);
+  GLUT_BITMAP_HELVETICA_10	  = Pointer(6);
+  GLUT_BITMAP_HELVETICA_12	  = Pointer(7);
+  GLUT_BITMAP_HELVETICA_18	  = Pointer(8);
+
+  // glutGet parameters.
+  GLUT_WINDOW_X                   = 100;
+  GLUT_WINDOW_Y                   = 101;
+  GLUT_WINDOW_WIDTH               = 102;
+  GLUT_WINDOW_HEIGHT              = 103;
+  GLUT_WINDOW_BUFFER_SIZE         = 104;
+  GLUT_WINDOW_STENCIL_SIZE        = 105;
+  GLUT_WINDOW_DEPTH_SIZE          = 106;
+  GLUT_WINDOW_RED_SIZE            = 107;
+  GLUT_WINDOW_GREEN_SIZE          = 108;
+  GLUT_WINDOW_BLUE_SIZE           = 109;
+  GLUT_WINDOW_ALPHA_SIZE          = 110;
+  GLUT_WINDOW_ACCUM_RED_SIZE      = 111;
+  GLUT_WINDOW_ACCUM_GREEN_SIZE    = 112;
+  GLUT_WINDOW_ACCUM_BLUE_SIZE     = 113;
+  GLUT_WINDOW_ACCUM_ALPHA_SIZE    = 114;
+  GLUT_WINDOW_DOUBLEBUFFER        = 115;
+  GLUT_WINDOW_RGBA                = 116;
+  GLUT_WINDOW_PARENT              = 117;
+  GLUT_WINDOW_NUM_CHILDREN        = 118;
+  GLUT_WINDOW_COLORMAP_SIZE       = 119;
+  GLUT_WINDOW_NUM_SAMPLES         = 120;
+  GLUT_WINDOW_STEREO              = 121;
+  GLUT_WINDOW_CURSOR              = 122;
+  GLUT_SCREEN_WIDTH               = 200;
+  GLUT_SCREEN_HEIGHT              = 201;
+  GLUT_SCREEN_WIDTH_MM            = 202;
+  GLUT_SCREEN_HEIGHT_MM           = 203;
+  GLUT_MENU_NUM_ITEMS             = 300;
+  GLUT_DISPLAY_MODE_POSSIBLE      = 400;
+  GLUT_INIT_WINDOW_X              = 500;
+  GLUT_INIT_WINDOW_Y              = 501;
+  GLUT_INIT_WINDOW_WIDTH          = 502;
+  GLUT_INIT_WINDOW_HEIGHT         = 503;
+  GLUT_INIT_DISPLAY_MODE          = 504;
+  GLUT_ELAPSED_TIME               = 700;
+
+  // glutDeviceGet parameters.
+  GLUT_HAS_KEYBOARD               = 600;
+  GLUT_HAS_MOUSE                  = 601;
+  GLUT_HAS_SPACEBALL              = 602;
+  GLUT_HAS_DIAL_AND_BUTTON_BOX    = 603;
+  GLUT_HAS_TABLET                 = 604;
+  GLUT_NUM_MOUSE_BUTTONS          = 605;
+  GLUT_NUM_SPACEBALL_BUTTONS      = 606;
+  GLUT_NUM_BUTTON_BOX_BUTTONS     = 607;
+  GLUT_NUM_DIALS                  = 608;
+  GLUT_NUM_TABLET_BUTTONS         = 609;
+
+  // glutLayerGet parameters.
+  GLUT_OVERLAY_POSSIBLE           = 800;
+  GLUT_LAYER_IN_USE               = 801;
+  GLUT_HAS_OVERLAY                = 802;
+  GLUT_TRANSPARENT_INDEX          = 803;
+  GLUT_NORMAL_DAMAGED             = 804;
+  GLUT_OVERLAY_DAMAGED            = 805;
+
+  // glutVideoResizeGet parameters.
+  GLUT_VIDEO_RESIZE_POSSIBLE       = 900;
+  GLUT_VIDEO_RESIZE_IN_USE         = 901;
+  GLUT_VIDEO_RESIZE_X_DELTA        = 902;
+  GLUT_VIDEO_RESIZE_Y_DELTA        = 903;
+  GLUT_VIDEO_RESIZE_WIDTH_DELTA    = 904;
+  GLUT_VIDEO_RESIZE_HEIGHT_DELTA   = 905;
+  GLUT_VIDEO_RESIZE_X              = 906;
+  GLUT_VIDEO_RESIZE_Y              = 907;
+  GLUT_VIDEO_RESIZE_WIDTH          = 908;
+  GLUT_VIDEO_RESIZE_HEIGHT         = 909;
+
+  // glutGetModifiers return mask.
+  GLUT_ACTIVE_SHIFT                = 1;
+  GLUT_ACTIVE_CTRL                 = 2;
+  GLUT_ACTIVE_ALT                  = 4;
+
+  // glutSetCursor parameters.
+  // Basic arrows.
+  GLUT_CURSOR_RIGHT_ARROW          = 0;
+  GLUT_CURSOR_LEFT_ARROW           = 1;
+  // Symbolic cursor shapes.
+  GLUT_CURSOR_INFO                 = 2;
+  GLUT_CURSOR_DESTROY              = 3;
+  GLUT_CURSOR_HELP                 = 4;
+  GLUT_CURSOR_CYCLE                = 5;
+  GLUT_CURSOR_SPRAY                = 6;
+  GLUT_CURSOR_WAIT                 = 7;
+  GLUT_CURSOR_TEXT                 = 8;
+  GLUT_CURSOR_CROSSHAIR            = 9;
+  // Directional cursors.
+  GLUT_CURSOR_UP_DOWN              = 10;
+  GLUT_CURSOR_LEFT_RIGHT           = 11;
+  // Sizing cursors.
+  GLUT_CURSOR_TOP_SIDE             = 12;
+  GLUT_CURSOR_BOTTOM_SIDE          = 13;
+  GLUT_CURSOR_LEFT_SIDE            = 14;
+  GLUT_CURSOR_RIGHT_SIDE           = 15;
+  GLUT_CURSOR_TOP_LEFT_CORNER      = 16;
+  GLUT_CURSOR_TOP_RIGHT_CORNER     = 17;
+  GLUT_CURSOR_BOTTOM_RIGHT_CORNER  = 18;
+  GLUT_CURSOR_BOTTOM_LEFT_CORNER   = 19;
+  // Inherit from parent window.
+  GLUT_CURSOR_INHERIT              = 100;
+  // Blank cursor.
+  GLUT_CURSOR_NONE                 = 101;
+  // Fullscreen crosshair (if available).
+  GLUT_CURSOR_FULL_CROSSHAIR       = 102;
+
+  // GLUT game mode sub-API.
+  // glutGameModeGet.
+  GLUT_GAME_MODE_ACTIVE           = 0;
+  GLUT_GAME_MODE_POSSIBLE         = 1;
+  GLUT_GAME_MODE_WIDTH            = 2;
+  GLUT_GAME_MODE_HEIGHT           = 3;
+  GLUT_GAME_MODE_PIXEL_DEPTH      = 4;
+  GLUT_GAME_MODE_REFRESH_RATE     = 5;
+  GLUT_GAME_MODE_DISPLAY_CHANGED  = 6;
+
+var
+// GLUT initialization sub-API.
+  glutInit: procedure(argcp: PInteger; argv: PPChar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutInitDisplayMode: procedure(mode: Word); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutInitDisplayString: procedure(const str: PChar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutInitWindowPosition: procedure(x, y: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutInitWindowSize: procedure(width, height: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutMainLoop: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT window sub-API.
+  glutCreateWindow: function(const title: PChar): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutCreateSubWindow: function(win, x, y, width, height: Integer): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutDestroyWindow: procedure(win: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutPostRedisplay: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutPostWindowRedisplay: procedure(win: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSwapBuffers: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutGetWindow: function: Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSetWindow: procedure(win: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSetWindowTitle: procedure(const title: PChar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSetIconTitle: procedure(const title: PChar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutPositionWindow: procedure(x, y: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutReshapeWindow: procedure(width, height: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutPopWindow: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutPushWindow: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutIconifyWindow: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutShowWindow: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutHideWindow: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutFullScreen: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSetCursor: procedure(cursor: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWarpPointer: procedure(x, y: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT overlay sub-API.
+  glutEstablishOverlay: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutRemoveOverlay: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutUseLayer: procedure(layer: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutPostOverlayRedisplay: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutPostWindowOverlayRedisplay: procedure(win: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutShowOverlay: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutHideOverlay: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT menu sub-API.
+  glutCreateMenu: function(callback: TGlut1IntCallback): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutDestroyMenu: procedure(menu: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutGetMenu: function: Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSetMenu: procedure(menu: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutAddMenuEntry: procedure(const caption: PChar; value: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutAddSubMenu: procedure(const caption: PChar; submenu: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutChangeToMenuEntry: procedure(item: Integer; const caption: PChar; value: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutChangeToSubMenu: procedure(item: Integer; const caption: PChar; submenu: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutRemoveMenuItem: procedure(item: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutAttachMenu: procedure(button: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutDetachMenu: procedure(button: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUTsub-API.
+  glutDisplayFunc: procedure(f: TGlutVoidCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutReshapeFunc: procedure(f: TGlut2IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutKeyboardFunc: procedure(f: TGlut1Char2IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutMouseFunc: procedure(f: TGlut4IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutMotionFunc: procedure(f: TGlut2IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutPassiveMotionFunc: procedure(f: TGlut2IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutEntryFunc: procedure(f: TGlut1IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutVisibilityFunc: procedure(f: TGlut1IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutIdleFunc: procedure(f: TGlutVoidCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutTimerFunc: procedure(millis: Word; f: TGlut1IntCallback; value: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutMenuStateFunc: procedure(f: TGlut1IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSpecialFunc: procedure(f: TGlut3IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSpaceballMotionFunc: procedure(f: TGlut3IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSpaceballRotateFunc: procedure(f: TGlut3IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSpaceballButtonFunc: procedure(f: TGlut2IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutButtonBoxFunc: procedure(f: TGlut2IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutDialsFunc: procedure(f: TGlut2IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutTabletMotionFunc: procedure(f: TGlut2IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutTabletButtonFunc: procedure(f: TGlut4IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutMenuStatusFunc: procedure(f: TGlut3IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutOverlayDisplayFunc: procedure(f:TGlutVoidCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWindowStatusFunc: procedure(f: TGlut1IntCallback); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT color index sub-API.
+  glutSetColor: procedure(cell: Integer; red, green, blue: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutGetColor: function(ndx, component: Integer): GLfloat; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutCopyColormap: procedure(win: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT state retrieval sub-API.
+  glutGet: function(t: GLenum): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutDeviceGet: function(t: GLenum): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT extension support sub-API
+  glutExtensionSupported: function(const name: PChar): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutGetModifiers: function: Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutLayerGet: function(t: GLenum): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT font sub-API
+  glutBitmapCharacter: procedure(font : pointer; character: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutBitmapWidth: function(font : pointer; character: Integer): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutStrokeCharacter: procedure(font : pointer; character: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutStrokeWidth: function(font : pointer; character: Integer): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutBitmapLength: function(font: pointer; const str: PChar): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutStrokeLength: function(font: pointer; const str: PChar): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT pre-built models sub-API
+  glutWireSphere: procedure(radius: GLdouble; slices, stacks: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSolidSphere: procedure(radius: GLdouble; slices, stacks: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWireCone: procedure(base, height: GLdouble; slices, stacks: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSolidCone: procedure(base, height: GLdouble; slices, stacks: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWireCube: procedure(size: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSolidCube: procedure(size: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWireTorus: procedure(innerRadius, outerRadius: GLdouble; sides, rings: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSolidTorus: procedure(innerRadius, outerRadius: GLdouble; sides, rings: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWireDodecahedron: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSolidDodecahedron: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWireTeapot: procedure(size: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSolidTeapot: procedure(size: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWireOctahedron: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSolidOctahedron: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWireTetrahedron: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSolidTetrahedron: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutWireIcosahedron: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSolidIcosahedron: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT video resize sub-API.
+  glutVideoResizeGet: function(param: GLenum): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutSetupVideoResizing: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutStopVideoResizing: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutVideoResize: procedure(x, y, width, height: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutVideoPan: procedure(x, y, width, height: Integer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+// GLUT debugging sub-API.
+  glutReportErrors: procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+var
+  //example glutGameModeString('1280x1024:32@75');
+  glutGameModeString : procedure (const AString : PChar); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutEnterGameMode : function : integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutLeaveGameMode : procedure; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glutGameModeGet : function (mode : GLenum) : integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF} 
+
+procedure LoadGlut(const dll: PChar);
+procedure FreeGlut;
+
+implementation
+
+var
+  LibGLUT : TModuleHandle;
+
+procedure FreeGlut;
+begin
+
+  UnLoadModule( LibGLUT );
+
+  @glutInit := nil;
+  @glutInitDisplayMode := nil;
+  @glutInitDisplayString := nil;
+  @glutInitWindowPosition := nil;
+  @glutInitWindowSize := nil;
+  @glutMainLoop := nil;
+  @glutCreateWindow := nil;
+  @glutCreateSubWindow := nil;
+  @glutDestroyWindow := nil;
+  @glutPostRedisplay := nil;
+  @glutPostWindowRedisplay := nil;
+  @glutSwapBuffers := nil;
+  @glutGetWindow := nil;
+  @glutSetWindow := nil;
+  @glutSetWindowTitle := nil;
+  @glutSetIconTitle := nil;
+  @glutPositionWindow := nil;
+  @glutReshapeWindow := nil;
+  @glutPopWindow := nil;
+  @glutPushWindow := nil;
+  @glutIconifyWindow := nil;
+  @glutShowWindow := nil;
+  @glutHideWindow := nil;
+  @glutFullScreen := nil;
+  @glutSetCursor := nil;
+  @glutWarpPointer := nil;
+  @glutEstablishOverlay := nil;
+  @glutRemoveOverlay := nil;
+  @glutUseLayer := nil;
+  @glutPostOverlayRedisplay := nil;
+  @glutPostWindowOverlayRedisplay := nil;
+  @glutShowOverlay := nil;
+  @glutHideOverlay := nil;
+  @glutCreateMenu := nil;
+  @glutDestroyMenu := nil;
+  @glutGetMenu := nil;
+  @glutSetMenu := nil;
+  @glutAddMenuEntry := nil;
+  @glutAddSubMenu := nil;
+  @glutChangeToMenuEntry := nil;
+  @glutChangeToSubMenu := nil;
+  @glutRemoveMenuItem := nil;
+  @glutAttachMenu := nil;
+  @glutDetachMenu := nil;
+  @glutDisplayFunc := nil;
+  @glutReshapeFunc := nil;
+  @glutKeyboardFunc := nil;
+  @glutMouseFunc := nil;
+  @glutMotionFunc := nil;
+  @glutPassiveMotionFunc := nil;
+  @glutEntryFunc := nil;
+  @glutVisibilityFunc := nil;
+  @glutIdleFunc := nil;
+  @glutTimerFunc := nil;
+  @glutMenuStateFunc := nil;
+  @glutSpecialFunc := nil;
+  @glutSpaceballMotionFunc := nil;
+  @glutSpaceballRotateFunc := nil;
+  @glutSpaceballButtonFunc := nil;
+  @glutButtonBoxFunc := nil;
+  @glutDialsFunc := nil;
+  @glutTabletMotionFunc := nil;
+  @glutTabletButtonFunc := nil;
+  @glutMenuStatusFunc := nil;
+  @glutOverlayDisplayFunc := nil;
+  @glutWindowStatusFunc := nil;
+  @glutSetColor := nil;
+  @glutGetColor := nil;
+  @glutCopyColormap := nil;
+  @glutGet := nil;
+  @glutDeviceGet := nil;
+  @glutExtensionSupported := nil;
+  @glutGetModifiers := nil;
+  @glutLayerGet := nil;
+  @glutBitmapCharacter := nil;
+  @glutBitmapWidth := nil;
+  @glutStrokeCharacter := nil;
+  @glutStrokeWidth := nil;
+  @glutBitmapLength := nil;
+  @glutStrokeLength := nil;
+  @glutWireSphere := nil;
+  @glutSolidSphere := nil;
+  @glutWireCone := nil;
+  @glutSolidCone := nil;
+  @glutWireCube := nil;
+  @glutSolidCube := nil;
+  @glutWireTorus := nil;
+  @glutSolidTorus := nil;
+  @glutWireDodecahedron := nil;
+  @glutSolidDodecahedron := nil;
+  @glutWireTeapot := nil;
+  @glutSolidTeapot := nil;
+  @glutWireOctahedron := nil;
+  @glutSolidOctahedron := nil;
+  @glutWireTetrahedron := nil;
+  @glutSolidTetrahedron := nil;
+  @glutWireIcosahedron := nil;
+  @glutSolidIcosahedron := nil;
+  @glutVideoResizeGet := nil;
+  @glutSetupVideoResizing := nil;
+  @glutStopVideoResizing := nil;
+  @glutVideoResize := nil;
+  @glutVideoPan := nil;
+  @glutReportErrors := nil;
+
+end;
+
+procedure LoadGlut(const dll: PChar);
+begin
+
+  FreeGlut;
+
+  if LoadModule( LibGLUT, dll ) then
+  begin
+    @glutInit := GetModuleSymbol(LibGLUT, 'glutInit');
+    @glutInitDisplayMode := GetModuleSymbol(LibGLUT, 'glutInitDisplayMode');
+    @glutInitDisplayString := GetModuleSymbol(LibGLUT, 'glutInitDisplayString');
+    @glutInitWindowPosition := GetModuleSymbol(LibGLUT, 'glutInitWindowPosition');
+    @glutInitWindowSize := GetModuleSymbol(LibGLUT, 'glutInitWindowSize');
+    @glutMainLoop := GetModuleSymbol(LibGLUT, 'glutMainLoop');
+    @glutCreateWindow := GetModuleSymbol(LibGLUT, 'glutCreateWindow');
+    @glutCreateSubWindow := GetModuleSymbol(LibGLUT, 'glutCreateSubWindow');
+    @glutDestroyWindow := GetModuleSymbol(LibGLUT, 'glutDestroyWindow');
+    @glutPostRedisplay := GetModuleSymbol(LibGLUT, 'glutPostRedisplay');
+    @glutPostWindowRedisplay := GetModuleSymbol(LibGLUT, 'glutPostWindowRedisplay');
+    @glutSwapBuffers := GetModuleSymbol(LibGLUT, 'glutSwapBuffers');
+    @glutGetWindow := GetModuleSymbol(LibGLUT, 'glutGetWindow');
+    @glutSetWindow := GetModuleSymbol(LibGLUT, 'glutSetWindow');
+    @glutSetWindowTitle := GetModuleSymbol(LibGLUT, 'glutSetWindowTitle');
+    @glutSetIconTitle := GetModuleSymbol(LibGLUT, 'glutSetIconTitle');
+    @glutPositionWindow := GetModuleSymbol(LibGLUT, 'glutPositionWindow');
+    @glutReshapeWindow := GetModuleSymbol(LibGLUT, 'glutReshapeWindow');
+    @glutPopWindow := GetModuleSymbol(LibGLUT, 'glutPopWindow');
+    @glutPushWindow := GetModuleSymbol(LibGLUT, 'glutPushWindow');
+    @glutIconifyWindow := GetModuleSymbol(LibGLUT, 'glutIconifyWindow');
+    @glutShowWindow := GetModuleSymbol(LibGLUT, 'glutShowWindow');
+    @glutHideWindow := GetModuleSymbol(LibGLUT, 'glutHideWindow');
+    @glutFullScreen := GetModuleSymbol(LibGLUT, 'glutFullScreen');
+    @glutSetCursor := GetModuleSymbol(LibGLUT, 'glutSetCursor');
+    @glutWarpPointer := GetModuleSymbol(LibGLUT, 'glutWarpPointer');
+    @glutEstablishOverlay := GetModuleSymbol(LibGLUT, 'glutEstablishOverlay');
+    @glutRemoveOverlay := GetModuleSymbol(LibGLUT, 'glutRemoveOverlay');
+    @glutUseLayer := GetModuleSymbol(LibGLUT, 'glutUseLayer');
+    @glutPostOverlayRedisplay := GetModuleSymbol(LibGLUT, 'glutPostOverlayRedisplay');
+    @glutPostWindowOverlayRedisplay := GetModuleSymbol(LibGLUT, 'glutPostWindowOverlayRedisplay');
+    @glutShowOverlay := GetModuleSymbol(LibGLUT, 'glutShowOverlay');
+    @glutHideOverlay := GetModuleSymbol(LibGLUT, 'glutHideOverlay');
+    @glutCreateMenu := GetModuleSymbol(LibGLUT, 'glutCreateMenu');
+    @glutDestroyMenu := GetModuleSymbol(LibGLUT, 'glutDestroyMenu');
+    @glutGetMenu := GetModuleSymbol(LibGLUT, 'glutGetMenu');
+    @glutSetMenu := GetModuleSymbol(LibGLUT, 'glutSetMenu');
+    @glutAddMenuEntry := GetModuleSymbol(LibGLUT, 'glutAddMenuEntry');
+    @glutAddSubMenu := GetModuleSymbol(LibGLUT, 'glutAddSubMenu');
+    @glutChangeToMenuEntry := GetModuleSymbol(LibGLUT, 'glutChangeToMenuEntry');
+    @glutChangeToSubMenu := GetModuleSymbol(LibGLUT, 'glutChangeToSubMenu');
+    @glutRemoveMenuItem := GetModuleSymbol(LibGLUT, 'glutRemoveMenuItem');
+    @glutAttachMenu := GetModuleSymbol(LibGLUT, 'glutAttachMenu');
+    @glutDetachMenu := GetModuleSymbol(LibGLUT, 'glutDetachMenu');
+    @glutDisplayFunc := GetModuleSymbol(LibGLUT, 'glutDisplayFunc');
+    @glutReshapeFunc := GetModuleSymbol(LibGLUT, 'glutReshapeFunc');
+    @glutKeyboardFunc := GetModuleSymbol(LibGLUT, 'glutKeyboardFunc');
+    @glutMouseFunc := GetModuleSymbol(LibGLUT, 'glutMouseFunc');
+    @glutMotionFunc := GetModuleSymbol(LibGLUT, 'glutMotionFunc');
+    @glutPassiveMotionFunc := GetModuleSymbol(LibGLUT, 'glutPassiveMotionFunc');
+    @glutEntryFunc := GetModuleSymbol(LibGLUT, 'glutEntryFunc');
+    @glutVisibilityFunc := GetModuleSymbol(LibGLUT, 'glutVisibilityFunc');
+    @glutIdleFunc := GetModuleSymbol(LibGLUT, 'glutIdleFunc');
+    @glutTimerFunc := GetModuleSymbol(LibGLUT, 'glutTimerFunc');
+    @glutMenuStateFunc := GetModuleSymbol(LibGLUT, 'glutMenuStateFunc');
+    @glutSpecialFunc := GetModuleSymbol(LibGLUT, 'glutSpecialFunc');
+    @glutSpaceballMotionFunc := GetModuleSymbol(LibGLUT, 'glutSpaceballMotionFunc');
+    @glutSpaceballRotateFunc := GetModuleSymbol(LibGLUT, 'glutSpaceballRotateFunc');
+    @glutSpaceballButtonFunc := GetModuleSymbol(LibGLUT, 'glutSpaceballButtonFunc');
+    @glutButtonBoxFunc := GetModuleSymbol(LibGLUT, 'glutButtonBoxFunc');
+    @glutDialsFunc := GetModuleSymbol(LibGLUT, 'glutDialsFunc');
+    @glutTabletMotionFunc := GetModuleSymbol(LibGLUT, 'glutTabletMotionFunc');
+    @glutTabletButtonFunc := GetModuleSymbol(LibGLUT, 'glutTabletButtonFunc');
+    @glutMenuStatusFunc := GetModuleSymbol(LibGLUT, 'glutMenuStatusFunc');
+    @glutOverlayDisplayFunc := GetModuleSymbol(LibGLUT, 'glutOverlayDisplayFunc');
+    @glutWindowStatusFunc := GetModuleSymbol(LibGLUT, 'glutWindowStatusFunc');
+    @glutSetColor := GetModuleSymbol(LibGLUT, 'glutSetColor');
+    @glutGetColor := GetModuleSymbol(LibGLUT, 'glutGetColor');
+    @glutCopyColormap := GetModuleSymbol(LibGLUT, 'glutCopyColormap');
+    @glutGet := GetModuleSymbol(LibGLUT, 'glutGet');
+    @glutDeviceGet := GetModuleSymbol(LibGLUT, 'glutDeviceGet');
+    @glutExtensionSupported := GetModuleSymbol(LibGLUT, 'glutExtensionSupported');
+    @glutGetModifiers := GetModuleSymbol(LibGLUT, 'glutGetModifiers');
+    @glutLayerGet := GetModuleSymbol(LibGLUT, 'glutLayerGet');
+    @glutBitmapCharacter := GetModuleSymbol(LibGLUT, 'glutBitmapCharacter');
+    @glutBitmapWidth := GetModuleSymbol(LibGLUT, 'glutBitmapWidth');
+    @glutStrokeCharacter := GetModuleSymbol(LibGLUT, 'glutStrokeCharacter');
+    @glutStrokeWidth := GetModuleSymbol(LibGLUT, 'glutStrokeWidth');
+    @glutBitmapLength := GetModuleSymbol(LibGLUT, 'glutBitmapLength');
+    @glutStrokeLength := GetModuleSymbol(LibGLUT, 'glutStrokeLength');
+    @glutWireSphere := GetModuleSymbol(LibGLUT, 'glutWireSphere');
+    @glutSolidSphere := GetModuleSymbol(LibGLUT, 'glutSolidSphere');
+    @glutWireCone := GetModuleSymbol(LibGLUT, 'glutWireCone');
+    @glutSolidCone := GetModuleSymbol(LibGLUT, 'glutSolidCone');
+    @glutWireCube := GetModuleSymbol(LibGLUT, 'glutWireCube');
+    @glutSolidCube := GetModuleSymbol(LibGLUT, 'glutSolidCube');
+    @glutWireTorus := GetModuleSymbol(LibGLUT, 'glutWireTorus');
+    @glutSolidTorus := GetModuleSymbol(LibGLUT, 'glutSolidTorus');
+    @glutWireDodecahedron := GetModuleSymbol(LibGLUT, 'glutWireDodecahedron');
+    @glutSolidDodecahedron := GetModuleSymbol(LibGLUT, 'glutSolidDodecahedron');
+    @glutWireTeapot := GetModuleSymbol(LibGLUT, 'glutWireTeapot');
+    @glutSolidTeapot := GetModuleSymbol(LibGLUT, 'glutSolidTeapot');
+    @glutWireOctahedron := GetModuleSymbol(LibGLUT, 'glutWireOctahedron');
+    @glutSolidOctahedron := GetModuleSymbol(LibGLUT, 'glutSolidOctahedron');
+    @glutWireTetrahedron := GetModuleSymbol(LibGLUT, 'glutWireTetrahedron');
+    @glutSolidTetrahedron := GetModuleSymbol(LibGLUT, 'glutSolidTetrahedron');
+    @glutWireIcosahedron := GetModuleSymbol(LibGLUT, 'glutWireIcosahedron');
+    @glutSolidIcosahedron := GetModuleSymbol(LibGLUT, 'glutSolidIcosahedron');
+    @glutVideoResizeGet := GetModuleSymbol(LibGLUT, 'glutVideoResizeGet');
+    @glutSetupVideoResizing := GetModuleSymbol(LibGLUT, 'glutSetupVideoResizing');
+    @glutStopVideoResizing := GetModuleSymbol(LibGLUT, 'glutStopVideoResizing');
+    @glutVideoResize := GetModuleSymbol(LibGLUT, 'glutVideoResize');
+    @glutVideoPan := GetModuleSymbol(LibGLUT, 'glutVideoPan');
+    @glutReportErrors := GetModuleSymbol(LibGLUT, 'glutReportErrors');
+    @glutGameModeString := GetModuleSymbol(LibGLUT, 'glutGameModeString');
+    @glutEnterGameMode  := GetModuleSymbol(LibGLUT, 'glutEnterGameMode');
+    @glutLeaveGameMode  := GetModuleSymbol(LibGLUT, 'glutLeaveGameMode');
+    @glutGameModeGet    := GetModuleSymbol(LibGLUT, 'glutGameModeGet');
+  end;
+end;
+
+initialization
+  LoadGlut( GlutLibName );
+
+finalization
+  FreeGlut;
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas
new file mode 100644
index 00000000..9f36d2b5
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas
@@ -0,0 +1,279 @@
+unit glx;
+{
+  $Id: glx.pas,v 1.3 2006/11/20 21:20:59 savage Exp $
+
+  Translation of the Mesa GLX headers for FreePascal
+  Copyright (C) 1999 Sebastian Guenther
+
+
+  Mesa 3-D graphics library
+  Version:  3.0
+  Copyright (C) 1995-1998  Brian Paul
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Library General Public
+  License as published by the Free Software Foundation; either
+  version 2 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Library General Public License for more details.
+
+  You should have received a copy of the GNU Library General Public
+  License along with this library; if not, write to the Free
+  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+}
+
+// {$MODE delphi}  // objfpc would not work because of direct proc var assignments
+
+{You have to enable Macros (compiler switch "-Sm") for compiling this unit!
+ This is necessary for supporting different platforms with different calling
+ conventions via a single unit.}
+
+{
+  $Log: glx.pas,v $
+  Revision 1.3  2006/11/20 21:20:59  savage
+  Updated to work in MacOS X
+
+  Revision 1.2  2006/04/18 18:38:33  savage
+  fixed boolean test - thanks grudzio
+
+  Revision 1.1  2004/03/30 21:53:55  savage
+  Moved to it's own folder.
+
+  Revision 1.5  2004/02/15 22:48:35  savage
+  More FPC and FreeBSD support changes.
+
+  Revision 1.4  2004/02/14 22:36:29  savage
+  Fixed inconsistencies of using LoadLibrary and LoadModule.
+  Now all units make use of LoadModule rather than LoadLibrary and other dynamic proc procedures.
+
+  Revision 1.3  2004/02/14 00:23:39  savage
+  As UNIX is defined in jedi-sdl.inc this will be used to check linux compatability as well. Units have been changed to reflect this change.
+
+  Revision 1.2  2004/02/14 00:09:19  savage
+  Changed uses to now make use of moduleloader.pas rather than dllfuncs.pas
+
+  Revision 1.1  2004/02/05 00:08:19  savage
+  Module 1.0 release
+
+  Revision 1.1  2003/05/11 13:18:03  savage
+  Newest OpenGL Headers For Delphi, Kylix and FPC
+
+  Revision 1.1  2002/10/13 13:57:31  sg
+  * Finally, the new units are available: Match the C headers more closely;
+    support for OpenGL extensions, and much more. Based on the Delphi units
+    by Tom Nuydens of delphi3d.net
+
+}
+
+interface
+
+{$I jedi-sdl.inc}
+
+{$IFDEF UNIX}
+  uses
+    {$IFDEF FPC}
+    x,
+    xlib,
+    xutil;
+    {$ELSE}
+    xlib;
+    {$ENDIF}
+  {$DEFINE HasGLX}  // Activate GLX stuff
+{$ELSE}
+  {$MESSAGE Unsupported platform.}
+{$ENDIF}
+
+{$IFNDEF HasGLX}
+  {$MESSAGE GLX not present on this platform.}
+{$ENDIF}
+
+
+// =======================================================
+//   Unit specific extensions
+// =======================================================
+
+// Note: Requires that the GL library has already been initialized
+function InitGLX: Boolean;
+
+var
+  GLXDumpUnresolvedFunctions,
+  GLXInitialized: Boolean;
+
+
+// =======================================================
+//   GLX consts, types and functions
+// =======================================================
+
+// Tokens for glXChooseVisual and glXGetConfig:
+const
+  GLX_USE_GL                            = 1;
+  GLX_BUFFER_SIZE                       = 2;
+  GLX_LEVEL                             = 3;
+  GLX_RGBA                              = 4;
+  GLX_DOUBLEBUFFER                      = 5;
+  GLX_STEREO                            = 6;
+  GLX_AUX_BUFFERS                       = 7;
+  GLX_RED_SIZE                          = 8;
+  GLX_GREEN_SIZE                        = 9;
+  GLX_BLUE_SIZE                         = 10;
+  GLX_ALPHA_SIZE                        = 11;
+  GLX_DEPTH_SIZE                        = 12;
+  GLX_STENCIL_SIZE                      = 13;
+  GLX_ACCUM_RED_SIZE                    = 14;
+  GLX_ACCUM_GREEN_SIZE                  = 15;
+  GLX_ACCUM_BLUE_SIZE                   = 16;
+  GLX_ACCUM_ALPHA_SIZE                  = 17;
+
+  // GLX_EXT_visual_info extension
+  GLX_X_VISUAL_TYPE_EXT                 = $22;
+  GLX_TRANSPARENT_TYPE_EXT              = $23;
+  GLX_TRANSPARENT_INDEX_VALUE_EXT       = $24;
+  GLX_TRANSPARENT_RED_VALUE_EXT         = $25;
+  GLX_TRANSPARENT_GREEN_VALUE_EXT       = $26;
+  GLX_TRANSPARENT_BLUE_VALUE_EXT        = $27;
+  GLX_TRANSPARENT_ALPHA_VALUE_EXT       = $28;
+
+
+  // Error codes returned by glXGetConfig:
+  GLX_BAD_SCREEN                        = 1;
+  GLX_BAD_ATTRIBUTE                     = 2;
+  GLX_NO_EXTENSION                      = 3;
+  GLX_BAD_VISUAL                        = 4;
+  GLX_BAD_CONTEXT                       = 5;
+  GLX_BAD_VALUE                         = 6;
+  GLX_BAD_ENUM                          = 7;
+
+  // GLX 1.1 and later:
+  GLX_VENDOR                            = 1;
+  GLX_VERSION                           = 2;
+  GLX_EXTENSIONS                        = 3;
+
+  // GLX_visual_info extension
+  GLX_TRUE_COLOR_EXT                    = $8002;
+  GLX_DIRECT_COLOR_EXT                  = $8003;
+  GLX_PSEUDO_COLOR_EXT                  = $8004;
+  GLX_STATIC_COLOR_EXT                  = $8005;
+  GLX_GRAY_SCALE_EXT                    = $8006;
+  GLX_STATIC_GRAY_EXT                   = $8007;
+  GLX_NONE_EXT                          = $8000;
+  GLX_TRANSPARENT_RGB_EXT               = $8008;
+  GLX_TRANSPARENT_INDEX_EXT             = $8009;
+
+type
+  // From XLib:
+  {$IFNDEF FPC}
+  TXID = XID;
+  {$ENDIF}
+  XPixmap = TXID;
+  XFont = TXID;
+  XColormap = TXID;
+
+  GLXContext = Pointer;
+  GLXPixmap = TXID;
+  GLXDrawable = TXID;
+  GLXContextID = TXID;
+
+var
+  glXChooseVisual: function(dpy: PDisplay; screen: Integer; var attribList: Integer): PXVisualInfo; cdecl;
+  glXCreateContext: function(dpy: PDisplay; vis: PXVisualInfo; shareList: GLXContext; direct: Boolean): GLXContext; cdecl;
+  glXDestroyContext: procedure(dpy: PDisplay; ctx: GLXContext); cdecl;
+  glXMakeCurrent: function(dpy: PDisplay; drawable: GLXDrawable; ctx: GLXContext): Boolean; cdecl;
+  glXCopyContext: procedure(dpy: PDisplay; src, dst: GLXContext; mask: LongWord); cdecl;
+  glXSwapBuffers: procedure(dpy: PDisplay; drawable: GLXDrawable); cdecl;
+  glXCreateGLXPixmap: function(dpy: PDisplay; visual: PXVisualInfo; pixmap: XPixmap): GLXPixmap; cdecl;
+  glXDestroyGLXPixmap: procedure(dpy: PDisplay; pixmap: GLXPixmap); cdecl;
+  glXQueryExtension: function(dpy: PDisplay; var errorb, event: Integer): Boolean; cdecl;
+  glXQueryVersion: function(dpy: PDisplay; var maj, min: Integer): Boolean; cdecl;
+  glXIsDirect: function(dpy: PDisplay; ctx: GLXContext): Boolean; cdecl;
+  glXGetConfig: function(dpy: PDisplay; visual: PXVisualInfo; attrib: Integer; var value: Integer): Integer; cdecl;
+  glXGetCurrentContext: function: GLXContext; cdecl;
+  glXGetCurrentDrawable: function: GLXDrawable; cdecl;
+  glXWaitGL: procedure; cdecl;
+  glXWaitX: procedure; cdecl;
+  glXUseXFont: procedure(font: XFont; first, count, list: Integer); cdecl;
+
+  // GLX 1.1 and later
+  glXQueryExtensionsString: function(dpy: PDisplay; screen: Integer): PChar; cdecl;
+  glXQueryServerString: function(dpy: PDisplay; screen, name: Integer): PChar; cdecl;
+  glXGetClientString: function(dpy: PDisplay; name: Integer): PChar; cdecl;
+
+  // Mesa GLX Extensions
+  glXCreateGLXPixmapMESA: function(dpy: PDisplay; visual: PXVisualInfo; pixmap: XPixmap; cmap: XColormap): GLXPixmap; cdecl;
+  glXReleaseBufferMESA: function(dpy: PDisplay; d: GLXDrawable): Boolean; cdecl;
+  glXCopySubBufferMESA: procedure(dpy: PDisplay; drawbale: GLXDrawable; x, y, width, height: Integer); cdecl;
+  glXGetVideoSyncSGI: function(var counter: LongWord): Integer; cdecl;
+  glXWaitVideoSyncSGI: function(divisor, remainder: Integer; var count: LongWord): Integer; cdecl;
+
+
+// =======================================================
+//
+// =======================================================
+
+implementation
+
+uses
+  {$IFNDEF __GPC__}
+  SysUtils,
+  {$ENDIF}
+  moduleloader;
+
+(* {$LINKLIB m}  *)
+
+var
+  libGLX: TModuleHandle;
+
+function InitGLXFromLibrary( dll : PChar ): Boolean;
+begin
+  Result := False;
+
+  if not LoadModule( libGLX, dll ) then
+    exit;
+
+  glXChooseVisual := GetModuleSymbol(libglx, 'glXChooseVisual');
+  glXCreateContext := GetModuleSymbol(libglx, 'glXCreateContext');
+  glXDestroyContext := GetModuleSymbol(libglx, 'glXDestroyContext');
+  glXMakeCurrent := GetModuleSymbol(libglx, 'glXMakeCurrent');
+  glXCopyContext := GetModuleSymbol(libglx, 'glXCopyContext');
+  glXSwapBuffers := GetModuleSymbol(libglx, 'glXSwapBuffers');
+  glXCreateGLXPixmap := GetModuleSymbol(libglx, 'glXCreateGLXPixmap');
+  glXDestroyGLXPixmap := GetModuleSymbol(libglx, 'glXDestroyGLXPixmap');
+  glXQueryExtension := GetModuleSymbol(libglx, 'glXQueryExtension');
+  glXQueryVersion := GetModuleSymbol(libglx, 'glXQueryVersion');
+  glXIsDirect := GetModuleSymbol(libglx, 'glXIsDirect');
+  glXGetConfig := GetModuleSymbol(libglx, 'glXGetConfig');
+  glXGetCurrentContext := GetModuleSymbol(libglx, 'glXGetCurrentContext');
+  glXGetCurrentDrawable := GetModuleSymbol(libglx, 'glXGetCurrentDrawable');
+  glXWaitGL := GetModuleSymbol(libglx, 'glXWaitGL');
+  glXWaitX := GetModuleSymbol(libglx, 'glXWaitX');
+  glXUseXFont := GetModuleSymbol(libglx, 'glXUseXFont');
+  // GLX 1.1 and later
+  glXQueryExtensionsString := GetModuleSymbol(libglx, 'glXQueryExtensionsString');
+  glXQueryServerString := GetModuleSymbol(libglx, 'glXQueryServerString');
+  glXGetClientString := GetModuleSymbol(libglx, 'glXGetClientString');
+  // Mesa GLX Extensions
+  glXCreateGLXPixmapMESA := GetModuleSymbol(libglx, 'glXCreateGLXPixmapMESA');
+  glXReleaseBufferMESA := GetModuleSymbol(libglx, 'glXReleaseBufferMESA');
+  glXCopySubBufferMESA := GetModuleSymbol(libglx, 'glXCopySubBufferMESA');
+  glXGetVideoSyncSGI := GetModuleSymbol(libglx, 'glXGetVideoSyncSGI');
+  glXWaitVideoSyncSGI := GetModuleSymbol(libglx, 'glXWaitVideoSyncSGI');
+
+  GLXInitialized := True;
+  Result := True;
+end;
+
+function InitGLX: Boolean;
+begin
+  Result := InitGLXFromLibrary('libGL.so.1') or
+            InitGLXFromLibrary('libMesaGL.so') or
+            InitGLXFromLibrary('libMesaGL.so.3');
+end;
+
+
+initialization
+  InitGLX;
+finalization
+  UnloadModule(libGLX);
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/Readme.txt b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/Readme.txt
new file mode 100644
index 00000000..f176d0c9
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/Readme.txt
@@ -0,0 +1,27 @@
+Delphi interface unit for OpenGL version 1.2 compilable with Delphi 3-6 and Kylix.
+
+This unit is open source under the Mozilla Public License and 
+the original author is Dipl. Ing. Mike Lischke (public@lischke-online.de).
+
+You can obtain this unit also from the JEDI (Joint Endeavor of Delphi Innovators) 
+API page at www.delphi-jedi.org.
+
+Note for GLScene users: Eric Grange has provided a general vector types unit which 
+resolves conflicts for types which are defined in OpenGL12.pas as well as Geometry.pas.
+This unit is located in the sub folder "GLScene AddOn".
+Please add this unit to the uses clause of OpenGL12.pas and remove the few types which 
+are already declared in VectorTypes.pas.
+
+For tests and as starting point three demos are included into the package. Two of them (GLDiag and GLTest)
+need the (also provided) simple OpenGL control GLControl (see "GLControl\Package").
+
+- Basic is a very simple test program which only uses an empty form.
+- GLTest (in GLControl) uses GLControl to show four rendering contexts simultanously.
+- GLDiag is a diagnosis tool similar to DXDiag which shows some properties of the current
+   OpenGL driver implementation.
+
+Have fun and 
+
+Ciao, Mike
+www.lischke-online.de
+www.delphi-unicode.net
\ No newline at end of file
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc
new file mode 100644
index 00000000..31817d24
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc
@@ -0,0 +1,442 @@
+{
+  $Id: jedi-sdl.inc,v 1.15 2007/05/29 21:30:48 savage Exp $
+}
+{******************************************************************************}
+{                                                                              }
+{       Borland Delphi SDL - Simple DirectMedia Layer                          }
+{       Global Conditional Definitions for JEDI-SDL cross-compilation          }
+{                                                                              }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{  Prof. Abimbola Olowofoyeku <http://www.bigfoot.com/~African_Chief/>         }
+{                                                                              }
+{ Portions created by Prof. Abimbola Olowofoyeku are                           }
+{ Copyright (C) 2000 - 2100 Prof. Abimbola Olowofoyeku.                        }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{  Prof. Abimbola Olowofoyeku <http://www.bigfoot.com/~African_Chief/>         }
+{  Dominqiue Louis <Dominique@SavageSoftware.com.au>                           }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{ This code has been copied from...                                            }
+{ Global Conditional Definitions for Chief's UNZIP package                     }
+{ By Prof. Abimbola Olowofoyeku (The African Chief)                            }
+{          http://www.bigfoot.com/~African_Chief/                              }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   The SDL Runtime libraris on Win32  : SDL.dll on Linux : libSDL.so          }
+{   They are available from...                                                 }
+{   http://www.libsdl.org .                                                    }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{   2003-04-03   DL - Initial addition                                         }
+{                                                                              }
+{   2003-04-07   DL - Added Macro ON derective for FPC and OpenGL and removed  }
+{                WEAKPACKAGE derective. WEAKPACKAGE should be set when         }
+{                appropriate.                                                  }
+{                                                                              }
+{   2003-04-23 - DL : under instruction from Alexey Barkovoy I have added      }
+{                          better TMT Pascal support and under instruction     }
+{                          from Prof. Abimbola Olowofoyeku (The African Chief) }
+{                          I have added better Gnu Pascal support              }
+{                                                                              }
+{   2004-01-19 - DL : Under instruction from Marco van de Voort, I have added  }
+{                     Better FPC support for FreeBSD.                          }
+{                                                                              }
+(*
+  $Log: jedi-sdl.inc,v $
+  Revision 1.15  2007/05/29 21:30:48  savage
+  Changes as suggested by Almindor for 64bit compatibility.
+
+  Revision 1.14  2007/05/20 20:29:11  savage
+  Initial Changes to Handle 64 Bits
+
+  Revision 1.13  2007/01/21 15:51:45  savage
+  Added Delphi 2006 support
+
+  Revision 1.12  2006/11/19 18:41:01  savage
+  removed THREADING ON flag as it is no longer needed in latest versions of FPC.
+
+  Revision 1.11  2006/01/04 00:52:41  drellis
+  Updated to include defined for ENDIAN values, SDL_BYTEORDER should now be correctly defined depending onthe platform. Code taken from sdl_mixer
+
+  Revision 1.10  2005/05/22 18:42:31  savage
+  Changes as suggested by Michalis Kamburelis. Thanks again.
+
+  Revision 1.9  2004/12/23 23:42:17  savage
+  Applied Patches supplied by Michalis Kamburelis ( THANKS! ), for greater FreePascal compatability.
+
+  Revision 1.8  2004/10/20 22:43:04  savage
+  Ensure that UNSAFE type warning are off in D9 as well
+
+  Revision 1.7  2004/04/05 09:59:51  savage
+  Changes for FreePacal as suggested by Marco
+
+  Revision 1.6  2004/03/31 22:18:15  savage
+  Small comment for turning off warning under GnuPascal
+
+  Revision 1.5  2004/03/30 22:41:02  savage
+  Added extra commenting due to previous compiler directive
+
+  Revision 1.4  2004/03/30 22:08:33  savage
+  Added Kylix Define
+
+  Revision 1.3  2004/03/30 21:34:40  savage
+  {$H+} needed for FPC compatiblity
+
+  Revision 1.2  2004/02/14 00:23:39  savage
+  As UNIX is defined in jedi-sdl.inc this will be used to check linux compatability as well. Units have been changed to reflect this change.
+
+*)
+{******************************************************************************}
+
+{.$define Debug}           { uncomment for debugging }
+
+{$IFNDEF FPC}
+  {$IFDEF __GPC__}
+    {$I-}
+    {$W-} // turn off GPC warnings
+    {$X+}
+  {$ELSE} {__GPC__}
+    {$IFDEF Debug}
+      {$F+,D+,Q-,L+,R+,I-,S+,Y+,A+}
+    {$ELSE}
+      {$F+,Q-,R-,S-,I-,A+}
+    {$ENDIF}
+  {$ENDIF} {__GPC__}
+{$ELSE}  {FPC}
+  //{$M+}
+{$ENDIF} {FPC}
+
+{$IFDEF LINUX}
+{$DEFINE UNIX}
+{$ENDIF}
+
+{$IFDEF ver70}
+   {$IFDEF Windows}
+     {$DEFINE Win16}
+   {$ENDIF Windows}
+   {$IFDEF MSDOS}
+     {$DEFINE NO_EXPORTS}
+   {$ENDIF MSDOS}
+   {$IFDEF DPMI}
+     {$DEFINE BP_DPMI}
+   {$ENDIF}
+   {$DEFINE OS_16_BIT}
+   {$DEFINE __OS_DOS__}
+{$ENDIF ver70}
+
+{$IFDEF ver80}
+   {$DEFINE Delphi}      {Delphi 1.x}
+   {$DEFINE Delphi16}
+   {$DEFINE Win16}
+   {$DEFINE OS_16_BIT}
+   {$DEFINE __OS_DOS__}
+{$ENDIF ver80}
+
+{$IFDEF ver90}
+   {$DEFINE Delphi}      {Delphi 2.x}
+   {$DEFINE Delphi32}
+   {$DEFINE WIN32}
+   {$DEFINE WINDOWS}
+{$ENDIF ver90}
+
+{$IFDEF ver100}
+   {$DEFINE Delphi}      {Delphi 3.x}
+   {$DEFINE Delphi32}
+   {$DEFINE WIN32}
+   {$DEFINE WINDOWS}
+{$ENDIF ver100}
+
+{$IFDEF ver93}
+   {$DEFINE Delphi}      {C++ Builder 1.x}
+   {$DEFINE Delphi32}
+   {$DEFINE WINDOWS}
+{$ENDIF ver93}
+
+{$IFDEF ver110}
+   {$DEFINE Delphi}      {C++ Builder 3.x}
+   {$DEFINE Delphi32}
+   {$DEFINE WINDOWS}
+{$ENDIF ver110}
+
+{$IFDEF ver120}
+   {$DEFINE Delphi}      {Delphi 4.x}
+   {$DEFINE Delphi32}
+   {$DEFINE Delphi4UP}
+   {$DEFINE Has_Int64}
+   {$DEFINE WINDOWS}
+{$ENDIF ver120}
+
+{$IFDEF ver130}
+   {$DEFINE Delphi}      {Delphi 5.x}
+   {$DEFINE Delphi32}
+   {$DEFINE Delphi4UP}
+   {$DEFINE Delphi5UP}
+   {$DEFINE Has_Int64}
+   {$DEFINE WINDOWS}
+{$ENDIF ver130}
+
+{$IFDEF ver140}
+   {$DEFINE Delphi}      {Delphi 6.x}
+   {$DEFINE Delphi32}
+   {$DEFINE Delphi4UP}
+   {$DEFINE Delphi5UP}
+   {$DEFINE Delphi6UP}
+   {$DEFINE Has_Int64}
+   {$DEFINE HAS_TYPES}
+{$ENDIF ver140}
+
+{$IFDEF ver150}
+   {$DEFINE Delphi}      {Delphi 7.x}
+   {$DEFINE Delphi32}
+   {$DEFINE Delphi4UP}
+   {$DEFINE Delphi5UP}
+   {$DEFINE Delphi6UP}
+   {$DEFINE Delphi7UP}
+   {$WARN UNSAFE_TYPE OFF} {Disable warning for unsafe types in Delphi 7}
+   {$DEFINE Has_Int64}
+   {$DEFINE HAS_TYPES}
+{$ENDIF ver150}
+
+{$IFDEF ver160}
+   {$DEFINE Delphi}      {Delphi 8}
+   {$DEFINE Delphi32}
+   {$DEFINE Delphi4UP}
+   {$DEFINE Delphi5UP}
+   {$DEFINE Delphi6UP}
+   {$DEFINE Delphi7UP}
+   {$DEFINE Delphi8UP}
+   {$DEFINE Has_Int64}
+   {$DEFINE HAS_TYPES}
+{$ENDIF ver160}
+
+{$IFDEF ver170}
+   {$DEFINE Delphi}      {Delphi 2005}
+   {$DEFINE Delphi32}
+   {$DEFINE Delphi4UP}
+   {$DEFINE Delphi5UP}
+   {$DEFINE Delphi6UP}
+   {$DEFINE Delphi7UP}
+   {$DEFINE Delphi8UP}
+   {$DEFINE Delphi9UP}
+   {$WARN UNSAFE_TYPE OFF} {Disable warning for unsafe types in Delphi 7}
+   {$DEFINE Has_Int64}
+   {$DEFINE HAS_TYPES}
+{$ENDIF ver170}
+
+{$IFDEF ver180}
+   {$DEFINE Delphi}      {Delphi 2006}
+   {$DEFINE Delphi32}
+   {$DEFINE Delphi4UP}
+   {$DEFINE Delphi5UP}
+   {$DEFINE Delphi6UP}
+   {$DEFINE Delphi7UP}
+   {$DEFINE Delphi8UP}
+   {$DEFINE Delphi9UP}
+   {$DEFINE Delphi10UP}
+   {$WARN UNSAFE_TYPE OFF} {Disable warning for unsafe types in Delphi 7}
+   {$DEFINE Has_Int64}
+   {$DEFINE HAS_TYPES}
+{$ENDIF ver180}
+
+{$IFDEF ver185}
+   {$DEFINE Delphi}      {Delphi 2007}
+   {$DEFINE Delphi32}
+   {$DEFINE Delphi4UP}
+   {$DEFINE Delphi5UP}
+   {$DEFINE Delphi6UP}
+   {$DEFINE Delphi7UP}
+   {$DEFINE Delphi8UP}
+   {$DEFINE Delphi9UP}
+   {$DEFINE Delphi10UP}
+   {$WARN UNSAFE_TYPE OFF} {Disable warning for unsafe types in Delphi 7}
+   {$DEFINE Has_Int64}
+   {$DEFINE HAS_TYPES}
+{$ENDIF ver180}
+
+{$IFDEF UNIX}
+  {$ifdef VER140}    // Kylix 1 & 2
+    {$DEFINE KYLIX}
+    {$DEFINE KYLIX1UP}
+    {$DEFINE KYLIX2UP}
+    {$DEFINE HAS_TYPES}
+  {$endif}
+
+  {$ifdef VER150}   // Kylix 3
+    {$DEFINE KYLIX}
+    {$DEFINE KYLIX1UP}
+    {$DEFINE KYLIX2UP}
+    {$DEFINE KYLIX3UP}
+    {$DEFINE HAS_TYPES}
+  {$endif}
+{$ENDIF UNIX}
+
+{$IFDEF VirtualPascal} {  Virtual Pascal 2.x }
+   {$DEFINE Delphi}    {  Use Delphi Syntax }
+   {$DEFINE VP2}
+   {&Delphi+}
+{$ENDIF VirtualPascal}
+
+{$IFDEF Delphi}
+  {$DEFINE Windows}
+  {$DEFINE USE_STDCALL}
+  {$MINENUMSIZE 4}
+  //{$ALIGN ON}
+{$ENDIF Delphi}
+
+{$IFDEF FPC}
+  {$MODE Delphi}          { use Delphi compatibility mode }
+  {$H+}
+  {$PACKRECORDS C}        // Added for record
+  {$PACKENUM 4}           // Use 4-byte enums
+  {$MACRO ON}             // Added For OpenGL
+  {$DEFINE Delphi}
+  {$DEFINE UseAT}
+  {$UNDEF USE_STDCALL}
+  {$DEFINE OS_BigMem}
+  {$DEFINE NO_EXPORTS}
+  {$DEFINE Has_Int64}
+  {$DEFINE NOCRT}
+  {$IFDEF UNIX}
+     {$DEFINE fpc_unix}
+  {$ELSE}
+     {$DEFINE __OS_DOS__}
+  {$ENDIF}
+  {$IFDEF MSWINDOWS}
+   {$DEFINE UseWin}
+  {$ENDIF}
+  {$DEFINE HAS_TYPES}
+{$ENDIF FPC}
+
+{$IFDEF Win16}
+  {$K+}   {smart callbacks}
+{$ENDIF Win16}
+
+ {$IFDEF OS2}
+    {$UNDEF Windows}
+    {$DEFINE UseWin}
+    {$DEFINE OS_BigMem}
+ {$ENDIF OS2}
+
+{$IFDEF __GPC__}
+  {$UNDEF UseWin}
+  {$UNDEF USE_STDCALL}
+  {$DEFINE OS_BigMem}
+  {$DEFINE NO_EXPORTS}
+  {$DEFINE NOCRT}
+  {$DEFINE cdecl attribute(cdecl)}
+{$ENDIF}
+
+{$IFDEF __TMT__}
+  {$DEFINE OS_BigMem}
+  {$DEFINE NO_EXPORTS}
+  {$DEFINE __OS_DOS__}
+  {$DEFINE UseAT}
+  {$IFNDEF MSDOS}
+    {$DEFINE USE_STDCALL}
+  {$ENDIF}
+
+  {$IFDEF __WIN32__}
+    {$DEFINE Win32}
+    {$DEFINE UseWin}
+    {$DEFINE NOCRT}
+    {$DEFINE Win32}
+    {$IFNDEF __CON__}
+      {$DEFINE Windows}
+    {$ENDIF}
+  {$ENDIF}
+
+  {$A+}  // Word alignment data
+  {$OA+} // Objects and structures align
+{$ENDIF}
+
+{$IFDEF MSWINDOWS}
+  {$DEFINE OS_BigMem}
+{$ELSE MSWINDOWS}
+  {$IFDEF ver70}
+    {$DEFINE assembler}
+  {$ENDIF} { use 16-bit assembler! }
+{$ENDIF MSWINDOWS}
+
+{ ************************** dos/dos-like platforms **************}
+{$IFDEF Windows}
+   {$DEFINE __OS_DOS__}
+   {$DEFINE UseWin}
+   {$DEFINE MSWINDOWS}
+{$ENDIF Delphi}
+
+{$IFDEF OS2}
+   {$DEFINE __OS_DOS__}
+   {$DEFINE Can_Use_DLL}
+{$ENDIF Delphi}
+
+{$IFDEF UseWin}
+   {$DEFINE Can_Use_DLL}
+{$ENDIF}
+
+{$IFDEF Win16}
+   {$DEFINE Can_Use_DLL}
+{$ENDIF}
+
+{$IFDEF BP_DPMI}
+   {$DEFINE Can_Use_DLL}
+{$ENDIF}
+
+{$IFDEF USE_STDCALL}
+   {$IFNDEF __TMT__}
+     {$DEFINE BY_NAME}
+   {$ENDIF}
+{$ENDIF}
+
+{$IFNDEF ver70}
+  {$UNDEF assembler}
+{$ENDIF}
+
+{*************** define LITTLE ENDIAN platforms ********************}
+
+
+{$IFDEF Delphi}
+{$DEFINE IA32}
+{$ENDIF}
+
+{$IFDEF KYLIX}
+{$DEFINE IA32}
+{$ENDIF}
+
+{$IFDEF FPC}
+{$IFDEF FPC_LITTLE_ENDIAN}
+   {$DEFINE IA32}
+{$ELSE FPC_LITTLE_ENDIAN}
+   {$UNDEF IA32}
+{$ENDIF FPC_LITTLE_ENDIAN}
+{$ENDIF}
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/libxmlparser.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/libxmlparser.pas
new file mode 100644
index 00000000..63e7b7fb
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/libxmlparser.pas
@@ -0,0 +1,2688 @@
+(**
+===============================================================================================
+Name    : LibXmlParser
+===============================================================================================
+Project : All Projects
+===============================================================================================
+Subject : Progressive XML Parser for all types of XML Files
+===============================================================================================
+Author  : Stefan Heymann
+          Eschenweg 3
+          72076 T�bingen
+          GERMANY
+
+E-Mail:   stefan@destructor.de
+URL:      www.destructor.de
+===============================================================================================
+Source, Legals ("Licence")
+--------------------------
+The official site to get this parser is http://www.destructor.de/
+
+Usage and Distribution of this Source Code is ruled by the
+"Destructor.de Source code Licence" (DSL) which comes with this file or
+can be downloaded at http://www.destructor.de/
+
+IN SHORT: Usage and distribution of this source code is free.
+          You use it completely on your own risk.
+
+Postcardware
+------------
+If you like this code, please send a postcard of your city to my above address.
+===============================================================================================
+!!!  All parts of this code which are not finished or not conforming exactly to
+     the XmlSpec are marked with three exclamation marks
+
+-!-  Parts where the parser may be able to detect errors in the document's syntax are
+     marked with the dash-exlamation mark-dash sequence.
+===============================================================================================
+Terminology:
+------------
+- Start:   Start of a buffer part
+- Final:   End (last character) of a buffer part
+- DTD:     Document Type Definition
+- DTDc:    Document Type Declaration
+- XMLSpec: The current W3C XML Recommendation (version 1.0 as of 1998-02-10), Chapter No.
+- Cur*:    Fields concerning the "Current" part passed back by the "Scan" method
+===============================================================================================
+Scanning the XML document
+-------------------------
+- Create TXmlParser Instance                     MyXml := TXmlParser.Create;
+- Load XML Document                              MyXml.LoadFromFile (Filename);
+- Start Scanning                                 MyXml.StartScan;
+- Scan Loop                                      WHILE MyXml.Scan DO
+- Test for Part Type                               CASE MyXml.CurPartType OF
+- Handle Parts                                       ... : ;;;
+- Handle Parts                                       ... : ;;;
+- Handle Parts                                       ... : ;;;
+                                                     END;
+- Destroy                                        MyXml.Free;
+===============================================================================================
+Loading the XML document
+------------------------
+You can load the XML document from a file with the "LoadFromFile" method.
+It is beyond the scope of this parser to perform HTTP or FTP accesses. If you want your
+application to handle such requests (URLs), you can load the XML via HTTP or FTP or whatever
+protocol and hand over the data buffer using the "LoadFromBuffer" or "SetBuffer" method.
+"LoadFromBuffer" loads the internal buffer of TXmlParser with the given null-terminated
+string, thereby creating a copy of that buffer.
+"SetBuffer" just takes the pointer to another buffer, which means that the given
+buffer pointer must be valid while the document is accessed via TXmlParser.
+===============================================================================================
+Encodings:
+----------
+This XML parser kind of "understands" the following encodings:
+- UTF-8
+- ISO-8859-1
+- Windows-1252
+
+Any flavor of multi-byte characters (and this includes UTF-16) is not supported. Sorry.
+
+Every string which has to be passed to the application passes the virtual method
+"TranslateEncoding" which translates the string from the current encoding (stored in
+"CurEncoding") into the encoding the application wishes to receive.
+The "TranslateEncoding" method that is built into TXmlParser assumes that the application
+wants to receive Windows ANSI (Windows-1252, about the same as ISO-8859-1) and is able
+to convert UTF-8 and ISO-8859-1 encodings.
+For other source and target encodings, you will have to override "TranslateEncoding".
+===============================================================================================
+Buffer Handling
+---------------
+- The document must be loaded completely into a piece of RAM
+- All character positions are referenced by PChar pointers
+- The TXmlParser instance can either "own" the buffer itself (then, FBufferSize is > 0)
+  or reference the buffer of another instance or object (then, FBuffersize is 0 and
+  FBuffer is not NIL)
+- The Property DocBuffer passes back a pointer to the first byte of the document. If there
+  is no document stored (FBuffer is NIL), the DocBuffer returns a pointer to a NULL character.
+===============================================================================================
+Whitespace Handling
+-------------------
+The TXmlParser property "PackSpaces" determines how Whitespace is returned in Text Content:
+While PackSpaces is true, all leading and trailing whitespace characters are trimmed of, all
+Whitespace is converted to Space #x20 characters and contiguous Whitespace characters are
+compressed to one.
+If the "Scan" method reports a ptContent part, the application can get the original text
+with all whitespace characters by extracting the characters from "CurStart" to "CurFinal".
+If the application detects an xml:space attribute, it can set "PackSpaces" accordingly or
+use CurStart/CurFinal.
+Please note that TXmlParser does _not_ normalize Line Breaks to single LineFeed characters
+as the XmlSpec requires (XmlSpec 2.11).
+The xml:space attribute is not handled by TXmlParser. This is on behalf of the application.
+===============================================================================================
+Non-XML-Conforming
+------------------
+TXmlParser does not conform 100 % exactly to the XmlSpec:
+- UTF-16 is not supported (XmlSpec 2.2)
+  (Workaround: Convert UTF-16 to UTF-8 and hand the buffer over to TXmlParser)
+- As the parser only works with single byte strings, all Unicode characters > 255
+  can currently not be handled correctly.
+- Line breaks are not normalized to single Linefeed #x0A characters (XmlSpec 2.11)
+  (Workaround: The Application can access the text contents on its own [CurStart, CurFinal],
+  thereby applying every normalization it wishes to)
+- The attribute value normalization does not work exactly as defined in the
+  Second Edition of the XML 1.0 specification.
+- See also the code parts marked with three consecutive exclamation marks. These are
+  parts which are not finished in the current code release.
+
+This list may be incomplete, so it may grow if I get to know any other points.
+As work on the parser proceeds, this list may also shrink.
+===============================================================================================
+Things Todo
+-----------
+- Introduce a new event/callback which is called when there is an unresolvable
+  entity or character reference
+- Support Unicode
+- Use Streams instead of reading the whole XML into memory
+===============================================================================================
+Change History, Version numbers
+-------------------------------
+The Date is given in ISO Year-Month-Day (YYYY-MM-DD) order.
+Versions are counted from 1.0.0 beginning with the version from 2000-03-16.
+Unreleased versions don't get a version number.
+
+Date        Author Version Changes
+-----------------------------------------------------------------------------------------------
+2000-03-16  HeySt  1.0.0   Start
+2000-03-28  HeySt  1.0.1   Initial Publishing of TXmlParser on the destructor.de Web Site
+2000-03-30  HeySt  1.0.2   TXmlParser.AnalyzeCData: Call "TranslateEncoding" for CurContent
+2000-03-31  HeySt  1.0.3   Deleted the StrPosE function (was not needed anyway)
+2000-04-04  HeySt  1.0.4   TDtdElementRec modified: Start/Final for all Elements;
+                           Should be backwards compatible.
+                           AnalyzeDtdc: Set CurPartType to ptDtdc
+2000-04-23  HeySt  1.0.5   New class TObjectList. Eliminated reference to the Delphi 5
+                           "Contnrs" unit so LibXmlParser is Delphi 4 compatible.
+2000-07-03  HeySt  1.0.6   TNvpNode: Added Constructor
+2000-07-11  HeySt  1.0.7   Removed "Windows" from USES clause
+                           Added three-exclamation-mark comments for Utf8ToAnsi/AnsiToUtf8
+                           Added three-exclamation-mark comments for CHR function calls
+2000-07-23  HeySt  1.0.8   TXmlParser.Clear: CurAttr.Clear; EntityStack.Clear;
+                           (This was not a bug; just defensive programming)
+2000-07-29  HeySt  1.0.9   TNvpList: Added methods: Node(Index), Value(Index), Name(Index);
+2000-10-07  HeySt          Introduced Conditional Defines
+                           Uses Contnrs unit and its TObjectList class again for
+                           Delphi 5 and newer versions
+2001-01-30  HeySt          Introduced Version Numbering
+                           Made LoadFromFile and LoadFromBuffer BOOLEAN functions
+                           Introduced FileMode parameter for LoadFromFile
+                           BugFix: TAttrList.Analyze: Must add CWhitespace to ExtractName call
+                           Comments worked over
+2001-02-28  HeySt  1.0.10  Completely worked over and tested the UTF-8 functions
+                           Fixed a bug in TXmlParser.Scan which caused it to start over when it
+                           was called after the end of scanning, resulting in an endless loop
+                           TEntityStack is now a TObjectList instead of TList
+2001-07-03  HeySt  1.0.11  Updated Compiler Version IFDEFs for Kylix
+2001-07-11  HeySt  1.0.12  New TCustomXmlScanner component (taken over from LibXmlComps.pas)
+2001-07-14  HeySt  1.0.13  Bugfix TCustomXmlScanner.FOnTranslateEncoding
+2001-10-22  HeySt          Don't clear CurName anymore when the parser finds a CDATA section.
+2001-12-03  HeySt  1.0.14  TObjectList.Clear: Make call to INHERITED method (fixes a memory leak)
+2001-12-05  HeySt  1.0.15  TObjectList.Clear: removed call to INHERITED method
+                           TObjectList.Destroy: Inserted SetCapacity call.
+                           Reduces need for frequent re-allocation of pointer buffer
+                           Dedicated to my father, Theodor Heymann
+2002-06-26  HeySt  1.0.16  TXmlParser.Scan: Fixed a bug with PIs whose name is beginning
+                           with 'xml'. Thanks to Uwe Kamm for submitting this bug.
+                           The CurEncoding property is now always in uppercase letters (the XML
+                           spec wants it to be treated case independently so when it's uppercase
+                           comparisons are faster)
+2002-03-04  HeySt  1.0.17  Included an IFDEF for Delphi 7 (VER150) and Kylix
+                           There is a new symbol HAS_CONTNRS_UNIT which is used now to
+                           distinguish between IDEs which come with the Contnrs unit and
+                           those that don't.
+*)
+
+UNIT libxmlparser;
+
+{$I jedi-sdl.inc}
+
+INTERFACE
+
+USES
+  SysUtils, Classes,
+  (*$IFDEF HAS_CONTNRS_UNIT *)  // The Contnrs Unit was introduced in Delphi 5
+  Contnrs,
+  (*$ENDIF*)
+  Math;
+
+CONST
+  CVersion = '1.0.17';  // This variable will be updated for every release
+                        // (I hope, I won't forget to do it everytime ...)
+
+TYPE
+  TPartType    = // --- Document Part Types
+                 (ptNone,            // Nothing
+                  ptXmlProlog,       // XML Prolog                  XmlSpec 2.8 / 4.3.1
+                  ptComment,         // Comment                     XmlSpec 2.5
+                  ptPI,              // Processing Instruction      XmlSpec 2.6
+                  ptDtdc,            // Document Type Declaration   XmlSpec 2.8
+                  ptStartTag,        // Start Tag                   XmlSpec 3.1
+                  ptEmptyTag,        // Empty-Element Tag           XmlSpec 3.1
+                  ptEndTag,          // End Tag                     XmlSpec 3.1
+                  ptContent,         // Text Content between Tags
+                  ptCData);          // CDATA Section               XmlSpec 2.7
+
+  TDtdElemType = // --- DTD Elements
+                 (deElement,         // !ELEMENT declaration
+                  deAttList,         // !ATTLIST declaration
+                  deEntity,          // !ENTITY declaration
+                  deNotation,        // !NOTATION declaration
+                  dePI,              // PI in DTD
+                  deComment,         // Comment in DTD
+                  deError);          // Error found in the DTD
+
+TYPE
+  TAttrList    = CLASS;
+  TEntityStack = CLASS;
+  TNvpList     = CLASS;
+  TElemDef     = CLASS;
+  TElemList    = CLASS;
+  TEntityDef   = CLASS;
+  TNotationDef = CLASS;
+
+  TDtdElementRec = RECORD    // --- This Record is returned by the DTD parser callback function
+                     Start, Final : PChar;                             // Start/End of the Element's Declaration
+                     CASE ElementType : TDtdElemType OF                // Type of the Element
+                       deElement,                                      // <!ELEMENT>
+                       deAttList  : (ElemDef      : TElemDef);         // <!ATTLIST>
+                       deEntity   : (EntityDef    : TEntityDef);       // <!ENTITY>
+                       deNotation : (NotationDef  : TNotationDef);     // <!NOTATION>
+                       dePI       : (Target       : PChar;             // <?PI ?>
+                                     Content      : PChar;
+                                     AttrList     : TAttrList);
+                       deError    : (Pos          : PChar);            // Error
+                       // deComment : ((No additional fields here));   // <!-- Comment -->
+                   END;
+
+  TXmlParser = CLASS                             // --- Internal Properties and Methods
+               PROTECTED
+                 FBuffer      : PChar;           // NIL if there is no buffer available
+                 FBufferSize  : INTEGER;         // 0 if the buffer is not owned by the Document instance
+                 FSource      : STRING;          // Name of Source of document. Filename for Documents loaded with LoadFromFile
+
+                 FXmlVersion  : STRING;          // XML version from Document header. Default is '1.0'
+                 FEncoding    : STRING;          // Encoding from Document header. Default is 'UTF-8'
+                 FStandalone  : BOOLEAN;         // Standalone declaration from Document header. Default is 'yes'
+                 FRootName    : STRING;          // Name of the Root Element (= DTD name)
+                 FDtdcFinal   : PChar;           // Pointer to the '>' character terminating the DTD declaration
+
+                 FNormalize   : BOOLEAN;         // If true: Pack Whitespace and don't return empty contents
+                 EntityStack  : TEntityStack;    // Entity Stack for Parameter and General Entities
+                 FCurEncoding : STRING;          // Current Encoding during parsing (always uppercase)
+
+                 PROCEDURE AnalyzeProlog;                                         // Analyze XML Prolog or Text Declaration
+                 PROCEDURE AnalyzeComment (Start : PChar; VAR Final : PChar);     // Analyze Comments
+                 PROCEDURE AnalyzePI      (Start : PChar; VAR Final : PChar);     // Analyze Processing Instructions (PI)
+                 PROCEDURE AnalyzeDtdc;                                           // Analyze Document Type Declaration
+                 PROCEDURE AnalyzeDtdElements (Start : PChar; VAR Final : PChar); // Analyze DTD declarations
+                 PROCEDURE AnalyzeTag;                                            // Analyze Start/End/Empty-Element Tags
+                 PROCEDURE AnalyzeCData;                                          // Analyze CDATA Sections
+                 PROCEDURE AnalyzeText (VAR IsDone : BOOLEAN);                    // Analyze Text Content between Tags
+                 PROCEDURE AnalyzeElementDecl  (Start : PChar; VAR Final : PChar);
+                 PROCEDURE AnalyzeAttListDecl  (Start : PChar; VAR Final : PChar);
+                 PROCEDURE AnalyzeEntityDecl   (Start : PChar; VAR Final : PChar);
+                 PROCEDURE AnalyzeNotationDecl (Start : PChar; VAR Final : PChar);
+
+                 PROCEDURE PushPE (VAR Start : PChar);
+                 PROCEDURE ReplaceCharacterEntities (VAR Str : STRING);
+                 PROCEDURE ReplaceParameterEntities (VAR Str : STRING);
+                 PROCEDURE ReplaceGeneralEntities   (VAR Str : STRING);
+
+                 FUNCTION GetDocBuffer : PChar;  // Returns FBuffer or a pointer to a NUL char if Buffer is empty
+
+               PUBLIC                         // --- Document Properties
+                 PROPERTY XmlVersion : STRING  READ FXmlVersion;                 // XML version from the Document Prolog
+                 PROPERTY Encoding   : STRING  READ FEncoding;                   // Document Encoding from Prolog
+                 PROPERTY Standalone : BOOLEAN READ FStandalone;                 // Standalone Declaration from Prolog
+                 PROPERTY RootName   : STRING  READ FRootName;                   // Name of the Root Element
+                 PROPERTY Normalize  : BOOLEAN READ FNormalize WRITE FNormalize; // True if Content is to be normalized
+                 PROPERTY Source     : STRING  READ FSource;                     // Name of Document Source (Filename)
+                 PROPERTY DocBuffer  : PChar   READ GetDocBuffer;                // Returns document buffer
+               PUBLIC                         // --- DTD Objects
+                 Elements    : TElemList;     // Elements: List of TElemDef (contains Attribute Definitions)
+                 Entities    : TNvpList;      // General Entities: List of TEntityDef
+                 ParEntities : TNvpList;      // Parameter Entities: List of TEntityDef
+                 Notations   : TNvpList;      // Notations: List of TNotationDef
+               PUBLIC
+                 CONSTRUCTOR Create;
+                 DESTRUCTOR Destroy;                                      OVERRIDE;
+
+                 // --- Document Handling
+                 FUNCTION  LoadFromFile   (Filename : STRING;
+                                           FileMode : INTEGER = fmOpenRead OR fmShareDenyNone) : BOOLEAN;
+                                                                          // Loads Document from given file
+                 FUNCTION  LoadFromBuffer (Buffer : PChar) : BOOLEAN;     // Loads Document from another buffer
+                 PROCEDURE SetBuffer      (Buffer : PChar);               // References another buffer
+                 PROCEDURE Clear;                                         // Clear Document
+
+               PUBLIC
+                 // --- Scanning through the document
+                 CurPartType : TPartType;                         // Current Type
+                 CurName     : STRING;                            // Current Name
+                 CurContent  : STRING;                            // Current Normalized Content
+                 CurStart    : PChar;                             // Current First character
+                 CurFinal    : PChar;                             // Current Last character
+                 CurAttr     : TAttrList;                         // Current Attribute List
+                 PROPERTY CurEncoding : STRING READ FCurEncoding; // Current Encoding
+                 PROCEDURE StartScan;
+                 FUNCTION  Scan : BOOLEAN;
+
+                 // --- Events / Callbacks
+                 FUNCTION  LoadExternalEntity (SystemId, PublicId,
+                                               Notation : STRING) : TXmlParser;     VIRTUAL;
+                 FUNCTION  TranslateEncoding  (CONST Source : STRING) : STRING;     VIRTUAL;
+                 PROCEDURE DtdElementFound (DtdElementRec : TDtdElementRec);        VIRTUAL;
+               END;
+
+  TValueType   = // --- Attribute Value Type
+                 (vtNormal,       // Normal specified Attribute
+                  vtImplied,      // #IMPLIED attribute value
+                  vtFixed,        // #FIXED attribute value
+                  vtDefault);     // Attribute value from default value in !ATTLIST declaration
+
+  TAttrDefault = // --- Attribute Default Type
+                 (adDefault,      // Normal default value
+                  adRequired,     // #REQUIRED attribute
+                  adImplied,      // #IMPLIED attribute
+                  adFixed);       // #FIXED attribute
+
+  TAttrType    = // --- Type of attribute
+                 (atUnknown,      // Unknown type
+                  atCData,        // Character data only
+                  atID,           // ID
+                  atIdRef,        // ID Reference
+                  atIdRefs,       // Several ID References, separated by Whitespace
+                  atEntity,       // Name of an unparsed Entity
+                  atEntities,     // Several unparsed Entity names, separated by Whitespace
+                  atNmToken,      // Name Token
+                  atNmTokens,     // Several Name Tokens, separated by Whitespace
+                  atNotation,     // A selection of Notation names (Unparsed Entity)
+                  atEnumeration); // Enumeration
+
+  TElemType    = // --- Element content type
+                 (etEmpty,        // Element is always empty
+                  etAny,          // Element can have any mixture of PCDATA and any elements
+                  etChildren,     // Element must contain only elements
+                  etMixed);       // Mixed PCDATA and elements
+
+  (*$IFDEF HAS_CONTNRS_UNIT *)
+  TObjectList = Contnrs.TObjectList;    // Re-Export this identifier
+  (*$ELSE *)
+  TObjectList = CLASS (TList)
+                  DESTRUCTOR Destroy; OVERRIDE;
+                  PROCEDURE Delete (Index : INTEGER);
+                  PROCEDURE Clear; OVERRIDE;
+                END;
+  (*$ENDIF *)
+
+  TNvpNode  = CLASS                     // Name-Value Pair Node
+                 Name  : STRING;
+                 Value : STRING;
+                 CONSTRUCTOR Create (TheName : STRING = ''; TheValue : STRING = '');
+              END;
+
+  TNvpList  = CLASS (TObjectList)       // Name-Value Pair List
+                PROCEDURE Add   (Node  : TNvpNode);
+                FUNCTION  Node  (Name  : STRING)  : TNvpNode;  OVERLOAD;
+                FUNCTION  Node  (Index : INTEGER) : TNvpNode;  OVERLOAD;
+                FUNCTION  Value (Name  : STRING)  : STRING;    OVERLOAD;
+                FUNCTION  Value (Index : INTEGER) : STRING;    OVERLOAD;
+                FUNCTION  Name  (Index : INTEGER) : STRING;
+              END;
+
+  TAttr     = CLASS (TNvpNode)          // Attribute of a Start-Tag or Empty-Element-Tag
+                 ValueType : TValueType;
+                 AttrType  : TAttrType;
+               END;
+
+  TAttrList = CLASS (TNvpList)          // List of Attributes
+                PROCEDURE Analyze (Start : PChar; VAR Final : PChar);
+              END;
+
+  TEntityStack = CLASS (TObjectList)    // Stack where current position is stored before parsing entities
+                 PROTECTED
+                   Owner : TXmlParser;
+                 PUBLIC
+                   CONSTRUCTOR Create (TheOwner : TXmlParser);
+                   PROCEDURE Push (LastPos : PChar);                      OVERLOAD;
+                   PROCEDURE Push (Instance : TObject; LastPos : PChar);  OVERLOAD;
+                   FUNCTION  Pop : PChar;         // Returns next char or NIL if EOF is reached. Frees Instance.
+                 END;
+
+  TAttrDef    = CLASS (TNvpNode)        // Represents a <!ATTLIST Definition. "Value" is the default value
+                  TypeDef     : STRING;           // Type definition from the DTD
+                  Notations   : STRING;           // Notation List, separated by pipe symbols '|'
+                  AttrType    : TAttrType;        // Attribute Type
+                  DefaultType : TAttrDefault;     // Default Type
+                END;
+
+  TElemDef    = CLASS (TNvpList)       // Represents a <!ELEMENT Definition. Is a list of TAttrDef-Nodes
+                  Name       : STRING;            // Element name
+                  ElemType   : TElemType;         // Element type
+                  Definition : STRING;            // Element definition from DTD
+                END;
+
+  TElemList   = CLASS (TObjectList)    // List of TElemDef nodes
+                  FUNCTION  Node (Name : STRING) : TElemDef;
+                  PROCEDURE Add (Node : TElemDef);
+                END;
+
+  TEntityDef  = CLASS (TNvpNode)       // Represents a <!ENTITY Definition.
+                  SystemId     : STRING;
+                  PublicId     : STRING;
+                  NotationName : STRING;
+                END;
+
+  TNotationDef = CLASS (TNvpNode)      // Represents a <!NOTATION Definition. Value is the System ID
+                   PublicId : STRING;
+                 END;
+
+  TCharset = SET OF CHAR;
+
+
+CONST
+  CWhitespace   = [#32, #9, #13, #10];                // Whitespace characters (XmlSpec 2.3)
+  CLetter       = [#$41..#$5A, #$61..#$7A, #$C0..#$D6, #$D8..#$F6, #$F8..#$FF];
+  CDigit        = [#$30..#$39];
+  CNameChar     = CLetter + CDigit + ['.', '-', '_', ':', #$B7];
+  CNameStart    = CLetter + ['_', ':'];
+  CQuoteChar    = ['"', ''''];
+  CPubidChar    = [#32, ^M, ^J, #9, 'a'..'z', 'A'..'Z', '0'..'9',
+                   '-', '''', '(', ')', '+', ',', '.', '/', ':',
+                   '=', '?', ';', '!', '*', '#', '@', '$', '_', '%'];
+
+  CDStart       = '<![CDATA[';
+  CDEnd         = ']]>';
+
+  // --- Name Constants for the above enumeration types
+  CPartType_Name : ARRAY [TPartType] OF STRING =
+                   ('', 'XML Prolog', 'Comment', 'PI',
+                    'DTD Declaration', 'Start Tag', 'Empty Tag', 'End Tag',
+                    'Text', 'CDATA');
+  CValueType_Name   : ARRAY [TValueType]    OF STRING = ('Normal', 'Implied', 'Fixed', 'Default');
+  CAttrDefault_Name : ARRAY [TAttrDefault]  OF STRING = ('Default', 'Required', 'Implied', 'Fixed');
+  CElemType_Name    : ARRAY [TElemType]     OF STRING = ('Empty', 'Any', 'Childs only', 'Mixed');
+  CAttrType_Name    : ARRAY [TAttrType]     OF STRING = ('Unknown', 'CDATA',
+                                                         'ID', 'IDREF', 'IDREFS',
+                                                         'ENTITY', 'ENTITIES',
+                                                         'NMTOKEN', 'NMTOKENS',
+                                                         'Notation', 'Enumeration');
+
+FUNCTION  ConvertWs   (Source: STRING; PackWs: BOOLEAN) : STRING;          // Convert WS to spaces #x20
+PROCEDURE SetStringSF (VAR S : STRING; BufferStart, BufferFinal : PChar);  // SetString by Start/Final of buffer
+FUNCTION  StrSFPas    (Start, Finish : PChar) : STRING;                    // Convert buffer part to Pascal string
+FUNCTION  TrimWs      (Source : STRING) : STRING;                          // Trim Whitespace
+
+FUNCTION  AnsiToUtf8  (Source : ANSISTRING) : STRING;                            // Convert Win-1252 to UTF-8
+FUNCTION  Utf8ToAnsi  (Source : STRING; UnknownChar : CHAR = '�') : ANSISTRING;  // Convert UTF-8 to Win-1252
+
+
+(*
+===============================================================================================
+TCustomXmlScanner event based component wrapper for TXmlParser
+===============================================================================================
+*)
+
+TYPE
+  TCustomXmlScanner = CLASS;
+  TXmlPrologEvent   = PROCEDURE (Sender : TObject; XmlVersion, Encoding: STRING; Standalone : BOOLEAN) OF OBJECT;
+  TCommentEvent     = PROCEDURE (Sender : TObject; Comment : STRING)                                   OF OBJECT;
+  TPIEvent          = PROCEDURE (Sender : TObject; Target, Content: STRING; Attributes : TAttrList)    OF OBJECT;
+  TDtdEvent         = PROCEDURE (Sender : TObject; RootElementName : STRING)                           OF OBJECT;
+  TStartTagEvent    = PROCEDURE (Sender : TObject; TagName : STRING; Attributes : TAttrList)           OF OBJECT;
+  TEndTagEvent      = PROCEDURE (Sender : TObject; TagName : STRING)                                   OF OBJECT;
+  TContentEvent     = PROCEDURE (Sender : TObject; Content : STRING)                                   OF OBJECT;
+  TElementEvent     = PROCEDURE (Sender : TObject; ElemDef : TElemDef)                                 OF OBJECT;
+  TEntityEvent      = PROCEDURE (Sender : TObject; EntityDef : TEntityDef)                             OF OBJECT;
+  TNotationEvent    = PROCEDURE (Sender : TObject; NotationDef : TNotationDef)                         OF OBJECT;
+  TErrorEvent       = PROCEDURE (Sender : TObject; ErrorPos : PChar)                                   OF OBJECT;
+  TExternalEvent    = PROCEDURE (Sender : TObject; SystemId, PublicId, NotationId : STRING;
+                                 VAR Result : TXmlParser)                                              OF OBJECT;
+  TEncodingEvent    = FUNCTION  (Sender : TObject; CurrentEncoding, Source : STRING) : STRING          OF OBJECT;
+
+
+  TCustomXmlScanner = CLASS (TComponent)
+    PROTECTED
+      FXmlParser           : TXmlParser;
+      FOnXmlProlog         : TXmlPrologEvent;
+      FOnComment           : TCommentEvent;
+      FOnPI                : TPIEvent;
+      FOnDtdRead           : TDtdEvent;
+      FOnStartTag          : TStartTagEvent;
+      FOnEmptyTag          : TStartTagEvent;
+      FOnEndTag            : TEndTagEvent;
+      FOnContent           : TContentEvent;
+      FOnCData             : TContentEvent;
+      FOnElement           : TElementEvent;
+      FOnAttList           : TElementEvent;
+      FOnEntity            : TEntityEvent;
+      FOnNotation          : TNotationEvent;
+      FOnDtdError          : TErrorEvent;
+      FOnLoadExternal      : TExternalEvent;
+      FOnTranslateEncoding : TEncodingEvent;
+      FStopParser          : BOOLEAN;
+      FUNCTION  GetNormalize : BOOLEAN;
+      PROCEDURE SetNormalize (Value : BOOLEAN);
+
+      PROCEDURE WhenXmlProlog(XmlVersion, Encoding: STRING; Standalone : BOOLEAN); VIRTUAL;
+      PROCEDURE WhenComment  (Comment : STRING);                                   VIRTUAL;
+      PROCEDURE WhenPI       (Target, Content: STRING; Attributes : TAttrList);    VIRTUAL;
+      PROCEDURE WhenDtdRead  (RootElementName : STRING);                           VIRTUAL;
+      PROCEDURE WhenStartTag (TagName : STRING; Attributes : TAttrList);           VIRTUAL;
+      PROCEDURE WhenEmptyTag (TagName : STRING; Attributes : TAttrList);           VIRTUAL;
+      PROCEDURE WhenEndTag   (TagName : STRING);                                   VIRTUAL;
+      PROCEDURE WhenContent  (Content : STRING);                                   VIRTUAL;
+      PROCEDURE WhenCData    (Content : STRING);                                   VIRTUAL;
+      PROCEDURE WhenElement  (ElemDef : TElemDef);                                 VIRTUAL;
+      PROCEDURE WhenAttList  (ElemDef : TElemDef);                                 VIRTUAL;
+      PROCEDURE WhenEntity   (EntityDef : TEntityDef);                             VIRTUAL;
+      PROCEDURE WhenNotation (NotationDef : TNotationDef);                         VIRTUAL;
+      PROCEDURE WhenDtdError (ErrorPos : PChar);                                   VIRTUAL;
+
+    PUBLIC
+      CONSTRUCTOR Create (AOwner: TComponent); OVERRIDE;
+      DESTRUCTOR Destroy;                      OVERRIDE;
+
+      PROCEDURE LoadFromFile   (Filename : TFilename);   // Load XML Document from file
+      PROCEDURE LoadFromBuffer (Buffer : PChar);         // Load XML Document from buffer
+      PROCEDURE SetBuffer      (Buffer : PChar);         // Refer to Buffer
+      FUNCTION  GetFilename : TFilename;
+
+      PROCEDURE Execute;                                 // Perform scanning
+
+    PROTECTED
+      PROPERTY XmlParser           : TXmlParser        READ FXmlParser;
+      PROPERTY StopParser          : BOOLEAN           READ FStopParser          WRITE FStopParser;
+      PROPERTY Filename            : TFilename         READ GetFilename          WRITE LoadFromFile;
+      PROPERTY Normalize           : BOOLEAN           READ GetNormalize         WRITE SetNormalize;
+      PROPERTY OnXmlProlog         : TXmlPrologEvent   READ FOnXmlProlog         WRITE FOnXmlProlog;
+      PROPERTY OnComment           : TCommentEvent     READ FOnComment           WRITE FOnComment;
+      PROPERTY OnPI                : TPIEvent          READ FOnPI                WRITE FOnPI;
+      PROPERTY OnDtdRead           : TDtdEvent         READ FOnDtdRead           WRITE FOnDtdRead;
+      PROPERTY OnStartTag          : TStartTagEvent    READ FOnStartTag          WRITE FOnStartTag;
+      PROPERTY OnEmptyTag          : TStartTagEvent    READ FOnEmptyTag          WRITE FOnEmptyTag;
+      PROPERTY OnEndTag            : TEndTagEvent      READ FOnEndTag            WRITE FOnEndTag;
+      PROPERTY OnContent           : TContentEvent     READ FOnContent           WRITE FOnContent;
+      PROPERTY OnCData             : TContentEvent     READ FOnCData             WRITE FOnCData;
+      PROPERTY OnElement           : TElementEvent     READ FOnElement           WRITE FOnElement;
+      PROPERTY OnAttList           : TElementEvent     READ FOnAttList           WRITE FOnAttList;
+      PROPERTY OnEntity            : TEntityEvent      READ FOnEntity            WRITE FOnEntity;
+      PROPERTY OnNotation          : TNotationEvent    READ FOnNotation          WRITE FOnNotation;
+      PROPERTY OnDtdError          : TErrorEvent       READ FOnDtdError          WRITE FOnDtdError;
+      PROPERTY OnLoadExternal      : TExternalEvent    READ FOnLoadExternal      WRITE FOnLoadExternal;
+      PROPERTY OnTranslateEncoding : TEncodingEvent    READ FOnTranslateEncoding WRITE FOnTranslateEncoding;
+    END;
+
+(*
+===============================================================================================
+IMPLEMENTATION
+===============================================================================================
+*)
+
+IMPLEMENTATION
+
+
+(*
+===============================================================================================
+Unicode and UTF-8 stuff
+===============================================================================================
+*)
+
+CONST
+  // --- Character Translation Table for Unicode <-> Win-1252
+  WIN1252_UNICODE : ARRAY [$00..$FF] OF WORD = (
+                    $0000, $0001, $0002, $0003, $0004, $0005, $0006, $0007, $0008, $0009,
+                    $000A, $000B, $000C, $000D, $000E, $000F, $0010, $0011, $0012, $0013,
+                    $0014, $0015, $0016, $0017, $0018, $0019, $001A, $001B, $001C, $001D,
+                    $001E, $001F, $0020, $0021, $0022, $0023, $0024, $0025, $0026, $0027,
+                    $0028, $0029, $002A, $002B, $002C, $002D, $002E, $002F, $0030, $0031,
+                    $0032, $0033, $0034, $0035, $0036, $0037, $0038, $0039, $003A, $003B,
+                    $003C, $003D, $003E, $003F, $0040, $0041, $0042, $0043, $0044, $0045,
+                    $0046, $0047, $0048, $0049, $004A, $004B, $004C, $004D, $004E, $004F,
+                    $0050, $0051, $0052, $0053, $0054, $0055, $0056, $0057, $0058, $0059,
+                    $005A, $005B, $005C, $005D, $005E, $005F, $0060, $0061, $0062, $0063,
+                    $0064, $0065, $0066, $0067, $0068, $0069, $006A, $006B, $006C, $006D,
+                    $006E, $006F, $0070, $0071, $0072, $0073, $0074, $0075, $0076, $0077,
+                    $0078, $0079, $007A, $007B, $007C, $007D, $007E, $007F,
+
+                    $20AC, $0081, $201A, $0192, $201E, $2026, $2020, $2021, $02C6, $2030,
+                    $0160, $2039, $0152, $008D, $017D, $008F, $0090, $2018, $2019, $201C,
+                    $201D, $2022, $2013, $2014, $02DC, $2122, $0161, $203A, $0153, $009D,
+                    $017E, $0178, $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7,
+                    $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF, $00B0, $00B1,
+                    $00B2, $00B3, $00B4, $00B5, $00B6, $00B7, $00B8, $00B9, $00BA, $00BB,
+                    $00BC, $00BD, $00BE, $00BF, $00C0, $00C1, $00C2, $00C3, $00C4, $00C5,
+                    $00C6, $00C7, $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF,
+                    $00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7, $00D8, $00D9,
+                    $00DA, $00DB, $00DC, $00DD, $00DE, $00DF, $00E0, $00E1, $00E2, $00E3,
+                    $00E4, $00E5, $00E6, $00E7, $00E8, $00E9, $00EA, $00EB, $00EC, $00ED,
+                    $00EE, $00EF, $00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7,
+                    $00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF);
+
+(* UTF-8  (somewhat simplified)
+   -----
+   Character Range    Byte sequence
+   ---------------    --------------------------     (x=Bits from original character)
+   $0000..$007F       0xxxxxxx
+   $0080..$07FF       110xxxxx 10xxxxxx
+   $8000..$FFFF       1110xxxx 10xxxxxx 10xxxxxx
+
+   Example
+   --------
+   Transforming the Unicode character U+00E4 LATIN SMALL LETTER A WITH DIAERESIS  ("�"):
+
+         ISO-8859-1,           Decimal  228
+         Win1252,              Hex      $E4
+         ANSI                  Bin      1110 0100
+                                        abcd efgh
+
+         UTF-8                 Binary   1100xxab 10cdefgh
+                               Binary   11000011 10100100
+                               Hex      $C3      $A4
+                               Decimal  195      164
+                               ANSI     �        �         *)
+
+
+FUNCTION  AnsiToUtf8 (Source : ANSISTRING) : STRING;
+          (* Converts the given Windows ANSI (Win1252) String to UTF-8. *)
+VAR
+  I   : INTEGER;  // Loop counter
+  U   : WORD;     // Current Unicode value
+  Len : INTEGER;  // Current real length of "Result" string
+BEGIN
+  SetLength (Result, Length (Source) * 3);   // Worst case
+  Len := 0;
+  FOR I := 1 TO Length (Source) DO BEGIN
+    U := WIN1252_UNICODE [ORD (Source [I])];
+    CASE U OF
+      $0000..$007F : BEGIN
+                       INC (Len);
+                       Result [Len] := CHR (U);
+                     END;
+      $0080..$07FF : BEGIN
+                       INC (Len);
+                       Result [Len] := CHR ($C0 OR (U SHR 6));
+                       INC (Len);
+                       Result [Len] := CHR ($80 OR (U AND $3F));
+                     END;
+      $0800..$FFFF : BEGIN
+                       INC (Len);
+                       Result [Len] := CHR ($E0 OR (U SHR 12));
+                       INC (Len);
+                       Result [Len] := CHR ($80 OR ((U SHR 6) AND $3F));
+                       INC (Len);
+                       Result [Len] := CHR ($80 OR (U AND $3F));
+                     END;
+      END;
+    END;
+  SetLength (Result, Len);
+END;
+
+
+FUNCTION  Utf8ToAnsi (Source : STRING; UnknownChar : CHAR = '�') : ANSISTRING;
+          (* Converts the given UTF-8 String to Windows ANSI (Win-1252).
+             If a character can not be converted, the "UnknownChar" is inserted. *)
+VAR
+  SourceLen : INTEGER;  // Length of Source string
+  I, K      : INTEGER;
+  A         : BYTE;     // Current ANSI character value
+  U         : WORD;
+  Ch        : CHAR;     // Dest char
+  Len       : INTEGER;  // Current real length of "Result" string
+BEGIN
+  SourceLen := Length (Source);
+  SetLength (Result, SourceLen);   // Enough room to live
+  Len := 0;
+  I   := 1;
+  WHILE I <= SourceLen DO BEGIN
+    A := ORD (Source [I]);
+    IF A < $80 THEN BEGIN                                               // Range $0000..$007F
+      INC (Len);
+      Result [Len] := Source [I];
+      INC (I);
+      END
+    ELSE BEGIN                                                          // Determine U, Inc I
+      IF (A AND $E0 = $C0) AND (I < SourceLen) THEN BEGIN               // Range $0080..$07FF
+        U := (WORD (A AND $1F) SHL 6) OR (ORD (Source [I+1]) AND $3F);
+        INC (I, 2);
+        END
+      ELSE IF (A AND $F0 = $E0) AND (I < SourceLen-1) THEN BEGIN        // Range $0800..$FFFF
+        U := (WORD (A AND $0F) SHL 12) OR
+             (WORD (ORD (Source [I+1]) AND $3F) SHL 6) OR
+             (      ORD (Source [I+2]) AND $3F);
+        INC (I, 3);
+        END
+      ELSE BEGIN                                                        // Unknown/unsupported
+        INC (I);
+        FOR K := 7 DOWNTO 0 DO
+          IF A AND (1 SHL K) = 0 THEN BEGIN
+            INC (I, (A SHR (K+1))-1);
+            BREAK;
+            END;
+        U := WIN1252_UNICODE [ORD (UnknownChar)];
+        END;
+      Ch := UnknownChar;                                                // Retrieve ANSI char
+      FOR A := $00 TO $FF DO
+        IF WIN1252_UNICODE [A] = U THEN BEGIN
+          Ch := CHR (A);
+          BREAK;
+          END;
+      INC (Len);
+      Result [Len] := Ch;
+      END;
+    END;
+  SetLength (Result, Len);
+END;
+
+
+(*
+===============================================================================================
+"Special" Helper Functions
+
+Don't ask me why. But including these functions makes the parser *DRAMATICALLY* faster
+on my K6-233 machine. You can test it yourself just by commenting them out.
+They do exactly the same as the Assembler routines defined in SysUtils.
+(This is where you can see how great the Delphi compiler really is. The compiled code is
+faster than hand-coded assembler!)
+===============================================================================================
+--> Just move this line below the StrScan function -->  *)
+
+
+FUNCTION StrPos (CONST Str, SearchStr : PChar) : PChar;
+         // Same functionality as SysUtils.StrPos
+VAR
+  First : CHAR;
+  Len   : INTEGER;
+BEGIN
+  First  := SearchStr^;
+  Len    := StrLen (SearchStr);
+  Result := Str;
+  REPEAT
+    IF Result^ = First THEN
+      IF StrLComp (Result, SearchStr, Len) = 0 THEN BREAK;
+    IF Result^ = #0 THEN BEGIN
+      Result := NIL;
+      BREAK;
+      END;
+    INC (Result);
+  UNTIL FALSE;
+END;
+
+
+FUNCTION StrScan (CONST Start : PChar; CONST Ch : CHAR) : PChar;
+         // Same functionality as SysUtils.StrScan
+BEGIN
+  Result := Start;
+  WHILE Result^ <> Ch DO BEGIN
+    IF Result^ = #0 THEN BEGIN
+      Result := NIL;
+      EXIT;
+      END;
+    INC (Result);
+    END;
+END;
+
+
+(*
+===============================================================================================
+Helper Functions
+===============================================================================================
+*)
+
+FUNCTION  DelChars (Source : STRING; CharsToDelete : TCharset) : STRING;
+          // Delete all "CharsToDelete" from the string
+VAR
+  I : INTEGER;
+BEGIN
+  Result := Source;
+  FOR I := Length (Result) DOWNTO 1 DO
+    IF Result [I] IN CharsToDelete THEN
+      Delete (Result, I, 1);
+END;
+
+
+FUNCTION  TrimWs (Source : STRING) : STRING;
+          // Trimms off Whitespace characters from both ends of the string
+VAR
+  I : INTEGER;
+BEGIN
+  // --- Trim Left
+  I := 1;
+  WHILE (I <= Length (Source)) AND (Source [I] IN CWhitespace) DO
+    INC (I);
+  Result := Copy (Source, I, MaxInt);
+
+  // --- Trim Right
+  I := Length (Result);
+  WHILE (I > 1) AND (Result [I] IN CWhitespace) DO
+    DEC (I);
+  Delete (Result, I+1, Length (Result)-I);
+END;
+
+
+FUNCTION  ConvertWs (Source: STRING; PackWs: BOOLEAN) : STRING;
+          // Converts all Whitespace characters to the Space #x20 character
+          // If "PackWs" is true, contiguous Whitespace characters are packed to one
+VAR
+  I : INTEGER;
+BEGIN
+  Result := Source;
+  FOR I := Length (Result) DOWNTO 1 DO
+    IF (Result [I] IN CWhitespace) THEN
+      IF PackWs AND (I > 1) AND (Result [I-1] IN CWhitespace)
+        THEN Delete (Result, I, 1)
+        ELSE Result [I] := #32;
+END;
+
+
+PROCEDURE SetStringSF (VAR S : STRING; BufferStart, BufferFinal : PChar);
+BEGIN
+  SetString (S, BufferStart, BufferFinal-BufferStart+1);
+END;
+
+
+FUNCTION  StrLPas  (Start : PChar; Len : INTEGER) : STRING;
+BEGIN
+  SetString (Result, Start, Len);
+END;
+
+
+FUNCTION  StrSFPas (Start, Finish : PChar) : STRING;
+BEGIN
+  SetString (Result, Start, Finish-Start+1);
+END;
+
+
+FUNCTION  StrScanE (CONST Source : PChar; CONST CharToScanFor : CHAR) : PChar;
+          // If "CharToScanFor" is not found, StrScanE returns the last char of the
+          // buffer instead of NIL
+BEGIN
+  Result := StrScan (Source, CharToScanFor);
+  IF Result = NIL THEN
+    Result := StrEnd (Source)-1;
+END;
+
+
+PROCEDURE ExtractName (Start : PChar; Terminators : TCharset; VAR Final : PChar);
+          (* Extracts the complete Name beginning at "Start".
+             It is assumed that the name is contained in Markup, so the '>' character is
+             always a Termination.
+             Start:       IN  Pointer to first char of name. Is always considered to be valid
+             Terminators: IN  Characters which terminate the name
+             Final:       OUT Pointer to last char of name *)
+BEGIN
+  Final := Start+1;
+  Include (Terminators, #0);
+  Include (Terminators, '>');
+  WHILE NOT (Final^ IN Terminators) DO
+    INC (Final);
+  DEC (Final);
+END;
+
+
+PROCEDURE ExtractQuote (Start : PChar; VAR Content : STRING; VAR Final : PChar);
+          (* Extract a string which is contained in single or double Quotes.
+             Start:    IN   Pointer to opening quote
+             Content:  OUT  The quoted string
+             Final:    OUT  Pointer to closing quote *)
+BEGIN
+  Final := StrScan (Start+1, Start^);
+  IF Final = NIL THEN BEGIN
+    Final := StrEnd (Start+1)-1;
+    SetString (Content, Start+1, Final-Start);
+    END
+  ELSE
+    SetString (Content, Start+1, Final-1-Start);
+END;
+
+
+(*
+===============================================================================================
+TEntityStackNode
+This Node is pushed to the "Entity Stack" whenever the parser parses entity replacement text.
+The "Instance" field holds the Instance pointer of an External Entity buffer. When it is
+popped, the Instance is freed.
+The "Encoding" field holds the name of the Encoding. External Parsed Entities may have
+another encoding as the document entity (XmlSpec 4.3.3). So when there is an "<?xml" PI
+found in the stream (= Text Declaration at the beginning of external parsed entities), the
+Encoding found there is used for the External Entity (is assigned to TXmlParser.CurEncoding)
+Default Encoding is for the Document Entity is UTF-8. It is assumed that External Entities
+have the same Encoding as the Document Entity, unless they carry a Text Declaration.
+===============================================================================================
+*)
+
+TYPE
+  TEntityStackNode = CLASS
+                       Instance : TObject;
+                       Encoding : STRING;
+                       LastPos  : PChar;
+                     END;
+
+(*
+===============================================================================================
+TEntityStack
+For nesting of Entities.
+When there is an entity reference found in the data stream, the corresponding entity
+definition is searched and the current position is pushed to this stack.
+From then on, the program scans the entitiy replacement text as if it were normal content.
+When the parser reaches the end of an entity, the current position is popped off the
+stack again.
+===============================================================================================
+*)
+
+CONSTRUCTOR TEntityStack.Create (TheOwner : TXmlParser);
+BEGIN
+  INHERITED Create;
+  Owner := TheOwner;
+END;
+
+
+PROCEDURE TEntityStack.Push (LastPos : PChar);
+BEGIN
+  Push (NIL, LastPos);
+END;
+
+
+PROCEDURE TEntityStack.Push (Instance : TObject; LastPos : PChar);
+VAR
+  ESN : TEntityStackNode;
+BEGIN
+  ESN := TEntityStackNode.Create;
+  ESN.Instance := Instance;
+  ESN.Encoding := Owner.FCurEncoding;  // Save current Encoding
+  ESN.LastPos  := LastPos;
+  Add (ESN);
+END;
+
+
+FUNCTION  TEntityStack.Pop : PChar;
+VAR
+  ESN : TEntityStackNode;
+BEGIN
+  IF Count > 0 THEN BEGIN
+    ESN := TEntityStackNode (Items [Count-1]);
+    Result := ESN.LastPos;
+    IF ESN.Instance <> NIL THEN
+      ESN.Instance.Free;
+    IF ESN.Encoding <> '' THEN
+      Owner.FCurEncoding := ESN.Encoding;   // Restore current Encoding
+    Delete (Count-1);
+    END
+  ELSE
+    Result := NIL;
+END;
+
+
+(*
+===============================================================================================
+TExternalID
+-----------
+XmlSpec 4.2.2:  ExternalID ::= 'SYSTEM' S SystemLiteral |
+                               'PUBLIC' S PubidLiteral S SystemLiteral
+XmlSpec 4.7:    PublicID   ::= 'PUBLIC' S PubidLiteral
+SystemLiteral and PubidLiteral are quoted
+===============================================================================================
+*)
+
+TYPE
+  TExternalID = CLASS
+                  PublicId : STRING;
+                  SystemId : STRING;
+                  Final    : PChar;
+                  CONSTRUCTOR Create (Start : PChar);
+                END;
+
+CONSTRUCTOR TExternalID.Create (Start : PChar);
+BEGIN
+  INHERITED Create;
+  Final := Start;
+  IF StrLComp (Start, 'SYSTEM', 6) = 0 THEN BEGIN
+    WHILE NOT (Final^ IN (CQuoteChar + [#0, '>', '['])) DO INC (Final);
+    IF NOT (Final^ IN CQuoteChar) THEN EXIT;
+    ExtractQuote (Final, SystemID, Final);
+    END
+  ELSE IF StrLComp (Start, 'PUBLIC', 6) = 0 THEN BEGIN
+    WHILE NOT (Final^ IN (CQuoteChar + [#0, '>', '['])) DO INC (Final);
+    IF NOT (Final^ IN CQuoteChar) THEN EXIT;
+    ExtractQuote (Final, PublicID, Final);
+    INC (Final);
+    WHILE NOT (Final^ IN (CQuoteChar + [#0, '>', '['])) DO INC (Final);
+    IF NOT (Final^ IN CQuoteChar) THEN EXIT;
+    ExtractQuote (Final, SystemID, Final);
+    END;
+END;
+
+
+(*
+===============================================================================================
+TXmlParser
+===============================================================================================
+*)
+
+CONSTRUCTOR TXmlParser.Create;
+BEGIN
+  INHERITED Create;
+  FBuffer     := NIL;
+  FBufferSize := 0;
+  Elements    := TElemList.Create;
+  Entities    := TNvpList.Create;
+  ParEntities := TNvpList.Create;
+  Notations   := TNvpList.Create;
+  CurAttr     := TAttrList.Create;
+  EntityStack := TEntityStack.Create (Self);
+  Clear;
+END;
+
+
+DESTRUCTOR TXmlParser.Destroy;
+BEGIN
+  Clear;
+  Elements.Free;
+  Entities.Free;
+  ParEntities.Free;
+  Notations.Free;
+  CurAttr.Free;
+  EntityStack.Free;
+  INHERITED Destroy;
+END;
+
+
+PROCEDURE TXmlParser.Clear;
+          // Free Buffer and clear all object attributes
+BEGIN
+  IF (FBufferSize > 0) AND (FBuffer <> NIL) THEN
+    FreeMem (FBuffer);
+  FBuffer     := NIL;
+  FBufferSize := 0;
+  FSource     := '';
+  FXmlVersion := '';
+  FEncoding   := '';
+  FStandalone := FALSE;
+  FRootName   := '';
+  FDtdcFinal  := NIL;
+  FNormalize  := TRUE;
+  Elements.Clear;
+  Entities.Clear;
+  ParEntities.Clear;
+  Notations.Clear;
+  CurAttr.Clear;
+  EntityStack.Clear;
+END;
+
+
+FUNCTION  TXmlParser.LoadFromFile (Filename : STRING; FileMode : INTEGER = fmOpenRead OR fmShareDenyNone) : BOOLEAN;
+          // Loads Document from given file
+          // Returns TRUE if successful
+VAR
+  f           : FILE;
+  ReadIn      : INTEGER;
+  OldFileMode : INTEGER;
+BEGIN
+  Result := FALSE;
+  Clear;
+
+  // --- Open File
+  OldFileMode := SYSTEM.FileMode;
+  TRY
+    SYSTEM.FileMode := FileMode;
+    TRY
+      AssignFile (f, Filename);
+      Reset (f, 1);
+    EXCEPT
+      EXIT;
+      END;
+
+    TRY
+      // --- Allocate Memory
+      TRY
+        FBufferSize := Filesize (f) + 1;
+        GetMem (FBuffer, FBufferSize);
+      EXCEPT
+        Clear;
+        EXIT;
+        END;
+
+      // --- Read File
+      TRY
+        BlockRead (f, FBuffer^, FBufferSize, ReadIn);
+        (FBuffer+ReadIn)^ := #0;  // NULL termination
+      EXCEPT
+        Clear;
+        EXIT;
+        END;
+    FINALLY
+      CloseFile (f);
+      END;
+
+    FSource := Filename;
+    Result  := TRUE;
+
+  FINALLY
+    SYSTEM.FileMode := OldFileMode;
+    END;
+END;
+
+
+FUNCTION  TXmlParser.LoadFromBuffer (Buffer : PChar) : BOOLEAN;
+          // Loads Document from another buffer
+          // Returns TRUE if successful
+          // The "Source" property becomes '<MEM>' if successful
+BEGIN
+  Result := FALSE;
+  Clear;
+  FBufferSize := StrLen (Buffer) + 1;
+  TRY
+    GetMem (FBuffer, FBufferSize);
+  EXCEPT
+    Clear;
+    EXIT;
+    END;
+  StrCopy (FBuffer, Buffer);
+  FSource := '<MEM>';
+  Result := TRUE;
+END;
+
+
+PROCEDURE TXmlParser.SetBuffer (Buffer : PChar);      // References another buffer
+BEGIN
+  Clear;
+  FBuffer     := Buffer;
+  FBufferSize := 0;
+  FSource := '<REFERENCE>';
+END;
+
+
+//-----------------------------------------------------------------------------------------------
+// Scanning through the document
+//-----------------------------------------------------------------------------------------------
+
+PROCEDURE TXmlParser.StartScan;
+BEGIN
+  CurPartType := ptNone;
+  CurName     := '';
+  CurContent  := '';
+  CurStart    := NIL;
+  CurFinal    := NIL;
+  CurAttr.Clear;
+  EntityStack.Clear;
+END;
+
+
+FUNCTION  TXmlParser.Scan : BOOLEAN;
+          // Scans the next Part
+          // Returns TRUE if a part could be found, FALSE if there is no part any more
+          //
+          // "IsDone" can be set to FALSE by AnalyzeText in order to go to the next part
+          // if there is no Content due to normalization
+VAR
+  IsDone : BOOLEAN;
+BEGIN
+  REPEAT
+    IsDone := TRUE;
+
+    // --- Start of next Part
+    IF CurStart = NIL
+      THEN CurStart := DocBuffer
+      ELSE CurStart := CurFinal+1;
+    CurFinal := CurStart;
+
+    // --- End of Document of Pop off a new part from the Entity stack?
+    IF CurStart^ = #0 THEN
+      CurStart := EntityStack.Pop;
+
+    // --- No Document or End Of Document: Terminate Scan
+    IF (CurStart = NIL) OR (CurStart^ = #0) THEN BEGIN
+      CurStart := StrEnd (DocBuffer);
+      CurFinal := CurStart-1;
+      EntityStack.Clear;
+      Result   := FALSE;
+      EXIT;
+      END;
+
+    IF (StrLComp (CurStart, '<?xml', 5) = 0) AND
+       ((CurStart+5)^ IN CWhitespace) THEN AnalyzeProlog                                      // XML Declaration, Text Declaration
+    ELSE IF StrLComp (CurStart, '<?',        2) = 0 THEN AnalyzePI (CurStart, CurFinal)       // PI
+    ELSE IF StrLComp (CurStart, '<!--',      4) = 0 THEN AnalyzeComment (CurStart, CurFinal)  // Comment
+    ELSE IF StrLComp (CurStart, '<!DOCTYPE', 9) = 0 THEN AnalyzeDtdc                          // DTDc
+    ELSE IF StrLComp (CurStart, CDStart, Length (CDStart)) = 0 THEN AnalyzeCdata              // CDATA Section
+    ELSE IF StrLComp (CurStart, '<',         1) = 0 THEN AnalyzeTag                           // Start-Tag, End-Tag, Empty-Element-Tag
+    ELSE AnalyzeText (IsDone);                                                                // Text Content
+  UNTIL IsDone;
+  Result := TRUE;
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeProlog;
+          // Analyze XML Prolog or Text Declaration
+VAR
+  F : PChar;
+BEGIN
+  CurAttr.Analyze (CurStart+5, F);
+  IF EntityStack.Count = 0 THEN BEGIN
+    FXmlVersion := CurAttr.Value ('version');
+    FEncoding   := CurAttr.Value ('encoding');
+    FStandalone := CurAttr.Value ('standalone') = 'yes';
+    END;
+  CurFinal := StrPos (F, '?>');
+  IF CurFinal <> NIL
+    THEN INC (CurFinal)
+    ELSE CurFinal := StrEnd (CurStart)-1;
+  FCurEncoding := AnsiUpperCase (CurAttr.Value ('encoding'));
+  IF FCurEncoding = '' THEN
+    FCurEncoding := 'UTF-8';   // Default XML Encoding is UTF-8
+  CurPartType  := ptXmlProlog;
+  CurName      := '';
+  CurContent   := '';
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeComment (Start : PChar; VAR Final : PChar);
+          // Analyze Comments
+BEGIN
+  Final := StrPos (Start+4, '-->');
+  IF Final = NIL
+    THEN Final := StrEnd (Start)-1
+    ELSE INC (Final, 2);
+  CurPartType := ptComment;
+END;
+
+
+PROCEDURE TXmlParser.AnalyzePI (Start : PChar; VAR Final : PChar);
+          // Analyze Processing Instructions (PI)
+          // This is also called for Character
+VAR
+  F : PChar;
+BEGIN
+  CurPartType := ptPI;
+  Final := StrPos (Start+2, '?>');
+  IF Final = NIL
+    THEN Final := StrEnd (Start)-1
+    ELSE INC (Final);
+  ExtractName (Start+2, CWhitespace + ['?', '>'], F);
+  SetStringSF (CurName, Start+2, F);
+  SetStringSF (CurContent, F+1, Final-2);
+  CurAttr.Analyze (F+1, F);
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeDtdc;
+          (* Analyze Document Type Declaration
+                 doctypedecl  ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
+                 markupdecl   ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment
+                 PEReference  ::= '%' Name ';'
+
+                 elementdecl  ::= '<!ELEMENT' S Name S contentspec S?                    '>'
+                 AttlistDecl  ::= '<!ATTLIST' S Name AttDef* S?                          '>'
+                 EntityDecl   ::= '<!ENTITY' S Name S EntityDef S?                       '>' |
+                                  '<!ENTITY' S '%' S Name S PEDef S?                     '>'
+                 NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S?      '>'
+                 PI           ::=  '<?' PITarget (S (Char* - (Char* '?>' Char* )))?     '?>'
+                 Comment      ::= '<!--' ((Char - '-') | ('-' (Char - '-')))*          '-->'  *)
+TYPE
+  TPhase = (phName, phDtd, phInternal, phFinishing);
+VAR
+  Phase       : TPhase;
+  F           : PChar;
+  ExternalID  : TExternalID;
+  ExternalDTD : TXmlParser;
+  DER         : TDtdElementRec;
+BEGIN
+  DER.Start := CurStart;
+  EntityStack.Clear;    // Clear stack for Parameter Entities
+  CurPartType := ptDtdc;
+
+  // --- Don't read DTDc twice
+  IF FDtdcFinal <> NIL THEN BEGIN
+    CurFinal := FDtdcFinal;
+    EXIT;
+    END;
+
+  // --- Scan DTDc
+  CurFinal := CurStart + 9;    // First char after '<!DOCTYPE'
+  Phase    := phName;
+  REPEAT
+    CASE CurFinal^ OF
+      '%' : BEGIN
+              PushPE (CurFinal);
+              CONTINUE;
+            END;
+      #0  : IF EntityStack.Count = 0 THEN
+              BREAK
+            ELSE BEGIN
+              CurFinal := EntityStack.Pop;
+              CONTINUE;
+              END;
+      '[' : BEGIN
+              Phase := phInternal;
+              AnalyzeDtdElements (CurFinal+1, CurFinal);
+              CONTINUE;
+            END;
+      ']' : Phase := phFinishing;
+      '>' : BREAK;
+      ELSE  IF NOT (CurFinal^ IN CWhitespace) THEN BEGIN
+              CASE Phase OF
+                phName : IF (CurFinal^ IN CNameStart)  THEN BEGIN
+                           ExtractName (CurFinal, CWhitespace + ['[', '>'], F);
+                           SetStringSF (FRootName, CurFinal, F);
+                           CurFinal := F;
+                           Phase := phDtd;
+                           END;
+                phDtd  : IF (StrLComp (CurFinal, 'SYSTEM', 6) = 0) OR
+                            (StrLComp (CurFinal, 'PUBLIC', 6) = 0) THEN BEGIN
+                           ExternalID  := TExternalID.Create (CurFinal);
+                           ExternalDTD := LoadExternalEntity (ExternalId.SystemId, ExternalID.PublicId, '');
+                           F := StrPos (ExternalDtd.DocBuffer, '<!');
+                           IF F <> NIL THEN
+                             AnalyzeDtdElements (F, F);
+                           ExternalDTD.Free;
+                           CurFinal := ExternalID.Final;
+                           ExternalID.Free;
+                           END;
+                ELSE     BEGIN
+                           DER.ElementType := deError;
+                           DER.Pos         := CurFinal;
+                           DER.Final       := CurFinal;
+                           DtdElementFound (DER);
+                         END;
+                END;
+
+              END;
+      END;
+    INC (CurFinal);
+  UNTIL FALSE;
+
+  CurPartType := ptDtdc;
+  CurName     := '';
+  CurContent  := '';
+
+  // It is an error in the document if "EntityStack" is not empty now
+  IF EntityStack.Count > 0 THEN BEGIN
+    DER.ElementType := deError;
+    DER.Final       := CurFinal;
+    DER.Pos         := CurFinal;
+    DtdElementFound (DER);
+    END;
+
+  EntityStack.Clear;    // Clear stack for General Entities
+  FDtdcFinal := CurFinal;
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeDtdElements (Start : PChar; VAR Final : PChar);
+          // Analyze the "Elements" of a DTD contained in the external or
+          // internal DTD subset.
+VAR
+  DER : TDtdElementRec;
+BEGIN
+  Final := Start;
+  REPEAT
+    CASE Final^ OF
+      '%' : BEGIN
+              PushPE (Final);
+              CONTINUE;
+            END;
+      #0  : IF EntityStack.Count = 0 THEN
+              BREAK
+            ELSE BEGIN
+              CurFinal := EntityStack.Pop;
+              CONTINUE;
+              END;
+      ']',
+      '>' : BREAK;
+      '<' : IF      StrLComp (Final, '<!ELEMENT',   9) = 0 THEN AnalyzeElementDecl  (Final, Final)
+            ELSE IF StrLComp (Final, '<!ATTLIST',   9) = 0 THEN AnalyzeAttListDecl  (Final, Final)
+            ELSE IF StrLComp (Final, '<!ENTITY',    8) = 0 THEN AnalyzeEntityDecl   (Final, Final)
+            ELSE IF StrLComp (Final, '<!NOTATION', 10) = 0 THEN AnalyzeNotationDecl (Final, Final)
+            ELSE IF StrLComp (Final, '<?',          2) = 0 THEN BEGIN   // PI in DTD
+              DER.ElementType := dePI;
+              DER.Start       := Final;
+              AnalyzePI (Final, Final);
+              DER.Target      := PChar (CurName);
+              DER.Content     := PChar (CurContent);
+              DER.AttrList    := CurAttr;
+              DER.Final       := Final;
+              DtdElementFound (DER);
+              END
+            ELSE IF StrLComp (Final, '<!--', 4) = 0 THEN BEGIN   // Comment in DTD
+              DER.ElementType := deComment;
+              DER.Start       := Final;
+              AnalyzeComment  (Final, Final);
+              DER.Final       := Final;
+              DtdElementFound (DER);
+              END
+            ELSE BEGIN
+              DER.ElementType := deError;
+              DER.Start       := Final;
+              DER.Pos         := Final;
+              DER.Final       := Final;
+              DtdElementFound (DER);
+              END;
+
+      END;
+    INC (Final);
+  UNTIL FALSE;
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeTag;
+          // Analyze Tags
+VAR
+  S, F    : PChar;
+  Attr    : TAttr;
+  ElemDef : TElemDef;
+  AttrDef : TAttrDef;
+  I       : INTEGER;
+BEGIN
+  CurPartType := ptStartTag;
+  S := CurStart+1;
+  IF S^ = '/' THEN BEGIN
+    CurPartType := ptEndTag;
+    INC (S);
+    END;
+  ExtractName (S, CWhitespace + ['/'], F);
+  SetStringSF (CurName, S, F);
+  CurAttr.Analyze (F+1, CurFinal);
+  IF CurFinal^ = '/' THEN BEGIN
+    CurPartType := ptEmptyTag;
+    END;
+  CurFinal := StrScanE (CurFinal, '>');
+
+  // --- Set Default Attribute values for nonexistent attributes
+  IF (CurPartType = ptStartTag) OR (CurPartType = ptEmptyTag) THEN BEGIN
+    ElemDef := Elements.Node (CurName);
+    IF ElemDef <> NIL THEN BEGIN
+      FOR I := 0 TO ElemDef.Count-1 DO BEGIN
+        AttrDef := TAttrDef (ElemDef [I]);
+        Attr := TAttr (CurAttr.Node (AttrDef.Name));
+        IF (Attr = NIL) AND (AttrDef.Value <> '') THEN BEGIN
+          Attr           := TAttr.Create (AttrDef.Name, AttrDef.Value);
+          Attr.ValueType := vtDefault;
+          CurAttr.Add (Attr);
+          END;
+        IF Attr <> NIL THEN BEGIN
+          CASE AttrDef.DefaultType OF
+            adDefault  : ;
+            adRequired : ; // -!- It is an error in the document if "Attr.Value" is an empty string
+            adImplied  : Attr.ValueType := vtImplied;
+            adFixed    : BEGIN
+                           Attr.ValueType := vtFixed;
+                           Attr.Value     := AttrDef.Value;
+                         END;
+            END;
+          Attr.AttrType := AttrDef.AttrType;
+          END;
+        END;
+      END;
+
+    // --- Normalize Attribute Values. XmlSpec:
+           // - a character reference is processed by appending the referenced character to the attribute value
+           // - an entity reference is processed by recursively processing the replacement text of the entity
+           // - a whitespace character (#x20, #xD, #xA, #x9) is processed by appending #x20 to the normalized value,
+           //   except that only a single #x20 is appended for a "#xD#xA" sequence that is part of an external
+           //   parsed entity or the literal entity value of an internal parsed entity
+           // - other characters are processed by appending them to the normalized value
+           // If the declared value is not CDATA, then the XML processor must further process the
+           // normalized attribute value by discarding any leading and trailing space (#x20) characters,
+           // and by replacing sequences of space (#x20) characters by a single space (#x20) character.
+           // All attributes for which no declaration has been read should be treated by a
+           // non-validating parser as if declared CDATA.
+           // !!! The XML 1.0 SE specification is somewhat different here
+           //     This code does not conform exactly to this specification
+    FOR I := 0 TO CurAttr.Count-1 DO
+      WITH TAttr (CurAttr [I]) DO BEGIN
+        ReplaceGeneralEntities   (Value);
+        ReplaceCharacterEntities (Value);
+        IF (AttrType <> atCData) AND (AttrType <> atUnknown)
+          THEN Value := TranslateEncoding (TrimWs (ConvertWs (Value, TRUE)))
+          ELSE Value := TranslateEncoding (ConvertWs (Value, FALSE));
+        END;
+    END;
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeCData;
+          // Analyze CDATA Sections
+BEGIN
+  CurPartType := ptCData;
+  CurFinal := StrPos (CurStart, CDEnd);
+  IF CurFinal = NIL THEN BEGIN
+    CurFinal   := StrEnd (CurStart)-1;
+    CurContent := TranslateEncoding (StrPas (CurStart+Length (CDStart)));
+    END
+  ELSE BEGIN
+    SetStringSF (CurContent, CurStart+Length (CDStart), CurFinal-1);
+    INC (CurFinal, Length (CDEnd)-1);
+    CurContent := TranslateEncoding (CurContent);
+    END;
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeText (VAR IsDone : BOOLEAN);
+          (* Analyzes Text Content between Tags. CurFinal will point to the last content character.
+             Content ends at a '<' character or at the end of the document.
+             Entity References and Character Entity references are resolved.
+             If PackSpaces is TRUE, contiguous Whitespace Characters will be compressed to
+             one Space #x20 character, Whitespace at the beginning and end of content will
+             be trimmed off and content which is or becomes empty is not returned to
+             the application (in this case, "IsDone" is set to FALSE which causes the
+             Scan method to proceed directly to the next part. *)
+
+  PROCEDURE ProcessEntity;
+            (* Is called if there is an ampsersand '&' character found in the document.
+               IN  "CurFinal" points to the ampersand
+               OUT "CurFinal" points to the first character after the semi-colon ';' *)
+  VAR
+    P              : PChar;
+    Name           : STRING;
+    EntityDef      : TEntityDef;
+    ExternalEntity : TXmlParser;
+  BEGIN
+    P := StrScan (CurFinal , ';');
+    IF P <> NIL THEN BEGIN
+      SetStringSF (Name, CurFinal+1, P-1);
+
+      // Is it a Character Entity?
+      IF (CurFinal+1)^ = '#' THEN BEGIN
+        IF UpCase ((CurFinal+2)^) = 'X'       // !!! Can't use "CHR" for Unicode characters > 255:
+          THEN CurContent := CurContent + CHR (StrToIntDef ('$'+Copy (Name, 3, MaxInt), 32))
+          ELSE CurContent := CurContent + CHR (StrToIntDef (Copy (Name, 2, MaxInt), 32));
+        CurFinal := P+1;
+        EXIT;
+        END
+
+      // Is it a Predefined Entity?
+      ELSE IF Name = 'lt'   THEN BEGIN CurContent := CurContent + '<';  CurFinal := P+1; EXIT; END
+      ELSE IF Name = 'gt'   THEN BEGIN CurContent := CurContent + '>';  CurFinal := P+1; EXIT; END
+      ELSE IF Name = 'amp'  THEN BEGIN CurContent := CurContent + '&';  CurFinal := P+1; EXIT; END
+      ELSE IF Name = 'apos' THEN BEGIN CurContent := CurContent + ''''; CurFinal := P+1; EXIT; END
+      ELSE IF Name = 'quot' THEN BEGIN CurContent := CurContent + '"';  CurFinal := P+1; EXIT; END;
+
+      // Replace with Entity from DTD
+      EntityDef := TEntityDef (Entities.Node (Name));
+      IF EntityDef <> NIL THEN BEGIN
+        IF EntityDef.Value <> '' THEN BEGIN
+          EntityStack.Push (P+1);
+          CurFinal := PChar (EntityDef.Value);
+          END
+        ELSE BEGIN
+          ExternalEntity := LoadExternalEntity (EntityDef.SystemId, EntityDef.PublicId, EntityDef.NotationName);
+          EntityStack.Push (ExternalEntity, P+1);
+          CurFinal := ExternalEntity.DocBuffer;
+          END;
+        END
+      ELSE BEGIN
+        CurContent := CurContent + Name;
+        CurFinal   := P+1;
+        END;
+      END
+    ELSE BEGIN
+      INC (CurFinal);
+      END;
+  END;
+
+VAR
+  C  : INTEGER;
+BEGIN
+  CurFinal    := CurStart;
+  CurPartType := ptContent;
+  CurContent  := '';
+  C           := 0;
+  REPEAT
+    CASE CurFinal^ OF
+      '&' : BEGIN
+              CurContent := CurContent + TranslateEncoding (StrLPas (CurFinal-C, C));
+              C := 0;
+              ProcessEntity;
+              CONTINUE;
+            END;
+      #0  : BEGIN
+              IF EntityStack.Count = 0 THEN
+                BREAK
+              ELSE BEGIN
+                CurContent := CurContent + TranslateEncoding (StrLPas (CurFinal-C, C));
+                C := 0;
+                CurFinal := EntityStack.Pop;
+                CONTINUE;
+                END;
+            END;
+      '<' : BREAK;
+      ELSE INC (C);
+      END;
+    INC (CurFinal);
+  UNTIL FALSE;
+  CurContent := CurContent + TranslateEncoding (StrLPas (CurFinal-C, C));
+  DEC (CurFinal);
+
+  IF FNormalize THEN BEGIN
+    CurContent := ConvertWs (TrimWs (CurContent), TRUE);
+    IsDone     := CurContent <> '';    // IsDone will only get FALSE if PackSpaces is TRUE
+    END;
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeElementDecl  (Start : PChar; VAR Final : PChar);
+          (* Parse <!ELEMENT declaration starting at "Start"
+             Final must point to the terminating '>' character
+             XmlSpec 3.2:
+                 elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
+                 contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
+                 Mixed       ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'   |
+                                 '(' S? '#PCDATA' S? ')'
+                 children    ::= (choice | seq) ('?' | '*' | '+')?
+                 choice      ::= '(' S? cp ( S? '|' S? cp )* S? ')'
+                 cp          ::= (Name | choice | seq) ('?' | '*' | '+')?
+                 seq         ::= '(' S? cp ( S? ',' S? cp )* S? ')'
+
+             More simply:
+                 contentspec ::= EMPTY
+                                 ANY
+                                 '(#PCDATA)'
+                                 '(#PCDATA | A | B)*'
+                                 '(A, B, C)'
+                                 '(A | B | C)'
+                                 '(A?, B*, C+),
+                                 '(A, (B | C | D)* )'                       *)
+VAR
+  Element : TElemDef;
+  Elem2   : TElemDef;
+  F       : PChar;
+  DER     : TDtdElementRec;
+BEGIN
+  Element   := TElemDef.Create;
+  Final     := Start + 9;
+  DER.Start := Start;
+  REPEAT
+    IF Final^ = '>' THEN BREAK;
+    IF (Final^ IN CNameStart) AND (Element.Name = '') THEN BEGIN
+      ExtractName (Final, CWhitespace, F);
+      SetStringSF (Element.Name, Final, F);
+      Final := F;
+      F := StrScan (Final+1, '>');
+      IF F = NIL THEN BEGIN
+        Element.Definition := STRING (Final);
+        Final := StrEnd (Final);
+        BREAK;
+        END
+      ELSE BEGIN
+        SetStringSF (Element.Definition, Final+1, F-1);
+        Final := F;
+        BREAK;
+        END;
+      END;
+    INC (Final);
+  UNTIL FALSE;
+  Element.Definition := DelChars (Element.Definition, CWhitespace);
+  ReplaceParameterEntities (Element.Definition);
+  IF      Element.Definition = 'EMPTY' THEN Element.ElemType := etEmpty
+  ELSE IF Element.Definition = 'ANY'   THEN Element.ElemType := etAny
+  ELSE IF Copy (Element.Definition, 1, 8) = '(#PCDATA' THEN Element.ElemType := etMixed
+  ELSE IF Copy (Element.Definition, 1, 1) = '('        THEN Element.ElemType := etChildren
+  ELSE Element.ElemType := etAny;
+
+  Elem2 := Elements.Node (Element.Name);
+  IF Elem2 <> NIL THEN
+    Elements.Delete (Elements.IndexOf (Elem2));
+  Elements.Add (Element);
+  Final := StrScanE (Final, '>');
+  DER.ElementType := deElement;
+  DER.ElemDef  := Element;
+  DER.Final    := Final;
+  DtdElementFound (DER);
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeAttListDecl  (Start : PChar; VAR Final : PChar);
+          (* Parse <!ATTLIST declaration starting at "Start"
+             Final must point to the terminating '>' character
+             XmlSpec 3.3:
+                 AttlistDecl    ::= '<!ATTLIST' S Name AttDef* S? '>'
+                 AttDef         ::= S Name S AttType S DefaultDecl
+                 AttType        ::= StringType | TokenizedType | EnumeratedType
+                 StringType     ::= 'CDATA'
+                 TokenizedType  ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
+                 EnumeratedType ::= NotationType | Enumeration
+                 NotationType   ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
+                 Enumeration    ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
+                 DefaultDecl    ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
+                 AttValue       ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
+            Examples:
+                 <!ATTLIST address
+                           A1 CDATA "Default"
+                           A2 ID    #REQUIRED
+                           A3 IDREF #IMPLIED
+                           A4 IDREFS #IMPLIED
+                           A5 ENTITY #FIXED "&at;&#252;"
+                           A6 ENTITIES #REQUIRED
+                           A7 NOTATION (WMF | DXF) "WMF"
+                           A8 (A | B | C) #REQUIRED>                *)
+TYPE
+  TPhase = (phElementName, phName, phType, phNotationContent, phDefault);
+VAR
+  Phase       : TPhase;
+  F           : PChar;
+  ElementName : STRING;
+  ElemDef     : TElemDef;
+  AttrDef     : TAttrDef;
+  AttrDef2    : TAttrDef;
+  Strg        : STRING;
+  DER         : TDtdElementRec;
+BEGIN
+  Final     := Start + 9;   // The character after <!ATTLIST
+  Phase     := phElementName;
+  DER.Start := Start;
+  AttrDef   := NIL;
+  ElemDef   := NIL;
+  REPEAT
+    IF NOT (Final^ IN CWhitespace) THEN
+      CASE Final^ OF
+        '%' : BEGIN
+                PushPE (Final);
+                CONTINUE;
+              END;
+        #0  : IF EntityStack.Count = 0 THEN
+                BREAK
+              ELSE BEGIN
+                Final := EntityStack.Pop;
+                CONTINUE;
+                END;
+        '>' : BREAK;
+        ELSE  CASE Phase OF
+                phElementName     : BEGIN
+                                      ExtractName (Final, CWhitespace + CQuoteChar + ['#'], F);
+                                      SetStringSF (ElementName, Final, F);
+                                      Final := F;
+                                      ElemDef := Elements.Node (ElementName);
+                                      IF ElemDef = NIL THEN BEGIN
+                                        ElemDef := TElemDef.Create;
+                                        ElemDef.Name       := ElementName;
+                                        ElemDef.Definition := 'ANY';
+                                        ElemDef.ElemType   := etAny;
+                                        Elements.Add (ElemDef);
+                                        END;
+                                      Phase := phName;
+                                    END;
+                phName            : BEGIN
+                                      AttrDef := TAttrDef.Create;
+                                      ExtractName (Final, CWhitespace + CQuoteChar + ['#'], F);
+                                      SetStringSF (AttrDef.Name, Final, F);
+                                      Final := F;
+                                      AttrDef2 := TAttrDef (ElemDef.Node (AttrDef.Name));
+                                      IF AttrDef2 <> NIL THEN
+                                        ElemDef.Delete (ElemDef.IndexOf (AttrDef2));
+                                      ElemDef.Add (AttrDef);
+                                      Phase := phType;
+                                    END;
+                phType            : BEGIN
+                                      IF Final^ = '(' THEN BEGIN
+                                        F := StrScan (Final+1, ')');
+                                        IF F <> NIL
+                                          THEN SetStringSF (AttrDef.TypeDef, Final+1, F-1)
+                                          ELSE AttrDef.TypeDef := STRING (Final+1);
+                                        AttrDef.TypeDef := DelChars (AttrDef.TypeDef, CWhitespace);
+                                        AttrDef.AttrType := atEnumeration;
+                                        ReplaceParameterEntities (AttrDef.TypeDef);
+                                        ReplaceCharacterEntities (AttrDef.TypeDef);
+                                        Phase := phDefault;
+                                        END
+                                      ELSE IF StrLComp (Final, 'NOTATION', 8) = 0 THEN BEGIN
+                                        INC (Final, 8);
+                                        AttrDef.AttrType := atNotation;
+                                        Phase := phNotationContent;
+                                        END
+                                      ELSE BEGIN
+                                        ExtractName (Final, CWhitespace+CQuoteChar+['#'], F);
+                                        SetStringSF (AttrDef.TypeDef, Final, F);
+                                        IF      AttrDef.TypeDef = 'CDATA'    THEN AttrDef.AttrType := atCData
+                                        ELSE IF AttrDef.TypeDef = 'ID'       THEN AttrDef.AttrType := atId
+                                        ELSE IF AttrDef.TypeDef = 'IDREF'    THEN AttrDef.AttrType := atIdRef
+                                        ELSE IF AttrDef.TypeDef = 'IDREFS'   THEN AttrDef.AttrType := atIdRefs
+                                        ELSE IF AttrDef.TypeDef = 'ENTITY'   THEN AttrDef.AttrType := atEntity
+                                        ELSE IF AttrDef.TypeDef = 'ENTITIES' THEN AttrDef.AttrType := atEntities
+                                        ELSE IF AttrDef.TypeDef = 'NMTOKEN'  THEN AttrDef.AttrType := atNmToken
+                                        ELSE IF AttrDef.TypeDef = 'NMTOKENS' THEN AttrDef.AttrType := atNmTokens;
+                                        Phase := phDefault;
+                                        END
+                                    END;
+                phNotationContent : BEGIN
+                                      F := StrScan (Final, ')');
+                                      IF F <> NIL THEN
+                                        SetStringSF (AttrDef.Notations, Final+1, F-1)
+                                      ELSE BEGIN
+                                        AttrDef.Notations := STRING (Final+1);
+                                        Final := StrEnd (Final);
+                                        END;
+                                      ReplaceParameterEntities (AttrDef.Notations);
+                                      AttrDef.Notations := DelChars (AttrDef.Notations, CWhitespace);
+                                      Phase := phDefault;
+                                    END;
+                phDefault :         BEGIN
+                                      IF Final^ = '#' THEN BEGIN
+                                        ExtractName (Final, CWhiteSpace + CQuoteChar, F);
+                                        SetStringSF (Strg, Final, F);
+                                        Final := F;
+                                        ReplaceParameterEntities (Strg);
+                                        IF      Strg = '#REQUIRED' THEN BEGIN AttrDef.DefaultType := adRequired; Phase := phName; END
+                                        ELSE IF Strg = '#IMPLIED'  THEN BEGIN AttrDef.DefaultType := adImplied;  Phase := phName; END
+                                        ELSE IF Strg = '#FIXED'    THEN       AttrDef.DefaultType := adFixed;
+                                        END
+                                      ELSE IF (Final^ IN CQuoteChar) THEN BEGIN
+                                        ExtractQuote (Final, AttrDef.Value, Final);
+                                        ReplaceParameterEntities (AttrDef.Value);
+                                        ReplaceCharacterEntities (AttrDef.Value);
+                                        Phase := phName;
+                                        END;
+                                      IF Phase = phName THEN BEGIN
+                                        AttrDef := NIL;
+                                        END;
+                                    END;
+
+                END;
+        END;
+    INC (Final);
+  UNTIL FALSE;
+
+  Final := StrScan (Final, '>');
+
+  DER.ElementType := deAttList;
+  DER.ElemDef  := ElemDef;
+  DER.Final    := Final;
+  DtdElementFound (DER);
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeEntityDecl   (Start : PChar; VAR Final : PChar);
+          (* Parse <!ENTITY declaration starting at "Start"
+             Final must point to the terminating '>' character
+             XmlSpec 4.2:
+                 EntityDecl  ::= '<!ENTITY' S Name S EntityDef S? '>'   |
+                                 '<!ENTITY' S '%' S Name S PEDef S? '>'
+                 EntityDef   ::= EntityValue | (ExternalID NDataDecl?)
+                 PEDef       ::= EntityValue | ExternalID
+                 NDataDecl   ::= S 'NDATA' S Name
+                 EntityValue ::= '"' ([^%&"] | PEReference | EntityRef | CharRef)* '"'   |
+                                 "'" ([^%&'] | PEReference | EntityRef | CharRef)* "'"
+                 PEReference ::= '%' Name ';'
+
+             Examples
+                 <!ENTITY test1 "Stefan Heymann">                   <!-- Internal, general, parsed              -->
+                 <!ENTITY test2 SYSTEM "ent2.xml">                  <!-- External, general, parsed              -->
+                 <!ENTITY test2 SYSTEM "ent3.gif" NDATA gif>        <!-- External, general, unparsed            -->
+                 <!ENTITY % test3 "<!ELEMENT q ANY>">               <!-- Internal, parameter                    -->
+                 <!ENTITY % test6 SYSTEM "ent6.xml">                <!-- External, parameter                    -->
+                 <!ENTITY test4 "&test1; ist lieb">                 <!-- IGP, Replacement text <> literal value -->
+                 <!ENTITY test5 "<p>Dies ist ein Test-Absatz</p>">  <!-- IGP, See XmlSpec 2.4                   -->
+          *)
+TYPE
+  TPhase = (phName, phContent, phNData, phNotationName, phFinalGT);
+VAR
+  Phase         : TPhase;
+  IsParamEntity : BOOLEAN;
+  F             : PChar;
+  ExternalID    : TExternalID;
+  EntityDef     : TEntityDef;
+  EntityDef2    : TEntityDef;
+  DER           : TDtdElementRec;
+BEGIN
+  Final         := Start + 8;   // First char after <!ENTITY
+  DER.Start     := Start;
+  Phase         := phName;
+  IsParamEntity := FALSE;
+  EntityDef     := TEntityDef.Create;
+  REPEAT
+    IF NOT (Final^ IN CWhitespace) THEN
+      CASE Final^ OF
+        '%' : IsParamEntity := TRUE;
+        '>' : BREAK;
+        ELSE  CASE Phase OF
+                phName         : IF Final^ IN CNameStart THEN BEGIN
+                                   ExtractName (Final, CWhitespace + CQuoteChar, F);
+                                   SetStringSF (EntityDef.Name, Final, F);
+                                   Final := F;
+                                   Phase := phContent;
+                                   END;
+                phContent      : IF Final^ IN CQuoteChar THEN BEGIN
+                                   ExtractQuote (Final, EntityDef.Value, Final);
+                                   Phase := phFinalGT;
+                                   END
+                                 ELSE IF (StrLComp (Final, 'SYSTEM', 6) = 0) OR
+                                         (StrLComp (Final, 'PUBLIC', 6) = 0) THEN BEGIN
+                                   ExternalID := TExternalID.Create (Final);
+                                   EntityDef.SystemId := ExternalID.SystemId;
+                                   EntityDef.PublicId := ExternalID.PublicId;
+                                   Final      := ExternalID.Final;
+                                   Phase      := phNData;
+                                   ExternalID.Free;
+                                   END;
+                phNData        : IF StrLComp (Final, 'NDATA', 5) = 0 THEN BEGIN
+                                   INC (Final, 4);
+                                   Phase := phNotationName;
+                                   END;
+                phNotationName : IF Final^ IN CNameStart THEN BEGIN
+                                   ExtractName (Final, CWhitespace + ['>'], F);
+                                   SetStringSF (EntityDef.NotationName, Final, F);
+                                   Final := F;
+                                   Phase := phFinalGT;
+                                   END;
+                phFinalGT      : ; // -!- There is an error in the document if this branch is called
+                END;
+        END;
+    INC (Final);
+  UNTIL FALSE;
+  IF IsParamEntity THEN BEGIN
+    EntityDef2 := TEntityDef (ParEntities.Node (EntityDef.Name));
+    IF EntityDef2 <> NIL THEN
+      ParEntities.Delete (ParEntities.IndexOf (EntityDef2));
+    ParEntities.Add (EntityDef);
+    ReplaceCharacterEntities (EntityDef.Value);
+    END
+  ELSE BEGIN
+    EntityDef2 := TEntityDef (Entities.Node (EntityDef.Name));
+    IF EntityDef2 <> NIL THEN
+      Entities.Delete (Entities.IndexOf (EntityDef2));
+    Entities.Add (EntityDef);
+    ReplaceParameterEntities (EntityDef.Value);  //  Create replacement texts (see XmlSpec 4.5)
+    ReplaceCharacterEntities (EntityDef.Value);
+    END;
+  Final := StrScanE (Final, '>');
+
+  DER.ElementType := deEntity;
+  DER.EntityDef   := EntityDef;
+  DER.Final       := Final;
+  DtdElementFound (DER);
+END;
+
+
+PROCEDURE TXmlParser.AnalyzeNotationDecl (Start : PChar; VAR Final : PChar);
+          // Parse <!NOTATION declaration starting at "Start"
+          // Final must point to the terminating '>' character
+          // XmlSpec 4.7: NotationDecl ::=  '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
+TYPE
+  TPhase = (phName, phExtId, phEnd);
+VAR
+  ExternalID  : TExternalID;
+  Phase       : TPhase;
+  F           : PChar;
+  NotationDef : TNotationDef;
+  DER         : TDtdElementRec;
+BEGIN
+  Final       := Start + 10;   // Character after <!NOTATION
+  DER.Start   := Start;
+  Phase       := phName;
+  NotationDef := TNotationDef.Create;
+  REPEAT
+    IF NOT (Final^ IN CWhitespace) THEN
+      CASE Final^ OF
+        '>',
+        #0   : BREAK;
+        ELSE   CASE Phase OF
+                 phName  : BEGIN
+                             ExtractName (Final, CWhitespace + ['>'], F);
+                             SetStringSF (NotationDef.Name, Final, F);
+                             Final := F;
+                             Phase := phExtId;
+                           END;
+                 phExtId : BEGIN
+                             ExternalID := TExternalID.Create (Final);
+                             NotationDef.Value    := ExternalID.SystemId;
+                             NotationDef.PublicId := ExternalID.PublicId;
+                             Final := ExternalId.Final;
+                             ExternalId.Free;
+                             Phase := phEnd;
+                           END;
+                 phEnd   : ;   // -!- There is an error in the document if this branch is called
+                 END;
+        END;
+    INC (Final);
+  UNTIL FALSE;
+  Notations.Add (NotationDef);
+  Final := StrScanE (Final, '>');
+
+  DER.ElementType := deNotation;
+  DER.NotationDef := NotationDef;
+  DER.Final       := Final;
+  DtdElementFound (DER);
+END;
+
+
+PROCEDURE TXmlParser.PushPE (VAR Start : PChar);
+          (* If there is a parameter entity reference found in the data stream,
+             the current position will be pushed to the entity stack.
+             Start:  IN  Pointer to the '%' character starting the PE reference
+                     OUT Pointer to first character of PE replacement text *)
+VAR
+  P         : PChar;
+  EntityDef : TEntityDef;
+BEGIN
+  P := StrScan (Start, ';');
+  IF P <> NIL THEN BEGIN
+    EntityDef := TEntityDef (ParEntities.Node (StrSFPas (Start+1, P-1)));
+    IF EntityDef <> NIL THEN BEGIN
+      EntityStack.Push (P+1);
+      Start := PChar (EntityDef.Value);
+      END
+    ELSE
+      Start := P+1;
+    END;
+END;
+
+
+PROCEDURE TXmlParser.ReplaceCharacterEntities (VAR Str : STRING);
+          // Replaces all Character Entity References in the String
+VAR
+  Start  : INTEGER;
+  PAmp   : PChar;
+  PSemi  : PChar;
+  PosAmp : INTEGER;
+  Len    : INTEGER;    // Length of Entity Reference
+BEGIN
+  IF Str = '' THEN EXIT;
+  Start := 1;
+  REPEAT
+    PAmp := StrPos (PChar (Str) + Start-1, '&#');
+    IF PAmp = NIL THEN BREAK;
+    PSemi := StrScan (PAmp+2, ';');
+    IF PSemi = NIL THEN BREAK;
+    PosAmp := PAmp - PChar (Str) + 1;
+    Len    := PSemi-PAmp+1;
+    IF CompareText (Str [PosAmp+2], 'x') = 0          // !!! Can't use "CHR" for Unicode characters > 255
+      THEN Str [PosAmp] := CHR (StrToIntDef ('$'+Copy (Str, PosAmp+3, Len-4), 0))
+      ELSE Str [PosAmp] := CHR (StrToIntDef (Copy (Str, PosAmp+2, Len-3), 32));
+    Delete (Str, PosAmp+1, Len-1);  
+    Start := PosAmp + 1;
+  UNTIL FALSE;
+END;
+
+
+PROCEDURE TXmlParser.ReplaceParameterEntities (VAR Str : STRING);
+          // Recursively replaces all Parameter Entity References in the String
+  PROCEDURE ReplaceEntities (VAR Str : STRING);
+  VAR
+    Start   : INTEGER;
+    PAmp    : PChar;
+    PSemi   : PChar;
+    PosAmp  : INTEGER;
+    Len     : INTEGER;
+    Entity  : TEntityDef;
+    Repl    : STRING;        // Replacement
+  BEGIN
+    IF Str = '' THEN EXIT;
+    Start := 1;
+    REPEAT
+      PAmp := StrPos (PChar (Str)+Start-1, '%');
+      IF PAmp = NIL THEN BREAK;
+      PSemi := StrScan (PAmp+2, ';');
+      IF PSemi = NIL THEN BREAK;
+      PosAmp := PAmp - PChar (Str) + 1;
+      Len    := PSemi-PAmp+1;
+      Entity := TEntityDef (ParEntities.Node (Copy (Str, PosAmp+1, Len-2)));
+      IF Entity <> NIL THEN BEGIN
+        Repl := Entity.Value;
+        ReplaceEntities (Repl);    // Recursion
+        END
+      ELSE
+        Repl := Copy (Str, PosAmp, Len);
+      Delete (Str, PosAmp, Len);  
+      Insert (Repl, Str, PosAmp);
+      Start := PosAmp + Length (Repl);
+    UNTIL FALSE;
+  END;
+BEGIN
+  ReplaceEntities (Str);
+END;
+
+
+PROCEDURE TXmlParser.ReplaceGeneralEntities (VAR Str : STRING);
+          // Recursively replaces General Entity References in the String
+  PROCEDURE ReplaceEntities (VAR Str : STRING);
+  VAR
+    Start          : INTEGER;
+    PAmp           : PChar;
+    PSemi          : PChar;
+    PosAmp         : INTEGER;
+    Len            : INTEGER;
+    EntityDef      : TEntityDef;
+    EntName        : STRING;
+    Repl           : STRING;        // Replacement
+    ExternalEntity : TXmlParser;
+  BEGIN
+    IF Str = '' THEN EXIT;
+    Start := 1;
+    REPEAT
+      PAmp := StrPos (PChar (Str)+Start-1, '&');
+      IF PAmp = NIL THEN BREAK;
+      PSemi := StrScan (PAmp+2, ';');
+      IF PSemi = NIL THEN BREAK;
+      PosAmp := PAmp - PChar (Str) + 1;
+      Len    := PSemi-PAmp+1;
+      EntName := Copy (Str, PosAmp+1, Len-2);
+      IF      EntName = 'lt'   THEN Repl := '<'
+      ELSE IF EntName = 'gt'   THEN Repl := '>'
+      ELSE IF EntName = 'amp'  THEN Repl := '&'
+      ELSE IF EntName = 'apos' THEN Repl := ''''
+      ELSE IF EntName = 'quot' THEN Repl := '"'
+      ELSE BEGIN
+        EntityDef := TEntityDef (Entities.Node (EntName));
+        IF EntityDef <> NIL THEN BEGIN
+          IF EntityDef.Value <> '' THEN   // Internal Entity
+            Repl := EntityDef.Value
+          ELSE BEGIN                      // External Entity
+            ExternalEntity := LoadExternalEntity (EntityDef.SystemId, EntityDef.PublicId, EntityDef.NotationName);
+            Repl := StrPas (ExternalEntity.DocBuffer);  // !!! What if it contains a Text Declaration?
+            ExternalEntity.Free;
+            END;
+          ReplaceEntities (Repl);    // Recursion
+          END
+        ELSE
+          Repl := Copy (Str, PosAmp, Len);
+        END;
+      Delete (Str, PosAmp, Len);  
+      Insert (Repl, Str, PosAmp);
+      Start := PosAmp + Length (Repl);
+    UNTIL FALSE;
+  END;
+BEGIN
+  ReplaceEntities (Str);
+END;
+
+
+FUNCTION  TXmlParser.LoadExternalEntity (SystemId, PublicId, Notation : STRING) : TXmlParser;
+          // This will be called whenever there is a Parsed External Entity or
+          // the DTD External Subset to be parsed.
+          // It has to create a TXmlParser instance and load the desired Entity.
+          // This instance of LoadExternalEntity assumes that "SystemId" is a valid
+          // file name (relative to the Document source) and loads this file using
+          // the LoadFromFile method.
+VAR
+  Filename : STRING;
+BEGIN
+  // --- Convert System ID to complete filename
+  Filename := StringReplace (SystemId, '/', '\', [rfReplaceAll]);
+  IF Copy (FSource, 1, 1) <> '<' THEN
+    IF (Copy (Filename, 1, 2) = '\\') OR (Copy (Filename, 2, 1) = ':') THEN
+      // Already has an absolute Path
+    ELSE BEGIN
+      Filename := ExtractFilePath (FSource) + Filename;
+      END;
+
+  // --- Load the File
+  Result := TXmlParser.Create;
+  Result.LoadFromFile (Filename);
+END;
+
+
+FUNCTION  TXmlParser.TranslateEncoding  (CONST Source : STRING) : STRING;
+          // The member variable "CurEncoding" always holds the name of the current
+          // encoding, e.g. 'UTF-8' or 'ISO-8859-1'.
+          // This virtual method "TranslateEncoding" is responsible for translating
+          // the content passed in the "Source" parameter to the Encoding which
+          // is expected by the application.
+          // This instance of "TranlateEncoding" assumes that the Application expects
+          // Windows ANSI (Win1252) strings. It is able to transform UTF-8 or ISO-8859-1
+          // encodings.
+          // If you want your application to understand or create other encodings, you
+          // override this function.
+BEGIN
+  IF CurEncoding = 'UTF-8'
+    THEN Result := Utf8ToAnsi (Source)
+    ELSE Result := Source;
+END;
+
+
+PROCEDURE TXmlParser.DtdElementFound (DtdElementRec : TDtdElementRec);
+          // This method is called for every element which is found in the DTD
+          // declaration. The variant record TDtdElementRec is passed which
+          // holds informations about the element.
+          // You can override this function to handle DTD declarations.
+          // Note that when you parse the same Document instance a second time,
+          // the DTD will not get parsed again.
+BEGIN
+END;
+
+
+FUNCTION TXmlParser.GetDocBuffer: PChar;
+         // Returns FBuffer or a pointer to a NUL char if Buffer is empty
+BEGIN
+  IF FBuffer = NIL
+    THEN Result := #0
+    ELSE Result := FBuffer;
+END;
+
+
+(*$IFNDEF HAS_CONTNRS_UNIT
+===============================================================================================
+TObjectList
+===============================================================================================
+*)
+
+DESTRUCTOR TObjectList.Destroy;
+BEGIN
+  Clear;
+  SetCapacity(0);
+  INHERITED Destroy;
+END;
+
+
+PROCEDURE TObjectList.Delete (Index : INTEGER);
+BEGIN
+  IF (Index < 0) OR (Index >= Count) THEN EXIT;
+  TObject (Items [Index]).Free;
+  INHERITED Delete (Index);
+END;
+
+
+PROCEDURE TObjectList.Clear;
+BEGIN
+  WHILE Count > 0 DO
+    Delete (Count-1);
+END;
+
+(*$ENDIF *)
+
+(*
+===============================================================================================
+TNvpNode
+--------
+Node base class for the TNvpList
+===============================================================================================
+*)
+
+CONSTRUCTOR TNvpNode.Create (TheName, TheValue : STRING);
+BEGIN
+  INHERITED Create;
+  Name  := TheName;
+  Value := TheValue;
+END;
+
+
+(*
+===============================================================================================
+TNvpList
+--------
+A generic List of Name-Value Pairs, based on the TObjectList introduced in Delphi 5
+===============================================================================================
+*)
+
+PROCEDURE TNvpList.Add (Node : TNvpNode);
+VAR
+  I : INTEGER;
+BEGIN
+  FOR I := Count-1 DOWNTO 0 DO
+    IF Node.Name > TNvpNode (Items [I]).Name THEN BEGIN
+      Insert (I+1, Node);
+      EXIT;
+      END;
+  Insert (0, Node);
+END;
+
+
+
+FUNCTION  TNvpList.Node (Name : STRING) : TNvpNode;
+          // Binary search for Node
+VAR
+  L, H : INTEGER;    // Low, High Limit
+  T, C : INTEGER;    // Test Index, Comparison result
+  Last : INTEGER;    // Last Test Index
+BEGIN
+  IF Count=0 THEN BEGIN
+    Result := NIL;
+    EXIT;
+    END;
+
+  L    := 0;
+  H    := Count;
+  Last := -1;
+  REPEAT
+    T := (L+H) DIV 2;
+    IF T=Last THEN BREAK;
+    Result := TNvpNode (Items [T]);
+    C := CompareStr (Result.Name, Name);
+    IF      C = 0 THEN EXIT
+    ELSE IF C < 0 THEN L := T
+    ELSE               H := T;
+    Last := T;
+  UNTIL FALSE;
+  Result := NIL;
+END;
+
+
+FUNCTION  TNvpList.Node (Index : INTEGER) : TNvpNode;
+BEGIN
+  IF (Index < 0) OR (Index >= Count)
+    THEN Result := NIL
+    ELSE Result := TNvpNode (Items [Index]);
+END;
+
+
+FUNCTION  TNvpList.Value (Name : STRING) : STRING;
+VAR
+  Nvp : TNvpNode;
+BEGIN
+  Nvp := TNvpNode (Node (Name));
+  IF Nvp <> NIL
+    THEN Result := Nvp.Value
+    ELSE Result := '';
+END;
+
+
+FUNCTION  TNvpList.Value (Index : INTEGER) : STRING;
+BEGIN
+  IF (Index < 0) OR (Index >= Count)
+    THEN Result := ''
+    ELSE Result := TNvpNode (Items [Index]).Value;
+END;
+
+
+FUNCTION  TNvpList.Name (Index : INTEGER) : STRING;
+BEGIN
+  IF (Index < 0) OR (Index >= Count)
+    THEN Result := ''
+    ELSE Result := TNvpNode (Items [Index]).Name;
+END;
+
+
+(*
+===============================================================================================
+TAttrList
+List of Attributes. The "Analyze" method extracts the Attributes from the given Buffer.
+Is used for extraction of Attributes in Start-Tags, Empty-Element Tags and the "pseudo"
+attributes in XML Prologs, Text Declarations and PIs.
+===============================================================================================
+*)
+
+PROCEDURE TAttrList.Analyze (Start : PChar; VAR Final : PChar);
+          // Analyze the Buffer for Attribute=Name pairs.
+          // Terminates when there is a character which is not IN CNameStart
+          // (e.g. '?>' or '>' or '/>')
+TYPE
+  TPhase = (phName, phEq, phValue);
+VAR
+  Phase : TPhase;
+  F     : PChar;
+  Name  : STRING;
+  Value : STRING;
+  Attr  : TAttr;
+BEGIN
+  Clear;
+  Phase := phName;
+  Final := Start;
+  REPEAT
+    IF (Final^ = #0) OR (Final^ = '>') THEN BREAK;
+    IF NOT (Final^ IN CWhitespace) THEN
+      CASE Phase OF
+        phName  : BEGIN
+                    IF NOT (Final^ IN CNameStart) THEN EXIT;
+                    ExtractName (Final, CWhitespace + ['=', '/'], F);
+                    SetStringSF (Name, Final, F);
+                    Final := F;
+                    Phase := phEq;
+                  END;
+        phEq    : BEGIN
+                    IF Final^ = '=' THEN
+                      Phase := phValue
+                  END;
+        phValue : BEGIN
+                    IF Final^ IN CQuoteChar THEN BEGIN
+                      ExtractQuote (Final, Value, F);
+                      Attr := TAttr.Create;
+                      Attr.Name      := Name;
+                      Attr.Value     := Value;
+                      Attr.ValueType := vtNormal;
+                      Add (Attr);
+                      Final := F;
+                      Phase := phName;
+                      END;
+                  END;
+        END;
+    INC (Final);
+  UNTIL FALSE;
+END;
+
+
+(*
+===============================================================================================
+TElemList
+List of TElemDef nodes.
+===============================================================================================
+*)
+
+FUNCTION  TElemList.Node (Name : STRING) : TElemDef;
+          // Binary search for the Node with the given Name
+VAR
+  L, H : INTEGER;    // Low, High Limit
+  T, C : INTEGER;    // Test Index, Comparison result
+  Last : INTEGER;    // Last Test Index
+BEGIN
+  IF Count=0 THEN BEGIN
+    Result := NIL;
+    EXIT;
+    END;
+
+  L    := 0;
+  H    := Count;
+  Last := -1;
+  REPEAT
+    T := (L+H) DIV 2;
+    IF T=Last THEN BREAK;
+    Result := TElemDef (Items [T]);
+    C := CompareStr (Result.Name, Name);
+    IF C = 0 THEN EXIT
+    ELSE IF C < 0 THEN L := T
+    ELSE               H := T;
+    Last := T;
+  UNTIL FALSE;
+  Result := NIL;
+END;
+
+
+PROCEDURE TElemList.Add (Node : TElemDef);
+VAR
+  I : INTEGER;
+BEGIN
+  FOR I := Count-1 DOWNTO 0 DO
+    IF Node.Name > TElemDef (Items [I]).Name THEN BEGIN
+      Insert (I+1, Node);
+      EXIT;
+      END;
+  Insert (0, Node);
+END;
+
+
+(*
+===============================================================================================
+TScannerXmlParser
+A TXmlParser descendant for the TCustomXmlScanner component
+===============================================================================================
+*)
+
+TYPE
+  TScannerXmlParser = CLASS (TXmlParser)
+                       Scanner : TCustomXmlScanner;
+                       CONSTRUCTOR Create (TheScanner : TCustomXmlScanner);
+                       FUNCTION  LoadExternalEntity (SystemId, PublicId,
+                                                     Notation : STRING) : TXmlParser;  OVERRIDE;
+                       FUNCTION  TranslateEncoding  (CONST Source : STRING) : STRING;  OVERRIDE;
+                       PROCEDURE DtdElementFound (DtdElementRec : TDtdElementRec);     OVERRIDE;
+                      END;
+
+CONSTRUCTOR TScannerXmlParser.Create (TheScanner : TCustomXmlScanner);
+BEGIN
+  INHERITED Create;
+  Scanner := TheScanner;
+END;
+
+
+FUNCTION  TScannerXmlParser.LoadExternalEntity (SystemId, PublicId, Notation : STRING) : TXmlParser;
+BEGIN
+  IF Assigned (Scanner.FOnLoadExternal)
+    THEN Scanner.FOnLoadExternal (Scanner, SystemId, PublicId, Notation, Result)
+    ELSE Result :=  INHERITED LoadExternalEntity (SystemId, PublicId, Notation);
+END;
+
+
+FUNCTION  TScannerXmlParser.TranslateEncoding  (CONST Source : STRING) : STRING;
+BEGIN
+  IF Assigned (Scanner.FOnTranslateEncoding)
+    THEN Result := Scanner.FOnTranslateEncoding (Scanner, CurEncoding, Source)
+    ELSE Result := INHERITED TranslateEncoding (Source);
+END;
+
+
+PROCEDURE TScannerXmlParser.DtdElementFound (DtdElementRec : TDtdElementRec);
+BEGIN
+  WITH DtdElementRec DO
+    CASE ElementType OF
+      deElement  : Scanner.WhenElement  (ElemDef);
+      deAttList  : Scanner.WhenAttList  (ElemDef);
+      deEntity   : Scanner.WhenEntity   (EntityDef);
+      deNotation : Scanner.WhenNotation (NotationDef);
+      dePI       : Scanner.WhenPI       (STRING (Target), STRING (Content), AttrList);
+      deComment  : Scanner.WhenComment  (StrSFPas (Start, Final));
+      deError    : Scanner.WhenDtdError (Pos);
+      END;
+END;
+
+
+(*
+===============================================================================================
+TCustomXmlScanner
+===============================================================================================
+*)
+
+CONSTRUCTOR TCustomXmlScanner.Create (AOwner: TComponent);
+BEGIN
+  INHERITED;
+  FXmlParser := TScannerXmlParser.Create (Self);
+END;
+
+
+DESTRUCTOR TCustomXmlScanner.Destroy;
+BEGIN
+  FXmlParser.Free;
+  INHERITED;
+END;
+
+
+PROCEDURE TCustomXmlScanner.LoadFromFile (Filename : TFilename);
+          // Load XML Document from file
+BEGIN
+  FXmlParser.LoadFromFile (Filename);
+END;
+
+
+PROCEDURE TCustomXmlScanner.LoadFromBuffer (Buffer : PChar);
+          // Load XML Document from buffer
+BEGIN
+  FXmlParser.LoadFromBuffer (Buffer);
+END;
+
+
+PROCEDURE TCustomXmlScanner.SetBuffer (Buffer : PChar);
+          // Refer to Buffer
+BEGIN
+  FXmlParser.SetBuffer (Buffer);
+END;
+
+
+FUNCTION  TCustomXmlScanner.GetFilename : TFilename;
+BEGIN
+  Result := FXmlParser.Source;
+END;
+
+
+FUNCTION  TCustomXmlScanner.GetNormalize : BOOLEAN;
+BEGIN
+  Result := FXmlParser.Normalize;
+END;
+
+
+PROCEDURE TCustomXmlScanner.SetNormalize (Value : BOOLEAN);
+BEGIN
+  FXmlParser.Normalize := Value;
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenXmlProlog(XmlVersion, Encoding: STRING; Standalone : BOOLEAN);
+          // Is called when the parser has parsed the <? xml ?> declaration of the prolog
+BEGIN
+  IF Assigned (FOnXmlProlog) THEN FOnXmlProlog (Self, XmlVersion, Encoding, Standalone);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenComment  (Comment : STRING);
+          // Is called when the parser has parsed a <!-- comment -->
+BEGIN
+  IF Assigned (FOnComment) THEN FOnComment (Self, Comment);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenPI (Target, Content: STRING; Attributes : TAttrList);
+          // Is called when the parser has parsed a <?processing instruction ?>
+BEGIN
+  IF Assigned (FOnPI) THEN FOnPI (Self, Target, Content, Attributes);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenDtdRead (RootElementName : STRING);
+          // Is called when the parser has completely parsed the DTD
+BEGIN
+  IF Assigned (FOnDtdRead) THEN FOnDtdRead (Self, RootElementName);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenStartTag (TagName : STRING; Attributes : TAttrList);
+          // Is called when the parser has parsed a start tag like <p>
+BEGIN
+  IF Assigned (FOnStartTag) THEN FOnStartTag (Self, TagName, Attributes);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenEmptyTag (TagName : STRING; Attributes : TAttrList);
+          // Is called when the parser has parsed an Empty Element Tag like <br/>
+BEGIN
+  IF Assigned (FOnEmptyTag) THEN FOnEmptyTag (Self, TagName, Attributes);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenEndTag (TagName : STRING);
+          // Is called when the parser has parsed an End Tag like </p>
+BEGIN
+  IF Assigned (FOnEndTag) THEN FOnEndTag (Self, TagName);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenContent (Content : STRING);
+          // Is called when the parser has parsed an element's text content
+BEGIN
+  IF Assigned (FOnContent) THEN FOnContent (Self, Content);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenCData (Content : STRING);
+          // Is called when the parser has parsed a CDATA section
+BEGIN
+  IF Assigned (FOnCData) THEN FOnCData (Self, Content);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenElement (ElemDef : TElemDef);
+          // Is called when the parser has parsed an <!ELEMENT> definition
+          // inside the DTD
+BEGIN
+  IF Assigned (FOnElement) THEN FOnElement (Self, ElemDef);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenAttList (ElemDef : TElemDef);
+          // Is called when the parser has parsed an <!ATTLIST> definition
+          // inside the DTD
+BEGIN
+  IF Assigned (FOnAttList) THEN FOnAttList (Self, ElemDef);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenEntity   (EntityDef : TEntityDef);
+          // Is called when the parser has parsed an <!ENTITY> definition
+          // inside the DTD
+BEGIN
+  IF Assigned (FOnEntity) THEN FOnEntity (Self, EntityDef);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenNotation (NotationDef : TNotationDef);
+          // Is called when the parser has parsed a <!NOTATION> definition
+          // inside the DTD
+BEGIN
+  IF Assigned (FOnNotation) THEN FOnNotation (Self, NotationDef);
+END;
+
+
+PROCEDURE TCustomXmlScanner.WhenDtdError (ErrorPos : PChar);
+          // Is called when the parser has found an Error in the DTD
+BEGIN
+  IF Assigned (FOnDtdError) THEN FOnDtdError (Self, ErrorPos);
+END;
+
+
+PROCEDURE TCustomXmlScanner.Execute;
+          // Perform scanning
+          // Scanning is done synchronously, i.e. you can expect events to be triggered
+          // in the order of the XML data stream. Execute will finish when the whole XML
+          // document has been scanned or when the StopParser property has been set to TRUE.
+BEGIN
+  FStopParser := FALSE;
+  FXmlParser.StartScan;
+  WHILE FXmlParser.Scan AND (NOT FStopParser) DO
+    CASE FXmlParser.CurPartType OF
+      ptNone      : ;
+      ptXmlProlog : WhenXmlProlog (FXmlParser.XmlVersion, FXmlParser.Encoding, FXmlParser.Standalone);
+      ptComment   : WhenComment   (StrSFPas (FXmlParser.CurStart, FXmlParser.CurFinal));
+      ptPI        : WhenPI        (FXmlParser.CurName, FXmlParser.CurContent, FXmlParser.CurAttr);
+      ptDtdc      : WhenDtdRead   (FXmlParser.RootName);
+      ptStartTag  : WhenStartTag  (FXmlParser.CurName, FXmlParser.CurAttr);
+      ptEmptyTag  : WhenEmptyTag  (FXmlParser.CurName, FXmlParser.CurAttr);
+      ptEndTag    : WhenEndTag    (FXmlParser.CurName);
+      ptContent   : WhenContent   (FXmlParser.CurContent);
+      ptCData     : WhenCData     (FXmlParser.CurContent);
+      END;
+END;
+
+
+END.
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/logger.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/logger.pas
new file mode 100644
index 00000000..ad9b24e6
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/logger.pas
@@ -0,0 +1,189 @@
+unit logger;
+{
+  $Id: logger.pas,v 1.2 2006/11/26 16:58:04 savage Exp $
+
+}
+{******************************************************************************}
+{                                                                              }
+{                Error Logging Unit                                            }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Portions created by Dominique Louis are                                      }
+{ Copyright (C) 2000 - 2001 Dominique Louis.                                   }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{                                                                              }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{   Logging functions...                                                       }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   SDL.dll on Windows platforms                                               }
+{   libSDL-1.1.so.0 on Linux platform                                          }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{               2001 - DL : Initial creation                                   }
+{         25/10/2001 - DRE : Added $M+ directive to allow published            }
+{                                in classes. Added a compile directive         }
+{                                around fmShareExclusive as this does not      }
+{                                exist in Free Pascal                          }
+{                                                                              }
+{******************************************************************************}
+{
+  $Log: logger.pas,v $
+  Revision 1.2  2006/11/26 16:58:04  savage
+  Modifed to create separate log files. Therefore each instance running from the same directory will have their own individual log file, prepended with a number.
+
+  Revision 1.1  2004/02/05 00:08:20  savage
+  Module 1.0 release
+
+  
+}
+
+{$I jedi-sdl.inc}
+
+{$WEAKPACKAGEUNIT OFF}
+
+interface
+
+uses
+  Classes,
+  SysUtils;
+
+type
+  TLogger = class
+  private
+    FFileHandle : TextFile;
+    FApplicationName : string;
+    FApplicationPath : string;
+  protected
+
+  public
+    constructor Create;
+    destructor Destroy; override;
+    function GetApplicationName: string;
+    function GetApplicationPath: string;
+    procedure LogError( ErrorMessage : string; Location : string );
+    procedure LogWarning( WarningMessage : string; Location : string );
+    procedure LogStatus( StatusMessage : string; Location : string );
+  published
+    property ApplicationName : string read GetApplicationName;
+    property ApplicationPath : string read GetApplicationPath;
+  end;
+
+var
+  Log : TLogger;
+
+implementation
+
+{ TLogger }
+constructor TLogger.Create;
+var
+  FileName : string;
+  FileNo : integer;
+begin
+  FApplicationName := ExtractFileName( ParamStr(0) );
+  FApplicationPath := ExtractFilePath( ParamStr(0) );
+  FileName := FApplicationPath + ChangeFileExt( FApplicationName, '.log' );
+  FileNo := 0;
+  while FileExists( FileName ) do
+  begin
+    inc( FileNo );
+    FileName := FApplicationPath + IntToStr( FileNo ) + ChangeFileExt( FApplicationName, '.log' )
+  end;
+  AssignFile( FFileHandle, FileName );
+  ReWrite( FFileHandle );
+  (*inherited Create( FApplicationPath + ChangeFileExt( FApplicationName, '.log' ),
+                    fmCreate {$IFNDEF FPC}or fmShareExclusive{$ENDIF} );*)
+end;
+
+destructor TLogger.Destroy;
+begin
+  CloseFile( FFileHandle );
+  inherited;
+end;
+
+function TLogger.GetApplicationName: string;
+begin
+  result := FApplicationName;
+end;
+
+function TLogger.GetApplicationPath: string;
+begin
+  result := FApplicationPath;
+end;
+
+procedure TLogger.LogError(ErrorMessage, Location: string);
+var
+  S : string;
+begin
+  S := '*** ERROR *** : @ ' + TimeToStr(Time) + ' MSG : ' + ErrorMessage + ' IN : ' + Location + #13#10;
+  WriteLn( FFileHandle,  S );
+  Flush( FFileHandle );
+end;
+
+procedure TLogger.LogStatus(StatusMessage, Location: string);
+var
+  S : string;
+begin
+  S := 'STATUS INFO : @ ' + TimeToStr(Time) + ' MSG : ' + StatusMessage + ' IN : ' + Location + #13#10;
+  WriteLn( FFileHandle,  S );
+  Flush( FFileHandle );
+end;
+
+procedure TLogger.LogWarning(WarningMessage, Location: string);
+var
+  S : string;
+begin
+  S := '=== WARNING === : @ ' + TimeToStr(Time) + ' MSG : ' + WarningMessage + ' IN : ' + Location + #13#10;
+  WriteLn( FFileHandle,  S );
+  Flush( FFileHandle );
+end;
+
+initialization
+begin
+  Log := TLogger.Create;
+  Log.LogStatus( 'Starting Application', 'Initialization' );
+end;
+
+finalization
+begin
+  Log.LogStatus( 'Terminating Application', 'Finalization' );
+  Log.Free;
+  Log := nil;
+end;
+
+end.
+ 
\ No newline at end of file
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas
new file mode 100644
index 00000000..796aa0ab
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas
@@ -0,0 +1,320 @@
+unit moduleloader;
+{
+  $Id: moduleloader.pas,v 1.4 2004/02/20 17:19:10 savage Exp $
+  
+}
+{******************************************************************}
+{                                                                  }
+{       Project JEDI                                               }
+{       OS independent Dynamic Loading Helpers                     }
+{                                                                  }
+{ The initial developer of the this code is                        }
+{ Robert Marquardt <robert_marquardt@gmx.de)                       }
+{                                                                  }
+{ Copyright (C) 2000, 2001 Robert Marquardt.                       }
+{                                                                  }
+{ Obtained through:                                                }
+{ Joint Endeavour of Delphi Innovators (Project JEDI)              }
+{                                                                  }
+{ You may retrieve the latest version of this file at the Project  }
+{ JEDI home page, located at http://delphi-jedi.org                }
+{                                                                  }
+{ The contents of this file are used with permission, subject to   }
+{ the Mozilla Public License Version 1.1 (the "License"); you may  }
+{ not use this file except in compliance with the License. You may }
+{ obtain a copy of the License at                                  }
+{ http://www.mozilla.org/NPL/NPL-1_1Final.html                     }
+{                                                                  }
+{ Software distributed under the License is distributed on an      }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or   }
+{ implied. See the License for the specific language governing     }
+{ rights and limitations under the License.                        }
+{                                                                  }
+{******************************************************************}
+{
+  $Log: moduleloader.pas,v $
+  Revision 1.4  2004/02/20 17:19:10  savage
+  Added Calling convention to Win32 functions just in case.
+
+  Revision 1.3  2004/02/14 22:36:29  savage
+  Fixed inconsistencies of using LoadLibrary and LoadModule.
+  Now all units make use of LoadModule rather than LoadLibrary and other dynamic proc procedures.
+
+  Revision 1.2  2004/02/14 00:23:39  savage
+  As UNIX is defined in jedi-sdl.inc this will be used to check linux compatability as well. Units have been changed to reflect this change.
+
+  Revision 1.1  2004/02/14 00:04:50  savage
+  dllfuncs conflicts with FreePascal so it has been renamed back to the moduleloader.pas
+
+  Revision 1.1  2004/02/05 00:08:19  savage
+  Module 1.0 release
+
+  
+}
+
+interface
+
+{$i jedi-sdl.inc}
+{$WEAKPACKAGEUNIT ON}
+
+// each OS gets its own IFDEFed complete code block to make reading easier
+
+{$IFDEF MSWINDOWS}
+uses
+  Windows;
+
+type
+  // Handle to a loaded DLL
+  TModuleHandle = HINST;
+
+const
+  // Value designating an unassigned TModuleHandle od a failed loading
+  INVALID_MODULEHANDLE_VALUE = TModuleHandle(0);
+
+function LoadModule(var Module: TModuleHandle; FileName: PChar): Boolean; stdcall;
+function LoadModuleEx(var Module: TModuleHandle; FileName: PChar; Flags: Cardinal): Boolean; stdcall;
+procedure UnloadModule(var Module: TModuleHandle); stdcall;
+function GetModuleSymbol(Module: TModuleHandle; SymbolName: PChar): Pointer; stdcall;
+function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: PChar; var Accu: Boolean): Pointer; stdcall;
+function ReadModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean; stdcall;
+function WriteModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean; stdcall;
+
+implementation
+
+// load the DLL file FileName
+// the rules for FileName are those of LoadLibrary
+// Returns: True = success, False = failure to load
+// Assigns: the handle of the loaded DLL to Module
+// Warning: if Module has any other value than INVALID_MODULEHANDLE_VALUE
+// on entry the function will do nothing but returning success.
+
+function LoadModule(var Module: TModuleHandle; FileName: PChar): Boolean;
+begin
+  if Module = INVALID_MODULEHANDLE_VALUE then
+    Module := LoadLibrary( FileName );
+  Result := Module <> INVALID_MODULEHANDLE_VALUE;
+end;
+
+// load the DLL file FileName
+// LoadLibraryEx is used to get better control of the loading
+// for the allowed values for flags see LoadLibraryEx documentation.
+
+function LoadModuleEx(var Module: TModuleHandle; FileName: PChar; Flags: Cardinal): Boolean;
+begin
+  if Module = INVALID_MODULEHANDLE_VALUE then
+    Module := LoadLibraryEx( FileName, 0, Flags);
+  Result := Module <> INVALID_MODULEHANDLE_VALUE;
+end;
+
+// unload a DLL loaded with LoadModule or LoadModuleEx
+// The procedure will not try to unload a handle with
+// value INVALID_MODULEHANDLE_VALUE and assigns this value
+// to Module after unload.
+
+procedure UnloadModule(var Module: TModuleHandle);
+begin
+  if Module <> INVALID_MODULEHANDLE_VALUE then
+    FreeLibrary(Module);
+  Module := INVALID_MODULEHANDLE_VALUE;
+end;
+
+// returns the pointer to the symbol named SymbolName
+// if it is exported from the DLL Module
+// nil is returned if the symbol is not available
+
+function GetModuleSymbol(Module: TModuleHandle; SymbolName: PChar): Pointer;
+begin
+  Result := nil;
+  if Module <> INVALID_MODULEHANDLE_VALUE then
+    Result := GetProcAddress(Module, SymbolName );
+end;
+
+// returns the pointer to the symbol named SymbolName
+// if it is exported from the DLL Module
+// nil is returned if the symbol is not available.
+// as an extra the boolean variable Accu is updated
+// by anding in the success of the function.
+// This is very handy for rendering a global result
+// when accessing a long list of symbols.
+
+function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: PChar; var Accu: Boolean): Pointer;
+begin
+  Result := nil;
+  if Module <> INVALID_MODULEHANDLE_VALUE then
+    Result := GetProcAddress(Module, SymbolName );
+  Accu := Accu and (Result <> nil);
+end;
+
+// get the value of variables exported from a DLL Module
+// Delphi cannot access variables in a DLL directly, so
+// this function allows to copy the data from the DLL.
+// Beware! You are accessing the DLL memory image directly.
+// Be sure to access a variable not a function and be sure
+// to read the correct amount of data.
+
+function ReadModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
+var
+  Sym: Pointer;
+begin
+  Result := True;
+  Sym := GetModuleSymbolEx(Module, SymbolName, Result);
+  if Result then
+    Move(Sym^, Buffer, Size);
+end;
+
+// set the value of variables exported from a DLL Module
+// Delphi cannot access variables in a DLL directly, so
+// this function allows to copy the data to the DLL!
+// BEWARE! You are accessing the DLL memory image directly.
+// Be sure to access a variable not a function and be sure
+// to write the correct amount of data.
+// The changes are not persistent. They get lost when the
+// DLL is unloaded.
+
+function WriteModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
+var
+  Sym: Pointer;
+begin
+  Result := True;
+  Sym := GetModuleSymbolEx(Module, SymbolName, Result);
+  if Result then
+    Move(Buffer, Sym^, Size);
+end;
+
+{$ENDIF}
+
+{$IFDEF Unix}
+uses
+{$ifdef FPC}
+  dl,
+  Types,
+  Baseunix,
+  Unix;
+{$else}
+  Types,
+  Libc;
+{$endif}
+
+type
+  // Handle to a loaded .so
+  TModuleHandle = Pointer;
+
+const
+  // Value designating an unassigned TModuleHandle od a failed loading
+  INVALID_MODULEHANDLE_VALUE = TModuleHandle(nil);
+
+function LoadModule(var Module: TModuleHandle; FileName: PChar): Boolean;
+function LoadModuleEx(var Module: TModuleHandle; FileName: PChar; Flags: Cardinal): Boolean;
+procedure UnloadModule(var Module: TModuleHandle);
+function GetModuleSymbol(Module: TModuleHandle; SymbolName: PChar): Pointer;
+function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: PChar; var Accu: Boolean): Pointer;
+function ReadModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
+function WriteModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
+
+implementation
+
+// load the .so file FileName
+// the rules for FileName are those of dlopen()
+// Returns: True = success, False = failure to load
+// Assigns: the handle of the loaded .so to Module
+// Warning: if Module has any other value than INVALID_MODULEHANDLE_VALUE
+// on entry the function will do nothing but returning success.
+
+function LoadModule(var Module: TModuleHandle; FileName: PChar): Boolean;
+begin
+  if Module = INVALID_MODULEHANDLE_VALUE then
+    Module := dlopen( FileName, RTLD_NOW);
+  Result := Module <> INVALID_MODULEHANDLE_VALUE;
+end;
+
+// load the .so file FileName
+// dlopen() with flags is used to get better control of the loading
+// for the allowed values for flags see "man dlopen".
+
+function LoadModuleEx(var Module: TModuleHandle; FileName: PChar; Flags: Cardinal): Boolean;
+begin
+  if Module = INVALID_MODULEHANDLE_VALUE then
+    Module := dlopen( FileName, Flags);
+  Result := Module <> INVALID_MODULEHANDLE_VALUE;
+end;
+
+// unload a .so loaded with LoadModule or LoadModuleEx
+// The procedure will not try to unload a handle with
+// value INVALID_MODULEHANDLE_VALUE and assigns this value
+// to Module after unload.
+
+procedure UnloadModule(var Module: TModuleHandle);
+begin
+  if Module <> INVALID_MODULEHANDLE_VALUE then
+    dlclose(Module);
+  Module := INVALID_MODULEHANDLE_VALUE;
+end;
+
+// returns the pointer to the symbol named SymbolName
+// if it is exported from the .so Module
+// nil is returned if the symbol is not available
+
+function GetModuleSymbol(Module: TModuleHandle; SymbolName: PChar): Pointer;
+begin
+  Result := nil;
+  if Module <> INVALID_MODULEHANDLE_VALUE then
+    Result := dlsym(Module, SymbolName );
+end;
+
+// returns the pointer to the symbol named SymbolName
+// if it is exported from the .so Module
+// nil is returned if the symbol is not available.
+// as an extra the boolean variable Accu is updated
+// by anding in the success of the function.
+// This is very handy for rendering a global result
+// when accessing a long list of symbols.
+
+function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: PChar; var Accu: Boolean): Pointer;
+begin
+  Result := nil;
+  if Module <> INVALID_MODULEHANDLE_VALUE then
+    Result := dlsym(Module, SymbolName );
+  Accu := Accu and (Result <> nil);
+end;
+
+// get the value of variables exported from a .so Module
+// Delphi cannot access variables in a .so directly, so
+// this function allows to copy the data from the .so.
+// Beware! You are accessing the .so memory image directly.
+// Be sure to access a variable not a function and be sure
+// to read the correct amount of data.
+
+function ReadModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
+var
+  Sym: Pointer;
+begin
+  Result := True;
+  Sym := GetModuleSymbolEx(Module, SymbolName, Result);
+  if Result then
+    Move(Sym^, Buffer, Size);
+end;
+
+// set the value of variables exported from a .so Module
+// Delphi cannot access variables in a .so directly, so
+// this function allows to copy the data to the .so!
+// BEWARE! You are accessing the .so memory image directly.
+// Be sure to access a variable not a function and be sure
+// to write the correct amount of data.
+// The changes are not persistent. They get lost when the
+// .so is unloaded.
+
+function WriteModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
+var
+  Sym: Pointer;
+begin
+  Result := True;
+  Sym := GetModuleSymbolEx(Module, SymbolName, Result);
+  if Result then
+    Move(Buffer, Sym^, Size);
+end;
+{$ENDIF}
+
+{$IFDEF __MACH__} // Mach definitions go here
+{$ENDIF}
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/registryuserpreferences.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/registryuserpreferences.pas
new file mode 100644
index 00000000..4a5d55f0
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/registryuserpreferences.pas
@@ -0,0 +1,229 @@
+unit registryuserpreferences;
+{
+  $Id: registryuserpreferences.pas,v 1.1 2004/09/30 22:35:47 savage Exp $
+  
+}
+{******************************************************************************}
+{                                                                              }
+{          JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer          }
+{             Wrapper class for Windows Register and INI Files                 }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Dominqiue Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Portions created by Dominqiue Louis are                                      }
+{ Copyright (C) 2000 - 2001 Dominqiue Louis.                                   }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{                                                                              }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   The SDL Runtime libraris on Win32  : SDL.dll on Linux : libSDL.so          }
+{   They are available from...                                                 }
+{   http://www.libsdl.org .                                                    }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{   September   23 2004 - DL : Initial Creation                                }
+{
+  $Log: registryuserpreferences.pas,v $
+  Revision 1.1  2004/09/30 22:35:47  savage
+  Changes, enhancements and additions as required to get SoAoS working.
+
+
+}
+{******************************************************************************}
+
+interface
+
+uses
+  {$IFDEF REG}
+  Registry,
+  {$ELSE}
+  IniFiles,
+  {$ENDIF}
+  Classes,
+  userpreferences;
+
+type
+  TRegistryUserPreferences = class( TUserPreferences )
+  private
+
+  protected
+    function GetSection( const Index : Integer ) : string; virtual; abstract;
+    function GetIdentifier( const Index : Integer ) : string; virtual; abstract;
+    function GetDefaultBoolean( const Index : Integer ) : Boolean; override;
+    function GetBoolean( const Index : Integer ) : Boolean; override;
+    procedure SetBoolean( const Index : Integer; const Value : Boolean ); override;
+    function GetDefaultDateTime( const Index : Integer ) : TDateTime; override;
+    function GetDateTime( const Index : Integer ) : TDateTime; override;
+    procedure SetDateTime( const Index : Integer; const Value : TDateTime ); override;
+    function GetDefaultInteger( const Index : Integer ) : Integer; override;
+    function GetInteger( const Index : Integer ) : Integer; override;
+    procedure SetInteger( const Index : Integer; const Value : Integer ); override;
+    function GetDefaultFloat( const Index : Integer ) : single; override;
+    function GetFloat( const Index : Integer ) : single; override;
+    procedure SetFloat( const Index : Integer; const Value : single ); override;
+    function GetDefaultString( const Index : Integer ) : string; override;
+    function GetString( const Index : Integer ) : string; override;
+    procedure SetString( const Index : Integer; const Value : string ); override;
+  public
+    Registry : {$IFDEF REG}TRegIniFile{$ELSE}TIniFile{$ENDIF};
+    constructor Create( const FileName : string = '' ); reintroduce;
+    destructor Destroy; override;
+    procedure Update; override;
+  end;
+
+implementation
+
+uses
+  SysUtils;
+
+{ TRegistryUserPreferences }
+constructor TRegistryUserPreferences.Create( const FileName : string );
+var
+  defFileName : string;
+begin
+  inherited Create;
+
+  if FileName <> '' then
+    defFileName := FileName
+  else
+    defFileName := ChangeFileExt( ParamStr( 0 ), '.ini' );
+
+  Registry := {$IFDEF REG}TRegIniFile{$ELSE}TIniFile{$ENDIF}.Create( defFileName );
+end;
+
+destructor TRegistryUserPreferences.Destroy;
+begin
+  Update;
+  Registry.Free;
+  Registry := nil;
+  inherited;
+end;
+
+function TRegistryUserPreferences.GetBoolean( const Index : Integer ) : Boolean;
+begin
+  Result := Registry.ReadBool( GetSection( Index ), GetIdentifier( Index ), GetDefaultBoolean( Index ) );
+end;
+
+function TRegistryUserPreferences.GetDateTime( const Index : Integer ): TDateTime;
+begin
+  Result := Registry.ReadDateTime( GetSection( Index ){$IFNDEF REG}, GetIdentifier( Index ), GetDefaultDateTime( Index ){$ENDIF} );
+end;
+
+function TRegistryUserPreferences.GetDefaultBoolean( const Index : Integer ) : Boolean;
+begin
+  result := false;
+end;
+
+function TRegistryUserPreferences.GetDefaultDateTime( const Index: Integer ) : TDateTime;
+begin
+  result := Now;
+end;
+
+function TRegistryUserPreferences.GetDefaultFloat( const Index: Integer ) : single;
+begin
+  result := 0.0;
+end;
+
+function TRegistryUserPreferences.GetDefaultInteger(const Index : Integer ) : Integer;
+begin
+  result := 0;
+end;
+
+function TRegistryUserPreferences.GetDefaultString( const Index : Integer ) : string;
+begin
+  result := '';
+end;
+
+function TRegistryUserPreferences.GetFloat( const Index : Integer ): single;
+begin
+  Result := Registry.ReadFloat( GetSection( Index ){$IFNDEF REG}, GetIdentifier( Index ), GetDefaultFloat( Index ){$ENDIF} );
+end;
+
+function TRegistryUserPreferences.GetInteger( const Index : Integer ) : Integer;
+begin
+  Result := Registry.ReadInteger( GetSection( Index ), GetIdentifier( Index ), GetDefaultInteger( Index )  );
+end;
+
+function TRegistryUserPreferences.GetString( const Index : Integer ): string;
+begin
+  Result := Registry.ReadString( GetSection( Index ), GetIdentifier( Index ), GetDefaultString( Index ) );
+end;
+
+procedure TRegistryUserPreferences.SetBoolean( const Index : Integer; const Value : Boolean );
+begin
+  Registry.WriteBool( GetSection( Index ), GetIdentifier( Index ), Value );
+  inherited;
+end;
+
+procedure TRegistryUserPreferences.SetDateTime( const Index: Integer; const Value: TDateTime );
+begin
+  Registry.WriteDateTime( GetSection( Index ){$IFNDEF REG}, GetIdentifier( Index ){$ENDIF}, Value );
+  inherited;
+end;
+
+procedure TRegistryUserPreferences.SetFloat(const Index: Integer; const Value: single);
+begin
+  Registry.WriteFloat( GetSection( Index ){$IFNDEF REG}, GetIdentifier( Index ){$ENDIF}, Value );
+  inherited;
+end;
+
+procedure TRegistryUserPreferences.SetInteger( const Index, Value : Integer );
+begin
+  Registry.WriteInteger( GetSection( Index ), GetIdentifier( Index ), Value );
+  inherited;
+end;
+
+procedure TRegistryUserPreferences.SetString( const Index : Integer; const Value : string );
+begin
+  Registry.WriteString( GetSection( Index ), GetIdentifier( Index ), Value );
+  inherited;
+end;
+
+procedure TRegistryUserPreferences.Update;
+begin
+  {$IFDEF REG}
+  Registry.CloseKey;
+  {$ELSE}
+  Registry.UpdateFile;
+  {$ENDIF}
+end;
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdl.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdl.pas
new file mode 100644
index 00000000..736009c2
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdl.pas
@@ -0,0 +1,4332 @@
+unit sdl;
+{
+  $Id: sdl.pas,v 1.38 2008/01/26 10:09:32 savage Exp $
+
+}
+{******************************************************************************}
+{                                                                              }
+{          JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer          }
+{             Conversion of the Simple DirectMedia Layer Headers               }
+{                                                                              }
+{ Portions created by Sam Lantinga <slouken@devolution.com> are                }
+{ Copyright (C) 1997-2004  Sam Lantinga                                        }
+{ 5635-34 Springhouse Dr.                                                      }
+{ Pleasanton, CA 94588 (USA)                                                   }
+{                                                                              }
+{ All Rights Reserved.                                                         }
+{                                                                              }
+{ The original files are : SDL.h                                               }
+{                          SDL_main.h                                          }
+{                          SDL_types.h                                         }
+{                          SDL_rwops.h                                         }
+{                          SDL_timer.h                                         }
+{                          SDL_audio.h                                         }
+{                          SDL_cdrom.h                                         }
+{                          SDL_joystick.h                                      }
+{                          SDL_mouse.h                                         }
+{                          SDL_keyboard.h                                      }
+{                          SDL_events.h                                        }
+{                          SDL_video.h                                         }
+{                          SDL_byteorder.h                                     }
+{                          SDL_version.h                                       }
+{                          SDL_active.h                                        }
+{                          SDL_thread.h                                        }
+{                          SDL_mutex .h                                        }
+{                          SDL_getenv.h                                        }
+{                          SDL_loadso.h                                        }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Portions created by Dominique Louis are                                      }
+{ Copyright (C) 2000 - 2004 Dominique Louis.                                   }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{ Tom Jones <tigertomjones@gmx.de>  His Project inspired this conversion       }
+{ Matthias Thoma <ma.thoma@gmx.de>                                             }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   The SDL Runtime libraris on Win32  : SDL.dll on Linux : libSDL.so          }
+{   They are available from...                                                 }
+{   http://www.libsdl.org .                                                    }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{   May      08 2001 - DL : Added Keyboard  State Array ( See demos for how to }
+{                           use )                                              }
+{                           PKeyStateArr = ^TKeyStateArr;                      }
+{                           TKeyStateArr = array[0..65000] of UInt8;           }
+{                           As most games will need it.                        }
+{                                                                              }
+{   April    02 2001 - DL : Added SDL_getenv.h definitions and tested version  }
+{                           1.2.0 compatability.                               }
+{                                                                              }
+{   March    13 2001 - MT : Added Linux compatibility.                         }
+{                                                                              }
+{   March    10 2001 - MT : Added externalsyms for DEFINES                     }
+{                           Changed the license header                         }
+{                                                                              }
+{   March    09 2001 - MT : Added Kylix Ifdefs/Deleted the uses mmsystem       }
+{                                                                              }
+{   March    01 2001 - DL : Update conversion of version 1.1.8                 }
+{                                                                              }
+{   July     22 2001 - DL : Added TUInt8Array and PUIntArray after suggestions }
+{                           from Matthias Thoma and Eric Grange.               }
+{                                                                              }
+{   October  12 2001 - DL : Various changes as suggested by Matthias Thoma and }
+{                           David Acklam                                       }
+{                                                                              }
+{   October  24 2001 - DL : Added FreePascal support as per suggestions from   }
+{                           Dean Ellis.                                        }
+{                                                                              }
+{   October  27 2001 - DL : Added SDL_BUTTON macro                             }
+{                                                                              }
+{  November  08 2001 - DL : Bug fix as pointed out by Puthoon.                 }
+{                                                                              }
+{  November  29 2001 - DL : Bug fix of SDL_SetGammaRamp as pointed out by Simon}
+{                           Rushton.                                           }
+{                                                                              }
+{  November  30 2001 - DL : SDL_NOFRAME added as pointed out by Simon Rushton. }
+{                                                                              }
+{  December  11 2001 - DL : Added $WEAKPACKAGEUNIT ON to facilitate useage in  }
+{                           Components                                         }
+{                                                                              }
+{  January   05 2002 - DL : Added SDL_Swap32 function as suggested by Matthias }
+{                           Thoma and also made sure the _getenv from          }
+{                           MSVCRT.DLL uses the right calling convention       }
+{                                                                              }
+{  January   25 2002 - DL : Updated conversion of SDL_AddTimer &               }
+{                           SDL_RemoveTimer as per suggestions from Matthias   }
+{                           Thoma.                                             }
+{                                                                              }
+{  January   27 2002 - DL : Commented out exported function putenv and getenv  }
+{                           So that developers get used to using SDL_putenv    }
+{                           SDL_getenv, as they are more portable              }
+{                                                                              }
+{  March     05 2002 - DL : Added FreeAnNil procedure for Delphi 4 users.      }
+{                                                                              }
+{  October   23 2002 - DL : Added Delphi 3 Define of Win32.                    }
+{                           If you intend to you Delphi 3...                   }
+{                           ( which is officially unsupported ) make sure you  }
+{                           remove references to $EXTERNALSYM in this and other}
+{                           SDL files.                                         }
+{                                                                              }
+{ November  29 2002 - DL : Fixed bug in Declaration of SDL_GetRGBA that was    }
+{                          pointed out by Todd Lang                            }
+{                                                                              }
+{   April   03 2003 - DL : Added jedi-sdl.inc include file to support more     }
+{                          Pascal compilers. Initial support is now included   }
+{                          for GnuPascal, VirtualPascal, TMT and obviously     }
+{                          continue support for Delphi Kylix and FreePascal.   }
+{                                                                              }
+{   April   08 2003 - MK : Aka Mr Kroket - Added Better FPC support            }
+{                                                                              }
+{   April   24 2003 - DL : under instruction from Alexey Barkovoy, I have added}
+{                          better TMT Pascal support and under instruction     }
+{                          from Prof. Abimbola Olowofoyeku (The African Chief),}
+{                          I have added better Gnu Pascal support              }
+{                                                                              }
+{   April   30 2003 - DL : under instruction from David Mears AKA              }
+{                          Jason Siletto, I have added FPC Linux support.      }
+{                          This was compiled with fpc 1.1, so remember to set  }
+{                          include file path. ie. -Fi/usr/share/fpcsrc/rtl/*   }
+{                                                                              }
+{
+  $Log: sdl.pas,v $
+  Revision 1.38  2008/01/26 10:09:32  savage
+  Added SDL_BUTTON_X1 and SDL_BUTTON_X2 constants for extended mouse buttons. Now makes SDL v1.2.13 compliant.
+
+  Revision 1.37  2007/12/20 22:36:56  savage
+  Added SKYOS support, thanks to Sebastian-Torsten Tillmann
+
+  Revision 1.36  2007/12/05 22:52:04  savage
+  Better Mac OS X support for Frameworks.
+
+  Revision 1.35  2007/12/02 22:41:13  savage
+  Change for Mac OS X to link to SDL Framework
+
+  Revision 1.34  2007/08/26 23:50:53  savage
+  Jonas supplied another fix.
+
+  Revision 1.33  2007/08/26 15:59:46  savage
+  Mac OS changes as suggested by Jonas Maebe
+
+  Revision 1.32  2007/08/22 21:18:43  savage
+  Thanks to Dean for his MouseDelta patch.
+
+  Revision 1.31  2007/05/29 21:30:48  savage
+  Changes as suggested by Almindor for 64bit compatibility.
+
+  Revision 1.30  2007/05/29 19:31:03  savage
+  Fix to TSDL_Overlay structure - thanks David Pethes (aka imcold)
+
+  Revision 1.29  2007/05/20 20:29:11  savage
+  Initial Changes to Handle 64 Bits
+
+  Revision 1.26  2007/02/11 13:38:04  savage
+  Added Nintendo DS support - Thanks Dean.
+
+  Revision 1.25  2006/12/02 00:12:52  savage
+  Updated to latest version
+
+  Revision 1.24  2006/05/18 21:10:04  savage
+  Added 1.2.10 Changes
+
+  Revision 1.23  2005/12/04 23:17:52  drellis
+  Added declaration of SInt8 and PSInt8
+
+  Revision 1.22  2005/05/24 21:59:03  savage
+  Re-arranged uses clause to work on Win32 and Linux, Thanks again Michalis.
+
+  Revision 1.21  2005/05/22 18:42:31  savage
+  Changes as suggested by Michalis Kamburelis. Thanks again.
+
+  Revision 1.20  2005/04/10 11:48:33  savage
+  Changes as suggested by Michalis, thanks.
+
+  Revision 1.19  2005/01/05 01:47:06  savage
+  Changed LibName to reflect what MacOS X should have. ie libSDL*-1.2.0.dylib respectively.
+
+  Revision 1.18  2005/01/04 23:14:41  savage
+  Changed LibName to reflect what most Linux distros will have. ie libSDL*-1.2.so.0 respectively.
+
+  Revision 1.17  2005/01/03 18:40:59  savage
+  Updated Version number to reflect latest one
+
+  Revision 1.16  2005/01/01 02:02:06  savage
+  Updated to v1.2.8
+
+  Revision 1.15  2004/12/24 18:57:11  savage
+  forgot to apply Michalis Kamburelis' patch to the implementation section. now fixed
+
+  Revision 1.14  2004/12/23 23:42:18  savage
+  Applied Patches supplied by Michalis Kamburelis ( THANKS! ), for greater FreePascal compatability.
+
+  Revision 1.13  2004/09/30 22:31:59  savage
+  Updated with slightly different header comments
+
+  Revision 1.12  2004/09/12 21:52:58  savage
+  Slight changes to fix some issues with the sdl classes.
+
+  Revision 1.11  2004/08/14 22:54:30  savage
+  Updated so that Library name defines are correctly defined for MacOS X.
+
+  Revision 1.10  2004/07/20 23:57:33  savage
+  Thanks to Paul Toth for spotting an error in the SDL Audio Convertion structures.
+  In TSDL_AudioCVT the filters variable should point to and array of pointers and not what I had there previously.
+
+  Revision 1.9  2004/07/03 22:07:22  savage
+  Added Bitwise Manipulation Functions for TSDL_VideoInfo struct.
+
+  Revision 1.8  2004/05/10 14:10:03  savage
+  Initial MacOS X support. Fixed defines for MACOS ( Classic ) and DARWIN ( MacOS X ).
+
+  Revision 1.7  2004/04/13 09:32:08  savage
+  Changed Shared object names back to just the .so extension to avoid conflicts on various Linux/Unix distros. Therefore developers will need to create Symbolic links to the actual Share Objects if necessary.
+
+  Revision 1.6  2004/04/01 20:53:23  savage
+  Changed Linux Shared Object names so they reflect the Symbolic Links that are created when installing the RPMs from the SDL site.
+
+  Revision 1.5  2004/02/22 15:32:10  savage
+  SDL_GetEnv Fix so it also works on FPC/Linux. Thanks to Rodrigo for pointing this out.
+
+  Revision 1.4  2004/02/21 23:24:29  savage
+  SDL_GetEnv Fix so that it is not define twice for FPC. Thanks to Rene Hugentobler for pointing out this bug,
+
+  Revision 1.3  2004/02/18 22:35:51  savage
+  Brought sdl.pas up to 1.2.7 compatability
+  Thus...
+  Added SDL_GL_STEREO,
+      SDL_GL_MULTISAMPLEBUFFERS,
+      SDL_GL_MULTISAMPLESAMPLES
+
+  Add DLL/Shared object functions
+  function SDL_LoadObject( const sofile : PChar ) : Pointer;
+
+  function SDL_LoadFunction( handle : Pointer; const name : PChar ) : Pointer;
+
+  procedure SDL_UnloadObject( handle : Pointer );
+
+  Added function to create RWops from const memory: SDL_RWFromConstMem()
+  function SDL_RWFromConstMem(const mem: Pointer; size: Integer) : PSDL_RWops;
+
+  Ported SDL_cpuinfo.h so Now you can test for Specific CPU types.
+
+  Revision 1.2  2004/02/17 21:37:12  savage
+  Tidying up of units
+
+  Revision 1.1  2004/02/05 00:08:20  savage
+  Module 1.0 release
+
+}
+{******************************************************************************}
+
+{$I jedi-sdl.inc}
+
+interface
+
+uses
+{$IFDEF __GPC__}
+  system,
+  {$IFDEF WINDOWS}
+  wintypes,
+  {$ELSE}
+  {$ENDIF}
+  gpc;
+{$ENDIF}
+
+{$IFDEF HAS_TYPES}
+  Types{$IFNDEF NDS},{$ELSE};{$ENDIF}
+{$ENDIF}
+
+{$IFDEF WINDOWS}
+  Windows;
+{$ENDIF}
+
+{$IFDEF UNIX}
+  {$IFDEF FPC}
+  {$IFNDEF SKYOS}
+  pthreads,
+  {$ENDIF}
+  baseunix,
+  {$IFNDEF GP2X}
+  {$IFNDEF DARWIN}
+  {$IFNDEF SKYOS}
+  unix,
+  {$ELSE}
+  unix;
+  {$ENDIF}
+  {$ELSE}
+  unix;
+  {$ENDIF}
+  {$ELSE}
+  unix;
+  {$ENDIF}
+  {$IFNDEF GP2X}
+  {$IFNDEF DARWIN}
+  {$IFNDEF SKYOS}
+  x,
+  xlib;
+  {$ENDIF}
+  {$ENDIF}
+  {$ENDIF}
+  {$ELSE}
+  Libc,
+  Xlib;
+  {$ENDIF}
+{$ENDIF}
+
+{$IFDEF __MACH__}
+  GPCMacOSAll;
+{$ENDIF}
+
+{$ifndef FPC}
+type
+  PtrInt = LongInt;
+  PtrUInt = LongWord;
+{$endif}
+
+const
+{$IFDEF WINDOWS}
+  SDLLibName = 'SDL.dll';
+{$ENDIF}
+
+{$IFDEF UNIX}
+{$IFDEF DARWIN}
+  SDLLibName = 'libSDL-1.2.0.dylib';
+  {$linklib libSDL-1.2.0}
+//  {$linklib gcc}
+  {$linklib SDLmain}
+  {$linkframework Cocoa}
+  {$PASCALMAINNAME SDL_main}
+{$ELSE}
+  {$IFDEF FPC}
+  SDLLibName = 'libSDL.so';
+  {$ELSE}
+  SDLLibName = 'libSDL-1.2.so.0';
+  {$ENDIF}
+{$ENDIF}
+{$ENDIF}
+
+{$IFDEF MACOS}
+  SDLLibName = 'SDL';
+  {$linklib libSDL}
+{$ENDIF}
+
+{$IFDEF NDS}
+  SDLLibName = 'libSDL.a';
+  {$linklib libSDL.a}
+  {$linklib libnds9.a}
+  {$linklib libc.a}
+  {$linklib libgcc.a}
+  {$linklib libsysbase.a}
+{$ENDIF}
+
+  // SDL_verion.h constants
+  // Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
+  SDL_MAJOR_VERSION = 1;
+{$EXTERNALSYM SDL_MAJOR_VERSION}
+  SDL_MINOR_VERSION = 2;
+{$EXTERNALSYM SDL_MINOR_VERSION}
+  SDL_PATCHLEVEL    = 13;
+{$EXTERNALSYM SDL_PATCHLEVEL}
+
+  // SDL.h constants
+  SDL_INIT_TIMER = $00000001;
+{$EXTERNALSYM SDL_INIT_TIMER}
+  SDL_INIT_AUDIO = $00000010;
+{$EXTERNALSYM SDL_INIT_AUDIO}
+  SDL_INIT_VIDEO = $00000020;
+{$EXTERNALSYM SDL_INIT_VIDEO}
+  SDL_INIT_CDROM = $00000100;
+{$EXTERNALSYM SDL_INIT_CDROM}
+  SDL_INIT_JOYSTICK = $00000200;
+{$EXTERNALSYM SDL_INIT_JOYSTICK}
+  SDL_INIT_NOPARACHUTE = $00100000; // Don't catch fatal signals
+{$EXTERNALSYM SDL_INIT_NOPARACHUTE}
+  SDL_INIT_EVENTTHREAD = $01000000; // Not supported on all OS's
+{$EXTERNALSYM SDL_INIT_EVENTTHREAD}
+  SDL_INIT_EVERYTHING = $0000FFFF;
+{$EXTERNALSYM SDL_INIT_EVERYTHING}
+
+  // SDL_error.h constants
+  ERR_MAX_STRLEN = 128;
+{$EXTERNALSYM ERR_MAX_STRLEN}
+  ERR_MAX_ARGS = 5;
+{$EXTERNALSYM ERR_MAX_ARGS}
+
+  // SDL_types.h constants
+  SDL_PRESSED = $01;
+{$EXTERNALSYM SDL_PRESSED}
+  SDL_RELEASED = $00;
+{$EXTERNALSYM SDL_RELEASED}
+
+  // SDL_timer.h constants
+  // This is the OS scheduler timeslice, in milliseconds
+  SDL_TIMESLICE = 10;
+{$EXTERNALSYM SDL_TIMESLICE}
+  // This is the maximum resolution of the SDL timer on all platforms
+  TIMER_RESOLUTION = 10; // Experimentally determined
+{$EXTERNALSYM TIMER_RESOLUTION}
+
+  // SDL_audio.h constants
+  AUDIO_U8 = $0008; // Unsigned 8-bit samples
+{$EXTERNALSYM AUDIO_U8}
+  AUDIO_S8 = $8008; // Signed 8-bit samples
+{$EXTERNALSYM AUDIO_S8}
+  AUDIO_U16LSB = $0010; // Unsigned 16-bit samples
+{$EXTERNALSYM AUDIO_U16LSB}
+  AUDIO_S16LSB = $8010; // Signed 16-bit samples
+{$EXTERNALSYM AUDIO_S16LSB}
+  AUDIO_U16MSB = $1010; // As above, but big-endian byte order
+{$EXTERNALSYM AUDIO_U16MSB}
+  AUDIO_S16MSB = $9010; // As above, but big-endian byte order
+{$EXTERNALSYM AUDIO_S16MSB}
+  AUDIO_U16 = AUDIO_U16LSB;
+{$EXTERNALSYM AUDIO_U16}
+  AUDIO_S16 = AUDIO_S16LSB;
+{$EXTERNALSYM AUDIO_S16}
+
+
+  // SDL_cdrom.h constants
+  // The maximum number of CD-ROM tracks on a disk
+  SDL_MAX_TRACKS = 99;
+{$EXTERNALSYM SDL_MAX_TRACKS}
+  // The types of CD-ROM track possible
+  SDL_AUDIO_TRACK = $00;
+{$EXTERNALSYM SDL_AUDIO_TRACK}
+  SDL_DATA_TRACK = $04;
+{$EXTERNALSYM SDL_DATA_TRACK}
+
+  // Conversion functions from frames to Minute/Second/Frames and vice versa
+  CD_FPS = 75;
+{$EXTERNALSYM CD_FPS}
+  // SDL_byteorder.h constants
+  // The two types of endianness
+  SDL_LIL_ENDIAN = 1234;
+{$EXTERNALSYM SDL_LIL_ENDIAN}
+  SDL_BIG_ENDIAN = 4321;
+{$EXTERNALSYM SDL_BIG_ENDIAN}
+
+{$IFDEF IA32}
+
+  SDL_BYTEORDER = SDL_LIL_ENDIAN;
+{$EXTERNALSYM SDL_BYTEORDER}
+  // Native audio byte ordering
+  AUDIO_U16SYS = AUDIO_U16LSB;
+{$EXTERNALSYM AUDIO_U16SYS}
+  AUDIO_S16SYS = AUDIO_S16LSB;
+{$EXTERNALSYM AUDIO_S16SYS}
+
+{$ELSE}
+
+  SDL_BYTEORDER = SDL_BIG_ENDIAN;
+{$EXTERNALSYM SDL_BYTEORDER}
+  // Native audio byte ordering
+  AUDIO_U16SYS = AUDIO_U16MSB;
+{$EXTERNALSYM AUDIO_U16SYS}
+  AUDIO_S16SYS = AUDIO_S16MSB;
+{$EXTERNALSYM AUDIO_S16SYS}
+
+{$ENDIF}
+
+
+  SDL_MIX_MAXVOLUME = 128;
+{$EXTERNALSYM SDL_MIX_MAXVOLUME}
+
+  // SDL_joystick.h constants
+  MAX_JOYSTICKS = 2; // only 2 are supported in the multimedia API
+{$EXTERNALSYM MAX_JOYSTICKS}
+  MAX_AXES = 6; // each joystick can have up to 6 axes
+{$EXTERNALSYM MAX_AXES}
+  MAX_BUTTONS = 32; // and 32 buttons
+{$EXTERNALSYM MAX_BUTTONS}
+  AXIS_MIN = -32768; // minimum value for axis coordinate
+{$EXTERNALSYM AXIS_MIN}
+  AXIS_MAX = 32767; // maximum value for axis coordinate
+{$EXTERNALSYM AXIS_MAX}
+  JOY_AXIS_THRESHOLD = (((AXIS_MAX) - (AXIS_MIN)) / 100); // 1% motion
+{$EXTERNALSYM JOY_AXIS_THRESHOLD}
+  //JOY_BUTTON_FLAG(n)        (1<<n)
+  // array to hold joystick ID values
+  //static UInt        SYS_JoystickID[MAX_JOYSTICKS];
+  //static JOYCAPS        SYS_Joystick[MAX_JOYSTICKS];
+
+  { Get the current state of a POV hat on a joystick
+    The return value is one of the following positions: }
+  SDL_HAT_CENTERED = $00;
+{$EXTERNALSYM SDL_HAT_CENTERED}
+  SDL_HAT_UP = $01;
+{$EXTERNALSYM SDL_HAT_UP}
+  SDL_HAT_RIGHT = $02;
+{$EXTERNALSYM SDL_HAT_RIGHT}
+  SDL_HAT_DOWN = $04;
+{$EXTERNALSYM SDL_HAT_DOWN}
+  SDL_HAT_LEFT = $08;
+{$EXTERNALSYM SDL_HAT_LEFT}
+  SDL_HAT_RIGHTUP = SDL_HAT_RIGHT or SDL_HAT_UP;
+{$EXTERNALSYM SDL_HAT_RIGHTUP}
+  SDL_HAT_RIGHTDOWN = SDL_HAT_RIGHT or SDL_HAT_DOWN;
+{$EXTERNALSYM SDL_HAT_RIGHTDOWN}
+  SDL_HAT_LEFTUP = SDL_HAT_LEFT or SDL_HAT_UP;
+{$EXTERNALSYM SDL_HAT_LEFTUP}
+  SDL_HAT_LEFTDOWN = SDL_HAT_LEFT or SDL_HAT_DOWN;
+{$EXTERNALSYM SDL_HAT_LEFTDOWN}
+
+  // SDL_events.h constants
+  SDL_NOEVENT = 0; // Unused (do not remove)
+{$EXTERNALSYM SDL_NOEVENT}
+  SDL_ACTIVEEVENT = 1; // Application loses/gains visibility
+{$EXTERNALSYM SDL_ACTIVEEVENT}
+  SDL_KEYDOWN = 2; // Keys pressed
+{$EXTERNALSYM SDL_KEYDOWN}
+  SDL_KEYUP = 3; // Keys released
+{$EXTERNALSYM SDL_KEYUP}
+  SDL_MOUSEMOTION = 4; // Mouse moved
+{$EXTERNALSYM SDL_MOUSEMOTION}
+  SDL_MOUSEBUTTONDOWN = 5; // Mouse button pressed
+{$EXTERNALSYM SDL_MOUSEBUTTONDOWN}
+  SDL_MOUSEBUTTONUP = 6; // Mouse button released
+{$EXTERNALSYM SDL_MOUSEBUTTONUP}
+  SDL_JOYAXISMOTION = 7; // Joystick axis motion
+{$EXTERNALSYM SDL_JOYAXISMOTION}
+  SDL_JOYBALLMOTION = 8; // Joystick trackball motion
+{$EXTERNALSYM SDL_JOYBALLMOTION}
+  SDL_JOYHATMOTION = 9; // Joystick hat position change
+{$EXTERNALSYM SDL_JOYHATMOTION}
+  SDL_JOYBUTTONDOWN = 10; // Joystick button pressed
+{$EXTERNALSYM SDL_JOYBUTTONDOWN}
+  SDL_JOYBUTTONUP = 11; // Joystick button released
+{$EXTERNALSYM SDL_JOYBUTTONUP}
+  SDL_QUITEV = 12; // User-requested quit ( Changed due to procedure conflict )
+{$EXTERNALSYM SDL_QUIT}
+  SDL_SYSWMEVENT = 13; // System specific event
+{$EXTERNALSYM SDL_SYSWMEVENT}
+  SDL_EVENT_RESERVEDA = 14; // Reserved for future use..
+{$EXTERNALSYM SDL_EVENT_RESERVEDA}
+  SDL_EVENT_RESERVED = 15; // Reserved for future use..
+{$EXTERNALSYM SDL_EVENT_RESERVED}
+  SDL_VIDEORESIZE = 16; // User resized video mode
+{$EXTERNALSYM SDL_VIDEORESIZE}
+  SDL_VIDEOEXPOSE = 17; // Screen needs to be redrawn
+{$EXTERNALSYM SDL_VIDEOEXPOSE}
+  SDL_EVENT_RESERVED2 = 18; // Reserved for future use..
+{$EXTERNALSYM SDL_EVENT_RESERVED2}
+  SDL_EVENT_RESERVED3 = 19; // Reserved for future use..
+{$EXTERNALSYM SDL_EVENT_RESERVED3}
+  SDL_EVENT_RESERVED4 = 20; // Reserved for future use..
+{$EXTERNALSYM SDL_EVENT_RESERVED4}
+  SDL_EVENT_RESERVED5 = 21; // Reserved for future use..
+{$EXTERNALSYM SDL_EVENT_RESERVED5}
+  SDL_EVENT_RESERVED6 = 22; // Reserved for future use..
+{$EXTERNALSYM SDL_EVENT_RESERVED6}
+  SDL_EVENT_RESERVED7 = 23; // Reserved for future use..
+{$EXTERNALSYM SDL_EVENT_RESERVED7}
+  // Events SDL_USEREVENT through SDL_MAXEVENTS-1 are for your use
+  SDL_USEREVENT = 24;
+{$EXTERNALSYM SDL_USEREVENT}
+  // This last event is only for bounding internal arrays
+  // It is the number of bits in the event mask datatype -- UInt32
+  SDL_NUMEVENTS = 32;
+{$EXTERNALSYM SDL_NUMEVENTS}
+
+  SDL_ALLEVENTS = $FFFFFFFF;
+{$EXTERNALSYM SDL_ALLEVENTS}
+
+  SDL_ACTIVEEVENTMASK = 1 shl SDL_ACTIVEEVENT;
+{$EXTERNALSYM SDL_ACTIVEEVENTMASK}
+  SDL_KEYDOWNMASK = 1 shl SDL_KEYDOWN;
+{$EXTERNALSYM SDL_KEYDOWNMASK}
+  SDL_KEYUPMASK = 1 shl SDL_KEYUP;
+{$EXTERNALSYM SDL_KEYUPMASK}
+  SDL_MOUSEMOTIONMASK = 1 shl SDL_MOUSEMOTION;
+{$EXTERNALSYM SDL_MOUSEMOTIONMASK}
+  SDL_MOUSEBUTTONDOWNMASK = 1 shl SDL_MOUSEBUTTONDOWN;
+{$EXTERNALSYM SDL_MOUSEBUTTONDOWNMASK}
+  SDL_MOUSEBUTTONUPMASK = 1 shl SDL_MOUSEBUTTONUP;
+{$EXTERNALSYM SDL_MOUSEBUTTONUPMASK}
+  SDL_MOUSEEVENTMASK = 1 shl SDL_MOUSEMOTION or
+    1 shl SDL_MOUSEBUTTONDOWN or
+    1 shl SDL_MOUSEBUTTONUP;
+{$EXTERNALSYM SDL_MOUSEEVENTMASK}
+  SDL_JOYAXISMOTIONMASK = 1 shl SDL_JOYAXISMOTION;
+{$EXTERNALSYM SDL_JOYAXISMOTIONMASK}
+  SDL_JOYBALLMOTIONMASK = 1 shl SDL_JOYBALLMOTION;
+{$EXTERNALSYM SDL_JOYBALLMOTIONMASK}
+  SDL_JOYHATMOTIONMASK = 1 shl SDL_JOYHATMOTION;
+{$EXTERNALSYM SDL_JOYHATMOTIONMASK}
+  SDL_JOYBUTTONDOWNMASK = 1 shl SDL_JOYBUTTONDOWN;
+{$EXTERNALSYM SDL_JOYBUTTONDOWNMASK}
+  SDL_JOYBUTTONUPMASK = 1 shl SDL_JOYBUTTONUP;
+{$EXTERNALSYM SDL_JOYBUTTONUPMASK}
+  SDL_JOYEVENTMASK = 1 shl SDL_JOYAXISMOTION or
+    1 shl SDL_JOYBALLMOTION or
+    1 shl SDL_JOYHATMOTION or
+    1 shl SDL_JOYBUTTONDOWN or
+    1 shl SDL_JOYBUTTONUP;
+{$EXTERNALSYM SDL_JOYEVENTMASK}
+  SDL_VIDEORESIZEMASK = 1 shl SDL_VIDEORESIZE;
+{$EXTERNALSYM SDL_VIDEORESIZEMASK}
+  SDL_QUITMASK = 1 shl SDL_QUITEV;
+{$EXTERNALSYM SDL_QUITMASK}
+  SDL_SYSWMEVENTMASK = 1 shl SDL_SYSWMEVENT;
+{$EXTERNALSYM SDL_SYSWMEVENTMASK}
+
+  { This function allows you to set the state of processing certain events.
+    If 'state' is set to SDL_IGNORE, that event will be automatically dropped
+    from the event queue and will not event be filtered.
+    If 'state' is set to SDL_ENABLE, that event will be processed normally.
+    If 'state' is set to SDL_QUERY, SDL_EventState() will return the
+    current processing state of the specified event. }
+
+  SDL_QUERY = -1;
+{$EXTERNALSYM SDL_QUERY}
+  SDL_IGNORE = 0;
+{$EXTERNALSYM SDL_IGNORE}
+  SDL_DISABLE = 0;
+{$EXTERNALSYM SDL_DISABLE}
+  SDL_ENABLE = 1;
+{$EXTERNALSYM SDL_ENABLE}
+
+  //SDL_keyboard.h constants
+  // This is the mask which refers to all hotkey bindings
+  SDL_ALL_HOTKEYS = $FFFFFFFF;
+{$EXTERNALSYM SDL_ALL_HOTKEYS}
+
+{ Enable/Disable keyboard repeat.  Keyboard repeat defaults to off.
+  'delay' is the initial delay in ms between the time when a key is
+  pressed, and keyboard repeat begins.
+  'interval' is the time in ms between keyboard repeat events. }
+
+  SDL_DEFAULT_REPEAT_DELAY = 500;
+{$EXTERNALSYM SDL_DEFAULT_REPEAT_DELAY}
+  SDL_DEFAULT_REPEAT_INTERVAL = 30;
+{$EXTERNALSYM SDL_DEFAULT_REPEAT_INTERVAL}
+
+  // The keyboard syms have been cleverly chosen to map to ASCII
+  SDLK_UNKNOWN = 0;
+{$EXTERNALSYM SDLK_UNKNOWN}
+  SDLK_FIRST = 0;
+{$EXTERNALSYM SDLK_FIRST}
+  SDLK_BACKSPACE = 8;
+{$EXTERNALSYM SDLK_BACKSPACE}
+  SDLK_TAB = 9;
+{$EXTERNALSYM SDLK_TAB}
+  SDLK_CLEAR = 12;
+{$EXTERNALSYM SDLK_CLEAR}
+  SDLK_RETURN = 13;
+{$EXTERNALSYM SDLK_RETURN}
+  SDLK_PAUSE = 19;
+{$EXTERNALSYM SDLK_PAUSE}
+  SDLK_ESCAPE = 27;
+{$EXTERNALSYM SDLK_ESCAPE}
+  SDLK_SPACE = 32;
+{$EXTERNALSYM SDLK_SPACE}
+  SDLK_EXCLAIM = 33;
+{$EXTERNALSYM SDLK_EXCLAIM}
+  SDLK_QUOTEDBL = 34;
+{$EXTERNALSYM SDLK_QUOTEDBL}
+  SDLK_HASH = 35;
+{$EXTERNALSYM SDLK_HASH}
+  SDLK_DOLLAR = 36;
+{$EXTERNALSYM SDLK_DOLLAR}
+  SDLK_AMPERSAND = 38;
+{$EXTERNALSYM SDLK_AMPERSAND}
+  SDLK_QUOTE = 39;
+{$EXTERNALSYM SDLK_QUOTE}
+  SDLK_LEFTPAREN = 40;
+{$EXTERNALSYM SDLK_LEFTPAREN}
+  SDLK_RIGHTPAREN = 41;
+{$EXTERNALSYM SDLK_RIGHTPAREN}
+  SDLK_ASTERISK = 42;
+{$EXTERNALSYM SDLK_ASTERISK}
+  SDLK_PLUS = 43;
+{$EXTERNALSYM SDLK_PLUS}
+  SDLK_COMMA = 44;
+{$EXTERNALSYM SDLK_COMMA}
+  SDLK_MINUS = 45;
+{$EXTERNALSYM SDLK_MINUS}
+  SDLK_PERIOD = 46;
+{$EXTERNALSYM SDLK_PERIOD}
+  SDLK_SLASH = 47;
+{$EXTERNALSYM SDLK_SLASH}
+  SDLK_0 = 48;
+{$EXTERNALSYM SDLK_0}
+  SDLK_1 = 49;
+{$EXTERNALSYM SDLK_1}
+  SDLK_2 = 50;
+{$EXTERNALSYM SDLK_2}
+  SDLK_3 = 51;
+{$EXTERNALSYM SDLK_3}
+  SDLK_4 = 52;
+{$EXTERNALSYM SDLK_4}
+  SDLK_5 = 53;
+{$EXTERNALSYM SDLK_5}
+  SDLK_6 = 54;
+{$EXTERNALSYM SDLK_6}
+  SDLK_7 = 55;
+{$EXTERNALSYM SDLK_7}
+  SDLK_8 = 56;
+{$EXTERNALSYM SDLK_8}
+  SDLK_9 = 57;
+{$EXTERNALSYM SDLK_9}
+  SDLK_COLON = 58;
+{$EXTERNALSYM SDLK_COLON}
+  SDLK_SEMICOLON = 59;
+{$EXTERNALSYM SDLK_SEMICOLON}
+  SDLK_LESS = 60;
+{$EXTERNALSYM SDLK_LESS}
+  SDLK_EQUALS = 61;
+{$EXTERNALSYM SDLK_EQUALS}
+  SDLK_GREATER = 62;
+{$EXTERNALSYM SDLK_GREATER}
+  SDLK_QUESTION = 63;
+{$EXTERNALSYM SDLK_QUESTION}
+  SDLK_AT = 64;
+{$EXTERNALSYM SDLK_AT}
+
+  { Skip uppercase letters }
+
+  SDLK_LEFTBRACKET = 91;
+{$EXTERNALSYM SDLK_LEFTBRACKET}
+  SDLK_BACKSLASH = 92;
+{$EXTERNALSYM SDLK_BACKSLASH}
+  SDLK_RIGHTBRACKET = 93;
+{$EXTERNALSYM SDLK_RIGHTBRACKET}
+  SDLK_CARET = 94;
+{$EXTERNALSYM SDLK_CARET}
+  SDLK_UNDERSCORE = 95;
+{$EXTERNALSYM SDLK_UNDERSCORE}
+  SDLK_BACKQUOTE = 96;
+{$EXTERNALSYM SDLK_BACKQUOTE}
+  SDLK_a = 97;
+{$EXTERNALSYM SDLK_a}
+  SDLK_b = 98;
+{$EXTERNALSYM SDLK_b}
+  SDLK_c = 99;
+{$EXTERNALSYM SDLK_c}
+  SDLK_d = 100;
+{$EXTERNALSYM SDLK_d}
+  SDLK_e = 101;
+{$EXTERNALSYM SDLK_e}
+  SDLK_f = 102;
+{$EXTERNALSYM SDLK_f}
+  SDLK_g = 103;
+{$EXTERNALSYM SDLK_g}
+  SDLK_h = 104;
+{$EXTERNALSYM SDLK_h}
+  SDLK_i = 105;
+{$EXTERNALSYM SDLK_i}
+  SDLK_j = 106;
+{$EXTERNALSYM SDLK_j}
+  SDLK_k = 107;
+{$EXTERNALSYM SDLK_k}
+  SDLK_l = 108;
+{$EXTERNALSYM SDLK_l}
+  SDLK_m = 109;
+{$EXTERNALSYM SDLK_m}
+  SDLK_n = 110;
+{$EXTERNALSYM SDLK_n}
+  SDLK_o = 111;
+{$EXTERNALSYM SDLK_o}
+  SDLK_p = 112;
+{$EXTERNALSYM SDLK_p}
+  SDLK_q = 113;
+{$EXTERNALSYM SDLK_q}
+  SDLK_r = 114;
+{$EXTERNALSYM SDLK_r}
+  SDLK_s = 115;
+{$EXTERNALSYM SDLK_s}
+  SDLK_t = 116;
+{$EXTERNALSYM SDLK_t}
+  SDLK_u = 117;
+{$EXTERNALSYM SDLK_u}
+  SDLK_v = 118;
+{$EXTERNALSYM SDLK_v}
+  SDLK_w = 119;
+{$EXTERNALSYM SDLK_w}
+  SDLK_x = 120;
+{$EXTERNALSYM SDLK_x}
+  SDLK_y = 121;
+{$EXTERNALSYM SDLK_y}
+  SDLK_z = 122;
+{$EXTERNALSYM SDLK_z}
+  SDLK_DELETE = 127;
+{$EXTERNALSYM SDLK_DELETE}
+  // End of ASCII mapped keysyms
+
+  // International keyboard syms
+  SDLK_WORLD_0 = 160; // 0xA0
+{$EXTERNALSYM SDLK_WORLD_0}
+  SDLK_WORLD_1 = 161;
+{$EXTERNALSYM SDLK_WORLD_1}
+  SDLK_WORLD_2 = 162;
+{$EXTERNALSYM SDLK_WORLD_2}
+  SDLK_WORLD_3 = 163;
+{$EXTERNALSYM SDLK_WORLD_3}
+  SDLK_WORLD_4 = 164;
+{$EXTERNALSYM SDLK_WORLD_4}
+  SDLK_WORLD_5 = 165;
+{$EXTERNALSYM SDLK_WORLD_5}
+  SDLK_WORLD_6 = 166;
+{$EXTERNALSYM SDLK_WORLD_6}
+  SDLK_WORLD_7 = 167;
+{$EXTERNALSYM SDLK_WORLD_7}
+  SDLK_WORLD_8 = 168;
+{$EXTERNALSYM SDLK_WORLD_8}
+  SDLK_WORLD_9 = 169;
+{$EXTERNALSYM SDLK_WORLD_9}
+  SDLK_WORLD_10 = 170;
+{$EXTERNALSYM SDLK_WORLD_10}
+  SDLK_WORLD_11 = 171;
+{$EXTERNALSYM SDLK_WORLD_11}
+  SDLK_WORLD_12 = 172;
+{$EXTERNALSYM SDLK_WORLD_12}
+  SDLK_WORLD_13 = 173;
+{$EXTERNALSYM SDLK_WORLD_13}
+  SDLK_WORLD_14 = 174;
+{$EXTERNALSYM SDLK_WORLD_14}
+  SDLK_WORLD_15 = 175;
+{$EXTERNALSYM SDLK_WORLD_15}
+  SDLK_WORLD_16 = 176;
+{$EXTERNALSYM SDLK_WORLD_16}
+  SDLK_WORLD_17 = 177;
+{$EXTERNALSYM SDLK_WORLD_17}
+  SDLK_WORLD_18 = 178;
+{$EXTERNALSYM SDLK_WORLD_18}
+  SDLK_WORLD_19 = 179;
+{$EXTERNALSYM SDLK_WORLD_19}
+  SDLK_WORLD_20 = 180;
+{$EXTERNALSYM SDLK_WORLD_20}
+  SDLK_WORLD_21 = 181;
+{$EXTERNALSYM SDLK_WORLD_21}
+  SDLK_WORLD_22 = 182;
+{$EXTERNALSYM SDLK_WORLD_22}
+  SDLK_WORLD_23 = 183;
+{$EXTERNALSYM SDLK_WORLD_23}
+  SDLK_WORLD_24 = 184;
+{$EXTERNALSYM SDLK_WORLD_24}
+  SDLK_WORLD_25 = 185;
+{$EXTERNALSYM SDLK_WORLD_25}
+  SDLK_WORLD_26 = 186;
+{$EXTERNALSYM SDLK_WORLD_26}
+  SDLK_WORLD_27 = 187;
+{$EXTERNALSYM SDLK_WORLD_27}
+  SDLK_WORLD_28 = 188;
+{$EXTERNALSYM SDLK_WORLD_28}
+  SDLK_WORLD_29 = 189;
+{$EXTERNALSYM SDLK_WORLD_29}
+  SDLK_WORLD_30 = 190;
+{$EXTERNALSYM SDLK_WORLD_30}
+  SDLK_WORLD_31 = 191;
+{$EXTERNALSYM SDLK_WORLD_31}
+  SDLK_WORLD_32 = 192;
+{$EXTERNALSYM SDLK_WORLD_32}
+  SDLK_WORLD_33 = 193;
+{$EXTERNALSYM SDLK_WORLD_33}
+  SDLK_WORLD_34 = 194;
+{$EXTERNALSYM SDLK_WORLD_34}
+  SDLK_WORLD_35 = 195;
+{$EXTERNALSYM SDLK_WORLD_35}
+  SDLK_WORLD_36 = 196;
+{$EXTERNALSYM SDLK_WORLD_36}
+  SDLK_WORLD_37 = 197;
+{$EXTERNALSYM SDLK_WORLD_37}
+  SDLK_WORLD_38 = 198;
+{$EXTERNALSYM SDLK_WORLD_38}
+  SDLK_WORLD_39 = 199;
+{$EXTERNALSYM SDLK_WORLD_39}
+  SDLK_WORLD_40 = 200;
+{$EXTERNALSYM SDLK_WORLD_40}
+  SDLK_WORLD_41 = 201;
+{$EXTERNALSYM SDLK_WORLD_41}
+  SDLK_WORLD_42 = 202;
+{$EXTERNALSYM SDLK_WORLD_42}
+  SDLK_WORLD_43 = 203;
+{$EXTERNALSYM SDLK_WORLD_43}
+  SDLK_WORLD_44 = 204;
+{$EXTERNALSYM SDLK_WORLD_44}
+  SDLK_WORLD_45 = 205;
+{$EXTERNALSYM SDLK_WORLD_45}
+  SDLK_WORLD_46 = 206;
+{$EXTERNALSYM SDLK_WORLD_46}
+  SDLK_WORLD_47 = 207;
+{$EXTERNALSYM SDLK_WORLD_47}
+  SDLK_WORLD_48 = 208;
+{$EXTERNALSYM SDLK_WORLD_48}
+  SDLK_WORLD_49 = 209;
+{$EXTERNALSYM SDLK_WORLD_49}
+  SDLK_WORLD_50 = 210;
+{$EXTERNALSYM SDLK_WORLD_50}
+  SDLK_WORLD_51 = 211;
+{$EXTERNALSYM SDLK_WORLD_51}
+  SDLK_WORLD_52 = 212;
+{$EXTERNALSYM SDLK_WORLD_52}
+  SDLK_WORLD_53 = 213;
+{$EXTERNALSYM SDLK_WORLD_53}
+  SDLK_WORLD_54 = 214;
+{$EXTERNALSYM SDLK_WORLD_54}
+  SDLK_WORLD_55 = 215;
+{$EXTERNALSYM SDLK_WORLD_55}
+  SDLK_WORLD_56 = 216;
+{$EXTERNALSYM SDLK_WORLD_56}
+  SDLK_WORLD_57 = 217;
+{$EXTERNALSYM SDLK_WORLD_57}
+  SDLK_WORLD_58 = 218;
+{$EXTERNALSYM SDLK_WORLD_58}
+  SDLK_WORLD_59 = 219;
+{$EXTERNALSYM SDLK_WORLD_59}
+  SDLK_WORLD_60 = 220;
+{$EXTERNALSYM SDLK_WORLD_60}
+  SDLK_WORLD_61 = 221;
+{$EXTERNALSYM SDLK_WORLD_61}
+  SDLK_WORLD_62 = 222;
+{$EXTERNALSYM SDLK_WORLD_62}
+  SDLK_WORLD_63 = 223;
+{$EXTERNALSYM SDLK_WORLD_63}
+  SDLK_WORLD_64 = 224;
+{$EXTERNALSYM SDLK_WORLD_64}
+  SDLK_WORLD_65 = 225;
+{$EXTERNALSYM SDLK_WORLD_65}
+  SDLK_WORLD_66 = 226;
+{$EXTERNALSYM SDLK_WORLD_66}
+  SDLK_WORLD_67 = 227;
+{$EXTERNALSYM SDLK_WORLD_67}
+  SDLK_WORLD_68 = 228;
+{$EXTERNALSYM SDLK_WORLD_68}
+  SDLK_WORLD_69 = 229;
+{$EXTERNALSYM SDLK_WORLD_69}
+  SDLK_WORLD_70 = 230;
+{$EXTERNALSYM SDLK_WORLD_70}
+  SDLK_WORLD_71 = 231;
+{$EXTERNALSYM SDLK_WORLD_71}
+  SDLK_WORLD_72 = 232;
+{$EXTERNALSYM SDLK_WORLD_72}
+  SDLK_WORLD_73 = 233;
+{$EXTERNALSYM SDLK_WORLD_73}
+  SDLK_WORLD_74 = 234;
+{$EXTERNALSYM SDLK_WORLD_74}
+  SDLK_WORLD_75 = 235;
+{$EXTERNALSYM SDLK_WORLD_75}
+  SDLK_WORLD_76 = 236;
+{$EXTERNALSYM SDLK_WORLD_76}
+  SDLK_WORLD_77 = 237;
+{$EXTERNALSYM SDLK_WORLD_77}
+  SDLK_WORLD_78 = 238;
+{$EXTERNALSYM SDLK_WORLD_78}
+  SDLK_WORLD_79 = 239;
+{$EXTERNALSYM SDLK_WORLD_79}
+  SDLK_WORLD_80 = 240;
+{$EXTERNALSYM SDLK_WORLD_80}
+  SDLK_WORLD_81 = 241;
+{$EXTERNALSYM SDLK_WORLD_81}
+  SDLK_WORLD_82 = 242;
+{$EXTERNALSYM SDLK_WORLD_82}
+  SDLK_WORLD_83 = 243;
+{$EXTERNALSYM SDLK_WORLD_83}
+  SDLK_WORLD_84 = 244;
+{$EXTERNALSYM SDLK_WORLD_84}
+  SDLK_WORLD_85 = 245;
+{$EXTERNALSYM SDLK_WORLD_85}
+  SDLK_WORLD_86 = 246;
+{$EXTERNALSYM SDLK_WORLD_86}
+  SDLK_WORLD_87 = 247;
+{$EXTERNALSYM SDLK_WORLD_87}
+  SDLK_WORLD_88 = 248;
+{$EXTERNALSYM SDLK_WORLD_88}
+  SDLK_WORLD_89 = 249;
+{$EXTERNALSYM SDLK_WORLD_89}
+  SDLK_WORLD_90 = 250;
+{$EXTERNALSYM SDLK_WORLD_90}
+  SDLK_WORLD_91 = 251;
+{$EXTERNALSYM SDLK_WORLD_91}
+  SDLK_WORLD_92 = 252;
+{$EXTERNALSYM SDLK_WORLD_92}
+  SDLK_WORLD_93 = 253;
+{$EXTERNALSYM SDLK_WORLD_93}
+  SDLK_WORLD_94 = 254;
+{$EXTERNALSYM SDLK_WORLD_94}
+  SDLK_WORLD_95 = 255; // 0xFF
+{$EXTERNALSYM SDLK_WORLD_95}
+
+  // Numeric keypad
+  SDLK_KP0 = 256;
+{$EXTERNALSYM SDLK_KP0}
+  SDLK_KP1 = 257;
+{$EXTERNALSYM SDLK_KP1}
+  SDLK_KP2 = 258;
+{$EXTERNALSYM SDLK_KP2}
+  SDLK_KP3 = 259;
+{$EXTERNALSYM SDLK_KP3}
+  SDLK_KP4 = 260;
+{$EXTERNALSYM SDLK_KP4}
+  SDLK_KP5 = 261;
+{$EXTERNALSYM SDLK_KP5}
+  SDLK_KP6 = 262;
+{$EXTERNALSYM SDLK_KP6}
+  SDLK_KP7 = 263;
+{$EXTERNALSYM SDLK_KP7}
+  SDLK_KP8 = 264;
+{$EXTERNALSYM SDLK_KP8}
+  SDLK_KP9 = 265;
+{$EXTERNALSYM SDLK_KP9}
+  SDLK_KP_PERIOD = 266;
+{$EXTERNALSYM SDLK_KP_PERIOD}
+  SDLK_KP_DIVIDE = 267;
+{$EXTERNALSYM SDLK_KP_DIVIDE}
+  SDLK_KP_MULTIPLY = 268;
+{$EXTERNALSYM SDLK_KP_MULTIPLY}
+  SDLK_KP_MINUS = 269;
+{$EXTERNALSYM SDLK_KP_MINUS}
+  SDLK_KP_PLUS = 270;
+{$EXTERNALSYM SDLK_KP_PLUS}
+  SDLK_KP_ENTER = 271;
+{$EXTERNALSYM SDLK_KP_ENTER}
+  SDLK_KP_EQUALS = 272;
+{$EXTERNALSYM SDLK_KP_EQUALS}
+
+  // Arrows + Home/End pad
+  SDLK_UP = 273;
+{$EXTERNALSYM SDLK_UP}
+  SDLK_DOWN = 274;
+{$EXTERNALSYM SDLK_DOWN}
+  SDLK_RIGHT = 275;
+{$EXTERNALSYM SDLK_RIGHT}
+  SDLK_LEFT = 276;
+{$EXTERNALSYM SDLK_LEFT}
+  SDLK_INSERT = 277;
+{$EXTERNALSYM SDLK_INSERT}
+  SDLK_HOME = 278;
+{$EXTERNALSYM SDLK_HOME}
+  SDLK_END = 279;
+{$EXTERNALSYM SDLK_END}
+  SDLK_PAGEUP = 280;
+{$EXTERNALSYM SDLK_PAGEUP}
+  SDLK_PAGEDOWN = 281;
+{$EXTERNALSYM SDLK_PAGEDOWN}
+
+  // Function keys
+  SDLK_F1 = 282;
+{$EXTERNALSYM SDLK_F1}
+  SDLK_F2 = 283;
+{$EXTERNALSYM SDLK_F2}
+  SDLK_F3 = 284;
+{$EXTERNALSYM SDLK_F3}
+  SDLK_F4 = 285;
+{$EXTERNALSYM SDLK_F4}
+  SDLK_F5 = 286;
+{$EXTERNALSYM SDLK_F5}
+  SDLK_F6 = 287;
+{$EXTERNALSYM SDLK_F6}
+  SDLK_F7 = 288;
+{$EXTERNALSYM SDLK_F7}
+  SDLK_F8 = 289;
+{$EXTERNALSYM SDLK_F8}
+  SDLK_F9 = 290;
+{$EXTERNALSYM SDLK_F9}
+  SDLK_F10 = 291;
+{$EXTERNALSYM SDLK_F10}
+  SDLK_F11 = 292;
+{$EXTERNALSYM SDLK_F11}
+  SDLK_F12 = 293;
+{$EXTERNALSYM SDLK_F12}
+  SDLK_F13 = 294;
+{$EXTERNALSYM SDLK_F13}
+  SDLK_F14 = 295;
+{$EXTERNALSYM SDLK_F14}
+  SDLK_F15 = 296;
+{$EXTERNALSYM SDLK_F15}
+
+  // Key state modifier keys
+  SDLK_NUMLOCK = 300;
+{$EXTERNALSYM SDLK_NUMLOCK}
+  SDLK_CAPSLOCK = 301;
+{$EXTERNALSYM SDLK_CAPSLOCK}
+  SDLK_SCROLLOCK = 302;
+{$EXTERNALSYM SDLK_SCROLLOCK}
+  SDLK_RSHIFT = 303;
+{$EXTERNALSYM SDLK_RSHIFT}
+  SDLK_LSHIFT = 304;
+{$EXTERNALSYM SDLK_LSHIFT}
+  SDLK_RCTRL = 305;
+{$EXTERNALSYM SDLK_RCTRL}
+  SDLK_LCTRL = 306;
+{$EXTERNALSYM SDLK_LCTRL}
+  SDLK_RALT = 307;
+{$EXTERNALSYM SDLK_RALT}
+  SDLK_LALT = 308;
+{$EXTERNALSYM SDLK_LALT}
+  SDLK_RMETA = 309;
+{$EXTERNALSYM SDLK_RMETA}
+  SDLK_LMETA = 310;
+{$EXTERNALSYM SDLK_LMETA}
+  SDLK_LSUPER = 311; // Left "Windows" key
+{$EXTERNALSYM SDLK_LSUPER}
+  SDLK_RSUPER = 312; // Right "Windows" key
+{$EXTERNALSYM SDLK_RSUPER}
+  SDLK_MODE = 313; // "Alt Gr" key
+{$EXTERNALSYM SDLK_MODE}
+  SDLK_COMPOSE = 314; // Multi-key compose key
+{$EXTERNALSYM SDLK_COMPOSE}
+
+  // Miscellaneous function keys
+  SDLK_HELP = 315;
+{$EXTERNALSYM SDLK_HELP}
+  SDLK_PRINT = 316;
+{$EXTERNALSYM SDLK_PRINT}
+  SDLK_SYSREQ = 317;
+{$EXTERNALSYM SDLK_SYSREQ}
+  SDLK_BREAK = 318;
+{$EXTERNALSYM SDLK_BREAK}
+  SDLK_MENU = 319;
+{$EXTERNALSYM SDLK_MENU}
+  SDLK_POWER = 320; // Power Macintosh power key
+{$EXTERNALSYM SDLK_POWER}
+  SDLK_EURO = 321; // Some european keyboards
+{$EXTERNALSYM SDLK_EURO}
+
+{$IFDEF GP2X}
+SDLK_GP2X_UP = 0;
+{$EXTERNALSYM SDLK_GP2X_UP}
+SDLK_GP2X_UPLEFT = 1;
+{$EXTERNALSYM SDLK_GP2X_UPLEFT}
+SDLK_GP2X_LEFT = 2;
+{$EXTERNALSYM SDLK_GP2X_LEFT}
+SDLK_GP2X_DOWNLEFT = 3;
+{$EXTERNALSYM SDLK_GP2X_DOWNLEFT}
+SDLK_GP2X_DOWN = 4;
+{$EXTERNALSYM SDLK_GP2X_DOWN}
+SDLK_GP2X_DOWNRIGHT = 5;
+{$EXTERNALSYM SDLK_GP2X_DOWNRIGHT}
+SDLK_GP2X_RIGHT = 6;
+{$EXTERNALSYM SDLK_GP2X_RIGHT}
+SDLK_GP2X_UPRIGHT = 7;
+{$EXTERNALSYM SDLK_GP2X_UPRIGHT}
+SDLK_GP2X_START = 8;
+{$EXTERNALSYM SDLK_GP2X_START}
+SDLK_GP2X_SELECT = 9;
+{$EXTERNALSYM SDLK_GP2X_SELECT}
+SDLK_GP2X_L = 10;
+{$EXTERNALSYM SDLK_GP2X_L}
+SDLK_GP2X_R = 11;
+{$EXTERNALSYM SDLK_GP2X_R}
+SDLK_GP2X_A = 12;
+{$EXTERNALSYM SDLK_GP2X_A}
+SDLK_GP2X_B = 13;
+{$EXTERNALSYM SDLK_GP2X_B}
+SDLK_GP2X_Y = 14;
+{$EXTERNALSYM SDLK_GP2X_Y}
+SDLK_GP2X_X = 15;
+{$EXTERNALSYM SDLK_GP2X_X}
+SDLK_GP2X_VOLUP = 16;
+{$EXTERNALSYM SDLK_GP2X_VOLUP}
+SDLK_GP2X_VOLDOWN = 17;
+{$EXTERNALSYM SDLK_GP2X_VOLDOWN}
+SDLK_GP2X_CLICK = 18;
+{$EXTERNALSYM SDLK_GP2X_CLICK}
+{$ENDIF}
+
+  // Enumeration of valid key mods (possibly OR'd together)
+  KMOD_NONE = $0000;
+{$EXTERNALSYM KMOD_NONE}
+  KMOD_LSHIFT = $0001;
+{$EXTERNALSYM KMOD_LSHIFT}
+  KMOD_RSHIFT = $0002;
+{$EXTERNALSYM KMOD_RSHIFT}
+  KMOD_LCTRL = $0040;
+{$EXTERNALSYM KMOD_LCTRL}
+  KMOD_RCTRL = $0080;
+{$EXTERNALSYM KMOD_RCTRL}
+  KMOD_LALT = $0100;
+{$EXTERNALSYM KMOD_LALT}
+  KMOD_RALT = $0200;
+{$EXTERNALSYM KMOD_RALT}
+  KMOD_LMETA = $0400;
+{$EXTERNALSYM KMOD_LMETA}
+  KMOD_RMETA = $0800;
+{$EXTERNALSYM KMOD_RMETA}
+  KMOD_NUM = $1000;
+{$EXTERNALSYM KMOD_NUM}
+  KMOD_CAPS = $2000;
+{$EXTERNALSYM KMOD_CAPS}
+  KMOD_MODE = 44000;
+{$EXTERNALSYM KMOD_MODE}
+  KMOD_RESERVED = $8000;
+{$EXTERNALSYM KMOD_RESERVED}
+
+  KMOD_CTRL = (KMOD_LCTRL or KMOD_RCTRL);
+{$EXTERNALSYM KMOD_CTRL}
+  KMOD_SHIFT = (KMOD_LSHIFT or KMOD_RSHIFT);
+{$EXTERNALSYM KMOD_SHIFT}
+  KMOD_ALT = (KMOD_LALT or KMOD_RALT);
+{$EXTERNALSYM KMOD_ALT}
+  KMOD_META = (KMOD_LMETA or KMOD_RMETA);
+{$EXTERNALSYM KMOD_META}
+
+  //SDL_video.h constants
+  // Transparency definitions: These define alpha as the opacity of a surface */
+  SDL_ALPHA_OPAQUE = 255;
+{$EXTERNALSYM SDL_ALPHA_OPAQUE}
+  SDL_ALPHA_TRANSPARENT = 0;
+{$EXTERNALSYM SDL_ALPHA_TRANSPARENT}
+
+  // These are the currently supported flags for the SDL_surface
+  // Available for SDL_CreateRGBSurface() or SDL_SetVideoMode()
+  SDL_SWSURFACE = $00000000; // Surface is in system memory
+{$EXTERNALSYM SDL_SWSURFACE}
+  SDL_HWSURFACE = $00000001; // Surface is in video memory
+{$EXTERNALSYM SDL_HWSURFACE}
+  SDL_ASYNCBLIT = $00000004; // Use asynchronous blits if possible
+{$EXTERNALSYM SDL_ASYNCBLIT}
+  // Available for SDL_SetVideoMode()
+  SDL_ANYFORMAT = $10000000; // Allow any video depth/pixel-format
+{$EXTERNALSYM SDL_ANYFORMAT}
+  SDL_HWPALETTE = $20000000; // Surface has exclusive palette
+{$EXTERNALSYM SDL_HWPALETTE}
+  SDL_DOUBLEBUF = $40000000; // Set up double-buffered video mode
+{$EXTERNALSYM SDL_DOUBLEBUF}
+  SDL_FULLSCREEN = $80000000; // Surface is a full screen display
+{$EXTERNALSYM SDL_FULLSCREEN}
+  SDL_OPENGL = $00000002; // Create an OpenGL rendering context
+{$EXTERNALSYM SDL_OPENGL}
+  SDL_OPENGLBLIT = $00000002; // Create an OpenGL rendering context
+{$EXTERNALSYM SDL_OPENGLBLIT}
+  SDL_RESIZABLE = $00000010; // This video mode may be resized
+{$EXTERNALSYM SDL_RESIZABLE}
+  SDL_NOFRAME = $00000020; // No window caption or edge frame
+{$EXTERNALSYM SDL_NOFRAME}
+  // Used internally (read-only)
+  SDL_HWACCEL = $00000100; // Blit uses hardware acceleration
+{$EXTERNALSYM SDL_HWACCEL}
+  SDL_SRCCOLORKEY = $00001000; // Blit uses a source color key
+{$EXTERNALSYM SDL_SRCCOLORKEY}
+  SDL_RLEACCELOK = $00002000; // Private flag
+{$EXTERNALSYM SDL_RLEACCELOK}
+  SDL_RLEACCEL = $00004000; // Colorkey blit is RLE accelerated
+{$EXTERNALSYM SDL_RLEACCEL}
+  SDL_SRCALPHA = $00010000; // Blit uses source alpha blending
+{$EXTERNALSYM SDL_SRCALPHA}
+  SDL_SRCCLIPPING = $00100000; // Blit uses source clipping
+{$EXTERNALSYM SDL_SRCCLIPPING}
+  SDL_PREALLOC = $01000000; // Surface uses preallocated memory
+{$EXTERNALSYM SDL_PREALLOC}
+
+  { The most common video overlay formats.
+    For an explanation of these pixel formats, see:
+    http://www.webartz.com/fourcc/indexyuv.htm
+
+   For information on the relationship between color spaces, see:
+   http://www.neuro.sfc.keio.ac.jp/~aly/polygon/info/color-space-faq.html }
+
+  SDL_YV12_OVERLAY = $32315659; // Planar mode: Y + V + U  (3 planes)
+{$EXTERNALSYM SDL_YV12_OVERLAY}
+  SDL_IYUV_OVERLAY = $56555949; // Planar mode: Y + U + V  (3 planes)
+{$EXTERNALSYM SDL_IYUV_OVERLAY}
+  SDL_YUY2_OVERLAY = $32595559; // Packed mode: Y0+U0+Y1+V0 (1 plane)
+{$EXTERNALSYM SDL_YUY2_OVERLAY}
+  SDL_UYVY_OVERLAY = $59565955; // Packed mode: U0+Y0+V0+Y1 (1 plane)
+{$EXTERNALSYM SDL_UYVY_OVERLAY}
+  SDL_YVYU_OVERLAY = $55595659; // Packed mode: Y0+V0+Y1+U0 (1 plane)
+{$EXTERNALSYM SDL_YVYU_OVERLAY}
+
+  // flags for SDL_SetPalette()
+  SDL_LOGPAL = $01;
+{$EXTERNALSYM SDL_LOGPAL}
+  SDL_PHYSPAL = $02;
+{$EXTERNALSYM SDL_PHYSPAL}
+
+  //SDL_mouse.h constants
+  { Used as a mask when testing buttons in buttonstate
+    Button 1:	Left mouse button
+    Button 2:	Middle mouse button
+    Button 3:	Right mouse button
+    Button 4:	Mouse Wheel Up (may also be a real button)
+    Button 5:	Mouse Wheel Down (may also be a real button)
+    Button 6:	Mouse X1 (may also be a real button)
+    Button 7:	Mouse X2 (may also be a real button)
+  }
+  SDL_BUTTON_LEFT      = 1;
+{$EXTERNALSYM SDL_BUTTON_LEFT}
+  SDL_BUTTON_MIDDLE    = 2;
+{$EXTERNALSYM SDL_BUTTON_MIDDLE}
+  SDL_BUTTON_RIGHT     = 3;
+{$EXTERNALSYM SDL_BUTTON_RIGHT}
+  SDL_BUTTON_WHEELUP   = 4;
+{$EXTERNALSYM SDL_BUTTON_WHEELUP}
+  SDL_BUTTON_WHEELDOWN = 5;
+{$EXTERNALSYM SDL_BUTTON_WHEELDOWN}
+  SDL_BUTTON_X1        = 6;
+{$EXTERNALSYM SDL_BUTTON_X1}
+  SDL_BUTTON_X2        = 7;
+{$EXTERNALSYM SDL_BUTTON_X2}
+
+  SDL_BUTTON_LMASK = SDL_PRESSED shl (SDL_BUTTON_LEFT - 1);
+{$EXTERNALSYM SDL_BUTTON_LMASK}
+  SDL_BUTTON_MMASK = SDL_PRESSED shl (SDL_BUTTON_MIDDLE - 1);
+{$EXTERNALSYM SDL_BUTTON_MMASK}
+  SDL_BUTTON_RMASK = SDL_PRESSED shl (SDL_BUTTON_RIGHT - 1);
+{$EXTERNALSYM SDL_BUTTON_RMASK}
+  SDL_BUTTON_X1MASK = SDL_PRESSED shl (SDL_BUTTON_X1 - 1);
+{$EXTERNALSYM SDL_BUTTON_X1MASK}
+  SDL_BUTTON_X2MASK = SDL_PRESSED shl (SDL_BUTTON_X2 - 1);
+{$EXTERNALSYM SDL_BUTTON_X2MASK}
+
+  // SDL_active.h constants
+  // The available application states
+  SDL_APPMOUSEFOCUS = $01; // The app has mouse coverage
+{$EXTERNALSYM SDL_APPMOUSEFOCUS}
+  SDL_APPINPUTFOCUS = $02; // The app has input focus
+{$EXTERNALSYM SDL_APPINPUTFOCUS}
+  SDL_APPACTIVE = $04; // The application is active
+{$EXTERNALSYM SDL_APPACTIVE}
+
+  // SDL_mutex.h constants
+  // Synchronization functions which can time out return this value
+  //  they time out.
+
+  SDL_MUTEX_TIMEDOUT = 1;
+{$EXTERNALSYM SDL_MUTEX_TIMEDOUT}
+
+  // This is the timeout value which corresponds to never time out
+  SDL_MUTEX_MAXWAIT = not Cardinal(0);
+{$EXTERNALSYM SDL_MUTEX_MAXWAIT}
+
+  {TSDL_GrabMode = (
+    SDL_GRAB_QUERY,
+    SDL_GRAB_OFF,
+    SDL_GRAB_ON,
+    SDL_GRAB_FULLSCREEN	); // Used internally}
+  SDL_GRAB_QUERY = -1;
+  SDL_GRAB_OFF   = 0;
+  SDL_GRAB_ON    = 1;
+  //SDL_GRAB_FULLSCREEN // Used internally
+
+type
+  THandle = Cardinal;
+  //SDL_types.h types
+  // Basic data types
+
+  SDL_Bool  = (SDL_FALSE, SDL_TRUE);
+  TSDL_Bool = SDL_Bool;
+
+  PUInt8Array = ^TUInt8Array;
+  PUInt8 = ^UInt8;
+  PPUInt8 = ^PUInt8;
+  UInt8 = Byte;
+{$EXTERNALSYM UInt8}
+  TUInt8Array = array [0..MAXINT shr 1] of UInt8;
+
+  PUInt16 = ^UInt16;
+  UInt16 = word;
+{$EXTERNALSYM UInt16}
+
+  PSInt8 = ^SInt8;
+  SInt8 = Shortint;
+{$EXTERNALSYM SInt8}
+
+  PSInt16 = ^SInt16;
+  SInt16 = smallint;
+{$EXTERNALSYM SInt16}
+
+  PUInt32 = ^UInt32;
+  UInt32 = Cardinal;
+{$EXTERNALSYM UInt32}
+
+  SInt32 = Integer;
+{$EXTERNALSYM SInt32}
+
+  PInt = ^Integer;
+
+  PShortInt = ^ShortInt;
+
+  PUInt64 = ^UInt64;
+  UInt64 = record
+    hi: UInt32;
+    lo: UInt32;
+  end;
+{$EXTERNALSYM UInt64}
+
+  PSInt64 = ^SInt64;
+  SInt64 = record
+    hi: UInt32;
+    lo: UInt32;
+  end;
+{$EXTERNALSYM SInt64}
+
+  TSDL_GrabMode = Integer;
+
+  // SDL_error.h types
+  TSDL_errorcode = (
+    SDL_ENOMEM,
+    SDL_EFREAD,
+    SDL_EFWRITE,
+    SDL_EFSEEK,
+    SDL_LASTERROR);
+
+  SDL_errorcode = TSDL_errorcode;
+{$EXTERNALSYM SDL_errorcode}
+
+  TArg = record
+    case Byte of
+      0: (value_ptr: Pointer);
+      (* #if 0 means: never
+      1 :  ( value_c : Byte );
+      *)
+      2: (value_i: Integer);
+      3: (value_f: double);
+      4: (buf: array[0..ERR_MAX_STRLEN - 1] of Byte);
+  end;
+
+  PSDL_error = ^TSDL_error;
+  TSDL_error = record
+    { This is a numeric value corresponding to the current error }
+    error: Integer;
+
+    { This is a key used to index into a language hashtable containing
+       internationalized versions of the SDL error messages.  If the key
+       is not in the hashtable, or no hashtable is available, the key is
+       used directly as an error message format string. }
+    key: array[0..ERR_MAX_STRLEN - 1] of Byte;
+
+    { These are the arguments for the error functions }
+    argc: Integer;
+    args: array[0..ERR_MAX_ARGS - 1] of TArg;
+  end;
+
+  // SDL_rwops.h types
+  // This is the read/write operation structure -- very basic
+  // some helper types to handle the unions
+  // "packed" is only guessed
+
+  TStdio = record
+    autoclose: Integer;
+   // FILE * is only defined in Kylix so we use a simple Pointer
+    fp: Pointer;
+  end;
+
+  TMem = record
+    base: PUInt8;
+    here: PUInt8;
+    stop: PUInt8;
+  end;
+
+  TUnknown = record
+    data1: Pointer;
+  end;
+
+  // first declare the pointer type
+  PSDL_RWops = ^TSDL_RWops;
+  // now the pointer to function types
+  {$IFNDEF __GPC__}
+  TSeek = function( context: PSDL_RWops; offset: Integer; whence: Integer ): Integer; cdecl;
+  TRead = function( context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer ): Integer;  cdecl;
+  TWrite = function( context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer ): Integer; cdecl;
+  TClose = function( context: PSDL_RWops ): Integer; cdecl;
+  {$ELSE}
+  TSeek = function( context: PSDL_RWops; offset: Integer; whence: Integer ): Integer;
+  TRead = function( context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer ): Integer;
+  TWrite = function( context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer ): Integer;
+  TClose = function( context: PSDL_RWops ): Integer;
+  {$ENDIF}
+  // the variant record itself
+  TSDL_RWops = record
+    seek: TSeek;
+    read: TRead;
+    write: TWrite;
+    close: TClose;
+    // a keyword as name is not allowed
+    type_: UInt32;
+    // be warned! structure alignment may arise at this point
+    case Integer of
+      0: (stdio: TStdio);
+      1: (mem: TMem);
+      2: (unknown: TUnknown);
+  end;
+
+  SDL_RWops = TSDL_RWops;
+{$EXTERNALSYM SDL_RWops}
+
+
+  // SDL_timer.h types
+  // Function prototype for the timer callback function
+  {$IFNDEF __GPC__}
+  TSDL_TimerCallback = function( interval: UInt32 ): UInt32; cdecl;
+  {$ELSE}
+  TSDL_TimerCallback = function( interval: UInt32 ): UInt32;
+  {$ENDIF}
+
+ { New timer API, supports multiple timers
+   Written by Stephane Peter <megastep@lokigames.com> }
+
+ { Function prototype for the new timer callback function.
+   The callback function is passed the current timer interval and returns
+   the next timer interval.  If the returned value is the same as the one
+   passed in, the periodic alarm continues, otherwise a new alarm is
+   scheduled.  If the callback returns 0, the periodic alarm is cancelled. }
+  {$IFNDEF __GPC__}
+  TSDL_NewTimerCallback = function( interval: UInt32; param: Pointer ): UInt32; cdecl;
+  {$ELSE}
+  TSDL_NewTimerCallback = function( interval: UInt32; param: Pointer ): UInt32;
+  {$ENDIF}
+  
+  // Definition of the timer ID type
+  PSDL_TimerID = ^TSDL_TimerID;
+  TSDL_TimerID = record
+    interval: UInt32;
+    callback: TSDL_NewTimerCallback;
+    param: Pointer;
+    last_alarm: UInt32;
+    next: PSDL_TimerID;
+  end;
+
+  {$IFNDEF __GPC__}
+  TSDL_AudioSpecCallback = procedure( userdata: Pointer; stream: PUInt8; len: Integer ); cdecl;
+  {$ELSE}
+  TSDL_AudioSpecCallback = procedure( userdata: Pointer; stream: PUInt8; len: Integer );
+  {$ENDIF}
+
+  // SDL_audio.h types
+  // The calculated values in this structure are calculated by SDL_OpenAudio()
+  PSDL_AudioSpec = ^TSDL_AudioSpec;
+  TSDL_AudioSpec = record
+    freq: Integer; // DSP frequency -- samples per second
+    format: UInt16; // Audio data format
+    channels: UInt8; // Number of channels: 1 mono, 2 stereo
+    silence: UInt8; // Audio buffer silence value (calculated)
+    samples: UInt16; // Audio buffer size in samples
+    padding: UInt16; // Necessary for some compile environments
+    size: UInt32; // Audio buffer size in bytes (calculated)
+    { This function is called when the audio device needs more data.
+      'stream' is a pointer to the audio data buffer
+      'len' is the length of that buffer in bytes.
+      Once the callback returns, the buffer will no longer be valid.
+      Stereo samples are stored in a LRLRLR ordering.}
+    callback: TSDL_AudioSpecCallback;
+    userdata: Pointer;
+  end;
+
+  // A structure to hold a set of audio conversion filters and buffers
+  PSDL_AudioCVT = ^TSDL_AudioCVT;
+
+  PSDL_AudioCVTFilter = ^TSDL_AudioCVTFilter;
+  TSDL_AudioCVTFilter = record
+    cvt: PSDL_AudioCVT;
+    format: UInt16;
+  end;
+
+  PSDL_AudioCVTFilterArray = ^TSDL_AudioCVTFilterArray;
+  TSDL_AudioCVTFilterArray = array[0..9] of PSDL_AudioCVTFilter;
+
+  TSDL_AudioCVT = record
+    needed: Integer; // Set to 1 if conversion possible
+    src_format: UInt16; // Source audio format
+    dst_format: UInt16; // Target audio format
+    rate_incr: double; // Rate conversion increment
+    buf: PUInt8; // Buffer to hold entire audio data
+    len: Integer; // Length of original audio buffer
+    len_cvt: Integer; // Length of converted audio buffer
+    len_mult: Integer; // buffer must be len*len_mult big
+    len_ratio: double; // Given len, final size is len*len_ratio
+    filters: TSDL_AudioCVTFilterArray;
+    filter_index: Integer; // Current audio conversion function
+  end;
+
+  TSDL_Audiostatus = (
+    SDL_AUDIO_STOPPED,
+    SDL_AUDIO_PLAYING,
+    SDL_AUDIO_PAUSED
+    );
+
+  // SDL_cdrom.h types
+  TSDL_CDStatus = (
+    CD_ERROR,
+    CD_TRAYEMPTY,
+    CD_STOPPED,
+    CD_PLAYING,
+    CD_PAUSED );
+
+  PSDL_CDTrack = ^TSDL_CDTrack;
+  TSDL_CDTrack = record
+    id: UInt8; // Track number
+    type_: UInt8; // Data or audio track
+    unused: UInt16;
+    length: UInt32; // Length, in frames, of this track
+    offset: UInt32; // Offset, in frames, from start of disk
+  end;
+
+  // This structure is only current as of the last call to SDL_CDStatus()
+  PSDL_CD = ^TSDL_CD;
+  TSDL_CD = record
+    id: Integer; // Private drive identifier
+    status: TSDL_CDStatus; // Current drive status
+
+    // The rest of this structure is only valid if there's a CD in drive
+    numtracks: Integer; // Number of tracks on disk
+    cur_track: Integer; // Current track position
+    cur_frame: Integer; // Current frame offset within current track
+    track: array[0..SDL_MAX_TRACKS] of TSDL_CDTrack;
+  end;
+
+  //SDL_joystick.h types
+  PTransAxis = ^TTransAxis;
+  TTransAxis = record
+    offset: Integer;
+    scale: single;
+  end;
+
+  // The private structure used to keep track of a joystick
+  PJoystick_hwdata = ^TJoystick_hwdata;
+  TJoystick_hwdata = record
+    // joystick ID
+    id: Integer;
+    // values used to translate device-specific coordinates into  SDL-standard ranges
+    transaxis: array[0..5] of TTransAxis;
+  end;
+
+  PBallDelta = ^TBallDelta;
+  TBallDelta = record
+    dx: Integer;
+    dy: Integer;
+  end; // Current ball motion deltas
+
+  // The SDL joystick structure
+  PSDL_Joystick = ^TSDL_Joystick;
+  TSDL_Joystick = record
+    index: UInt8; // Device index
+    name: PChar; // Joystick name - system dependent
+
+    naxes: Integer; // Number of axis controls on the joystick
+    axes: PUInt16; // Current axis states
+
+    nhats: Integer; // Number of hats on the joystick
+    hats: PUInt8; // Current hat states
+
+    nballs: Integer; // Number of trackballs on the joystick
+    balls: PBallDelta; // Current ball motion deltas
+
+    nbuttons: Integer; // Number of buttons on the joystick
+    buttons: PUInt8; // Current button states
+
+    hwdata: PJoystick_hwdata; // Driver dependent information
+
+    ref_count: Integer; // Reference count for multiple opens
+  end;
+
+  // SDL_verion.h types
+  PSDL_version = ^TSDL_version;
+  TSDL_version = record
+    major: UInt8;
+    minor: UInt8;
+    patch: UInt8;
+  end;
+
+  // SDL_keyboard.h types
+  TSDLKey = LongWord;
+
+  TSDLMod = LongWord;
+
+  PSDL_KeySym = ^TSDL_KeySym;
+  TSDL_KeySym = record
+    scancode: UInt8; // hardware specific scancode
+    sym: TSDLKey; // SDL virtual keysym
+    modifier: TSDLMod; // current key modifiers
+    unicode: UInt16; // translated character
+  end;
+
+  // SDL_events.h types
+  {Checks the event queue for messages and optionally returns them.
+   If 'action' is SDL_ADDEVENT, up to 'numevents' events will be added to
+   the back of the event queue.
+   If 'action' is SDL_PEEKEVENT, up to 'numevents' events at the front
+   of the event queue, matching 'mask', will be returned and will not
+   be removed from the queue.
+   If 'action' is SDL_GETEVENT, up to 'numevents' events at the front
+   of the event queue, matching 'mask', will be returned and will be
+   removed from the queue.
+   This function returns the number of events actually stored, or -1
+   if there was an error.  This function is thread-safe. }
+
+  TSDL_EventAction = (SDL_ADDEVENT, SDL_PEEKEVENT, SDL_GETEVENT);
+
+  // Application visibility event structure
+  TSDL_ActiveEvent = record
+    type_: UInt8; // SDL_ACTIVEEVENT
+    gain: UInt8; // Whether given states were gained or lost (1/0)
+    state: UInt8; // A mask of the focus states
+  end;
+
+  // Keyboard event structure
+  TSDL_KeyboardEvent = record
+    type_: UInt8; // SDL_KEYDOWN or SDL_KEYUP
+    which: UInt8; // The keyboard device index
+    state: UInt8; // SDL_PRESSED or SDL_RELEASED
+    keysym: TSDL_KeySym;
+  end;
+
+  // Mouse motion event structure
+  TSDL_MouseMotionEvent = record
+    type_: UInt8; // SDL_MOUSEMOTION
+    which: UInt8; // The mouse device index
+    state: UInt8; // The current button state
+    x, y: UInt16; // The X/Y coordinates of the mouse
+    xrel: SInt16; // The relative motion in the X direction
+    yrel: SInt16; // The relative motion in the Y direction
+  end;
+
+  // Mouse button event structure
+  TSDL_MouseButtonEvent = record
+    type_: UInt8;  // SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP
+    which: UInt8;  // The mouse device index
+    button: UInt8; // The mouse button index
+    state: UInt8;  // SDL_PRESSED or SDL_RELEASED
+    x: UInt16;     // The X coordinates of the mouse at press time
+    y: UInt16;     // The Y coordinates of the mouse at press time
+  end;
+
+  // Joystick axis motion event structure
+  TSDL_JoyAxisEvent = record
+    type_: UInt8; // SDL_JOYAXISMOTION
+    which: UInt8; // The joystick device index
+    axis: UInt8; // The joystick axis index
+    value: SInt16; // The axis value (range: -32768 to 32767)
+  end;
+
+  // Joystick trackball motion event structure
+  TSDL_JoyBallEvent = record
+    type_: UInt8; // SDL_JOYAVBALLMOTION
+    which: UInt8; // The joystick device index
+    ball: UInt8; // The joystick trackball index
+    xrel: SInt16; // The relative motion in the X direction
+    yrel: SInt16; // The relative motion in the Y direction
+  end;
+
+  // Joystick hat position change event structure
+  TSDL_JoyHatEvent = record
+    type_: UInt8; // SDL_JOYHATMOTION */
+    which: UInt8; // The joystick device index */
+    hat: UInt8; // The joystick hat index */
+    value: UInt8; { The hat position value:
+                    8   1   2
+                    7   0   3
+                    6   5   4
+
+                    Note that zero means the POV is centered. }
+
+  end;
+
+  // Joystick button event structure
+  TSDL_JoyButtonEvent = record
+    type_: UInt8; // SDL_JOYBUTTONDOWN or SDL_JOYBUTTONUP
+    which: UInt8; // The joystick device index
+    button: UInt8; // The joystick button index
+    state: UInt8; // SDL_PRESSED or SDL_RELEASED
+  end;
+
+  { The "window resized" event
+    When you get this event, you are responsible for setting a new video
+    mode with the new width and height. }
+  TSDL_ResizeEvent = record
+    type_: UInt8; // SDL_VIDEORESIZE
+    w: Integer; // New width
+    h: Integer; // New height
+  end;
+
+  // The "quit requested" event
+  PSDL_QuitEvent = ^TSDL_QuitEvent;
+  TSDL_QuitEvent = record
+    type_: UInt8;
+  end;
+
+  // A user-defined event type
+  PSDL_UserEvent = ^TSDL_UserEvent;
+  TSDL_UserEvent = record
+    type_: UInt8; // SDL_USEREVENT through SDL_NUMEVENTS-1
+    code: Integer; // User defined event code */
+    data1: Pointer; // User defined data pointer */
+    data2: Pointer; // User defined data pointer */
+  end;
+
+  // The "screen redraw" event
+  PSDL_ExposeEvent = ^TSDL_ExposeEvent;
+  TSDL_ExposeEvent = record
+    type_ : Uint8;        // SDL_VIDEOEXPOSE
+  end;
+
+ {$IFDEF Unix}
+ //These are the various supported subsystems under UNIX
+  TSDL_SysWm = ( SDL_SYSWM_X11 ) ;
+ {$ENDIF}
+
+// The windows custom event structure
+{$IFDEF WINDOWS}
+  PSDL_SysWMmsg = ^TSDL_SysWMmsg;
+  TSDL_SysWMmsg = record
+    version: TSDL_version;
+    h_wnd: HWND; // The window for the message
+    msg: UInt; // The type of message
+    w_Param: WPARAM; // WORD message parameter
+    lParam: LPARAM; // LONG message parameter
+  end;
+{$ELSE}
+
+{$IFDEF Unix}
+{ The Linux custom event structure }
+  PSDL_SysWMmsg = ^TSDL_SysWMmsg;
+  TSDL_SysWMmsg = record
+    version : TSDL_version;
+    subsystem : TSDL_SysWm;
+    {$IFDEF FPC}
+    {$IFNDEF GP2X}
+    {$IFNDEF DARWIN}
+    {$IFNDEF SKYOS}
+    event : TXEvent;
+    {$ENDIF}
+    {$ENDIF}
+    {$ENDIF}
+    {$ELSE}
+    event : XEvent;
+    {$ENDIF}
+  end;
+{$ELSE}
+{ The generic custom event structure }
+  PSDL_SysWMmsg = ^TSDL_SysWMmsg;
+  TSDL_SysWMmsg = record
+    version: TSDL_version;
+    data: Integer;
+  end;
+{$ENDIF}
+
+{$ENDIF}
+
+// The Windows custom window manager information structure
+{$IFDEF WINDOWS}
+  PSDL_SysWMinfo = ^TSDL_SysWMinfo;
+  TSDL_SysWMinfo = record
+    version : TSDL_version;
+    window : HWnd;	// The display window
+  end;
+{$ELSE}
+
+// The Linux custom window manager information structure
+{$IFDEF Unix}
+  {$IFNDEF GP2X}
+  {$IFNDEF DARWIN}
+  {$IFNDEF SKYOS}
+  TX11 = record
+    display : PDisplay;	// The X11 display
+    window : TWindow ;		// The X11 display window */
+    {* These locking functions should be called around
+       any X11 functions using the display variable.
+       They lock the event thread, so should not be
+       called around event functions or from event filters.
+     *}
+    lock_func : Pointer;
+    unlock_func : Pointer;
+
+    // Introduced in SDL 1.0.2
+    fswindow : TWindow ;	// The X11 fullscreen window */
+    wmwindow : TWindow ;	// The X11 managed input window */
+  end;
+  {$ENDIF}
+  {$ENDIF}
+  {$ENDIF}
+  
+  PSDL_SysWMinfo = ^TSDL_SysWMinfo;
+  TSDL_SysWMinfo = record
+     version : TSDL_version ;
+     subsystem : TSDL_SysWm;
+     {$IFNDEF GP2X}
+     {$IFNDEF DARWIN}
+     {$IFNDEF SKYOS}
+     X11 : TX11;
+     {$ENDIF}
+     {$ENDIF}
+     {$ENDIF}
+  end;
+{$ELSE}
+  // The generic custom window manager information structure
+  PSDL_SysWMinfo = ^TSDL_SysWMinfo;
+  TSDL_SysWMinfo = record
+    version : TSDL_version ;
+    data : integer;
+  end;
+{$ENDIF}
+
+{$ENDIF}
+
+  PSDL_SysWMEvent = ^TSDL_SysWMEvent;
+  TSDL_SysWMEvent = record
+    type_: UInt8;
+    msg: PSDL_SysWMmsg;
+  end;
+
+  PSDL_Event = ^TSDL_Event;
+  TSDL_Event = record
+    case UInt8 of
+      SDL_NOEVENT: (type_: byte);
+      SDL_ACTIVEEVENT: (active: TSDL_ActiveEvent);
+      SDL_KEYDOWN, SDL_KEYUP: (key: TSDL_KeyboardEvent);
+      SDL_MOUSEMOTION: (motion: TSDL_MouseMotionEvent);
+      SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP: (button: TSDL_MouseButtonEvent );
+      SDL_JOYAXISMOTION: (jaxis: TSDL_JoyAxisEvent );
+      SDL_JOYBALLMOTION: (jball: TSDL_JoyBallEvent );
+      SDL_JOYHATMOTION: (jhat: TSDL_JoyHatEvent );
+      SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP: (jbutton: TSDL_JoyButtonEvent );
+      SDL_VIDEORESIZE: (resize: TSDL_ResizeEvent );
+      SDL_QUITEV: (quit: TSDL_QuitEvent );
+      SDL_USEREVENT : ( user : TSDL_UserEvent );
+      SDL_SYSWMEVENT: (syswm: TSDL_SysWMEvent );
+  end;
+
+
+{ This function sets up a filter to process all events before they
+  change internal state and are posted to the internal event queue.
+
+  The filter is protypted as: }
+  {$IFNDEF __GPC__}
+  TSDL_EventFilter = function( event : PSDL_Event ): Integer; cdecl;
+  {$ELSE}
+  TSDL_EventFilter = function( event : PSDL_Event ): Integer;
+  {$ENDIF}
+
+  // SDL_video.h types
+  // Useful data types
+  PPSDL_Rect = ^PSDL_Rect;
+  PSDL_Rect = ^TSDL_Rect;
+  TSDL_Rect = record
+    x, y: SInt16;
+    w, h: UInt16;
+  end;
+
+  SDL_Rect = TSDL_Rect;
+{$EXTERNALSYM SDL_Rect}
+
+  PSDL_Color = ^TSDL_Color;
+  TSDL_Color = record
+    r: UInt8;
+    g: UInt8;
+    b: UInt8;
+    unused: UInt8;
+  end;
+
+  PSDL_ColorArray = ^TSDL_ColorArray;
+  TSDL_ColorArray = array[0..65000] of TSDL_Color;
+
+  PSDL_Palette = ^TSDL_Palette;
+  TSDL_Palette = record
+    ncolors: Integer;
+    colors: PSDL_ColorArray;
+  end;
+
+  // Everything in the pixel format structure is read-only
+  PSDL_PixelFormat = ^TSDL_PixelFormat;
+  TSDL_PixelFormat = record
+    palette: PSDL_Palette;
+    BitsPerPixel: UInt8;
+    BytesPerPixel: UInt8;
+    Rloss: UInt8;
+    Gloss: UInt8;
+    Bloss: UInt8;
+    Aloss: UInt8;
+    Rshift: UInt8;
+    Gshift: UInt8;
+    Bshift: UInt8;
+    Ashift: UInt8;
+    RMask: UInt32;
+    GMask: UInt32;
+    BMask: UInt32;
+    AMask: UInt32;
+    colorkey: UInt32; // RGB color key information
+    alpha: UInt8; // Alpha value information (per-surface alpha)
+  end;
+
+{$IFDEF WINDOWS}
+  {PPrivate_hwdata = ^TPrivate_hwdata;
+  TPrivate_hwdata = record
+    dd_surface : IDIRECTDRAWSURFACE3;
+    dd_writebuf : IDIRECTDRAWSURFACE3;
+  end;}
+  {ELSE}
+{$ENDIF}
+
+  // The structure passed to the low level blit functions
+  PSDL_BlitInfo = ^TSDL_BlitInfo;
+  TSDL_BlitInfo = record
+    s_pixels: PUInt8;
+    s_width: Integer;
+    s_height: Integer;
+    s_skip: Integer;
+    d_pixels: PUInt8;
+    d_width: Integer;
+    d_height: Integer;
+    d_skip: Integer;
+    aux_data: Pointer;
+    src: PSDL_PixelFormat;
+    table: PUInt8;
+    dst: PSDL_PixelFormat;
+  end;
+
+  // typedef for private surface blitting functions
+  PSDL_Surface = ^TSDL_Surface;
+
+  {$IFNDEF __GPC__}
+  TSDL_Blit = function( src: PSDL_Surface; srcrect: PSDL_Rect; dst: PSDL_Surface; dstrect: PSDL_Rect ): Integer; cdecl;
+  {$ELSE}
+  TSDL_Blit = function( src: PSDL_Surface; srcrect: PSDL_Rect; dst: PSDL_Surface; dstrect: PSDL_Rect ): Integer;
+  {$ENDIF}
+
+  // The type definition for the low level blit functions
+  //TSDL_LoBlit = procedure( info : PSDL_BlitInfo ); cdecl;
+
+  // This is the private info structure for software accelerated blits
+  {PPrivate_swaccel = ^TPrivate_swaccel;
+  TPrivate_swaccel = record
+    blit : TSDL_LoBlit;
+    aux_data : Pointer;
+  end;}
+
+  // Blit mapping definition
+  {PSDL_BlitMap = ^TSDL_BlitMap;
+  TSDL_BlitMap = record
+    dst : PSDL_Surface;
+    identity : Integer;
+    table : PUInt8;
+    hw_blit : TSDL_Blit;
+    sw_blit : TSDL_Blit;
+    hw_data : PPrivate_hwaccel;
+    sw_data : PPrivate_swaccel;
+
+    // the version count matches the destination; mismatch indicates an invalid mapping
+    format_version : Cardinal;
+  end;}
+
+  TSDL_Surface = record
+    flags: UInt32; // Read-only
+    format: PSDL_PixelFormat; // Read-only
+    w, h: Integer; // Read-only
+    pitch: UInt16; // Read-only
+    pixels: Pointer; // Read-write
+    offset: Integer; // Private
+    hwdata: Pointer; //TPrivate_hwdata;  Hardware-specific surface info
+
+    // clipping information:
+    clip_rect: TSDL_Rect; // Read-only
+    unused1: UInt32; // for binary compatibility
+    // Allow recursive locks
+    locked: UInt32; // Private
+    // info for fast blit mapping to other surfaces
+    Blitmap: Pointer; // PSDL_BlitMap; //   Private
+    // format version, bumped at every change to invalidate blit maps
+    format_version: Cardinal; // Private
+    refcount: Integer;
+  end;
+
+  // Useful for determining the video hardware capabilities
+  PSDL_VideoInfo = ^TSDL_VideoInfo;
+  TSDL_VideoInfo = record
+    hw_available: UInt8; // Hardware and WindowManager flags in first 2 bits ( see below )
+    {hw_available: 1; // Can you create hardware surfaces
+    wm_available: 1; // Can you talk to a window manager?
+    UnusedBits1: 6;}
+    blit_hw: UInt8; // Blit Hardware flags. See below for which bits do what
+    {UnusedBits2: 1;
+    blit_hw: 1; // Flag:UInt32  Accelerated blits HW --> HW
+    blit_hw_CC: 1; // Flag:UInt32  Accelerated blits with Colorkey
+    blit_hw_A: 1; // Flag:UInt32  Accelerated blits with Alpha
+    blit_sw: 1; // Flag:UInt32  Accelerated blits SW --> HW
+    blit_sw_CC: 1; // Flag:UInt32  Accelerated blits with Colorkey
+    blit_sw_A: 1; // Flag:UInt32  Accelerated blits with Alpha
+    blit_fill: 1; // Flag:UInt32  Accelerated color fill}
+    UnusedBits3: UInt8; // Unused at this point
+    video_mem: UInt32; // The total amount of video memory (in K)
+    vfmt: PSDL_PixelFormat; // Value: The format of the video surface
+    current_w : SInt32;	// Value: The current video mode width
+	  current_h : SInt32;	// Value: The current video mode height
+  end;
+
+  // The YUV hardware video overlay
+  PSDL_Overlay = ^TSDL_Overlay;
+  TSDL_Overlay = record
+    format: UInt32; // Overlay format
+    w, h: Integer; // Width and height of overlay
+    planes: Integer; // Number of planes in the overlay. Usually either 1 or 3
+    pitches: PUInt16;
+      // An array of pitches, one for each plane. Pitch is the length of a row in bytes.
+    pixels: PPUInt8;
+      // An array of pointers to the data of each plane. The overlay should be locked before these pointers are used.
+    hw_overlay: UInt32;
+      // This will be set to 1 if the overlay is hardware accelerated.
+  end;
+
+  // Public enumeration for setting the OpenGL window attributes.
+  TSDL_GLAttr = (
+    SDL_GL_RED_SIZE,
+    SDL_GL_GREEN_SIZE,
+    SDL_GL_BLUE_SIZE,
+    SDL_GL_ALPHA_SIZE,
+    SDL_GL_BUFFER_SIZE,
+    SDL_GL_DOUBLEBUFFER,
+    SDL_GL_DEPTH_SIZE,
+    SDL_GL_STENCIL_SIZE,
+    SDL_GL_ACCUM_RED_SIZE,
+    SDL_GL_ACCUM_GREEN_SIZE,
+    SDL_GL_ACCUM_BLUE_SIZE,
+    SDL_GL_ACCUM_ALPHA_SIZE,
+    SDL_GL_STEREO,
+    SDL_GL_MULTISAMPLEBUFFERS,
+    SDL_GL_MULTISAMPLESAMPLES,
+    SDL_GL_ACCELERATED_VISUAL,
+    SDL_GL_SWAP_CONTROL);
+
+
+
+  PSDL_Cursor = ^TSDL_Cursor;
+  TSDL_Cursor = record
+    area: TSDL_Rect; // The area of the mouse cursor
+    hot_x, hot_y: SInt16; // The "tip" of the cursor
+    data: PUInt8; // B/W cursor data
+    mask: PUInt8; // B/W cursor mask
+    save: array[1..2] of PUInt8; // Place to save cursor area
+    wm_cursor: Pointer; // Window-manager cursor
+  end;
+
+// SDL_mutex.h types
+
+{$IFDEF WINDOWS}
+  PSDL_Mutex = ^TSDL_Mutex;
+  TSDL_Mutex = record
+    id: THANDLE;
+  end;
+{$ENDIF}
+
+{$IFDEF Unix}
+  PSDL_Mutex = ^TSDL_Mutex;
+  TSDL_mutex = record
+    id: pthread_mutex_t;
+{$IFDEF PTHREAD_NO_RECURSIVE_MUTEX}
+    recursive: Integer;
+    owner: pthread_t;
+{$ENDIF}
+  end;
+{$ENDIF}
+
+{$IFDEF NDS}
+  PSDL_mutex = ^TSDL_Mutex;
+  TSDL_Mutex = record
+    recursive: Integer;
+    Owner: UInt32;
+    sem: PSDL_sem;
+  end;
+{$ENDIF}
+
+{$IFDEF __MACH__}
+  {$define USE_NAMED_SEMAPHORES}
+  // Broken sem_getvalue() in MacOS X Public Beta */
+  {$define BROKEN_SEMGETVALUE}
+{$ENDIF}
+
+PSDL_semaphore = ^TSDL_semaphore;
+{$IFDEF WINDOWS}
+  // WINDOWS or Machintosh
+  TSDL_semaphore = record
+    id: THANDLE;
+    count: UInt32;
+  end;
+{$ELSE}
+  {$IFDEF FPC}
+  // This should be semaphore.h 
+  __sem_lock_t = {packed} record { Not in header file - anonymous }
+    status: Longint;
+    spinlock: Integer;
+  end;
+
+  sem_t = {packed} record
+    __sem_lock: __sem_lock_t;
+    __sem_value: Integer;
+    __sem_waiting: longint ; {_pthread_queue;}
+  end;
+  {$ENDIF}
+  
+  TSDL_semaphore = record
+    sem: Pointer; //PSem_t;
+  {$IFNDEF USE_NAMED_SEMAPHORES}
+    sem_data: Sem_t;
+  {$ENDIF}
+
+  {$IFDEF BROKEN_SEMGETVALUE}
+    { This is a little hack for MacOS X -
+      It's not thread-safe, but it's better than nothing }
+    sem_value: Integer;
+  {$ENDIF}
+  end;
+{$ENDIF}
+
+  PSDL_Sem = ^TSDL_Sem;
+  TSDL_Sem = TSDL_Semaphore;
+
+  PSDL_Cond = ^TSDL_Cond;
+  TSDL_Cond = record
+{$IFDEF Unix}
+    cond: pthread_cond_t;
+{$ELSE}
+    // Generic Cond structure
+    lock: PSDL_mutex;
+    waiting: Integer;
+    signals: Integer;
+    wait_sem: PSDL_Sem;
+    wait_done: PSDL_Sem;
+{$ENDIF}
+  end;
+
+  // SDL_thread.h types
+{$IFDEF WINDOWS}
+  TSYS_ThreadHandle = THandle;
+{$ENDIF}
+
+{$IFDEF Unix}
+  TSYS_ThreadHandle = pthread_t;
+{$ENDIF}
+
+{$IFDEF NDS}
+  TSYS_ThreadHandle = Integer;
+{$ENDIF}
+
+  { This is the system-independent thread info structure }
+  PSDL_Thread = ^TSDL_Thread;
+  TSDL_Thread = record
+    threadid: UInt32;
+    handle: TSYS_ThreadHandle;
+    status: Integer;
+    errbuf: TSDL_Error;
+    data: Pointer;
+  end;
+
+  // Helper Types
+
+  // Keyboard  State Array ( See demos for how to use )
+  PKeyStateArr = ^TKeyStateArr;
+  TKeyStateArr = array[0..65000] of UInt8;
+
+  // Types required so we don't need to use Windows.pas
+  PInteger = ^Integer;
+  PByte = ^Byte;
+  PWord = ^Word;
+  PLongWord = ^Longword;
+
+  // General arrays
+  PByteArray = ^TByteArray;
+  TByteArray = array[0..32767] of Byte;
+
+  PWordArray = ^TWordArray;
+  TWordArray = array[0..16383] of Word;
+
+  PPoint = ^TPoint;
+  {$IFDEF HAS_TYPES}
+  TPoint = Types.TPoint;
+  {$ELSE}
+    {$IFDEF WINDOWS}
+      {$IFDEF __GPC__}
+      TPoint = wintypes.TPoint;
+      {$ELSE}
+      TPoint = Windows.TPoint;
+      {$ENDIF}
+    {$ELSE}
+      //Can't define TPoint : neither Types nor Windows unit available.
+    {$ENDIF}
+  {$ENDIF}
+
+  PRect = ^TRect;
+  {$IFDEF HAS_TYPES}
+  TRect = Types.TRect;
+  {$ELSE}
+    {$IFDEF WINDOWS}
+      {$IFDEF __GPC__}
+      TRect = wintypes.TRect;
+      {$ELSE}
+      TRect = Windows.TRect;
+      {$ENDIF}
+    {$ELSE}
+      //Can't define TRect: neither Types nor Windows unit available.
+    {$ENDIF}
+  {$ENDIF}
+
+  { Generic procedure pointer }
+  TProcedure = procedure;
+
+{------------------------------------------------------------------------------}
+{ initialization                                                               }
+{------------------------------------------------------------------------------}
+
+{ This function loads the SDL dynamically linked library and initializes
+  the subsystems specified by 'flags' (and those satisfying dependencies)
+  Unless the SDL_INIT_NOPARACHUTE flag is set, it will install cleanup
+  signal handlers for some commonly ignored fatal signals (like SIGSEGV) }
+
+function SDL_Init( flags : UInt32 ) : Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_Init'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_Init}
+
+// This function initializes specific SDL subsystems
+function SDL_InitSubSystem( flags : UInt32 ) : Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_InitSubSystem'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_InitSubSystem}
+
+// This function cleans up specific SDL subsystems
+procedure SDL_QuitSubSystem( flags : UInt32 );
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_QuitSubSystem'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_QuitSubSystem}
+
+{ This function returns mask of the specified subsystems which have
+  been initialized.
+  If 'flags' is 0, it returns a mask of all initialized subsystems. }
+
+function SDL_WasInit( flags : UInt32 ): UInt32;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WasInit'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WasInit}
+
+{ This function cleans up all initialized subsystems and unloads the
+  dynamically linked library.  You should call it upon all exit conditions. }
+procedure SDL_Quit;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_Quit'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_Quit}
+
+{$IFDEF WINDOWS}
+// This should be called from your WinMain() function, if any
+function SDL_RegisterApp(name: PChar; style: UInt32; h_Inst: Pointer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_RegisterApp'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_RegisterApp}
+{$ENDIF}
+
+{$IFDEF __MACH__}
+// This should be called from your main() function, if any
+procedure SDL_InitQuickDraw( the_qd: QDGlobals );
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_InitQuickDraw'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_InitQuickDraw}
+{$ENDIF}
+
+
+{------------------------------------------------------------------------------}
+{ types }
+{------------------------------------------------------------------------------}
+// The number of elements in a table
+function SDL_TableSize( table: PChar ): Integer;
+{$EXTERNALSYM SDL_TABLESIZE}
+
+
+{------------------------------------------------------------------------------}
+{ error-handling }
+{------------------------------------------------------------------------------}
+// Public functions
+function SDL_GetError: PChar;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetError'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetError}
+procedure SDL_SetError(fmt: PChar);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetError'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetError}
+procedure SDL_ClearError;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_ClearError'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_ClearError}
+
+{$IFNDEF WINDOWS}
+procedure SDL_Error(Code: TSDL_errorcode);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_Error'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_Error}
+{$ENDIF}
+
+// Private error message function - used internally
+procedure SDL_OutOfMemory;
+
+{------------------------------------------------------------------------------}
+{ io handling                                                                  }
+{------------------------------------------------------------------------------}
+// Functions to create SDL_RWops structures from various data sources
+
+function SDL_RWFromFile(filename, mode: PChar): PSDL_RWops;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_RWFromFile'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_RWFromFile}
+procedure SDL_FreeRW(area: PSDL_RWops);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_FreeRW'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_FreeRW}
+
+//fp is FILE *fp ???
+function SDL_RWFromFP(fp: Pointer; autoclose: Integer): PSDL_RWops;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_RWFromFP'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_RWFromFP}
+function SDL_RWFromMem(mem: Pointer; size: Integer): PSDL_RWops;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_RWFromMem'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_RWFromMem}
+function SDL_RWFromConstMem(const mem: Pointer; size: Integer) : PSDL_RWops;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_RWFromConstMem'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_RWFromConstMem}
+function SDL_AllocRW: PSDL_RWops;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_AllocRW'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_AllocRW}
+
+function SDL_RWSeek(context: PSDL_RWops; offset: Integer; whence: Integer) : Integer;
+{$EXTERNALSYM SDL_RWSeek}
+function SDL_RWTell(context: PSDL_RWops): Integer;
+{$EXTERNALSYM SDL_RWTell}
+function SDL_RWRead(context: PSDL_RWops; ptr: Pointer; size: Integer; n : Integer): Integer;
+{$EXTERNALSYM SDL_RWRead}
+function SDL_RWWrite(context: PSDL_RWops; ptr: Pointer; size: Integer; n : Integer): Integer;
+{$EXTERNALSYM SDL_RWWrite}
+function SDL_RWClose(context: PSDL_RWops): Integer;
+{$EXTERNALSYM SDL_RWClose}
+
+{------------------------------------------------------------------------------}
+{ time-handling                                                                }
+{------------------------------------------------------------------------------}
+
+{ Get the number of milliseconds since the SDL library initialization. }
+{ Note that this value wraps if the program runs for more than ~49 days. }
+function SDL_GetTicks: UInt32;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetTicks'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetTicks}
+
+// Wait a specified number of milliseconds before returning
+procedure SDL_Delay(msec: UInt32);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_Delay'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_Delay}
+
+{ Add a new timer to the pool of timers already running. }
+{ Returns a timer ID, or NULL when an error occurs.      }
+function SDL_AddTimer(interval: UInt32; callback: TSDL_NewTimerCallback; param : Pointer): PSDL_TimerID;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_AddTimer'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_AddTimer}
+
+{ Remove one of the multiple timers knowing its ID. }
+{ Returns a boolean value indicating success. }
+function SDL_RemoveTimer(t: PSDL_TimerID): TSDL_Bool;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_RemoveTimer'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_RemoveTimer}
+
+function SDL_SetTimer(interval: UInt32; callback: TSDL_TimerCallback): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetTimer'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetTimer}
+
+{------------------------------------------------------------------------------}
+{ audio-routines                                                               }
+{------------------------------------------------------------------------------}
+
+{ These functions are used internally, and should not be used unless you
+  have a specific need to specify the audio driver you want to use.
+  You should normally use SDL_Init() or SDL_InitSubSystem(). }
+
+function SDL_AudioInit(driver_name: PChar): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_AudioInit'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_AudioInit}
+procedure SDL_AudioQuit;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_AudioQuit'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_AudioQuit}
+
+{ This function fills the given character buffer with the name of the
+  current audio driver, and returns a Pointer to it if the audio driver has
+  been initialized.  It returns NULL if no driver has been initialized. }
+
+function SDL_AudioDriverName(namebuf: PChar; maxlen: Integer): PChar;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_AudioDriverName'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_AudioDriverName}
+
+{ This function opens the audio device with the desired parameters, and
+  returns 0 if successful, placing the actual hardware parameters in the
+  structure pointed to by 'obtained'.  If 'obtained' is NULL, the audio
+  data passed to the callback function will be guaranteed to be in the
+  requested format, and will be automatically converted to the hardware
+  audio format if necessary.  This function returns -1 if it failed
+  to open the audio device, or couldn't set up the audio thread.
+
+  When filling in the desired audio spec structure,
+   'desired->freq' should be the desired audio frequency in samples-per-second.
+   'desired->format' should be the desired audio format.
+   'desired->samples' is the desired size of the audio buffer, in samples.
+      This number should be a power of two, and may be adjusted by the audio
+      driver to a value more suitable for the hardware.  Good values seem to
+      range between 512 and 8096 inclusive, depending on the application and
+      CPU speed.  Smaller values yield faster response time, but can lead
+      to underflow if the application is doing heavy processing and cannot
+      fill the audio buffer in time.  A stereo sample consists of both right
+      and left channels in LR ordering.
+      Note that the number of samples is directly related to time by the
+      following formula:  ms = (samples*1000)/freq
+   'desired->size' is the size in bytes of the audio buffer, and is
+      calculated by SDL_OpenAudio().
+   'desired->silence' is the value used to set the buffer to silence,
+      and is calculated by SDL_OpenAudio().
+   'desired->callback' should be set to a function that will be called
+      when the audio device is ready for more data.  It is passed a pointer
+      to the audio buffer, and the length in bytes of the audio buffer.
+      This function usually runs in a separate thread, and so you should
+      protect data structures that it accesses by calling SDL_LockAudio()
+      and SDL_UnlockAudio() in your code.
+   'desired->userdata' is passed as the first parameter to your callback
+      function.
+
+  The audio device starts out playing silence when it's opened, and should
+  be enabled for playing by calling SDL_PauseAudio(0) when you are ready
+  for your audio callback function to be called.  Since the audio driver
+  may modify the requested size of the audio buffer, you should allocate
+  any local mixing buffers after you open the audio device. }
+
+function SDL_OpenAudio(desired, obtained: PSDL_AudioSpec): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_OpenAudio'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_OpenAudio}
+
+{ Get the current audio state: }
+function SDL_GetAudioStatus: TSDL_Audiostatus;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetAudioStatus'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetAudioStatus}
+
+{ This function pauses and unpauses the audio callback processing.
+  It should be called with a parameter of 0 after opening the audio
+  device to start playing sound.  This is so you can safely initialize
+  data for your callback function after opening the audio device.
+  Silence will be written to the audio device during the pause. }
+
+procedure SDL_PauseAudio(pause_on: Integer);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_PauseAudio'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_PauseAudio}
+
+{ This function loads a WAVE from the data source, automatically freeing
+  that source if 'freesrc' is non-zero.  For example, to load a WAVE file,
+  you could do:
+  SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...);
+
+  If this function succeeds, it returns the given SDL_AudioSpec,
+  filled with the audio data format of the wave data, and sets
+  'audio_buf' to a malloc()'d buffer containing the audio data,
+  and sets 'audio_len' to the length of that audio buffer, in bytes.
+  You need to free the audio buffer with SDL_FreeWAV() when you are
+  done with it.
+
+  This function returns NULL and sets the SDL error message if the
+  wave file cannot be opened, uses an unknown data format, or is
+  corrupt.  Currently raw and MS-ADPCM WAVE files are supported. }
+
+function SDL_LoadWAV_RW(src: PSDL_RWops; freesrc: Integer; spec:
+  PSDL_AudioSpec; audio_buf: PUInt8; audiolen: PUInt32): PSDL_AudioSpec;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_LoadWAV_RW'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_LoadWAV_RW}
+
+// Compatibility convenience function -- loads a WAV from a file
+function SDL_LoadWAV(filename: PChar; spec: PSDL_AudioSpec; audio_buf:
+  PUInt8; audiolen: PUInt32): PSDL_AudioSpec;
+{$EXTERNALSYM SDL_LoadWAV}
+
+{ This function frees data previously allocated with SDL_LoadWAV_RW() }
+
+procedure SDL_FreeWAV(audio_buf: PUInt8);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_FreeWAV'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_FreeWAV}
+
+{ This function takes a source format and rate and a destination format
+  and rate, and initializes the 'cvt' structure with information needed
+  by SDL_ConvertAudio() to convert a buffer of audio data from one format
+  to the other.
+  This function returns 0, or -1 if there was an error. }
+function SDL_BuildAudioCVT(cvt: PSDL_AudioCVT; src_format: UInt16;
+  src_channels: UInt8; src_rate: Integer; dst_format: UInt16; dst_channels: UInt8;
+  dst_rate: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_BuildAudioCVT'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_BuildAudioCVT}
+
+{ Once you have initialized the 'cvt' structure using SDL_BuildAudioCVT(),
+  created an audio buffer cvt->buf, and filled it with cvt->len bytes of
+  audio data in the source format, this function will convert it in-place
+  to the desired format.
+  The data conversion may expand the size of the audio data, so the buffer
+  cvt->buf should be allocated after the cvt structure is initialized by
+  SDL_BuildAudioCVT(), and should be cvt->len*cvt->len_mult bytes long. }
+function SDL_ConvertAudio(cvt: PSDL_AudioCVT): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_ConvertAudio'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_ConvertAudio}
+
+{ This takes two audio buffers of the playing audio format and mixes
+  them, performing addition, volume adjustment, and overflow clipping.
+  The volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME
+  for full audio volume.  Note this does not change hardware volume.
+  This is provided for convenience -- you can mix your own audio data. }
+
+procedure SDL_MixAudio(dst, src: PUInt8; len: UInt32; volume: Integer);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_MixAudio'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_MixAudio}
+
+{ The lock manipulated by these functions protects the callback function.
+  During a LockAudio/UnlockAudio pair, you can be guaranteed that the
+  callback function is not running.  Do not call these from the callback
+  function or you will cause deadlock. }
+procedure SDL_LockAudio;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_LockAudio'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_LockAudio}
+procedure SDL_UnlockAudio;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_UnlockAudio'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_UnlockAudio}
+
+{ This function shuts down audio processing and closes the audio device. }
+
+procedure SDL_CloseAudio;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CloseAudio'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CloseAudio}
+
+{------------------------------------------------------------------------------}
+{ CD-routines }
+{------------------------------------------------------------------------------}
+
+{ Returns the number of CD-ROM drives on the system, or -1 if
+  SDL_Init() has not been called with the SDL_INIT_CDROM flag. }
+
+function SDL_CDNumDrives: Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDNumDrives'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDNumDrives}
+
+{ Returns a human-readable, system-dependent identifier for the CD-ROM.
+   Example:
+   "/dev/cdrom"
+   "E:"
+   "/dev/disk/ide/1/master" }
+
+function SDL_CDName(drive: Integer): PChar;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDName'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDName}
+
+{ Opens a CD-ROM drive for access.  It returns a drive handle on success,
+  or NULL if the drive was invalid or busy.  This newly opened CD-ROM
+  becomes the default CD used when other CD functions are passed a NULL
+  CD-ROM handle.
+  Drives are numbered starting with 0.  Drive 0 is the system default CD-ROM. }
+
+function SDL_CDOpen(drive: Integer): PSDL_CD;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDOpen'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDOpen}
+
+{ This function returns the current status of the given drive.
+  If the drive has a CD in it, the table of contents of the CD and current
+  play position of the CD will be stored in the SDL_CD structure. }
+
+function SDL_CDStatus(cdrom: PSDL_CD): TSDL_CDStatus;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDStatus'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDStatus}
+
+{  Play the given CD starting at 'start_track' and 'start_frame' for 'ntracks'
+   tracks and 'nframes' frames.  If both 'ntrack' and 'nframe' are 0, play
+   until the end of the CD.  This function will skip data tracks.
+   This function should only be called after calling SDL_CDStatus() to
+   get track information about the CD.
+
+   For example:
+   // Play entire CD:
+  if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) then
+    SDL_CDPlayTracks(cdrom, 0, 0, 0, 0);
+   // Play last track:
+   if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) then
+   begin
+    SDL_CDPlayTracks(cdrom, cdrom->numtracks-1, 0, 0, 0);
+   end;
+
+   // Play first and second track and 10 seconds of third track:
+   if ( CD_INDRIVE(SDL_CDStatus(cdrom)) )
+    SDL_CDPlayTracks(cdrom, 0, 0, 2, 10);
+
+   This function returns 0, or -1 if there was an error. }
+
+function SDL_CDPlayTracks(cdrom: PSDL_CD; start_track: Integer; start_frame:
+  Integer; ntracks: Integer; nframes: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDPlayTracks'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDPlayTracks}
+
+
+{  Play the given CD starting at 'start' frame for 'length' frames.
+   It returns 0, or -1 if there was an error. }
+
+function SDL_CDPlay(cdrom: PSDL_CD; start: Integer; length: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDPlay'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDPlay}
+
+// Pause play -- returns 0, or -1 on error
+function SDL_CDPause(cdrom: PSDL_CD): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDPause'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDPause}
+
+// Resume play -- returns 0, or -1 on error
+function SDL_CDResume(cdrom: PSDL_CD): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDResume'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDResume}
+
+// Stop play -- returns 0, or -1 on error
+function SDL_CDStop(cdrom: PSDL_CD): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDStop'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDStop}
+
+// Eject CD-ROM -- returns 0, or -1 on error
+function SDL_CDEject(cdrom: PSDL_CD): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDEject'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDEject}
+
+// Closes the handle for the CD-ROM drive
+procedure SDL_CDClose(cdrom: PSDL_CD);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CDClose'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CDClose}
+
+// Given a status, returns true if there's a disk in the drive
+function SDL_CDInDrive( status : TSDL_CDStatus ) : LongBool;
+{$EXTERNALSYM SDL_CDInDrive}
+
+// Conversion functions from frames to Minute/Second/Frames and vice versa
+procedure FRAMES_TO_MSF(frames: Integer; var M: Integer; var S: Integer; var
+  F: Integer);
+{$EXTERNALSYM FRAMES_TO_MSF}
+function MSF_TO_FRAMES(M: Integer; S: Integer; F: Integer): Integer;
+{$EXTERNALSYM MSF_TO_FRAMES}
+
+{------------------------------------------------------------------------------}
+{ JoyStick-routines                                                            }
+{------------------------------------------------------------------------------}
+
+{ Count the number of joysticks attached to the system }
+function SDL_NumJoysticks: Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_NumJoysticks'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_NumJoysticks}
+
+{ Get the implementation dependent name of a joystick.
+  This can be called before any joysticks are opened.
+  If no name can be found, this function returns NULL. }
+function SDL_JoystickName(index: Integer): PChar;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickName'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickName}
+
+{ Open a joystick for use - the index passed as an argument refers to
+  the N'th joystick on the system.  This index is the value which will
+  identify this joystick in future joystick events.
+
+  This function returns a joystick identifier, or NULL if an error occurred. }
+function SDL_JoystickOpen(index: Integer): PSDL_Joystick;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickOpen'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickOpen}
+
+{ Returns 1 if the joystick has been opened, or 0 if it has not. }
+function SDL_JoystickOpened(index: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickOpened'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickOpened}
+
+{ Get the device index of an opened joystick. }
+function SDL_JoystickIndex(joystick: PSDL_Joystick): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickIndex'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickIndex}
+
+{ Get the number of general axis controls on a joystick }
+function SDL_JoystickNumAxes(joystick: PSDL_Joystick): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickNumAxes'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickNumAxes}
+
+{ Get the number of trackballs on a joystick
+  Joystick trackballs have only relative motion events associated
+  with them and their state cannot be polled. }
+function SDL_JoystickNumBalls(joystick: PSDL_Joystick): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickNumBalls'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickNumBalls}
+
+
+{ Get the number of POV hats on a joystick }
+function SDL_JoystickNumHats(joystick: PSDL_Joystick): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickNumHats'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickNumHats}
+
+{ Get the number of buttons on a joystick }
+function SDL_JoystickNumButtons(joystick: PSDL_Joystick): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickNumButtons'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickNumButtons}
+
+{ Update the current state of the open joysticks.
+  This is called automatically by the event loop if any joystick
+  events are enabled. }
+
+procedure SDL_JoystickUpdate;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickUpdate'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickUpdate;}
+
+{ Enable/disable joystick event polling.
+  If joystick events are disabled, you must call SDL_JoystickUpdate()
+  yourself and check the state of the joystick when you want joystick
+  information.
+  The state can be one of SDL_QUERY, SDL_ENABLE or SDL_IGNORE. }
+
+function SDL_JoystickEventState(state: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickEventState'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickEventState}
+
+{ Get the current state of an axis control on a joystick
+  The state is a value ranging from -32768 to 32767.
+  The axis indices start at index 0. }
+
+function SDL_JoystickGetAxis(joystick: PSDL_Joystick; axis: Integer) : SInt16;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickGetAxis'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickGetAxis}
+
+{ The hat indices start at index 0. }
+
+function SDL_JoystickGetHat(joystick: PSDL_Joystick; hat: Integer): UInt8;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickGetHat'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickGetHat}
+
+{ Get the ball axis change since the last poll
+  This returns 0, or -1 if you passed it invalid parameters.
+  The ball indices start at index 0. }
+
+function SDL_JoystickGetBall(joystick: PSDL_Joystick; ball: Integer; var dx: Integer; var dy: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickGetBall'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickGetBall}
+
+{ Get the current state of a button on a joystick
+  The button indices start at index 0. }
+function SDL_JoystickGetButton( joystick: PSDL_Joystick; Button: Integer): UInt8;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickGetButton'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickGetButton}
+
+{ Close a joystick previously opened with SDL_JoystickOpen() }
+procedure SDL_JoystickClose(joystick: PSDL_Joystick);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_JoystickClose'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_JoystickClose}
+
+{------------------------------------------------------------------------------}
+{ event-handling }
+{------------------------------------------------------------------------------}
+
+{ Pumps the event loop, gathering events from the input devices.
+  This function updates the event queue and internal input device state.
+  This should only be run in the thread that sets the video mode. }
+
+procedure SDL_PumpEvents;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_PumpEvents'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_PumpEvents;}
+
+{ Checks the event queue for messages and optionally returns them.
+  If 'action' is SDL_ADDEVENT, up to 'numevents' events will be added to
+  the back of the event queue.
+  If 'action' is SDL_PEEKEVENT, up to 'numevents' events at the front
+  of the event queue, matching 'mask', will be returned and will not
+  be removed from the queue.
+  If 'action' is SDL_GETEVENT, up to 'numevents' events at the front
+  of the event queue, matching 'mask', will be returned and will be
+  removed from the queue.
+  This function returns the number of events actually stored, or -1
+  if there was an error.  This function is thread-safe. }
+
+function SDL_PeepEvents(events: PSDL_Event; numevents: Integer; action: TSDL_eventaction; mask: UInt32): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_PeepEvents'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_PeepEvents}
+
+{ Polls for currently pending events, and returns 1 if there are any pending
+   events, or 0 if there are none available.  If 'event' is not NULL, the next
+   event is removed from the queue and stored in that area. }
+
+function SDL_PollEvent(event: PSDL_Event): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_PollEvent'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_PollEvent}
+
+{  Waits indefinitely for the next available event, returning 1, or 0 if there
+   was an error while waiting for events.  If 'event' is not NULL, the next
+   event is removed from the queue and stored in that area. }
+
+function SDL_WaitEvent(event: PSDL_Event): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WaitEvent'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WaitEvent}
+
+function SDL_PushEvent( event : PSDL_Event ) : Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_PushEvent'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_PushEvent}
+
+{ If the filter returns 1, then the event will be added to the internal queue.
+  If it returns 0, then the event will be dropped from the queue, but the
+  internal state will still be updated.  This allows selective filtering of
+  dynamically arriving events.
+
+  WARNING:  Be very careful of what you do in the event filter function, as
+            it may run in a different thread!
+
+  There is one caveat when dealing with the SDL_QUITEVENT event type.  The
+  event filter is only called when the window manager desires to close the
+  application window.  If the event filter returns 1, then the window will
+  be closed, otherwise the window will remain open if possible.
+  If the quit event is generated by an interrupt signal, it will bypass the
+  internal queue and be delivered to the application at the next event poll. }
+procedure SDL_SetEventFilter( filter : TSDL_EventFilter );
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetEventFilter'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetEventFilter}
+
+{ Return the current event filter - can be used to "chain" filters.
+  If there is no event filter set, this function returns NULL. }
+
+function SDL_GetEventFilter: TSDL_EventFilter;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetEventFilter'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetEventFilter}
+
+{ This function allows you to set the state of processing certain events.
+  If 'state' is set to SDL_IGNORE, that event will be automatically dropped
+  from the event queue and will not event be filtered.
+  If 'state' is set to SDL_ENABLE, that event will be processed normally.
+  If 'state' is set to SDL_QUERY, SDL_EventState() will return the
+  current processing state of the specified event. }
+
+function SDL_EventState(type_: UInt8; state: Integer): UInt8;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_EventState'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_EventState}
+
+{------------------------------------------------------------------------------}
+{ Version Routines }
+{------------------------------------------------------------------------------}
+
+{ This macro can be used to fill a version structure with the compile-time
+  version of the SDL library. }
+procedure SDL_VERSION(var X: TSDL_Version);
+{$EXTERNALSYM SDL_VERSION}
+
+{ This macro turns the version numbers into a numeric value:
+   (1,2,3) -> (1203)
+   This assumes that there will never be more than 100 patchlevels }
+
+function SDL_VERSIONNUM(X, Y, Z: Integer): Integer;
+{$EXTERNALSYM SDL_VERSIONNUM}
+
+// This is the version number macro for the current SDL version
+function SDL_COMPILEDVERSION: Integer;
+{$EXTERNALSYM SDL_COMPILEDVERSION}
+
+// This macro will evaluate to true if compiled with SDL at least X.Y.Z
+function SDL_VERSION_ATLEAST(X: Integer; Y: Integer; Z: Integer) : LongBool;
+{$EXTERNALSYM SDL_VERSION_ATLEAST}
+
+{ This function gets the version of the dynamically linked SDL library.
+  it should NOT be used to fill a version structure, instead you should
+  use the SDL_Version() macro. }
+
+function SDL_Linked_Version: PSDL_version;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_Linked_Version'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_Linked_Version}
+
+{------------------------------------------------------------------------------}
+{ video                                                                        }
+{------------------------------------------------------------------------------}
+
+{ These functions are used internally, and should not be used unless you
+  have a specific need to specify the video driver you want to use.
+  You should normally use SDL_Init() or SDL_InitSubSystem().
+
+  SDL_VideoInit() initializes the video subsystem -- sets up a connection
+  to the window manager, etc, and determines the current video mode and
+  pixel format, but does not initialize a window or graphics mode.
+  Note that event handling is activated by this routine.
+
+  If you use both sound and video in your application, you need to call
+  SDL_Init() before opening the sound device, otherwise under Win32 DirectX,
+  you won't be able to set full-screen display modes. }
+
+function SDL_VideoInit(driver_name: PChar; flags: UInt32): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_VideoInit'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_VideoInit}
+procedure SDL_VideoQuit;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_VideoQuit'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_VideoQuit}
+
+{ This function fills the given character buffer with the name of the
+  video driver, and returns a pointer to it if the video driver has
+  been initialized.  It returns NULL if no driver has been initialized. }
+
+function SDL_VideoDriverName(namebuf: PChar; maxlen: Integer): PChar;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_VideoDriverName'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_VideoDriverName}
+
+{ This function returns a pointer to the current display surface.
+  If SDL is doing format conversion on the display surface, this
+  function returns the publicly visible surface, not the real video
+  surface. }
+
+function SDL_GetVideoSurface: PSDL_Surface;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetVideoSurface'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetVideoSurface}
+
+{ This function returns a read-only pointer to information about the
+  video hardware.  If this is called before SDL_SetVideoMode(), the 'vfmt'
+  member of the returned structure will contain the pixel format of the
+  "best" video mode. }
+function SDL_GetVideoInfo: PSDL_VideoInfo;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetVideoInfo'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetVideoInfo}
+
+{ Check to see if a particular video mode is supported.
+  It returns 0 if the requested mode is not supported under any bit depth,
+  or returns the bits-per-pixel of the closest available mode with the
+  given width and height.  If this bits-per-pixel is different from the
+  one used when setting the video mode, SDL_SetVideoMode() will succeed,
+  but will emulate the requested bits-per-pixel with a shadow surface.
+
+  The arguments to SDL_VideoModeOK() are the same ones you would pass to
+  SDL_SetVideoMode() }
+
+function SDL_VideoModeOK(width, height, bpp: Integer; flags: UInt32): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_VideoModeOK'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_VideoModeOK}
+
+{ Return a pointer to an array of available screen dimensions for the
+  given format and video flags, sorted largest to smallest.  Returns
+  NULL if there are no dimensions available for a particular format,
+  or (SDL_Rect **)-1 if any dimension is okay for the given format.
+
+  if 'format' is NULL, the mode list will be for the format given
+  by SDL_GetVideoInfo( ) - > vfmt }
+
+function SDL_ListModes(format: PSDL_PixelFormat; flags: UInt32): PPSDL_Rect;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_ListModes'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_ListModes}
+
+
+{ Set up a video mode with the specified width, height and bits-per-pixel.
+
+  If 'bpp' is 0, it is treated as the current display bits per pixel.
+
+  If SDL_ANYFORMAT is set in 'flags', the SDL library will try to set the
+  requested bits-per-pixel, but will return whatever video pixel format is
+  available.  The default is to emulate the requested pixel format if it
+  is not natively available.
+
+  If SDL_HWSURFACE is set in 'flags', the video surface will be placed in
+  video memory, if possible, and you may have to call SDL_LockSurface()
+  in order to access the raw framebuffer.  Otherwise, the video surface
+  will be created in system memory.
+
+  If SDL_ASYNCBLIT is set in 'flags', SDL will try to perform rectangle
+  updates asynchronously, but you must always lock before accessing pixels.
+  SDL will wait for updates to complete before returning from the lock.
+
+  If SDL_HWPALETTE is set in 'flags', the SDL library will guarantee
+  that the colors set by SDL_SetColors() will be the colors you get.
+  Otherwise, in 8-bit mode, SDL_SetColors() may not be able to set all
+  of the colors exactly the way they are requested, and you should look
+  at the video surface structure to determine the actual palette.
+  If SDL cannot guarantee that the colors you request can be set,
+  i.e. if the colormap is shared, then the video surface may be created
+  under emulation in system memory, overriding the SDL_HWSURFACE flag.
+
+  If SDL_FULLSCREEN is set in 'flags', the SDL library will try to set
+  a fullscreen video mode.  The default is to create a windowed mode
+  if the current graphics system has a window manager.
+  If the SDL library is able to set a fullscreen video mode, this flag
+  will be set in the surface that is returned.
+
+  If SDL_DOUBLEBUF is set in 'flags', the SDL library will try to set up
+  two surfaces in video memory and swap between them when you call
+  SDL_Flip().  This is usually slower than the normal single-buffering
+  scheme, but prevents "tearing" artifacts caused by modifying video
+  memory while the monitor is refreshing.  It should only be used by
+  applications that redraw the entire screen on every update.
+
+  This function returns the video framebuffer surface, or NULL if it fails. }
+
+function SDL_SetVideoMode(width, height, bpp: Integer; flags: UInt32): PSDL_Surface;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetVideoMode'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetVideoMode}
+
+
+{ Makes sure the given list of rectangles is updated on the given screen.
+  If 'x', 'y', 'w' and 'h' are all 0, SDL_UpdateRect will update the entire
+  screen.
+  These functions should not be called while 'screen' is locked. }
+
+procedure SDL_UpdateRects(screen: PSDL_Surface; numrects: Integer; rects: PSDL_Rect);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_UpdateRects'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_UpdateRects}
+procedure SDL_UpdateRect(screen: PSDL_Surface; x, y: SInt32; w, h: UInt32);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_UpdateRect'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_UpdateRect}
+
+
+{ On hardware that supports double-buffering, this function sets up a flip
+  and returns.  The hardware will wait for vertical retrace, and then swap
+  video buffers before the next video surface blit or lock will return.
+  On hardware that doesn not support double-buffering, this is equivalent
+  to calling SDL_UpdateRect(screen, 0, 0, 0, 0);
+  The SDL_DOUBLEBUF flag must have been passed to SDL_SetVideoMode() when
+  setting the video mode for this function to perform hardware flipping.
+  This function returns 0 if successful, or -1 if there was an error.}
+
+function SDL_Flip(screen: PSDL_Surface): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_Flip'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_Flip}
+
+{ Set the gamma correction for each of the color channels.
+  The gamma values range (approximately) between 0.1 and 10.0
+
+  If this function isn't supported directly by the hardware, it will
+  be emulated using gamma ramps, if available.  If successful, this
+  function returns 0, otherwise it returns -1. }
+
+function SDL_SetGamma(redgamma: single; greengamma: single; bluegamma: single ): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetGamma'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetGamma}
+
+{ Set the gamma translation table for the red, green, and blue channels
+  of the video hardware.  Each table is an array of 256 16-bit quantities,
+  representing a mapping between the input and output for that channel.
+  The input is the index into the array, and the output is the 16-bit
+  gamma value at that index, scaled to the output color precision.
+
+  You may pass NULL for any of the channels to leave it unchanged.
+  If the call succeeds, it will return 0.  If the display driver or
+  hardware does not support gamma translation, or otherwise fails,
+  this function will return -1. }
+
+function SDL_SetGammaRamp( redtable: PUInt16; greentable: PUInt16; bluetable: PUInt16): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetGammaRamp'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetGammaRamp}
+
+{ Retrieve the current values of the gamma translation tables.
+
+  You must pass in valid pointers to arrays of 256 16-bit quantities.
+  Any of the pointers may be NULL to ignore that channel.
+  If the call succeeds, it will return 0.  If the display driver or
+  hardware does not support gamma translation, or otherwise fails,
+  this function will return -1. }
+
+function SDL_GetGammaRamp( redtable: PUInt16; greentable: PUInt16; bluetable: PUInt16): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetGammaRamp'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetGammaRamp}
+
+{ Sets a portion of the colormap for the given 8-bit surface.  If 'surface'
+  is not a palettized surface, this function does nothing, returning 0.
+  If all of the colors were set as passed to SDL_SetColors(), it will
+  return 1.  If not all the color entries were set exactly as given,
+  it will return 0, and you should look at the surface palette to
+  determine the actual color palette.
+
+  When 'surface' is the surface associated with the current display, the
+  display colormap will be updated with the requested colors.  If
+  SDL_HWPALETTE was set in SDL_SetVideoMode() flags, SDL_SetColors()
+  will always return 1, and the palette is guaranteed to be set the way
+  you desire, even if the window colormap has to be warped or run under
+  emulation. }
+
+
+function SDL_SetColors(surface: PSDL_Surface; colors: PSDL_Color; firstcolor : Integer; ncolors: Integer) : Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetColors'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetColors}
+
+{ Sets a portion of the colormap for a given 8-bit surface.
+  'flags' is one or both of:
+  SDL_LOGPAL  -- set logical palette, which controls how blits are mapped
+                 to/from the surface,
+  SDL_PHYSPAL -- set physical palette, which controls how pixels look on
+                 the screen
+  Only screens have physical palettes. Separate change of physical/logical
+  palettes is only possible if the screen has SDL_HWPALETTE set.
+
+  The return value is 1 if all colours could be set as requested, and 0
+  otherwise.
+
+  SDL_SetColors() is equivalent to calling this function with
+  flags = (SDL_LOGPAL or SDL_PHYSPAL). }
+
+function SDL_SetPalette(surface: PSDL_Surface; flags: Integer; colors: PSDL_Color; firstcolor: Integer; ncolors: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetPalette'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetPalette}
+
+{ Maps an RGB triple to an opaque pixel value for a given pixel format }
+function SDL_MapRGB(format: PSDL_PixelFormat; r: UInt8; g: UInt8; b: UInt8) : UInt32;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_MapRGB'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_MapRGB}
+
+{ Maps an RGBA quadruple to a pixel value for a given pixel format }
+function SDL_MapRGBA(format: PSDL_PixelFormat; r: UInt8; g: UInt8; b: UInt8; a: UInt8): UInt32;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_MapRGBA'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_MapRGBA}
+
+{ Maps a pixel value into the RGB components for a given pixel format }
+procedure SDL_GetRGB(pixel: UInt32; fmt: PSDL_PixelFormat; r: PUInt8; g: PUInt8; b: PUInt8);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetRGB'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetRGB}
+
+{ Maps a pixel value into the RGBA components for a given pixel format }
+procedure SDL_GetRGBA(pixel: UInt32; fmt: PSDL_PixelFormat; r: PUInt8; g: PUInt8; b: PUInt8; a: PUInt8);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetRGBA'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetRGBA}
+
+{ Allocate and free an RGB surface (must be called after SDL_SetVideoMode)
+  If the depth is 4 or 8 bits, an empty palette is allocated for the surface.
+  If the depth is greater than 8 bits, the pixel format is set using the
+  flags '[RGB]mask'.
+  If the function runs out of memory, it will return NULL.
+
+  The 'flags' tell what kind of surface to create.
+  SDL_SWSURFACE means that the surface should be created in system memory.
+  SDL_HWSURFACE means that the surface should be created in video memory,
+  with the same format as the display surface.  This is useful for surfaces
+  that will not change much, to take advantage of hardware acceleration
+  when being blitted to the display surface.
+  SDL_ASYNCBLIT means that SDL will try to perform asynchronous blits with
+  this surface, but you must always lock it before accessing the pixels.
+  SDL will wait for current blits to finish before returning from the lock.
+  SDL_SRCCOLORKEY indicates that the surface will be used for colorkey blits.
+  If the hardware supports acceleration of colorkey blits between
+  two surfaces in video memory, SDL will try to place the surface in
+  video memory. If this isn't possible or if there is no hardware
+  acceleration available, the surface will be placed in system memory.
+  SDL_SRCALPHA means that the surface will be used for alpha blits and
+  if the hardware supports hardware acceleration of alpha blits between
+  two surfaces in video memory, to place the surface in video memory
+  if possible, otherwise it will be placed in system memory.
+  If the surface is created in video memory, blits will be _much_ faster,
+  but the surface format must be identical to the video surface format,
+  and the only way to access the pixels member of the surface is to use
+  the SDL_LockSurface() and SDL_UnlockSurface() calls.
+  If the requested surface actually resides in video memory, SDL_HWSURFACE
+  will be set in the flags member of the returned surface.  If for some
+  reason the surface could not be placed in video memory, it will not have
+  the SDL_HWSURFACE flag set, and will be created in system memory instead. }
+
+function SDL_AllocSurface(flags: UInt32; width, height, depth: Integer;
+  RMask, GMask, BMask, AMask: UInt32): PSDL_Surface;
+{$EXTERNALSYM SDL_AllocSurface}
+
+function SDL_CreateRGBSurface(flags: UInt32; width, height, depth: Integer; RMask, GMask, BMask, AMask: UInt32): PSDL_Surface;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CreateRGBSurface'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CreateRGBSurface}
+
+function SDL_CreateRGBSurfaceFrom(pixels: Pointer; width, height, depth, pitch
+  : Integer; RMask, GMask, BMask, AMask: UInt32): PSDL_Surface;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CreateRGBSurfaceFrom'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CreateRGBSurfaceFrom}
+
+procedure SDL_FreeSurface(surface: PSDL_Surface);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_FreeSurface'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_FreeSurface}
+
+function SDL_MustLock(Surface: PSDL_Surface): Boolean;
+{$EXTERNALSYM SDL_MustLock}
+{ SDL_LockSurface() sets up a surface for directly accessing the pixels.
+  Between calls to SDL_LockSurface()/SDL_UnlockSurface(), you can write
+  to and read from 'surface->pixels', using the pixel format stored in
+  'surface->format'.  Once you are done accessing the surface, you should
+  use SDL_UnlockSurface() to release it.
+
+  Not all surfaces require locking.  If SDL_MUSTLOCK(surface) evaluates
+  to 0, then you can read and write to the surface at any time, and the
+  pixel format of the surface will not change.  In particular, if the
+  SDL_HWSURFACE flag is not given when calling SDL_SetVideoMode(), you
+  will not need to lock the display surface before accessing it.
+
+  No operating system or library calls should be made between lock/unlock
+  pairs, as critical system locks may be held during this time.
+
+  SDL_LockSurface() returns 0, or -1 if the surface couldn't be locked. }
+function SDL_LockSurface(surface: PSDL_Surface): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_LockSurface'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_LockSurface}
+
+procedure SDL_UnlockSurface(surface: PSDL_Surface);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_UnlockSurface'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_UnlockSurface}
+
+{ Load a surface from a seekable SDL data source (memory or file.)
+  If 'freesrc' is non-zero, the source will be closed after being read.
+  Returns the new surface, or NULL if there was an error.
+  The new surface should be freed with SDL_FreeSurface(). }
+function SDL_LoadBMP_RW(src: PSDL_RWops; freesrc: Integer): PSDL_Surface;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_LoadBMP_RW'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_LoadBMP_RW}
+
+// Convenience macro -- load a surface from a file
+function SDL_LoadBMP(filename: PChar): PSDL_Surface;
+{$EXTERNALSYM SDL_LoadBMP}
+
+{ Save a surface to a seekable SDL data source (memory or file.)
+  If 'freedst' is non-zero, the source will be closed after being written.
+  Returns 0 if successful or -1 if there was an error. }
+
+function SDL_SaveBMP_RW(surface: PSDL_Surface; dst: PSDL_RWops; freedst: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SaveBMP_RW'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SaveBMP_RW}
+
+// Convenience macro -- save a surface to a file
+function SDL_SaveBMP(surface: PSDL_Surface; filename: PChar): Integer;
+{$EXTERNALSYM SDL_SaveBMP}
+
+{ Sets the color key (transparent pixel) in a blittable surface.
+  If 'flag' is SDL_SRCCOLORKEY (optionally OR'd with SDL_RLEACCEL),
+  'key' will be the transparent pixel in the source image of a blit.
+  SDL_RLEACCEL requests RLE acceleration for the surface if present,
+  and removes RLE acceleration if absent.
+  If 'flag' is 0, this function clears any current color key.
+  This function returns 0, or -1 if there was an error. }
+
+function SDL_SetColorKey(surface: PSDL_Surface; flag, key: UInt32) : Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetColorKey'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetColorKey}
+
+{ This function sets the alpha value for the entire surface, as opposed to
+  using the alpha component of each pixel. This value measures the range
+  of transparency of the surface, 0 being completely transparent to 255
+  being completely opaque. An 'alpha' value of 255 causes blits to be
+  opaque, the source pixels copied to the destination (the default). Note
+  that per-surface alpha can be combined with colorkey transparency.
+
+  If 'flag' is 0, alpha blending is disabled for the surface.
+  If 'flag' is SDL_SRCALPHA, alpha blending is enabled for the surface.
+  OR:ing the flag with SDL_RLEACCEL requests RLE acceleration for the
+  surface; if SDL_RLEACCEL is not specified, the RLE accel will be removed. }
+
+
+function SDL_SetAlpha(surface: PSDL_Surface; flag: UInt32; alpha: UInt8): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetAlpha'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetAlpha}
+
+{ Sets the clipping rectangle for the destination surface in a blit.
+
+  If the clip rectangle is NULL, clipping will be disabled.
+  If the clip rectangle doesn't intersect the surface, the function will
+  return SDL_FALSE and blits will be completely clipped.  Otherwise the
+  function returns SDL_TRUE and blits to the surface will be clipped to
+  the intersection of the surface area and the clipping rectangle.
+
+  Note that blits are automatically clipped to the edges of the source
+  and destination surfaces. }
+procedure SDL_SetClipRect(surface: PSDL_Surface; rect: PSDL_Rect); cdecl;
+external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetClipRect'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetClipRect}
+
+{ Gets the clipping rectangle for the destination surface in a blit.
+  'rect' must be a pointer to a valid rectangle which will be filled
+  with the correct values. }
+procedure SDL_GetClipRect(surface: PSDL_Surface; rect: PSDL_Rect); cdecl;
+external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetClipRect'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetClipRect}
+
+{ Creates a new surface of the specified format, and then copies and maps
+  the given surface to it so the blit of the converted surface will be as
+  fast as possible.  If this function fails, it returns NULL.
+
+  The 'flags' parameter is passed to SDL_CreateRGBSurface() and has those
+  semantics.  You can also pass SDL_RLEACCEL in the flags parameter and
+  SDL will try to RLE accelerate colorkey and alpha blits in the resulting
+  surface.
+
+  This function is used internally by SDL_DisplayFormat(). }
+
+function SDL_ConvertSurface(src: PSDL_Surface; fmt: PSDL_PixelFormat; flags: UInt32): PSDL_Surface;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_ConvertSurface'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_ConvertSurface}
+
+{
+  This performs a fast blit from the source surface to the destination
+  surface.  It assumes that the source and destination rectangles are
+  the same size.  If either 'srcrect' or 'dstrect' are NULL, the entire
+  surface (src or dst) is copied.  The final blit rectangles are saved
+  in 'srcrect' and 'dstrect' after all clipping is performed.
+  If the blit is successful, it returns 0, otherwise it returns -1.
+ 
+  The blit function should not be called on a locked surface.
+ 
+  The blit semantics for surfaces with and without alpha and colorkey
+  are defined as follows:
+ 
+  RGBA->RGB:
+      SDL_SRCALPHA set:
+   alpha-blend (using alpha-channel).
+   SDL_SRCCOLORKEY ignored.
+      SDL_SRCALPHA not set:
+   copy RGB.
+   if SDL_SRCCOLORKEY set, only copy the pixels matching the
+   RGB values of the source colour key, ignoring alpha in the
+   comparison.
+ 
+  RGB->RGBA:
+      SDL_SRCALPHA set:
+   alpha-blend (using the source per-surface alpha value);
+   set destination alpha to opaque.
+      SDL_SRCALPHA not set:
+   copy RGB, set destination alpha to opaque.
+      both:
+   if SDL_SRCCOLORKEY set, only copy the pixels matching the
+   source colour key.
+ 
+  RGBA->RGBA:
+      SDL_SRCALPHA set:
+   alpha-blend (using the source alpha channel) the RGB values;
+   leave destination alpha untouched. [Note: is this correct?]
+   SDL_SRCCOLORKEY ignored.
+      SDL_SRCALPHA not set:
+   copy all of RGBA to the destination.
+   if SDL_SRCCOLORKEY set, only copy the pixels matching the
+   RGB values of the source colour key, ignoring alpha in the
+   comparison.
+ 
+  RGB->RGB:
+      SDL_SRCALPHA set:
+   alpha-blend (using the source per-surface alpha value).
+      SDL_SRCALPHA not set:
+   copy RGB.
+      both:
+   if SDL_SRCCOLORKEY set, only copy the pixels matching the
+   source colour key.
+ 
+  If either of the surfaces were in video memory, and the blit returns -2,
+  the video memory was lost, so it should be reloaded with artwork and
+  re-blitted:
+  while ( SDL_BlitSurface(image, imgrect, screen, dstrect) = -2 ) do
+  begin
+  while ( SDL_LockSurface(image) < 0 ) do
+   Sleep(10);
+  -- Write image pixels to image->pixels --
+  SDL_UnlockSurface(image);
+ end;
+
+  This happens under DirectX 5.0 when the system switches away from your
+  fullscreen application.  The lock will also fail until you have access
+  to the video memory again. }
+
+{ You should call SDL_BlitSurface() unless you know exactly how SDL
+   blitting works internally and how to use the other blit functions. }
+
+function SDL_BlitSurface(src: PSDL_Surface; srcrect: PSDL_Rect; dst: PSDL_Surface; dstrect: PSDL_Rect): Integer;
+{$EXTERNALSYM SDL_BlitSurface}
+
+{  This is the public blit function, SDL_BlitSurface(), and it performs
+   rectangle validation and clipping before passing it to SDL_LowerBlit() }
+function SDL_UpperBlit(src: PSDL_Surface; srcrect: PSDL_Rect; dst: PSDL_Surface; dstrect: PSDL_Rect): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_UpperBlit'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_UpperBlit}
+
+{ This is a semi-private blit function and it performs low-level surface
+  blitting only. }
+function SDL_LowerBlit(src: PSDL_Surface; srcrect: PSDL_Rect; dst: PSDL_Surface; dstrect: PSDL_Rect): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_LowerBlit'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_LowerBlit}
+
+{ This function performs a fast fill of the given rectangle with 'color'
+  The given rectangle is clipped to the destination surface clip area
+  and the final fill rectangle is saved in the passed in pointer.
+  If 'dstrect' is NULL, the whole surface will be filled with 'color'
+  The color should be a pixel of the format used by the surface, and
+  can be generated by the SDL_MapRGB() function.
+  This function returns 0 on success, or -1 on error. }
+
+function SDL_FillRect(dst: PSDL_Surface; dstrect: PSDL_Rect; color: UInt32) : Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_FillRect'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_FillRect}
+
+{ This function takes a surface and copies it to a new surface of the
+  pixel format and colors of the video framebuffer, suitable for fast
+  blitting onto the display surface.  It calls SDL_ConvertSurface()
+
+  If you want to take advantage of hardware colorkey or alpha blit
+  acceleration, you should set the colorkey and alpha value before
+  calling this function.
+
+  If the conversion fails or runs out of memory, it returns NULL }
+
+function SDL_DisplayFormat(surface: PSDL_Surface): PSDL_Surface; cdecl;
+external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_DisplayFormat'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_DisplayFormat}
+
+{ This function takes a surface and copies it to a new surface of the
+  pixel format and colors of the video framebuffer (if possible),
+  suitable for fast alpha blitting onto the display surface.
+  The new surface will always have an alpha channel.
+
+  If you want to take advantage of hardware colorkey or alpha blit
+  acceleration, you should set the colorkey and alpha value before
+  calling this function.
+
+  If the conversion fails or runs out of memory, it returns NULL }
+
+
+function SDL_DisplayFormatAlpha(surface: PSDL_Surface): PSDL_Surface; cdecl;
+external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_DisplayFormatAlpha'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_DisplayFormatAlpha}
+
+//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+//* YUV video surface overlay functions                                       */
+//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+{ This function creates a video output overlay
+  Calling the returned surface an overlay is something of a misnomer because
+  the contents of the display surface underneath the area where the overlay
+  is shown is undefined - it may be overwritten with the converted YUV data. }
+
+function SDL_CreateYUVOverlay(width: Integer; height: Integer; format: UInt32; display: PSDL_Surface): PSDL_Overlay;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CreateYUVOverlay'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CreateYUVOverlay}
+
+// Lock an overlay for direct access, and unlock it when you are done
+function SDL_LockYUVOverlay(Overlay: PSDL_Overlay): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_LockYUVOverlay'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_LockYUVOverlay}
+
+procedure SDL_UnlockYUVOverlay(Overlay: PSDL_Overlay); cdecl;
+external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_UnlockYUVOverlay'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_UnlockYUVOverlay}
+
+
+{ Blit a video overlay to the display surface.
+  The contents of the video surface underneath the blit destination are
+  not defined.
+  The width and height of the destination rectangle may be different from
+  that of the overlay, but currently only 2x scaling is supported. }
+
+function SDL_DisplayYUVOverlay(Overlay: PSDL_Overlay; dstrect: PSDL_Rect) : Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_DisplayYUVOverlay'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_DisplayYUVOverlay}
+
+// Free a video overlay
+procedure SDL_FreeYUVOverlay(Overlay: PSDL_Overlay);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_FreeYUVOverlay'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_FreeYUVOverlay}
+
+{------------------------------------------------------------------------------}
+{ OpenGL Routines                                                              }
+{------------------------------------------------------------------------------}
+
+{ Dynamically load a GL driver, if SDL is built with dynamic GL.
+
+  SDL links normally with the OpenGL library on your system by default,
+  but you can compile it to dynamically load the GL driver at runtime.
+  If you do this, you need to retrieve all of the GL functions used in
+  your program from the dynamic library using SDL_GL_GetProcAddress().
+
+  This is disabled in default builds of SDL. }
+
+
+function SDL_GL_LoadLibrary(filename: PChar): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GL_LoadLibrary'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GL_LoadLibrary}
+
+{ Get the address of a GL function (for extension functions) }
+function SDL_GL_GetProcAddress(procname: PChar) : Pointer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GL_GetProcAddress'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GL_GetProcAddress}
+
+{ Set an attribute of the OpenGL subsystem before intialization. }
+function SDL_GL_SetAttribute(attr: TSDL_GLAttr; value: Integer) : Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GL_SetAttribute'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GL_SetAttribute}
+
+{ Get an attribute of the OpenGL subsystem from the windowing
+  interface, such as glX. This is of course different from getting
+  the values from SDL's internal OpenGL subsystem, which only
+  stores the values you request before initialization.
+
+  Developers should track the values they pass into SDL_GL_SetAttribute
+  themselves if they want to retrieve these values. }
+
+function SDL_GL_GetAttribute(attr: TSDL_GLAttr; var value: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GL_GetAttribute'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GL_GetAttribute}
+
+{ Swap the OpenGL buffers, if double-buffering is supported. }
+
+procedure SDL_GL_SwapBuffers;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GL_SwapBuffers'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GL_SwapBuffers;}
+
+{ Internal functions that should not be called unless you have read
+  and understood the source code for these functions. }
+
+procedure SDL_GL_UpdateRects(numrects: Integer; rects: PSDL_Rect);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GL_UpdateRects'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GL_UpdateRects}
+procedure SDL_GL_Lock;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GL_Lock'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GL_Lock;}
+procedure SDL_GL_Unlock;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GL_Unlock'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GL_Unlock;}
+
+{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
+{* These functions allow interaction with the window manager, if any.        *}
+{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
+
+{ Sets/Gets the title and icon text of the display window }
+procedure SDL_WM_GetCaption(var title : PChar; var icon : PChar);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WM_GetCaption'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WM_GetCaption}
+procedure SDL_WM_SetCaption( const title : PChar; const icon : PChar);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WM_SetCaption'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WM_SetCaption}
+
+{ Sets the icon for the display window.
+  This function must be called before the first call to SDL_SetVideoMode().
+  It takes an icon surface, and a mask in MSB format.
+  If 'mask' is NULL, the entire icon surface will be used as the icon. }
+procedure SDL_WM_SetIcon(icon: PSDL_Surface; mask: PUInt8);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WM_SetIcon'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WM_SetIcon}
+
+{ This function iconifies the window, and returns 1 if it succeeded.
+  If the function succeeds, it generates an SDL_APPACTIVE loss event.
+  This function is a noop and returns 0 in non-windowed environments. }
+
+function SDL_WM_IconifyWindow: Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WM_IconifyWindow'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WM_IconifyWindow}
+
+{ Toggle fullscreen mode without changing the contents of the screen.
+  If the display surface does not require locking before accessing
+  the pixel information, then the memory pointers will not change.
+
+  If this function was able to toggle fullscreen mode (change from
+  running in a window to fullscreen, or vice-versa), it will return 1.
+  If it is not implemented, or fails, it returns 0.
+
+  The next call to SDL_SetVideoMode() will set the mode fullscreen
+  attribute based on the flags parameter - if SDL_FULLSCREEN is not
+  set, then the display will be windowed by default where supported.
+
+  This is currently only implemented in the X11 video driver. }
+
+function SDL_WM_ToggleFullScreen(surface: PSDL_Surface): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WM_ToggleFullScreen'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WM_ToggleFullScreen}
+
+{ Grabbing means that the mouse is confined to the application window,
+  and nearly all keyboard input is passed directly to the application,
+  and not interpreted by a window manager, if any. }
+
+function SDL_WM_GrabInput(mode: TSDL_GrabMode): TSDL_GrabMode;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WM_GrabInput'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WM_GrabInput}
+
+{------------------------------------------------------------------------------}
+{ mouse-routines }
+{------------------------------------------------------------------------------}
+
+{ Retrieve the current state of the mouse.
+  The current button state is returned as a button bitmask, which can
+  be tested using the SDL_BUTTON(X) macros, and x and y are set to the
+  current mouse cursor position.  You can pass NULL for either x or y. }
+
+function SDL_GetMouseState(var x: Integer; var y: Integer): UInt8;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetMouseState'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetMouseState}
+
+{ Retrieve the current state of the mouse.
+  The current button state is returned as a button bitmask, which can
+  be tested using the SDL_BUTTON(X) macros, and x and y are set to the
+  mouse deltas since the last call to SDL_GetRelativeMouseState(). }
+function SDL_GetRelativeMouseState(var x: Integer; var y: Integer): UInt8;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetRelativeMouseState'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetRelativeMouseState}
+
+{ Set the position of the mouse cursor (generates a mouse motion event) }
+procedure SDL_WarpMouse(x, y: UInt16);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WarpMouse'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WarpMouse}
+
+{ Create a cursor using the specified data and mask (in MSB format).
+  The cursor width must be a multiple of 8 bits.
+
+  The cursor is created in black and white according to the following:
+  data  mask    resulting pixel on screen
+   0     1       White
+   1     1       Black
+   0     0       Transparent
+   1     0       Inverted color if possible, black if not.
+
+  Cursors created with this function must be freed with SDL_FreeCursor(). }
+function SDL_CreateCursor(data, mask: PUInt8; w, h, hot_x, hot_y: Integer): PSDL_Cursor;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CreateCursor'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CreateCursor}
+
+{ Set the currently active cursor to the specified one.
+  If the cursor is currently visible, the change will be immediately
+  represented on the display. }
+procedure SDL_SetCursor(cursor: PSDL_Cursor);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetCursor'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetCursor}
+
+{ Returns the currently active cursor. }
+function SDL_GetCursor: PSDL_Cursor;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetCursor'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetCursor}
+
+{ Deallocates a cursor created with SDL_CreateCursor(). }
+procedure SDL_FreeCursor(cursor: PSDL_Cursor);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_FreeCursor'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_FreeCursor}
+
+{ Toggle whether or not the cursor is shown on the screen.
+  The cursor start off displayed, but can be turned off.
+  SDL_ShowCursor() returns 1 if the cursor was being displayed
+  before the call, or 0 if it was not.  You can query the current
+  state by passing a 'toggle' value of -1. }
+function SDL_ShowCursor(toggle: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_ShowCursor'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_ShowCursor}
+
+function SDL_BUTTON( Button : Integer ) : Integer;
+
+{------------------------------------------------------------------------------}
+{ Keyboard-routines                                                            }
+{------------------------------------------------------------------------------}
+
+{ Enable/Disable UNICODE translation of keyboard input.
+  This translation has some overhead, so translation defaults off.
+  If 'enable' is 1, translation is enabled.
+  If 'enable' is 0, translation is disabled.
+  If 'enable' is -1, the translation state is not changed.
+  It returns the previous state of keyboard translation. }
+function SDL_EnableUNICODE(enable: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_EnableUNICODE'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_EnableUNICODE}
+
+{ If 'delay' is set to 0, keyboard repeat is disabled. }
+function SDL_EnableKeyRepeat(delay: Integer; interval: Integer): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_EnableKeyRepeat'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_EnableKeyRepeat}
+
+procedure SDL_GetKeyRepeat(delay : PInteger; interval: PInteger);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetKeyRepeat'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetKeyRepeat}
+
+{ Get a snapshot of the current state of the keyboard.
+  Returns an array of keystates, indexed by the SDLK_* syms.
+  Used:
+
+  UInt8 *keystate = SDL_GetKeyState(NULL);
+  if ( keystate[SDLK_RETURN] ) ... <RETURN> is pressed }
+
+function SDL_GetKeyState(numkeys: PInt): PUInt8;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetKeyState'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetKeyState}
+
+{ Get the current key modifier state }
+function SDL_GetModState: TSDLMod;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetModState'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetModState}
+
+{ Set the current key modifier state
+  This does not change the keyboard state, only the key modifier flags. }
+procedure SDL_SetModState(modstate: TSDLMod);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SetModState'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SetModState}
+
+{ Get the name of an SDL virtual keysym }
+function SDL_GetKeyName(key: TSDLKey): PChar;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetKeyName'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetKeyName}
+
+{------------------------------------------------------------------------------}
+{ Active Routines                                                              }
+{------------------------------------------------------------------------------}
+
+{ This function returns the current state of the application, which is a
+  bitwise combination of SDL_APPMOUSEFOCUS, SDL_APPINPUTFOCUS, and
+  SDL_APPACTIVE.  If SDL_APPACTIVE is set, then the user is able to
+  see your application, otherwise it has been iconified or disabled. }
+
+function SDL_GetAppState: UInt8;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetAppState'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetAppState}
+
+
+{ Mutex functions }
+
+{ Create a mutex, initialized unlocked }
+
+function SDL_CreateMutex: PSDL_Mutex;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CreateMutex'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CreateMutex}
+
+{ Lock the mutex  (Returns 0, or -1 on error) }
+
+ function SDL_mutexP(mutex: PSDL_mutex): Integer;
+ cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_mutexP'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{ $ EXTERNALSYM SDL_mutexP}
+
+function SDL_LockMutex(mutex: PSDL_mutex): Integer;
+{$EXTERNALSYM SDL_LockMutex}
+
+{ Unlock the mutex  (Returns 0, or -1 on error) }
+function SDL_mutexV(mutex: PSDL_mutex): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_mutexV'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_mutexV}
+
+function SDL_UnlockMutex(mutex: PSDL_mutex): Integer;
+{$EXTERNALSYM SDL_UnlockMutex}
+
+{ Destroy a mutex }
+procedure SDL_DestroyMutex(mutex: PSDL_mutex);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_DestroyMutex'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_DestroyMutex}
+
+{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * }
+{ Semaphore functions                                           }
+{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * }
+{ Create a semaphore, initialized with value, returns NULL on failure. }
+function SDL_CreateSemaphore(initial_value: UInt32): PSDL_Sem;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CreateSemaphore'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CreateSemaphore}
+
+
+{ Destroy a semaphore }
+procedure SDL_DestroySemaphore(sem: PSDL_sem);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_DestroySemaphore'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_DestroySemaphore}
+
+{ This function suspends the calling thread until the semaphore pointed
+  to by sem has a positive count. It then atomically decreases the semaphore
+  count. }
+
+function SDL_SemWait(sem: PSDL_sem): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SemWait'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SemWait}
+
+{ Non-blocking variant of SDL_SemWait(), returns 0 if the wait succeeds,
+   SDL_MUTEX_TIMEDOUT if the wait would block, and -1 on error. }
+
+function SDL_SemTryWait(sem: PSDL_sem): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SemTryWait'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SemTryWait}
+
+{ Variant of SDL_SemWait() with a timeout in milliseconds, returns 0 if
+   the wait succeeds, SDL_MUTEX_TIMEDOUT if the wait does not succeed in
+   the allotted time, and -1 on error.
+   On some platforms this function is implemented by looping with a delay
+   of 1 ms, and so should be avoided if possible. }
+
+function SDL_SemWaitTimeout(sem: PSDL_sem; ms: UInt32): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SemWaitTimeout'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SemTryWait}
+
+{ Atomically increases the semaphore's count (not blocking), returns 0,
+   or -1 on error. }
+
+function SDL_SemPost(sem: PSDL_sem): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SemPost'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SemTryWait}
+
+{ Returns the current count of the semaphore }
+
+function SDL_SemValue(sem: PSDL_sem): UInt32;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_SemValue'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_SemValue}
+
+{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * }
+{ Condition variable functions                                  }
+{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * }
+{ Create a condition variable }
+function SDL_CreateCond: PSDL_Cond;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CreateCond'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CreateCond}
+
+{ Destroy a condition variable }
+procedure SDL_DestroyCond(cond: PSDL_Cond);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_DestroyCond'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_DestroyCond}
+
+{ Restart one of the threads that are waiting on the condition variable,
+   returns 0 or -1 on error. }
+
+function SDL_CondSignal(cond: PSDL_cond): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CondSignal'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CondSignal}
+
+{ Restart all threads that are waiting on the condition variable,
+  returns 0 or -1 on error. }
+
+function SDL_CondBroadcast(cond: PSDL_cond): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CondBroadcast'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CondBroadcast}
+
+
+{ Wait on the condition variable, unlocking the provided mutex.
+  The mutex must be locked before entering this function!
+  Returns 0 when it is signaled, or -1 on error. }
+
+function SDL_CondWait(cond: PSDL_cond; mut: PSDL_mutex): Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CondWait'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CondWait}
+
+{ Waits for at most 'ms' milliseconds, and returns 0 if the condition
+  variable is signaled, SDL_MUTEX_TIMEDOUT if the condition is not
+  signaled in the allotted time, and -1 on error.
+  On some platforms this function is implemented by looping with a delay
+  of 1 ms, and so should be avoided if possible. }
+
+function SDL_CondWaitTimeout(cond: PSDL_cond; mut: PSDL_mutex; ms: UInt32) : Integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CondWaitTimeout'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CondWaitTimeout}
+
+{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * }
+{ Condition variable functions                                  }
+{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * }
+
+{ Create a thread }
+function SDL_CreateThread(fn: PInt; data: Pointer): PSDL_Thread;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_CreateThread'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_CreateThread}
+
+{ Get the 32-bit thread identifier for the current thread }
+function SDL_ThreadID: UInt32;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_ThreadID'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_ThreadID}
+
+{ Get the 32-bit thread identifier for the specified thread,
+  equivalent to SDL_ThreadID() if the specified thread is NULL. }
+function SDL_GetThreadID(thread: PSDL_Thread): UInt32;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetThreadID'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetThreadID}
+
+{ Wait for a thread to finish.
+  The return code for the thread function is placed in the area
+  pointed to by 'status', if 'status' is not NULL. }
+
+procedure SDL_WaitThread(thread: PSDL_Thread; var status: Integer);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_WaitThread'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_WaitThread}
+
+{ Forcefully kill a thread without worrying about its state }
+procedure SDL_KillThread(thread: PSDL_Thread);
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_KillThread'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_KillThread}
+
+{------------------------------------------------------------------------------}
+{ Get Environment Routines                                                     }
+{------------------------------------------------------------------------------}
+{$IFDEF WINDOWS}
+function _putenv( const variable : Pchar ): integer;
+cdecl;
+{$ENDIF}
+
+{$IFDEF Unix}
+{$IFDEF FPC}
+function _putenv( const variable : Pchar ): integer;
+cdecl; external 'libc.so' name 'putenv';
+{$ENDIF}
+{$ENDIF}
+
+{ Put a variable of the form "name=value" into the environment }
+//function SDL_putenv(const variable: PChar): integer; cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_Init'{$ELSE} SDLLibName{$ENDIF __GPC__}SDLLibName name '';
+function SDL_putenv(const variable: PChar): integer;
+{$EXTERNALSYM SDL_putenv}
+
+// The following function has been commented out to encourage developers to use
+// SDL_putenv as it it more portable
+//function putenv(const variable: PChar): integer;
+//{$EXTERNALSYM putenv}
+
+{$IFDEF WINDOWS}
+{$IFNDEF __GPC__}
+function getenv( const name : Pchar ): PChar; cdecl;
+{$ENDIF}
+{$ENDIF}
+
+{* Retrieve a variable named "name" from the environment }
+//function SDL_getenv(const name: PChar): PChar; cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_Init'{$ELSE} SDLLibName{$ENDIF __GPC__}SDLLibName name '';
+function SDL_getenv(const name: PChar): PChar;
+{$EXTERNALSYM SDL_getenv}
+
+// The following function has been commented out to encourage developers to use
+// SDL_getenv as it it more portable
+//function getenv(const name: PChar): PChar;
+//{$EXTERNALSYM getenv}
+
+{*
+ * This function gives you custom hooks into the window manager information.
+ * It fills the structure pointed to by 'info' with custom information and
+ * returns 1 if the function is implemented.  If it's not implemented, or
+ * the version member of the 'info' structure is invalid, it returns 0.
+ *}
+function SDL_GetWMInfo(info : PSDL_SysWMinfo) : integer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_GetWMInfo'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_GetWMInfo}
+
+{------------------------------------------------------------------------------}
+
+//SDL_loadso.h
+{* This function dynamically loads a shared object and returns a pointer
+ * to the object handle (or NULL if there was an error).
+ * The 'sofile' parameter is a system dependent name of the object file.
+ *}
+function SDL_LoadObject( const sofile : PChar ) : Pointer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_LoadObject'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_LoadObject}
+
+{* Given an object handle, this function looks up the address of the
+ * named function in the shared object and returns it.  This address
+ * is no longer valid after calling SDL_UnloadObject().
+ *}
+function SDL_LoadFunction( handle : Pointer; const name : PChar ) : Pointer;
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_LoadFunction'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_LoadFunction}
+
+{* Unload a shared object from memory *}
+procedure SDL_UnloadObject( handle : Pointer );
+cdecl; external {$IFNDEF NDS}{$IFDEF __GPC__}name 'SDL_UnloadObject'{$ELSE} SDLLibName{$ENDIF __GPC__}{$ENDIF};
+{$EXTERNALSYM SDL_UnloadObject}
+
+
+
+{------------------------------------------------------------------------------}
+
+function SDL_Swap32(D: Uint32): Uint32;
+{$EXTERNALSYM SDL_Swap32}
+
+{ FreeAndNil frees the given TObject instance and sets the variable reference
+  to nil.  Be careful to only pass TObjects to this routine. }
+procedure FreeAndNil(var Obj);
+
+{ Exit procedure handling }
+
+{ AddExitProc adds the given procedure to the run-time library's exit
+  procedure list. When an application terminates, its exit procedures are
+  executed in reverse order of definition, i.e. the last procedure passed
+  to AddExitProc is the first one to get executed upon termination. }
+procedure AddExitProc(Proc: TProcedure);
+
+// Bitwise Checking functions
+function IsBitOn( value : integer; bit : Byte ) : boolean;
+
+function TurnBitOn( value : integer; bit : Byte ) : integer;
+
+function TurnBitOff( value : integer; bit : Byte ) : integer;
+
+implementation
+
+{$IFDEF __GPC__}
+  {$L 'sdl'}  { link sdl.dll.a or libsdl.so or libsdl.a }
+{$ENDIF}
+
+function SDL_TABLESIZE(table: PChar): Integer;
+begin
+  Result := SizeOf(table) div SizeOf(table[0]);
+end;
+
+procedure SDL_OutOfMemory;
+begin
+  {$IFNDEF WINDOWS}
+  SDL_Error(SDL_ENOMEM);
+  {$ENDIF}
+end;
+
+function SDL_RWSeek(context: PSDL_RWops; offset: Integer; whence: Integer) : Integer;
+begin
+  Result := context^.seek(context, offset, whence);
+end;
+
+function SDL_RWTell(context: PSDL_RWops): Integer;
+begin
+  Result := context^.seek(context, 0, 1);
+end;
+
+function SDL_RWRead(context: PSDL_RWops; ptr: Pointer; size: Integer; n: Integer): Integer;
+begin
+  Result := context^.read(context, ptr, size, n);
+end;
+
+function SDL_RWWrite(context: PSDL_RWops; ptr: Pointer; size: Integer; n: Integer): Integer;
+begin
+  Result := context^.write(context, ptr, size, n);
+end;
+
+function SDL_RWClose(context: PSDL_RWops): Integer;
+begin
+  Result := context^.close(context);
+end;
+
+function SDL_LoadWAV(filename: PChar; spec: PSDL_AudioSpec; audio_buf: PUInt8; audiolen: PUInt32): PSDL_AudioSpec;
+begin
+  Result := SDL_LoadWAV_RW(SDL_RWFromFile(filename, 'rb'), 1, spec, audio_buf, audiolen);
+end;
+
+function SDL_CDInDrive( status : TSDL_CDStatus ): LongBool;
+begin
+  Result := ord( status ) > ord( CD_ERROR );
+end;
+
+procedure FRAMES_TO_MSF(frames: Integer; var M: Integer; var S: Integer; var
+  F: Integer);
+var
+  value: Integer;
+begin
+  value := frames;
+  F := value mod CD_FPS;
+  value := value div CD_FPS;
+  S := value mod 60;
+  value := value div 60;
+  M := value;
+end;
+
+function MSF_TO_FRAMES(M: Integer; S: Integer; F: Integer): Integer;
+begin
+  Result := M * 60 * CD_FPS + S * CD_FPS + F;
+end;
+
+procedure SDL_VERSION(var X: TSDL_Version);
+begin
+  X.major := SDL_MAJOR_VERSION;
+  X.minor := SDL_MINOR_VERSION;
+  X.patch := SDL_PATCHLEVEL;
+end;
+
+function SDL_VERSIONNUM(X, Y, Z: Integer): Integer;
+begin
+  Result := X * 1000 + Y * 100 + Z;
+end;
+
+function SDL_COMPILEDVERSION: Integer;
+begin
+  Result := SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL
+    );
+end;
+
+function SDL_VERSION_ATLEAST(X, Y, Z: Integer): LongBool;
+begin
+  Result := (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z));
+end;
+
+function SDL_LoadBMP(filename: PChar): PSDL_Surface;
+begin
+  Result := SDL_LoadBMP_RW(SDL_RWFromFile(filename, 'rb'), 1);
+end;
+
+function SDL_SaveBMP(surface: PSDL_Surface; filename: PChar): Integer;
+begin
+  Result := SDL_SaveBMP_RW(surface, SDL_RWFromFile(filename, 'wb'), 1);
+end;
+
+function SDL_BlitSurface(src: PSDL_Surface; srcrect: PSDL_Rect; dst:
+  PSDL_Surface;
+  dstrect: PSDL_Rect): Integer;
+begin
+  Result := SDL_UpperBlit(src, srcrect, dst, dstrect);
+end;
+
+function SDL_AllocSurface(flags: UInt32; width, height, depth: Integer;
+  RMask, GMask, BMask, AMask: UInt32): PSDL_Surface;
+begin
+  Result := SDL_CreateRGBSurface(flags, width, height, depth, RMask, GMask,
+    BMask, AMask);
+end;
+
+function SDL_MustLock(Surface: PSDL_Surface): Boolean;
+begin
+  Result := ( ( surface^.offset <> 0 ) or
+           ( ( surface^.flags and ( SDL_HWSURFACE or SDL_ASYNCBLIT or SDL_RLEACCEL ) ) <> 0 ) );
+end;
+
+function SDL_LockMutex(mutex: PSDL_mutex): Integer;
+begin
+  Result := SDL_mutexP(mutex);
+end;
+
+function SDL_UnlockMutex(mutex: PSDL_mutex): Integer;
+begin
+  Result := SDL_mutexV(mutex);
+end;
+
+{$IFDEF WINDOWS}
+function _putenv( const variable : Pchar ): Integer;
+cdecl; external {$IFDEF __GPC__}name '_putenv'{$ELSE} 'MSVCRT.DLL'{$ENDIF __GPC__};
+{$ENDIF}
+
+
+function SDL_putenv(const variable: PChar): Integer;
+begin
+  {$IFDEF WINDOWS}
+  Result := _putenv(variable);
+  {$ENDIF}
+
+  {$IFDEF UNIX}
+  {$IFDEF FPC}
+  Result := _putenv(variable);
+  {$ELSE}
+  Result := libc.putenv(variable);
+  {$ENDIF}
+  {$ENDIF}
+end;
+
+{$IFDEF WINDOWS}
+{$IFNDEF __GPC__}
+function getenv( const name : Pchar ): PChar;
+cdecl; external {$IFDEF __GPC__}name 'getenv'{$ELSE} 'MSVCRT.DLL'{$ENDIF};
+{$ENDIF}
+{$ENDIF}
+
+function SDL_getenv(const name: PChar): PChar;
+begin
+  {$IFDEF WINDOWS}
+
+  {$IFDEF __GPC__}
+  Result := getenv( string( name ) );
+  {$ELSE}
+  Result := getenv( name );
+  {$ENDIF}
+
+  {$ELSE}
+
+  {$IFDEF UNIX}
+
+  {$IFDEF FPC}
+  Result := fpgetenv(name);
+  {$ELSE}
+  Result := libc.getenv(name);  
+  {$ENDIF}
+
+  {$ENDIF}
+
+  {$ENDIF}
+end;
+
+function SDL_BUTTON( Button : Integer ) : Integer;
+begin
+  Result := SDL_PRESSED shl ( Button - 1 );
+end;
+
+function SDL_Swap32(D: Uint32): Uint32;
+begin
+  Result := ((D shl 24) or ((D shl 8) and $00FF0000) or ((D shr 8) and $0000FF00) or (D shr 24));
+end;
+
+procedure FreeAndNil(var Obj);
+{$IFNDEF __GPC__}
+{$IFNDEF __TMT__}
+var
+  Temp: TObject;
+{$ENDIF}
+{$ENDIF}
+begin
+{$IFNDEF __GPC__}
+{$IFNDEF __TMT__}
+  Temp := TObject(Obj);
+  Pointer(Obj) := nil;
+  Temp.Free;
+{$ENDIF}
+{$ENDIF}
+end;
+
+{ Exit procedure handling }
+type
+  PExitProcInfo = ^TExitProcInfo;
+  TExitProcInfo = record
+    Next: PExitProcInfo;
+    SaveExit: Pointer;
+    Proc: TProcedure;
+  end;
+
+var
+  ExitProcList: PExitProcInfo = nil;
+
+procedure DoExitProc;
+var
+  P: PExitProcInfo;
+  Proc: TProcedure;
+begin
+  P := ExitProcList;
+  ExitProcList := P^.Next;
+  ExitProc := P^.SaveExit;
+  Proc := P^.Proc;
+  Dispose(P);
+  Proc;
+end;
+
+procedure AddExitProc(Proc: TProcedure);
+var
+  P: PExitProcInfo;
+begin
+  New(P);
+  P^.Next := ExitProcList;
+  P^.SaveExit := ExitProc;
+  P^.Proc := Proc;
+  ExitProcList := P;
+  ExitProc := @DoExitProc;
+end;
+
+function IsBitOn( value : integer; bit : Byte ) : boolean;
+begin
+  result := ( ( value and ( 1 shl bit ) ) <> 0 );
+end;
+
+function TurnBitOn( value : integer; bit : Byte ) : integer;
+begin
+  result := ( value or ( 1 shl bit ) );
+end;
+
+function TurnBitOff( value : integer; bit : Byte ) : integer;
+begin
+  result := ( value and not ( 1 shl bit ) );
+end;
+
+end.
+
+
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdl_cpuinfo.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdl_cpuinfo.pas
new file mode 100644
index 00000000..b09f19f9
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdl_cpuinfo.pas
@@ -0,0 +1,155 @@
+unit sdl_cpuinfo;
+{
+  $Id: sdl_cpuinfo.pas,v 1.2 2004/02/18 22:52:53 savage Exp $
+
+}
+{******************************************************************************}
+{                                                                              }
+{       Borland Delphi SDL - Simple DirectMedia Layer                          }
+{       Conversion of the Simple DirectMedia Layer Headers                     }
+{                                                                              }
+{ Portions created by Sam Lantinga <slouken@devolution.com> are                }
+{ Copyright (C) 1997-2004  Sam Lantinga                                        }
+{ 5635-34 Springhouse Dr.                                                      }
+{ Pleasanton, CA 94588 (USA)                                                   }
+{                                                                              }
+{ All Rights Reserved.                                                         }
+{                                                                              }
+{ The original files are : SDL_cpuinfo.h                                       }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Dominqiue Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Portions created by Dominqiue Louis are                                      }
+{ Copyright (C) 2000 - 2004 Dominqiue Louis.                                   }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   The SDL Runtime libraris on Win32  : SDL.dll on Linux : libSDL.so          }
+{   They are available from...                                                 }
+{   http://www.libsdl.org .                                                    }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{
+  $Log: sdl_cpuinfo.pas,v $
+  Revision 1.2  2004/02/18 22:52:53  savage
+  Forgot to add jedi-sdl.inc file. It's there now.
+
+  Revision 1.1  2004/02/18 22:35:54  savage
+  Brought sdl.pas up to 1.2.7 compatability
+  Thus...
+  Added SDL_GL_STEREO,
+      SDL_GL_MULTISAMPLEBUFFERS,
+      SDL_GL_MULTISAMPLESAMPLES
+
+  Add DLL/Shared object functions
+  function SDL_LoadObject( const sofile : PChar ) : Pointer;
+
+  function SDL_LoadFunction( handle : Pointer; const name : PChar ) : Pointer;
+
+  procedure SDL_UnloadObject( handle : Pointer );
+
+  Added function to create RWops from const memory: SDL_RWFromConstMem()
+  function SDL_RWFromConstMem(const mem: Pointer; size: Integer) : PSDL_RWops;
+
+  Ported SDL_cpuinfo.h so Now you can test for Specific CPU types.
+
+
+}
+{******************************************************************************}
+
+interface
+
+{$I jedi-sdl.inc}
+
+uses
+  sdl;
+
+{* This function returns true if the CPU has the RDTSC instruction
+ *}
+function SDL_HasRDTSC : SDL_Bool;
+cdecl; external {$IFDEF __GPC__}name 'SDL_HasRDTSC'{$ELSE} SDLLibName{$ENDIF __GPC__};
+{$EXTERNALSYM SDL_HasRDTSC}
+
+{* This function returns true if the CPU has MMX features
+ *}
+function SDL_HasMMX : SDL_Bool;
+cdecl; external {$IFDEF __GPC__}name 'SDL_HasMMX'{$ELSE} SDLLibName{$ENDIF __GPC__};
+{$EXTERNALSYM SDL_HasMMX}
+
+{* This function returns true if the CPU has MMX Ext. features
+ *}
+function SDL_HasMMXExt : SDL_Bool;
+cdecl; external {$IFDEF __GPC__}name 'SDL_HasMMXExt'{$ELSE} SDLLibName{$ENDIF __GPC__};
+{$EXTERNALSYM SDL_HasMMXExt}
+
+{* This function returns true if the CPU has 3DNow features
+ *}
+function SDL_Has3DNow : SDL_Bool;
+cdecl; external {$IFDEF __GPC__}name 'SDL_Has3DNow'{$ELSE} SDLLibName{$ENDIF __GPC__};
+{$EXTERNALSYM SDL_Has3DNow}
+
+{* This function returns true if the CPU has 3DNow! Ext. features
+ *}
+function SDL_Has3DNowExt : SDL_Bool;
+cdecl; external {$IFDEF __GPC__}name 'SDL_Has3DNowExt'{$ELSE} SDLLibName{$ENDIF __GPC__};
+{$EXTERNALSYM SDL_Has3DNowExt}
+
+{* This function returns true if the CPU has SSE features
+ *}
+function SDL_HasSSE : SDL_Bool;
+cdecl; external {$IFDEF __GPC__}name 'SDL_HasSSE'{$ELSE} SDLLibName{$ENDIF __GPC__};
+{$EXTERNALSYM SDL_HasSSE}
+
+{* This function returns true if the CPU has SSE2 features
+ *}
+function SDL_HasSSE2 : SDL_Bool;
+cdecl; external {$IFDEF __GPC__}name 'SDL_HasSSE2'{$ELSE} SDLLibName{$ENDIF __GPC__};
+{$EXTERNALSYM SDL_HasSSE2}
+
+{* This function returns true if the CPU has AltiVec features
+ *}
+function SDL_HasAltiVec : SDL_Bool;
+cdecl; external {$IFDEF __GPC__}name 'SDL_HasAltiVec'{$ELSE} SDLLibName{$ENDIF __GPC__};
+{$EXTERNALSYM SDL_HasAltiVec}
+
+implementation
+
+end.
+ 
\ No newline at end of file
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlgameinterface.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlgameinterface.pas
new file mode 100644
index 00000000..9a58ff40
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlgameinterface.pas
@@ -0,0 +1,202 @@
+unit sdlgameinterface;
+{
+  $Id: sdlgameinterface.pas,v 1.4 2005/08/03 18:57:31 savage Exp $
+  
+}
+{******************************************************************************}
+{                                                                              }
+{          JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer          }
+{                    Game Interface Base class                                 }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Dominqiue Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Portions created by Dominqiue Louis are                                      }
+{ Copyright (C) 2000 - 2001 Dominqiue Louis.                                   }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{                                                                              }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   The SDL Runtime libraris on Win32  : SDL.dll on Linux : libSDL.so          }
+{   They are available from...                                                 }
+{   http://www.libsdl.org .                                                    }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{   September   23 2004 - DL : Initial Creation                                }
+{
+  $Log: sdlgameinterface.pas,v $
+  Revision 1.4  2005/08/03 18:57:31  savage
+  Various updates and additions. Mainly to handle OpenGL 3D Window support and better cursor support for the mouse class
+
+  Revision 1.3  2004/10/17 18:41:49  savage
+  Slight Change to allow Reseting of Input Event handlers
+
+  Revision 1.2  2004/09/30 22:35:47  savage
+  Changes, enhancements and additions as required to get SoAoS working.
+
+
+}
+{******************************************************************************}
+
+interface
+
+uses
+  sdl,
+  sdlwindow;
+
+type
+  TGameInterfaceClass = class of TGameInterface;
+
+  TGameInterface = class( TObject )
+  private
+    FNextGameInterface : TGameInterfaceClass;
+  protected
+    Dragging : Boolean;
+    Loaded : Boolean;
+    procedure FreeSurfaces; virtual;
+    procedure Render; virtual; abstract;
+    procedure Close; virtual;
+    procedure Update( aElapsedTime : single ); virtual; 
+    procedure MouseDown( Button : Integer; Shift: TSDLMod; MousePos : TPoint ); virtual;
+    procedure MouseMove( Shift: TSDLMod; CurrentPos : TPoint; RelativePos : TPoint ); virtual;
+    procedure MouseUp( Button : Integer; Shift: TSDLMod; MousePos : TPoint ); virtual;
+    procedure MouseWheelScroll( WheelDelta : Integer; Shift: TSDLMod; MousePos : TPoint ); virtual;
+    procedure KeyDown( var Key: TSDLKey; Shift: TSDLMod; unicode : UInt16 ); virtual;
+  public
+    MainWindow : TSDLCustomWindow;
+    procedure ResetInputManager;
+    procedure LoadSurfaces; virtual;
+    function PointIsInRect( Point : TPoint; x, y, x1, y1 : integer ) : Boolean;
+    constructor Create( const aMainWindow : TSDLCustomWindow );
+    destructor Destroy; override;
+    property NextGameInterface : TGameInterfaceClass read FNextGameInterface write FNextGameInterface;
+  end;
+
+implementation
+
+{ TGameInterface }
+procedure TGameInterface.Close;
+begin
+  FNextGameInterface := nil;
+end;
+
+constructor TGameInterface.Create( const aMainWindow : TSDLCustomWindow );
+begin
+  inherited Create;
+  MainWindow := aMainWindow;
+  FNextGameInterface := TGameInterface;
+  ResetInputManager;
+end;
+
+destructor TGameInterface.Destroy;
+begin
+  if Loaded then
+    FreeSurfaces;
+  inherited;
+end;
+
+procedure TGameInterface.FreeSurfaces;
+begin
+  Loaded := False;
+end;
+
+procedure TGameInterface.KeyDown(var Key: TSDLKey; Shift: TSDLMod; unicode: UInt16);
+begin
+
+end;
+
+procedure TGameInterface.LoadSurfaces;
+begin
+  Loaded := True;
+end;
+
+procedure TGameInterface.MouseDown(Button: Integer; Shift: TSDLMod; MousePos: TPoint);
+begin
+  Dragging := True;
+end;
+
+procedure TGameInterface.MouseMove(Shift: TSDLMod; CurrentPos, RelativePos: TPoint);
+begin
+
+end;
+
+procedure TGameInterface.MouseUp(Button: Integer; Shift: TSDLMod; MousePos: TPoint);
+begin
+  Dragging := True;
+end;
+
+procedure TGameInterface.MouseWheelScroll(WheelDelta: Integer; Shift: TSDLMod; MousePos: TPoint);
+begin
+
+end;
+
+function TGameInterface.PointIsInRect( Point : TPoint; x, y, x1, y1: integer ): Boolean;
+begin
+  if ( Point.x >= x )
+  and ( Point.y >= y )
+  and ( Point.x <= x1 )
+  and ( Point.y <= y1 ) then
+    result := true
+  else
+    result := false;
+end;
+
+procedure TGameInterface.ResetInputManager;
+var
+  temp : TSDLNotifyEvent;
+begin
+  MainWindow.InputManager.Mouse.OnMouseDown := MouseDown;
+  MainWindow.InputManager.Mouse.OnMouseMove := MouseMove;
+  MainWindow.InputManager.Mouse.OnMouseUp := MouseUp;
+  MainWindow.InputManager.Mouse.OnMouseWheel := MouseWheelScroll;
+  MainWindow.InputManager.KeyBoard.OnKeyDown := KeyDown;
+  temp := Render;
+  MainWindow.OnRender := temp;
+  temp := Close;
+  MainWindow.OnClose := temp;
+  MainWindow.OnUpdate := Update;
+end;
+
+procedure TGameInterface.Update(aElapsedTime: single);
+begin
+
+end;
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdli386utils.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdli386utils.pas
new file mode 100644
index 00000000..4de4ebee
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdli386utils.pas
@@ -0,0 +1,5236 @@
+unit sdli386utils;
+{
+  $Id: sdli386utils.pas,v 1.5 2004/06/02 19:38:53 savage Exp $
+  
+}
+{******************************************************************************}
+{                                                                              }
+{       Borland Delphi SDL - Simple DirectMedia Layer                          }
+{                SDL Utility functions                                         }
+{                                                                              }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Tom Jones <tigertomjones@gmx.de>                                             }
+{                                                                              }
+{ Portions created by Tom Jones are                                            }
+{ Copyright (C) 2000 - 2001 Tom Jones.                                         }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{ R�bert Kisn�meth <mikrobi@freemail.hu>                                       }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{   Helper functions...                                                        }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   SDL.dll on Windows platforms                                               }
+{   libSDL-1.1.so.0 on Linux platform                                          }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{               2000 - TJ : Initial creation                                   }
+{                                                                              }
+{   July   13   2001 - DL : Added PutPixel and GetPixel routines.              }
+{                                                                              }
+{   Sept   14   2001 - RK : Added flipping routines.                           }
+{                                                                              }
+{   Sept   19   2001 - RK : Added PutPixel & line drawing & blitting with ADD  }
+{                           effect. Fixed a bug in SDL_PutPixel & SDL_GetPixel }
+{                           Added PSDLRect()                                   }
+{   Sept   22   2001 - DL : Removed need for Windows.pas by defining types here}
+{                           Also removed by poor attempt or a dialog box       }
+{                                                                              }
+{   Sept   25   2001 - RK : Added PixelTest, NewPutPixel, SubPixel, SubLine,   }
+{                           SubSurface, MonoSurface & TexturedSurface          }
+{                                                                              }
+{   Sept   26   2001 - DL : Made change so that it refers to native Pascal     }
+{                           types rather that Windows types. This makes it more}
+{                           portable to Linix.                                 }
+{                                                                              }
+{   Sept   27   2001 - RK : SDLUtils now can be compiled with FreePascal       }
+{                                                                              }
+{   Oct    27   2001 - JF : Added ScrollY function                             }
+{                                                                              }
+{   Jan    21   2002 - RK : Added SDL_ZoomSurface and SDL_WarpSurface          }
+{                                                                              }
+{   Mar    28   2002 - JF : Added SDL_RotateSurface                            }
+{                                                                              }
+{   May    13   2002 - RK : Improved SDL_FillRectAdd & SDL_FillRectSub         }
+{                                                                              }
+{   May    27   2002 - YS : GradientFillRect function                          }
+{                                                                              }
+{   May    30   2002 - RK : Added SDL_2xBlit, SDL_Scanline2xBlit               }
+{                           & SDL_50Scanline2xBlit                             }
+{                                                                              }
+{  June    12   2002 - RK : Added SDL_PixelTestSurfaceVsRect                   }
+{                                                                              }
+{  June    12   2002 - JF : Updated SDL_PixelTestSurfaceVsRect                 }
+{                                                                              }
+{ November  9   2002 - JF : Added Jason's boolean Surface functions            }
+{                                                                              }
+{ December 10   2002 - DE : Added Dean's SDL_ClipLine function                 }
+{                                                                              }
+{******************************************************************************}
+{
+  $Log: sdli386utils.pas,v $
+  Revision 1.5  2004/06/02 19:38:53  savage
+  Changes to SDL_GradientFillRect as suggested by
+  �ngel Eduardo Garc�a Hern�ndez.  Many thanks.
+
+  Revision 1.4  2004/05/29 23:11:53  savage
+  Changes to SDL_ScaleSurfaceRect as suggested by
+  �ngel Eduardo Garc�a Hern�ndez to fix a colour issue with the function. Many thanks.
+
+  Revision 1.3  2004/02/20 22:04:11  savage
+  Added Changes as mentioned by Rodrigo "Rui" R. (1/2 RRC2Soft) to facilitate FPC compilation and it also works in Delphi. Also syncronized the funcitons so that they are identical to sdlutils.pas, when no assembly version is available.
+
+  Revision 1.2  2004/02/14 00:23:39  savage
+  As UNIX is defined in jedi-sdl.inc this will be used to check linux compatability as well. Units have been changed to reflect this change.
+
+  Revision 1.1  2004/02/05 00:08:20  savage
+  Module 1.0 release
+
+  
+}
+
+interface
+
+{$i jedi-sdl.inc}
+
+uses
+{$IFDEF UNIX}
+  Types,
+  Xlib,
+{$ENDIF}
+  SysUtils,
+  sdl;
+
+type
+  TGradientStyle = ( gsHorizontal, gsVertical );
+
+  // Pixel procedures
+function SDL_PixelTest( SrcSurface1 : PSDL_Surface; SrcRect1 : PSDL_Rect; SrcSurface2 :
+  PSDL_Surface; SrcRect2 : PSDL_Rect; Left1, Top1, Left2, Top2 : integer ) : Boolean;
+  
+function SDL_GetPixel( SrcSurface : PSDL_Surface; x : cardinal; y : cardinal ) : Uint32;
+
+procedure SDL_PutPixel( SrcSurface : PSDL_Surface; x : integer; y : integer; Color :
+  cardinal );
+
+procedure SDL_AddPixel( SrcSurface : PSDL_Surface; x : integer; y : integer; Color :
+  cardinal );
+
+procedure SDL_SubPixel( SrcSurface : PSDL_Surface; x : integer; y : integer; Color :
+  cardinal );
+
+// Line procedures
+procedure SDL_DrawLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );overload;
+
+procedure SDL_DrawLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal ; DashLength, DashSpace : byte );  overload;  
+
+procedure SDL_AddLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+
+procedure SDL_SubLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+
+// Surface procedures
+procedure SDL_AddSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DstSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+procedure SDL_SubSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DstSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+procedure SDL_MonoSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DstSurface : PSDL_Surface; DestRect : PSDL_Rect; Color : cardinal );
+
+procedure SDL_TexturedSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DstSurface : PSDL_Surface; DestRect : PSDL_Rect; Texture : PSDL_Surface;
+  TextureRect : PSDL_Rect );
+
+procedure SDL_ZoomSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect; DstSurface : PSDL_Surface; DstRect : PSDL_Rect );
+
+procedure SDL_WarpSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect; DstSurface : PSDL_Surface; UL, UR, LR, LL : PPoint );
+
+// Flip procedures
+procedure SDL_FlipRectH( DstSurface : PSDL_Surface; Rect : PSDL_Rect );
+
+procedure SDL_FlipRectV( DstSurface : PSDL_Surface; Rect : PSDL_Rect );
+
+function PSDLRect( aLeft, aTop, aWidth, aHeight : integer ) : PSDL_Rect;
+
+function SDLRect( aLeft, aTop, aWidth, aHeight : integer ) : TSDL_Rect; overload;
+
+function SDLRect( aRect : TRect ) : TSDL_Rect; overload;
+
+function SDL_ScaleSurfaceRect( SrcSurface : PSDL_Surface; SrcX1, SrcY1, SrcW, SrcH,
+  Width, Height : integer ) : PSDL_Surface;
+
+procedure SDL_ScrollY( DstSurface : PSDL_Surface; DifY : integer );
+
+procedure SDL_ScrollX( DstSurface : PSDL_Surface; DifX : integer );
+
+procedure SDL_RotateDeg( DstSurface, SrcSurface : PSDL_Surface; SrcRect :
+  PSDL_Rect; DestX, DestY, OffsetX, OffsetY : Integer; Angle : Integer );
+
+procedure SDL_RotateRad( DstSurface, SrcSurface : PSDL_Surface; SrcRect :
+  PSDL_Rect; DestX, DestY, OffsetX, OffsetY : Integer; Angle : Single );
+
+function ValidateSurfaceRect( DstSurface : PSDL_Surface; dstrect : PSDL_Rect ) : TSDL_Rect;
+
+// Fill Rect routine
+procedure SDL_FillRectAdd( DstSurface : PSDL_Surface; dstrect : PSDL_Rect; color : UInt32 );
+
+procedure SDL_FillRectSub( DstSurface : PSDL_Surface; dstrect : PSDL_Rect; color : UInt32 );
+
+procedure SDL_GradientFillRect( DstSurface : PSDL_Surface; const Rect : PSDL_Rect; const StartColor, EndColor : TSDL_Color; const Style : TGradientStyle );
+
+// NOTE for All SDL_2xblit... function : the dest surface must be 2x of the source surface!
+procedure SDL_2xBlit( Src, Dest : PSDL_Surface );
+
+procedure SDL_Scanline2xBlit( Src, Dest : PSDL_Surface );
+
+procedure SDL_50Scanline2xBlit( Src, Dest : PSDL_Surface );
+
+function SDL_PixelTestSurfaceVsRect( SrcSurface1 : PSDL_Surface; SrcRect1 :
+PSDL_Rect; SrcRect2 : PSDL_Rect; Left1, Top1, Left2, Top2 : integer ) :
+boolean;
+
+// Jason's boolean Surface functions
+procedure SDL_ORSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+procedure SDL_ANDSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+procedure SDL_GTSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+procedure SDL_LTSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+function SDL_ClipLine(var x1,y1,x2,y2: Integer; ClipRect: PSDL_Rect) : boolean;
+
+implementation
+
+uses
+  Math;
+
+function SDL_PixelTest( SrcSurface1 : PSDL_Surface; SrcRect1 : PSDL_Rect; SrcSurface2 :
+  PSDL_Surface; SrcRect2 : PSDL_Rect; Left1, Top1, Left2, Top2 : integer ) : boolean;
+var
+  Src_Rect1, Src_Rect2 : TSDL_Rect;
+  right1, bottom1 : integer;
+  right2, bottom2 : integer;
+  Scan1Start, Scan2Start, ScanWidth, ScanHeight : cardinal;
+  Mod1, Mod2 : cardinal;
+  Addr1, Addr2 : cardinal;
+  BPP : cardinal;
+  Pitch1, Pitch2 : cardinal;
+  TransparentColor1, TransparentColor2 : cardinal;
+  tx, ty : cardinal;
+  StartTick : cardinal;
+  Color1, Color2 : cardinal;
+begin
+  Result := false;
+  if SrcRect1 = nil then
+  begin
+    with Src_Rect1 do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface1.w;
+      h := SrcSurface1.h;
+    end;
+  end
+  else
+    Src_Rect1 := SrcRect1^;
+  if SrcRect2 = nil then
+  begin
+    with Src_Rect2 do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface2.w;
+      h := SrcSurface2.h;
+    end;
+  end
+  else
+    Src_Rect2 := SrcRect2^;
+  with Src_Rect1 do
+  begin
+    Right1 := Left1 + w;
+    Bottom1 := Top1 + h;
+  end;
+  with Src_Rect2 do
+  begin
+    Right2 := Left2 + w;
+    Bottom2 := Top2 + h;
+  end;
+  if ( Left1 >= Right2 ) or ( Right1 <= Left2 ) or ( Top1 >= Bottom2 ) or ( Bottom1 <=
+    Top2 ) then
+    exit;
+  if Left1 <= Left2 then
+  begin
+    // 1. left, 2. right
+    Scan1Start := Src_Rect1.x + Left2 - Left1;
+    Scan2Start := Src_Rect2.x;
+    ScanWidth := Right1 - Left2;
+    with Src_Rect2 do
+      if ScanWidth > w then
+        ScanWidth := w;
+  end
+  else
+  begin
+    // 1. right, 2. left
+    Scan1Start := Src_Rect1.x;
+    Scan2Start := Src_Rect2.x + Left1 - Left2;
+    ScanWidth := Right2 - Left1;
+    with Src_Rect1 do
+      if ScanWidth > w then
+        ScanWidth := w;
+  end;
+  with SrcSurface1^ do
+  begin
+    Pitch1 := Pitch;
+    Addr1 := cardinal( Pixels );
+    inc( Addr1, Pitch1 * UInt32( Src_Rect1.y ) );
+    with format^ do
+    begin
+      BPP := BytesPerPixel;
+      TransparentColor1 := colorkey;
+    end;
+  end;
+  with SrcSurface2^ do
+  begin
+    TransparentColor2 := format.colorkey;
+    Pitch2 := Pitch;
+    Addr2 := cardinal( Pixels );
+    inc( Addr2, Pitch2 * UInt32( Src_Rect2.y ) );
+  end;
+  Mod1 := Pitch1 - ( ScanWidth * BPP );
+  Mod2 := Pitch2 - ( ScanWidth * BPP );
+  inc( Addr1, BPP * Scan1Start );
+  inc( Addr2, BPP * Scan2Start );
+  if Top1 <= Top2 then
+  begin
+    // 1. up, 2. down
+    ScanHeight := Bottom1 - Top2;
+    if ScanHeight > Src_Rect2.h then
+      ScanHeight := Src_Rect2.h;
+    inc( Addr1, Pitch1 * UInt32( Top2 - Top1 ) );
+  end
+  else
+  begin
+    // 1. down, 2. up
+    ScanHeight := Bottom2 - Top1;
+    if ScanHeight > Src_Rect1.h then
+      ScanHeight := Src_Rect1.h;
+    inc( Addr2, Pitch2 * UInt32( Top1 - Top2 ) );
+  end;
+  case BPP of
+    1 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PByte( Addr1 )^ <> TransparentColor1 ) and ( PByte( Addr2 )^ <>
+            TransparentColor2 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1 );
+          inc( Addr2 );
+        end;
+        inc( Addr1, Mod1 );
+        inc( Addr2, Mod2 );
+      end;
+    2 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PWord( Addr1 )^ <> TransparentColor1 ) and ( PWord( Addr2 )^ <>
+            TransparentColor2 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 2 );
+          inc( Addr2, 2 );
+        end;
+        inc( Addr1, Mod1 );
+        inc( Addr2, Mod2 );
+      end;
+    3 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          Color1 := PLongWord( Addr1 )^ and $00FFFFFF;
+          Color2 := PLongWord( Addr2 )^ and $00FFFFFF;
+          if ( Color1 <> TransparentColor1 ) and ( Color2 <> TransparentColor2 )
+            then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 3 );
+          inc( Addr2, 3 );
+        end;
+        inc( Addr1, Mod1 );
+        inc( Addr2, Mod2 );
+      end;
+    4 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PLongWord( Addr1 )^ <> TransparentColor1 ) and ( PLongWord( Addr2 )^ <>
+            TransparentColor2 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 4 );
+          inc( Addr2, 4 );
+        end;
+        inc( Addr1, Mod1 );
+        inc( Addr2, Mod2 );
+      end;
+  end;
+end;
+
+function SDL_GetPixel( SrcSurface : PSDL_Surface; x : cardinal; y : cardinal ) : Uint32;
+var
+  bpp : UInt32;
+  p : PInteger;
+begin
+  bpp := SrcSurface.format.BytesPerPixel;
+  // Here p is the address to the pixel we want to retrieve
+  p := Pointer( Uint32( SrcSurface.pixels ) + UInt32( y ) * SrcSurface.pitch + UInt32( x ) *
+    bpp );
+  case bpp of
+    1 : result := PUint8( p )^;
+    2 : result := PUint16( p )^;
+    3 :
+      if ( SDL_BYTEORDER = SDL_BIG_ENDIAN ) then
+        result := PUInt8Array( p )[ 0 ] shl 16 or PUInt8Array( p )[ 1 ] shl 8 or
+          PUInt8Array( p )[ 2 ]
+      else
+        result := PUInt8Array( p )[ 0 ] or PUInt8Array( p )[ 1 ] shl 8 or
+          PUInt8Array( p )[ 2 ] shl 16;
+    4 : result := PUint32( p )^;
+  else
+    result := 0; // shouldn't happen, but avoids warnings
+  end;
+end;
+
+procedure SDL_PutPixel( SrcSurface : PSDL_Surface; x : integer; y : integer; Color :
+  cardinal );
+var
+  Addr, Pitch, BPP : cardinal;
+begin
+  Addr := cardinal( SrcSurface.Pixels );
+  Pitch := SrcSurface.Pitch;
+  BPP := SrcSurface.format.BytesPerPixel;
+  asm
+    mov eax, y
+    mul Pitch      // EAX := y * Pitch
+    add Addr, eax  // Addr:= Addr + (y * Pitch)
+    mov eax, x
+    mov ecx, Color
+    cmp BPP, 1
+    jne @Not1BPP
+    add eax, Addr  // Now:   EAX:= Addr + (y * Pitch) + x
+    mov [eax], cl
+    jmp @Quit
+   @Not1BPP:
+    cmp BPP, 2
+    jne @Not2BPP
+    mul BPP   // EAX := x * BPP
+    add eax, Addr  // Now:   EAX:= Addr + (y * Pitch) + x * BPP
+    mov [eax], cx
+    jmp @Quit
+   @Not2BPP:
+    cmp BPP, 3
+    jne @Not3BPP
+    mul BPP   // EAX := x * BPP
+    add eax, Addr  // Now:   EAX:= Addr + (y * Pitch) + x * BPP
+    mov edx, [eax]
+    and edx, $ff000000
+    or edx, ecx
+    mov [eax], edx
+    jmp @Quit
+   @Not3BPP:
+    mul BPP   // EAX := x * BPP
+    add eax, Addr  // Now:   EAX:= Addr + (y * Pitch) + x * BPP
+    mov [eax], ecx
+   @Quit:
+  end;
+end;
+
+procedure SDL_AddPixel( SrcSurface : PSDL_Surface; x : integer; y : integer; Color :
+  cardinal );
+var
+  SrcColor, FinalColor : cardinal;
+  Addr, Pitch, Bits : cardinal;
+begin
+  if Color = 0 then
+    exit;
+  Addr := cardinal( SrcSurface.Pixels );
+  Pitch := SrcSurface.Pitch;
+  Bits := SrcSurface.format.BitsPerPixel;
+  asm
+    mov eax, y
+    mul Pitch      // EAX := y * Pitch
+    add Addr, eax  // Addr:= Addr + (y * Pitch)
+    mov eax, x
+    cmp Bits, 8
+    jne @Not8bit
+    add eax, Addr  // Now:   EAX:= Addr + (y * Pitch) + x
+    mov cl, [eax]
+    movzx ecx, cl
+    mov SrcColor, ecx
+    mov edx, Color
+    and ecx, 3
+    and edx, 3
+    add ecx, edx
+    cmp ecx, 3
+    jbe @Skip1_8bit
+    mov ecx, 3
+   @Skip1_8bit:
+    mov FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $1c
+    and edx, $1c
+    add ecx, edx
+    cmp ecx, $1c
+    jbe @Skip2_8bit
+    mov ecx, $1c
+   @Skip2_8bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $e0
+    and edx, $e0
+    add ecx, edx
+    cmp ecx, $e0
+    jbe @Skip3_8bit
+    mov ecx, $e0
+   @Skip3_8bit:
+    or ecx, FinalColor
+    mov [eax], cl
+    jmp @Quit
+   @Not8bit:
+    cmp Bits, 15
+    jne @Not15bit
+    shl eax, 1
+    add eax, Addr  // Now:   EAX:= Addr + (y * Pitch) + x * 2
+    mov ecx, [eax]
+    and ecx, $00007fff
+    mov SrcColor, ecx
+    mov edx, Color
+    and ecx, $1f
+    and edx, $1f
+    add ecx, edx
+    cmp ecx, $1f
+    jbe @Skip1_15bit
+    mov ecx, $1f
+   @Skip1_15bit:
+    mov FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $03e0
+    and edx, $03e0
+    add ecx, edx
+    cmp ecx, $03e0
+    jbe @Skip2_15bit
+    mov ecx, $03e0
+   @Skip2_15bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $7c00
+    and edx, $7c00
+    add ecx, edx
+    cmp ecx, $7c00
+    jbe @Skip3_15bit
+    mov ecx, $7c00
+   @Skip3_15bit:
+    or ecx, FinalColor
+    mov [eax], cx
+    jmp @Quit
+   @Not15Bit:
+    cmp Bits, 16
+    jne @Not16bit
+    shl eax, 1
+    add eax, Addr  // Now:   EAX:= Addr + (y * Pitch) + x * 2
+    mov ecx, [eax]
+    and ecx, $0000ffff
+    mov SrcColor, ecx
+    mov edx, Color
+    and ecx, $1f
+    and edx, $1f
+    add ecx, edx
+    cmp ecx, $1f
+    jbe @Skip1_16bit
+    mov ecx, $1f
+   @Skip1_16bit:
+    mov FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $07e0
+    and edx, $07e0
+    add ecx, edx
+    cmp ecx, $07e0
+    jbe @Skip2_16bit
+    mov ecx, $07e0
+   @Skip2_16bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $f800
+    and edx, $f800
+    add ecx, edx
+    cmp ecx, $f800
+    jbe @Skip3_16bit
+    mov ecx, $f800
+   @Skip3_16bit:
+    or ecx, FinalColor
+    mov [eax], cx
+    jmp @Quit
+   @Not16Bit:
+    cmp Bits, 24
+    jne @Not24bit
+    mov ecx, 0
+    add ecx, eax
+    shl ecx, 1
+    add ecx, eax
+    mov eax, ecx
+    jmp @32bit
+   @Not24bit:
+    shl eax, 2
+   @32bit:
+    add eax, Addr  // Now:   EAX:= Addr + (y * Pitch) + x * 2
+    mov ecx, [eax]
+    mov FinalColor, ecx
+    and FinalColor, $ff000000
+    and ecx, $00ffffff
+    mov SrcColor, ecx
+    mov edx, Color
+    and ecx, $000000ff
+    and edx, $000000ff
+    add ecx, edx
+    cmp ecx, $000000ff
+    jbe @Skip1_32bit
+    mov ecx, $000000ff
+   @Skip1_32bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $0000ff00
+    and edx, $0000ff00
+    add ecx, edx
+    cmp ecx, $0000ff00
+    jbe @Skip2_32bit
+    mov ecx, $0000ff00
+   @Skip2_32bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $00ff0000
+    and edx, $00ff0000
+    add ecx, edx
+    cmp ecx, $00ff0000
+    jbe @Skip3_32bit
+    mov ecx, $00ff0000
+   @Skip3_32bit:
+    or ecx, FinalColor
+    mov [eax], ecx
+   @Quit:
+  end;
+end;
+
+procedure SDL_SubPixel( SrcSurface : PSDL_Surface; x : integer; y : integer; Color :
+  cardinal );
+var
+  SrcColor, FinalColor : cardinal;
+  Addr, Pitch, Bits : cardinal;
+begin
+  if Color = 0 then
+    exit;
+  Addr := cardinal( SrcSurface.Pixels );
+  Pitch := SrcSurface.Pitch;
+  Bits := SrcSurface.format.BitsPerPixel;
+  asm
+    mov eax, y
+    mul Pitch      // EAX := y * Pitch
+    add Addr, eax  // Addr:= Addr + (y * Pitch)
+    mov eax, x
+    cmp Bits, 8
+    jne @Not8bit
+    add eax, Addr  // Now:   EAX:= Addr + (y * Pitch) + x
+    mov cl, [eax]
+    movzx ecx, cl
+    mov SrcColor, ecx
+    mov edx, Color
+    and ecx, 3
+    and edx, 3
+    sub ecx, edx
+    jns @Skip1_8bit
+    mov ecx, 0
+   @Skip1_8bit:
+    mov FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $1c
+    and edx, $1c
+    sub ecx, edx
+    jns @Skip2_8bit
+    mov ecx, 0
+   @Skip2_8bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $e0
+    and edx, $e0
+    sub ecx, edx
+    jns @Skip3_8bit
+    mov ecx, 0
+   @Skip3_8bit:
+    or ecx, FinalColor
+    mov [eax], cl
+    jmp @Quit
+   @Not8bit:
+    cmp Bits, 15
+    jne @Not15bit
+    shl eax, 1
+    add eax, Addr
+    mov ecx, [eax]
+    and ecx, $00007fff
+    mov SrcColor, ecx
+    mov edx, Color
+    and ecx, $1f
+    and edx, $1f
+    sub ecx, edx
+    jns @Skip1_15bit
+    mov ecx, 0
+   @Skip1_15bit:
+    mov FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $03e0
+    and edx, $03e0
+    sub ecx, edx
+    jns @Skip2_15bit
+    mov ecx, 0
+   @Skip2_15bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $7c00
+    and edx, $7c00
+    sub ecx, edx
+    jns @Skip3_15bit
+    mov ecx, 0
+   @Skip3_15bit:
+    or ecx, FinalColor
+    mov [eax], cx
+    jmp @Quit
+   @Not15Bit:
+    cmp Bits, 16
+    jne @Not16bit
+    shl eax, 1
+    add eax, Addr
+    mov ecx, [eax]
+    and ecx, $0000ffff
+    mov SrcColor, ecx
+    mov edx, Color
+    and ecx, $1f
+    and edx, $1f
+    sub ecx, edx
+    jns @Skip1_16bit
+    mov ecx, 0
+   @Skip1_16bit:
+    mov FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $07e0
+    and edx, $07e0
+    sub ecx, edx
+    jns @Skip2_16bit
+    mov ecx, 0
+   @Skip2_16bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $f800
+    and edx, $f800
+    sub ecx, edx
+    jns @Skip3_16bit
+    mov ecx, 0
+   @Skip3_16bit:
+    or ecx, FinalColor
+    mov [eax], cx
+    jmp @Quit
+   @Not16Bit:
+    cmp Bits, 24
+    jne @Not24bit
+    mov ecx, 0
+    add ecx, eax
+    shl ecx, 1
+    add ecx, eax
+    mov eax, ecx
+    jmp @32bit
+   @Not24bit:
+    shl eax, 2
+   @32bit:
+    add eax, Addr
+    mov ecx, [eax]
+    mov FinalColor, ecx
+    and FinalColor, $ff000000
+    and ecx, $00ffffff
+    mov SrcColor, ecx
+    mov edx, Color
+    and ecx, $000000ff
+    and edx, $000000ff
+    sub ecx, edx
+    jns @Skip1_32bit
+    mov ecx, 0
+   @Skip1_32bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $0000ff00
+    and edx, $0000ff00
+    sub ecx, edx
+    jns @Skip2_32bit
+    mov ecx, 0
+   @Skip2_32bit:
+    or FinalColor, ecx
+    mov ecx, SrcColor
+    mov edx, Color
+    and ecx, $00ff0000
+    and edx, $00ff0000
+    sub ecx, edx
+    jns @Skip3_32bit
+    mov ecx, 0
+   @Skip3_32bit:
+    or ecx, FinalColor
+    mov [eax], ecx
+   @Quit:
+  end;
+end;
+
+// Draw a line between x1,y1 and x2,y2 to the given surface
+// NOTE: The surface must be locked before calling this!
+procedure SDL_DrawLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+var
+  dx, dy, sdx, sdy, x, y, px, py : integer;
+begin
+  dx := x2 - x1;
+  dy := y2 - y1;
+  if dx < 0 then
+    sdx := -1
+  else
+    sdx := 1;
+  if dy < 0 then
+    sdy := -1
+  else
+    sdy := 1;
+  dx := sdx * dx + 1;
+  dy := sdy * dy + 1;
+  x := 0;
+  y := 0;
+  px := x1;
+  py := y1;
+  if dx >= dy then
+  begin
+    for x := 0 to dx - 1 do
+    begin
+      SDL_PutPixel( DstSurface, px, py, Color );
+      y := y + dy;
+      if y >= dx then
+      begin
+        y := y - dx;
+        py := py + sdy;
+      end;
+      px := px + sdx;
+    end;
+  end
+  else
+  begin
+    for y := 0 to dy - 1 do
+    begin
+      SDL_PutPixel( DstSurface, px, py, Color );
+      x := x + dx;
+      if x >= dy then
+      begin
+        x := x - dy;
+        px := px + sdx;
+      end;
+      py := py + sdy;
+    end;
+  end;
+end;
+
+// Draw a dashed line between x1,y1 and x2,y2 to the given surface
+// NOTE: The surface must be locked before calling this!
+procedure SDL_DrawLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal ; DashLength, DashSpace : byte );  overload;
+var
+  dx, dy, sdx, sdy, x, y, px, py, counter : integer; drawdash : boolean;
+begin
+  counter := 0;
+  drawdash := true; //begin line drawing with dash
+
+  //Avoid invalid user-passed dash parameters
+  if (DashLength < 1)
+  then DashLength := 1;
+  if (DashSpace < 1)
+  then DashSpace := 0;
+
+  dx := x2 - x1;
+  dy := y2 - y1;
+  if dx < 0 then
+    sdx := -1
+  else
+    sdx := 1;
+  if dy < 0 then
+    sdy := -1
+  else
+    sdy := 1;
+  dx := sdx * dx + 1;
+  dy := sdy * dy + 1;
+  x := 0;
+  y := 0;
+  px := x1;
+  py := y1;
+  if dx >= dy then
+  begin
+    for x := 0 to dx - 1 do
+      begin
+
+      //Alternate drawing dashes, or leaving spaces
+      if drawdash then
+        begin
+          SDL_PutPixel( DstSurface, px, py, Color );
+          inc(counter);
+          if (counter > DashLength-1) and (DashSpace > 0) then
+            begin
+              drawdash := false;
+              counter := 0;
+            end;
+        end
+      else //space
+        begin
+          inc(counter);
+          if counter > DashSpace-1 then
+            begin
+              drawdash := true;
+              counter := 0;
+            end;
+        end;
+
+      y := y + dy;
+      if y >= dx then
+      begin
+        y := y - dx;
+        py := py + sdy;
+      end;
+      px := px + sdx;
+    end;
+  end
+  else
+  begin
+    for y := 0 to dy - 1 do
+    begin
+
+      //Alternate drawing dashes, or leaving spaces
+      if drawdash then
+        begin
+          SDL_PutPixel( DstSurface, px, py, Color );
+          inc(counter);
+          if (counter > DashLength-1) and (DashSpace > 0) then
+            begin
+              drawdash := false;
+              counter := 0;
+            end;
+        end
+      else //space
+        begin
+          inc(counter);
+          if counter > DashSpace-1 then
+            begin
+              drawdash := true;
+              counter := 0;
+            end;
+        end;
+
+      x := x + dx;
+      if x >= dy then
+      begin
+        x := x - dy;
+        px := px + sdx;
+      end;
+      py := py + sdy;
+    end;
+  end;
+end;
+
+procedure SDL_AddLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+var
+  dx, dy, sdx, sdy, x, y, px, py : integer;
+begin
+  dx := x2 - x1;
+  dy := y2 - y1;
+  if dx < 0 then
+    sdx := -1
+  else
+    sdx := 1;
+  if dy < 0 then
+    sdy := -1
+  else
+    sdy := 1;
+  dx := sdx * dx + 1;
+  dy := sdy * dy + 1;
+  x := 0;
+  y := 0;
+  px := x1;
+  py := y1;
+  if dx >= dy then
+  begin
+    for x := 0 to dx - 1 do
+    begin
+      SDL_AddPixel( DstSurface, px, py, Color );
+      y := y + dy;
+      if y >= dx then
+      begin
+        y := y - dx;
+        py := py + sdy;
+      end;
+      px := px + sdx;
+    end;
+  end
+  else
+  begin
+    for y := 0 to dy - 1 do
+    begin
+      SDL_AddPixel( DstSurface, px, py, Color );
+      x := x + dx;
+      if x >= dy then
+      begin
+        x := x - dy;
+        px := px + sdx;
+      end;
+      py := py + sdy;
+    end;
+  end;
+end;
+
+procedure SDL_SubLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+var
+  dx, dy, sdx, sdy, x, y, px, py : integer;
+begin
+  dx := x2 - x1;
+  dy := y2 - y1;
+  if dx < 0 then
+    sdx := -1
+  else
+    sdx := 1;
+  if dy < 0 then
+    sdy := -1
+  else
+    sdy := 1;
+  dx := sdx * dx + 1;
+  dy := sdy * dy + 1;
+  x := 0;
+  y := 0;
+  px := x1;
+  py := y1;
+  if dx >= dy then
+  begin
+    for x := 0 to dx - 1 do
+    begin
+      SDL_SubPixel( DstSurface, px, py, Color );
+      y := y + dy;
+      if y >= dx then
+      begin
+        y := y - dx;
+        py := py + sdy;
+      end;
+      px := px + sdx;
+    end;
+  end
+  else
+  begin
+    for y := 0 to dy - 1 do
+    begin
+      SDL_SubPixel( DstSurface, px, py, Color );
+      x := x + dx;
+      if x >= dy then
+      begin
+        x := x - dy;
+        px := px + sdx;
+      end;
+      py := py + sdy;
+    end;
+  end;
+end;
+
+// This procedure works on 8, 15, 16, 24 and 32 bits color depth surfaces.
+// In 8 bit color depth mode the procedure works with the default packed
+//  palette (RRRGGGBB). It handles all clipping.
+procedure SDL_AddSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DstSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  Src, Dest : TSDL_Rect;
+  Diff : integer;
+  SrcAddr, DestAddr : cardinal;
+  // TransparentColor: cardinal;
+  _ebx, _esi, _edi, _esp : cardinal;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DstSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DstSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DstSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    //    TransparentColor := format.ColorKey;
+  end;
+  with DstSurface^ do
+  begin
+    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DstSurface );
+  case bits of
+    8 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        cmp al, 0
+        je @SkipColor         // if AL=0 or AL=transparent color then skip everything
+        mov esp, eax          // ESP - source color
+        mov bl, [edi]         // BL := destination color
+        mov dl, bl            // DL := destination color
+        and ax, $03           // Adding BLUE
+        and bl, $03
+        add al, bl
+        cmp al, $03
+        jbe @Skip1
+        mov al, $03
+       @Skip1:
+        mov cl, al
+        mov eax, esp          // Adding GREEN
+        mov bl, dl
+        and al, $1c
+        and bl, $1c
+        add al, bl
+        cmp al, $1c
+        jbe @Skip2
+        mov al, $1c
+       @Skip2:
+        or cl, al
+        mov eax, esp          // Adding RED
+        mov bl, dl
+        and ax, $e0
+        and bx, $e0
+        add ax, bx
+        cmp ax, $e0
+        jbe @Skip3
+        mov al, $e0
+       @Skip3:
+        or cl, al
+        mov [edi], cl
+       @SkipColor:
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    15 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax          // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AX := source color
+        cmp ax, 0
+        je @SkipColor         // if AX=0 then skip everything
+        mov esp, eax          // ESP - source color
+        mov bx, [edi]         // BX := destination color
+        mov dx, bx            // DX := destination color
+        and ax, $001F         // Adding BLUE
+        and bx, $001F
+        add ax, bx
+        cmp ax, $001F
+        jbe @Skip1
+        mov ax, $001F
+       @Skip1:
+        mov cx, ax
+        mov eax, esp          // Adding GREEN
+        mov bx, dx
+        and ax, $3E0
+        and bx, $3E0
+        add ax, bx
+        cmp ax, $3E0
+        jbe @Skip2
+        mov ax, $3E0
+       @Skip2:
+        or cx, ax
+        mov eax, esp          // Adding RED
+        mov bx, dx
+        and ax, $7C00
+        and bx, $7C00
+        add ax, bx
+        cmp ax, $7C00
+        jbe @Skip3
+        mov ax, $7C00
+       @Skip3:
+        or cx, ax
+        mov [edi], cx
+       @SkipColor:
+        add esi, 2
+        add edi, 2
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    16 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AX := source color
+        cmp ax, 0
+        je @SkipColor         // if AX=0 then skip everything
+        mov esp, eax          // ESP - source color
+        mov bx, [edi]         // BX := destination color
+        mov dx, bx            // DX := destination color
+        and ax, $1F           // Adding BLUE
+        and bx, $1F
+        add ax, bx
+        cmp ax, $1F
+        jbe @Skip1
+        mov ax, $1F
+       @Skip1:
+        mov cx, ax
+        mov eax, esp          // Adding GREEN
+        mov bx, dx
+        and ax, $7E0
+        and bx, $7E0
+        add ax, bx
+        cmp ax, $7E0
+        jbe @Skip2
+        mov ax, $7E0
+       @Skip2:
+        or cx, ax
+        mov eax, esp          // Adding RED
+        mov bx, dx
+        and eax, $F800
+        and ebx, $F800
+        add eax, ebx
+        cmp eax, $F800
+        jbe @Skip3
+        mov ax, $F800
+       @Skip3:
+        or cx, ax
+        mov [edi], cx
+       @SkipColor:
+        add esi, 2
+        add edi, 2
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    24 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       add WorkX, ax         // WorkX := Src.w * 2
+       add WorkX, ax         // WorkX := Src.w * 3
+       @Loopx:
+        mov bl, [edi]         // BX := destination color
+        mov al, [esi]         // AX := source color
+        cmp al, 0
+        je @Skip              // if AL=0 then skip COMPONENT
+        mov ah, 0             // AX := COLOR COMPONENT
+        mov bh, 0
+        add bx, ax
+        cmp bx, $00ff
+        jb @Skip
+        mov bl, $ff
+       @Skip:
+        mov [edi], bl
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    32 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       shl ax, 2
+       mov WorkX, ax         // WorkX := Src.w * 4
+       @Loopx:
+        mov bl, [edi]         // BX := destination color
+        mov al, [esi]         // AX := source color
+        cmp al, 0
+        je @Skip              // if AL=0 then skip COMPONENT
+        mov ah, 0             // AX := COLOR COMPONENT
+        mov bh, 0
+        add bx, ax
+        cmp bx, $00ff
+        jb @Skip
+        mov bl, $ff
+       @Skip:
+        mov [edi], bl
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DstSurface );
+end;
+
+procedure SDL_SubSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DstSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  Src, Dest : TSDL_Rect;
+  Diff : integer;
+  SrcAddr, DestAddr : cardinal;
+  _ebx, _esi, _edi, _esp : cardinal;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DstSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DstSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DstSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+  end;
+  with DstSurface^ do
+  begin
+    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := DstSurface.Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DstSurface );
+  case bits of
+    8 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        cmp al, 0
+        je @SkipColor         // if AL=0 then skip everything
+        mov esp, eax          // ESP - source color
+        mov bl, [edi]         // BL := destination color
+        mov dl, bl            // DL := destination color
+        and al, $03           // Subtract BLUE
+        and bl, $03
+        sub bl, al
+        jns @Skip1
+        mov bl, 0
+       @Skip1:
+        mov cl, bl
+        mov eax, esp          // Subtract GREEN
+        mov bl, dl
+        and al, $1c
+        and bl, $1c
+        sub bl, al
+        jns @Skip2
+        mov bl, 0
+       @Skip2:
+        or cl, bl
+        mov eax, esp          // Subtract RED
+        mov bl, dl
+        and ax, $e0
+        and bx, $e0
+        sub bx, ax
+        jns @Skip3
+        mov bl, 0
+       @Skip3:
+        or cl, bl
+        mov [edi], cl
+       @SkipColor:
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    15 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax          // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AX := source color
+        cmp ax, 0
+        je @SkipColor         // if AX=0 then skip everything
+        mov esp, eax          // ESP - source color
+        mov bx, [edi]         // BX := destination color
+        mov dx, bx            // DX := destination color
+        and ax, $001F         // Subtract BLUE
+        and bx, $001F
+        sub bx, ax
+        jns @Skip1
+        mov bx, 0
+       @Skip1:
+        mov cx, bx
+        mov eax, esp          // Subtract GREEN
+        mov bx, dx
+        and ax, $3E0
+        and bx, $3E0
+        sub bx, ax
+        jns @Skip2
+        mov bx, 0
+       @Skip2:
+        or cx, bx
+        mov eax, esp          // Subtract RED
+        mov bx, dx
+        and ax, $7C00
+        and bx, $7C00
+        sub bx, ax
+        jns @Skip3
+        mov bx, 0
+       @Skip3:
+        or cx, bx
+        mov [edi], cx
+       @SkipColor:
+        add esi, 2
+        add edi, 2
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    16 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AX := source color
+        cmp ax, 0
+        je @SkipColor         // if AX=0 then skip everything
+        mov esp, eax          // ESP - source color
+        mov bx, [edi]         // BX := destination color
+        mov dx, bx            // DX := destination color
+        and ax, $1F           // Subtracting BLUE
+        and bx, $1F
+        sub bx, ax
+        jns @Skip1
+        mov bx, 0
+       @Skip1:
+        mov cx, bx
+        mov eax, esp          // Adding GREEN
+        mov bx, dx
+        and ax, $7E0
+        and bx, $7E0
+        sub bx, ax
+        jns @Skip2
+        mov bx, 0
+       @Skip2:
+        or cx, bx
+        mov eax, esp          // Adding RED
+        mov bx, dx
+        and eax, $F800
+        and ebx, $F800
+        sub ebx, eax
+        jns @Skip3
+        mov bx, 0
+       @Skip3:
+        or cx, bx
+        mov [edi], cx
+       @SkipColor:
+        add esi, 2
+        add edi, 2
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    24 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       add WorkX, ax         // WorkX := Src.w * 2
+       add WorkX, ax         // WorkX := Src.w * 3
+       @Loopx:
+        mov bl, [edi]         // BX := destination color
+        mov al, [esi]         // AX := source color
+        cmp al, 0
+        je @Skip              // if AL=0 then skip COMPONENT
+        mov ah, 0             // AX := COLOR COMPONENT
+        mov bh, 0
+        sub bx, ax
+        jns @Skip
+        mov bl, 0
+       @Skip:
+        mov [edi], bl
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    32 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       shl ax, 2
+       mov WorkX, ax         // WorkX := Src.w * 4
+       @Loopx:
+        mov bl, [edi]         // BX := destination color
+        mov al, [esi]         // AX := source color
+        cmp al, 0
+        je @Skip              // if AL=0 then skip COMPONENT
+        mov ah, 0             // AX := COLOR COMPONENT
+        mov bh, 0
+        sub bx, ax
+        jns @Skip
+        mov bl, 0
+       @Skip:
+        mov [edi], bl
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DstSurface );
+end;
+
+procedure SDL_MonoSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DstSurface : PSDL_Surface; DestRect : PSDL_Rect; Color : cardinal );
+var
+  Src, Dest : TSDL_Rect;
+  Diff : integer;
+  SrcAddr, DestAddr : cardinal;
+  _ebx, _esi, _edi, _esp : cardinal;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  SrcTransparentColor : cardinal;
+  Bits : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DstSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DstSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DstSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    SrcTransparentColor := format.colorkey;
+  end;
+  with DstSurface^ do
+  begin
+    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := DstSurface.Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DstSurface );
+  case bits of
+    8 :
+      asm
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      mov ecx, Color
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        movzx eax, al
+        cmp eax, SrcTransparentColor
+        je @SkipColor         // if AL=Transparent color then skip everything
+        mov [edi], cl
+       @SkipColor:
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      end;
+    15, 16 :
+      asm
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      mov ecx, Color
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AX := source color
+        movzx eax, ax
+        cmp eax, SrcTransparentColor
+        je @SkipColor         // if AX=Transparent color then skip everything
+        mov [edi], cx
+       @SkipColor:
+        inc esi
+        inc esi
+        inc edi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      end;
+    24 :
+      asm
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov _ebx, ebx
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      mov ecx, Color
+      and ecx, $00ffffff
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov eax, [esi]         // EAX := source color
+        and eax, $00ffffff
+        cmp eax, SrcTransparentColor
+        je @SkipColor         // if EAX=Transparent color then skip everything
+        mov ebx, [edi]
+        and ebx, $ff000000
+        or ebx, ecx
+        mov [edi], ecx
+       @SkipColor:
+        add esi, 3
+        add edi, 3
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp, _esp
+      mov edi, _edi
+      mov esi, _esi
+      mov ebx, _ebx
+      end;
+    32 :
+      asm
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      mov ecx, Color
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov eax, [esi]         // EAX := source color
+        cmp eax, SrcTransparentColor
+        je @SkipColor         // if EAX=Transparent color then skip everything
+        mov [edi], ecx
+       @SkipColor:
+        add esi, 4
+        add edi, 4
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp, _esp
+      mov edi, _edi
+      mov esi, _esi
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DstSurface );
+end;
+// TextureRect.w and TextureRect.h are not used.
+// The TextureSurface's size MUST larger than the drawing rectangle!!!
+
+procedure SDL_TexturedSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DstSurface : PSDL_Surface; DestRect : PSDL_Rect; Texture : PSDL_Surface;
+  TextureRect : PSDL_Rect );
+var
+  Src, Dest : TSDL_Rect;
+  Diff : integer;
+  SrcAddr, DestAddr, TextAddr : cardinal;
+  _ebx, _esi, _edi, _esp : cardinal;
+  WorkX, WorkY : word;
+  SrcMod, DestMod, TextMod : cardinal;
+  SrcTransparentColor : cardinal;
+  Bits : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DstSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DstSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DstSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    SrcTransparentColor := format.colorkey;
+  end;
+  with DstSurface^ do
+  begin
+    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := DstSurface.Format.BitsPerPixel;
+  end;
+  with Texture^ do
+  begin
+    TextAddr := cardinal( Pixels ) + UInt32( TextureRect.y ) * Pitch +
+      UInt32( TextureRect.x ) * Format.BytesPerPixel;
+    TextMod := Pitch - Src.w * Format.BytesPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DstSurface );
+  SDL_LockSurface( Texture );
+  case bits of
+    8 :
+      asm
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov _ebx, ebx
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ebx, TextAddr
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        movzx eax, al
+        cmp eax, SrcTransparentColor
+        je @SkipColor         // if AL=Transparent color then skip everything
+        mov al, [ebx]
+        mov [edi], al
+       @SkipColor:
+        inc esi
+        inc edi
+        inc ebx
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       add ebx, TextMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx, _ebx
+      end;
+    15, 16 :
+      asm
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ecx, TextAddr
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AL := source color
+        movzx eax, ax
+        cmp eax, SrcTransparentColor
+        je @SkipColor         // if AL=Transparent color then skip everything
+        mov ax, [ecx]
+        mov [edi], ax
+       @SkipColor:
+        inc esi
+        inc esi
+        inc edi
+        inc edi
+        inc ecx
+        inc ecx
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       add ecx, TextMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      end;
+    24 :
+      asm
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov _ebx, ebx
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ebx, TextAddr
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov eax, [esi]         // AL := source color
+        and eax, $00ffffff
+        cmp eax, SrcTransparentColor
+        je @SkipColor         // if AL=Transparent color then skip everything
+        mov eax, [ebx]
+        and eax, $00ffffff
+        mov ecx, [edi]
+        and ecx, $ff000000
+        or ecx, eax
+        mov [edi], eax
+       @SkipColor:
+        add esi, 3
+        add edi, 3
+        add ebx, 3
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       add ebx, TextMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx, _ebx
+      end;
+    32 :
+      asm
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ecx, TextAddr
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov eax, [esi]         // AL := source color
+        cmp eax, SrcTransparentColor
+        je @SkipColor         // if AL=Transparent color then skip everything
+        mov eax, [ecx]
+        mov [edi], eax
+       @SkipColor:
+        add esi, 4
+        add edi, 4
+        add ecx, 4
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       add ecx, TextMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DstSurface );
+  SDL_UnlockSurface( Texture );
+end;
+
+procedure SDL_ZoomSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect; DstSurface : PSDL_Surface; DstRect : PSDL_Rect );
+var
+  xc, yc : cardinal;
+  rx, wx, ry, wy, ry16 : cardinal;
+  color : cardinal;
+  modx, mody : cardinal;
+begin
+  // Warning! No checks for surface pointers!!!
+  if srcrect = nil then
+    srcrect := @SrcSurface.clip_rect;
+  if dstrect = nil then
+    dstrect := @DstSurface.clip_rect;
+  if SDL_MustLock( SrcSurface ) then
+    SDL_LockSurface( SrcSurface );
+  if SDL_MustLock( DstSurface ) then
+    SDL_LockSurface( DstSurface );
+  modx := trunc( ( srcrect.w / dstrect.w ) * 65536 );
+  mody := trunc( ( srcrect.h / dstrect.h ) * 65536 );
+  //rx := srcrect.x * 65536;
+  ry := srcrect.y * 65536;
+  wy := dstrect.y;
+  for yc := 0 to dstrect.h - 1 do
+  begin
+    rx := srcrect.x * 65536;
+    wx := dstrect.x;
+    ry16 := ry shr 16;
+    for xc := 0 to dstrect.w - 1 do
+    begin
+      color := SDL_GetPixel( SrcSurface, rx shr 16, ry16 );
+      SDL_PutPixel( DstSurface, wx, wy, color );
+      rx := rx + modx;
+      inc( wx );
+    end;
+    ry := ry + mody;
+    inc( wy );
+  end;
+  if SDL_MustLock( SrcSurface ) then
+    SDL_UnlockSurface( SrcSurface );
+  if SDL_MustLock( DstSurface ) then
+    SDL_UnlockSurface( DstSurface );
+end;
+// Re-map a rectangular area into an area defined by four vertices
+// Converted from C to Pascal by KiCHY
+
+procedure SDL_WarpSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect; DstSurface : PSDL_Surface; UL, UR, LR, LL : PPoint );
+const
+  SHIFTS = 15; // Extend ints to limit round-off error (try 2 - 20)
+  THRESH = 1 shl SHIFTS; // Threshold for pixel size value
+  procedure CopySourceToDest( UL, UR, LR, LL : TPoint; x1, y1, x2, y2 : cardinal );
+  var
+    tm, lm, rm, bm, m : TPoint;
+    mx, my : cardinal;
+    cr : cardinal;
+  begin
+    // Does the destination area specify a single pixel?
+    if ( ( abs( ul.x - ur.x ) < THRESH ) and
+      ( abs( ul.x - lr.x ) < THRESH ) and
+      ( abs( ul.x - ll.x ) < THRESH ) and
+      ( abs( ul.y - ur.y ) < THRESH ) and
+      ( abs( ul.y - lr.y ) < THRESH ) and
+      ( abs( ul.y - ll.y ) < THRESH ) ) then
+    begin // Yes
+      cr := SDL_GetPixel( SrcSurface, ( x1 shr SHIFTS ), ( y1 shr SHIFTS ) );
+      SDL_PutPixel( DstSurface, ( ul.x shr SHIFTS ), ( ul.y shr SHIFTS ), cr );
+    end
+    else
+    begin // No
+      // Quarter the source and the destination, and then recurse
+      tm.x := ( ul.x + ur.x ) shr 1;
+      tm.y := ( ul.y + ur.y ) shr 1;
+      bm.x := ( ll.x + lr.x ) shr 1;
+      bm.y := ( ll.y + lr.y ) shr 1;
+      lm.x := ( ul.x + ll.x ) shr 1;
+      lm.y := ( ul.y + ll.y ) shr 1;
+      rm.x := ( ur.x + lr.x ) shr 1;
+      rm.y := ( ur.y + lr.y ) shr 1;
+      m.x := ( tm.x + bm.x ) shr 1;
+      m.y := ( tm.y + bm.y ) shr 1;
+      mx := ( x1 + x2 ) shr 1;
+      my := ( y1 + y2 ) shr 1;
+      CopySourceToDest( ul, tm, m, lm, x1, y1, mx, my );
+      CopySourceToDest( tm, ur, rm, m, mx, y1, x2, my );
+      CopySourceToDest( m, rm, lr, bm, mx, my, x2, y2 );
+      CopySourceToDest( lm, m, bm, ll, x1, my, mx, y2 );
+    end;
+  end;
+var
+  _UL, _UR, _LR, _LL : TPoint;
+  Rect_x, Rect_y, Rect_w, Rect_h : integer;
+begin
+  if SDL_MustLock( SrcSurface ) then
+    SDL_LockSurface( SrcSurface );
+  if SDL_MustLock( DstSurface ) then
+    SDL_LockSurface( DstSurface );
+  if SrcRect = nil then
+  begin
+    Rect_x := 0;
+    Rect_y := 0;
+    Rect_w := ( SrcSurface.w - 1 ) shl SHIFTS;
+    Rect_h := ( SrcSurface.h - 1 ) shl SHIFTS;
+  end
+  else
+  begin
+    Rect_x := SrcRect.x;
+    Rect_y := SrcRect.y;
+    Rect_w := ( SrcRect.w - 1 ) shl SHIFTS;
+    Rect_h := ( SrcRect.h - 1 ) shl SHIFTS;
+  end;
+  // Shift all values to help reduce round-off error.
+  _ul.x := ul.x shl SHIFTS;
+  _ul.y := ul.y shl SHIFTS;
+  _ur.x := ur.x shl SHIFTS;
+  _ur.y := ur.y shl SHIFTS;
+  _lr.x := lr.x shl SHIFTS;
+  _lr.y := lr.y shl SHIFTS;
+  _ll.x := ll.x shl SHIFTS;
+  _ll.y := ll.y shl SHIFTS;
+  CopySourceToDest( _ul, _ur, _lr, _ll, Rect_x, Rect_y, Rect_w, Rect_h );
+  if SDL_MustLock( SrcSurface ) then
+    SDL_UnlockSurface( SrcSurface );
+  if SDL_MustLock( DstSurface ) then
+    SDL_UnlockSurface( DstSurface );
+end;
+
+// flips a rectangle vertically on given surface
+procedure SDL_FlipRectV( DstSurface : PSDL_Surface; Rect : PSDL_Rect );
+var
+  TmpRect : TSDL_Rect;
+  Locked : boolean;
+  y, FlipLength, RowLength : integer;
+  Row1, Row2 : Pointer;
+  OneRow : TByteArray; // Optimize it if you wish
+begin
+  if DstSurface <> nil then
+  begin
+    if Rect = nil then
+    begin // if Rect=nil then we flip the whole surface
+      TmpRect := SDLRect( 0, 0, DstSurface.w, DstSurface.h );
+      Rect := @TmpRect;
+    end;
+    FlipLength := Rect^.h shr 1 - 1;
+    RowLength := Rect^.w * DstSurface^.format.BytesPerPixel;
+    if SDL_MustLock( DstSurface ) then
+    begin
+      Locked := true;
+      SDL_LockSurface( DstSurface );
+    end
+    else
+      Locked := false;
+    Row1 := pointer( cardinal( DstSurface^.Pixels ) + UInt32( Rect^.y ) *
+      DstSurface^.Pitch );
+    Row2 := pointer( cardinal( DstSurface^.Pixels ) + ( UInt32( Rect^.y ) + Rect^.h - 1 )
+      * DstSurface^.Pitch );
+    for y := 0 to FlipLength do
+    begin
+      Move( Row1^, OneRow, RowLength );
+      Move( Row2^, Row1^, RowLength );
+      Move( OneRow, Row2^, RowLength );
+      inc( cardinal( Row1 ), DstSurface^.Pitch );
+      dec( cardinal( Row2 ), DstSurface^.Pitch );
+    end;
+    if Locked then
+      SDL_UnlockSurface( DstSurface );
+  end;
+end;
+
+// flips a rectangle horizontally on given surface
+procedure SDL_FlipRectH( DstSurface : PSDL_Surface; Rect : PSDL_Rect );
+type
+  T24bit = packed array[ 0..2 ] of byte;
+  T24bitArray = packed array[ 0..8191 ] of T24bit;
+  P24bitArray = ^T24bitArray;
+  TLongWordArray = array[ 0..8191 ] of LongWord;
+  PLongWordArray = ^TLongWordArray;
+var
+  TmpRect : TSDL_Rect;
+  Row8bit : PByteArray;
+  Row16bit : PWordArray;
+  Row24bit : P24bitArray;
+  Row32bit : PLongWordArray;
+  y, x, RightSide, FlipLength : integer;
+  Pixel : cardinal;
+  Pixel24 : T24bit;
+  Locked : boolean;
+begin
+  if DstSurface <> nil then
+  begin
+    if Rect = nil then
+    begin
+      TmpRect := SDLRect( 0, 0, DstSurface.w, DstSurface.h );
+      Rect := @TmpRect;
+    end;
+    FlipLength := Rect^.w shr 1 - 1;
+    if SDL_MustLock( DstSurface ) then
+    begin
+      Locked := true;
+      SDL_LockSurface( DstSurface );
+    end
+    else
+      Locked := false;
+    case DstSurface^.format.BytesPerPixel of
+      1 :
+        begin
+          Row8Bit := pointer( cardinal( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+            DstSurface^.pitch );
+          for y := 1 to Rect^.h do
+          begin
+            RightSide := Rect^.w - 1;
+            for x := 0 to FlipLength do
+            begin
+              Pixel := Row8Bit^[ x ];
+              Row8Bit^[ x ] := Row8Bit^[ RightSide ];
+              Row8Bit^[ RightSide ] := Pixel;
+              dec( RightSide );
+            end;
+            inc( cardinal( Row8Bit ), DstSurface^.pitch );
+          end;
+        end;
+      2 :
+        begin
+          Row16Bit := pointer( cardinal( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+            DstSurface^.pitch );
+          for y := 1 to Rect^.h do
+          begin
+            RightSide := Rect^.w - 1;
+            for x := 0 to FlipLength do
+            begin
+              Pixel := Row16Bit^[ x ];
+              Row16Bit^[ x ] := Row16Bit^[ RightSide ];
+              Row16Bit^[ RightSide ] := Pixel;
+              dec( RightSide );
+            end;
+            inc( cardinal( Row16Bit ), DstSurface^.pitch );
+          end;
+        end;
+      3 :
+        begin
+          Row24Bit := pointer( cardinal( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+            DstSurface^.pitch );
+          for y := 1 to Rect^.h do
+          begin
+            RightSide := Rect^.w - 1;
+            for x := 0 to FlipLength do
+            begin
+              Pixel24 := Row24Bit^[ x ];
+              Row24Bit^[ x ] := Row24Bit^[ RightSide ];
+              Row24Bit^[ RightSide ] := Pixel24;
+              dec( RightSide );
+            end;
+            inc( cardinal( Row24Bit ), DstSurface^.pitch );
+          end;
+        end;
+      4 :
+        begin
+          Row32Bit := pointer( cardinal( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+            DstSurface^.pitch );
+          for y := 1 to Rect^.h do
+          begin
+            RightSide := Rect^.w - 1;
+            for x := 0 to FlipLength do
+            begin
+              Pixel := Row32Bit^[ x ];
+              Row32Bit^[ x ] := Row32Bit^[ RightSide ];
+              Row32Bit^[ RightSide ] := Pixel;
+              dec( RightSide );
+            end;
+            inc( cardinal( Row32Bit ), DstSurface^.pitch );
+          end;
+        end;
+    end;
+    if Locked then
+      SDL_UnlockSurface( DstSurface );
+  end;
+end;
+
+// Use with caution! The procedure allocates memory for TSDL_Rect and return with its pointer.
+// But you MUST free it after you don't need it anymore!!!
+function PSDLRect( aLeft, aTop, aWidth, aHeight : integer ) : PSDL_Rect;
+var
+  Rect : PSDL_Rect;
+begin
+  New( Rect );
+  with Rect^ do
+  begin
+    x := aLeft;
+    y := aTop;
+    w := aWidth;
+    h := aHeight;
+  end;
+  Result := Rect;
+end;
+
+function SDLRect( aLeft, aTop, aWidth, aHeight : integer ) : TSDL_Rect;
+begin
+  with result do
+  begin
+    x := aLeft;
+    y := aTop;
+    w := aWidth;
+    h := aHeight;
+  end;
+end;
+
+function SDLRect( aRect : TRect ) : TSDL_Rect;
+begin
+  with aRect do
+    result := SDLRect( Left, Top, Right - Left, Bottom - Top );
+end;
+
+procedure SDL_Stretch8( Surface, Dst_Surface : PSDL_Surface; x1, x2, y1, y2, yr, yw,
+  depth : integer );
+var
+  dx, dy, e, d, dx2 : integer;
+  src_pitch, dst_pitch : uint16;
+  src_pixels, dst_pixels : PUint8;
+begin
+  if ( yw >= dst_surface^.h ) then
+    exit;
+  dx := ( x2 - x1 );
+  dy := ( y2 - y1 );
+  dy := dy shl 1;
+  e := dy - dx;
+  dx2 := dx shl 1;
+  src_pitch := Surface^.pitch;
+  dst_pitch := dst_surface^.pitch;
+  src_pixels := PUint8( integer( Surface^.pixels ) + yr * src_pitch + y1 * depth );
+  dst_pixels := PUint8( integer( dst_surface^.pixels ) + yw * dst_pitch + x1 *
+    depth );
+  for d := 0 to dx - 1 do
+  begin
+    move( src_pixels^, dst_pixels^, depth );
+    while ( e >= 0 ) do
+    begin
+      inc( src_pixels, depth );
+      e := e - dx2;
+    end;
+    inc( dst_pixels, depth );
+    e := e + dy;
+  end;
+end;
+
+function sign( x : integer ) : integer;
+begin
+  if x > 0 then
+    result := 1
+  else
+    result := -1;
+end;
+
+// Stretches a part of a surface
+function SDL_ScaleSurfaceRect( SrcSurface : PSDL_Surface; SrcX1, SrcY1, SrcW, SrcH,
+  Width, Height : integer ) : PSDL_Surface;
+var
+  dst_surface : PSDL_Surface;
+  dx, dy, e, d, dx2, srcx2, srcy2 : integer;
+  destx1, desty1 : integer;
+begin
+  srcx2 := srcx1 + SrcW;
+  srcy2 := srcy1 + SrcH;
+  result := nil;
+  destx1 := 0;
+  desty1 := 0;
+  dx := abs( integer( Height - desty1 ) );
+  dy := abs( integer( SrcY2 - SrcY1 ) );
+  e := ( dy shl 1 ) - dx;
+  dx2 := dx shl 1;
+  dy := dy shl 1;
+  dst_surface := SDL_CreateRGBSurface( SDL_HWPALETTE, width - destx1, Height -
+      desty1,
+      SrcSurface^.Format^.BitsPerPixel,
+      SrcSurface^.Format^.RMask,
+      SrcSurface^.Format^.GMask,
+      SrcSurface^.Format^.BMask,
+      SrcSurface^.Format^.AMask );
+  if ( dst_surface^.format^.BytesPerPixel = 1 ) then
+    SDL_SetColors( dst_surface, @SrcSurface^.format^.palette^.colors^[ 0 ], 0, 256 );
+  SDL_SetColorKey( dst_surface, sdl_srccolorkey, SrcSurface^.format^.colorkey );
+  if ( SDL_MustLock( dst_surface ) ) then
+    if ( SDL_LockSurface( dst_surface ) < 0 ) then
+      exit;
+  for d := 0 to dx - 1 do
+  begin
+    SDL_Stretch8( SrcSurface, dst_surface, destx1, Width, SrcX1, SrcX2, SrcY1, desty1,
+      SrcSurface^.format^.BytesPerPixel );
+    while e >= 0 do
+    begin
+      inc( SrcY1 );
+      e := e - dx2;
+    end;
+    inc( desty1 );
+    e := e + dy;
+  end;
+  if SDL_MUSTLOCK( dst_surface ) then
+    SDL_UnlockSurface( dst_surface );
+  result := dst_surface;
+end;
+
+procedure SDL_ScrollY( DstSurface : PSDL_Surface; DifY : integer );
+var
+  r1, r2 : TSDL_Rect;
+  //buffer: PSDL_Surface;
+  YPos : Integer;
+begin
+  if ( DstSurface <> nil ) and ( DifY <> 0 ) then
+  begin
+    //if DifY > 0 then // going up
+    //begin
+    ypos := 0;
+    r1.x := 0;
+    r2.x := 0;
+    r1.w := DstSurface.w;
+    r2.w := DstSurface.w;
+    r1.h := DifY;
+    r2.h := DifY;
+    while ypos < DstSurface.h do
+    begin
+      r1.y := ypos;
+      r2.y := ypos + DifY;
+      SDL_BlitSurface( DstSurface, @r2, DstSurface, @r1 );
+      ypos := ypos + DifY;
+    end;
+    //end
+    //else
+    //begin // Going Down
+    //end;
+  end;
+end;
+
+procedure SDL_ScrollX( DstSurface : PSDL_Surface; DifX : integer );
+var
+  r1, r2 : TSDL_Rect;
+  buffer : PSDL_Surface;
+begin
+  if ( DstSurface <> nil ) and ( DifX <> 0 ) then
+  begin
+    buffer := SDL_CreateRGBSurface( SDL_HWSURFACE, ( DstSurface^.w - DifX ) * 2,
+      DstSurface^.h * 2,
+      DstSurface^.Format^.BitsPerPixel,
+      DstSurface^.Format^.RMask,
+      DstSurface^.Format^.GMask,
+      DstSurface^.Format^.BMask,
+      DstSurface^.Format^.AMask );
+    if buffer <> nil then
+    begin
+      if ( buffer^.format^.BytesPerPixel = 1 ) then
+        SDL_SetColors( buffer, @DstSurface^.format^.palette^.colors^[ 0 ], 0, 256 );
+      r1 := SDLRect( DifX, 0, buffer^.w, buffer^.h );
+      r2 := SDLRect( 0, 0, buffer^.w, buffer^.h );
+      SDL_BlitSurface( DstSurface, @r1, buffer, @r2 );
+      SDL_BlitSurface( buffer, @r2, DstSurface, @r2 );
+      SDL_FreeSurface( buffer );
+    end;
+  end;
+end;
+
+procedure SDL_RotateRad( DstSurface, SrcSurface : PSDL_Surface; SrcRect :
+  PSDL_Rect; DestX, DestY, OffsetX, OffsetY : Integer; Angle : Single );
+var
+  aSin, aCos : Single;
+  MX, MY, DX, DY, NX, NY, SX, SY, OX, OY, Width, Height, TX, TY, RX, RY, ROX, ROY : Integer;
+  Colour, TempTransparentColour : UInt32;
+  MAXX, MAXY : Integer;
+begin
+  // Rotate the surface to the target surface.
+  TempTransparentColour := SrcSurface.format.colorkey;
+  if srcRect.w > srcRect.h then
+  begin
+    Width := srcRect.w;
+    Height := srcRect.w;
+  end
+  else
+  begin
+    Width := srcRect.h;
+    Height := srcRect.h;
+  end;
+
+  maxx := DstSurface.w;
+  maxy := DstSurface.h;
+  aCos := cos( Angle );
+  aSin := sin( Angle );
+
+  Width := round( abs( srcrect.h * acos ) + abs( srcrect.w * asin ) );
+  Height := round( abs( srcrect.h * asin ) + abs( srcrect.w * acos ) );
+
+  OX := Width div 2;
+  OY := Height div 2; ;
+  MX := ( srcRect.x + ( srcRect.x + srcRect.w ) ) div 2;
+  MY := ( srcRect.y + ( srcRect.y + srcRect.h ) ) div 2;
+  ROX := ( -( srcRect.w div 2 ) ) + Offsetx;
+  ROY := ( -( srcRect.h div 2 ) ) + OffsetY;
+  Tx := ox + round( ROX * aSin - ROY * aCos );
+  Ty := oy + round( ROY * aSin + ROX * aCos );
+  SX := 0;
+  for DX := DestX - TX to DestX - TX + ( width ) do
+  begin
+    Inc( SX );
+    SY := 0;
+    for DY := DestY - TY to DestY - TY + ( Height ) do
+    begin
+      RX := SX - OX;
+      RY := SY - OY;
+      NX := round( mx + RX * aSin + RY * aCos ); //
+      NY := round( my + RY * aSin - RX * aCos ); //
+      // Used for testing only
+     //SDL_PutPixel(DstSurface.SDLSurfacePointer,DX,DY,0);
+      if ( ( DX > 0 ) and ( DX < MAXX ) ) and ( ( DY > 0 ) and ( DY < MAXY ) ) then
+      begin
+        if ( NX >= srcRect.x ) and ( NX <= srcRect.x + srcRect.w ) then
+        begin
+          if ( NY >= srcRect.y ) and ( NY <= srcRect.y + srcRect.h ) then
+          begin
+            Colour := SDL_GetPixel( SrcSurface, NX, NY );
+            if Colour <> TempTransparentColour then
+            begin
+              SDL_PutPixel( DstSurface, DX, DY, Colour );
+            end;
+          end;
+        end;
+      end;
+      inc( SY );
+    end;
+  end;
+end;
+
+procedure SDL_RotateDeg( DstSurface, SrcSurface : PSDL_Surface; SrcRect :
+  PSDL_Rect; DestX, DestY, OffsetX, OffsetY : Integer; Angle : Integer );
+begin
+  SDL_RotateRad( DstSurface, SrcSurface, SrcRect, DestX, DestY, OffsetX, OffsetY, DegToRad( Angle ) );
+end;
+
+function ValidateSurfaceRect( DstSurface : PSDL_Surface; dstrect : PSDL_Rect ) : TSDL_Rect;
+var
+  RealRect : TSDL_Rect;
+  OutOfRange : Boolean;
+begin
+  OutOfRange := false;
+  if dstrect = nil then
+  begin
+    RealRect.x := 0;
+    RealRect.y := 0;
+    RealRect.w := DstSurface.w;
+    RealRect.h := DstSurface.h;
+  end
+  else
+  begin
+    if dstrect.x < DstSurface.w then
+    begin
+      RealRect.x := dstrect.x;
+    end
+    else if dstrect.x < 0 then
+    begin
+      realrect.x := 0;
+    end
+    else
+    begin
+      OutOfRange := True;
+    end;
+    if dstrect.y < DstSurface.h then
+    begin
+      RealRect.y := dstrect.y;
+    end
+    else if dstrect.y < 0 then
+    begin
+      realrect.y := 0;
+    end
+    else
+    begin
+      OutOfRange := True;
+    end;
+    if OutOfRange = False then
+    begin
+      if realrect.x + dstrect.w <= DstSurface.w then
+      begin
+        RealRect.w := dstrect.w;
+      end
+      else
+      begin
+        RealRect.w := dstrect.w - realrect.x;
+      end;
+      if realrect.y + dstrect.h <= DstSurface.h then
+      begin
+        RealRect.h := dstrect.h;
+      end
+      else
+      begin
+        RealRect.h := dstrect.h - realrect.y;
+      end;
+    end;
+  end;
+  if OutOfRange = False then
+  begin
+    result := realrect;
+  end
+  else
+  begin
+    realrect.w := 0;
+    realrect.h := 0;
+    realrect.x := 0;
+    realrect.y := 0;
+    result := realrect;
+  end;
+end;
+
+procedure SDL_FillRectAdd( DstSurface : PSDL_Surface; dstrect : PSDL_Rect; color : UInt32 );
+var
+  RealRect : TSDL_Rect;
+  Addr : pointer;
+  ModX, BPP : cardinal;
+  x, y, R, G, B, SrcColor : cardinal;
+begin
+  RealRect := ValidateSurfaceRect( DstSurface, DstRect );
+  if ( RealRect.w > 0 ) and ( RealRect.h > 0 ) then
+  begin
+    SDL_LockSurface( DstSurface );
+    BPP := DstSurface.format.BytesPerPixel;
+    with DstSurface^ do
+    begin
+      Addr := pointer( UInt32( pixels ) + UInt32( RealRect.y ) * pitch + UInt32( RealRect.x ) * BPP );
+      ModX := Pitch - UInt32( RealRect.w ) * BPP;
+    end;
+    case DstSurface.format.BitsPerPixel of
+      8 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $E0 + Color and $E0;
+              G := SrcColor and $1C + Color and $1C;
+              B := SrcColor and $03 + Color and $03;
+              if R > $E0 then
+                R := $E0;
+              if G > $1C then
+                G := $1C;
+              if B > $03 then
+                B := $03;
+              PUInt8( Addr )^ := R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+      15 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $7C00 + Color and $7C00;
+              G := SrcColor and $03E0 + Color and $03E0;
+              B := SrcColor and $001F + Color and $001F;
+              if R > $7C00 then
+                R := $7C00;
+              if G > $03E0 then
+                G := $03E0;
+              if B > $001F then
+                B := $001F;
+              PUInt16( Addr )^ := R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+      16 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $F800 + Color and $F800;
+              G := SrcColor and $07C0 + Color and $07C0;
+              B := SrcColor and $001F + Color and $001F;
+              if R > $F800 then
+                R := $F800;
+              if G > $07C0 then
+                G := $07C0;
+              if B > $001F then
+                B := $001F;
+              PUInt16( Addr )^ := R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+      24 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $00FF0000 + Color and $00FF0000;
+              G := SrcColor and $0000FF00 + Color and $0000FF00;
+              B := SrcColor and $000000FF + Color and $000000FF;
+              if R > $FF0000 then
+                R := $FF0000;
+              if G > $00FF00 then
+                G := $00FF00;
+              if B > $0000FF then
+                B := $0000FF;
+              PUInt32( Addr )^ := SrcColor and $FF000000 or R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+      32 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $00FF0000 + Color and $00FF0000;
+              G := SrcColor and $0000FF00 + Color and $0000FF00;
+              B := SrcColor and $000000FF + Color and $000000FF;
+              if R > $FF0000 then
+                R := $FF0000;
+              if G > $00FF00 then
+                G := $00FF00;
+              if B > $0000FF then
+                B := $0000FF;
+              PUInt32( Addr )^ := R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+    end;
+    SDL_UnlockSurface( DstSurface );
+  end;
+end;
+
+procedure SDL_FillRectSub( DstSurface : PSDL_Surface; dstrect : PSDL_Rect; color : UInt32 );
+var
+  RealRect : TSDL_Rect;
+  Addr : pointer;
+  ModX, BPP : cardinal;
+  x, y, R, G, B, SrcColor : cardinal;
+begin
+  RealRect := ValidateSurfaceRect( DstSurface, DstRect );
+  if ( RealRect.w > 0 ) and ( RealRect.h > 0 ) then
+  begin
+    SDL_LockSurface( DstSurface );
+    BPP := DstSurface.format.BytesPerPixel;
+    with DstSurface^ do
+    begin
+      Addr := pointer( UInt32( pixels ) + UInt32( RealRect.y ) * pitch + UInt32( RealRect.x ) * BPP );
+      ModX := Pitch - UInt32( RealRect.w ) * BPP;
+    end;
+    case DstSurface.format.BitsPerPixel of
+      8 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $E0 - Color and $E0;
+              G := SrcColor and $1C - Color and $1C;
+              B := SrcColor and $03 - Color and $03;
+              if R > $E0 then
+                R := 0;
+              if G > $1C then
+                G := 0;
+              if B > $03 then
+                B := 0;
+              PUInt8( Addr )^ := R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+      15 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $7C00 - Color and $7C00;
+              G := SrcColor and $03E0 - Color and $03E0;
+              B := SrcColor and $001F - Color and $001F;
+              if R > $7C00 then
+                R := 0;
+              if G > $03E0 then
+                G := 0;
+              if B > $001F then
+                B := 0;
+              PUInt16( Addr )^ := R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+      16 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $F800 - Color and $F800;
+              G := SrcColor and $07C0 - Color and $07C0;
+              B := SrcColor and $001F - Color and $001F;
+              if R > $F800 then
+                R := 0;
+              if G > $07C0 then
+                G := 0;
+              if B > $001F then
+                B := 0;
+              PUInt16( Addr )^ := R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+      24 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $00FF0000 - Color and $00FF0000;
+              G := SrcColor and $0000FF00 - Color and $0000FF00;
+              B := SrcColor and $000000FF - Color and $000000FF;
+              if R > $FF0000 then
+                R := 0;
+              if G > $00FF00 then
+                G := 0;
+              if B > $0000FF then
+                B := 0;
+              PUInt32( Addr )^ := SrcColor and $FF000000 or R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+      32 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $00FF0000 - Color and $00FF0000;
+              G := SrcColor and $0000FF00 - Color and $0000FF00;
+              B := SrcColor and $000000FF - Color and $000000FF;
+              if R > $FF0000 then
+                R := 0;
+              if G > $00FF00 then
+                G := 0;
+              if B > $0000FF then
+                B := 0;
+              PUInt32( Addr )^ := R or G or B;
+              inc( UInt32( Addr ), BPP );
+            end;
+            inc( UInt32( Addr ), ModX );
+          end;
+        end;
+    end;
+    SDL_UnlockSurface( DstSurface );
+  end;
+end;
+
+procedure SDL_GradientFillRect( DstSurface : PSDL_Surface; const Rect : PSDL_Rect; const StartColor, EndColor : TSDL_Color; const Style : TGradientStyle );
+var
+  FBC : array[ 0..255 ] of Cardinal;
+  // temp vars
+  i, YR, YG, YB, SR, SG, SB, DR, DG, DB : Integer;
+
+  TempStepV, TempStepH : Single;
+  TempLeft, TempTop, TempHeight, TempWidth : integer;
+  TempRect : TSDL_Rect;
+
+begin
+  // calc FBC
+  YR := StartColor.r;
+  YG := StartColor.g;
+  YB := StartColor.b;
+  SR := YR;
+  SG := YG;
+  SB := YB;
+  DR := EndColor.r - SR;
+  DG := EndColor.g - SG;
+  DB := EndColor.b - SB;
+
+  for i := 0 to 255 do
+  begin
+    FBC[ i ] := SDL_MapRGB( DstSurface.format, YR, YG, YB );
+    YR := SR + round( DR / 255 * i );
+    YG := SG + round( DG / 255 * i );
+    YB := SB + round( DB / 255 * i );
+  end;
+
+  //  if aStyle = 1 then begin
+  TempStepH := Rect.w / 255;
+  TempStepV := Rect.h / 255;
+  TempHeight := Trunc( TempStepV + 1 );
+  TempWidth := Trunc( TempStepH + 1 );
+  TempTop := 0;
+  TempLeft := 0;
+  TempRect.x := Rect.x;
+  TempRect.y := Rect.y;
+  TempRect.h := Rect.h;
+  TempRect.w := Rect.w;
+
+  case Style of
+    gsHorizontal :
+      begin
+        TempRect.h := TempHeight;
+        for i := 0 to 255 do
+        begin
+          TempRect.y := Rect.y + TempTop;
+          SDL_FillRect( DstSurface, @TempRect, FBC[ i ] );
+          TempTop := Trunc( TempStepV * i );
+        end;
+      end;
+    gsVertical :
+      begin
+        TempRect.w := TempWidth;
+        for i := 0 to 255 do
+        begin
+          TempRect.x := Rect.x + TempLeft;
+          SDL_FillRect( DstSurface, @TempRect, FBC[ i ] );
+          TempLeft := Trunc( TempStepH * i );
+        end;
+      end;
+  end;
+end;
+
+procedure SDL_2xBlit( Src, Dest : PSDL_Surface );
+var
+  ReadAddr, WriteAddr, ReadRow, WriteRow : UInt32;
+  SrcPitch, DestPitch, x, y, w, h : UInt32;
+begin
+  if ( Src = nil ) or ( Dest = nil ) then
+    exit;
+  if ( Src.w shl 1 ) < Dest.w then
+    exit;
+  if ( Src.h shl 1 ) < Dest.h then
+    exit;
+
+  if SDL_MustLock( Src ) then
+    SDL_LockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_LockSurface( Dest );
+
+  ReadRow := UInt32( Src.Pixels );
+  WriteRow := UInt32( Dest.Pixels );
+
+  SrcPitch := Src.pitch;
+  DestPitch := Dest.pitch;
+
+  w := Src.w;
+  h := Src.h;
+
+  case Src.format.BytesPerPixel of
+    1 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+           mov ebx, DestPitch
+
+           @LoopX:
+             mov al, [ecx] // PUInt8(WriteAddr)^ := PUInt8(ReadAddr)^;
+             mov [edx], al
+             mov [edx + 1], al // PUInt8(WriteAddr + 1)^ := PUInt8(ReadAddr)^;
+             mov [edx + ebx], al // PUInt8(WriteAddr + DestPitch)^ := PUInt8(ReadAddr)^;
+             mov [edx + ebx + 1], al // PUInt8(WriteAddr + DestPitch + 1)^ := PUInt8(ReadAddr)^;
+
+             inc ecx // inc(ReadAddr);
+             add edx, 2 // inc(WriteAddr, 2);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    2 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+           mov ebx, DestPitch
+
+           @LoopX:
+             mov ax, [ecx] // PUInt16(WriteAddr)^ := PUInt16(ReadAddr)^;
+             mov [edx], ax
+             mov [edx + 2], ax // PUInt16(WriteAddr + 2)^ := PUInt16(ReadAddr)^;
+             mov [edx + ebx], ax // PUInt16(WriteAddr + DestPitch)^ := PUInt16(ReadAddr)^;
+             mov [edx + ebx + 2], ax // PUInt16(WriteAddr + DestPitch + 2)^ := PUInt16(ReadAddr)^;
+
+             add ecx, 2 // inc(ReadAddr, 2);
+             add edx, 4 // inc(WriteAddr, 4);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    3 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+           mov ebx, DestPitch
+
+           @LoopX:
+             mov eax, [ecx] // (PUInt32(WriteAddr)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             and eax, $00ffffff
+             and dword ptr [edx], $ff000000
+             or [edx], eax
+             and dword ptr [edx + 3], $00ffffff // (PUInt32(WriteAddr + 3)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             or [edx + 3], eax
+             and dword ptr [edx + ebx], $00ffffff // (PUInt32(WriteAddr + DestPitch)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             or [edx + ebx], eax
+             and dword ptr [edx + ebx + 3], $00ffffff // (PUInt32(WriteAddr + DestPitch + 3)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             or [edx + ebx + 3], eax
+
+             add ecx, 3 // inc(ReadAddr, 3);
+             add edx, 6 // inc(WriteAddr, 6);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    4 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+           mov ebx, DestPitch
+
+           @LoopX:
+             mov eax, [ecx] // PUInt32(WriteAddr)^ := PUInt32(ReadAddr)^;
+             mov [edx], eax
+             mov [edx + 4], eax // PUInt32(WriteAddr + 4)^ := PUInt32(ReadAddr)^;
+             mov [edx + ebx], eax // PUInt32(WriteAddr + DestPitch)^ := PUInt32(ReadAddr)^;
+             mov [edx + ebx + 4], eax // PUInt32(WriteAddr + DestPitch + 4)^ := PUInt32(ReadAddr)^;
+
+             add ecx, 4 // inc(ReadAddr, 4);
+             add edx, 8 // inc(WriteAddr, 8);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+  end;
+
+  if SDL_MustLock( Src ) then
+    SDL_UnlockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_UnlockSurface( Dest );
+end;
+
+procedure SDL_Scanline2xBlit( Src, Dest : PSDL_Surface );
+var
+  ReadAddr, WriteAddr, ReadRow, WriteRow : UInt32;
+  SrcPitch, DestPitch, x, y, w, h : UInt32;
+begin
+  if ( Src = nil ) or ( Dest = nil ) then
+    exit;
+  if ( Src.w shl 1 ) < Dest.w then
+    exit;
+  if ( Src.h shl 1 ) < Dest.h then
+    exit;
+
+  if SDL_MustLock( Src ) then
+    SDL_LockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_LockSurface( Dest );
+
+  ReadRow := UInt32( Src.Pixels );
+  WriteRow := UInt32( Dest.Pixels );
+
+  SrcPitch := Src.pitch;
+  DestPitch := Dest.pitch;
+
+  w := Src.w;
+  h := Src.h;
+
+  case Src.format.BytesPerPixel of
+    1 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+
+           @LoopX:
+             mov al, [ecx] // PUInt8(WriteAddr)^ := PUInt8(ReadAddr)^;
+             mov [edx], al
+             mov [edx + 1], al // PUInt8(WriteAddr + 1)^ := PUInt8(ReadAddr)^;
+
+             inc ecx // inc(ReadAddr);
+             add edx, 2 // inc(WriteAddr, 2);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    2 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+
+           @LoopX:
+             mov ax, [ecx] // PUInt16(WriteAddr)^ := PUInt16(ReadAddr)^;
+             mov [edx], ax
+             mov [edx + 2], eax // PUInt16(WriteAddr + 2)^ := PUInt16(ReadAddr)^;
+
+             add ecx, 2 // inc(ReadAddr, 2);
+             add edx, 4 // inc(WriteAddr, 4);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    3 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+
+           @LoopX:
+             mov eax, [ecx] // (PUInt32(WriteAddr)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             and eax, $00ffffff
+             and dword ptr [edx], $ff000000
+             or [edx], eax
+             and dword ptr [edx + 3], $00ffffff // (PUInt32(WriteAddr + 3)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             or [edx + 3], eax
+
+             add ecx, 3 // inc(ReadAddr, 3);
+             add edx, 6 // inc(WriteAddr, 6);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    4 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+
+           @LoopX:
+             mov eax, [ecx] // PUInt32(WriteAddr)^ := PUInt32(ReadAddr)^;
+             mov [edx], eax
+             mov [edx + 4], eax // PUInt32(WriteAddr + 4)^ := PUInt32(ReadAddr)^;
+
+             add ecx, 4 // inc(ReadAddr, 4);
+             add edx, 8 // inc(WriteAddr, 8);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+  end;
+
+  if SDL_MustLock( Src ) then
+    SDL_UnlockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_UnlockSurface( Dest );
+end;
+
+procedure SDL_50Scanline2xBlit( Src, Dest : PSDL_Surface );
+var
+  ReadAddr, WriteAddr, ReadRow, WriteRow : UInt32;
+  SrcPitch, DestPitch, x, y, w, h : UInt32;
+begin
+  if ( Src = nil ) or ( Dest = nil ) then
+    exit;
+  if ( Src.w shl 1 ) < Dest.w then
+    exit;
+  if ( Src.h shl 1 ) < Dest.h then
+    exit;
+
+  if SDL_MustLock( Src ) then
+    SDL_LockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_LockSurface( Dest );
+
+  ReadRow := UInt32( Src.Pixels );
+  WriteRow := UInt32( Dest.Pixels );
+
+  SrcPitch := Src.pitch;
+  DestPitch := Dest.pitch;
+
+  w := Src.w;
+  h := Src.h;
+
+  case Src.format.BitsPerPixel of
+    8 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+           mov ebx, DestPitch
+
+           @LoopX:
+             mov al, [ecx] // PUInt8(WriteAddr)^ := PUInt8(ReadAddr)^;
+             mov [edx], al
+             mov [edx + 1], al // PUInt8(WriteAddr + 1)^ := PUInt8(ReadAddr)^;
+             shr al, 1
+             and al, $6d
+             mov [edx + ebx], al // PUInt8(WriteAddr + DestPitch)^ := PUInt8(ReadAddr)^;
+             mov [edx + ebx + 1], al // PUInt8(WriteAddr + DestPitch + 1)^ := PUInt8(ReadAddr)^;
+
+             inc ecx // inc(ReadAddr);
+             add edx, 2 // inc(WriteAddr, 2);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    15 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+           mov ebx, DestPitch
+
+           @LoopX:
+             mov ax, [ecx] // PUInt16(WriteAddr)^ := PUInt16(ReadAddr)^;
+             mov [edx], ax
+             mov [edx + 2], ax // PUInt16(WriteAddr + 2)^ := PUInt16(ReadAddr)^;
+             shr ax, 1
+             and ax, $3def
+             mov [edx + ebx], ax // PUInt16(WriteAddr + DestPitch)^ := PUInt16(ReadAddr)^;
+             mov [edx + ebx + 2], ax // PUInt16(WriteAddr + DestPitch + 2)^ := PUInt16(ReadAddr)^;
+
+             add ecx, 2 // inc(ReadAddr, 2);
+             add edx, 4 // inc(WriteAddr, 4);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    16 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+           mov ebx, DestPitch
+
+           @LoopX:
+             mov ax, [ecx] // PUInt16(WriteAddr)^ := PUInt16(ReadAddr)^;
+             mov [edx], ax
+             mov [edx + 2], ax // PUInt16(WriteAddr + 2)^ := PUInt16(ReadAddr)^;
+             shr ax, 1
+             and ax, $7bef
+             mov [edx + ebx], ax // PUInt16(WriteAddr + DestPitch)^ := PUInt16(ReadAddr)^;
+             mov [edx + ebx + 2], ax // PUInt16(WriteAddr + DestPitch + 2)^ := PUInt16(ReadAddr)^;
+
+             add ecx, 2 // inc(ReadAddr, 2);
+             add edx, 4 // inc(WriteAddr, 4);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    24 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+           mov ebx, DestPitch
+
+           @LoopX:
+             mov eax, [ecx] // (PUInt32(WriteAddr)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             and eax, $00ffffff
+             and dword ptr [edx], $ff000000
+             or [edx], eax
+             and dword ptr [edx + 3], $00ffffff // (PUInt32(WriteAddr + 3)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             or [edx + 3], eax
+             shr eax, 1
+             and eax, $007f7f7f
+             and dword ptr [edx + ebx], $00ffffff // (PUInt32(WriteAddr + DestPitch)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             or [edx + ebx], eax
+             and dword ptr [edx + ebx + 3], $00ffffff // (PUInt32(WriteAddr + DestPitch + 3)^ and $ff000000) or (PUInt32(ReadAddr)^ and $00ffffff);
+             or [edx + ebx + 3], eax
+
+             add ecx, 3 // inc(ReadAddr, 3);
+             add edx, 6 // inc(WriteAddr, 6);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+    32 :
+      asm
+         push ebx
+         mov eax, h // for y := 1 to Src.h do
+         mov y, eax
+         @LoopY:
+           mov eax, ReadRow // ReadAddr := ReadRow;
+           mov ReadAddr, eax
+
+           mov eax, WriteRow // WriteAddr := WriteRow;
+           mov WriteAddr, eax
+
+           mov eax, w // for x := 1 to Src.w do
+           mov x, eax
+
+           mov ecx, ReadAddr
+           mov edx, WriteAddr
+           mov ebx, DestPitch
+
+           @LoopX:
+             mov eax, [ecx] // PUInt32(WriteAddr)^ := PUInt32(ReadAddr)^;
+             mov [edx], eax
+             mov [edx + 4], eax // PUInt32(WriteAddr + 4)^ := PUInt32(ReadAddr)^;
+             shr eax, 1
+             and eax, $7f7f7f7f
+             mov [edx + ebx], eax // PUInt32(WriteAddr + DestPitch)^ := PUInt32(ReadAddr)^;
+             mov [edx + ebx + 4], eax // PUInt32(WriteAddr + DestPitch + 4)^ := PUInt32(ReadAddr)^;
+
+             add ecx, 4 // inc(ReadAddr, 4);
+             add edx, 8 // inc(WriteAddr, 8);
+
+             dec x
+           jnz @LoopX
+
+           mov eax, SrcPitch // inc(UInt32(ReadRow), SrcPitch);
+           add ReadRow, eax
+
+           mov eax, DestPitch // inc(UInt32(WriteRow), DestPitch * 2);
+           add WriteRow, eax
+           add WriteRow, eax
+
+           dec y
+         jnz @LoopY
+         pop ebx
+      end;
+  end;
+
+  if SDL_MustLock( Src ) then
+    SDL_UnlockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_UnlockSurface( Dest );
+end;
+
+function SDL_PixelTestSurfaceVsRect( SrcSurface1 : PSDL_Surface; SrcRect1 : PSDL_Rect; SrcRect2 : PSDL_Rect; Left1, Top1, Left2, Top2 : integer ) :
+boolean;
+var
+  Src_Rect1, Src_Rect2 : TSDL_Rect;
+  right1, bottom1 : integer;
+  right2, bottom2 : integer;
+  Scan1Start, Scan2Start, ScanWidth, ScanHeight : cardinal;
+  Mod1: cardinal;
+  Addr1 : cardinal;
+  BPP : cardinal;
+  Pitch1 : cardinal;
+  TransparentColor1 : cardinal;
+  tx, ty : cardinal;
+  StartTick : cardinal;
+  Color1 : cardinal;
+begin
+  Result := false;
+  if SrcRect1 = nil then
+  begin
+    with Src_Rect1 do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface1.w;
+      h := SrcSurface1.h;
+    end;
+  end
+  else
+    Src_Rect1 := SrcRect1^;
+
+    Src_Rect2 := SrcRect2^;
+  with Src_Rect1 do
+  begin
+    Right1 := Left1 + w;
+    Bottom1 := Top1 + h;
+  end;
+  with Src_Rect2 do
+  begin
+    Right2 := Left2 + w;
+    Bottom2 := Top2 + h;
+  end;
+  if ( Left1 >= Right2 ) or ( Right1 <= Left2 ) or ( Top1 >= Bottom2 ) or ( 
+Bottom1 <=
+    Top2 ) then
+    exit;
+  if Left1 <= Left2 then
+  begin
+    // 1. left, 2. right
+    Scan1Start := Src_Rect1.x + Left2 - Left1;
+    Scan2Start := Src_Rect2.x;
+    ScanWidth := Right1 - Left2;
+    with Src_Rect2 do
+      if ScanWidth > w then
+        ScanWidth := w;
+  end
+  else
+  begin
+    // 1. right, 2. left
+    Scan1Start := Src_Rect1.x;
+    Scan2Start := Src_Rect2.x + Left1 - Left2;
+    ScanWidth := Right2 - Left1;
+    with Src_Rect1 do
+      if ScanWidth > w then
+        ScanWidth := w;
+  end;
+  with SrcSurface1^ do
+  begin
+    Pitch1 := Pitch;
+    Addr1 := cardinal( Pixels );
+    inc( Addr1, Pitch1 * UInt32( Src_Rect1.y ) );
+    with format^ do
+    begin
+      BPP := BytesPerPixel;
+      TransparentColor1 := colorkey;
+    end;
+  end;
+
+  Mod1 := Pitch1 - ( ScanWidth * BPP );
+
+  inc( Addr1, BPP * Scan1Start );
+
+  if Top1 <= Top2 then
+  begin
+    // 1. up, 2. down
+    ScanHeight := Bottom1 - Top2;
+    if ScanHeight > Src_Rect2.h then
+      ScanHeight := Src_Rect2.h;
+    inc( Addr1, Pitch1 * UInt32( Top2 - Top1 ) );
+  end
+  else
+  begin
+    // 1. down, 2. up
+    ScanHeight := Bottom2 - Top1;
+    if ScanHeight > Src_Rect1.h then
+      ScanHeight := Src_Rect1.h;
+
+  end;
+  case BPP of
+    1 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PByte( Addr1 )^ <> TransparentColor1 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1 );
+
+        end;
+        inc( Addr1, Mod1 );
+
+      end;
+    2 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PWord( Addr1 )^ <> TransparentColor1 )  then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 2 );
+
+        end;
+        inc( Addr1, Mod1 );
+
+      end;
+    3 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          Color1 := PLongWord( Addr1 )^ and $00FFFFFF;
+
+          if ( Color1 <> TransparentColor1 )
+            then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 3 );
+
+        end;
+        inc( Addr1, Mod1 );
+
+      end;
+    4 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PLongWord( Addr1 )^ <> TransparentColor1 )  then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 4 );
+
+        end;
+        inc( Addr1, Mod1 );
+
+      end;
+  end;
+end;
+
+procedure SDL_ORSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  Src, Dest : TSDL_Rect;
+  Diff : integer;
+  SrcAddr, DestAddr, TransparentColor : cardinal;
+  // TransparentColor: cardinal;
+  _ebx, _esi, _edi, _esp : cardinal;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        cmp al, 0
+        je @SkipColor         // if AL=0 or AL=transparent color then skip everything
+        cmp al, byte ptr TransparentColor
+        je @SkipColor
+        or al, [edi]
+        mov [edi], al
+       @SkipColor:
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    15 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax          // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AX := source color
+        cmp ax, 0
+        je @SkipColor         // if AX=0 then skip everything
+        cmp ax, word ptr TransparentColor
+        je @SkipColor
+        or ax, [edi]
+        mov [edi], ax
+       @SkipColor:
+        add esi, 2
+        add edi, 2
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    16 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AX := source color
+        cmp ax, 0
+        je @SkipColor         // if AX=0 then skip everything
+        cmp ax, word ptr TransparentColor
+        je @SkipColor
+        or ax, [edi]
+        mov [edi], ax
+       @SkipColor:
+        add esi, 2
+        add edi, 2
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    24 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       add WorkX, ax         // WorkX := Src.w * 2
+       add WorkX, ax         // WorkX := Src.w * 3
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        or al, [edi]
+        mov [edi], al
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    32 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       shl ax, 2
+       mov WorkX, ax         // WorkX := Src.w * 4
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        or al, [edi]
+        mov [edi], al
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+procedure SDL_ANDSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  Src, Dest : TSDL_Rect;
+  Diff : integer;
+  SrcAddr, DestAddr, TransparentColor : cardinal;
+  // TransparentColor: cardinal;
+  _ebx, _esi, _edi, _esp : cardinal;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        cmp al, 0
+        je @SkipColor         // if AL=0 or AL=transparent color then skip everything
+        cmp al, byte ptr TransparentColor
+        je @SkipColor
+        and al, [edi]
+        mov [edi], al
+       @SkipColor:
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    15 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax          // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AX := source color
+        cmp ax, 0
+        je @SkipColor         // if AX=0 then skip everything
+        cmp ax, word ptr TransparentColor
+        je @SkipColor
+        and ax, [edi]
+        mov [edi], ax
+       @SkipColor:
+        add esi, 2
+        add edi, 2
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    16 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       @Loopx:
+        mov ax, [esi]         // AX := source color
+        cmp ax, 0
+        je @SkipColor         // if AX=0 then skip everything
+        cmp ax, word ptr TransparentColor
+        je @SkipColor
+        and ax, [edi]
+        mov [edi], ax
+       @SkipColor:
+        add esi, 2
+        add edi, 2
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    24 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       mov WorkX, ax         // WorkX := Src.w
+       add WorkX, ax         // WorkX := Src.w * 2
+       add WorkX, ax         // WorkX := Src.w * 3
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        and al, [edi]
+        mov [edi], al
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+    32 :
+      asm
+      mov _ebx, ebx
+      mov _esi, esi
+      mov _edi, edi
+      mov _esp, esp
+      mov esi, SrcAddr      // ESI - Source Offset
+      mov edi, DestAddr     // EDI - Destination Offset
+      mov ax, Src.h         //  WorkY := Src.h
+      mov WorkY, ax
+      @LoopY:
+       mov ax, Src.w
+       shl ax, 2
+       mov WorkX, ax         // WorkX := Src.w * 4
+       @Loopx:
+        mov al, [esi]         // AL := source color
+        and al, [edi]
+        mov [edi], al
+        inc esi
+        inc edi
+        dec WorkX
+       jnz @LoopX
+       add esi, SrcMod
+       add edi, DestMod
+       dec WorkY
+      jnz @LoopY
+      mov esp,_esp
+      mov edi,_edi
+      mov esi,_esi
+      mov ebx,_ebx
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+
+procedure SDL_GTSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+  Src, Dest : TSDL_Rect;
+  Diff : integer;
+  SrcAddr, DestAddr : cardinal;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt8( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt8( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                if Pixel2 and $E0 > Pixel1 and $E0 then R := Pixel2 and $E0 else R := Pixel1 and $E0;
+                if Pixel2 and $1C > Pixel1 and $1C then G := Pixel2 and $1C else G := Pixel1 and $1C;
+                if Pixel2 and $03 > Pixel1 and $03 then B := Pixel2 and $03 else B := Pixel1 and $03;
+
+                if R > $E0 then
+                  R := $E0;
+                if G > $1C then
+                  G := $1C;
+                if B > $03 then
+                  B := $03;
+                PUInt8( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt8( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    15 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+              if Pixel2 and $7C00 > Pixel1 and $7C00 then R := Pixel2 and $7C00 else R := Pixel1 and $7C00;
+              if Pixel2 and $03E0 > Pixel1 and $03E0 then G := Pixel2 and $03E0 else G := Pixel1 and $03E0;
+              if Pixel2 and $001F > Pixel1 and $001F then B := Pixel2 and $001F else B := Pixel1 and $001F;
+
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    16 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+              if Pixel2 and $F800 > Pixel1 and $F800 then R := Pixel2 and $F800 else R := Pixel1 and $F800;
+              if Pixel2 and $07E0 > Pixel1 and $07E0 then G := Pixel2 and $07E0 else G := Pixel1 and $07E0;
+              if Pixel2 and $001F > Pixel1 and $001F then B := Pixel2 and $001F else B := Pixel1 and $001F;
+
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    24 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^ and $00FFFFFF;
+              if Pixel2 > 0 then
+              begin
+
+              if Pixel2 and $FF0000 > Pixel1 and $FF0000 then R := Pixel2 and $FF0000 else R := Pixel1 and $FF0000;
+              if Pixel2 and $00FF00 > Pixel1 and $00FF00 then G := Pixel2 and $00FF00 else G := Pixel1 and $00FF00;
+              if Pixel2 and $0000FF > Pixel1 and $0000FF then B := Pixel2 and $0000FF else B := Pixel1 and $0000FF;
+
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or ( R or G or B );
+              end
+              else
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or Pixel1;
+            end;
+            inc( SrcAddr, 3 );
+            inc( DestAddr, 3 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    32 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+              if Pixel2 and $FF0000 > Pixel1 and $FF0000 then R := Pixel2 and $FF0000 else R := Pixel1 and $FF0000;
+              if Pixel2 and $00FF00 > Pixel1 and $00FF00 then G := Pixel2 and $00FF00 else G := Pixel1 and $00FF00;
+              if Pixel2 and $0000FF > Pixel1 and $0000FF then B := Pixel2 and $0000FF else B := Pixel1 and $0000FF;
+
+                PUInt32( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt32( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 4 );
+            inc( DestAddr, 4 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+
+procedure SDL_LTSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+  Src, Dest : TSDL_Rect;
+  Diff : integer;
+  SrcAddr, DestAddr : cardinal;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt8( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt8( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                if Pixel2 and $E0 < Pixel1 and $E0 then R := Pixel2 and $E0 else R := Pixel1 and $E0;
+                if Pixel2 and $1C < Pixel1 and $1C then G := Pixel2 and $1C else G := Pixel1 and $1C;
+                if Pixel2 and $03 < Pixel1 and $03 then B := Pixel2 and $03 else B := Pixel1 and $03;
+
+                if R > $E0 then
+                  R := $E0;
+                if G > $1C then
+                  G := $1C;
+                if B > $03 then
+                  B := $03;
+                PUInt8( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt8( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    15 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+              if Pixel2 and $7C00 < Pixel1 and $7C00 then R := Pixel2 and $7C00 else R := Pixel1 and $7C00;
+              if Pixel2 and $03E0 < Pixel1 and $03E0 then G := Pixel2 and $03E0 else G := Pixel1 and $03E0;
+              if Pixel2 and $001F < Pixel1 and $001F then B := Pixel2 and $001F else B := Pixel1 and $001F;
+
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    16 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+              if Pixel2 and $F800 < Pixel1 and $F800 then R := Pixel2 and $F800 else R := Pixel1 and $F800;
+              if Pixel2 and $07E0 < Pixel1 and $07E0 then G := Pixel2 and $07E0 else G := Pixel1 and $07E0;
+              if Pixel2 and $001F < Pixel1 and $001F then B := Pixel2 and $001F else B := Pixel1 and $001F;
+
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    24 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^ and $00FFFFFF;
+              if Pixel2 > 0 then
+              begin
+
+              if Pixel2 and $FF0000 < Pixel1 and $FF0000 then R := Pixel2 and $FF0000 else R := Pixel1 and $FF0000;
+              if Pixel2 and $00FF00 < Pixel1 and $00FF00 then G := Pixel2 and $00FF00 else G := Pixel1 and $00FF00;
+              if Pixel2 and $0000FF < Pixel1 and $0000FF then B := Pixel2 and $0000FF else B := Pixel1 and $0000FF;
+
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or ( R or G or B );
+              end
+              else
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or Pixel1;
+            end;
+            inc( SrcAddr, 3 );
+            inc( DestAddr, 3 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    32 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+              if Pixel2 and $FF0000 < Pixel1 and $FF0000 then R := Pixel2 and $FF0000 else R := Pixel1 and $FF0000;
+              if Pixel2 and $00FF00 < Pixel1 and $00FF00 then G := Pixel2 and $00FF00 else G := Pixel1 and $00FF00;
+              if Pixel2 and $0000FF < Pixel1 and $0000FF then B := Pixel2 and $0000FF else B := Pixel1 and $0000FF;
+
+                PUInt32( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt32( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 4 );
+            inc( DestAddr, 4 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+function SDL_ClipLine(var x1,y1,x2,y2: Integer; ClipRect: PSDL_Rect) : boolean;
+var tflag, flag1, flag2: word;
+    txy, xedge, yedge: Integer;
+    slope: single;
+
+  function ClipCode(x,y: Integer): word;
+  begin
+    Result := 0;
+    if x < ClipRect.x then Result := 1;
+    if x >= ClipRect.w + ClipRect.x then Result := Result or 2;
+    if y < ClipRect.y then Result := Result or 4;
+    if y >= ClipRect.h + ClipRect.y then Result := Result or 8;
+  end;
+
+begin
+  flag1 := ClipCode(x1,y1);
+  flag2 := ClipCode(x2,y2);
+  result := true;
+
+  while true do
+  begin
+    if (flag1 or flag2) = 0 then Exit; // all in
+
+    if (flag1 and flag2) <> 0 then
+      begin
+        result := false;
+        Exit; // all out
+      end;
+
+    if flag2 = 0 then
+      begin
+        txy := x1; x1 := x2; x2 := txy;
+        txy := y1; y1 := y2; y2 := txy;
+        tflag := flag1; flag1 := flag2; flag2 := tflag;
+      end;
+
+    if (flag2 and 3) <> 0 then
+      begin
+        if (flag2 and 1) <> 0 then
+          xedge := ClipRect.x
+        else
+          xedge := ClipRect.w + ClipRect.x -1; // back 1 pixel otherwise we end up in a loop
+
+        slope := (y2 - y1) / (x2 - x1);
+        y2 := y1 + Round(slope * (xedge - x1));
+        x2 := xedge;
+      end
+    else
+      begin
+        if (flag2 and 4) <> 0 then
+          yedge := ClipRect.y
+        else
+          yedge := ClipRect.h + ClipRect.y -1; // up 1 pixel otherwise we end up in a loop
+
+        slope := (x2 - x1) / (y2 - y1);
+        x2 := x1 + Round(slope * (yedge - y1));
+        y2 := yedge;
+      end;
+
+    flag2 := ClipCode(x2, y2);
+  end;
+end;
+
+end.
+
+
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlinput.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlinput.pas
new file mode 100644
index 00000000..094f4e0f
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlinput.pas
@@ -0,0 +1,923 @@
+unit sdlinput;
+{
+  $Id: sdlinput.pas,v 1.9 2007/08/22 21:18:43 savage Exp $
+  
+}
+{******************************************************************************}
+{                                                                              }
+{          JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer          }
+{                     SDL Input Wrapper                                        }
+{                                                                              }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Portions created by Dominique Louis are                                      }
+{ Copyright (C) 2003 - 2100 Dominique Louis.                                   }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{   SDL Mouse, Keyboard and Joystick wrapper                                   }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   SDL.dll on Windows platforms                                               }
+{   libSDL-1.1.so.0 on Linux platform                                          }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{ March      12     2003 - DL : Initial creation                               }
+{                                                                              }
+{ February   02     2004 - DL : Added Custom Cursor Support to the Mouse class }
+{
+  $Log: sdlinput.pas,v $
+  Revision 1.9  2007/08/22 21:18:43  savage
+  Thanks to Dean for his MouseDelta patch.
+
+  Revision 1.8  2005/08/03 18:57:32  savage
+  Various updates and additions. Mainly to handle OpenGL 3D Window support and better cursor support for the mouse class
+
+  Revision 1.7  2004/09/30 22:32:04  savage
+  Updated with slightly different header comments
+
+  Revision 1.6  2004/09/12 21:52:58  savage
+  Slight changes to fix some issues with the sdl classes.
+
+  Revision 1.5  2004/05/10 21:11:49  savage
+  changes required to help get SoAoS off the ground.
+
+  Revision 1.4  2004/05/03 22:38:40  savage
+  Added the ability to enable or disable certain inputs @ runtime. Basically it just does not call UpdateInput if Enabled = false.
+  Can also disable and enable input devices via the InputManager.
+
+  Revision 1.3  2004/04/28 21:27:01  savage
+  Updated Joystick code and event handlers. Needs testing...
+
+  Revision 1.2  2004/02/14 22:36:29  savage
+  Fixed inconsistencies of using LoadLibrary and LoadModule.
+  Now all units make use of LoadModule rather than LoadLibrary and other dynamic proc procedures.
+
+  Revision 1.1  2004/02/05 00:08:20  savage
+  Module 1.0 release
+
+
+}
+{******************************************************************************}
+
+interface
+
+{$i jedi-sdl.inc}
+
+uses
+  Classes,
+  sdl;
+
+type
+  TSDLInputType = ( itJoystick , itKeyBoard, itMouse );
+  TSDLInputTypes = set of TSDLInputType;
+
+  TSDLCustomInput = class( TObject )
+  private
+    FEnabled: Boolean;
+  public
+    constructor Create;
+    function UpdateInput( event: TSDL_EVENT ) : Boolean; virtual; abstract;
+    property Enabled : Boolean read FEnabled write FEnabled;
+  end;
+
+  TSDLJoyAxisMoveEvent =  procedure ( Which: UInt8; Axis: UInt8; Value: SInt16 ) {$IFNDEF NOT_OO}of object{$ENDIF};
+  TSDLJoyBallMoveEvent =  procedure ( Which: UInt8; Ball: UInt8; RelativePos: TPoint ) {$IFNDEF NOT_OO}of object{$ENDIF};
+  TSDLJoyHatMoveEvent =  procedure ( Which: UInt8; Hat: UInt8; Value: SInt16 ) {$IFNDEF NOT_OO}of object{$ENDIF};
+  TSDLJoyButtonEvent =  procedure ( Which: UInt8; Button: UInt8; State: SInt16 ) {$IFNDEF NOT_OO}of object{$ENDIF};
+
+
+  TSDLJoyStick = class( TSDLCustomInput )
+  private
+    FJoystick : PSDL_Joystick;
+    FJoystickIndex : Integer;
+    FJoyAxisMoveEvent : TSDLJoyAxisMoveEvent;
+    FJoyBallMoveEvent : TSDLJoyBallMoveEvent;
+    FJoyHatMoveEvent : TSDLJoyHatMoveEvent;
+    FJoyButtonDownEvent : TSDLJoyButtonEvent;
+    FJoyButtonUpEvent : TSDLJoyButtonEvent;
+    procedure DoAxisMove( Event : TSDL_Event );
+    procedure DoBallMove( Event : TSDL_Event );
+    procedure DoHatMove( Event : TSDL_Event );
+    procedure DoButtonDown( Event : TSDL_Event );
+    procedure DoButtonUp( Event : TSDL_Event );
+    function GetName: PChar;
+    function GetNumAxes: integer;
+    function GetNumBalls: integer;
+    function GetNumButtons: integer;
+    function GetNumHats: integer;
+  public
+    constructor Create( Index : Integer );
+    destructor Destroy; override;
+    procedure Open;
+    procedure Close;
+    function UpdateInput( Event: TSDL_EVENT ) : Boolean; override;
+    property Name : PChar read GetName;
+    property NumAxes : integer read GetNumAxes;
+    property NumBalls : integer read GetNumBalls;
+    property NumButtons : integer read GetNumButtons;
+    property NumHats : integer read GetNumHats;
+    property OnAxisMove : TSDLJoyAxisMoveEvent read FJoyAxisMoveEvent write FJoyAxisMoveEvent;
+    property OnBallMove : TSDLJoyBallMoveEvent read FJoyBallMoveEvent write FJoyBallMoveEvent;
+    property OnHatMove : TSDLJoyHatMoveEvent read FJoyHatMoveEvent write FJoyHatMoveEvent;
+    property OnButtonDown : TSDLJoyButtonEvent read FJoyButtonDownEvent write FJoyButtonDownEvent;
+    property OnButtonUp : TSDLJoyButtonEvent read FJoyButtonUpEvent write FJoyButtonUpEvent;
+  end;
+
+  TSDLJoySticks = class( TObject )
+  private
+    FNumOfJoySticks: Integer;
+    FJoyStickList : TList;
+    function GetJoyStick(Index: integer): TSDLJoyStick;
+    procedure SetJoyStick(Index: integer; const Value: TSDLJoyStick);
+  public
+    constructor Create;
+    destructor Destroy; override;
+    function UpdateInput( event: TSDL_EVENT ) : Boolean;
+    property NumOfJoySticks : Integer read FNumOfJoySticks write FNumOfJoySticks;
+    property JoySticks[ Index : integer ] : TSDLJoyStick read GetJoyStick write SetJoyStick;
+  end;
+
+  TSDLKeyBoardEvent =  procedure ( var Key: TSDLKey; Shift: TSDLMod; unicode : UInt16 ) {$IFNDEF NOT_OO}of object{$ENDIF};
+
+  TSDLKeyBoard = class( TSDLCustomInput )
+  private
+    FKeys : PKeyStateArr;
+    FOnKeyUp: TSDLKeyBoardEvent;
+    FOnKeyDown: TSDLKeyBoardEvent;
+    procedure DoKeyDown( keysym : PSDL_keysym );
+    procedure DoKeyUp( keysym : PSDL_keysym );
+  public
+    function IsKeyDown( Key : TSDLKey ) : Boolean;
+    function IsKeyUp( Key : TSDLKey ) : Boolean;
+    function UpdateInput( event: TSDL_EVENT ) : Boolean; override;
+    property Keys : PKeyStateArr read FKeys write FKeys;
+    property OnKeyDown : TSDLKeyBoardEvent read FOnKeyDown write FOnKeyDown;
+    property OnKeyUp : TSDLKeyBoardEvent read FOnKeyUp write FOnKeyUp;
+  end;
+
+  TSDLMouseButtonEvent =  procedure ( Button : Integer; Shift: TSDLMod; MousePos : TPoint ) {$IFNDEF NOT_OO}of object{$ENDIF};
+  TSDLMouseMoveEvent =  procedure ( Shift: TSDLMod; CurrentPos : TPoint; RelativePos : TPoint ) {$IFNDEF NOT_OO}of object{$ENDIF};
+  TSDLMouseWheelEvent =  procedure ( WheelDelta : Integer; Shift: TSDLMod; MousePos : TPoint ) {$IFNDEF NOT_OO}of object{$ENDIF};
+
+  TSDLCustomCursor = class( TObject )
+  private
+    FFileName : string;
+    FHotPoint: TPoint;
+    procedure SetFileName(const aValue: string );
+    function ScanForChar( str : string; ch : Char; startPos : Integer; lookFor : Boolean ) : Integer;
+  public
+    constructor Create( const aFileName : string; aHotPoint: TPoint );
+    procedure LoadFromFile( const aFileName : string ); virtual; abstract;
+    procedure LoadFromStream( aStream : TStream ); virtual; abstract;
+    procedure Show; virtual; abstract;
+    property FileName : string read FFileName write SetFileName;
+    property HotPoint : TPoint read FHotPoint write FHotPoint;
+  end;
+
+  TSDLXPMCursor = class( TSDLCustomCursor )
+  private
+    FCursor : PSDL_Cursor;
+    procedure FreeCursor;
+  public
+    destructor Destroy; override;
+    procedure LoadFromFile( const aFileName : string ); override;
+    procedure LoadFromStream( aStream : TStream ); override;
+    procedure Show; override;
+  end;
+
+  TSDLCursorList = class( TStringList )
+  protected
+    function GetObject( aIndex : Integer ): TSDLCustomCursor; reintroduce;
+    procedure PutObject( aIndex : Integer; AObject : TSDLCustomCursor); reintroduce;
+  public
+    constructor Create;
+   function AddCursor(const aName : string; aObject : TSDLCustomCursor): Integer; virtual;
+  end;
+
+  TSDLMouse = class( TSDLCustomInput )
+  private
+    FDragging : Boolean;
+    FMousePos : TPoint;
+    FOnMouseUp: TSDLMouseButtonEvent;
+    FOnMouseDown: TSDLMouseButtonEvent;
+    FOnMouseMove: TSDLMouseMoveEvent;
+    FOnMouseWheel: TSDLMouseWheelEvent;
+    FCursorList : TSDLCursorList; // Cursor Pointer
+    procedure DoMouseMove( Event: TSDL_Event );
+    procedure DoMouseDown( Event: TSDL_Event );
+    procedure DoMouseUp( Event: TSDL_Event );
+    procedure DoMouseWheelScroll( Event: TSDL_Event );
+    function GetMousePosition: TPoint;
+    procedure SetMousePosition(const Value: TPoint);
+    function GetMouseDelta: TPoint;
+  public
+    destructor Destroy; override;
+    function UpdateInput( event: TSDL_EVENT ) : Boolean; override;
+    function MouseIsDown( Button : Integer ) : Boolean;
+    function MouseIsUp( Button : Integer ) : Boolean;
+    procedure ShowCursor;
+    procedure HideCursor;
+    property OnMouseDown : TSDLMouseButtonEvent read FOnMouseDown write FOnMouseDown;
+    property OnMouseUp : TSDLMouseButtonEvent read FOnMouseUp write FOnMouseUp;
+    property OnMouseMove : TSDLMouseMoveEvent read FOnMouseMove write FOnMouseMove;
+    property OnMouseWheel : TSDLMouseWheelEvent read FOnMouseWheel write FOnMouseWheel;
+    property MousePosition : TPoint read GetMousePosition write SetMousePosition;
+    property MouseDelta: TPoint read GetMouseDelta;
+    property Cursors : TSDLCursorList read FCursorList write FCursorList;
+  end;
+
+  TSDLInputManager = class( TObject )
+  private
+    FKeyBoard : TSDLKeyBoard;
+    FMouse : TSDLMouse;
+    FJoystick : TSDLJoysticks;
+  public
+    constructor Create( InitInputs : TSDLInputTypes );
+    destructor Destroy; override;
+    procedure Disable( InitInputs : TSDLInputTypes; JoyStickNumber : Integer = 0 );
+    procedure Enable( InitInputs : TSDLInputTypes; JoyStickNumber : Integer = 0 );
+    function UpdateInputs( event: TSDL_EVENT ) : Boolean;
+    property KeyBoard : TSDLKeyBoard read FKeyBoard write FKeyBoard;
+    property Mouse : TSDLMouse read FMouse write FMouse;
+    property JoyStick : TSDLJoysticks read FJoyStick write FJoyStick;
+  end;
+
+implementation
+
+uses
+  SysUtils;
+
+{ TSDLCustomInput }
+constructor TSDLCustomInput.Create;
+begin
+  inherited;
+  FEnabled := true;
+end;
+
+{ TSDLJoysticks }
+constructor TSDLJoysticks.Create;
+var
+  i : integer;
+begin
+  inherited;
+  if ( SDL_WasInit( SDL_INIT_JOYSTICK ) = 0 ) then
+    SDL_InitSubSystem( SDL_INIT_JOYSTICK );
+  FNumOfJoySticks := SDL_NumJoysticks;
+  FJoyStickList := TList.Create;
+  for i := 0 to FNumOfJoySticks - 1 do
+  begin
+    FJoyStickList.Add( TSDLJoyStick.Create( i )  );
+  end;
+end;
+
+destructor TSDLJoysticks.Destroy;
+var
+  i : integer;
+begin
+  if FJoyStickList.Count > 0 then
+  begin
+    for i := 0 to FJoyStickList.Count - 1 do
+    begin
+      TSDLJoyStick( FJoyStickList.Items[i] ).Free;
+    end;
+  end;
+  SDL_QuitSubSystem( SDL_INIT_JOYSTICK );
+  inherited;
+end;
+
+function TSDLJoySticks.GetJoyStick(Index: integer): TSDLJoyStick;
+begin
+  Result := TSDLJoyStick( FJoyStickList[ Index ] );
+end;
+
+procedure TSDLJoySticks.SetJoyStick(Index: integer;
+  const Value: TSDLJoyStick);
+begin
+  FJoyStickList[ Index ] :=  @Value;
+end;
+
+function TSDLJoysticks.UpdateInput(event: TSDL_EVENT): Boolean;
+var
+  i : integer;
+begin
+  result := false;
+  if FJoyStickList.Count > 0 then
+  begin
+    for i := 0 to FJoyStickList.Count - 1 do
+    begin
+      TSDLJoyStick( FJoyStickList.Items[i] ).UpdateInput( event );
+    end;
+  end;
+end;
+
+{ TSDLKeyBoard }
+procedure TSDLKeyBoard.DoKeyDown(keysym: PSDL_keysym);
+begin
+  if Assigned( FOnKeyDown ) then
+    FOnKeyDown( keysym.sym , keysym.modifier, keysym.unicode );
+end;
+
+procedure TSDLKeyBoard.DoKeyUp(keysym: PSDL_keysym);
+begin
+  if Assigned( FOnKeyUp ) then
+    FOnKeyUp( keysym.sym , keysym.modifier, keysym.unicode );
+end;
+
+function TSDLKeyBoard.IsKeyDown( Key: TSDLKey ): Boolean;
+begin
+  SDL_PumpEvents;
+
+  // Populate Keys array
+  FKeys := PKeyStateArr( SDL_GetKeyState( nil ) );
+  Result := ( FKeys[Key] = SDL_PRESSED );
+end;
+
+function TSDLKeyBoard.IsKeyUp( Key: TSDLKey ): Boolean;
+begin
+  SDL_PumpEvents;
+
+  // Populate Keys array
+  FKeys := PKeyStateArr( SDL_GetKeyState( nil ) );
+  Result := ( FKeys[Key] = SDL_RELEASED );
+end;
+
+function TSDLKeyBoard.UpdateInput(event: TSDL_EVENT): Boolean;
+begin
+  result := false;
+  if ( FEnabled ) then
+  begin
+    case event.type_ of
+      SDL_KEYDOWN :
+      begin
+        // handle key presses
+        DoKeyDown( @event.key.keysym );
+        result := true;
+      end;
+
+      SDL_KEYUP :
+      begin
+        // handle key releases
+        DoKeyUp( @event.key.keysym );
+        result := true;
+      end;
+    end;
+  end;
+end;
+
+{ TSDLMouse }
+destructor TSDLMouse.Destroy;
+begin
+
+  inherited;
+end;
+
+procedure TSDLMouse.DoMouseDown( Event: TSDL_Event );
+var
+  CurrentPos : TPoint;
+begin
+  FDragging := true;
+  if Assigned( FOnMouseDown ) then
+  begin
+    CurrentPos.x := event.button.x;
+    CurrentPos.y := event.button.y;
+    FOnMouseDown( event.button.button, SDL_GetModState, CurrentPos );
+  end;
+end;
+
+procedure TSDLMouse.DoMouseMove( Event: TSDL_Event );
+var
+  CurrentPos, RelativePos : TPoint;
+begin
+  if Assigned( FOnMouseMove ) then
+  begin
+    CurrentPos.x := event.motion.x;
+    CurrentPos.y := event.motion.y;
+    RelativePos.x := event.motion.xrel;
+    RelativePos.y := event.motion.yrel;
+    FOnMouseMove( SDL_GetModState, CurrentPos, RelativePos );
+  end;
+end;
+
+procedure TSDLMouse.DoMouseUp( event: TSDL_EVENT );
+var
+  Point : TPoint;
+begin
+  FDragging := false;
+  if Assigned( FOnMouseUp ) then
+  begin
+    Point.x := event.button.x;
+    Point.y := event.button.y;
+    FOnMouseUp( event.button.button, SDL_GetModState, Point );
+  end;
+end;
+
+procedure TSDLMouse.DoMouseWheelScroll( event: TSDL_EVENT );
+var
+  Point : TPoint;
+begin
+  if Assigned( FOnMouseWheel ) then
+  begin
+    Point.x := event.button.x;
+    Point.y := event.button.y;
+    if ( event.button.button = SDL_BUTTON_WHEELUP ) then
+      FOnMouseWheel( SDL_BUTTON_WHEELUP, SDL_GetModState, Point )
+    else
+      FOnMouseWheel( SDL_BUTTON_WHEELDOWN, SDL_GetModState, Point );
+  end;
+end;
+
+function TSDLMouse.GetMouseDelta: TPoint;
+begin
+  SDL_PumpEvents;
+  
+  SDL_GetRelativeMouseState( Result.X, Result.Y );
+end;
+
+function TSDLMouse.GetMousePosition: TPoint;
+begin
+  SDL_PumpEvents;
+
+  SDL_GetMouseState( FMousePos.X, FMousePos.Y );
+  Result := FMousePos;
+end;
+
+procedure TSDLMouse.HideCursor;
+begin
+  SDL_ShowCursor( SDL_DISABLE  );
+end;
+
+function TSDLMouse.MouseIsDown(Button: Integer): Boolean;
+begin
+  SDL_PumpEvents;
+
+  Result := ( SDL_GetMouseState( FMousePos.X, FMousePos.Y ) and SDL_BUTTON( Button ) = 0 );
+end;
+
+function TSDLMouse.MouseIsUp(Button: Integer): Boolean;
+begin
+  SDL_PumpEvents;
+
+  Result := not ( SDL_GetMouseState( FMousePos.X, FMousePos.Y ) and SDL_BUTTON( Button ) = 0 );
+end;
+
+procedure TSDLMouse.SetMousePosition(const Value: TPoint);
+begin
+  SDL_WarpMouse( Value.x, Value.y );
+end;
+
+procedure TSDLMouse.ShowCursor;
+begin
+  SDL_ShowCursor( SDL_ENABLE  );
+end;
+
+function TSDLMouse.UpdateInput(event: TSDL_EVENT): Boolean;
+begin
+  result := false;
+  if ( FEnabled ) then
+  begin
+    case event.type_ of
+      SDL_MOUSEMOTION :
+      begin
+        // handle Mouse Move
+        DoMouseMove( event );
+      end;
+
+      SDL_MOUSEBUTTONDOWN :
+      begin
+        // handle Mouse Down
+        if ( event.button.button = SDL_BUTTON_WHEELUP )
+        or ( event.button.button = SDL_BUTTON_WHEELDOWN ) then
+          DoMouseWheelScroll( event )
+        else
+          DoMouseDown( event );
+      end;
+
+      SDL_MOUSEBUTTONUP :
+      begin
+        // handle Mouse Up
+        if ( event.button.button = SDL_BUTTON_WHEELUP )
+        or ( event.button.button = SDL_BUTTON_WHEELDOWN ) then
+          DoMouseWheelScroll( event )
+        else
+          DoMouseUp( event );
+      end;
+    end;
+  end;
+end;
+
+{ TSDLInputManager }
+constructor TSDLInputManager.Create(InitInputs: TSDLInputTypes);
+begin
+  inherited Create;
+  if itJoystick in InitInputs then
+    FJoystick := TSDLJoysticks.Create;
+
+  if itKeyBoard in InitInputs then
+    FKeyBoard := TSDLKeyBoard.Create;
+    
+  if itMouse in InitInputs then
+    FMouse := TSDLMouse.Create;
+end;
+
+destructor TSDLInputManager.Destroy;
+begin
+  if FJoystick <> nil then
+    FreeAndNil( FJoystick );
+  if FKeyBoard <> nil then
+    FreeAndNil( FKeyBoard );
+  if FMouse <> nil then
+    FreeAndNil( FMouse );
+  inherited;
+end;
+
+procedure TSDLInputManager.Disable( InitInputs : TSDLInputTypes;  JoyStickNumber : Integer );
+begin
+  if itJoystick in InitInputs then
+    FJoystick.JoySticks[ JoyStickNumber ].Enabled := false;
+
+  if itKeyBoard in InitInputs then
+    FKeyBoard.Enabled := false;
+
+  if itMouse in InitInputs then
+    FMouse.Enabled := false;
+end;
+
+procedure TSDLInputManager.Enable( InitInputs: TSDLInputTypes; JoyStickNumber: Integer );
+begin
+  if itJoystick in InitInputs then
+    FJoystick.JoySticks[ JoyStickNumber ].Enabled := true;
+
+  if itKeyBoard in InitInputs then
+    FKeyBoard.Enabled := true;
+    
+  if itMouse in InitInputs then
+    FMouse.Enabled := true;
+end;
+
+function TSDLInputManager.UpdateInputs( event: TSDL_EVENT ): Boolean;
+begin
+  Result := false;
+  if ( FJoystick <> nil ) then
+   Result := FJoystick.UpdateInput( event );
+  if ( FKeyBoard <> nil ) then
+   Result := FKeyBoard.UpdateInput( event );
+  if ( FMouse <> nil ) then
+   Result := FMouse.UpdateInput( event );
+end;
+
+{ TSDLJoyStick }
+procedure TSDLJoyStick.Close;
+begin
+  SDL_JoystickClose( @FJoystick );
+end;
+
+constructor TSDLJoyStick.Create( Index : Integer );
+begin
+  inherited Create;
+  FJoystick := nil;
+  FJoystickIndex := Index;
+end;
+
+destructor TSDLJoyStick.Destroy;
+begin
+  if FJoystick <> nil then
+    Close;
+  inherited;
+end;
+
+procedure TSDLJoyStick.DoAxisMove(Event: TSDL_Event);
+begin
+  if Assigned( FJoyAxisMoveEvent ) then
+  begin
+    FJoyAxisMoveEvent( Event.jaxis.which, Event.jaxis.axis, Event.jaxis.value );
+  end
+end;
+
+procedure TSDLJoyStick.DoBallMove(Event: TSDL_Event);
+var
+  BallPoint : TPoint;
+begin
+  if Assigned( FJoyBallMoveEvent ) then
+  begin
+    BallPoint.x := Event.jball.xrel;
+    BallPoint.y := Event.jball.yrel;
+    FJoyBallMoveEvent( Event.jball.which, Event.jball.ball, BallPoint );
+  end;
+end;
+
+procedure TSDLJoyStick.DoButtonDown(Event: TSDL_Event);
+begin
+  if Assigned( FJoyButtonDownEvent ) then
+  begin
+    if ( Event.jbutton.state = SDL_PRESSED ) then
+      FJoyButtonDownEvent( Event.jbutton.which, Event.jbutton.button, Event.jbutton.state );
+  end;
+end;
+
+procedure TSDLJoyStick.DoButtonUp(Event: TSDL_Event);
+begin
+  if Assigned( FJoyButtonUpEvent ) then
+  begin
+    if ( Event.jbutton.state = SDL_RELEASED ) then
+      FJoyButtonUpEvent( Event.jbutton.which, Event.jbutton.button, Event.jbutton.state );
+  end
+end;
+
+procedure TSDLJoyStick.DoHatMove(Event: TSDL_Event);
+begin
+  if Assigned( FJoyHatMoveEvent ) then
+  begin
+    FJoyHatMoveEvent( Event.jhat.which, Event.jhat.hat, Event.jhat.value );
+  end;
+end;
+
+function TSDLJoyStick.GetName: PChar;
+begin
+  result := FJoystick.name;
+end;
+
+function TSDLJoyStick.GetNumAxes: integer;
+begin
+  result := FJoystick.naxes;
+end;
+
+function TSDLJoyStick.GetNumBalls: integer;
+begin
+  result := FJoystick.nballs;
+end;
+
+function TSDLJoyStick.GetNumButtons: integer;
+begin
+  result := FJoystick.nbuttons;
+end;
+
+function TSDLJoyStick.GetNumHats: integer;
+begin
+  result := FJoystick.nhats;
+end;
+
+procedure TSDLJoyStick.Open;
+begin
+  FJoystick := SDL_JoyStickOpen( FJoystickIndex );
+end;
+
+function TSDLJoyStick.UpdateInput(Event: TSDL_EVENT): Boolean;
+begin
+  Result := false;
+  
+  if ( FEnabled ) then
+  begin
+    case event.type_ of
+      SDL_JOYAXISMOTION :
+      begin
+        DoAxisMove( Event );
+      end;
+
+      SDL_JOYBALLMOTION :
+      begin
+        DoBallMove( Event );
+      end;
+
+      SDL_JOYHATMOTION :
+      begin
+        DoHatMove( Event );
+      end;
+
+      SDL_JOYBUTTONDOWN :
+      begin
+        DoButtonDown( Event );
+      end;
+
+      SDL_JOYBUTTONUP :
+      begin
+        DoButtonUp( Event );
+      end;
+    end;
+  end;
+end;
+
+{ TSDLCustomCursor }
+
+constructor TSDLCustomCursor.Create(const aFileName: string;  aHotPoint: TPoint);
+begin
+  inherited Create;
+  FHotPoint := aHotPoint;
+  LoadFromFile( aFileName );
+end;
+
+function TSDLCustomCursor.ScanForChar(str: string; ch: Char;
+  startPos: Integer; lookFor: Boolean): Integer;
+begin
+  Result := -1;
+  while ( ( ( str[ startPos ] = ch ) <> lookFor ) and ( startPos < Length( str ) ) ) do
+    inc( startPos );
+  if startPos <> Length( str ) then
+    Result := startPos;
+end;
+
+procedure TSDLCustomCursor.SetFileName(const aValue: string);
+begin
+  LoadFromFile( aValue );
+end;
+
+{ TSDLXPMCursor }
+
+destructor TSDLXPMCursor.Destroy;
+begin
+  FreeCursor;
+  inherited;
+end;
+
+procedure TSDLXPMCursor.FreeCursor;
+begin
+  if FCursor <> nil then
+  begin
+    SDL_FreeCursor( FCursor );
+    FFileName := ''; 
+  end;
+end;
+
+procedure TSDLXPMCursor.LoadFromFile(const aFileName: string);
+var
+  xpmFile : Textfile;
+  step : Integer;
+  holdPos : Integer;
+  counter : Integer;
+  dimensions : array[ 1..3 ] of Integer;
+  clr, clrNone, clrBlack, clrWhite : Char;
+  data, mask : array of UInt8;
+  i, col : Integer;
+  LineString : string;
+begin
+  FreeCursor;
+  AssignFile( xpmFile, aFileName );
+  Reset( xpmFile );
+  step := 0;
+  i := -1;
+  clrBlack := 'X';
+  clrWhite := ',';
+  clrNone := ' ';
+  counter := 0;
+  while not ( eof( xpmFile ) ) do
+  begin
+    Readln( xpmFile, LineString );
+    // scan for strings
+    if LineString[ 1 ] = '"' then
+    begin
+      case step of
+        0 : // Get dimensions  (should be width height number-of-colors ???)
+          begin
+            HoldPos := 2;
+            counter := ScanForChar( LineString, ' ', HoldPos, False );
+            counter := ScanForChar( LineString, ' ', counter, True );
+            dimensions[ 1 ] := StrToInt( Copy( LineString, HoldPos, counter - HoldPos ) );
+            counter := ScanForChar( LineString, ' ', counter, False );
+            holdPos := counter;
+            counter := ScanForChar( LineString, ' ', counter, True );
+            dimensions[ 2 ] := StrToInt( Copy( LineString, holdPos, counter - HoldPos ) );
+            counter := ScanForChar( LineString, ' ', counter, False );
+            holdPos := counter;
+            counter := ScanForChar( LineString, ' ', counter, True );
+            dimensions[ 3 ] := StrToInt( Copy( LineString, holdPos, counter - HoldPos ) );
+            step := 1;
+            SetLength( data, ( dimensions[ 1 ] * dimensions[ 2 ] ) div 8 );
+            SetLength( mask, ( dimensions[ 1 ] * dimensions[ 2 ] ) div 8 );
+            //Log.LogStatus( 'Length = ' + IntToStr( ( dimensions[ 1 ] * dimensions[ 2 ] ) div 8 ), 'LoadCursorFromFile' );
+          end;
+        1 : // get the symbols for transparent, black and white
+          begin
+            // get the symbol for the color
+            clr := LineString[ 2 ];
+            // look for the 'c' symbol
+            counter := ScanForChar( LineString, 'c', 3, True );
+            inc( counter );
+            counter := ScanForChar( LineString, ' ', counter, False );
+            if LowerCase( Copy( LineString, counter, 4 ) ) = 'none' then
+            begin
+              clrNone := clr;
+            end;
+            if LowerCase( Copy( LineString, counter, 7 ) ) = '#ffffff' then
+            begin
+              clrWhite := clr;
+            end;
+            if LowerCase( Copy( LineString, counter, 7 ) ) = '#000000' then
+            begin
+              clrBlack := clr;
+            end;
+            dec( dimensions[ 3 ] );
+            if dimensions[ 3 ] = 0 then
+            begin
+              step := 2;
+              counter := 0;
+            end;
+          end;
+        2 : // get cursor information -- modified from the SDL
+          // documentation of SDL_CreateCursor.
+          begin
+            for col := 1 to dimensions[1] do
+            begin
+              if ( ( col mod 8 ) <> 1 ) then
+              begin
+                data[ i ] := data[ i ] shl 1;
+                mask[ i ] := mask[ i ] shl 1;
+              end
+              else
+              begin
+                inc( i );
+                data[ i ] := 0;
+                mask[ i ] := 0;
+              end;
+              if LineString[ col ] = clrWhite then
+              begin
+                mask[ i ] := mask[ i ] or $01;
+              end
+              else if LineString[ col ] = clrBlack then
+              begin
+                data[ i ] := data[ i ] or $01;
+                mask[ i ] := mask[ i ] or $01;
+              end
+              else if LineString[ col + 1 ] = clrNone then
+              begin
+                //
+              end;
+            end;
+            inc(counter);
+            if counter = dimensions[2] then
+              step := 4;
+          end;
+      end;
+    end;
+  end;
+  CloseFile( xpmFile );
+  FCursor := SDL_CreateCursor( PUInt8( data ), PUInt8( mask ), dimensions[ 1 ], dimensions[ 2 ], FHotPoint.x, FHotPoint.y );
+end;
+
+procedure TSDLXPMCursor.LoadFromStream(aStream: TStream);
+begin
+  inherited;
+
+end;
+
+procedure TSDLXPMCursor.Show;
+begin
+  inherited;
+  SDL_SetCursor( FCursor );
+end;
+
+{ TSDLCursorList }
+function TSDLCursorList.AddCursor(const aName : string; aObject : TSDLCustomCursor): Integer;
+begin
+  result := inherited AddObject( aName, aObject );
+end;
+
+constructor TSDLCursorList.Create;
+begin
+  inherited;
+  Duplicates := dupIgnore;
+end;
+
+function TSDLCursorList.GetObject(aIndex: Integer): TSDLCustomCursor;
+begin
+  result := TSDLCustomCursor( inherited GetObject( aIndex ) );
+end;
+
+procedure TSDLCursorList.PutObject(aIndex: Integer; aObject: TSDLCustomCursor);
+begin
+  inherited PutObject( aIndex, aObject );
+end;
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlstreams.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlstreams.pas
new file mode 100644
index 00000000..8ba3946f
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlstreams.pas
@@ -0,0 +1,216 @@
+unit sdlstreams;
+{
+  $Id: sdlstreams.pas,v 1.1 2004/02/05 00:08:20 savage Exp $
+  
+}
+{******************************************************************}
+{                                                                  }
+{       SDL - Simple DirectMedia Layer                             }
+{    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga      }
+{                                                                  }
+{ Portions created by Chris Bruner are                             }
+{ Copyright (C) 2002 Chris Bruner.                                 }
+{                                                                  }
+{ Contributor(s)                                                   }
+{ --------------                                                   }
+{                                                                  }
+{                                                                  }
+{ Obtained through:                                                }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )            }
+{                                                                  }
+{ You may retrieve the latest version of this file at the Project  }
+{ JEDI home page, located at http://delphi-jedi.org                }
+{                                                                  }
+{ The contents of this file are used with permission, subject to   }
+{ the Mozilla Public License Version 1.1 (the "License"); you may  }
+{ not use this file except in compliance with the License. You may }
+{ obtain a copy of the License at                                  }
+{ http://www.mozilla.org/NPL/NPL-1_1Final.html                     }
+{                                                                  }
+{ Software distributed under the License is distributed on an      }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or   }
+{ implied. See the License for the specific language governing     }
+{ rights and limitations under the License.                        }
+{                                                                  }
+{ Description                                                      }
+{ -----------                                                      }
+{  Shows how to use OpenGL to do 2D and 3D with the SDL libraries  }
+{                                                                  }
+{                                                                  }
+{ Requires                                                         }
+{ --------                                                         }
+{   SDL runtime libary somewhere in your path                      }
+{   The Latest SDL runtime can be found on http://www.libsdl.org   }
+{                                                                  }
+{ Programming Notes                                                }
+{ -----------------                                                }
+{                                                                  }
+{                                                                  }
+{                                                                  }
+{                                                                  }
+{                                                                  }
+{ Revision History                                                 }
+{ ----------------                                                 }
+{   January  11 2002 - CB : Software embraced and extended by      }
+{                           Chris Bruner of Crystal Software       }
+{                           (Canada) Inc.                          }
+{                                                                  }
+{  February  11 2002 - DL : Added FreePascal support as suggested  }
+{                        by "QuePasha Pepe" <mrkroket@hotmail.com> }
+{                                                                  }
+{******************************************************************}
+{
+  $Log: sdlstreams.pas,v $
+  Revision 1.1  2004/02/05 00:08:20  savage
+  Module 1.0 release
+
+  
+}
+
+{$i jedi-sdl.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  sdl,
+  sdlutils;
+
+{$IFDEF FPC}
+type
+  EinvalidContainer=class(Exception); 
+ {$ENDIF}
+  
+function LoadSDLBMPFromStream( Stream : TStream ) : PSDL_Surface;
+procedure SaveSDLBMPToStream( SDL_Surface : PSDL_Surface; stream : TStream );
+function SDL_Swap16( D : UInt16 ) : Uint16;
+function SDL_Swap32( D : UInt32 ) : Uint32;
+function SDLStreamSetup( stream : TStream ) : PSDL_RWops;
+// this only closes the SDL_RWops part of the stream, not the stream itself
+procedure SDLStreamCloseRWops( SDL_RWops : PSDL_RWops );
+
+implementation
+
+function SDL_Swap16( D : UInt16 ) : Uint16;
+begin
+  Result := ( D shl 8 ) or ( D shr 8 );
+end;
+
+function SDL_Swap32( D : UInt32 ) : Uint32;
+begin
+  Result := ( ( D shl 24 ) or ( ( D shl 8 ) and $00FF0000 ) or ( ( D shr 8 ) and $0000FF00 ) or ( D shr 24 ) );
+end;
+
+(*function SDL_Swap64(D : UInt64) : Uint64;
+var hi,lo : Uint32;
+begin
+        // Separate into high and low 32-bit resultues and swap them
+        lo := Uint32(D and $0FFFFFFFF); // bloody pascal is too tight in it's type checking!
+        D := D shr 32;
+        hi = Uint32((D and $FFFFFFFF));
+        result = SDL_Swap32(lo);
+        result := result shl 32;
+        result := result or SDL_Swap32(hi);
+end;
+*)
+
+function SdlStreamSeek( context : PSDL_RWops; offset : Integer; whence : Integer ) : integer; cdecl;
+var
+  stream : TStream;
+  origin : Word;
+begin
+  stream := TStream( context.unknown );
+  if ( stream = nil ) then
+    raise EInvalidContainer.Create( 'SDLStreamSeek on nil' );
+  case whence of
+    0 : origin := soFromBeginning; //	Offset is from the beginning of the resource. Seek moves to the position Offset. Offset must be >= 0.
+    1 : origin := soFromCurrent; //	Offset is from the current position in the resource. Seek moves to Position + Offset.
+    2 : origin := soFromEnd;
+  else
+    origin := soFromBeginning; // just in case
+  end;
+  Result := stream.Seek( offset, origin );
+end;
+
+function SDLStreamWrite( context : PSDL_RWops; Ptr : Pointer;
+  size : Integer; num : Integer ) : Integer; cdecl;
+var
+  stream : TStream;
+begin
+  stream := TStream( context.unknown );
+  if ( stream = nil ) then
+    raise EInvalidContainer.Create( 'SDLStreamWrite on nil' );
+  try
+    Result := stream.Write( Ptr^, Size * num ) div size;
+  except
+    Result := -1;
+  end;
+end;
+
+function SdlStreamRead( context : PSDL_RWops; Ptr : Pointer; size : Integer; maxnum
+  : Integer ) : Integer; cdecl;
+var
+  stream : TStream;
+begin
+  stream := TStream( context.unknown );
+  if ( stream = nil ) then
+    raise EInvalidContainer.Create( 'SDLStreamRead on nil' );
+  try
+    Result := stream.read( Ptr^, Size * maxnum ) div size;
+  except
+    Result := -1;
+  end;
+end;
+
+function SDLStreamClose( context : PSDL_RWops ) : Integer; cdecl;
+var
+  stream : TStream;
+begin
+  stream := TStream( context.unknown );
+  if ( stream = nil ) then
+    raise EInvalidContainer.Create( 'SDLStreamClose on nil' );
+  stream.Free;
+  Result := 1;
+end;
+
+function SDLStreamSetup( stream : TStream ) : PSDL_RWops;
+begin
+  result := SDL_AllocRW;
+  if ( result = nil ) then
+    raise EInvalidContainer.Create( 'could not create SDLStream on nil' );
+  result.unknown := TUnknown( stream );
+  result.seek := SDLStreamSeek;
+  result.read := SDLStreamRead;
+  result.write := SDLStreamWrite;
+  result.close := SDLStreamClose;
+  Result.type_ := 2; // TUnknown
+end;
+
+// this only closes the SDL part of the stream, not the context
+
+procedure SDLStreamCloseRWops( SDL_RWops : PSDL_RWops );
+begin
+  SDL_FreeRW( SDL_RWops );
+end;
+
+function LoadSDLBMPFromStream( stream : TStream ) : PSDL_Surface;
+var
+  SDL_RWops : PSDL_RWops;
+begin
+  SDL_RWops := SDLStreamSetup( stream );
+  result := SDL_LoadBMP_RW( SDL_RWops, 0 );
+  SDLStreamCloseRWops( SDL_RWops );
+end;
+
+procedure SaveSDLBMPToStream( SDL_Surface : PSDL_Surface; stream : TStream );
+var
+  SDL_RWops : PSDL_RWops;
+begin
+  SDL_RWops := SDLStreamSetup( stream );
+  SDL_SaveBMP_RW( SDL_Surface, SDL_RWops, 0 );
+  SDLStreamCloseRWops( SDL_RWops );
+end;
+
+end.
+
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlticks.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlticks.pas
new file mode 100644
index 00000000..a479b493
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlticks.pas
@@ -0,0 +1,197 @@
+unit sdlticks;
+{
+  $Id: sdlticks.pas,v 1.2 2006/11/08 08:22:48 savage Exp $
+
+}
+{******************************************************************************}
+{                                                                              }
+{          JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer          }
+{                   SDL GetTicks Class Wrapper                                 }
+{                                                                              }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Portions created by Dominique Louis are                                      }
+{ Copyright (C) 2004 - 2100 Dominique Louis.                                   }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{   SDL Window Wrapper                                                         }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   SDL.dll on Windows platforms                                               }
+{   libSDL-1.1.so.0 on Linux platform                                          }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{                                                                              }
+{   September   23 2004 - DL : Initial Creation                                }
+{
+  $Log: sdlticks.pas,v $
+  Revision 1.2  2006/11/08 08:22:48  savage
+  updates tp sdlgameinterface and sdlticks functions.
+
+  Revision 1.1  2004/09/30 22:35:47  savage
+  Changes, enhancements and additions as required to get SoAoS working.
+
+}
+{******************************************************************************}
+
+interface
+
+uses
+  sdl;
+
+type
+  TSDLTicks = class
+  private
+    FStartTime : UInt32;
+    FTicksPerSecond : UInt32;
+    FElapsedLastTime : UInt32;
+    FFPSLastTime : UInt32;
+    FLockFPSLastTime : UInt32;
+  public
+    constructor Create;
+    destructor Destroy; override; // destructor
+
+    {*****************************************************************************
+     Init
+     If the hi-res timer is present, the tick rate is stored and the function
+     returns true. Otherwise, the function returns false, and the timer should
+     not be used.
+    *****************************************************************************}
+    function Init : boolean;
+
+    {***************************************************************************
+     GetGetElapsedSeconds
+     Returns the Elapsed time, since the function was last called.
+    ***************************************************************************}
+    function GetElapsedSeconds : Single;
+
+    {***************************************************************************
+     GetFPS
+     Returns the average frames per second.
+     If this is not called every frame, the client should track the number
+     of frames itself, and reset the value after this is called.
+    ***************************************************************************}
+    function GetFPS : single;
+
+    {***************************************************************************
+     LockFPS
+     Used to lock the frame rate to a set amount. This will block until enough
+     time has passed to ensure that the fps won't go over the requested amount.
+     Note that this can only keep the fps from going above the specified level;
+     it can still drop below it. It is assumed that if used, this function will
+     be called every frame. The value returned is the instantaneous fps, which
+     will be less than or equal to the targetFPS.
+    ***************************************************************************}
+    procedure LockFPS( targetFPS : Byte );
+  end;
+
+implementation
+
+{ TSDLTicks }
+constructor TSDLTicks.Create;
+begin
+  inherited;
+  FTicksPerSecond := 1000;
+end;
+
+destructor TSDLTicks.Destroy;
+begin
+  inherited;
+end;
+
+function TSDLTicks.GetElapsedSeconds : Single;
+var
+  currentTime       : Cardinal;
+begin
+  currentTime := SDL_GetTicks;
+
+  result := ( currentTime - FElapsedLastTime ) / FTicksPerSecond;
+
+  // reset the timer
+  FElapsedLastTime := currentTime;
+end;
+
+function TSDLTicks.GetFPS : Single;
+var
+  currentTime, FrameTime : UInt32;
+  fps               : single;
+begin
+  currentTime := SDL_GetTicks;
+
+  FrameTime := ( currentTime - FFPSLastTime );
+
+  if FrameTime = 0 then
+    FrameTime := 1;
+
+  fps := FTicksPerSecond / FrameTime;
+
+  // reset the timer
+  FFPSLastTime := currentTime;
+  result := fps;
+end;
+
+function TSDLTicks.Init : boolean;
+begin
+  FStartTime := SDL_GetTicks;
+  FElapsedLastTime := FStartTime;
+  FFPSLastTime := FStartTime;
+  FLockFPSLastTime := FStartTime;
+  result := true;
+end;
+
+procedure TSDLTicks.LockFPS( targetFPS : Byte );
+var
+  currentTime       : UInt32;
+  targetTime        : single;
+begin
+  if ( targetFPS = 0 ) then
+    targetFPS := 1;
+
+  targetTime := FTicksPerSecond / targetFPS;
+
+  // delay to maintain a constant frame rate
+  repeat
+    currentTime := SDL_GetTicks;
+  until ( ( currentTime - FLockFPSLastTime ) > targetTime );
+
+  // reset the timer
+  FLockFPSLastTime := currentTime;
+end;
+
+end.
+
+ 
\ No newline at end of file
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlutils.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlutils.pas
new file mode 100644
index 00000000..e01f3cdb
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlutils.pas
@@ -0,0 +1,4363 @@
+unit sdlutils;
+{
+  $Id: sdlutils.pas,v 1.5 2006/11/19 18:56:44 savage Exp $
+
+}
+{******************************************************************************}
+{                                                                              }
+{       Borland Delphi SDL - Simple DirectMedia Layer                          }
+{                SDL Utility functions                                         }
+{                                                                              }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Tom Jones <tigertomjones@gmx.de>                                             }
+{                                                                              }
+{ Portions created by Tom Jones are                                            }
+{ Copyright (C) 2000 - 2001 Tom Jones.                                         }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{ R�bert Kisn�meth <mikrobi@freemail.hu>                                       }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{   Helper functions...                                                        }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   SDL.dll on Windows platforms                                               }
+{   libSDL-1.1.so.0 on Linux platform                                          }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{               2000 - TJ : Initial creation                                   }
+{                                                                              }
+{   July   13   2001 - DL : Added PutPixel and GetPixel routines.              }
+{                                                                              }
+{   Sept   14   2001 - RK : Added flipping routines.                           }
+{                                                                              }
+{   Sept   19   2001 - RK : Added PutPixel & line drawing & blitting with ADD  }
+{                           effect. Fixed a bug in SDL_PutPixel & SDL_GetPixel }
+{                           Added PSDLRect()                                   }
+{   Sept   22   2001 - DL : Removed need for Windows.pas by defining types here}
+{                           Also removed by poor attempt or a dialog box       }
+{                                                                              }
+{   Sept   25   2001 - RK : Added PixelTest, NewPutPixel, SubPixel, SubLine,   }
+{                           SubSurface, MonoSurface & TexturedSurface          }
+{                                                                              }
+{   Sept   26   2001 - DL : Made change so that it refers to native Pascal     }
+{                           types rather that Windows types. This makes it more}
+{                           portable to Linix.                                 }
+{                                                                              }
+{   Sept   27   2001 - RK : SDLUtils now can be compiled with FreePascal       }
+{                                                                              }
+{   Oct    27   2001 - JF : Added ScrollY function                             }
+{                                                                              }
+{   Jan    21   2002 - RK : Added SDL_ZoomSurface and SDL_WarpSurface          }
+{                                                                              }
+{   Mar    28   2002 - JF : Added SDL_RotateSurface                            }
+{                                                                              }
+{   May    13   2002 - RK : Improved SDL_FillRectAdd & SDL_FillRectSub         }
+{                                                                              }
+{   May    27   2002 - YS : GradientFillRect function                          }
+{                                                                              }
+{   May    30   2002 - RK : Added SDL_2xBlit, SDL_Scanline2xBlit               }
+{                           & SDL_50Scanline2xBlit                             }
+{                                                                              }
+{  June    12   2002 - RK : Added SDL_PixelTestSurfaceVsRect                   }
+{                                                                              }
+{  June    12   2002 - JF : Updated SDL_PixelTestSurfaceVsRect                 }
+{                                                                              }
+{ November  9   2002 - JF : Added Jason's boolean Surface functions            }
+{                                                                              }
+{ December 10   2002 - DE : Added Dean's SDL_ClipLine function                 }
+{                                                                              }
+{    April 26   2003 - SS : Incorporated JF's changes to SDL_ClipLine          }
+{                           Fixed SDL_ClipLine bug for non-zero cliprect x, y  }
+{                           Added overloaded SDL_DrawLine for dashed lines     }
+{                                                                              }
+{******************************************************************************}
+{
+  $Log: sdlutils.pas,v $
+  Revision 1.5  2006/11/19 18:56:44  savage
+  Removed Hints and Warnings.
+
+  Revision 1.4  2004/06/02 19:38:53  savage
+  Changes to SDL_GradientFillRect as suggested by
+  �ngel Eduardo Garc�a Hern�ndez.  Many thanks.
+
+  Revision 1.3  2004/05/29 23:11:54  savage
+  Changes to SDL_ScaleSurfaceRect as suggested by
+  �ngel Eduardo Garc�a Hern�ndez to fix a colour issue with the function. Many thanks.
+
+  Revision 1.2  2004/02/14 00:23:39  savage
+  As UNIX is defined in jedi-sdl.inc this will be used to check linux compatability as well. Units have been changed to reflect this change.
+
+  Revision 1.1  2004/02/05 00:08:20  savage
+  Module 1.0 release
+
+
+}
+
+interface
+
+{$I jedi-sdl.inc}
+
+uses
+{$IFDEF UNIX}
+  Types,
+{$IFNDEF DARWIN}
+  Xlib,
+{$ENDIF}
+{$ENDIF}
+  SysUtils,
+  sdl;
+
+type
+  TGradientStyle = ( gsHorizontal, gsVertical );
+
+// Pixel procedures
+function SDL_PixelTest( SrcSurface1 : PSDL_Surface; SrcRect1 : PSDL_Rect; SrcSurface2 :
+  PSDL_Surface; SrcRect2 : PSDL_Rect; Left1, Top1, Left2, Top2 : integer ) : Boolean;
+
+function SDL_GetPixel( SrcSurface : PSDL_Surface; x : integer; y : integer ) : Uint32;
+
+procedure SDL_PutPixel( DstSurface : PSDL_Surface; x : integer; y : integer; pixel :
+  Uint32 );
+
+procedure SDL_AddPixel( DstSurface : PSDL_Surface; x : cardinal; y : cardinal; Color :
+  cardinal );
+
+procedure SDL_SubPixel( DstSurface : PSDL_Surface; x : cardinal; y : cardinal; Color :
+  cardinal );
+
+// Line procedures
+procedure SDL_DrawLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal ); overload;
+
+procedure SDL_DrawLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal; DashLength, DashSpace : byte ); overload;
+
+procedure SDL_AddLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+
+procedure SDL_SubLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+
+// Surface procedures
+procedure SDL_AddSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+procedure SDL_SubSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+procedure SDL_MonoSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect; Color : cardinal );
+
+procedure SDL_TexturedSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect; Texture : PSDL_Surface;
+  TextureRect : PSDL_Rect );
+
+procedure SDL_ZoomSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect; DstSurface : PSDL_Surface; DstRect : PSDL_Rect );
+
+procedure SDL_WarpSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect; DstSurface : PSDL_Surface; UL, UR, LR, LL : PPoint );
+
+// Flip procedures
+procedure SDL_FlipRectH( DstSurface : PSDL_Surface; Rect : PSDL_Rect );
+
+procedure SDL_FlipRectV( DstSurface : PSDL_Surface; Rect : PSDL_Rect );
+
+function PSDLRect( aLeft, aTop, aWidth, aHeight : integer ) : PSDL_Rect;
+
+function SDLRect( aLeft, aTop, aWidth, aHeight : integer ) : TSDL_Rect; overload;
+
+function SDLRect( aRect : TRect ) : TSDL_Rect; overload;
+
+function SDL_ScaleSurfaceRect( SrcSurface : PSDL_Surface; SrcX1, SrcY1, SrcW, SrcH,
+  Width, Height : integer ) : PSDL_Surface;
+
+procedure SDL_ScrollY( DstSurface : PSDL_Surface; DifY : integer );
+
+procedure SDL_ScrollX( DstSurface : PSDL_Surface; DifX : integer );
+
+procedure SDL_RotateDeg( DstSurface, SrcSurface : PSDL_Surface; SrcRect :
+  PSDL_Rect; DestX, DestY, OffsetX, OffsetY : Integer; Angle : Integer );
+
+procedure SDL_RotateRad( DstSurface, SrcSurface : PSDL_Surface; SrcRect :
+  PSDL_Rect; DestX, DestY, OffsetX, OffsetY : Integer; Angle : Single );
+
+function ValidateSurfaceRect( DstSurface : PSDL_Surface; dstrect : PSDL_Rect ) : TSDL_Rect;
+
+// Fill Rect routine
+procedure SDL_FillRectAdd( DstSurface : PSDL_Surface; dstrect : PSDL_Rect; color : UInt32 );
+
+procedure SDL_FillRectSub( DstSurface : PSDL_Surface; dstrect : PSDL_Rect; color : UInt32 );
+
+procedure SDL_GradientFillRect( DstSurface : PSDL_Surface; const Rect : PSDL_Rect; const StartColor, EndColor : TSDL_Color; const Style : TGradientStyle );
+
+// NOTE for All SDL_2xblit... function : the dest surface must be 2x of the source surface!
+procedure SDL_2xBlit( Src, Dest : PSDL_Surface );
+
+procedure SDL_Scanline2xBlit( Src, Dest : PSDL_Surface );
+
+procedure SDL_50Scanline2xBlit( Src, Dest : PSDL_Surface );
+
+//
+function SDL_PixelTestSurfaceVsRect( SrcSurface1 : PSDL_Surface; SrcRect1 :
+  PSDL_Rect; SrcRect2 : PSDL_Rect; Left1, Top1, Left2, Top2 : integer ) :
+  boolean;
+
+// Jason's boolean Surface functions
+procedure SDL_ORSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+procedure SDL_ANDSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+
+procedure SDL_GTSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+procedure SDL_LTSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+
+function SDL_ClipLine( var x1, y1, x2, y2 : Integer; ClipRect : PSDL_Rect ) : boolean;
+
+implementation
+
+uses
+  Math;
+
+function SDL_PixelTest( SrcSurface1 : PSDL_Surface; SrcRect1 : PSDL_Rect; SrcSurface2 :
+  PSDL_Surface; SrcRect2 : PSDL_Rect; Left1, Top1, Left2, Top2 : integer ) : boolean;
+var
+  Src_Rect1, Src_Rect2 : TSDL_Rect;
+  right1, bottom1 : integer;
+  right2, bottom2 : integer;
+  Scan1Start, Scan2Start, ScanWidth, ScanHeight : cardinal;
+  Mod1, Mod2   : cardinal;
+  Addr1, Addr2 : PtrUInt;
+  BPP          : cardinal;
+  Pitch1, Pitch2 : cardinal;
+  TransparentColor1, TransparentColor2 : cardinal;
+  tx, ty       : cardinal;
+// StartTick    : cardinal; // Auto Removed, Unused Variable
+  Color1, Color2 : cardinal;
+begin
+  Result := false;
+  if SrcRect1 = nil then
+  begin
+    with Src_Rect1 do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface1.w;
+      h := SrcSurface1.h;
+    end;
+  end
+  else
+    Src_Rect1 := SrcRect1^;
+  if SrcRect2 = nil then
+  begin
+    with Src_Rect2 do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface2.w;
+      h := SrcSurface2.h;
+    end;
+  end
+  else
+    Src_Rect2 := SrcRect2^;
+  with Src_Rect1 do
+  begin
+    Right1 := Left1 + w;
+    Bottom1 := Top1 + h;
+  end;
+  with Src_Rect2 do
+  begin
+    Right2 := Left2 + w;
+    Bottom2 := Top2 + h;
+  end;
+  if ( Left1 >= Right2 ) or ( Right1 <= Left2 ) or ( Top1 >= Bottom2 ) or ( Bottom1 <=
+    Top2 ) then
+    exit;
+  if Left1 <= Left2 then
+  begin
+    // 1. left, 2. right
+    Scan1Start := Src_Rect1.x + Left2 - Left1;
+    Scan2Start := Src_Rect2.x;
+    ScanWidth := Right1 - Left2;
+    with Src_Rect2 do
+      if ScanWidth > w then
+        ScanWidth := w;
+  end
+  else
+  begin
+    // 1. right, 2. left
+    Scan1Start := Src_Rect1.x;
+    Scan2Start := Src_Rect2.x + Left1 - Left2;
+    ScanWidth := Right2 - Left1;
+    with Src_Rect1 do
+      if ScanWidth > w then
+        ScanWidth := w;
+  end;
+  with SrcSurface1^ do
+  begin
+    Pitch1 := Pitch;
+    Addr1 := PtrUInt( Pixels );
+    inc( Addr1, Pitch1 * UInt32( Src_Rect1.y ) );
+    with format^ do
+    begin
+      BPP := BytesPerPixel;
+      TransparentColor1 := colorkey;
+    end;
+  end;
+  with SrcSurface2^ do
+  begin
+    TransparentColor2 := format.colorkey;
+    Pitch2 := Pitch;
+    Addr2 := PtrUInt( Pixels );
+    inc( Addr2, Pitch2 * UInt32( Src_Rect2.y ) );
+  end;
+  Mod1 := Pitch1 - ( ScanWidth * BPP );
+  Mod2 := Pitch2 - ( ScanWidth * BPP );
+  inc( Addr1, BPP * Scan1Start );
+  inc( Addr2, BPP * Scan2Start );
+  if Top1 <= Top2 then
+  begin
+    // 1. up, 2. down
+    ScanHeight := Bottom1 - Top2;
+    if ScanHeight > Src_Rect2.h then
+      ScanHeight := Src_Rect2.h;
+    inc( Addr1, Pitch1 * UInt32( Top2 - Top1 ) );
+  end
+  else
+  begin
+    // 1. down, 2. up
+    ScanHeight := Bottom2 - Top1;
+    if ScanHeight > Src_Rect1.h then
+      ScanHeight := Src_Rect1.h;
+    inc( Addr2, Pitch2 * UInt32( Top1 - Top2 ) );
+  end;
+  case BPP of
+    1 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PByte( Addr1 )^ <> TransparentColor1 ) and ( PByte( Addr2 )^ <>
+            TransparentColor2 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1 );
+          inc( Addr2 );
+        end;
+        inc( Addr1, Mod1 );
+        inc( Addr2, Mod2 );
+      end;
+    2 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PWord( Addr1 )^ <> TransparentColor1 ) and ( PWord( Addr2 )^ <>
+            TransparentColor2 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 2 );
+          inc( Addr2, 2 );
+        end;
+        inc( Addr1, Mod1 );
+        inc( Addr2, Mod2 );
+      end;
+    3 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          Color1 := PLongWord( Addr1 )^ and $00FFFFFF;
+          Color2 := PLongWord( Addr2 )^ and $00FFFFFF;
+          if ( Color1 <> TransparentColor1 ) and ( Color2 <> TransparentColor2 )
+            then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 3 );
+          inc( Addr2, 3 );
+        end;
+        inc( Addr1, Mod1 );
+        inc( Addr2, Mod2 );
+      end;
+    4 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PLongWord( Addr1 )^ <> TransparentColor1 ) and ( PLongWord( Addr2 )^ <>
+            TransparentColor2 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 4 );
+          inc( Addr2, 4 );
+        end;
+        inc( Addr1, Mod1 );
+        inc( Addr2, Mod2 );
+      end;
+  end;
+end;
+
+procedure SDL_AddPixel( DstSurface : PSDL_Surface; x : cardinal; y : cardinal; Color :
+  cardinal );
+var
+  SrcColor     : cardinal;
+  Addr         : PtrUInt;
+  R, G, B      : cardinal;
+begin
+  if Color = 0 then
+    exit;
+  with DstSurface^ do
+  begin
+    Addr := PtrUInt( Pixels ) + y * Pitch + x * format.BytesPerPixel;
+    SrcColor := PUInt32( Addr )^;
+    case format.BitsPerPixel of
+      8 :
+        begin
+          R := SrcColor and $E0 + Color and $E0;
+          G := SrcColor and $1C + Color and $1C;
+          B := SrcColor and $03 + Color and $03;
+          if R > $E0 then
+            R := $E0;
+          if G > $1C then
+            G := $1C;
+          if B > $03 then
+            B := $03;
+          PUInt8( Addr )^ := R or G or B;
+        end;
+      15 :
+        begin
+          R := SrcColor and $7C00 + Color and $7C00;
+          G := SrcColor and $03E0 + Color and $03E0;
+          B := SrcColor and $001F + Color and $001F;
+          if R > $7C00 then
+            R := $7C00;
+          if G > $03E0 then
+            G := $03E0;
+          if B > $001F then
+            B := $001F;
+          PUInt16( Addr )^ := R or G or B;
+        end;
+      16 :
+        begin
+          R := SrcColor and $F800 + Color and $F800;
+          G := SrcColor and $07C0 + Color and $07C0;
+          B := SrcColor and $001F + Color and $001F;
+          if R > $F800 then
+            R := $F800;
+          if G > $07C0 then
+            G := $07C0;
+          if B > $001F then
+            B := $001F;
+          PUInt16( Addr )^ := R or G or B;
+        end;
+      24 :
+        begin
+          R := SrcColor and $00FF0000 + Color and $00FF0000;
+          G := SrcColor and $0000FF00 + Color and $0000FF00;
+          B := SrcColor and $000000FF + Color and $000000FF;
+          if R > $FF0000 then
+            R := $FF0000;
+          if G > $00FF00 then
+            G := $00FF00;
+          if B > $0000FF then
+            B := $0000FF;
+          PUInt32( Addr )^ := SrcColor and $FF000000 or R or G or B;
+        end;
+      32 :
+        begin
+          R := SrcColor and $00FF0000 + Color and $00FF0000;
+          G := SrcColor and $0000FF00 + Color and $0000FF00;
+          B := SrcColor and $000000FF + Color and $000000FF;
+          if R > $FF0000 then
+            R := $FF0000;
+          if G > $00FF00 then
+            G := $00FF00;
+          if B > $0000FF then
+            B := $0000FF;
+          PUInt32( Addr )^ := R or G or B;
+        end;
+    end;
+  end;
+end;
+
+procedure SDL_SubPixel( DstSurface : PSDL_Surface; x : cardinal; y : cardinal; Color :
+  cardinal );
+var
+  SrcColor     : cardinal;
+  Addr         : PtrUInt;
+  R, G, B      : cardinal;
+begin
+  if Color = 0 then
+    exit;
+  with DstSurface^ do
+  begin
+    Addr := PtrUInt( Pixels ) + y * Pitch + x * format.BytesPerPixel;
+    SrcColor := PUInt32( Addr )^;
+    case format.BitsPerPixel of
+      8 :
+        begin
+          R := SrcColor and $E0 - Color and $E0;
+          G := SrcColor and $1C - Color and $1C;
+          B := SrcColor and $03 - Color and $03;
+          if R > $E0 then
+            R := 0;
+          if G > $1C then
+            G := 0;
+          if B > $03 then
+            B := 0;
+          PUInt8( Addr )^ := R or G or B;
+        end;
+      15 :
+        begin
+          R := SrcColor and $7C00 - Color and $7C00;
+          G := SrcColor and $03E0 - Color and $03E0;
+          B := SrcColor and $001F - Color and $001F;
+          if R > $7C00 then
+            R := 0;
+          if G > $03E0 then
+            G := 0;
+          if B > $001F then
+            B := 0;
+          PUInt16( Addr )^ := R or G or B;
+        end;
+      16 :
+        begin
+          R := SrcColor and $F800 - Color and $F800;
+          G := SrcColor and $07C0 - Color and $07C0;
+          B := SrcColor and $001F - Color and $001F;
+          if R > $F800 then
+            R := 0;
+          if G > $07C0 then
+            G := 0;
+          if B > $001F then
+            B := 0;
+          PUInt16( Addr )^ := R or G or B;
+        end;
+      24 :
+        begin
+          R := SrcColor and $00FF0000 - Color and $00FF0000;
+          G := SrcColor and $0000FF00 - Color and $0000FF00;
+          B := SrcColor and $000000FF - Color and $000000FF;
+          if R > $FF0000 then
+            R := 0;
+          if G > $00FF00 then
+            G := 0;
+          if B > $0000FF then
+            B := 0;
+          PUInt32( Addr )^ := SrcColor and $FF000000 or R or G or B;
+        end;
+      32 :
+        begin
+          R := SrcColor and $00FF0000 - Color and $00FF0000;
+          G := SrcColor and $0000FF00 - Color and $0000FF00;
+          B := SrcColor and $000000FF - Color and $000000FF;
+          if R > $FF0000 then
+            R := 0;
+          if G > $00FF00 then
+            G := 0;
+          if B > $0000FF then
+            B := 0;
+          PUInt32( Addr )^ := R or G or B;
+        end;
+    end;
+  end;
+end;
+// This procedure works on 8, 15, 16, 24 and 32 bits color depth surfaces.
+// In 8 bit color depth mode the procedure works with the default packed
+//  palette (RRRGGGBB). It handles all clipping.
+
+procedure SDL_AddSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+  Src, Dest    : TSDL_Rect;
+  Diff         : integer;
+  SrcAddr, DestAddr : PtrUInt;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits         : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt8( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt8( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel1 and $E0 + Pixel2 and $E0;
+                G := Pixel1 and $1C + Pixel2 and $1C;
+                B := Pixel1 and $03 + Pixel2 and $03;
+                if R > $E0 then
+                  R := $E0;
+                if G > $1C then
+                  G := $1C;
+                if B > $03 then
+                  B := $03;
+                PUInt8( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt8( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    15 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel1 and $7C00 + Pixel2 and $7C00;
+                G := Pixel1 and $03E0 + Pixel2 and $03E0;
+                B := Pixel1 and $001F + Pixel2 and $001F;
+                if R > $7C00 then
+                  R := $7C00;
+                if G > $03E0 then
+                  G := $03E0;
+                if B > $001F then
+                  B := $001F;
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    16 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel1 and $F800 + Pixel2 and $F800;
+                G := Pixel1 and $07E0 + Pixel2 and $07E0;
+                B := Pixel1 and $001F + Pixel2 and $001F;
+                if R > $F800 then
+                  R := $F800;
+                if G > $07E0 then
+                  G := $07E0;
+                if B > $001F then
+                  B := $001F;
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    24 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^ and $00FFFFFF;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel1 and $FF0000 + Pixel2 and $FF0000;
+                G := Pixel1 and $00FF00 + Pixel2 and $00FF00;
+                B := Pixel1 and $0000FF + Pixel2 and $0000FF;
+                if R > $FF0000 then
+                  R := $FF0000;
+                if G > $00FF00 then
+                  G := $00FF00;
+                if B > $0000FF then
+                  B := $0000FF;
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or ( R or G or B );
+              end
+              else
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or Pixel1;
+            end;
+            inc( SrcAddr, 3 );
+            inc( DestAddr, 3 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    32 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel1 and $FF0000 + Pixel2 and $FF0000;
+                G := Pixel1 and $00FF00 + Pixel2 and $00FF00;
+                B := Pixel1 and $0000FF + Pixel2 and $0000FF;
+                if R > $FF0000 then
+                  R := $FF0000;
+                if G > $00FF00 then
+                  G := $00FF00;
+                if B > $0000FF then
+                  B := $0000FF;
+                PUInt32( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt32( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 4 );
+            inc( DestAddr, 4 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+procedure SDL_SubSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+  Src, Dest    : TSDL_Rect;
+  Diff         : integer;
+  SrcAddr, DestAddr : PtrUInt;
+//{*_ebx, *}{*_esi, *}{*_edi, _esp*} : cardinal; // Auto Removed, Unused Variable (_ebx) // Auto Removed, Unused Variable (_esi) // Auto Removed, Unused Variable (_edi)
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits         : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := DestSurface.Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt8( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt8( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel2 and $E0 - Pixel1 and $E0;
+                G := Pixel2 and $1C - Pixel1 and $1C;
+                B := Pixel2 and $03 - Pixel1 and $03;
+                if R > $E0 then
+                  R := 0;
+                if G > $1C then
+                  G := 0;
+                if B > $03 then
+                  B := 0;
+                PUInt8( DestAddr )^ := R or G or B;
+              end;
+            end;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    15 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel2 and $7C00 - Pixel1 and $7C00;
+                G := Pixel2 and $03E0 - Pixel1 and $03E0;
+                B := Pixel2 and $001F - Pixel1 and $001F;
+                if R > $7C00 then
+                  R := 0;
+                if G > $03E0 then
+                  G := 0;
+                if B > $001F then
+                  B := 0;
+                PUInt16( DestAddr )^ := R or G or B;
+              end;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    16 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel2 and $F800 - Pixel1 and $F800;
+                G := Pixel2 and $07E0 - Pixel1 and $07E0;
+                B := Pixel2 and $001F - Pixel1 and $001F;
+                if R > $F800 then
+                  R := 0;
+                if G > $07E0 then
+                  G := 0;
+                if B > $001F then
+                  B := 0;
+                PUInt16( DestAddr )^ := R or G or B;
+              end;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    24 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^ and $00FFFFFF;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel2 and $FF0000 - Pixel1 and $FF0000;
+                G := Pixel2 and $00FF00 - Pixel1 and $00FF00;
+                B := Pixel2 and $0000FF - Pixel1 and $0000FF;
+                if R > $FF0000 then
+                  R := 0;
+                if G > $00FF00 then
+                  G := 0;
+                if B > $0000FF then
+                  B := 0;
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or ( R or G or B );
+              end;
+            end;
+            inc( SrcAddr, 3 );
+            inc( DestAddr, 3 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    32 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                R := Pixel2 and $FF0000 - Pixel1 and $FF0000;
+                G := Pixel2 and $00FF00 - Pixel1 and $00FF00;
+                B := Pixel2 and $0000FF - Pixel1 and $0000FF;
+                if R > $FF0000 then
+                  R := 0;
+                if G > $00FF00 then
+                  G := 0;
+                if B > $0000FF then
+                  B := 0;
+                PUInt32( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt32( DestAddr )^ := Pixel2;
+            end;
+            inc( SrcAddr, 4 );
+            inc( DestAddr, 4 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+procedure SDL_MonoSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect; Color : cardinal );
+var
+  Src, Dest    : TSDL_Rect;
+  Diff         : integer;
+  SrcAddr, DestAddr : PtrUInt;
+//{*_ebx, *}{*_esi, *}{*_edi, _esp*} : cardinal; // Auto Removed, Unused Variable (_ebx) // Auto Removed, Unused Variable (_esi) // Auto Removed, Unused Variable (_edi)
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  TransparentColor, SrcColor : cardinal;
+  BPP          : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    BPP := DestSurface.Format.BytesPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case BPP of
+    1 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            SrcColor := PUInt8( SrcAddr )^;
+            if SrcColor <> TransparentColor then
+              PUInt8( DestAddr )^ := SrcColor;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    2 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            SrcColor := PUInt16( SrcAddr )^;
+            if SrcColor <> TransparentColor then
+              PUInt16( DestAddr )^ := SrcColor;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    3 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            SrcColor := PUInt32( SrcAddr )^ and $FFFFFF;
+            if SrcColor <> TransparentColor then
+              PUInt32( DestAddr )^ := ( PUInt32( DestAddr )^ and $FFFFFF ) or SrcColor;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    4 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            SrcColor := PUInt32( SrcAddr )^;
+            if SrcColor <> TransparentColor then
+              PUInt32( DestAddr )^ := SrcColor;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+// TextureRect.w and TextureRect.h are not used.
+// The TextureSurface's size MUST larger than the drawing rectangle!!!
+
+procedure SDL_TexturedSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect; Texture : PSDL_Surface;
+  TextureRect : PSDL_Rect );
+var
+  Src, Dest    : TSDL_Rect;
+  Diff         : integer;
+  SrcAddr, DestAddr, TextAddr : PtrUInt;
+//{*_ebx, *}{*_esi, *}{*_edi, _esp*}: cardinal; // Auto Removed, Unused Variable (_ebx) // Auto Removed, Unused Variable (_esi) // Auto Removed, Unused Variable (_edi)
+  WorkX, WorkY : word;
+  SrcMod, DestMod, TextMod : cardinal;
+SrcColor, TransparentColor{*, TextureColor*} : cardinal; // Auto Removed, Unused Variable (TextureColor)
+  BPP          : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    BPP := DestSurface.Format.BitsPerPixel;
+  end;
+  with Texture^ do
+  begin
+    TextAddr := PtrUInt( Pixels ) + UInt32( TextureRect.y ) * Pitch +
+      UInt32( TextureRect.x ) * Format.BytesPerPixel;
+    TextMod := Pitch - Src.w * Format.BytesPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  SDL_LockSurface( Texture );
+  WorkY := Src.h;
+  case BPP of
+    1 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            SrcColor := PUInt8( SrcAddr )^;
+            if SrcColor <> TransparentColor then
+              PUInt8( DestAddr )^ := PUint8( TextAddr )^;
+            inc( SrcAddr );
+            inc( DestAddr );
+            inc( TextAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          inc( TextAddr, TextMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    2 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            SrcColor := PUInt16( SrcAddr )^;
+            if SrcColor <> TransparentColor then
+              PUInt16( DestAddr )^ := PUInt16( TextAddr )^;
+            inc( SrcAddr );
+            inc( DestAddr );
+            inc( TextAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          inc( TextAddr, TextMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    3 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            SrcColor := PUInt32( SrcAddr )^ and $FFFFFF;
+            if SrcColor <> TransparentColor then
+              PUInt32( DestAddr )^ := ( PUInt32( DestAddr )^ and $FFFFFF ) or ( PUInt32( TextAddr )^ and $FFFFFF );
+            inc( SrcAddr );
+            inc( DestAddr );
+            inc( TextAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          inc( TextAddr, TextMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    4 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            SrcColor := PUInt32( SrcAddr )^;
+            if SrcColor <> TransparentColor then
+              PUInt32( DestAddr )^ := PUInt32( TextAddr )^;
+            inc( SrcAddr );
+            inc( DestAddr );
+            inc( TextAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          inc( TextAddr, TextMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+  SDL_UnlockSurface( Texture );
+end;
+
+procedure SDL_ZoomSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect; DstSurface : PSDL_Surface; DstRect : PSDL_Rect );
+var
+  xc, yc       : cardinal;
+  rx, wx, ry, wy, ry16 : cardinal;
+  color        : cardinal;
+  modx, mody   : cardinal;
+begin
+  // Warning! No checks for surface pointers!!!
+  if srcrect = nil then
+    srcrect := @SrcSurface.clip_rect;
+  if dstrect = nil then
+    dstrect := @DstSurface.clip_rect;
+  if SDL_MustLock( SrcSurface ) then
+    SDL_LockSurface( SrcSurface );
+  if SDL_MustLock( DstSurface ) then
+    SDL_LockSurface( DstSurface );
+  modx := trunc( ( srcrect.w / dstrect.w ) * 65536 );
+  mody := trunc( ( srcrect.h / dstrect.h ) * 65536 );
+  //rx := srcrect.x * 65536;
+  ry := srcrect.y * 65536;
+  wy := dstrect.y;
+  for yc := 0 to dstrect.h - 1 do
+  begin
+    rx := srcrect.x * 65536;
+    wx := dstrect.x;
+    ry16 := ry shr 16;
+    for xc := 0 to dstrect.w - 1 do
+    begin
+      color := SDL_GetPixel( SrcSurface, rx shr 16, ry16 );
+      SDL_PutPixel( DstSurface, wx, wy, color );
+      rx := rx + modx;
+      inc( wx );
+    end;
+    ry := ry + mody;
+    inc( wy );
+  end;
+  if SDL_MustLock( SrcSurface ) then
+    SDL_UnlockSurface( SrcSurface );
+  if SDL_MustLock( DstSurface ) then
+    SDL_UnlockSurface( DstSurface );
+end;
+// Re-map a rectangular area into an area defined by four vertices
+// Converted from C to Pascal by KiCHY
+
+procedure SDL_WarpSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect; DstSurface : PSDL_Surface; UL, UR, LR, LL : PPoint );
+const
+  SHIFTS       = 15; // Extend ints to limit round-off error (try 2 - 20)
+  THRESH       = 1 shl SHIFTS; // Threshold for pixel size value
+  procedure CopySourceToDest( UL, UR, LR, LL : TPoint; x1, y1, x2, y2 : cardinal );
+  var
+    tm, lm, rm, bm, m : TPoint;
+    mx, my     : cardinal;
+    cr         : cardinal;
+  begin
+    // Does the destination area specify a single pixel?
+    if ( ( abs( ul.x - ur.x ) < THRESH ) and
+      ( abs( ul.x - lr.x ) < THRESH ) and
+      ( abs( ul.x - ll.x ) < THRESH ) and
+      ( abs( ul.y - ur.y ) < THRESH ) and
+      ( abs( ul.y - lr.y ) < THRESH ) and
+      ( abs( ul.y - ll.y ) < THRESH ) ) then
+    begin // Yes
+      cr := SDL_GetPixel( SrcSurface, ( x1 shr SHIFTS ), ( y1 shr SHIFTS ) );
+      SDL_PutPixel( DstSurface, ( ul.x shr SHIFTS ), ( ul.y shr SHIFTS ), cr );
+    end
+    else
+    begin // No
+      // Quarter the source and the destination, and then recurse
+      tm.x := ( ul.x + ur.x ) shr 1;
+      tm.y := ( ul.y + ur.y ) shr 1;
+      bm.x := ( ll.x + lr.x ) shr 1;
+      bm.y := ( ll.y + lr.y ) shr 1;
+      lm.x := ( ul.x + ll.x ) shr 1;
+      lm.y := ( ul.y + ll.y ) shr 1;
+      rm.x := ( ur.x + lr.x ) shr 1;
+      rm.y := ( ur.y + lr.y ) shr 1;
+      m.x := ( tm.x + bm.x ) shr 1;
+      m.y := ( tm.y + bm.y ) shr 1;
+      mx := ( x1 + x2 ) shr 1;
+      my := ( y1 + y2 ) shr 1;
+      CopySourceToDest( ul, tm, m, lm, x1, y1, mx, my );
+      CopySourceToDest( tm, ur, rm, m, mx, y1, x2, my );
+      CopySourceToDest( m, rm, lr, bm, mx, my, x2, y2 );
+      CopySourceToDest( lm, m, bm, ll, x1, my, mx, y2 );
+    end;
+  end;
+var
+  _UL, _UR, _LR, _LL : TPoint;
+  Rect_x, Rect_y, Rect_w, Rect_h : integer;
+begin
+  if SDL_MustLock( SrcSurface ) then
+    SDL_LockSurface( SrcSurface );
+  if SDL_MustLock( DstSurface ) then
+    SDL_LockSurface( DstSurface );
+  if SrcRect = nil then
+  begin
+    Rect_x := 0;
+    Rect_y := 0;
+    Rect_w := ( SrcSurface.w - 1 ) shl SHIFTS;
+    Rect_h := ( SrcSurface.h - 1 ) shl SHIFTS;
+  end
+  else
+  begin
+    Rect_x := SrcRect.x;
+    Rect_y := SrcRect.y;
+    Rect_w := ( SrcRect.w - 1 ) shl SHIFTS;
+    Rect_h := ( SrcRect.h - 1 ) shl SHIFTS;
+  end;
+  // Shift all values to help reduce round-off error.
+  _ul.x := ul.x shl SHIFTS;
+  _ul.y := ul.y shl SHIFTS;
+  _ur.x := ur.x shl SHIFTS;
+  _ur.y := ur.y shl SHIFTS;
+  _lr.x := lr.x shl SHIFTS;
+  _lr.y := lr.y shl SHIFTS;
+  _ll.x := ll.x shl SHIFTS;
+  _ll.y := ll.y shl SHIFTS;
+  CopySourceToDest( _ul, _ur, _lr, _ll, Rect_x, Rect_y, Rect_w, Rect_h );
+  if SDL_MustLock( SrcSurface ) then
+    SDL_UnlockSurface( SrcSurface );
+  if SDL_MustLock( DstSurface ) then
+    SDL_UnlockSurface( DstSurface );
+end;
+
+// Draw a line between x1,y1 and x2,y2 to the given surface
+// NOTE: The surface must be locked before calling this!
+
+procedure SDL_DrawLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+var
+  dx, dy, sdx, sdy, x, y, px, py : integer;
+begin
+  dx := x2 - x1;
+  dy := y2 - y1;
+  if dx < 0 then
+    sdx := -1
+  else
+    sdx := 1;
+  if dy < 0 then
+    sdy := -1
+  else
+    sdy := 1;
+  dx := sdx * dx + 1;
+  dy := sdy * dy + 1;
+  x := 0;
+  y := 0;
+  px := x1;
+  py := y1;
+  if dx >= dy then
+  begin
+    for x := 0 to dx - 1 do
+    begin
+      SDL_PutPixel( DstSurface, px, py, Color );
+      y := y + dy;
+      if y >= dx then
+      begin
+        y := y - dx;
+        py := py + sdy;
+      end;
+      px := px + sdx;
+    end;
+  end
+  else
+  begin
+    for y := 0 to dy - 1 do
+    begin
+      SDL_PutPixel( DstSurface, px, py, Color );
+      x := x + dx;
+      if x >= dy then
+      begin
+        x := x - dy;
+        px := px + sdx;
+      end;
+      py := py + sdy;
+    end;
+  end;
+end;
+
+// Draw a dashed line between x1,y1 and x2,y2 to the given surface
+// NOTE: The surface must be locked before calling this!
+
+procedure SDL_DrawLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal; DashLength, DashSpace : byte ); overload;
+var
+  dx, dy, sdx, sdy, x, y, px, py, counter : integer; drawdash : boolean;
+begin
+  counter := 0;
+  drawdash := true; //begin line drawing with dash
+
+  //Avoid invalid user-passed dash parameters
+  if ( DashLength < 1 )
+    then
+    DashLength := 1;
+  if ( DashSpace < 1 )
+    then
+    DashSpace := 0;
+
+  dx := x2 - x1;
+  dy := y2 - y1;
+  if dx < 0 then
+    sdx := -1
+  else
+    sdx := 1;
+  if dy < 0 then
+    sdy := -1
+  else
+    sdy := 1;
+  dx := sdx * dx + 1;
+  dy := sdy * dy + 1;
+  x := 0;
+  y := 0;
+  px := x1;
+  py := y1;
+  if dx >= dy then
+  begin
+    for x := 0 to dx - 1 do
+    begin
+
+      //Alternate drawing dashes, or leaving spaces
+      if drawdash then
+      begin
+        SDL_PutPixel( DstSurface, px, py, Color );
+        inc( counter );
+        if ( counter > DashLength - 1 ) and ( DashSpace > 0 ) then
+        begin
+          drawdash := false;
+          counter := 0;
+        end;
+      end
+      else //space
+      begin
+        inc( counter );
+        if counter > DashSpace - 1 then
+        begin
+          drawdash := true;
+          counter := 0;
+        end;
+      end;
+
+      y := y + dy;
+      if y >= dx then
+      begin
+        y := y - dx;
+        py := py + sdy;
+      end;
+      px := px + sdx;
+    end;
+  end
+  else
+  begin
+    for y := 0 to dy - 1 do
+    begin
+
+      //Alternate drawing dashes, or leaving spaces
+      if drawdash then
+      begin
+        SDL_PutPixel( DstSurface, px, py, Color );
+        inc( counter );
+        if ( counter > DashLength - 1 ) and ( DashSpace > 0 ) then
+        begin
+          drawdash := false;
+          counter := 0;
+        end;
+      end
+      else //space
+      begin
+        inc( counter );
+        if counter > DashSpace - 1 then
+        begin
+          drawdash := true;
+          counter := 0;
+        end;
+      end;
+
+      x := x + dx;
+      if x >= dy then
+      begin
+        x := x - dy;
+        px := px + sdx;
+      end;
+      py := py + sdy;
+    end;
+  end;
+end;
+
+procedure SDL_AddLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+var
+  dx, dy, sdx, sdy, x, y, px, py : integer;
+begin
+  dx := x2 - x1;
+  dy := y2 - y1;
+  if dx < 0 then
+    sdx := -1
+  else
+    sdx := 1;
+  if dy < 0 then
+    sdy := -1
+  else
+    sdy := 1;
+  dx := sdx * dx + 1;
+  dy := sdy * dy + 1;
+  x := 0;
+  y := 0;
+  px := x1;
+  py := y1;
+  if dx >= dy then
+  begin
+    for x := 0 to dx - 1 do
+    begin
+      SDL_AddPixel( DstSurface, px, py, Color );
+      y := y + dy;
+      if y >= dx then
+      begin
+        y := y - dx;
+        py := py + sdy;
+      end;
+      px := px + sdx;
+    end;
+  end
+  else
+  begin
+    for y := 0 to dy - 1 do
+    begin
+      SDL_AddPixel( DstSurface, px, py, Color );
+      x := x + dx;
+      if x >= dy then
+      begin
+        x := x - dy;
+        px := px + sdx;
+      end;
+      py := py + sdy;
+    end;
+  end;
+end;
+
+procedure SDL_SubLine( DstSurface : PSDL_Surface; x1, y1, x2, y2 : integer; Color :
+  cardinal );
+var
+  dx, dy, sdx, sdy, x, y, px, py : integer;
+begin
+  dx := x2 - x1;
+  dy := y2 - y1;
+  if dx < 0 then
+    sdx := -1
+  else
+    sdx := 1;
+  if dy < 0 then
+    sdy := -1
+  else
+    sdy := 1;
+  dx := sdx * dx + 1;
+  dy := sdy * dy + 1;
+  x := 0;
+  y := 0;
+  px := x1;
+  py := y1;
+  if dx >= dy then
+  begin
+    for x := 0 to dx - 1 do
+    begin
+      SDL_SubPixel( DstSurface, px, py, Color );
+      y := y + dy;
+      if y >= dx then
+      begin
+        y := y - dx;
+        py := py + sdy;
+      end;
+      px := px + sdx;
+    end;
+  end
+  else
+  begin
+    for y := 0 to dy - 1 do
+    begin
+      SDL_SubPixel( DstSurface, px, py, Color );
+      x := x + dx;
+      if x >= dy then
+      begin
+        x := x - dy;
+        px := px + sdx;
+      end;
+      py := py + sdy;
+    end;
+  end;
+end;
+
+// flips a rectangle vertically on given surface
+
+procedure SDL_FlipRectV( DstSurface : PSDL_Surface; Rect : PSDL_Rect );
+var
+  TmpRect      : TSDL_Rect;
+  Locked       : boolean;
+  y, FlipLength, RowLength : integer;
+  Row1, Row2   : Pointer;
+  OneRow       : TByteArray; // Optimize it if you wish
+begin
+  if DstSurface <> nil then
+  begin
+    if Rect = nil then
+    begin // if Rect=nil then we flip the whole surface
+      TmpRect := SDLRect( 0, 0, DstSurface.w, DstSurface.h );
+      Rect := @TmpRect;
+    end;
+    FlipLength := Rect^.h shr 1 - 1;
+    RowLength := Rect^.w * DstSurface^.format.BytesPerPixel;
+    if SDL_MustLock( DstSurface ) then
+    begin
+      Locked := true;
+      SDL_LockSurface( DstSurface );
+    end
+    else
+      Locked := false;
+    Row1 := pointer( PtrUInt( DstSurface^.Pixels ) + UInt32( Rect^.y ) *
+      DstSurface^.Pitch );
+    Row2 := pointer( PtrUInt( DstSurface^.Pixels ) + ( UInt32( Rect^.y ) + Rect^.h - 1 )
+      * DstSurface^.Pitch );
+    for y := 0 to FlipLength do
+    begin
+      Move( Row1^, OneRow, RowLength );
+      Move( Row2^, Row1^, RowLength );
+      Move( OneRow, Row2^, RowLength );
+      inc( PtrUInt( Row1 ), DstSurface^.Pitch );
+      dec( PtrUInt( Row2 ), DstSurface^.Pitch );
+    end;
+    if Locked then
+      SDL_UnlockSurface( DstSurface );
+  end;
+end;
+
+// flips a rectangle horizontally on given surface
+
+procedure SDL_FlipRectH( DstSurface : PSDL_Surface; Rect : PSDL_Rect );
+type
+  T24bit = packed array[ 0..2 ] of byte;
+  T24bitArray = packed array[ 0..8191 ] of T24bit;
+  P24bitArray = ^T24bitArray;
+  TLongWordArray = array[ 0..8191 ] of LongWord;
+  PLongWordArray = ^TLongWordArray;
+var
+  TmpRect      : TSDL_Rect;
+  Row8bit      : PByteArray;
+  Row16bit     : PWordArray;
+  Row24bit     : P24bitArray;
+  Row32bit     : PLongWordArray;
+  y, x, RightSide, FlipLength : integer;
+  Pixel        : cardinal;
+  Pixel24      : T24bit;
+  Locked       : boolean;
+begin
+  if DstSurface <> nil then
+  begin
+    if Rect = nil then
+    begin
+      TmpRect := SDLRect( 0, 0, DstSurface.w, DstSurface.h );
+      Rect := @TmpRect;
+    end;
+    FlipLength := Rect^.w shr 1 - 1;
+    if SDL_MustLock( DstSurface ) then
+    begin
+      Locked := true;
+      SDL_LockSurface( DstSurface );
+    end
+    else
+      Locked := false;
+    case DstSurface^.format.BytesPerPixel of
+      1 :
+        begin
+          Row8Bit := pointer( PtrUInt( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+            DstSurface^.pitch );
+          for y := 1 to Rect^.h do
+          begin
+            RightSide := Rect^.w - 1;
+            for x := 0 to FlipLength do
+            begin
+              Pixel := Row8Bit^[ x ];
+              Row8Bit^[ x ] := Row8Bit^[ RightSide ];
+              Row8Bit^[ RightSide ] := Pixel;
+              dec( RightSide );
+            end;
+            inc( PtrUInt( Row8Bit ), DstSurface^.pitch );
+          end;
+        end;
+      2 :
+        begin
+          Row16Bit := pointer( PtrUInt( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+            DstSurface^.pitch );
+          for y := 1 to Rect^.h do
+          begin
+            RightSide := Rect^.w - 1;
+            for x := 0 to FlipLength do
+            begin
+              Pixel := Row16Bit^[ x ];
+              Row16Bit^[ x ] := Row16Bit^[ RightSide ];
+              Row16Bit^[ RightSide ] := Pixel;
+              dec( RightSide );
+            end;
+            inc( PtrUInt( Row16Bit ), DstSurface^.pitch );
+          end;
+        end;
+      3 :
+        begin
+          Row24Bit := pointer( PtrUInt( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+            DstSurface^.pitch );
+          for y := 1 to Rect^.h do
+          begin
+            RightSide := Rect^.w - 1;
+            for x := 0 to FlipLength do
+            begin
+              Pixel24 := Row24Bit^[ x ];
+              Row24Bit^[ x ] := Row24Bit^[ RightSide ];
+              Row24Bit^[ RightSide ] := Pixel24;
+              dec( RightSide );
+            end;
+            inc( PtrUInt( Row24Bit ), DstSurface^.pitch );
+          end;
+        end;
+      4 :
+        begin
+          Row32Bit := pointer( PtrUInt( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+            DstSurface^.pitch );
+          for y := 1 to Rect^.h do
+          begin
+            RightSide := Rect^.w - 1;
+            for x := 0 to FlipLength do
+            begin
+              Pixel := Row32Bit^[ x ];
+              Row32Bit^[ x ] := Row32Bit^[ RightSide ];
+              Row32Bit^[ RightSide ] := Pixel;
+              dec( RightSide );
+            end;
+            inc( PtrUInt( Row32Bit ), DstSurface^.pitch );
+          end;
+        end;
+    end;
+    if Locked then
+      SDL_UnlockSurface( DstSurface );
+  end;
+end;
+
+// Use with caution! The procedure allocates memory for TSDL_Rect and return with its pointer.
+// But you MUST free it after you don't need it anymore!!!
+
+function PSDLRect( aLeft, aTop, aWidth, aHeight : integer ) : PSDL_Rect;
+var
+  Rect         : PSDL_Rect;
+begin
+  New( Rect );
+  with Rect^ do
+  begin
+    x := aLeft;
+    y := aTop;
+    w := aWidth;
+    h := aHeight;
+  end;
+  Result := Rect;
+end;
+
+function SDLRect( aLeft, aTop, aWidth, aHeight : integer ) : TSDL_Rect;
+begin
+  with result do
+  begin
+    x := aLeft;
+    y := aTop;
+    w := aWidth;
+    h := aHeight;
+  end;
+end;
+
+function SDLRect( aRect : TRect ) : TSDL_Rect;
+begin
+  with aRect do
+    result := SDLRect( Left, Top, Right - Left, Bottom - Top );
+end;
+
+procedure SDL_Stretch8( Surface, Dst_Surface : PSDL_Surface; x1, x2, y1, y2, yr, yw,
+  depth : integer );
+var
+  dx, dy, e, d, dx2 : integer;
+  src_pitch, dst_pitch : uint16;
+  src_pixels, dst_pixels : PUint8;
+begin
+  if ( yw >= dst_surface^.h ) then
+    exit;
+  dx := ( x2 - x1 );
+  dy := ( y2 - y1 );
+  dy := dy shl 1;
+  e := dy - dx;
+  dx2 := dx shl 1;
+  src_pitch := Surface^.pitch;
+  dst_pitch := dst_surface^.pitch;
+  src_pixels := PUint8( PtrUInt( Surface^.pixels ) + yr * src_pitch + y1 * depth );
+  dst_pixels := PUint8( PtrUInt( dst_surface^.pixels ) + yw * dst_pitch + x1 *
+    depth );
+  for d := 0 to dx - 1 do
+  begin
+    move( src_pixels^, dst_pixels^, depth );
+    while ( e >= 0 ) do
+    begin
+      inc( src_pixels, depth );
+      e := e - dx2;
+    end;
+    inc( dst_pixels, depth );
+    e := e + dy;
+  end;
+end;
+
+function sign( x : integer ) : integer;
+begin
+  if x > 0 then
+    result := 1
+  else
+    result := -1;
+end;
+
+// Stretches a part of a surface
+
+function SDL_ScaleSurfaceRect( SrcSurface : PSDL_Surface; SrcX1, SrcY1, SrcW, SrcH,
+  Width, Height : integer ) : PSDL_Surface;
+var
+  dst_surface  : PSDL_Surface;
+  dx, dy, e, d, dx2, srcx2, srcy2 : integer;
+  destx1, desty1 : integer;
+begin
+  srcx2 := srcx1 + SrcW;
+  srcy2 := srcy1 + SrcH;
+  result := nil;
+  destx1 := 0;
+  desty1 := 0;
+  dx := abs( integer( Height - desty1 ) );
+  dy := abs( integer( SrcY2 - SrcY1 ) );
+  e := ( dy shl 1 ) - dx;
+  dx2 := dx shl 1;
+  dy := dy shl 1;
+  dst_surface := SDL_CreateRGBSurface( SDL_HWPALETTE, width - destx1, Height -
+    desty1,
+    SrcSurface^.Format^.BitsPerPixel,
+    SrcSurface^.Format^.RMask,
+    SrcSurface^.Format^.GMask,
+    SrcSurface^.Format^.BMask,
+    SrcSurface^.Format^.AMask );
+  if ( dst_surface^.format^.BytesPerPixel = 1 ) then
+    SDL_SetColors( dst_surface, @SrcSurface^.format^.palette^.colors^[ 0 ], 0, 256 );
+  SDL_SetColorKey( dst_surface, sdl_srccolorkey, SrcSurface^.format^.colorkey );
+  if ( SDL_MustLock( dst_surface ) ) then
+    if ( SDL_LockSurface( dst_surface ) < 0 ) then
+      exit;
+  for d := 0 to dx - 1 do
+  begin
+    SDL_Stretch8( SrcSurface, dst_surface, destx1, Width, SrcX1, SrcX2, SrcY1, desty1,
+      SrcSurface^.format^.BytesPerPixel );
+    while e >= 0 do
+    begin
+      inc( SrcY1 );
+      e := e - dx2;
+    end;
+    inc( desty1 );
+    e := e + dy;
+  end;
+  if SDL_MUSTLOCK( dst_surface ) then
+    SDL_UnlockSurface( dst_surface );
+  result := dst_surface;
+end;
+
+procedure SDL_MoveLine( Surface : PSDL_Surface; x1, x2, y1, xofs, depth : integer );
+var
+  src_pixels, dst_pixels : PUint8;
+  i            : integer;
+begin
+  src_pixels := PUint8( PtrUInt( Surface^.pixels ) + Surface^.w * y1 * depth + x2 *
+    depth );
+  dst_pixels := PUint8( PtrUInt( Surface^.pixels ) + Surface^.w * y1 * depth + ( x2
+    + xofs ) * depth );
+  for i := x2 downto x1 do
+  begin
+    move( src_pixels^, dst_pixels^, depth );
+    dec( src_pixels );
+    dec( dst_pixels );
+  end;
+end;
+{ Return the pixel value at (x, y)
+NOTE: The surface must be locked before calling this! }
+
+function SDL_GetPixel( SrcSurface : PSDL_Surface; x : integer; y : integer ) : Uint32;
+var
+  bpp          : UInt32;
+  p            : PInteger;
+begin
+  bpp := SrcSurface.format.BytesPerPixel;
+  // Here p is the address to the pixel we want to retrieve
+  p := Pointer( PtrUInt( SrcSurface.pixels ) + UInt32( y ) * SrcSurface.pitch + UInt32( x ) *
+    bpp );
+  case bpp of
+    1 : result := PUint8( p )^;
+    2 : result := PUint16( p )^;
+    3 :
+      if ( SDL_BYTEORDER = SDL_BIG_ENDIAN ) then
+        result := PUInt8Array( p )[ 0 ] shl 16 or PUInt8Array( p )[ 1 ] shl 8 or
+          PUInt8Array( p )[ 2 ]
+      else
+        result := PUInt8Array( p )[ 0 ] or PUInt8Array( p )[ 1 ] shl 8 or
+          PUInt8Array( p )[ 2 ] shl 16;
+    4 : result := PUint32( p )^;
+  else
+    result := 0; // shouldn't happen, but avoids warnings
+  end;
+end;
+{ Set the pixel at (x, y) to the given value
+  NOTE: The surface must be locked before calling this! }
+
+procedure SDL_PutPixel( DstSurface : PSDL_Surface; x : integer; y : integer; pixel :
+  Uint32 );
+var
+  bpp          : UInt32;
+  p            : PInteger;
+begin
+  bpp := DstSurface.format.BytesPerPixel;
+  p := Pointer( PtrUInt( DstSurface.pixels ) + UInt32( y ) * DstSurface.pitch + UInt32( x )
+    * bpp );
+  case bpp of
+    1 : PUint8( p )^ := pixel;
+    2 : PUint16( p )^ := pixel;
+    3 :
+      if ( SDL_BYTEORDER = SDL_BIG_ENDIAN ) then
+      begin
+        PUInt8Array( p )[ 0 ] := ( pixel shr 16 ) and $FF;
+        PUInt8Array( p )[ 1 ] := ( pixel shr 8 ) and $FF;
+        PUInt8Array( p )[ 2 ] := pixel and $FF;
+      end
+      else
+      begin
+        PUInt8Array( p )[ 0 ] := pixel and $FF;
+        PUInt8Array( p )[ 1 ] := ( pixel shr 8 ) and $FF;
+        PUInt8Array( p )[ 2 ] := ( pixel shr 16 ) and $FF;
+      end;
+    4 :
+      PUint32( p )^ := pixel;
+  end;
+end;
+
+procedure SDL_ScrollY( DstSurface : PSDL_Surface; DifY : integer );
+var
+  r1, r2       : TSDL_Rect;
+  //buffer: PSDL_Surface;
+  YPos         : Integer;
+begin
+  if ( DstSurface <> nil ) and ( DifY <> 0 ) then
+  begin
+    //if DifY > 0 then // going up
+    //begin
+    ypos := 0;
+    r1.x := 0;
+    r2.x := 0;
+    r1.w := DstSurface.w;
+    r2.w := DstSurface.w;
+    r1.h := DifY;
+    r2.h := DifY;
+    while ypos < DstSurface.h do
+    begin
+      r1.y := ypos;
+      r2.y := ypos + DifY;
+      SDL_BlitSurface( DstSurface, @r2, DstSurface, @r1 );
+      ypos := ypos + DifY;
+    end;
+    //end
+    //else
+    //begin // Going Down
+    //end;
+  end;
+end;
+
+{procedure SDL_ScrollY(Surface: PSDL_Surface; DifY: integer);
+var
+  r1, r2: TSDL_Rect;
+  buffer: PSDL_Surface;
+begin
+  if (Surface <> nil) and (Dify <> 0) then
+  begin
+    buffer := SDL_CreateRGBSurface(SDL_HWSURFACE, (Surface^.w - DifY) * 2,
+      Surface^.h * 2,
+      Surface^.Format^.BitsPerPixel, 0, 0, 0, 0);
+    if buffer <> nil then
+    begin
+      if (buffer^.format^.BytesPerPixel = 1) then
+        SDL_SetColors(buffer, @Surface^.format^.palette^.colors^[0], 0, 256);
+      r1 := SDLRect(0, DifY, buffer^.w, buffer^.h);
+      r2 := SDLRect(0, 0, buffer^.w, buffer^.h);
+      SDL_BlitSurface(Surface, @r1, buffer, @r2);
+      SDL_BlitSurface(buffer, @r2, Surface, @r2);
+      SDL_FreeSurface(buffer);
+    end;
+  end;
+end;}
+
+procedure SDL_ScrollX( DstSurface : PSDL_Surface; DifX : integer );
+var
+  r1, r2       : TSDL_Rect;
+  buffer       : PSDL_Surface;
+begin
+  if ( DstSurface <> nil ) and ( DifX <> 0 ) then
+  begin
+    buffer := SDL_CreateRGBSurface( SDL_HWSURFACE, ( DstSurface^.w - DifX ) * 2,
+      DstSurface^.h * 2,
+      DstSurface^.Format^.BitsPerPixel,
+      DstSurface^.Format^.RMask,
+      DstSurface^.Format^.GMask,
+      DstSurface^.Format^.BMask,
+      DstSurface^.Format^.AMask );
+    if buffer <> nil then
+    begin
+      if ( buffer^.format^.BytesPerPixel = 1 ) then
+        SDL_SetColors( buffer, @DstSurface^.format^.palette^.colors^[ 0 ], 0, 256 );
+      r1 := SDLRect( DifX, 0, buffer^.w, buffer^.h );
+      r2 := SDLRect( 0, 0, buffer^.w, buffer^.h );
+      SDL_BlitSurface( DstSurface, @r1, buffer, @r2 );
+      SDL_BlitSurface( buffer, @r2, DstSurface, @r2 );
+      SDL_FreeSurface( buffer );
+    end;
+  end;
+end;
+
+procedure SDL_RotateRad( DstSurface, SrcSurface : PSDL_Surface; SrcRect :
+  PSDL_Rect; DestX, DestY, OffsetX, OffsetY : Integer; Angle : Single );
+var
+  aSin, aCos   : Single;
+  MX, MY, DX, DY, NX, NY, SX, SY, OX, OY, Width, Height, TX, TY, RX, RY, ROX, ROY : Integer;
+  Colour, TempTransparentColour : UInt32;
+  MAXX, MAXY   : Integer;
+begin
+  // Rotate the surface to the target surface.
+  TempTransparentColour := SrcSurface.format.colorkey;
+  {if srcRect.w > srcRect.h then
+  begin
+    Width := srcRect.w;
+    Height := srcRect.w;
+  end
+  else
+  begin
+    Width := srcRect.h;
+    Height := srcRect.h;
+  end; }
+
+  maxx := DstSurface.w;
+  maxy := DstSurface.h;
+  aCos := cos( Angle );
+  aSin := sin( Angle );
+
+  Width := round( abs( srcrect.h * acos ) + abs( srcrect.w * asin ) );
+  Height := round( abs( srcrect.h * asin ) + abs( srcrect.w * acos ) );
+
+  OX := Width div 2;
+  OY := Height div 2; ;
+  MX := ( srcRect.x + ( srcRect.x + srcRect.w ) ) div 2;
+  MY := ( srcRect.y + ( srcRect.y + srcRect.h ) ) div 2;
+  ROX := ( -( srcRect.w div 2 ) ) + Offsetx;
+  ROY := ( -( srcRect.h div 2 ) ) + OffsetY;
+  Tx := ox + round( ROX * aSin - ROY * aCos );
+  Ty := oy + round( ROY * aSin + ROX * aCos );
+  SX := 0;
+  for DX := DestX - TX to DestX - TX + ( width ) do
+  begin
+    Inc( SX );
+    SY := 0;
+    for DY := DestY - TY to DestY - TY + ( Height ) do
+    begin
+      RX := SX - OX;
+      RY := SY - OY;
+      NX := round( mx + RX * aSin + RY * aCos ); //
+      NY := round( my + RY * aSin - RX * aCos ); //
+      // Used for testing only
+     //SDL_PutPixel(DestSurface.SDLSurfacePointer,DX,DY,0);
+      if ( ( DX > 0 ) and ( DX < MAXX ) ) and ( ( DY > 0 ) and ( DY < MAXY ) ) then
+      begin
+        if ( NX >= srcRect.x ) and ( NX <= srcRect.x + srcRect.w ) then
+        begin
+          if ( NY >= srcRect.y ) and ( NY <= srcRect.y + srcRect.h ) then
+          begin
+            Colour := SDL_GetPixel( SrcSurface, NX, NY );
+            if Colour <> TempTransparentColour then
+            begin
+              SDL_PutPixel( DstSurface, DX, DY, Colour );
+            end;
+          end;
+        end;
+      end;
+      inc( SY );
+    end;
+  end;
+end;
+
+procedure SDL_RotateDeg( DstSurface, SrcSurface : PSDL_Surface; SrcRect :
+  PSDL_Rect; DestX, DestY, OffsetX, OffsetY : Integer; Angle : Integer );
+begin
+  SDL_RotateRad( DstSurface, SrcSurface, SrcRect, DestX, DestY, OffsetX, OffsetY, DegToRad( Angle ) );
+end;
+
+function ValidateSurfaceRect( DstSurface : PSDL_Surface; dstrect : PSDL_Rect ) : TSDL_Rect;
+var
+  RealRect     : TSDL_Rect;
+  OutOfRange   : Boolean;
+begin
+  OutOfRange := false;
+  if dstrect = nil then
+  begin
+    RealRect.x := 0;
+    RealRect.y := 0;
+    RealRect.w := DstSurface.w;
+    RealRect.h := DstSurface.h;
+  end
+  else
+  begin
+    if dstrect.x < DstSurface.w then
+    begin
+      RealRect.x := dstrect.x;
+    end
+    else if dstrect.x < 0 then
+    begin
+      realrect.x := 0;
+    end
+    else
+    begin
+      OutOfRange := True;
+    end;
+    if dstrect.y < DstSurface.h then
+    begin
+      RealRect.y := dstrect.y;
+    end
+    else if dstrect.y < 0 then
+    begin
+      realrect.y := 0;
+    end
+    else
+    begin
+      OutOfRange := True;
+    end;
+    if OutOfRange = False then
+    begin
+      if realrect.x + dstrect.w <= DstSurface.w then
+      begin
+        RealRect.w := dstrect.w;
+      end
+      else
+      begin
+        RealRect.w := dstrect.w - realrect.x;
+      end;
+      if realrect.y + dstrect.h <= DstSurface.h then
+      begin
+        RealRect.h := dstrect.h;
+      end
+      else
+      begin
+        RealRect.h := dstrect.h - realrect.y;
+      end;
+    end;
+  end;
+  if OutOfRange = False then
+  begin
+    result := realrect;
+  end
+  else
+  begin
+    realrect.w := 0;
+    realrect.h := 0;
+    realrect.x := 0;
+    realrect.y := 0;
+    result := realrect;
+  end;
+end;
+
+procedure SDL_FillRectAdd( DstSurface : PSDL_Surface; dstrect : PSDL_Rect; color : UInt32 );
+var
+  RealRect     : TSDL_Rect;
+  Addr         : pointer;
+  ModX, BPP    : cardinal;
+  x, y, R, G, B, SrcColor : cardinal;
+begin
+  RealRect := ValidateSurfaceRect( DstSurface, DstRect );
+  if ( RealRect.w > 0 ) and ( RealRect.h > 0 ) then
+  begin
+    SDL_LockSurface( DstSurface );
+    BPP := DstSurface.format.BytesPerPixel;
+    with DstSurface^ do
+    begin
+      Addr := pointer( PtrUInt( pixels ) + UInt32( RealRect.y ) * pitch + UInt32( RealRect.x ) * BPP );
+      ModX := Pitch - UInt32( RealRect.w ) * BPP;
+    end;
+    case DstSurface.format.BitsPerPixel of
+      8 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $E0 + Color and $E0;
+              G := SrcColor and $1C + Color and $1C;
+              B := SrcColor and $03 + Color and $03;
+              if R > $E0 then
+                R := $E0;
+              if G > $1C then
+                G := $1C;
+              if B > $03 then
+                B := $03;
+              PUInt8( Addr )^ := R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+      15 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $7C00 + Color and $7C00;
+              G := SrcColor and $03E0 + Color and $03E0;
+              B := SrcColor and $001F + Color and $001F;
+              if R > $7C00 then
+                R := $7C00;
+              if G > $03E0 then
+                G := $03E0;
+              if B > $001F then
+                B := $001F;
+              PUInt16( Addr )^ := R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+      16 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $F800 + Color and $F800;
+              G := SrcColor and $07C0 + Color and $07C0;
+              B := SrcColor and $001F + Color and $001F;
+              if R > $F800 then
+                R := $F800;
+              if G > $07C0 then
+                G := $07C0;
+              if B > $001F then
+                B := $001F;
+              PUInt16( Addr )^ := R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+      24 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $00FF0000 + Color and $00FF0000;
+              G := SrcColor and $0000FF00 + Color and $0000FF00;
+              B := SrcColor and $000000FF + Color and $000000FF;
+              if R > $FF0000 then
+                R := $FF0000;
+              if G > $00FF00 then
+                G := $00FF00;
+              if B > $0000FF then
+                B := $0000FF;
+              PUInt32( Addr )^ := SrcColor and $FF000000 or R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+      32 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $00FF0000 + Color and $00FF0000;
+              G := SrcColor and $0000FF00 + Color and $0000FF00;
+              B := SrcColor and $000000FF + Color and $000000FF;
+              if R > $FF0000 then
+                R := $FF0000;
+              if G > $00FF00 then
+                G := $00FF00;
+              if B > $0000FF then
+                B := $0000FF;
+              PUInt32( Addr )^ := R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+    end;
+    SDL_UnlockSurface( DstSurface );
+  end;
+end;
+
+procedure SDL_FillRectSub( DstSurface : PSDL_Surface; dstrect : PSDL_Rect; color : UInt32 );
+var
+  RealRect     : TSDL_Rect;
+  Addr         : pointer;
+  ModX, BPP    : cardinal;
+  x, y, R, G, B, SrcColor : cardinal;
+begin
+  RealRect := ValidateSurfaceRect( DstSurface, DstRect );
+  if ( RealRect.w > 0 ) and ( RealRect.h > 0 ) then
+  begin
+    SDL_LockSurface( DstSurface );
+    BPP := DstSurface.format.BytesPerPixel;
+    with DstSurface^ do
+    begin
+      Addr := pointer( PtrUInt( pixels ) + UInt32( RealRect.y ) * pitch + UInt32( RealRect.x ) * BPP );
+      ModX := Pitch - UInt32( RealRect.w ) * BPP;
+    end;
+    case DstSurface.format.BitsPerPixel of
+      8 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $E0 - Color and $E0;
+              G := SrcColor and $1C - Color and $1C;
+              B := SrcColor and $03 - Color and $03;
+              if R > $E0 then
+                R := 0;
+              if G > $1C then
+                G := 0;
+              if B > $03 then
+                B := 0;
+              PUInt8( Addr )^ := R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+      15 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $7C00 - Color and $7C00;
+              G := SrcColor and $03E0 - Color and $03E0;
+              B := SrcColor and $001F - Color and $001F;
+              if R > $7C00 then
+                R := 0;
+              if G > $03E0 then
+                G := 0;
+              if B > $001F then
+                B := 0;
+              PUInt16( Addr )^ := R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+      16 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $F800 - Color and $F800;
+              G := SrcColor and $07C0 - Color and $07C0;
+              B := SrcColor and $001F - Color and $001F;
+              if R > $F800 then
+                R := 0;
+              if G > $07C0 then
+                G := 0;
+              if B > $001F then
+                B := 0;
+              PUInt16( Addr )^ := R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+      24 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $00FF0000 - Color and $00FF0000;
+              G := SrcColor and $0000FF00 - Color and $0000FF00;
+              B := SrcColor and $000000FF - Color and $000000FF;
+              if R > $FF0000 then
+                R := 0;
+              if G > $00FF00 then
+                G := 0;
+              if B > $0000FF then
+                B := 0;
+              PUInt32( Addr )^ := SrcColor and $FF000000 or R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+      32 :
+        begin
+          for y := 0 to RealRect.h - 1 do
+          begin
+            for x := 0 to RealRect.w - 1 do
+            begin
+              SrcColor := PUInt32( Addr )^;
+              R := SrcColor and $00FF0000 - Color and $00FF0000;
+              G := SrcColor and $0000FF00 - Color and $0000FF00;
+              B := SrcColor and $000000FF - Color and $000000FF;
+              if R > $FF0000 then
+                R := 0;
+              if G > $00FF00 then
+                G := 0;
+              if B > $0000FF then
+                B := 0;
+              PUInt32( Addr )^ := R or G or B;
+              inc( PtrUInt( Addr ), BPP );
+            end;
+            inc( PtrUInt( Addr ), ModX );
+          end;
+        end;
+    end;
+    SDL_UnlockSurface( DstSurface );
+  end;
+end;
+
+procedure SDL_GradientFillRect( DstSurface : PSDL_Surface; const Rect : PSDL_Rect; const StartColor, EndColor : TSDL_Color; const Style : TGradientStyle );
+var
+  FBC          : array[ 0..255 ] of Cardinal;
+  // temp vars
+  i, YR, YG, YB, SR, SG, SB, DR, DG, DB : Integer;
+
+  TempStepV, TempStepH : Single;
+  TempLeft, TempTop, TempHeight, TempWidth : integer;
+  TempRect     : TSDL_Rect;
+
+begin
+  // calc FBC
+  YR := StartColor.r;
+  YG := StartColor.g;
+  YB := StartColor.b;
+  SR := YR;
+  SG := YG;
+  SB := YB;
+  DR := EndColor.r - SR;
+  DG := EndColor.g - SG;
+  DB := EndColor.b - SB;
+
+  for i := 0 to 255 do
+  begin
+    FBC[ i ] := SDL_MapRGB( DstSurface.format, YR, YG, YB );
+    YR := SR + round( DR / 255 * i );
+    YG := SG + round( DG / 255 * i );
+    YB := SB + round( DB / 255 * i );
+  end;
+
+  //  if aStyle = 1 then begin
+  TempStepH := Rect.w / 255;
+  TempStepV := Rect.h / 255;
+  TempHeight := Trunc( TempStepV + 1 );
+  TempWidth := Trunc( TempStepH + 1 );
+  TempTop := 0;
+  TempLeft := 0;
+  TempRect.x := Rect.x;
+  TempRect.y := Rect.y;
+  TempRect.h := Rect.h;
+  TempRect.w := Rect.w;
+
+  case Style of
+    gsHorizontal :
+      begin
+        TempRect.h := TempHeight;
+        for i := 0 to 255 do
+        begin
+          TempRect.y := Rect.y + TempTop;
+          SDL_FillRect( DstSurface, @TempRect, FBC[ i ] );
+          TempTop := Trunc( TempStepV * i );
+        end;
+      end;
+    gsVertical :
+      begin
+        TempRect.w := TempWidth;
+        for i := 0 to 255 do
+        begin
+          TempRect.x := Rect.x + TempLeft;
+          SDL_FillRect( DstSurface, @TempRect, FBC[ i ] );
+          TempLeft := Trunc( TempStepH * i );
+        end;
+      end;
+  end;
+end;
+
+procedure SDL_2xBlit( Src, Dest : PSDL_Surface );
+var
+  ReadAddr, WriteAddr, ReadRow, WriteRow : PtrUInt;
+  SrcPitch, DestPitch, x, y : UInt32;
+begin
+  if ( Src = nil ) or ( Dest = nil ) then
+    exit;
+  if ( Src.w shl 1 ) < Dest.w then
+    exit;
+  if ( Src.h shl 1 ) < Dest.h then
+    exit;
+
+  if SDL_MustLock( Src ) then
+    SDL_LockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_LockSurface( Dest );
+
+  ReadRow := PtrUInt( Src.Pixels );
+  WriteRow := PtrUInt( Dest.Pixels );
+
+  SrcPitch := Src.pitch;
+  DestPitch := Dest.pitch;
+
+  case Src.format.BytesPerPixel of
+    1 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          PUInt8( WriteAddr )^ := PUInt8( ReadAddr )^;
+          PUInt8( WriteAddr + 1 )^ := PUInt8( ReadAddr )^;
+          PUInt8( WriteAddr + DestPitch )^ := PUInt8( ReadAddr )^;
+          PUInt8( WriteAddr + DestPitch + 1 )^ := PUInt8( ReadAddr )^;
+          inc( ReadAddr );
+          inc( WriteAddr, 2 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    2 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          PUInt16( WriteAddr )^ := PUInt16( ReadAddr )^;
+          PUInt16( WriteAddr + 2 )^ := PUInt16( ReadAddr )^;
+          PUInt16( WriteAddr + DestPitch )^ := PUInt16( ReadAddr )^;
+          PUInt16( WriteAddr + DestPitch + 2 )^ := PUInt16( ReadAddr )^;
+          inc( ReadAddr, 2 );
+          inc( WriteAddr, 4 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    3 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          PUInt32( WriteAddr )^ := ( PUInt32( WriteAddr )^ and $FF000000 ) or ( PUInt32( ReadAddr )^ and $00FFFFFF );
+          PUInt32( WriteAddr + 3 )^ := ( PUInt32( WriteAddr + 3 )^ and $FF000000 ) or ( PUInt32( ReadAddr )^ and $00FFFFFF );
+          PUInt32( WriteAddr + DestPitch )^ := ( PUInt32( WriteAddr + DestPitch )^ and $FF000000 ) or ( PUInt32( ReadAddr )^ and $00FFFFFF );
+          PUInt32( WriteAddr + DestPitch + 3 )^ := ( PUInt32( WriteAddr + DestPitch + 3 )^ and $FF000000 ) or ( PUInt32( ReadAddr )^ and $00FFFFFF );
+          inc( ReadAddr, 3 );
+          inc( WriteAddr, 6 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    4 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          PUInt32( WriteAddr )^ := PUInt32( ReadAddr )^;
+          PUInt32( WriteAddr + 4 )^ := PUInt32( ReadAddr )^;
+          PUInt32( WriteAddr + DestPitch )^ := PUInt32( ReadAddr )^;
+          PUInt32( WriteAddr + DestPitch + 4 )^ := PUInt32( ReadAddr )^;
+          inc( ReadAddr, 4 );
+          inc( WriteAddr, 8 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+  end;
+
+  if SDL_MustLock( Src ) then
+    SDL_UnlockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_UnlockSurface( Dest );
+end;
+
+procedure SDL_Scanline2xBlit( Src, Dest : PSDL_Surface );
+var
+  ReadAddr, WriteAddr, ReadRow, WriteRow : PtrUInt;
+  SrcPitch, DestPitch, x, y : UInt32;
+begin
+  if ( Src = nil ) or ( Dest = nil ) then
+    exit;
+  if ( Src.w shl 1 ) < Dest.w then
+    exit;
+  if ( Src.h shl 1 ) < Dest.h then
+    exit;
+
+  if SDL_MustLock( Src ) then
+    SDL_LockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_LockSurface( Dest );
+
+  ReadRow := PtrUInt( Src.Pixels );
+  WriteRow := PtrUInt( Dest.Pixels );
+
+  SrcPitch := Src.pitch;
+  DestPitch := Dest.pitch;
+
+  case Src.format.BytesPerPixel of
+    1 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          PUInt8( WriteAddr )^ := PUInt8( ReadAddr )^;
+          PUInt8( WriteAddr + 1 )^ := PUInt8( ReadAddr )^;
+          inc( ReadAddr );
+          inc( WriteAddr, 2 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    2 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          PUInt16( WriteAddr )^ := PUInt16( ReadAddr )^;
+          PUInt16( WriteAddr + 2 )^ := PUInt16( ReadAddr )^;
+          inc( ReadAddr, 2 );
+          inc( WriteAddr, 4 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    3 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          PUInt32( WriteAddr )^ := ( PUInt32( WriteAddr )^ and $FF000000 ) or ( PUInt32( ReadAddr )^ and $00FFFFFF );
+          PUInt32( WriteAddr + 3 )^ := ( PUInt32( WriteAddr + 3 )^ and $FF000000 ) or ( PUInt32( ReadAddr )^ and $00FFFFFF );
+          inc( ReadAddr, 3 );
+          inc( WriteAddr, 6 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    4 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          PUInt32( WriteAddr )^ := PUInt32( ReadAddr )^;
+          PUInt32( WriteAddr + 4 )^ := PUInt32( ReadAddr )^;
+          inc( ReadAddr, 4 );
+          inc( WriteAddr, 8 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+  end;
+
+  if SDL_MustLock( Src ) then
+    SDL_UnlockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_UnlockSurface( Dest );
+end;
+
+procedure SDL_50Scanline2xBlit( Src, Dest : PSDL_Surface );
+var
+  ReadAddr, WriteAddr, ReadRow, WriteRow : PtrUInt;
+  SrcPitch, DestPitch, x, y, Color : UInt32;
+begin
+  if ( Src = nil ) or ( Dest = nil ) then
+    exit;
+  if ( Src.w shl 1 ) < Dest.w then
+    exit;
+  if ( Src.h shl 1 ) < Dest.h then
+    exit;
+
+  if SDL_MustLock( Src ) then
+    SDL_LockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_LockSurface( Dest );
+
+  ReadRow := PtrUInt( Src.Pixels );
+  WriteRow := PtrUInt( Dest.Pixels );
+
+  SrcPitch := Src.pitch;
+  DestPitch := Dest.pitch;
+
+  case Src.format.BitsPerPixel of
+    8 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          Color := PUInt8( ReadAddr )^;
+          PUInt8( WriteAddr )^ := Color;
+          PUInt8( WriteAddr + 1 )^ := Color;
+          Color := ( Color shr 1 ) and $6D; {%01101101}
+          PUInt8( WriteAddr + DestPitch )^ := Color;
+          PUInt8( WriteAddr + DestPitch + 1 )^ := Color;
+          inc( ReadAddr );
+          inc( WriteAddr, 2 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    15 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          Color := PUInt16( ReadAddr )^;
+          PUInt16( WriteAddr )^ := Color;
+          PUInt16( WriteAddr + 2 )^ := Color;
+          Color := ( Color shr 1 ) and $3DEF; {%0011110111101111}
+          PUInt16( WriteAddr + DestPitch )^ := Color;
+          PUInt16( WriteAddr + DestPitch + 2 )^ := Color;
+          inc( ReadAddr, 2 );
+          inc( WriteAddr, 4 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    16 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          Color := PUInt16( ReadAddr )^;
+          PUInt16( WriteAddr )^ := Color;
+          PUInt16( WriteAddr + 2 )^ := Color;
+          Color := ( Color shr 1 ) and $7BEF; {%0111101111101111}
+          PUInt16( WriteAddr + DestPitch )^ := Color;
+          PUInt16( WriteAddr + DestPitch + 2 )^ := Color;
+          inc( ReadAddr, 2 );
+          inc( WriteAddr, 4 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    24 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          Color := ( PUInt32( WriteAddr )^ and $FF000000 ) or ( PUInt32( ReadAddr )^ and $00FFFFFF );
+          PUInt32( WriteAddr )^ := Color;
+          PUInt32( WriteAddr + 3 )^ := Color;
+          Color := ( Color shr 1 ) and $007F7F7F; {%011111110111111101111111}
+          PUInt32( WriteAddr + DestPitch )^ := Color;
+          PUInt32( WriteAddr + DestPitch + 3 )^ := Color;
+          inc( ReadAddr, 3 );
+          inc( WriteAddr, 6 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+    32 : for y := 1 to Src.h do
+      begin
+        ReadAddr := ReadRow;
+        WriteAddr := WriteRow;
+        for x := 1 to Src.w do
+        begin
+          Color := PUInt32( ReadAddr )^;
+          PUInt32( WriteAddr )^ := Color;
+          PUInt32( WriteAddr + 4 )^ := Color;
+          Color := ( Color shr 1 ) and $7F7F7F7F;
+          PUInt32( WriteAddr + DestPitch )^ := Color;
+          PUInt32( WriteAddr + DestPitch + 4 )^ := Color;
+          inc( ReadAddr, 4 );
+          inc( WriteAddr, 8 );
+        end;
+        inc( PtrUInt( ReadRow ), SrcPitch );
+        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+      end;
+  end;
+
+  if SDL_MustLock( Src ) then
+    SDL_UnlockSurface( Src );
+  if SDL_MustLock( Dest ) then
+    SDL_UnlockSurface( Dest );
+end;
+
+function SDL_PixelTestSurfaceVsRect( SrcSurface1 : PSDL_Surface; SrcRect1 :
+  PSDL_Rect; SrcRect2 : PSDL_Rect; Left1, Top1, Left2, Top2 : integer ) :
+  boolean;
+var
+  Src_Rect1, Src_Rect2 : TSDL_Rect;
+  right1, bottom1 : integer;
+  right2, bottom2 : integer;
+  Scan1Start, {Scan2Start,} ScanWidth, ScanHeight : cardinal;
+  Mod1         : cardinal;
+  Addr1        : PtrUInt;
+  BPP          : cardinal;
+  Pitch1       : cardinal;
+  TransparentColor1 : cardinal;
+  tx, ty       : cardinal;
+// StartTick    : cardinal; // Auto Removed, Unused Variable
+  Color1       : cardinal;
+begin
+  Result := false;
+  if SrcRect1 = nil then
+  begin
+    with Src_Rect1 do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface1.w;
+      h := SrcSurface1.h;
+    end;
+  end
+  else
+    Src_Rect1 := SrcRect1^;
+
+  Src_Rect2 := SrcRect2^;
+  with Src_Rect1 do
+  begin
+    Right1 := Left1 + w;
+    Bottom1 := Top1 + h;
+  end;
+  with Src_Rect2 do
+  begin
+    Right2 := Left2 + w;
+    Bottom2 := Top2 + h;
+  end;
+  if ( Left1 >= Right2 ) or ( Right1 <= Left2 ) or ( Top1 >= Bottom2 ) or ( Bottom1 <= Top2 ) then
+    exit;
+  if Left1 <= Left2 then
+  begin
+    // 1. left, 2. right
+    Scan1Start := Src_Rect1.x + Left2 - Left1;
+    //Scan2Start := Src_Rect2.x;
+    ScanWidth := Right1 - Left2;
+    with Src_Rect2 do
+      if ScanWidth > w then
+        ScanWidth := w;
+  end
+  else
+  begin
+    // 1. right, 2. left
+    Scan1Start := Src_Rect1.x;
+    //Scan2Start := Src_Rect2.x + Left1 - Left2;
+    ScanWidth := Right2 - Left1;
+    with Src_Rect1 do
+      if ScanWidth > w then
+        ScanWidth := w;
+  end;
+  with SrcSurface1^ do
+  begin
+    Pitch1 := Pitch;
+    Addr1 := PtrUInt( Pixels );
+    inc( Addr1, Pitch1 * UInt32( Src_Rect1.y ) );
+    with format^ do
+    begin
+      BPP := BytesPerPixel;
+      TransparentColor1 := colorkey;
+    end;
+  end;
+
+  Mod1 := Pitch1 - ( ScanWidth * BPP );
+
+  inc( Addr1, BPP * Scan1Start );
+
+  if Top1 <= Top2 then
+  begin
+    // 1. up, 2. down
+    ScanHeight := Bottom1 - Top2;
+    if ScanHeight > Src_Rect2.h then
+      ScanHeight := Src_Rect2.h;
+    inc( Addr1, Pitch1 * UInt32( Top2 - Top1 ) );
+  end
+  else
+  begin
+    // 1. down, 2. up
+    ScanHeight := Bottom2 - Top1;
+    if ScanHeight > Src_Rect1.h then
+      ScanHeight := Src_Rect1.h;
+
+  end;
+  case BPP of
+    1 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PByte( Addr1 )^ <> TransparentColor1 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1 );
+
+        end;
+        inc( Addr1, Mod1 );
+
+      end;
+    2 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PWord( Addr1 )^ <> TransparentColor1 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 2 );
+
+        end;
+        inc( Addr1, Mod1 );
+
+      end;
+    3 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          Color1 := PLongWord( Addr1 )^ and $00FFFFFF;
+
+          if ( Color1 <> TransparentColor1 )
+            then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 3 );
+
+        end;
+        inc( Addr1, Mod1 );
+
+      end;
+    4 :
+      for ty := 1 to ScanHeight do
+      begin
+        for tx := 1 to ScanWidth do
+        begin
+          if ( PLongWord( Addr1 )^ <> TransparentColor1 ) then
+          begin
+            Result := true;
+            exit;
+          end;
+          inc( Addr1, 4 );
+
+        end;
+        inc( Addr1, Mod1 );
+
+      end;
+  end;
+end;
+
+procedure SDL_ORSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+{*R, *}{*G, *}{*B, *}Pixel1, Pixel2, TransparentColor : cardinal; // Auto Removed, Unused Variable (R) // Auto Removed, Unused Variable (G) // Auto Removed, Unused Variable (B)
+  Src, Dest    : TSDL_Rect;
+  Diff         : integer;
+  SrcAddr, DestAddr : PtrUInt;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits         : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt8( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt8( DestAddr )^;
+              PUInt8( DestAddr )^ := Pixel2 or Pixel1;
+            end;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    15 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+
+              PUInt16( DestAddr )^ := Pixel2 or Pixel1;
+
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    16 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+
+              PUInt16( DestAddr )^ := Pixel2 or Pixel1;
+
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    24 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^ and $00FFFFFF;
+
+              PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or Pixel2 or Pixel1;
+            end;
+            inc( SrcAddr, 3 );
+            inc( DestAddr, 3 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    32 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^;
+
+              PUInt32( DestAddr )^ := Pixel2 or Pixel1;
+            end;
+            inc( SrcAddr, 4 );
+            inc( DestAddr, 4 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+procedure SDL_ANDSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+{*R, *}{*G, *}{*B, *}Pixel1, Pixel2, TransparentColor : cardinal; // Auto Removed, Unused Variable (R) // Auto Removed, Unused Variable (G) // Auto Removed, Unused Variable (B)
+  Src, Dest    : TSDL_Rect;
+  Diff         : integer;
+  SrcAddr, DestAddr : PtrUInt;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits         : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt8( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt8( DestAddr )^;
+              PUInt8( DestAddr )^ := Pixel2 and Pixel1;
+            end;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    15 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+
+              PUInt16( DestAddr )^ := Pixel2 and Pixel1;
+
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    16 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+
+              PUInt16( DestAddr )^ := Pixel2 and Pixel1;
+
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    24 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^ and $00FFFFFF;
+
+              PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or Pixel2 and Pixel1;
+            end;
+            inc( SrcAddr, 3 );
+            inc( DestAddr, 3 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    32 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^;
+
+              PUInt32( DestAddr )^ := Pixel2 and Pixel1;
+            end;
+            inc( SrcAddr, 4 );
+            inc( DestAddr, 4 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+
+
+procedure SDL_GTSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+  Src, Dest    : TSDL_Rect;
+  Diff         : integer;
+  SrcAddr, DestAddr : PtrUInt;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits         : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt8( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt8( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                if Pixel2 and $E0 > Pixel1 and $E0 then
+                  R := Pixel2 and $E0
+                else
+                  R := Pixel1 and $E0;
+                if Pixel2 and $1C > Pixel1 and $1C then
+                  G := Pixel2 and $1C
+                else
+                  G := Pixel1 and $1C;
+                if Pixel2 and $03 > Pixel1 and $03 then
+                  B := Pixel2 and $03
+                else
+                  B := Pixel1 and $03;
+
+                if R > $E0 then
+                  R := $E0;
+                if G > $1C then
+                  G := $1C;
+                if B > $03 then
+                  B := $03;
+                PUInt8( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt8( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    15 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+                if Pixel2 and $7C00 > Pixel1 and $7C00 then
+                  R := Pixel2 and $7C00
+                else
+                  R := Pixel1 and $7C00;
+                if Pixel2 and $03E0 > Pixel1 and $03E0 then
+                  G := Pixel2 and $03E0
+                else
+                  G := Pixel1 and $03E0;
+                if Pixel2 and $001F > Pixel1 and $001F then
+                  B := Pixel2 and $001F
+                else
+                  B := Pixel1 and $001F;
+
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    16 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+                if Pixel2 and $F800 > Pixel1 and $F800 then
+                  R := Pixel2 and $F800
+                else
+                  R := Pixel1 and $F800;
+                if Pixel2 and $07E0 > Pixel1 and $07E0 then
+                  G := Pixel2 and $07E0
+                else
+                  G := Pixel1 and $07E0;
+                if Pixel2 and $001F > Pixel1 and $001F then
+                  B := Pixel2 and $001F
+                else
+                  B := Pixel1 and $001F;
+
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    24 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^ and $00FFFFFF;
+              if Pixel2 > 0 then
+              begin
+
+                if Pixel2 and $FF0000 > Pixel1 and $FF0000 then
+                  R := Pixel2 and $FF0000
+                else
+                  R := Pixel1 and $FF0000;
+                if Pixel2 and $00FF00 > Pixel1 and $00FF00 then
+                  G := Pixel2 and $00FF00
+                else
+                  G := Pixel1 and $00FF00;
+                if Pixel2 and $0000FF > Pixel1 and $0000FF then
+                  B := Pixel2 and $0000FF
+                else
+                  B := Pixel1 and $0000FF;
+
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or ( R or G or B );
+              end
+              else
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or Pixel1;
+            end;
+            inc( SrcAddr, 3 );
+            inc( DestAddr, 3 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    32 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+                if Pixel2 and $FF0000 > Pixel1 and $FF0000 then
+                  R := Pixel2 and $FF0000
+                else
+                  R := Pixel1 and $FF0000;
+                if Pixel2 and $00FF00 > Pixel1 and $00FF00 then
+                  G := Pixel2 and $00FF00
+                else
+                  G := Pixel1 and $00FF00;
+                if Pixel2 and $0000FF > Pixel1 and $0000FF then
+                  B := Pixel2 and $0000FF
+                else
+                  B := Pixel1 and $0000FF;
+
+                PUInt32( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt32( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 4 );
+            inc( DestAddr, 4 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+
+procedure SDL_LTSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
+  DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
+var
+  R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+  Src, Dest    : TSDL_Rect;
+  Diff         : integer;
+  SrcAddr, DestAddr : PtrUInt;
+  WorkX, WorkY : word;
+  SrcMod, DestMod : cardinal;
+  Bits         : cardinal;
+begin
+  if ( SrcSurface = nil ) or ( DestSurface = nil ) then
+    exit; // Remove this to make it faster
+  if ( SrcSurface.Format.BitsPerPixel <> DestSurface.Format.BitsPerPixel ) then
+    exit; // Remove this to make it faster
+  if SrcRect = nil then
+  begin
+    with Src do
+    begin
+      x := 0;
+      y := 0;
+      w := SrcSurface.w;
+      h := SrcSurface.h;
+    end;
+  end
+  else
+    Src := SrcRect^;
+  if DestRect = nil then
+  begin
+    Dest.x := 0;
+    Dest.y := 0;
+  end
+  else
+    Dest := DestRect^;
+  Dest.w := Src.w;
+  Dest.h := Src.h;
+  with DestSurface.Clip_Rect do
+  begin
+    // Source's right side is greater than the dest.cliprect
+    if Dest.x + Src.w > x + w then
+    begin
+      smallint( Src.w ) := x + w - Dest.x;
+      smallint( Dest.w ) := x + w - Dest.x;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's bottom side is greater than the dest.clip
+    if Dest.y + Src.h > y + h then
+    begin
+      smallint( Src.h ) := y + h - Dest.y;
+      smallint( Dest.h ) := y + h - Dest.y;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+    // Source's left side is less than the dest.clip
+    if Dest.x < x then
+    begin
+      Diff := x - Dest.x;
+      Src.x := Src.x + Diff;
+      smallint( Src.w ) := smallint( Src.w ) - Diff;
+      Dest.x := x;
+      smallint( Dest.w ) := smallint( Dest.w ) - Diff;
+      if smallint( Dest.w ) < 1 then
+        exit;
+    end;
+    // Source's Top side is less than the dest.clip
+    if Dest.y < y then
+    begin
+      Diff := y - Dest.y;
+      Src.y := Src.y + Diff;
+      smallint( Src.h ) := smallint( Src.h ) - Diff;
+      Dest.y := y;
+      smallint( Dest.h ) := smallint( Dest.h ) - Diff;
+      if smallint( Dest.h ) < 1 then
+        exit;
+    end;
+  end;
+  with SrcSurface^ do
+  begin
+    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+      Format.BytesPerPixel;
+    SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+    TransparentColor := Format.colorkey;
+  end;
+  with DestSurface^ do
+  begin
+    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+      Format.BytesPerPixel;
+    DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+    Bits := Format.BitsPerPixel;
+  end;
+  SDL_LockSurface( SrcSurface );
+  SDL_LockSurface( DestSurface );
+  WorkY := Src.h;
+  case bits of
+    8 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt8( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt8( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+                if Pixel2 and $E0 < Pixel1 and $E0 then
+                  R := Pixel2 and $E0
+                else
+                  R := Pixel1 and $E0;
+                if Pixel2 and $1C < Pixel1 and $1C then
+                  G := Pixel2 and $1C
+                else
+                  G := Pixel1 and $1C;
+                if Pixel2 and $03 < Pixel1 and $03 then
+                  B := Pixel2 and $03
+                else
+                  B := Pixel1 and $03;
+
+                if R > $E0 then
+                  R := $E0;
+                if G > $1C then
+                  G := $1C;
+                if B > $03 then
+                  B := $03;
+                PUInt8( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt8( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr );
+            inc( DestAddr );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    15 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+                if Pixel2 and $7C00 < Pixel1 and $7C00 then
+                  R := Pixel2 and $7C00
+                else
+                  R := Pixel1 and $7C00;
+                if Pixel2 and $03E0 < Pixel1 and $03E0 then
+                  G := Pixel2 and $03E0
+                else
+                  G := Pixel1 and $03E0;
+                if Pixel2 and $001F < Pixel1 and $001F then
+                  B := Pixel2 and $001F
+                else
+                  B := Pixel1 and $001F;
+
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    16 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt16( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt16( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+                if Pixel2 and $F800 < Pixel1 and $F800 then
+                  R := Pixel2 and $F800
+                else
+                  R := Pixel1 and $F800;
+                if Pixel2 and $07E0 < Pixel1 and $07E0 then
+                  G := Pixel2 and $07E0
+                else
+                  G := Pixel1 and $07E0;
+                if Pixel2 and $001F < Pixel1 and $001F then
+                  B := Pixel2 and $001F
+                else
+                  B := Pixel1 and $001F;
+
+                PUInt16( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt16( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 2 );
+            inc( DestAddr, 2 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    24 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^ and $00FFFFFF;
+              if Pixel2 > 0 then
+              begin
+
+                if Pixel2 and $FF0000 < Pixel1 and $FF0000 then
+                  R := Pixel2 and $FF0000
+                else
+                  R := Pixel1 and $FF0000;
+                if Pixel2 and $00FF00 < Pixel1 and $00FF00 then
+                  G := Pixel2 and $00FF00
+                else
+                  G := Pixel1 and $00FF00;
+                if Pixel2 and $0000FF < Pixel1 and $0000FF then
+                  B := Pixel2 and $0000FF
+                else
+                  B := Pixel1 and $0000FF;
+
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or ( R or G or B );
+              end
+              else
+                PUInt32( DestAddr )^ := PUInt32( DestAddr )^ and $FF000000 or Pixel1;
+            end;
+            inc( SrcAddr, 3 );
+            inc( DestAddr, 3 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+    32 :
+      begin
+        repeat
+          WorkX := Src.w;
+          repeat
+            Pixel1 := PUInt32( SrcAddr )^;
+            if ( Pixel1 <> TransparentColor ) and ( Pixel1 <> 0 ) then
+            begin
+              Pixel2 := PUInt32( DestAddr )^;
+              if Pixel2 > 0 then
+              begin
+
+                if Pixel2 and $FF0000 < Pixel1 and $FF0000 then
+                  R := Pixel2 and $FF0000
+                else
+                  R := Pixel1 and $FF0000;
+                if Pixel2 and $00FF00 < Pixel1 and $00FF00 then
+                  G := Pixel2 and $00FF00
+                else
+                  G := Pixel1 and $00FF00;
+                if Pixel2 and $0000FF < Pixel1 and $0000FF then
+                  B := Pixel2 and $0000FF
+                else
+                  B := Pixel1 and $0000FF;
+
+                PUInt32( DestAddr )^ := R or G or B;
+              end
+              else
+                PUInt32( DestAddr )^ := Pixel1;
+            end;
+            inc( SrcAddr, 4 );
+            inc( DestAddr, 4 );
+            dec( WorkX );
+          until WorkX = 0;
+          inc( SrcAddr, SrcMod );
+          inc( DestAddr, DestMod );
+          dec( WorkY );
+        until WorkY = 0;
+      end;
+  end;
+  SDL_UnlockSurface( SrcSurface );
+  SDL_UnlockSurface( DestSurface );
+end;
+
+// Will clip the x1,x2,y1,x2 params to the ClipRect provided
+
+function SDL_ClipLine( var x1, y1, x2, y2 : Integer; ClipRect : PSDL_Rect ) : boolean;
+var
+  tflag, flag1, flag2 : word;
+  txy, xedge, yedge : Integer;
+  slope        : single;
+
+  function ClipCode( x, y : Integer ) : word;
+  begin
+    Result := 0;
+    if x < ClipRect.x then
+      Result := 1;
+    if x >= ClipRect.w + ClipRect.x then
+      Result := Result or 2;
+    if y < ClipRect.y then
+      Result := Result or 4;
+    if y >= ClipRect.h + ClipRect.y then
+      Result := Result or 8;
+  end;
+
+begin
+  flag1 := ClipCode( x1, y1 );
+  flag2 := ClipCode( x2, y2 );
+  result := true;
+
+  while true do
+  begin
+    if ( flag1 or flag2 ) = 0 then
+      Exit; // all in
+
+    if ( flag1 and flag2 ) <> 0 then
+    begin
+      result := false;
+      Exit; // all out
+    end;
+
+    if flag2 = 0 then
+    begin
+      txy := x1; x1 := x2; x2 := txy;
+      txy := y1; y1 := y2; y2 := txy;
+      tflag := flag1; flag1 := flag2; flag2 := tflag;
+    end;
+
+    if ( flag2 and 3 ) <> 0 then
+    begin
+      if ( flag2 and 1 ) <> 0 then
+        xedge := ClipRect.x
+      else
+        xedge := ClipRect.w + ClipRect.x - 1; // back 1 pixel otherwise we end up in a loop
+
+      slope := ( y2 - y1 ) / ( x2 - x1 );
+      y2 := y1 + Round( slope * ( xedge - x1 ) );
+      x2 := xedge;
+    end
+    else
+    begin
+      if ( flag2 and 4 ) <> 0 then
+        yedge := ClipRect.y
+      else
+        yedge := ClipRect.h + ClipRect.y - 1; // up 1 pixel otherwise we end up in a loop
+
+      slope := ( x2 - x1 ) / ( y2 - y1 );
+      x2 := x1 + Round( slope * ( yedge - y1 ) );
+      y2 := yedge;
+    end;
+
+    flag2 := ClipCode( x2, y2 );
+  end;
+end;
+
+end.
+
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlwindow.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlwindow.pas
new file mode 100644
index 00000000..99eea304
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/sdlwindow.pas
@@ -0,0 +1,566 @@
+unit sdlwindow;
+{
+  $Id: sdlwindow.pas,v 1.9 2006/10/22 18:55:25 savage Exp $
+  
+}
+{******************************************************************************}
+{                                                                              }
+{          JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer          }
+{                SDL Window Wrapper                                            }
+{                                                                              }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Portions created by Dominique Louis are                                      }
+{ Copyright (C) 2004 - 2100 Dominique Louis.                                   }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{   SDL Window Wrapper                                                         }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   SDL.dll on Windows platforms                                               }
+{   libSDL-1.1.so.0 on Linux platform                                          }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{ January    31     2003 - DL : Initial creation                               }
+{                                                                              }
+{
+  $Log: sdlwindow.pas,v $
+  Revision 1.9  2006/10/22 18:55:25  savage
+  Slight Change to handle OpenGL context
+
+  Revision 1.8  2005/08/03 18:57:32  savage
+  Various updates and additions. Mainly to handle OpenGL 3D Window support and better cursor support for the mouse class
+
+  Revision 1.7  2004/09/30 22:35:47  savage
+  Changes, enhancements and additions as required to get SoAoS working.
+
+  Revision 1.6  2004/09/12 21:52:58  savage
+  Slight changes to fix some issues with the sdl classes.
+
+  Revision 1.5  2004/05/10 21:11:49  savage
+  changes required to help get SoAoS off the ground.
+
+  Revision 1.4  2004/05/01 14:59:27  savage
+  Updated code
+
+  Revision 1.3  2004/04/23 10:45:28  savage
+  Changes made by Dean Ellis to work more modularly.
+
+  Revision 1.2  2004/03/31 10:06:41  savage
+  Changed so that it now compiles, but is untested.
+
+  Revision 1.1  2004/02/05 00:08:20  savage
+  Module 1.0 release
+  
+}
+{******************************************************************************}
+
+interface
+
+{$i jedi-sdl.inc}
+
+uses
+  Classes,
+  sdl,
+  sdlinput,
+  sdlticks;
+
+type
+  TSDLNotifyEvent =  procedure {$IFNDEF NOT_OO}of object{$ENDIF};
+  TSDLUpdateEvent =  procedure( aElapsedTime : single ) {$IFNDEF NOT_OO}of object{$ENDIF};
+  TSDLResizeEvent =  procedure( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 ) {$IFNDEF NOT_OO}of object{$ENDIF};
+  TSDLUserEvent =  procedure( aType : UInt8; aCode : integer; aData1 : Pointer; aData2 : Pointer ) {$IFNDEF NOT_OO}of object{$ENDIF};
+  TSDLActiveEvent = procedure( aGain: UInt8; aState: UInt8 ) {$IFNDEF NOT_OO}of object{$ENDIF};
+
+  TSDLBaseWindow = class( TObject )
+  private
+    FDisplaySurface : PSDL_Surface;
+    FVideoFlags : Uint32;
+    FOnDestroy: TSDLNotifyEvent;
+    FOnCreate: TSDLNotifyEvent;
+    FOnShow: TSDLNotifyEvent;
+    FOnResize: TSDLResizeEvent;
+    FOnUpdate: TSDLUpdateEvent;
+    FOnRender: TSDLNotifyEvent;
+    FOnClose: TSDLNotifyEvent;
+    FLoaded: Boolean;
+    FRendering: Boolean;
+    FHeight: integer;
+    FBitDepth: integer;
+    FWidth: integer;
+    FInputManager: TSDLInputManager;
+    FCaptionText : PChar;
+    FIconName : PChar;
+    FOnActive: TSDLActiveEvent;
+    FOnQuit: TSDLNotifyEvent;
+    FOnExpose: TSDLNotifyEvent;
+    FOnUser: TSDLUserEvent;
+    FTimer : TSDLTicks;
+  protected
+    procedure DoActive( aGain: UInt8; aState: UInt8 );
+    procedure DoCreate;
+    procedure DoClose;
+    procedure DoDestroy;
+    procedure DoUpdate( aElapsedTime : single );
+    procedure DoQuit;
+    procedure DoRender;
+    procedure DoResize( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 );
+    procedure DoShow;
+    procedure DoUser( aType : UInt8; aCode : integer; aData1 : Pointer; aData2 : Pointer );
+    procedure DoExpose;
+    procedure Render; virtual;
+    procedure Update( aElapsedTime : single ); virtual;
+    procedure InitialiseObjects; virtual;
+    procedure RestoreObjects; virtual;
+    procedure DeleteObjects; virtual;
+    function Flip : integer; virtual;
+    property OnActive : TSDLActiveEvent read FOnActive write FOnActive;
+    property OnClose: TSDLNotifyEvent read FOnClose write FOnClose;
+    property OnDestroy : TSDLNotifyEvent read FOnDestroy write FOnDestroy;
+    property OnCreate : TSDLNotifyEvent read FOnCreate write FOnCreate;
+    property OnUpdate: TSDLUpdateEvent read FOnUpdate write FOnUpdate;
+    property OnQuit : TSDLNotifyEvent read FOnQuit write FOnQuit;
+    property OnResize : TSDLResizeEvent read FOnResize write FOnResize;
+    property OnRender: TSDLNotifyEvent read FOnRender write FOnRender;
+    property OnShow : TSDLNotifyEvent read FOnShow write FOnShow;
+    property OnUser : TSDLUserEvent read FOnUser write FOnUser;
+    property OnExpose : TSDLNotifyEvent read FOnExpose write FOnExpose;
+    property DisplaySurface: PSDL_Surface read FDisplaySurface;
+  public
+    property InputManager : TSDLInputManager read FInputManager;
+    property Loaded : Boolean read FLoaded;
+    property Width : integer read FWidth;
+    property Height : integer read FHeight;
+    property BitDepth : integer read FBitDepth;
+    property Rendering : Boolean read FRendering write FRendering;
+    procedure SetCaption( const aCaptionText : string; const aIconName : string );
+    procedure GetCaption( var aCaptionText : string; var aIconName : string );
+    procedure SetIcon( aIcon : PSDL_Surface; aMask: UInt8 );
+    procedure ActivateVideoMode;
+    constructor Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 ); virtual;
+    destructor Destroy; override;
+    procedure InitialiseEnvironment;
+    function Show : Boolean; virtual;
+  end;
+
+  TSDLCustomWindow = class( TSDLBaseWindow )
+  public
+    property OnCreate;
+    property OnDestroy;
+    property OnClose;
+    property OnShow;
+    property OnResize;
+    property OnRender;
+    property OnUpdate;
+    property DisplaySurface;
+  end;
+
+  TSDL2DWindow = class( TSDLCustomWindow )
+  public
+    constructor Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 = SDL_DOUBLEBUF or SDL_SWSURFACE); override;
+    procedure Render; override;
+    procedure Update( aElapsedTime : single ); override;
+    procedure InitialiseObjects; override;
+    procedure RestoreObjects; override;
+    procedure DeleteObjects; override;
+    function Flip : integer; override;
+  end;
+
+  TSDL3DWindow = class( TSDLCustomWindow )
+  public
+    constructor Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 = SDL_OPENGL or SDL_DOUBLEBUF); override;
+    function Flip : integer; override;
+    procedure Render; override;
+    procedure Update( aElapsedTime : single ); override;
+    procedure InitialiseObjects; override;
+    procedure RestoreObjects; override;
+    procedure DeleteObjects; override;
+  end;
+
+
+
+implementation
+
+uses
+  logger,
+  SysUtils;
+
+{ TSDLBaseWindow }
+procedure TSDLBaseWindow.ActivateVideoMode;
+begin
+  FDisplaySurface := SDL_SetVideoMode( FWidth, FHeight, FBitDepth, FVideoFlags);
+  if (FDisplaySurface = nil) then
+  begin
+    Log.LogError( Format('Could not set video mode: %s', [SDL_GetError]), 'Main');
+    exit;
+  end;
+
+  SetCaption( 'Made with JEDI-SDL', 'JEDI-SDL Icon' );
+end;
+
+constructor TSDLBaseWindow.Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 );
+begin
+  inherited Create;
+  SDL_Init(SDL_INIT_EVERYTHING);
+  FInputManager := TSDLInputManager.Create( [ itJoystick, itKeyBoard, itMouse ]);
+  FTimer := TSDLTicks.Create;
+
+  FWidth := aWidth;
+  FHeight := aHeight;
+  FBitDepth := aBitDepth;
+  FVideoFlags := aVideoFlags;
+
+  DoCreate;
+end;
+
+procedure TSDLBaseWindow.DeleteObjects;
+begin
+  FLoaded := False;
+end;
+
+destructor TSDLBaseWindow.Destroy;
+begin
+  DoDestroy;
+  if FLoaded then
+    DeleteObjects;
+  if FInputManager <> nil then
+    FreeAndNil( FInputManager );
+  if FTimer <> nil then
+    FreeAndNil( FTimer );
+  if FDisplaySurface <> nil then
+    SDL_FreeSurface( FDisplaySurface );
+  inherited Destroy;
+  SDL_Quit;
+end;
+
+procedure TSDLBaseWindow.DoActive(aGain, aState: UInt8);
+begin
+  if Assigned( FOnActive ) then
+  begin
+    FOnActive( aGain, aState );
+  end;
+end;
+
+procedure TSDLBaseWindow.DoClose;
+begin
+  if Assigned( FOnClose ) then
+  begin
+    FOnClose;
+  end;
+end;
+
+procedure TSDLBaseWindow.DoCreate;
+begin
+  if Assigned( FOnCreate ) then
+  begin
+    FOnCreate;
+  end;
+end;
+
+procedure TSDLBaseWindow.DoDestroy;
+begin
+  if Assigned( FOnDestroy ) then
+  begin
+    FOnDestroy;
+  end;
+end;
+
+procedure TSDLBaseWindow.DoExpose;
+begin
+  if Assigned( FOnExpose ) then
+  begin
+    FOnExpose;
+  end;
+end;
+
+procedure TSDLBaseWindow.DoUpdate( aElapsedTime : single );
+begin
+  if Assigned( FOnUpdate ) then
+  begin
+    FOnUpdate( aElapsedTime );
+  end;
+end;
+
+procedure TSDLBaseWindow.DoQuit;
+begin
+  FRendering := false;
+  if Assigned( FOnQuit ) then
+  begin
+    FOnQuit;
+  end;
+end;
+
+procedure TSDLBaseWindow.DoRender;
+begin
+  if Assigned(  FOnRender ) then
+  begin
+    FOnRender;
+  end;
+end;
+
+procedure TSDLBaseWindow.DoResize( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 );
+begin
+  // resize to the new size
+  SDL_FreeSurface(FDisplaySurface);
+  FWidth := aWidth;
+  FHeight := aHeight;
+  FBitDepth := aBitDepth;
+  FVideoFlags := aVideoFlags;
+  FDisplaySurface := SDL_SetVideoMode(aWidth, aHeight, aBitDepth, aVideoFlags);
+  if Assigned( FOnResize ) then
+  begin
+    FOnResize( aWidth, aHeight, aBitDepth, aVideoFlags );
+  end;
+end;
+
+procedure TSDLBaseWindow.DoShow;
+begin
+  if Assigned( FOnShow ) then
+  begin
+    FOnShow;
+  end;
+end;
+
+procedure TSDLBaseWindow.DoUser(aType: UInt8; aCode: integer; aData1, aData2: Pointer);
+begin
+  if Assigned(  FOnUser ) then
+  begin
+    FOnUser( aType, aCode, aData1, aData2 );
+  end;
+end;
+
+function TSDLBaseWindow.Flip : integer;
+begin
+  result := 0;
+end;
+
+procedure TSDLBaseWindow.GetCaption( var aCaptionText : string; var aIconName : string );
+begin
+  aCaptionText := string( FCaptionText );
+  aIconName := string( FIconName );
+end;
+
+procedure TSDLBaseWindow.InitialiseEnvironment;
+begin
+  InitialiseObjects;
+  RestoreObjects;
+end;
+
+procedure TSDLBaseWindow.InitialiseObjects;
+begin
+  FLoaded := True;
+end;
+
+procedure TSDLBaseWindow.Update( aElapsedTime : single );
+begin
+  DoUpdate( aElapsedTime );
+end;
+
+procedure TSDLBaseWindow.Render;
+begin
+  DoRender;
+end;
+
+procedure TSDLBaseWindow.RestoreObjects;
+begin
+  FLoaded := false;
+end;
+
+procedure TSDLBaseWindow.SetCaption( const aCaptionText : string; const aIconName : string );
+begin
+  if FCaptionText <> aCaptionText then
+  begin
+    FCaptionText := PChar( aCaptionText );
+    FIconName := PChar( aIconName );
+    SDL_WM_SetCaption( FCaptionText, FIconName );
+  end;
+end;
+
+procedure TSDLBaseWindow.SetIcon(aIcon: PSDL_Surface; aMask: UInt8);
+begin
+  SDL_WM_SetIcon( aIcon, aMask );
+end;
+
+function TSDLBaseWindow.Show : Boolean;
+var
+  eBaseWindowEvent : TSDL_Event;
+begin
+  DoShow;
+
+  FTimer.Init;
+
+  FRendering := true;
+  // repeat until we are told not to render
+  while FRendering do
+  begin
+    // wait for an event
+    while SDL_PollEvent( @eBaseWindowEvent ) > 0 do
+    begin
+
+      // check for a quit event
+      case eBaseWindowEvent.type_ of
+        SDL_ACTIVEEVENT :
+        begin
+          DoActive( eBaseWindowEvent.active.gain, eBaseWindowEvent.active.state );
+        end;
+
+        SDL_QUITEV :
+        begin
+          DoQuit;
+          DoClose;
+        end;
+
+        SDL_USEREVENT :
+        begin
+          DoUser( eBaseWindowEvent.user.type_, eBaseWindowEvent.user.code, eBaseWindowEvent.user.data1, eBaseWindowEvent.user.data2 );
+        end;
+
+        SDL_VIDEOEXPOSE :
+        begin
+          DoExpose;
+        end;
+
+        SDL_VIDEORESIZE :
+        begin
+          DoResize( eBaseWindowEvent.resize.w, eBaseWindowEvent.resize.h, FDisplaySurface.format.BitsPerPixel, FVideoflags );
+        end;
+
+
+      end;
+      InputManager.UpdateInputs( eBaseWindowEvent );
+    end;
+    // Prepare the Next Frame
+    Update( FTimer.GetElapsedSeconds );
+    // Display the Next Frame
+    Render;
+    // Flip the surfaces
+    Flip;
+  end;
+
+  Result := FRendering;
+end;
+
+{ TSDL2DWindow }
+
+constructor TSDL2DWindow.Create(aWidth, aHeight, aBitDepth: integer; aVideoFlags: Uint32);
+begin
+  // make sure double buffer is always included in the video flags
+  inherited Create(aWidth,aHeight, aBitDepth, aVideoFlags or SDL_DOUBLEBUF);
+end;
+
+procedure TSDL2DWindow.DeleteObjects;
+begin
+  inherited;
+
+end;
+
+function TSDL2DWindow.Flip: integer;
+begin
+  // let's show the back buffer
+  result := SDL_Flip( FDisplaySurface );
+end;
+
+procedure TSDL2DWindow.InitialiseObjects;
+begin
+  inherited;
+
+end;
+
+procedure TSDL2DWindow.Update( aElapsedTime : single );
+begin
+  inherited;
+
+end;
+
+procedure TSDL2DWindow.Render;
+begin
+  inherited;
+
+end;
+
+procedure TSDL2DWindow.RestoreObjects;
+begin
+  inherited;
+
+end;
+
+{ TSDL3DWindow }
+
+constructor TSDL3DWindow.Create(aWidth,
+  aHeight, aBitDepth: integer; aVideoFlags: Uint32);
+begin
+  // make sure opengl is always included in the video flags
+  inherited Create(aWidth,aHeight, aBitDepth, aVideoFlags or SDL_OPENGL or SDL_DOUBLEBUF);
+end;
+
+procedure TSDL3DWindow.DeleteObjects;
+begin
+  inherited;
+
+end;
+
+function TSDL3DWindow.Flip : integer;
+begin
+  SDL_GL_SwapBuffers;
+  result := 0;
+end;
+
+procedure TSDL3DWindow.InitialiseObjects;
+begin
+  inherited;
+
+end;
+
+procedure TSDL3DWindow.Update( aElapsedTime : single );
+begin
+  inherited;
+
+end;
+
+procedure TSDL3DWindow.Render;
+begin
+  inherited;
+  
+end;
+
+procedure TSDL3DWindow.RestoreObjects;
+begin
+  inherited;
+
+end;
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL/Pas/userpreferences.pas b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/userpreferences.pas
new file mode 100644
index 00000000..aed326d1
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL/Pas/userpreferences.pas
@@ -0,0 +1,159 @@
+unit userpreferences;
+{
+  $Id: userpreferences.pas,v 1.1 2004/09/30 22:35:47 savage Exp $
+  
+}
+{******************************************************************************}
+{                                                                              }
+{          JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer          }
+{                 Base Class for User Preferences                              }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Dominqiue Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Portions created by Dominqiue Louis are                                      }
+{ Copyright (C) 2000 - 2001 Dominqiue Louis.                                   }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{                                                                              }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   The SDL Runtime libraris on Win32  : SDL.dll on Linux : libSDL.so          }
+{   They are available from...                                                 }
+{   http://www.libsdl.org .                                                    }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{   September   23 2004 - DL : Initial Creation                                }
+{
+  $Log: userpreferences.pas,v $
+  Revision 1.1  2004/09/30 22:35:47  savage
+  Changes, enhancements and additions as required to get SoAoS working.
+
+
+}
+{******************************************************************************}
+
+interface
+
+uses
+  Classes;
+
+type
+  TUserPreferences = class
+  private
+    FAutoSave: Boolean;
+    procedure CheckAutoSave;
+  protected
+    function GetDefaultBoolean( const Index : Integer ) : Boolean; virtual; abstract;
+    function GetBoolean( const Index : Integer ) : Boolean; virtual; abstract;
+    procedure SetBoolean( const Index : Integer; const Value : Boolean ); virtual;
+    function GetDefaultDateTime( const Index : Integer ) : TDateTime; virtual; abstract;
+    function GetDateTime( const Index : Integer ) : TDateTime; virtual; abstract;
+    procedure SetDateTime( const Index : Integer; const Value : TDateTime ); virtual;
+    function GetDefaultInteger( const Index : Integer ) : Integer; virtual; abstract;
+    function GetInteger( const Index : Integer ) : Integer; virtual; abstract;
+    procedure SetInteger( const Index : Integer; const Value : Integer ); virtual;
+    function GetDefaultFloat( const Index : Integer ) : single; virtual; abstract;
+    function GetFloat( const Index : Integer ) : single; virtual; abstract;
+    procedure SetFloat( const Index : Integer; const Value : single ); virtual;
+    function GetDefaultString( const Index : Integer ) : string; virtual; abstract;
+    function GetString( const Index : Integer ) : string; virtual; abstract;
+    procedure SetString( const Index : Integer; const Value : string ); virtual;
+    function GetDefaultBinaryStream( const Index : Integer ) : TStream; virtual; abstract;
+    function GetBinaryStream( const Index : Integer ) : TStream; virtual; abstract;
+    procedure SetBinaryStream( const Index : Integer; const Value : TStream ); virtual;
+  public
+    procedure Update; virtual; abstract;
+    constructor Create; virtual;
+    destructor Destroy; override;
+    property AutoSave : Boolean read FAutoSave write FAutoSave;
+  end;
+
+implementation
+
+{ TUserPreferences }
+procedure TUserPreferences.CheckAutoSave;
+begin
+  if FAutoSave then
+    Update;
+end;
+
+constructor TUserPreferences.Create;
+begin
+  inherited;
+  FAutoSave := false;
+end;
+
+destructor TUserPreferences.Destroy;
+begin
+
+  inherited;
+end;
+
+procedure TUserPreferences.SetBinaryStream( const Index : Integer; const Value : TStream );
+begin
+  CheckAutoSave;
+end;
+
+procedure TUserPreferences.SetBoolean(const Index: Integer; const Value: Boolean);
+begin
+  CheckAutoSave;
+end;
+
+procedure TUserPreferences.SetDateTime(const Index: Integer; const Value: TDateTime);
+begin
+  CheckAutoSave;
+end;
+
+procedure TUserPreferences.SetFloat(const Index: Integer; const Value: single);
+begin
+  CheckAutoSave;
+end;
+
+procedure TUserPreferences.SetInteger(const Index, Value: Integer);
+begin
+  CheckAutoSave;
+end;
+
+procedure TUserPreferences.SetString(const Index: Integer; const Value: string);
+begin
+  CheckAutoSave;
+end;
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/SDL_Image/Pas/sdl_image.pas b/songmanagement/src/lib/JEDI-SDL/SDL_Image/Pas/sdl_image.pas
new file mode 100644
index 00000000..4468f036
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/SDL_Image/Pas/sdl_image.pas
@@ -0,0 +1,350 @@
+unit sdl_image;
+{
+  $Id: sdl_image.pas,v 1.15 2007/12/05 22:52:23 savage Exp $
+  
+}
+{******************************************************************************}
+{                                                                              }
+{       Borland Delphi SDL_Image - An example image loading library for use    }
+{                                  with SDL                                    }
+{       Conversion of the Simple DirectMedia Layer Image Headers               }
+{                                                                              }
+{ Portions created by Sam Lantinga <slouken@devolution.com> are                }
+{ Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga                     }
+{ 5635-34 Springhouse Dr.                                                      }
+{ Pleasanton, CA 94588 (USA)                                                   }
+{                                                                              }
+{ All Rights Reserved.                                                         }
+{                                                                              }
+{ The original files are : SDL_image.h                                         }
+{                                                                              }
+{ The initial developer of this Pascal code was :                              }
+{ Matthias Thoma <ma.thoma@gmx.de>                                             }
+{                                                                              }
+{ Portions created by Matthias Thoma are                                       }
+{ Copyright (C) 2000 - 2001 Matthias Thoma.                                    }
+{                                                                              }
+{                                                                              }
+{ Contributor(s)                                                               }
+{ --------------                                                               }
+{ Dominique Louis <Dominique@SavageSoftware.com.au>                            }
+{                                                                              }
+{ Obtained through:                                                            }
+{ Joint Endeavour of Delphi Innovators ( Project JEDI )                        }
+{                                                                              }
+{ You may retrieve the latest version of this file at the Project              }
+{ JEDI home page, located at http://delphi-jedi.org                            }
+{                                                                              }
+{ The contents of this file are used with permission, subject to               }
+{ the Mozilla Public License Version 1.1 (the "License"); you may              }
+{ not use this file except in compliance with the License. You may             }
+{ obtain a copy of the License at                                              }
+{ http://www.mozilla.org/MPL/MPL-1.1.html                                      }
+{                                                                              }
+{ Software distributed under the License is distributed on an                  }
+{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or               }
+{ implied. See the License for the specific language governing                 }
+{ rights and limitations under the License.                                    }
+{                                                                              }
+{ Description                                                                  }
+{ -----------                                                                  }
+{   A simple library to load images of various formats as SDL surfaces         }
+{                                                                              }
+{ Requires                                                                     }
+{ --------                                                                     }
+{   SDL.pas in your search path.                                               }
+{                                                                              }
+{ Programming Notes                                                            }
+{ -----------------                                                            }
+{   See the Aliens Demo on how to make use of this libaray                     }
+{                                                                              }
+{ Revision History                                                             }
+{ ----------------                                                             }
+{   April    02 2001 - MT : Initial Translation                                }
+{                                                                              }
+{   May      08 2001 - DL : Added ExternalSym derectives and copyright header  }
+{                                                                              }
+{   April   03 2003 - DL : Added jedi-sdl.inc include file to support more     }
+{                          Pascal compilers. Initial support is now included   }
+{                          for GnuPascal, VirtualPascal, TMT and obviously     }
+{                          continue support for Delphi Kylix and FreePascal.   }
+{                                                                              }
+{   April   08 2003 - MK : Aka Mr Kroket - Added Better FPC support            }
+{                                                                              }
+{   April   24 2003 - DL : under instruction from Alexey Barkovoy, I have added}
+{                          better TMT Pascal support and under instruction     }
+{                          from Prof. Abimbola Olowofoyeku (The African Chief),}
+{                          I have added better Gnu Pascal support              }
+{                                                                              }
+{   April   30 2003 - DL : under instruction from David Mears AKA              }
+{                          Jason Siletto, I have added FPC Linux support.      }
+{                          This was compiled with fpc 1.1, so remember to set  }
+{                          include file path. ie. -Fi/usr/share/fpcsrc/rtl/*   }
+{                                                                              }
+{
+  $Log: sdl_image.pas,v $
+  Revision 1.15  2007/12/05 22:52:23  savage
+  Better Mac OS X support for Frameworks.
+
+  Revision 1.14  2007/05/29 21:31:13  savage
+  Changes as suggested by Almindor for 64bit compatibility.
+
+  Revision 1.13  2007/05/20 20:30:54  savage
+  Initial Changes to Handle 64 Bits
+
+  Revision 1.12  2006/12/02 00:14:40  savage
+  Updated to latest version
+
+  Revision 1.11  2005/04/10 18:22:59  savage
+  Changes as suggested by Michalis, thanks.
+
+  Revision 1.10  2005/04/10 11:48:33  savage
+  Changes as suggested by Michalis, thanks.
+
+  Revision 1.9  2005/01/05 01:47:07  savage
+  Changed LibName to reflect what MacOS X should have. ie libSDL*-1.2.0.dylib respectively.
+
+  Revision 1.8  2005/01/04 23:14:44  savage
+  Changed LibName to reflect what most Linux distros will have. ie libSDL*-1.2.so.0 respectively.
+
+  Revision 1.7  2005/01/01 02:03:12  savage
+  Updated to v1.2.4
+
+  Revision 1.6  2004/08/14 22:54:30  savage
+  Updated so that Library name defines are correctly defined for MacOS X.
+
+  Revision 1.5  2004/05/10 14:10:04  savage
+  Initial MacOS X support. Fixed defines for MACOS ( Classic ) and DARWIN ( MacOS X ).
+
+  Revision 1.4  2004/04/13 09:32:08  savage
+  Changed Shared object names back to just the .so extension to avoid conflicts on various Linux/Unix distros. Therefore developers will need to create Symbolic links to the actual Share Objects if necessary.
+
+  Revision 1.3  2004/04/01 20:53:23  savage
+  Changed Linux Shared Object names so they reflect the Symbolic Links that are created when installing the RPMs from the SDL site.
+
+  Revision 1.2  2004/03/30 20:23:28  savage
+  Tidied up use of UNIX compiler directive.
+
+  Revision 1.1  2004/02/14 23:35:42  savage
+  version 1 of sdl_image, sdl_mixer and smpeg.
+
+
+}  
+{******************************************************************************}
+
+{$I jedi-sdl.inc}
+
+interface
+
+uses
+{$IFDEF __GPC__}
+  gpc,
+{$ENDIF}
+  sdl;
+
+const
+{$IFDEF WINDOWS}
+  SDL_ImageLibName =  'SDL_Image.dll';
+{$ENDIF}
+
+{$IFDEF UNIX}
+{$IFDEF DARWIN}
+  SDL_ImageLibName = 'libSDL_image-1.2.0.dylib';
+  {$linklib libSDL_image}
+{$ELSE}
+  {$IFDEF FPC}
+    SDL_ImageLibName = 'libSDL_image.so';
+  {$ELSE}
+    SDL_ImageLibName = 'libSDL_image-1.2.so.0';
+  {$ENDIF}
+{$ENDIF}
+{$ENDIF}
+
+{$IFDEF MACOS}
+  SDL_ImageLibName = 'SDL_image';
+  {$linklib libSDL_image}
+{$ENDIF}
+
+  // Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
+  SDL_IMAGE_MAJOR_VERSION = 1;
+{$EXTERNALSYM SDL_IMAGE_MAJOR_VERSION}
+  SDL_IMAGE_MINOR_VERSION = 2;
+{$EXTERNALSYM SDL_IMAGE_MINOR_VERSION}
+  SDL_IMAGE_PATCHLEVEL    = 6;
+{$EXTERNALSYM SDL_IMAGE_PATCHLEVEL}
+
+{ This macro can be used to fill a version structure with the compile-time
+  version of the SDL_image library. }
+procedure SDL_IMAGE_VERSION( var X : TSDL_Version );
+{$EXTERNALSYM SDL_IMAGE_VERSION}
+
+{ This function gets the version of the dynamically linked SDL_image library.
+   it should NOT be used to fill a version structure, instead you should
+   use the SDL_IMAGE_VERSION() macro.
+ }
+function IMG_Linked_Version : PSDL_version;
+external {$IFDEF __GPC__}name 'IMG_Linked_Version'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_Linked_Version}
+
+{ Load an image from an SDL data source.
+   The 'type' may be one of: "BMP", "GIF", "PNG", etc.
+
+   If the image format supports a transparent pixel, SDL will set the
+   colorkey for the surface.  You can enable RLE acceleration on the
+   surface afterwards by calling:
+        SDL_SetColorKey(image, SDL_RLEACCEL, image.format.colorkey);
+}
+function IMG_LoadTyped_RW(src: PSDL_RWops; freesrc: Integer; _type: PChar): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadTyped_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadTyped_RW}
+{ Convenience functions }
+function IMG_Load(const _file: PChar): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_Load'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_Load}
+function IMG_Load_RW(src: PSDL_RWops; freesrc: Integer): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_Load_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_Load_RW}
+
+{ Invert the alpha of a surface for use with OpenGL
+  This function is now a no-op, and only provided for backwards compatibility. }
+function IMG_InvertAlpha(_on: Integer): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_InvertAlpha'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_InvertAlpha}
+
+{ Functions to detect a file type, given a seekable source }
+function IMG_isBMP(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isBMP'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isBMP}
+
+function IMG_isGIF(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isGIF'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isGIF}
+
+function IMG_isJPG(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isJPG'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isJPG}
+
+function IMG_isLBM(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isLBM'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isLBM}
+
+function IMG_isPCX(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isPCX'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isPCX}
+
+function IMG_isPNG(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isPNG'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isPNG}
+
+function IMG_isPNM(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isPNM'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isPNM}
+
+function IMG_isTIF(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isTIF'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isTIF}
+
+function IMG_isXCF(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isXCF'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isXCF}
+
+function IMG_isXPM(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isXPM'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isXPM}
+
+function IMG_isXV(src: PSDL_RWops): Integer;
+cdecl; external {$IFDEF __GPC__}name 'IMG_isXV'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_isXV}
+
+
+{ Individual loading functions }
+function IMG_LoadBMP_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadBMP_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadBMP_RW}
+
+function IMG_LoadGIF_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadGIF_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadGIF_RW}
+
+function IMG_LoadJPG_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadJPG_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadJPG_RW}
+
+function IMG_LoadLBM_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadLBM_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadLBM_RW}
+
+function IMG_LoadPCX_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadPCX_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadPCX_RW}
+
+function IMG_LoadPNM_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadPNM_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadPNM_RW}
+
+function IMG_LoadPNG_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadPNG_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadPNG_RW}
+
+function IMG_LoadTGA_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadTGA_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadTGA_RW}
+
+function IMG_LoadTIF_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadTIF_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadTIF_RW}
+
+function IMG_LoadXCF_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadXCF_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadXCF_RW}
+
+function IMG_LoadXPM_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadXPM_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadXPM_RW}
+
+function IMG_LoadXV_RW(src: PSDL_RWops): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_LoadXV_RW'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_LoadXV_RW}
+
+function IMG_ReadXPMFromArray( xpm : PPChar ): PSDL_Surface;
+cdecl; external {$IFDEF __GPC__}name 'IMG_ReadXPMFromArray'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+{$EXTERNALSYM IMG_ReadXPMFromArray}
+
+
+
+
+{ used internally, NOT an exported function }
+//function IMG_string_equals( const str1 : PChar; const str2 : PChar ) : integer;
+//cdecl; external {$IFDEF __GPC__}name 'IMG_string_equals'{$ELSE} SDL_ImageLibName{$ENDIF __GPC__};
+//{ $ EXTERNALSYM IMG_string_equals}
+
+{ Error Macros }
+{ We'll use SDL for reporting errors }
+procedure IMG_SetError( fmt : PChar );
+
+function IMG_GetError : PChar;
+
+implementation
+
+{$IFDEF __GPC__}
+  {$L 'sdl_image'}  { link sdl_image.dll.a or libsdl_image.so or libsdl_image.a }
+{$ENDIF}
+
+procedure SDL_IMAGE_VERSION( var X : TSDL_Version );
+begin
+  X.major := SDL_IMAGE_MAJOR_VERSION;
+  X.minor := SDL_IMAGE_MINOR_VERSION;
+  X.patch := SDL_IMAGE_PATCHLEVEL;
+end;
+
+procedure IMG_SetError( fmt : PChar );
+begin
+  SDL_SetError( fmt );
+end;
+
+function IMG_GetError : PChar;
+begin
+  result := SDL_GetError;
+end;
+
+end.
diff --git a/songmanagement/src/lib/JEDI-SDL/fpc-install.sh b/songmanagement/src/lib/JEDI-SDL/fpc-install.sh
new file mode 100644
index 00000000..b7a5cf69
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/fpc-install.sh
@@ -0,0 +1,252 @@
+#!/bin/sh
+#
+# FreePascal & Delphi Installation script for JEDI-SDL
+# portions of which are based on the FreePascal install script
+# Copyright 1996-2002 Michael Van Canneyt and Peter Vreman
+#   
+# Copyright (c)2004-2100, JEDI-SDL Team
+# All Rights Reserved
+#
+# Don NOT edit this file. 
+# Everything should be configuration while the script is running.
+#
+############################################################################
+
+# Release Version
+VERSION=1.0
+
+# some useful functions
+# ask displays 1st parameter, and ask new value for variable, whose name is
+# in the second parameter.
+ask ()
+{
+askvar=$2
+eval old=\$$askvar
+eval echo -n \""$1 [$old] : "\" 
+read $askvar
+eval test -z \"\$$askvar\" && eval $askvar=\'$old\'
+}
+# yesno gives 1 on no, 0 on yes $1 gives text to display.
+yesno ()
+{
+  while true; do
+  echo -n "$1 (Y/n) ? "
+  read ans
+  case X$ans in
+   X|Xy|XY) return 0;;
+   Xn|XN) return 1;;
+  esac
+  done
+}
+
+# Untar files ($3,optional) from  file ($1) to the given directory ($2)
+unztar ()
+{
+ tar -xzf $HERE/$1 --directory $2 $3
+}
+
+# Untar tar.gz file ($2) from file ($1) and untar result to the given directory ($3)
+unztarfromtar ()
+{
+ tar -xOf $HERE/$1 $2 | tar --directory $3 -xzf -
+}
+# Get file list from tar archive ($1) in variable ($2)
+# optionally filter result through sed ($3)
+listtarfiles ()
+{
+  askvar=$2
+  if [ ! -z $3 ]; then
+    list=`tar tvf $1 | awk '{ print $(NF) }' | sed -n /$3/p`
+  else
+     list=`tar tvf $1 | awk '{ print $(NF) }'`
+  fi
+  eval $askvar='$list'
+}
+# Make all the necessary directories to get $1
+makedirhierarch ()
+{
+  OLDDIR=`pwd`
+  case $1 in
+    /*) cd /;;
+  esac
+  OLDIFS=$IFS;IFS=/;eval set $1; IFS=$OLDIFS
+  for i
+  do
+    test -d $i || mkdir $i || break
+    cd $i ||break
+  done
+  cd $OLDDIR
+}
+
+# check to see if something is in the path
+checkpath ()
+{
+ ARG=$1
+ OLDIFS=$IFS; IFS=":";eval set $PATH;IFS=$OLDIFS
+ for i
+ do
+   if [ $i = $ARG ]; then
+     return 0
+   fi
+ done 
+ return 1
+}
+
+# --------------------------------------------------------------------------
+# welcome message.
+#
+
+clear
+echo "This shell script will attempt to install the Free Pascal Compiler"
+echo "version $VERSION with the items you select"
+echo 
+
+# Here we start the thing.
+HERE=`pwd`
+
+# Install in /usr/local or /usr ?
+if checkpath /usr/local/bin; then
+    PREFIX=/usr/local
+else
+    PREFIX=/usr
+fi
+# If we can't write on prefix, select subdir of home dir
+if [ ! -w $PREFIX ]; then
+  PREFIX=$HOME/JEDI-SDLv$VERSION
+fi
+ask "Install prefix (/usr or /usr/local) " PREFIX
+makedirhierarch $PREFIX
+
+# Set some defaults.
+LIBDIR=$PREFIX/lib/JEDI-SDL/$VERSION
+SRCDIR=$PREFIX/src/JEDI-SDLv$VERSION
+EXECDIR=$PREFIX/bin
+OSNAME=`uname -s | tr A-Z a-z`
+
+BSDHIER=0
+case $OSNAME in 
+*bsd)
+  BSDHIER=1;;
+esac
+
+
+if [ "${BSDHIER}" = "1" ]; then
+DOCDIR=$PREFIX/share/doc/JEDI-SDLv$VERSION
+else
+DOCDIR=$PREFIX/doc/JEDI-SDLv$VERSION
+fi
+
+echo $DOCDIR
+
+DEMODIR=$PREFIX/demos
+
+# Install SDL headers
+if yesno "Install SDL headers"; then
+  
+fi
+
+# Install SDL_image headers
+if yesno "Install SDL_image headers"; then
+  
+fi
+
+# Install compiler/RTL. Mandatory.
+echo Installing compiler and RTL ...
+unztarfromtar binary.tar base${OSNAME}.tar.gz $PREFIX
+rm -f $EXECDIR/ppc386
+ln -sf $LIBDIR/ppc386 $EXECDIR/ppc386
+echo Installing utilities...
+unztarfromtar binary.tar util${OSNAME}.tar.gz $PREFIX
+if yesno "Install FCL"; then
+    unztarfromtar binary.tar unitsfcl${OSNAME}.tar.gz $PREFIX
+fi
+if yesno "Install packages"; then
+  listtarfiles binary.tar packages units
+  for f in $packages 
+  do
+    if [ $f != unitsfcl${OSNAME}.tar.gz ]; then
+      basename $f .tar.gz |\
+      sed -e s/units// -e s/${OSNAME}// |\
+      xargs echo Installing 
+      unztarfromtar binary.tar $f $PREFIX
+    fi
+  done
+fi
+rm -f *${OSNAME}.tar.gz
+echo Done.
+echo
+
+# Install the sources. Optional.
+if yesno "Install sources"; then
+  echo Installing sources in $SRCDIR ...
+  unztarfromtar sources.tar  basesrc.tar.gz $PREFIX
+  if yesno "Install compiler source"; then
+    unztarfromtar sources.tar compilersrc.tar.gz $PREFIX
+  fi    
+  if yesno "Install RTL source"; then
+    unztarfromtar sources.tar rtlsrc.tar.gz $PREFIX
+  fi    
+  if yesno "Install FCL source"; then
+    unztarfromtar sources.tar fclsrc.tar.gz $PREFIX
+  fi    
+  if yesno "Install IDE source"; then
+    unztarfromtar sources.tar idesrc.tar.gz $PREFIX
+  fi    
+  if yesno "Install installer source"; then
+    unztarfromtar sources.tar installersrc.tar.gz $PREFIX
+  fi    
+  if yesno "Install Packages source"; then
+    listtarfiles sources.tar packages units
+    for f in $packages
+    do
+      basename $f .tar.gz |\
+      sed -e s/units// -e s/src// |\
+      xargs echo Installing sources for 
+      unztarfromtar sources.tar $f $PREFIX
+    done
+  fi    
+  # rm -f *src.tar.gz
+  echo Done.
+fi
+echo
+
+# Install the documentation. Optional.
+if yesno "Install documentation"; then
+  echo Installing documentation in $DOCDIR ...
+  unztar docs.tar.gz $DOCDIR
+  echo Done.
+fi
+echo
+
+# Install the demos. Optional.
+if yesno "Install demos"; then
+  ask "Install demos in" DEMODIR
+  echo Installing demos in $DEMODIR ...
+  makedirhierarch $DEMODIR
+  unztar demo.tar.gz $DEMODIR
+  echo Done.
+fi
+echo
+
+# update fpc.cfg file
+if yesno "Update fpc.cfg file automagically"; then
+  echo Updating fpc.cfg in $DOCDIR ...
+  echo 
+  echo Done.
+fi
+
+# update Borland IDE file
+if yesno "Update the Kylix IDE automagically"; then
+  echo Updating the Kylix IDE in $DOCDIR ...
+  echo 
+  echo Done.
+fi
+
+$LIBDIR/samplecfg $LIBDIR
+
+# The End
+echo
+echo End of installation. 
+echo
+echo Refer to the documentation for more information.
+echo
\ No newline at end of file
diff --git a/songmanagement/src/lib/JEDI-SDL/jedi-sdl-64bit.patch b/songmanagement/src/lib/JEDI-SDL/jedi-sdl-64bit.patch
new file mode 100644
index 00000000..582ebe6a
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/jedi-sdl-64bit.patch
@@ -0,0 +1,1280 @@
+cvs diff: Diffing .
+cvs diff: Diffing Cal3D
+cvs diff: Diffing Cal3D/Demos
+cvs diff: Diffing Cal3D/Demos/DCally
+cvs diff: Diffing Cal3D/Demos/DCally/data
+cvs diff: Diffing Cal3D/Demos/DCally/data/cally
+cvs diff: Diffing Cal3D/Pas
+cvs diff: Diffing Demos
+cvs diff: Diffing Demos/2D
+cvs diff: Diffing Demos/2D/Aliens
+cvs diff: Diffing Demos/2D/Aliens/data
+cvs diff: Diffing Demos/2D/BlitzBomber
+cvs diff: Diffing Demos/2D/BlitzBomber/images
+cvs diff: Diffing Demos/2D/CustomCursors
+cvs diff: Diffing Demos/2D/CustomCursors/cursors
+cvs diff: Diffing Demos/2D/CustomCursors/images
+cvs diff: Diffing Demos/2D/Fading
+cvs diff: Diffing Demos/2D/Fading/images
+cvs diff: Diffing Demos/2D/Isometric
+cvs diff: Diffing Demos/2D/Isometric/images
+cvs diff: Diffing Demos/2D/Isometric/maps
+cvs diff: Diffing Demos/2D/Mouse
+cvs diff: Diffing Demos/2D/Mouse/images
+cvs diff: Diffing Demos/2D/PanAndZoom
+cvs diff: Diffing Demos/2D/Plasma
+Index: Demos/2D/Plasma/JEDISDLPlasma.dpr
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/Demos/2D/Plasma/JEDISDLPlasma.dpr,v
+retrieving revision 1.1
+diff -u -r1.1 JEDISDLPlasma.dpr
+--- Demos/2D/Plasma/JEDISDLPlasma.dpr	30 Sep 2006 17:20:08 -0000	1.1
++++ Demos/2D/Plasma/JEDISDLPlasma.dpr	27 Feb 2008 09:15:58 -0000
+@@ -107,13 +107,13 @@
+   X3_ := trunc(x3 * (TABLEX / 2));
+   Y3_ := trunc(y3 * (TABLEY / 2));
+ 
+-  t1 := Pointer(Integer(t) + X1_ + Y1_ * TABLEX);
+-  t2 := Pointer(Integer(t) + X2_ + Y2_ * TABLEX);
+-  t3 := Pointer(Integer(t) + X3_ + Y3_ * TABLEX);
++  t1 := Pointer(PtrInt(t) + X1_ + Y1_ * TABLEX);
++  t2 := Pointer(PtrInt(t) + X2_ + Y2_ * TABLEX);
++  t3 := Pointer(PtrInt(t) + X3_ + Y3_ * TABLEX);
+ 
+   for y := 0 to SCREEN_HEIGHT - 1  do
+   begin
+-    tmp :=  PByte(Integer(surface.pixels) + y * surface.pitch);
++    tmp :=  PByte(PtrInt(surface.pixels) + y * surface.pitch);
+ 
+     tmin := y * TABLEX;
+     tmax := tmin + SCREEN_WIDTH;
+cvs diff: Diffing Demos/2D/SDLTests
+cvs diff: Diffing Demos/2D/SDLTests/images
+cvs diff: Diffing Demos/2D/SDLTests/testalpha
+Index: Demos/2D/SDLTests/testalpha/testalpha.dpr
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/Demos/2D/SDLTests/testalpha/testalpha.dpr,v
+retrieving revision 1.1
+diff -u -r1.1 testalpha.dpr
+--- Demos/2D/SDLTests/testalpha/testalpha.dpr	30 Sep 2006 17:20:08 -0000	1.1
++++ Demos/2D/SDLTests/testalpha/testalpha.dpr	27 Feb 2008 09:15:59 -0000
+@@ -371,7 +371,6 @@
+   ticks, lastticks : Uint32;
+   clip, area : TSDL_Rect;
+ begin
+-
+   (* Initialize SDL *)
+   if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) then
+   begin
+@@ -392,11 +391,13 @@
+   end;
+ 
+   videoflags := SDL_SWSURFACE;
+-  for i := 0 to ParamCount - 1 do
++  i := 1;
++  while i <= ParamCount do
+   begin
+     if ( ParamStr( i ) = '-bpp' ) then
+     begin
+-      video_bpp := StrToInt( ParamStr( i + 1 ) );
++      Inc(i);
++      video_bpp := StrToInt( ParamStr( i ) );
+     end
+     else if ( ParamStr( i ) = '-hw' ) then
+     begin
+@@ -416,7 +417,9 @@
+         'MAIN' );
+       halt( 1 );
+     end;
++    Inc(i);
+   end;
++
+   (* Set 640 x 480 video mode *)
+   screen := SDL_SetVideoMode( 640, 480, video_bpp, videoflags );
+   if ( Screen = nil ) then
+@@ -442,7 +445,7 @@
+   buffer := PUint8( screen.pixels );
+   for i := 0 to screen.h - 1 do
+   begin
+-    FillChar( buffer, Screen.pitch, ( i * 255 ) div screen.h );
++    FillChar( buffer^, Screen.pitch, ( i * 255 ) div screen.h );
+     //memset(buffer, (i * 255) div screen.h , screen.pitch);
+     Inc( buffer, screen.pitch );
+   end;
+@@ -469,7 +472,7 @@
+   clip.w := screen.w - ( 2 * 32 );
+   clip.h := screen.h - ( 2 * 32 );
+   SDL_SetClipRect( screen, @clip );
+-
++  
+   (* Wait for a keystroke *)
+   lastticks := SDL_GetTicks;
+   done := False;
+cvs diff: Diffing Demos/2D/SDLTests/testgamma
+cvs diff: Diffing Demos/2D/SDLTests/testjoystick
+cvs diff: Diffing Demos/2D/SDLTests/testwin
+cvs diff: Diffing Demos/2D/SDLUtilsTests
+cvs diff: Diffing Demos/2D/SDLUtilsTests/MainTest
+cvs diff: Diffing Demos/2D/SDLUtilsTests/MainTest/images
+cvs diff: Diffing Demos/2D/SDLUtilsTests/PixelTest
+cvs diff: Diffing Demos/2D/SDLUtilsTests/PixelTest/images
+cvs diff: Diffing Demos/2D/SDLUtilsTests/RotateSurface
+cvs diff: Diffing Demos/2D/SDLUtilsTests/RotateSurface/images
+cvs diff: Diffing Demos/2D/SDLUtilsTests/WormHole
+cvs diff: Diffing Demos/2D/TimerTest
+cvs diff: Diffing Demos/2D/Voxel
+Index: Demos/2D/Voxel/JEDISDLNewVox.dpr
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/Demos/2D/Voxel/JEDISDLNewVox.dpr,v
+retrieving revision 1.2
+diff -u -r1.2 JEDISDLNewVox.dpr
+--- Demos/2D/Voxel/JEDISDLNewVox.dpr	29 May 2007 21:44:24 -0000	1.2
++++ Demos/2D/Voxel/JEDISDLNewVox.dpr	27 Feb 2008 09:16:00 -0000
+@@ -246,7 +246,7 @@
+     // Draw the column  from a (last height) to y (current height)
+     if ( y < a ) then
+     begin
+-      b1 := PByte(Integer(@Video[0]) + a * SCREEN_WIDTH + i);
++      b1 := PByte(PtrInt(@Video[0]) + a * SCREEN_WIDTH + i);
+ 
+       if lastc[i] = -1 then
+       	lastc[i] := c;
+cvs diff: Diffing Demos/2D/YuvPlayer
+cvs diff: Diffing Demos/3D
+cvs diff: Diffing Demos/3D/BasicShader
+cvs diff: Diffing Demos/3D/NeHe
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 10
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 10/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 10/levels
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 11
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 11/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 12
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 12/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 13
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 13/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 16
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 16/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 17
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 17/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 18
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 18/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 19
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 19/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 2
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 20
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 20/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 21
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 21/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 21/sound
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 3
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 37
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 4
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 5
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 6
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 6/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 7
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 7/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 8
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 8/images
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 9
+cvs diff: Diffing Demos/3D/NeHe/Tutorial 9/images
+cvs diff: Diffing Documentation
+cvs diff: Diffing Documentation/HLP
+cvs diff: Diffing Documentation/html
+cvs diff: Diffing Documentation/html/images
+cvs diff: Diffing HawkVoice
+cvs diff: Diffing HawkVoice/Demos
+cvs diff: Diffing HawkVoice/Pas
+cvs diff: Diffing Newton
+cvs diff: Diffing Newton/Demos
+cvs diff: Diffing Newton/Demos/SDLBasic
+cvs diff: Diffing Newton/Demos/SDLBuoyancy
+cvs diff: Diffing Newton/Demos/SDLCharacterController
+cvs diff: Diffing Newton/Demos/SDLCharacterController/data
+cvs diff: Diffing Newton/Demos/SDLJoints
+cvs diff: Diffing Newton/Demos/SDLRagDoll
+cvs diff: Diffing Newton/Demos/SDLVehicle
+cvs diff: Diffing Newton/Demos/Tutorial 1
+cvs diff: Diffing Newton/Demos/Tutorial 1/images
+cvs diff: Diffing Newton/Demos/common
+cvs diff: Diffing Newton/Pas
+cvs diff: Diffing ODE
+cvs diff: Diffing ODE/Demos
+cvs diff: Diffing ODE/Demos/RagDoll
+Index: ODE/Demos/RagDoll/JEDISDLRagDoll.dpr
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/ODE/Demos/RagDoll/JEDISDLRagDoll.dpr,v
+retrieving revision 1.3
+diff -u -r1.3 JEDISDLRagDoll.dpr
+--- ODE/Demos/RagDoll/JEDISDLRagDoll.dpr	20 May 2007 20:27:45 -0000	1.3
++++ ODE/Demos/RagDoll/JEDISDLRagDoll.dpr	27 Feb 2008 09:16:11 -0000
+@@ -83,8 +83,7 @@
+   glext,
+   logger,
+   sdl,
+-  odeimport,
+-  ragdoll;
++  odeimport;
+ 
+ const
+   // screen width, height, and bit depth
+cvs diff: Diffing ODE/Demos/TruckOff
+cvs diff: Diffing ODE/Demos/TruckOff/images
+cvs diff: Diffing ODE/Pas
+cvs diff: Diffing OpenGL
+cvs diff: Diffing OpenGL/Pas
+cvs diff: Diffing PixelPrachtFX
+cvs diff: Diffing PixelPrachtFX/Demo
+Index: PixelPrachtFX/Demo/Textures.pas
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/PixelPrachtFX/Demo/Textures.pas,v
+retrieving revision 1.2
+diff -u -r1.2 Textures.pas
+--- PixelPrachtFX/Demo/Textures.pas	20 Dec 2005 20:26:54 -0000	1.2
++++ PixelPrachtFX/Demo/Textures.pas	27 Feb 2008 09:16:11 -0000
+@@ -33,25 +33,6 @@
+ implementation
+ 
+ {------------------------------------------------------------------}
+-{  Swap bitmap format from BGR to RGB                              }
+-{------------------------------------------------------------------}
+-procedure SwapRGB(data : Pointer; Size : Integer);
+-asm
+-  mov ebx, eax
+-  mov ecx, size
+-
+-@@loop :
+-  mov al,[ebx+0]
+-  mov ah,[ebx+2]
+-  mov [ebx+2],al
+-  mov [ebx+0],ah
+-  add ebx,3
+-  dec ecx
+-  jnz @@loop
+-end;
+-
+-
+-{------------------------------------------------------------------}
+ {  Create the Texture                                              }
+ {------------------------------------------------------------------}
+ function CreateTexture(Width, Height, Format : Word; pData : Pointer) : Integer;
+Index: PixelPrachtFX/Demo/fxBurn.pas
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/PixelPrachtFX/Demo/fxBurn.pas,v
+retrieving revision 1.1
+diff -u -r1.1 fxBurn.pas
+--- PixelPrachtFX/Demo/fxBurn.pas	5 Dec 2005 01:09:29 -0000	1.1
++++ PixelPrachtFX/Demo/fxBurn.pas	27 Feb 2008 09:16:11 -0000
+@@ -2,7 +2,7 @@
+ 
+ interface
+ 
+-uses ppFXcore, ppFXlib, textures, gl;
++uses ppFXcore, ppFXlib, Textures, gl;
+ 
+ type
+ 
+cvs diff: Diffing PixelPrachtFX/Demo/gfx
+cvs diff: Diffing PixelPrachtFX/Pas
+cvs diff: Diffing SDL
+cvs diff: Diffing SDL/Pas
+Index: SDL/Pas/sdl.pas
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/SDL/Pas/sdl.pas,v
+retrieving revision 1.38
+diff -u -r1.38 sdl.pas
+--- SDL/Pas/sdl.pas	26 Jan 2008 10:09:32 -0000	1.38
++++ SDL/Pas/sdl.pas	27 Feb 2008 09:16:11 -0000
+@@ -355,6 +355,12 @@
+   GPCMacOSAll;
+ {$ENDIF}
+ 
++{$ifndef FPC}
++type
++  PtrInt = LongInt;
++  PtrUInt = LongWord;
++{$endif}
++
+ const
+ {$IFDEF WINDOWS}
+   SDLLibName = 'SDL.dll';
+Index: SDL/Pas/sdlutils.pas
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/SDL/Pas/sdlutils.pas,v
+retrieving revision 1.5
+diff -u -r1.5 sdlutils.pas
+--- SDL/Pas/sdlutils.pas	19 Nov 2006 18:56:44 -0000	1.5
++++ SDL/Pas/sdlutils.pas	27 Feb 2008 09:16:12 -0000
+@@ -260,7 +260,7 @@
+   right2, bottom2 : integer;
+   Scan1Start, Scan2Start, ScanWidth, ScanHeight : cardinal;
+   Mod1, Mod2   : cardinal;
+-  Addr1, Addr2 : cardinal;
++  Addr1, Addr2 : PtrUInt;
+   BPP          : cardinal;
+   Pitch1, Pitch2 : cardinal;
+   TransparentColor1, TransparentColor2 : cardinal;
+@@ -329,7 +329,7 @@
+   with SrcSurface1^ do
+   begin
+     Pitch1 := Pitch;
+-    Addr1 := cardinal( Pixels );
++    Addr1 := PtrUInt( Pixels );
+     inc( Addr1, Pitch1 * UInt32( Src_Rect1.y ) );
+     with format^ do
+     begin
+@@ -341,7 +341,7 @@
+   begin
+     TransparentColor2 := format.colorkey;
+     Pitch2 := Pitch;
+-    Addr2 := cardinal( Pixels );
++    Addr2 := PtrUInt( Pixels );
+     inc( Addr2, Pitch2 * UInt32( Src_Rect2.y ) );
+   end;
+   Mod1 := Pitch1 - ( ScanWidth * BPP );
+@@ -442,14 +442,14 @@
+   cardinal );
+ var
+   SrcColor     : cardinal;
+-  Addr         : cardinal;
++  Addr         : PtrUInt;
+   R, G, B      : cardinal;
+ begin
+   if Color = 0 then
+     exit;
+   with DstSurface^ do
+   begin
+-    Addr := cardinal( Pixels ) + y * Pitch + x * format.BytesPerPixel;
++    Addr := PtrUInt( Pixels ) + y * Pitch + x * format.BytesPerPixel;
+     SrcColor := PUInt32( Addr )^;
+     case format.BitsPerPixel of
+       8 :
+@@ -525,14 +525,14 @@
+   cardinal );
+ var
+   SrcColor     : cardinal;
+-  Addr         : cardinal;
++  Addr         : PtrUInt;
+   R, G, B      : cardinal;
+ begin
+   if Color = 0 then
+     exit;
+   with DstSurface^ do
+   begin
+-    Addr := cardinal( Pixels ) + y * Pitch + x * format.BytesPerPixel;
++    Addr := PtrUInt( Pixels ) + y * Pitch + x * format.BytesPerPixel;
+     SrcColor := PUInt32( Addr )^;
+     case format.BitsPerPixel of
+       8 :
+@@ -613,7 +613,7 @@
+   R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+   Src, Dest    : TSDL_Rect;
+   Diff         : integer;
+-  SrcAddr, DestAddr : cardinal;
++  SrcAddr, DestAddr : PtrUInt;
+   WorkX, WorkY : word;
+   SrcMod, DestMod : cardinal;
+   Bits         : cardinal;
+@@ -686,14 +686,14 @@
+   end;
+   with SrcSurface^ do
+   begin
+-    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
++    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+       Format.BytesPerPixel;
+     SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+     TransparentColor := Format.colorkey;
+   end;
+   with DestSurface^ do
+   begin
+-    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
++    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+       Format.BytesPerPixel;
+     DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+     Bits := Format.BitsPerPixel;
+@@ -883,7 +883,7 @@
+   R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+   Src, Dest    : TSDL_Rect;
+   Diff         : integer;
+-  SrcAddr, DestAddr : cardinal;
++  SrcAddr, DestAddr : PtrUInt;
+   _ebx, _esi, _edi, _esp : cardinal;
+   WorkX, WorkY : word;
+   SrcMod, DestMod : cardinal;
+@@ -957,14 +957,14 @@
+   end;
+   with SrcSurface^ do
+   begin
+-    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
++    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+       Format.BytesPerPixel;
+     SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+     TransparentColor := Format.colorkey;
+   end;
+   with DestSurface^ do
+   begin
+-    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
++    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+       Format.BytesPerPixel;
+     DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+     Bits := DestSurface.Format.BitsPerPixel;
+@@ -1145,7 +1145,7 @@
+ var
+   Src, Dest    : TSDL_Rect;
+   Diff         : integer;
+-  SrcAddr, DestAddr : cardinal;
++  SrcAddr, DestAddr : PtrUInt;
+   _ebx, _esi, _edi, _esp : cardinal;
+   WorkX, WorkY : word;
+   SrcMod, DestMod : cardinal;
+@@ -1220,14 +1220,14 @@
+   end;
+   with SrcSurface^ do
+   begin
+-    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
++    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+       Format.BytesPerPixel;
+     SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+     TransparentColor := Format.colorkey;
+   end;
+   with DestSurface^ do
+   begin
+-    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
++    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+       Format.BytesPerPixel;
+     DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+     BPP := DestSurface.Format.BytesPerPixel;
+@@ -1317,7 +1317,7 @@
+ var
+   Src, Dest    : TSDL_Rect;
+   Diff         : integer;
+-  SrcAddr, DestAddr, TextAddr : cardinal;
++  SrcAddr, DestAddr, TextAddr : PtrUInt;
+   _ebx, _esi, _edi, _esp : cardinal;
+   WorkX, WorkY : word;
+   SrcMod, DestMod, TextMod : cardinal;
+@@ -1392,21 +1392,21 @@
+   end;
+   with SrcSurface^ do
+   begin
+-    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
++    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+       Format.BytesPerPixel;
+     SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+     TransparentColor := format.colorkey;
+   end;
+   with DestSurface^ do
+   begin
+-    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
++    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+       Format.BytesPerPixel;
+     DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+     BPP := DestSurface.Format.BitsPerPixel;
+   end;
+   with Texture^ do
+   begin
+-    TextAddr := cardinal( Pixels ) + UInt32( TextureRect.y ) * Pitch +
++    TextAddr := PtrUInt( Pixels ) + UInt32( TextureRect.y ) * Pitch +
+       UInt32( TextureRect.x ) * Format.BytesPerPixel;
+     TextMod := Pitch - Src.w * Format.BytesPerPixel;
+   end;
+@@ -1910,17 +1910,17 @@
+     end
+     else
+       Locked := false;
+-    Row1 := pointer( cardinal( DstSurface^.Pixels ) + UInt32( Rect^.y ) *
++    Row1 := pointer( PtrUInt( DstSurface^.Pixels ) + UInt32( Rect^.y ) *
+       DstSurface^.Pitch );
+-    Row2 := pointer( cardinal( DstSurface^.Pixels ) + ( UInt32( Rect^.y ) + Rect^.h - 1 )
++    Row2 := pointer( PtrUInt( DstSurface^.Pixels ) + ( UInt32( Rect^.y ) + Rect^.h - 1 )
+       * DstSurface^.Pitch );
+     for y := 0 to FlipLength do
+     begin
+       Move( Row1^, OneRow, RowLength );
+       Move( Row2^, Row1^, RowLength );
+       Move( OneRow, Row2^, RowLength );
+-      inc( cardinal( Row1 ), DstSurface^.Pitch );
+-      dec( cardinal( Row2 ), DstSurface^.Pitch );
++      inc( PtrUInt( Row1 ), DstSurface^.Pitch );
++      dec( PtrUInt( Row2 ), DstSurface^.Pitch );
+     end;
+     if Locked then
+       SDL_UnlockSurface( DstSurface );
+@@ -1965,7 +1965,7 @@
+     case DstSurface^.format.BytesPerPixel of
+       1 :
+         begin
+-          Row8Bit := pointer( cardinal( DstSurface^.pixels ) + UInt32( Rect^.y ) *
++          Row8Bit := pointer( PtrUInt( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+             DstSurface^.pitch );
+           for y := 1 to Rect^.h do
+           begin
+@@ -1977,12 +1977,12 @@
+               Row8Bit^[ RightSide ] := Pixel;
+               dec( RightSide );
+             end;
+-            inc( cardinal( Row8Bit ), DstSurface^.pitch );
++            inc( PtrUInt( Row8Bit ), DstSurface^.pitch );
+           end;
+         end;
+       2 :
+         begin
+-          Row16Bit := pointer( cardinal( DstSurface^.pixels ) + UInt32( Rect^.y ) *
++          Row16Bit := pointer( PtrUInt( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+             DstSurface^.pitch );
+           for y := 1 to Rect^.h do
+           begin
+@@ -1994,12 +1994,12 @@
+               Row16Bit^[ RightSide ] := Pixel;
+               dec( RightSide );
+             end;
+-            inc( cardinal( Row16Bit ), DstSurface^.pitch );
++            inc( PtrUInt( Row16Bit ), DstSurface^.pitch );
+           end;
+         end;
+       3 :
+         begin
+-          Row24Bit := pointer( cardinal( DstSurface^.pixels ) + UInt32( Rect^.y ) *
++          Row24Bit := pointer( PtrUInt( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+             DstSurface^.pitch );
+           for y := 1 to Rect^.h do
+           begin
+@@ -2011,12 +2011,12 @@
+               Row24Bit^[ RightSide ] := Pixel24;
+               dec( RightSide );
+             end;
+-            inc( cardinal( Row24Bit ), DstSurface^.pitch );
++            inc( PtrUInt( Row24Bit ), DstSurface^.pitch );
+           end;
+         end;
+       4 :
+         begin
+-          Row32Bit := pointer( cardinal( DstSurface^.pixels ) + UInt32( Rect^.y ) *
++          Row32Bit := pointer( PtrUInt( DstSurface^.pixels ) + UInt32( Rect^.y ) *
+             DstSurface^.pitch );
+           for y := 1 to Rect^.h do
+           begin
+@@ -2028,7 +2028,7 @@
+               Row32Bit^[ RightSide ] := Pixel;
+               dec( RightSide );
+             end;
+-            inc( cardinal( Row32Bit ), DstSurface^.pitch );
++            inc( PtrUInt( Row32Bit ), DstSurface^.pitch );
+           end;
+         end;
+     end;
+@@ -2088,8 +2088,8 @@
+   dx2 := dx shl 1;
+   src_pitch := Surface^.pitch;
+   dst_pitch := dst_surface^.pitch;
+-  src_pixels := PUint8( integer( Surface^.pixels ) + yr * src_pitch + y1 * depth );
+-  dst_pixels := PUint8( integer( dst_surface^.pixels ) + yw * dst_pitch + x1 *
++  src_pixels := PUint8( PtrUInt( Surface^.pixels ) + yr * src_pitch + y1 * depth );
++  dst_pixels := PUint8( PtrUInt( dst_surface^.pixels ) + yw * dst_pitch + x1 *
+     depth );
+   for d := 0 to dx - 1 do
+   begin
+@@ -2166,9 +2166,9 @@
+   src_pixels, dst_pixels : PUint8;
+   i            : integer;
+ begin
+-  src_pixels := PUint8( integer( Surface^.pixels ) + Surface^.w * y1 * depth + x2 *
++  src_pixels := PUint8( PtrUInt( Surface^.pixels ) + Surface^.w * y1 * depth + x2 *
+     depth );
+-  dst_pixels := PUint8( integer( Surface^.pixels ) + Surface^.w * y1 * depth + ( x2
++  dst_pixels := PUint8( PtrUInt( Surface^.pixels ) + Surface^.w * y1 * depth + ( x2
+     + xofs ) * depth );
+   for i := x2 downto x1 do
+   begin
+@@ -2187,7 +2187,7 @@
+ begin
+   bpp := SrcSurface.format.BytesPerPixel;
+   // Here p is the address to the pixel we want to retrieve
+-  p := Pointer( Uint32( SrcSurface.pixels ) + UInt32( y ) * SrcSurface.pitch + UInt32( x ) *
++  p := Pointer( PtrUInt( SrcSurface.pixels ) + UInt32( y ) * SrcSurface.pitch + UInt32( x ) *
+     bpp );
+   case bpp of
+     1 : result := PUint8( p )^;
+@@ -2214,7 +2214,7 @@
+   p            : PInteger;
+ begin
+   bpp := DstSurface.format.BytesPerPixel;
+-  p := Pointer( Uint32( DstSurface.pixels ) + UInt32( y ) * DstSurface.pitch + UInt32( x )
++  p := Pointer( PtrUInt( DstSurface.pixels ) + UInt32( y ) * DstSurface.pitch + UInt32( x )
+     * bpp );
+   case bpp of
+     1 : PUint8( p )^ := pixel;
+@@ -2480,7 +2480,7 @@
+     BPP := DstSurface.format.BytesPerPixel;
+     with DstSurface^ do
+     begin
+-      Addr := pointer( UInt32( pixels ) + UInt32( RealRect.y ) * pitch + UInt32( RealRect.x ) * BPP );
++      Addr := pointer( PtrUInt( pixels ) + UInt32( RealRect.y ) * pitch + UInt32( RealRect.x ) * BPP );
+       ModX := Pitch - UInt32( RealRect.w ) * BPP;
+     end;
+     case DstSurface.format.BitsPerPixel of
+@@ -2501,9 +2501,9 @@
+               if B > $03 then
+                 B := $03;
+               PUInt8( Addr )^ := R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+       15 :
+@@ -2523,9 +2523,9 @@
+               if B > $001F then
+                 B := $001F;
+               PUInt16( Addr )^ := R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+       16 :
+@@ -2545,9 +2545,9 @@
+               if B > $001F then
+                 B := $001F;
+               PUInt16( Addr )^ := R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+       24 :
+@@ -2567,9 +2567,9 @@
+               if B > $0000FF then
+                 B := $0000FF;
+               PUInt32( Addr )^ := SrcColor and $FF000000 or R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+       32 :
+@@ -2589,9 +2589,9 @@
+               if B > $0000FF then
+                 B := $0000FF;
+               PUInt32( Addr )^ := R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+     end;
+@@ -2613,7 +2613,7 @@
+     BPP := DstSurface.format.BytesPerPixel;
+     with DstSurface^ do
+     begin
+-      Addr := pointer( UInt32( pixels ) + UInt32( RealRect.y ) * pitch + UInt32( RealRect.x ) * BPP );
++      Addr := pointer( PtrUInt( pixels ) + UInt32( RealRect.y ) * pitch + UInt32( RealRect.x ) * BPP );
+       ModX := Pitch - UInt32( RealRect.w ) * BPP;
+     end;
+     case DstSurface.format.BitsPerPixel of
+@@ -2634,9 +2634,9 @@
+               if B > $03 then
+                 B := 0;
+               PUInt8( Addr )^ := R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+       15 :
+@@ -2656,9 +2656,9 @@
+               if B > $001F then
+                 B := 0;
+               PUInt16( Addr )^ := R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+       16 :
+@@ -2678,9 +2678,9 @@
+               if B > $001F then
+                 B := 0;
+               PUInt16( Addr )^ := R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+       24 :
+@@ -2700,9 +2700,9 @@
+               if B > $0000FF then
+                 B := 0;
+               PUInt32( Addr )^ := SrcColor and $FF000000 or R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+       32 :
+@@ -2722,9 +2722,9 @@
+               if B > $0000FF then
+                 B := 0;
+               PUInt32( Addr )^ := R or G or B;
+-              inc( UInt32( Addr ), BPP );
++              inc( PtrUInt( Addr ), BPP );
+             end;
+-            inc( UInt32( Addr ), ModX );
++            inc( PtrUInt( Addr ), ModX );
+           end;
+         end;
+     end;
+@@ -2800,7 +2800,7 @@
+ 
+ procedure SDL_2xBlit( Src, Dest : PSDL_Surface );
+ var
+-  ReadAddr, WriteAddr, ReadRow, WriteRow : UInt32;
++  ReadAddr, WriteAddr, ReadRow, WriteRow : PtrUInt;
+   SrcPitch, DestPitch, x, y : UInt32;
+ begin
+   if ( Src = nil ) or ( Dest = nil ) then
+@@ -2815,8 +2815,8 @@
+   if SDL_MustLock( Dest ) then
+     SDL_LockSurface( Dest );
+ 
+-  ReadRow := UInt32( Src.Pixels );
+-  WriteRow := UInt32( Dest.Pixels );
++  ReadRow := PtrUInt( Src.Pixels );
++  WriteRow := PtrUInt( Dest.Pixels );
+ 
+   SrcPitch := Src.pitch;
+   DestPitch := Dest.pitch;
+@@ -2835,8 +2835,8 @@
+           inc( ReadAddr );
+           inc( WriteAddr, 2 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     2 : for y := 1 to Src.h do
+       begin
+@@ -2851,8 +2851,8 @@
+           inc( ReadAddr, 2 );
+           inc( WriteAddr, 4 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     3 : for y := 1 to Src.h do
+       begin
+@@ -2867,8 +2867,8 @@
+           inc( ReadAddr, 3 );
+           inc( WriteAddr, 6 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     4 : for y := 1 to Src.h do
+       begin
+@@ -2883,8 +2883,8 @@
+           inc( ReadAddr, 4 );
+           inc( WriteAddr, 8 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+   end;
+ 
+@@ -2896,7 +2896,7 @@
+ 
+ procedure SDL_Scanline2xBlit( Src, Dest : PSDL_Surface );
+ var
+-  ReadAddr, WriteAddr, ReadRow, WriteRow : UInt32;
++  ReadAddr, WriteAddr, ReadRow, WriteRow : PtrUInt;
+   SrcPitch, DestPitch, x, y : UInt32;
+ begin
+   if ( Src = nil ) or ( Dest = nil ) then
+@@ -2911,8 +2911,8 @@
+   if SDL_MustLock( Dest ) then
+     SDL_LockSurface( Dest );
+ 
+-  ReadRow := UInt32( Src.Pixels );
+-  WriteRow := UInt32( Dest.Pixels );
++  ReadRow := PtrUInt( Src.Pixels );
++  WriteRow := PtrUInt( Dest.Pixels );
+ 
+   SrcPitch := Src.pitch;
+   DestPitch := Dest.pitch;
+@@ -2929,8 +2929,8 @@
+           inc( ReadAddr );
+           inc( WriteAddr, 2 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     2 : for y := 1 to Src.h do
+       begin
+@@ -2943,8 +2943,8 @@
+           inc( ReadAddr, 2 );
+           inc( WriteAddr, 4 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     3 : for y := 1 to Src.h do
+       begin
+@@ -2957,8 +2957,8 @@
+           inc( ReadAddr, 3 );
+           inc( WriteAddr, 6 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     4 : for y := 1 to Src.h do
+       begin
+@@ -2971,8 +2971,8 @@
+           inc( ReadAddr, 4 );
+           inc( WriteAddr, 8 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+   end;
+ 
+@@ -2984,7 +2984,7 @@
+ 
+ procedure SDL_50Scanline2xBlit( Src, Dest : PSDL_Surface );
+ var
+-  ReadAddr, WriteAddr, ReadRow, WriteRow : UInt32;
++  ReadAddr, WriteAddr, ReadRow, WriteRow : PtrUInt;
+   SrcPitch, DestPitch, x, y, Color : UInt32;
+ begin
+   if ( Src = nil ) or ( Dest = nil ) then
+@@ -2999,8 +2999,8 @@
+   if SDL_MustLock( Dest ) then
+     SDL_LockSurface( Dest );
+ 
+-  ReadRow := UInt32( Src.Pixels );
+-  WriteRow := UInt32( Dest.Pixels );
++  ReadRow := PtrUInt( Src.Pixels );
++  WriteRow := PtrUInt( Dest.Pixels );
+ 
+   SrcPitch := Src.pitch;
+   DestPitch := Dest.pitch;
+@@ -3021,8 +3021,8 @@
+           inc( ReadAddr );
+           inc( WriteAddr, 2 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     15 : for y := 1 to Src.h do
+       begin
+@@ -3039,8 +3039,8 @@
+           inc( ReadAddr, 2 );
+           inc( WriteAddr, 4 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     16 : for y := 1 to Src.h do
+       begin
+@@ -3057,8 +3057,8 @@
+           inc( ReadAddr, 2 );
+           inc( WriteAddr, 4 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     24 : for y := 1 to Src.h do
+       begin
+@@ -3075,8 +3075,8 @@
+           inc( ReadAddr, 3 );
+           inc( WriteAddr, 6 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+     32 : for y := 1 to Src.h do
+       begin
+@@ -3093,8 +3093,8 @@
+           inc( ReadAddr, 4 );
+           inc( WriteAddr, 8 );
+         end;
+-        inc( UInt32( ReadRow ), SrcPitch );
+-        inc( UInt32( WriteRow ), DestPitch * 2 );
++        inc( PtrUInt( ReadRow ), SrcPitch );
++        inc( PtrUInt( WriteRow ), DestPitch * 2 );
+       end;
+   end;
+ 
+@@ -3113,7 +3113,7 @@
+   right2, bottom2 : integer;
+   Scan1Start, {Scan2Start,} ScanWidth, ScanHeight : cardinal;
+   Mod1         : cardinal;
+-  Addr1        : cardinal;
++  Addr1        : PtrUInt;
+   BPP          : cardinal;
+   Pitch1       : cardinal;
+   TransparentColor1 : cardinal;
+@@ -3171,7 +3171,7 @@
+   with SrcSurface1^ do
+   begin
+     Pitch1 := Pitch;
+-    Addr1 := cardinal( Pixels );
++    Addr1 := PtrUInt( Pixels );
+     inc( Addr1, Pitch1 * UInt32( Src_Rect1.y ) );
+     with format^ do
+     begin
+@@ -3277,7 +3277,7 @@
+   R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+   Src, Dest    : TSDL_Rect;
+   Diff         : integer;
+-  SrcAddr, DestAddr : cardinal;
++  SrcAddr, DestAddr : PtrUInt;
+   WorkX, WorkY : word;
+   SrcMod, DestMod : cardinal;
+   Bits         : cardinal;
+@@ -3350,14 +3350,14 @@
+   end;
+   with SrcSurface^ do
+   begin
+-    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
++    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+       Format.BytesPerPixel;
+     SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+     TransparentColor := Format.colorkey;
+   end;
+   with DestSurface^ do
+   begin
+-    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
++    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+       Format.BytesPerPixel;
+     DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+     Bits := Format.BitsPerPixel;
+@@ -3483,7 +3483,7 @@
+   R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+   Src, Dest    : TSDL_Rect;
+   Diff         : integer;
+-  SrcAddr, DestAddr : cardinal;
++  SrcAddr, DestAddr : PtrUInt;
+   WorkX, WorkY : word;
+   SrcMod, DestMod : cardinal;
+   Bits         : cardinal;
+@@ -3556,14 +3556,14 @@
+   end;
+   with SrcSurface^ do
+   begin
+-    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
++    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+       Format.BytesPerPixel;
+     SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+     TransparentColor := Format.colorkey;
+   end;
+   with DestSurface^ do
+   begin
+-    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
++    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+       Format.BytesPerPixel;
+     DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+     Bits := Format.BitsPerPixel;
+@@ -3691,7 +3691,7 @@
+   R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+   Src, Dest    : TSDL_Rect;
+   Diff         : integer;
+-  SrcAddr, DestAddr : cardinal;
++  SrcAddr, DestAddr : PtrUInt;
+   WorkX, WorkY : word;
+   SrcMod, DestMod : cardinal;
+   Bits         : cardinal;
+@@ -3764,14 +3764,14 @@
+   end;
+   with SrcSurface^ do
+   begin
+-    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
++    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+       Format.BytesPerPixel;
+     SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+     TransparentColor := Format.colorkey;
+   end;
+   with DestSurface^ do
+   begin
+-    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
++    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+       Format.BytesPerPixel;
+     DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+     Bits := Format.BitsPerPixel;
+@@ -3992,7 +3992,7 @@
+   R, G, B, Pixel1, Pixel2, TransparentColor : cardinal;
+   Src, Dest    : TSDL_Rect;
+   Diff         : integer;
+-  SrcAddr, DestAddr : cardinal;
++  SrcAddr, DestAddr : PtrUInt;
+   WorkX, WorkY : word;
+   SrcMod, DestMod : cardinal;
+   Bits         : cardinal;
+@@ -4065,14 +4065,14 @@
+   end;
+   with SrcSurface^ do
+   begin
+-    SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
++    SrcAddr := PtrUInt( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
+       Format.BytesPerPixel;
+     SrcMod := Pitch - Src.w * Format.BytesPerPixel;
+     TransparentColor := Format.colorkey;
+   end;
+   with DestSurface^ do
+   begin
+-    DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
++    DestAddr := PtrUInt( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
+       Format.BytesPerPixel;
+     DestMod := Pitch - Dest.w * Format.BytesPerPixel;
+     Bits := Format.BitsPerPixel;
+cvs diff: Diffing SDLCtrls
+cvs diff: Diffing SDLCtrls/Demos
+cvs diff: Diffing SDLCtrls/Demos/SDLCtrls
+cvs diff: Diffing SDLCtrls/Demos/SDLCtrls/Graphic
+cvs diff: Diffing SDLCtrls/Pas
+cvs diff: Diffing SDLCtrls/Tools
+cvs diff: Diffing SDLCtrls/Tools/SDLFDesign
+cvs diff: Diffing SDLCtrls/Tools/SDLFDesign/Data
+cvs diff: Diffing SDLCtrls/Tools/SDLFDesign/Source
+cvs diff: Diffing SDLCtrls/Tools/SDLImages
+cvs diff: Diffing SDLCtrls/Tools/SGFont
+cvs diff: Diffing SDLCtrls/Tools/SGFont/SGFontConv
+cvs diff: Diffing SDLCtrls/docs
+cvs diff: Diffing SDLCtrls/docs/images
+cvs diff: Diffing SDLCtrls/zlib
+cvs diff: Diffing SDLFilter
+cvs diff: Diffing SDLFilter/Demos
+cvs diff: Diffing SDLFilter/Demos/Test
+cvs diff: Diffing SDLFilter/Demos/Test/images
+cvs diff: Diffing SDLFilter/Pas
+cvs diff: Diffing SDLMonoFonts
+cvs diff: Diffing SDLMonoFonts/Demos
+cvs diff: Diffing SDLMonoFonts/Demos/Test
+cvs diff: Diffing SDLMonoFonts/Images
+cvs diff: Diffing SDLMonoFonts/Pas
+Index: SDLMonoFonts/Pas/sdlmonofonts.pas
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/SDLMonoFonts/Pas/sdlmonofonts.pas,v
+retrieving revision 1.3
+diff -u -r1.3 sdlmonofonts.pas
+--- SDLMonoFonts/Pas/sdlmonofonts.pas	26 Nov 2006 10:25:19 -0000	1.3
++++ SDLMonoFonts/Pas/sdlmonofonts.pas	27 Feb 2008 09:16:12 -0000
+@@ -152,7 +152,7 @@
+     end;
+     inc( ReadPos );
+   until ReadPos >= TextLength;
+-  FoundWord := pointer( cardinal( Txt ) + StartPos );
++  FoundWord := pointer( PtrUInt( Txt ) + StartPos );
+   ItsLength := ReadPos - StartPos;
+ end;
+ 
+cvs diff: Diffing SDLSpriteEngine
+cvs diff: Diffing SDLSpriteEngine/Demos
+cvs diff: Diffing SDLSpriteEngine/Demos/CollisionTest
+cvs diff: Diffing SDLSpriteEngine/Demos/Oxygene
+cvs diff: Diffing SDLSpriteEngine/Demos/Oxygene/Caverns
+cvs diff: Diffing SDLSpriteEngine/Demos/Oxygene/Gfx
+cvs diff: Diffing SDLSpriteEngine/Demos/Oxygene/Music
+cvs diff: Diffing SDLSpriteEngine/Demos/Oxygene/Sounds
+cvs diff: Diffing SDLSpriteEngine/Demos/Shooting
+Index: SDLSpriteEngine/Demos/Shooting/Shooting.dpr
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/SDLSpriteEngine/Demos/Shooting/Shooting.dpr,v
+retrieving revision 1.2
+diff -u -r1.2 Shooting.dpr
+--- SDLSpriteEngine/Demos/Shooting/Shooting.dpr	23 Dec 2004 23:37:27 -0000	1.2
++++ SDLSpriteEngine/Demos/Shooting/Shooting.dpr	27 Feb 2008 09:16:13 -0000
+@@ -445,13 +445,13 @@
+   y : integer;
+   Row : array[ 0..319 ] of byte;
+   MustLock : boolean;
+-  Video1, Video2 : cardinal;
++  Video1, Video2 : PtrUInt;
+ begin
+   MustLock := SDL_MustLock( Background );
+   if MustLock then
+     SDL_LockSurface( Background );
+-  Video1 := cardinal( Background.pixels ) + 238 * Background.pitch; { from }
+-  Video2 := cardinal( Background.pixels ) + 239 * Background.pitch; { to }
++  Video1 := PtrUInt( Background.pixels ) + 238 * Background.pitch; { from }
++  Video2 := PtrUInt( Background.pixels ) + 239 * Background.pitch; { to }
+   { store lowest row }
+   Move( pointer( Video2 )^, Row[ 0 ], 320 );
+   for y := 0 to 238 do
+cvs diff: Diffing SDLSpriteEngine/Demos/ZTest
+cvs diff: Diffing SDLSpriteEngine/Demos/images
+cvs diff: Diffing SDLSpriteEngine/Pas
+cvs diff: Diffing SDL_Gfx
+cvs diff: Diffing SDL_Gfx/Pas
+cvs diff: Diffing SDL_Image
+cvs diff: Diffing SDL_Image/Pas
+cvs diff: Diffing SDL_Mixer
+cvs diff: Diffing SDL_Mixer/Demos
+cvs diff: Diffing SDL_Mixer/Demos/WavTest
+cvs diff: Diffing SDL_Mixer/Pas
+cvs diff: Diffing SDL_Net
+cvs diff: Diffing SDL_Net/Demos
+cvs diff: Diffing SDL_Net/Demos/Clients
+cvs diff: Diffing SDL_Net/Demos/Clients/TCPConsole
+cvs diff: Diffing SDL_Net/Demos/Clients/TCPGUI
+cvs diff: Diffing SDL_Net/Demos/Clients/TimeSync
+cvs diff: Diffing SDL_Net/Demos/Clients/UDPConsole
+cvs diff: Diffing SDL_Net/Demos/Servers
+cvs diff: Diffing SDL_Net/Demos/Servers/TCPMulti
+cvs diff: Diffing SDL_Net/Demos/Servers/TimeSync
+cvs diff: Diffing SDL_Net/Demos/Servers/UDP
+cvs diff: Diffing SDL_Net/Demos/WebUpdate
+cvs diff: Diffing SDL_Net/Demos/WebUpdate/fonts
+cvs diff: Diffing SDL_Net/Demos/WebUpdate/images
+cvs diff: Diffing SDL_Net/Pas
+cvs diff: Diffing SDL_Sound
+cvs diff: Diffing SDL_Sound/Pas
+cvs diff: Diffing SDL_flic
+cvs diff: Diffing SDL_flic/Demo
+cvs diff: Diffing SDL_flic/Pas
+Index: SDL_flic/Pas/sdl_flic.pas
+===================================================================
+RCS file: /cvsroot/jedi-sdl/JEDI-SDLv1.0/SDL_flic/Pas/sdl_flic.pas,v
+retrieving revision 1.1
+diff -u -r1.1 sdl_flic.pas
+--- SDL_flic/Pas/sdl_flic.pas	4 Jan 2006 00:49:06 -0000	1.1
++++ SDL_flic/Pas/sdl_flic.pas	27 Feb 2008 09:16:14 -0000
+@@ -276,16 +276,16 @@
+ var line , p: PUInt8;
+     numlines, numpackets, size: Integer;
+ begin
+-  line :=PUint8( Integer(flic.Surface.pixels) + readu16(flic) * flic.Surface.pitch);
++  line :=PUint8( PtrInt(flic.Surface.pixels) + readu16(flic) * flic.Surface.pitch);
+   numlines := readu16(flic);
+   while (numlines > 0) do
+   begin
+     p := line;
+-    line := PUint8(Integer(line) + flic.Surface.pitch);
++    line := PUint8(PtrInt(line) + flic.Surface.pitch);
+     numpackets := readu8(flic);
+     while numpackets > 0 do
+     begin
+-      p := PUint8(Integer(p)+ readu8(flic));
++      p := PUint8(PtrInt(p)+ readu8(flic));
+       size := Sint8(readu8(flic));
+       if size >= 0 then
+         readbuffer(flic, p, size)
+@@ -294,7 +294,7 @@
+         size := -size;
+         FillChar(p^, size, readu8(flic));
+       end;
+-      p := PUint8(Integer(p) + Size);
++      p := PUint8(PtrInt(p) + Size);
+       dec(numpackets);
+     end;
+     dec(numlines);
+@@ -316,8 +316,8 @@
+   begin
+           //* The number of packages is ignored, packets run until the next line is reached. */
+     readu8(flic);
+-    next := PUint8(Integer(p) + flic.Surface.pitch);
+-    while (Integer(p) < Integer(next)) do
++    next := PUint8(PtrInt(p) + flic.Surface.pitch);
++    while (PtrInt(p) < PtrInt(next)) do
+     begin
+        // size pixels will change. */
+        size := SInt8(readu8(flic));
+@@ -332,7 +332,7 @@
+           //* One pixel to be repeated follow. */
+           FillChar(p^, size, readu8(flic));
+        end;
+-       p := PUint8(Integer(p) + size);
++       p := PUint8(PtrInt(p) + size);
+      end;
+      dec(numlines);
+   end;
+@@ -382,11 +382,11 @@
+     case ((code shr 14) and $03) of
+       $00:
+         begin
+-          p := PUint8(Uint32(flic.Surface.pixels) + flic.Surface.pitch * y);
++          p := PUint8(PtrUInt(flic.Surface.pixels) + flic.Surface.pitch * y);
+           while (code > 0) do
+           begin
+             // Skip some pixels.
+-            p := PUint8(Integer(p) + readu8(flic));
++            p := PUint8(PtrInt(p) + readu8(flic));
+             size := SInt8(readu8(flic)) * 2;
+             if (size >= 0) then
+             begin
+@@ -399,7 +399,7 @@
+               readu8(flic);
+               FillChar(p, size, readu8(flic));
+             end;
+-            p := PUint8(Integer(p)+size);
++            p := PUint8(PtrInt(p)+size);
+             dec(code);
+           end;
+           y := y + 1;
+@@ -409,7 +409,7 @@
+       $02:
+         begin
+           // Last pixel of the line. */
+-          p := Pointer(UInt32(flic.Surface.pixels) + flic.Surface.pitch * UInt32(y + 1));
++          p := Pointer(PtrUInt(flic.Surface.pixels) + flic.Surface.pitch * UInt32(y + 1));
+           //p[-1] = code & 0xFF;
+           PUint8(p^-1)^ := code and $FF;
+         end;
+cvs diff: Diffing SDL_ttf
+cvs diff: Diffing SDL_ttf/Demos
+cvs diff: Diffing SDL_ttf/Demos/GLFont
+cvs diff: Diffing SDL_ttf/Demos/ShowFont
+cvs diff: Diffing SDL_ttf/Pas
+cvs diff: Diffing SFont
+cvs diff: Diffing SFont/Demos
+cvs diff: Diffing SFont/Demos/Tests
+cvs diff: Diffing SFont/Demos/Tests/images
+cvs diff: Diffing SFont/Pas
+cvs diff: Diffing fmod
+cvs diff: Diffing fmod/Pas
+cvs diff: Diffing smpeg
+cvs diff: Diffing smpeg/Demos
+cvs diff: Diffing smpeg/Demos/GLMovie
+cvs diff: Diffing smpeg/Demos/MpegPlayer
+cvs diff: Diffing smpeg/Demos/SMpegPlayer
+cvs diff: Diffing smpeg/Pas
diff --git a/songmanagement/src/lib/JEDI-SDL/moduleloader-libc.patch b/songmanagement/src/lib/JEDI-SDL/moduleloader-libc.patch
new file mode 100644
index 00000000..02255db0
--- /dev/null
+++ b/songmanagement/src/lib/JEDI-SDL/moduleloader-libc.patch
@@ -0,0 +1,25 @@
+Index: SDL/Pas/moduleloader.pas
+===================================================================
+--- SDL/Pas/moduleloader.pas	(revision 1144)
++++ SDL/Pas/moduleloader.pas	(working copy)
+@@ -185,15 +185,16 @@
+ 
+ {$IFDEF Unix}
+ uses
+-{$ifdef Linux}
+-  Types,
+-  Libc;
+-{$else}
++{$ifdef FPC}
+   dl,
+   Types,
+   Baseunix,
+   Unix;
++{$else}
++  Types,
++  Libc;
+ {$endif}
++
+ type
+   // Handle to a loaded .so
+   TModuleHandle = Pointer;
diff --git a/songmanagement/src/lib/Lua/ULua.pas b/songmanagement/src/lib/Lua/ULua.pas
new file mode 100644
index 00000000..1de48a3c
--- /dev/null
+++ b/songmanagement/src/lib/Lua/ULua.pas
@@ -0,0 +1,1086 @@
+unit ULua;
+
+(*
+ * A complete Pascal wrapper for Lua 5.1 DLL module.
+ *
+ * Created by Geo Massar, 2006
+ * Distributed as free/open source.
+ *)
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$IFDEF UNIX}
+uses
+  dl,
+  UConfig;
+{$ENDIF}
+
+{$DEFINE LUA51}
+
+type
+  size_t   = type Cardinal;
+  Psize_t  = ^size_t;
+  PPointer = ^Pointer;
+
+  lua_State = record end;
+  Plua_State = ^lua_State;
+
+const
+{$IFDEF WIN32}
+  LuaDLL = 'lua5.1.dll';
+{$ENDIF}
+{$IFDEF UNIX}
+{$IFDEF DARWIN}
+  LuaDLL = 'liblua.5.1.dylib';
+  {$linklib liblua.5.1}
+{$ELSE}
+  LuaDLL = lua_lib_name;
+{$ENDIF}
+{$ENDIF}
+{$IFDEF MACOS}
+  SDLgfxLibName = 'lua5.1';
+{$ENDIF}
+
+(* formats for Lua numbers *)
+{$IFNDEF LUA_NUMBER_SCAN}
+const
+  LUA_NUMBER_SCAN = '%lf';
+{$ENDIF}
+
+{$IFNDEF LUA_NUMBER_FMT}
+const
+  LUA_NUMBER_FMT = '%.14g';
+{$ENDIF}
+
+(*****************************************************************************)
+(*                               luaconfig.h                                 *)
+(*****************************************************************************)
+
+(*
+** $Id: luaconf.h,v 1.81 2006/02/10 17:44:06 roberto Exp $
+** Configuration file for Lua
+** See Copyright Notice in lua.h
+*)
+
+(*
+** {==================================================================
+@@ LUA_NUMBER is the type of numbers in Lua.
+** CHANGE the following definitions only if you want to build Lua
+** with a number type different from double. You may also need to
+** change lua_number2int & lua_number2integer.
+** ===================================================================
+*)
+type
+  LUA_NUMBER_  = type Double;            // ending underscore is needed in Pascal
+  LUA_INTEGER_ = type Integer;
+
+(*
+@@ LUA_IDSIZE gives the maximum size for the description of the source
+@* of a function in debug information.
+** CHANGE it if you want a different size.
+*)
+const
+  LUA_IDSIZE = 60;
+
+(*
+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
+*)
+const
+  LUAL_BUFFERSIZE = 1024;
+
+(*
+@@ LUA_PROMPT is the default prompt used by stand-alone Lua.
+@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.
+** CHANGE them if you want different prompts. (You can also change the
+** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
+*)
+const
+  LUA_PROMPT  = '> ';
+  LUA_PROMPT2 = '>> ';
+
+(*
+@@ lua_readline defines how to show a prompt and then read a line from
+@* the standard input.
+@@ lua_saveline defines how to "save" a read line in a "history".
+@@ lua_freeline defines how to free a line read by lua_readline.
+** CHANGE them if you want to improve this functionality (e.g., by using
+** GNU readline and history facilities).
+*)
+function  lua_readline(L : Plua_State; var b : PChar; p : PChar): Boolean;
+procedure lua_saveline(L : Plua_State; idx : Integer);
+procedure lua_freeline(L : Plua_State; b : PChar);
+
+(*
+@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that
+@* is, whether we're running lua interactively).
+** CHANGE it if you have a better definition for non-POSIX/non-Windows
+** systems.
+*/
+#include <io.h>
+#include <stdio.h>
+#define lua_stdin_is_tty()	_isatty(_fileno(stdin))
+*)
+const
+  lua_stdin_is_tty = TRUE;
+
+(*****************************************************************************)
+(*                                  lua.h                                    *)
+(*****************************************************************************)
+
+(*
+** $Id: lua.h,v 1.216 2006/01/10 12:50:13 roberto Exp $
+** Lua - An Extensible Extension Language
+** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
+** See Copyright Notice at the end of this file
+*)
+
+const
+  LUA_VERSION     = 'Lua 5.1';
+  LUA_VERSION_NUM = 501;
+  LUA_COPYRIGHT   = 'Copyright (C) 1994-2006 Tecgraf, PUC-Rio';
+  LUA_AUTHORS     = 'R. Ierusalimschy, L. H. de Figueiredo & W. Celes';
+
+  (* mark for precompiled code (`<esc>Lua') *)
+  LUA_SIGNATURE = #27'Lua';
+
+  (* option for multiple returns in `lua_pcall' and `lua_call' *)
+  LUA_MULTRET = -1;
+
+  (*
+  ** pseudo-indices
+  *)
+  LUA_REGISTRYINDEX = -10000;
+  LUA_ENVIRONINDEX  = -10001;
+  LUA_GLOBALSINDEX  = -10002;
+
+function lua_upvalueindex(idx : Integer) : Integer;   // a marco
+
+const
+  (* thread status; 0 is OK *)
+  LUA_YIELD_    = 1;     // Note: the ending underscore is needed in Pascal
+  LUA_ERRRUN    = 2;
+  LUA_ERRSYNTAX = 3;
+  LUA_ERRMEM    = 4;
+  LUA_ERRERR    = 5;
+
+type
+  lua_CFunction = function(L : Plua_State) : Integer; cdecl;
+
+  (*
+  ** functions that read/write blocks when loading/dumping Lua chunks
+  *)
+  lua_Reader = function (L : Plua_State; ud : Pointer;
+                         sz : Psize_t) : PChar; cdecl;
+  lua_Writer = function (L : Plua_State; const p : Pointer; sz : size_t;
+                         ud : Pointer) : Integer; cdecl;
+
+  (*
+  ** prototype for memory-allocation functions
+  *)
+  lua_Alloc = function (ud, ptr : Pointer;
+                        osize, nsize : size_t) : Pointer; cdecl;
+
+const
+  (*
+  ** basic types
+  *)
+  LUA_TNONE          = -1;
+
+  LUA_TNIL           = 0;
+  LUA_TBOOLEAN       = 1;
+  LUA_TLIGHTUSERDATA = 2;
+  LUA_TNUMBER        = 3;
+  LUA_TSTRING        = 4;
+  LUA_TTABLE         = 5;
+  LUA_TFUNCTION      = 6;
+  LUA_TUSERDATA	     = 7;
+  LUA_TTHREAD        = 8;
+
+  (* minimum Lua stack available to a C function *)
+  LUA_MINSTACK = 20;
+
+type
+  (* type of numbers in Lua *)
+  lua_Number = LUA_NUMBER_;
+
+  (* type for integer functions *)
+  lua_Integer = LUA_INTEGER_;
+
+(*
+** state manipulation
+*)
+function  lua_newstate(f : lua_Alloc; ud : Pointer) : Plua_State;
+  cdecl; external LuaDLL;
+procedure lua_close(L: Plua_State);
+  cdecl; external LuaDLL;
+function  lua_newthread(L : Plua_State) : Plua_State;
+  cdecl; external LuaDLL;
+
+function  lua_atpanic(L : Plua_State; panicf : lua_CFunction) : lua_CFunction;
+  cdecl; external LuaDLL;
+
+
+(*
+** basic stack manipulation
+*)
+function  lua_gettop(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+procedure lua_settop(L : Plua_State; idx : Integer);
+  cdecl; external LuaDLL;
+procedure lua_pushvalue(L : Plua_State; idx : Integer);
+  cdecl; external LuaDLL;
+procedure lua_remove(L : Plua_State; idx : Integer);
+  cdecl; external LuaDLL;
+procedure lua_insert(L : Plua_State; idx : Integer);
+  cdecl; external LuaDLL;
+procedure lua_replace(L : Plua_State; idx : Integer);
+  cdecl; external LuaDLL;
+function  lua_checkstack(L : Plua_State; sz : Integer) : LongBool;
+  cdecl; external LuaDLL;
+
+procedure lua_xmove(src, dest : Plua_State; n : Integer);
+  cdecl; external LuaDLL;
+
+
+(*
+** access functions (stack -> C)
+*)
+function lua_isnumber(L : Plua_State; idx : Integer) : LongBool;
+  cdecl; external LuaDLL;
+function lua_isstring(L : Plua_State; idx : Integer) : LongBool;
+  cdecl; external LuaDLL;
+function lua_iscfunction(L : Plua_State; idx : Integer) : LongBool;
+  cdecl; external LuaDLL;
+function lua_isuserdata(L : Plua_State; idx : Integer) : LongBool;
+  cdecl; external LuaDLL;
+function lua_type(L : Plua_State; idx : Integer) : Integer;
+  cdecl; external LuaDLL;
+function lua_typename(L : Plua_State; tp : Integer) : PChar;
+  cdecl; external LuaDLL;
+
+function lua_equal(L : Plua_State; idx1, idx2 : Integer) : LongBool;
+  cdecl; external LuaDLL;
+function lua_rawequal(L : Plua_State; idx1, idx2 : Integer) : LongBool;
+  cdecl; external LuaDLL;
+function lua_lessthan(L : Plua_State; idx1, idx2 : Integer) : LongBool;
+  cdecl; external LuaDLL;
+
+function lua_tonumber(L : Plua_State; idx : Integer) : lua_Number;
+  cdecl; external LuaDLL;
+function lua_tointeger(L : Plua_State; idx : Integer) : lua_Integer;
+  cdecl; external LuaDLL;
+function lua_toboolean(L : Plua_State; idx : Integer) : LongBool;
+  cdecl; external LuaDLL;
+function lua_tolstring(L : Plua_State; idx : Integer;
+                       len : Psize_t) : PChar;
+  cdecl; external LuaDLL;
+function lua_objlen(L : Plua_State; idx : Integer) : size_t;
+  cdecl; external LuaDLL;
+function lua_tocfunction(L : Plua_State; idx : Integer) : lua_CFunction;
+  cdecl; external LuaDLL;
+function lua_touserdata(L : Plua_State; idx : Integer) : Pointer;
+  cdecl; external LuaDLL;
+function lua_tothread(L : Plua_State; idx : Integer) : Plua_State;
+  cdecl; external LuaDLL;
+function lua_topointer(L : Plua_State; idx : Integer) : Pointer;
+  cdecl; external LuaDLL;
+
+
+(*
+** push functions (C -> stack)
+*)
+procedure lua_pushnil(L : Plua_State);
+  cdecl; external LuaDLL;
+procedure lua_pushnumber(L : Plua_State; n : lua_Number);
+  cdecl; external LuaDLL;
+procedure lua_pushinteger(L : Plua_State; n : lua_Integer);
+  cdecl; external LuaDLL;
+procedure lua_pushlstring(L : Plua_State; const s : PChar; ls : size_t);
+  cdecl; external LuaDLL;
+procedure lua_pushstring(L : Plua_State; const s : PChar);
+  cdecl; external LuaDLL;
+function  lua_pushvfstring(L : Plua_State;
+                           const fmt : PChar; argp : Pointer) : PChar;
+  cdecl; external LuaDLL;
+function  lua_pushfstring(L : Plua_State; const fmt : PChar) : PChar; varargs;
+  cdecl; external LuaDLL;
+procedure lua_pushcclosure(L : Plua_State; fn : lua_CFunction; n : Integer);
+  cdecl; external LuaDLL;
+procedure lua_pushboolean(L : Plua_State; b : LongBool);
+  cdecl; external LuaDLL;
+procedure lua_pushlightuserdata(L : Plua_State; p : Pointer);
+  cdecl; external LuaDLL;
+function  lua_pushthread(L : Plua_state) : Cardinal;
+  cdecl; external LuaDLL;
+
+
+(*
+** get functions (Lua -> stack)
+*)
+procedure lua_gettable(L : Plua_State ; idx : Integer);
+  cdecl; external LuaDLL;
+procedure lua_getfield(L : Plua_State; idx : Integer; k : PChar);
+  cdecl; external LuaDLL;
+procedure lua_rawget(L : Plua_State; idx : Integer);
+  cdecl; external LuaDLL;
+procedure lua_rawgeti(L : Plua_State; idx, n : Integer);
+  cdecl; external LuaDLL;
+procedure lua_createtable(L : Plua_State; narr, nrec : Integer);
+  cdecl; external LuaDLL;
+function  lua_newuserdata(L : Plua_State; sz : size_t) : Pointer;
+  cdecl; external LuaDLL;
+function  lua_getmetatable(L : Plua_State; objindex : Integer) : LongBool;
+  cdecl; external LuaDLL;
+procedure lua_getfenv(L : Plua_State; idx : Integer);
+  cdecl; external LuaDLL;
+
+
+(*
+** set functions (stack -> Lua)
+*)
+procedure lua_settable(L : Plua_State; idx : Integer);
+  cdecl; external LuaDLL;
+procedure lua_setfield(L : Plua_State; idx : Integer; const k : PChar);
+  cdecl; external LuaDLL;
+procedure lua_rawset(L : Plua_State; idx : Integer);
+  cdecl; external LuaDLL;
+procedure lua_rawseti(L : Plua_State; idx , n: Integer);
+  cdecl; external LuaDLL;
+function lua_setmetatable(L : Plua_State; objindex : Integer): LongBool;
+  cdecl; external LuaDLL;
+function lua_setfenv(L : Plua_State; idx : Integer): LongBool;
+  cdecl; external LuaDLL;
+
+(*
+** `load' and `call' functions (load and run Lua code)
+*)
+procedure lua_call(L : Plua_State; nargs, nresults : Integer);
+  cdecl; external LuaDLL;
+function  lua_pcall(L : Plua_State;
+                    nargs, nresults, errfunc : Integer) : Integer;
+  cdecl; external LuaDLL;
+function  lua_cpcall(L : Plua_State;
+                     func : lua_CFunction; ud : Pointer) : Integer;
+  cdecl; external LuaDLL;
+function  lua_load(L : Plua_State; reader : lua_Reader;
+                   dt : Pointer; const chunkname : PChar) : Integer;
+  cdecl; external LuaDLL;
+
+function lua_dump(L : Plua_State; writer : lua_Writer; data: Pointer) : Integer;
+  cdecl; external LuaDLL;
+
+
+(*
+** coroutine functions
+*)
+function lua_yield(L : Plua_State; nresults : Integer) : Integer;
+  cdecl; external LuaDLL;
+function lua_resume(L : Plua_State; narg : Integer) : Integer;
+  cdecl; external LuaDLL;
+function lua_status(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+(*
+** garbage-collection functions and options
+*)
+const
+  LUA_GCSTOP       = 0;
+  LUA_GCRESTART    = 1;
+  LUA_GCCOLLECT    = 2;
+  LUA_GCCOUNT      = 3;
+  LUA_GCCOUNTB	   = 4;
+  LUA_GCSTEP       = 5;
+  LUA_GCSETPAUSE   = 6;
+  LUA_GCSETSTEPMUL = 7;
+
+function lua_gc(L : Plua_State; what, data : Integer) : Integer;
+  cdecl; external LuaDLL;
+
+(*
+** miscellaneous functions
+*)
+function lua_error(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+function lua_next(L : Plua_State; idx : Integer) : Integer;
+  cdecl; external LuaDLL;
+
+procedure lua_concat(L : Plua_State; n : Integer);
+  cdecl; external LuaDLL;
+
+function  lua_getallocf(L : Plua_State; ud : PPointer) : lua_Alloc;
+  cdecl; external LuaDLL;
+procedure lua_setallocf(L : Plua_State; f : lua_Alloc; ud : Pointer);
+  cdecl; external LuaDLL;
+
+(*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*)
+procedure lua_pop(L : Plua_State; n : Integer);
+
+procedure lua_newtable(L : Plua_State);
+
+procedure lua_register(L : Plua_State; n : PChar; f : lua_CFunction);
+
+procedure lua_pushcfunction(L : Plua_State; f : lua_CFunction);
+
+function  lua_strlen(L : Plua_State; idx : Integer) : Integer;
+
+function lua_isfunction(L : Plua_State; n : Integer) : Boolean;
+function lua_istable(L : Plua_State; n : Integer) : Boolean;
+function lua_islightuserdata(L : Plua_State; n : Integer) : Boolean;
+function lua_isnil(L : Plua_State; n : Integer) : Boolean;
+function lua_isboolean(L : Plua_State; n : Integer) : Boolean;
+function lua_isthread(L : Plua_State; n : Integer) : Boolean;
+function lua_isnone(L : Plua_State; n : Integer) : Boolean;
+function lua_isnoneornil(L : Plua_State; n : Integer) : Boolean;
+
+procedure lua_pushliteral(L : Plua_State; s : PChar);
+
+procedure lua_setglobal(L : Plua_State; s : PChar);
+procedure lua_getglobal(L : Plua_State; s : PChar);
+
+function lua_tostring(L : Plua_State; idx : Integer) : PChar;
+
+
+(*
+** compatibility macros and functions
+*)
+function lua_open : Plua_State;
+
+procedure lua_getregistry(L : Plua_State);
+
+function lua_getgccount(L : Plua_State) : Integer;
+
+type
+  lua_Chuckreader = type lua_Reader;
+  lua_Chuckwriter = type lua_Writer;
+
+(* ====================================================================== *)
+
+(*
+** {======================================================================
+** Debug API
+** =======================================================================
+*)
+
+(*
+** Event codes
+*)
+const
+  LUA_HOOKCALL    = 0;
+  LUA_HOOKRET     = 1;
+  LUA_HOOKLINE    = 2;
+  LUA_HOOKCOUNT   = 3;
+  LUA_HOOKTAILRET = 4;
+
+
+(*
+** Event masks
+*)
+  LUA_MASKCALL  = 1 shl LUA_HOOKCALL;
+  LUA_MASKRET   = 1 shl LUA_HOOKRET;
+  LUA_MASKLINE  = 1 shl LUA_HOOKLINE;
+  LUA_MASKCOUNT = 1 shl LUA_HOOKCOUNT;
+
+type
+  lua_Debug = packed record
+    event : Integer;
+    name : PChar;          (* (n) *)
+    namewhat : PChar;      (* (n) `global', `local', `field', `method' *)
+    what : PChar;          (* (S) `Lua', `C', `main', `tail' *)
+    source : PChar;        (* (S) *)
+    currentline : Integer; (* (l) *)
+    nups : Integer;        (* (u) number of upvalues *)
+    linedefined : Integer; (* (S) *)
+    short_src : array [0..LUA_IDSIZE-1] of Char; (* (S) *)
+    (* private part *)
+    i_ci : Integer;        (* active function *)
+  end;
+  Plua_Debug = ^lua_Debug;
+
+  (* Functions to be called by the debuger in specific events *)
+  lua_Hook = procedure (L : Plua_State; ar : Plua_Debug); cdecl;
+
+
+function lua_getstack(L : Plua_State; level : Integer;
+                      ar : Plua_Debug) : Integer;
+  cdecl; external LuaDLL;
+function lua_getinfo(L : Plua_State; const what : PChar;
+                     ar: Plua_Debug): Integer;
+  cdecl; external LuaDLL;
+function lua_getlocal(L : Plua_State;
+                      ar : Plua_Debug; n : Integer) : PChar;
+  cdecl; external LuaDLL;
+function lua_setlocal(L : Plua_State;
+                      ar : Plua_Debug; n : Integer) : PChar;
+  cdecl; external LuaDLL;
+function lua_getupvalue(L : Plua_State; funcindex, n : Integer) : PChar;
+  cdecl; external LuaDLL;
+function lua_setupvalue(L : Plua_State; funcindex, n : Integer) : PChar;
+  cdecl; external LuaDLL;
+
+function lua_sethook(L : Plua_State; func : lua_Hook;
+                     mask, count: Integer): Integer;
+  cdecl; external LuaDLL;
+{
+function lua_gethook(L : Plua_State) : lua_Hook;
+  cdecl; external LuaDLL;
+}
+function lua_gethookmask(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+function lua_gethookcount(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+
+(*****************************************************************************)
+(*                                  lualib.h                                 *)
+(*****************************************************************************)
+
+(*
+** $Id: lualib.h,v 1.36 2005/12/27 17:12:00 roberto Exp $
+** Lua standard libraries
+** See Copyright Notice at the end of this file
+*)
+
+const
+  (* Key to file-handle type *)
+  LUA_FILEHANDLE  = 'FILE*';
+
+  LUA_COLIBNAME   = 'coroutine';
+  LUA_TABLIBNAME  = 'table';
+  LUA_IOLIBNAME   = 'io';
+  LUA_OSLIBNAME   = 'os';
+  LUA_STRLIBNAME  = 'string';
+  LUA_MATHLIBNAME = 'math';
+  LUA_DBLIBNAME   = 'debug';
+  LUA_LOADLIBNAME = 'package';
+
+function luaopen_base(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+function luaopen_table(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+function luaopen_io(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+function luaopen_os(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+function luaopen_string(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+function luaopen_math(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+function luaopen_debug(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+function luaopen_package(L : Plua_State) : Integer;
+  cdecl; external LuaDLL;
+
+procedure luaL_openlibs(L : Plua_State);
+  cdecl; external LuaDLL;
+
+procedure lua_assert(x : Boolean);    // a macro
+
+
+(*****************************************************************************)
+(*                                  lauxlib.h                                *)
+(*****************************************************************************)
+
+(*
+** $Id: lauxlib.h,v 1.87 2005/12/29 15:32:11 roberto Exp $
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice at the end of this file.
+*)
+
+// not compatibility with the behavior of setn/getn in Lua 5.0
+function  luaL_getn(L : Plua_State; idx : Integer) : Integer;
+procedure luaL_setn(L : Plua_State; i, j : Integer);
+
+const
+  LUA_ERRFILE = LUA_ERRERR + 1;
+
+type
+  luaL_Reg = packed record
+    name : PChar;
+    func : lua_CFunction;
+  end;
+  PluaL_Reg = ^luaL_Reg;
+
+
+procedure luaL_openlib(L : Plua_State; const libname : PChar;
+                       const lr : PluaL_Reg; nup : Integer);
+  cdecl; external LuaDLL;
+procedure luaL_register(L : Plua_State; const libname : PChar;
+                       const lr : PluaL_Reg);
+  cdecl; external LuaDLL;
+function luaL_getmetafield(L : Plua_State; obj : Integer;
+                           const e : PChar) : Integer;
+  cdecl; external LuaDLL;
+function luaL_callmeta(L : Plua_State; obj : Integer;
+                       const e : PChar) : Integer;
+  cdecl; external LuaDLL;
+function luaL_typerror(L : Plua_State; narg : Integer;
+                       const tname : PChar) : Integer;
+  cdecl; external LuaDLL;
+function luaL_argerror(L : Plua_State; numarg : Integer;
+                       const extramsg : PChar) : Integer;
+  cdecl; external LuaDLL;
+function luaL_checklstring(L : Plua_State; numArg : Integer;
+                           ls : Psize_t) : PChar;
+  cdecl; external LuaDLL;
+function luaL_optlstring(L : Plua_State; numArg : Integer;
+                         const def: PChar; ls: Psize_t) : PChar;
+  cdecl; external LuaDLL;
+function luaL_checknumber(L : Plua_State; numArg : Integer) : lua_Number;
+  cdecl; external LuaDLL;
+function luaL_optnumber(L : Plua_State; nArg : Integer;
+                        def : lua_Number) : lua_Number;
+  cdecl; external LuaDLL;
+
+function luaL_checkinteger(L : Plua_State; numArg : Integer) : lua_Integer;
+  cdecl; external LuaDLL;
+function luaL_optinteger(L : Plua_State; nArg : Integer;
+                        def : lua_Integer) : lua_Integer;
+  cdecl; external LuaDLL;
+
+procedure luaL_checkstack(L : Plua_State; sz : Integer; const msg : PChar);
+  cdecl; external LuaDLL;
+procedure luaL_checktype(L : Plua_State; narg, t : Integer);
+  cdecl; external LuaDLL;
+procedure luaL_checkany(L : Plua_State; narg : Integer);
+  cdecl; external LuaDLL;
+
+function luaL_newmetatable(L : Plua_State; const tname : PChar) : Integer;
+  cdecl; external LuaDLL;
+function luaL_checkudata(L : Plua_State; ud : Integer;
+                         const tname : PChar) : Pointer;
+  cdecl; external LuaDLL;
+
+procedure luaL_where(L : Plua_State; lvl : Integer);
+  cdecl; external LuaDLL;
+function  luaL_error(L : Plua_State; const fmt : PChar) : Integer; varargs;
+  cdecl; external LuaDLL;
+
+function luaL_checkoption(L : Plua_State; narg : Integer; const def : PChar;
+                          const lst : array of PChar) : Integer;
+  cdecl; external LuaDLL;
+
+function  luaL_ref(L : Plua_State; t : Integer) : Integer;
+  cdecl; external LuaDLL;
+procedure luaL_unref(L : Plua_State; t, ref : Integer);
+  cdecl; external LuaDLL;
+
+function luaL_loadfile(L : Plua_State; const filename : PChar) : Integer;
+  cdecl; external LuaDLL;
+function luaL_loadbuffer(L : Plua_State; const buff : PChar;
+                         sz : size_t; const name: PChar) : Integer;
+  cdecl; external LuaDLL;
+
+function luaL_loadstring(L : Plua_State; const s : Pchar) : Integer;
+  cdecl; external LuaDLL;
+
+function luaL_newstate : Plua_State;
+  cdecl; external LuaDLL;
+
+function luaL_gsub(L : Plua_State; const s, p, r : PChar) : PChar;
+  cdecl; external LuaDLL;
+
+function luaL_findtable(L : Plua_State; idx : Integer;
+                        const fname : PChar; szhint : Integer) : PChar;
+  cdecl; external LuaDLL;
+
+
+(*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*)
+
+function luaL_argcheck(L : Plua_State; cond : Boolean; numarg : Integer;
+                       extramsg : PChar): Integer;
+function luaL_checkstring(L : Plua_State; n : Integer) : PChar;
+function luaL_optstring(L : Plua_State; n : Integer; d : PChar) : PChar;
+function luaL_checkint(L : Plua_State; n : Integer) : Integer;
+function luaL_optint(L : Plua_State; n, d : Integer): Integer;
+function luaL_checklong(L : Plua_State; n : LongInt) : LongInt;
+function luaL_optlong(L : Plua_State; n : Integer; d : LongInt) : LongInt;
+
+function luaL_typename(L : Plua_State; idx : Integer) : PChar;
+
+function luaL_dofile(L : Plua_State; fn : PChar) : Integer;
+
+function luaL_dostring(L : Plua_State; s : PChar) : Integer;
+
+procedure luaL_getmetatable(L : Plua_State; n : PChar);
+
+(* not implemented yet
+#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
+*)
+
+(*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*)
+
+type
+  luaL_Buffer = packed record
+    p : PChar;       (* current position in buffer *)
+    lvl : Integer;   (* number of strings in the stack (level) *)
+    L : Plua_State;
+    buffer : array [0..LUAL_BUFFERSIZE-1] of Char;
+  end;
+  PluaL_Buffer = ^luaL_Buffer;
+
+procedure luaL_addchar(B : PluaL_Buffer; c : Char);
+
+(* compatibility only *)
+procedure luaL_putchar(B : PluaL_Buffer; c : Char);
+
+procedure luaL_addsize(B : PluaL_Buffer; n : Integer);
+
+procedure luaL_buffinit(L : Plua_State; B : PluaL_Buffer);
+  cdecl; external LuaDLL;
+function  luaL_prepbuffer(B : PluaL_Buffer) : PChar;
+  cdecl; external LuaDLL;
+procedure luaL_addlstring(B : PluaL_Buffer; const s : PChar; ls : size_t);
+  cdecl; external LuaDLL;
+procedure luaL_addstring(B : PluaL_Buffer; const s : PChar);
+  cdecl; external LuaDLL;
+procedure luaL_addvalue(B : PluaL_Buffer);
+  cdecl; external LuaDLL;
+procedure luaL_pushresult(B : PluaL_Buffer);
+  cdecl; external LuaDLL;
+
+(* ====================================================== *)
+
+
+(* compatibility with ref system *)
+
+(* pre-defined references *)
+const
+  LUA_NOREF  = -2;
+  LUA_REFNIL = -1;
+
+function lua_ref(L : Plua_State; lock : Boolean) : Integer;
+
+procedure lua_unref(L : Plua_State; ref : Integer);
+
+procedure lua_getref(L : Plua_State; ref : Integer);
+
+
+(******************************************************************************)
+(******************************************************************************)
+(******************************************************************************)
+
+implementation
+
+uses
+  SysUtils;
+
+(*****************************************************************************)
+(*                            luaconfig.h                                    *)
+(*****************************************************************************)
+
+function  lua_readline(L : Plua_State; var b : PChar; p : PChar): Boolean;
+var
+  s : AnsiString;
+begin
+  Write(p);                        // show prompt
+  ReadLn(s);                       // get line
+  b := PChar(s);                   //   and return it
+  lua_readline := (b[0] <> #4);          // test for ctrl-D
+end;
+
+procedure lua_saveline(L : Plua_State; idx : Integer);
+begin
+end;
+
+procedure lua_freeline(L : Plua_State; b : PChar);
+begin
+end;
+
+
+(*****************************************************************************)
+(*                                  lua.h                                    *)
+(*****************************************************************************)
+
+function lua_upvalueindex(idx : Integer) : Integer;
+begin
+  lua_upvalueindex := LUA_GLOBALSINDEX - idx;
+end;
+
+procedure lua_pop(L : Plua_State; n : Integer);
+begin
+  lua_settop(L, -n - 1);
+end;
+
+procedure lua_newtable(L : Plua_State);
+begin
+  lua_createtable(L, 0, 0);
+end;
+
+procedure lua_register(L : Plua_State; n : PChar; f : lua_CFunction);
+begin
+  lua_pushcfunction(L, f);
+  lua_setglobal(L, n);
+end;
+
+procedure lua_pushcfunction(L : Plua_State; f : lua_CFunction);
+begin
+  lua_pushcclosure(L, f, 0);
+end;
+
+function  lua_strlen(L : Plua_State; idx : Integer) : Integer;
+begin
+  lua_strlen := lua_objlen(L, idx);
+end;
+
+function lua_isfunction(L : Plua_State; n : Integer) : Boolean;
+begin
+  lua_isfunction := lua_type(L, n) = LUA_TFUNCTION;
+end;
+
+function lua_istable(L : Plua_State; n : Integer) : Boolean;
+begin
+  lua_istable := lua_type(L, n) = LUA_TTABLE;
+end;
+
+function lua_islightuserdata(L : Plua_State; n : Integer) : Boolean;
+begin
+  lua_islightuserdata := lua_type(L, n) = LUA_TLIGHTUSERDATA;
+end;
+
+function lua_isnil(L : Plua_State; n : Integer) : Boolean;
+begin
+  lua_isnil := lua_type(L, n) = LUA_TNIL;
+end;
+
+function lua_isboolean(L : Plua_State; n : Integer) : Boolean;
+begin
+  lua_isboolean := lua_type(L, n) = LUA_TBOOLEAN;
+end;
+
+function lua_isthread(L : Plua_State; n : Integer) : Boolean;
+begin
+  lua_isthread := lua_type(L, n) = LUA_TTHREAD;
+end;
+
+function lua_isnone(L : Plua_State; n : Integer) : Boolean;
+begin
+  lua_isnone := lua_type(L, n) = LUA_TNONE;
+end;
+
+function lua_isnoneornil(L : Plua_State; n : Integer) : Boolean;
+begin
+  lua_isnoneornil := lua_type(L, n) <= 0;
+end;
+
+procedure lua_pushliteral(L : Plua_State; s : PChar);
+begin
+  lua_pushlstring(L, s, StrLen(s));
+end;
+
+procedure lua_setglobal(L : Plua_State; s : PChar);
+begin
+  lua_setfield(L, LUA_GLOBALSINDEX, s);
+end;
+
+procedure lua_getglobal(L: Plua_State; s: PChar);
+begin
+  lua_getfield(L, LUA_GLOBALSINDEX, s);
+end;
+
+function lua_tostring(L : Plua_State; idx : Integer) : PChar;
+begin
+  lua_tostring := lua_tolstring(L, idx, nil);
+end;
+
+function lua_open : Plua_State;
+begin
+  lua_open := luaL_newstate;
+end;
+
+procedure lua_getregistry(L : Plua_State);
+begin
+  lua_pushvalue(L, LUA_REGISTRYINDEX);
+end;
+
+function lua_getgccount(L : Plua_State) : Integer;
+begin
+  lua_getgccount := lua_gc(L, LUA_GCCOUNT, 0);
+end;
+
+
+(*****************************************************************************)
+(*                                  lualib.h                                 *)
+(*****************************************************************************)
+
+procedure lua_assert(x : Boolean);
+begin
+end;
+
+
+(*****************************************************************************)
+(*                                  lauxlib.h    n                           *)
+(*****************************************************************************)
+
+function luaL_getn(L : Plua_State; idx : Integer) : Integer;
+begin
+  luaL_getn := lua_objlen(L, idx);
+end;
+
+procedure luaL_setn(L : plua_State; i, j : Integer);
+begin
+  (* no op *)
+end;
+
+function luaL_argcheck(L : Plua_State; cond : Boolean; numarg : Integer;
+                       extramsg : PChar): Integer;
+begin
+  if not cond then
+    luaL_argcheck := luaL_argerror(L, numarg, extramsg)
+  else
+    luaL_argcheck := 0;
+end;
+
+function luaL_checkstring(L : Plua_State; n : Integer) : PChar;
+begin
+  luaL_checkstring := luaL_checklstring(L, n, nil);
+end;
+
+function luaL_optstring(L : Plua_State; n : Integer; d : PChar) : PChar;
+begin
+  luaL_optstring := luaL_optlstring(L, n, d, nil);
+end;
+
+function luaL_checkint(L : Plua_State; n : Integer) : Integer;
+begin
+  luaL_checkint := luaL_checkinteger(L, n);
+end;
+
+function luaL_optint(L : Plua_State; n, d : Integer): Integer;
+begin
+  luaL_optint := luaL_optinteger(L, n, d);
+end;
+
+function luaL_checklong(L : Plua_State; n : LongInt) : LongInt;
+begin
+  luaL_checklong := luaL_checkinteger(L, n);
+end;
+
+function luaL_optlong(L : Plua_State; n : Integer; d : LongInt) : LongInt;
+begin
+  luaL_optlong := luaL_optinteger(L, n, d);
+end;
+
+function luaL_typename(L : Plua_State; idx : Integer) : PChar;
+begin
+  luaL_typename := lua_typename( L, lua_type(L, idx) );
+end;
+
+function luaL_dofile(L : Plua_State; fn : PChar) : Integer;
+Var
+  Res : Integer;
+begin
+  // WC 2007\03\22 - Updated for Delphi
+  Res := luaL_loadfile(L, fn);
+  if Res = 0 then
+    Res := lua_pcall(L, 0, LUA_MULTRET, 0);
+  Result := Res;
+end;
+
+function luaL_dostring(L : Plua_State; s : PChar) : Integer;
+Var
+  Res : Integer;
+begin
+  // WC 2007\03\22 - Updated for Delphi
+  Res := luaL_loadstring(L, s);
+  if Res = 0 then
+    Res := lua_pcall(L, 0, LUA_MULTRET, 0);
+  Result := Res;
+end;
+
+procedure luaL_getmetatable(L : Plua_State; n : PChar);
+begin
+  lua_getfield(L, LUA_REGISTRYINDEX, n);
+end;
+
+procedure luaL_addchar(B : PluaL_Buffer; c : Char);
+begin
+  if not(B^.p < B^.buffer + LUAL_BUFFERSIZE) then
+    luaL_prepbuffer(B);
+  B^.p^ := c;
+  Inc(B^.p);
+end;
+
+procedure luaL_putchar(B : PluaL_Buffer; c : Char);
+begin
+  luaL_addchar(B, c);
+end;
+
+procedure luaL_addsize(B : PluaL_Buffer; n : Integer);
+begin
+  Inc(B^.p, n);
+end;
+
+function lua_ref(L : Plua_State; lock : Boolean) : Integer;
+begin
+  if lock then
+    lua_ref := luaL_ref(L, LUA_REGISTRYINDEX)
+  else begin
+    lua_pushstring(L, 'unlocked references are obsolete');
+    lua_error(L);
+    lua_ref := 0;
+  end;
+end;
+
+procedure lua_unref(L : Plua_State; ref : Integer);
+begin
+  luaL_unref(L, LUA_REGISTRYINDEX, ref);
+end;
+
+procedure lua_getref(L : Plua_State; ref : Integer);
+begin
+  lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
+end;
+
+
+(******************************************************************************
+* Original copyright for the lua source and headers:
+*  1994-2004 Tecgraf, PUC-Rio.
+*  www.lua.org.
+*
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************)
+
+end.
+
diff --git a/songmanagement/src/lib/SQLite/SQLite3.pas b/songmanagement/src/lib/SQLite/SQLite3.pas
new file mode 100644
index 00000000..7b7207c4
--- /dev/null
+++ b/songmanagement/src/lib/SQLite/SQLite3.pas
@@ -0,0 +1,253 @@
+unit SQLite3;
+
+{
+  Simplified interface for SQLite.
+  Updated for Sqlite 3 by Tim Anderson (tim@itwriting.com)
+  Note: NOT COMPLETE for version 3, just minimal functionality
+  Adapted from file created by Pablo Pissanetzky (pablo@myhtpc.net)
+  which was based on SQLite.pas by Ben Hochstrasser (bhoc@surfeu.ch)
+}
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$H+}            (* use long strings *)
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+interface
+
+const
+{$IF Defined(MSWINDOWS)}
+  SQLiteDLL = 'sqlite3.dll';
+{$ELSEIF Defined(DARWIN)}
+  SQLiteDLL = 'libsqlite3.dylib';
+  {$linklib libsqlite3}
+{$ELSEIF Defined(UNIX)}
+  SQLiteDLL = 'sqlite3.so';
+{$IFEND}
+
+// Return values for sqlite3_exec() and sqlite3_step()
+
+const
+  SQLITE_OK          =  0; // Successful result
+  (* beginning-of-error-codes *)
+  SQLITE_ERROR       =  1; // SQL error or missing database
+  SQLITE_INTERNAL    =  2; // An internal logic error in SQLite
+  SQLITE_PERM        =  3; // Access permission denied
+  SQLITE_ABORT       =  4; // Callback routine requested an abort
+  SQLITE_BUSY        =  5; // The database file is locked
+  SQLITE_LOCKED      =  6; // A table in the database is locked
+  SQLITE_NOMEM       =  7; // A malloc() failed
+  SQLITE_READONLY    =  8; // Attempt to write a readonly database
+  SQLITE_INTERRUPT   =  9; // Operation terminated by sqlite3_interrupt()
+  SQLITE_IOERR       = 10; // Some kind of disk I/O error occurred
+  SQLITE_CORRUPT     = 11; // The database disk image is malformed
+  SQLITE_NOTFOUND    = 12; // (Internal Only) Table or record not found
+  SQLITE_FULL        = 13; // Insertion failed because database is full
+  SQLITE_CANTOPEN    = 14; // Unable to open the database file
+  SQLITE_PROTOCOL    = 15; // Database lock protocol error
+  SQLITE_EMPTY       = 16; // Database is empty
+  SQLITE_SCHEMA      = 17; // The database schema changed
+  SQLITE_TOOBIG      = 18; // Too much data for one row of a table
+  SQLITE_CONSTRAINT  = 19; // Abort due to contraint violation
+  SQLITE_MISMATCH    = 20; // Data type mismatch
+  SQLITE_MISUSE      = 21; // Library used incorrectly
+  SQLITE_NOLFS       = 22; // Uses OS features not supported on host
+  SQLITE_AUTH        = 23; // Authorization denied
+  SQLITE_FORMAT      = 24; // Auxiliary database format error
+  SQLITE_RANGE       = 25; // 2nd parameter to sqlite3_bind out of range
+  SQLITE_NOTADB      = 26; // File opened that is not a database file
+  SQLITE_ROW         = 100; // sqlite3_step() has another row ready
+  SQLITE_DONE        = 101; // sqlite3_step() has finished executing
+
+  SQLITE_INTEGER = 1;
+  SQLITE_FLOAT   = 2;
+  SQLITE_TEXT    = 3;
+  SQLITE_BLOB    = 4;
+  SQLITE_NULL    = 5;
+
+  SQLITE_UTF8     = 1;
+  SQLITE_UTF16    = 2;
+  SQLITE_UTF16BE  = 3;
+  SQLITE_UTF16LE  = 4;
+  SQLITE_ANY      = 5;
+
+  SQLITE_STATIC    {: TSQLite3Destructor} = Pointer(0);
+  SQLITE_TRANSIENT {: TSQLite3Destructor} = Pointer(-1);
+
+type
+  TSQLiteDB = Pointer;
+  TSQLiteResult = ^PAnsiChar;
+  TSQLiteStmt = Pointer;
+
+type
+  PPAnsiCharArray = ^TPAnsiCharArray; 
+  TPAnsiCharArray = array[0 .. (MaxInt div SizeOf(PAnsiChar))-1] of PAnsiChar;
+
+type
+  TSQLiteExecCallback = function(UserData: Pointer; NumCols: integer; ColValues:
+    PPAnsiCharArray; ColNames: PPAnsiCharArray): integer; cdecl;
+  TSQLiteBusyHandlerCallback = function(UserData: Pointer; P2: integer): integer; cdecl;
+
+  //function prototype for define own collate
+  TCollateXCompare = function(UserData: pointer; Buf1Len: integer; Buf1: pointer;
+    Buf2Len: integer; Buf2: pointer): integer; cdecl;
+    
+
+function SQLite3_Open(filename: PAnsiChar; out db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_open';
+function SQLite3_Close(db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_close';
+function SQLite3_Exec(db: TSQLiteDB; SQLStatement: PAnsiChar; CallbackPtr: TSQLiteExecCallback; UserData: Pointer; var ErrMsg: PAnsiChar): integer; cdecl; external SQLiteDLL name 'sqlite3_exec';
+function SQLite3_Version(): PAnsiChar; cdecl; external SQLiteDLL name 'sqlite3_libversion';
+function SQLite3_ErrMsg(db: TSQLiteDB): PAnsiChar; cdecl; external SQLiteDLL name 'sqlite3_errmsg';
+function SQLite3_ErrCode(db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_errcode';
+procedure SQlite3_Free(P: PAnsiChar); cdecl; external SQLiteDLL name 'sqlite3_free';
+function SQLite3_GetTable(db: TSQLiteDB; SQLStatement: PAnsiChar; var ResultPtr: TSQLiteResult; var RowCount: Cardinal; var ColCount: Cardinal; var ErrMsg: PAnsiChar): integer; cdecl; external SQLiteDLL name 'sqlite3_get_table';
+procedure SQLite3_FreeTable(Table: TSQLiteResult); cdecl; external SQLiteDLL name 'sqlite3_free_table';
+function SQLite3_Complete(P: PAnsiChar): boolean; cdecl; external SQLiteDLL name 'sqlite3_complete';
+function SQLite3_LastInsertRowID(db: TSQLiteDB): int64; cdecl; external SQLiteDLL name 'sqlite3_last_insert_rowid';
+procedure SQLite3_Interrupt(db: TSQLiteDB); cdecl; external SQLiteDLL name 'sqlite3_interrupt';
+procedure SQLite3_BusyHandler(db: TSQLiteDB; CallbackPtr: TSQLiteBusyHandlerCallback; UserData: Pointer); cdecl; external SQLiteDLL name 'sqlite3_busy_handler';
+procedure SQLite3_BusyTimeout(db: TSQLiteDB; TimeOut: integer); cdecl; external SQLiteDLL name 'sqlite3_busy_timeout';
+function SQLite3_Changes(db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_changes';
+function SQLite3_TotalChanges(db: TSQLiteDB): integer; cdecl; external SQLiteDLL name 'sqlite3_total_changes';
+function SQLite3_Prepare(db: TSQLiteDB; SQLStatement: PAnsiChar; nBytes: integer; out hStmt: TSqliteStmt; out pzTail: PAnsiChar): integer; cdecl; external SQLiteDLL name 'sqlite3_prepare';
+function SQLite3_Prepare_v2(db: TSQLiteDB; SQLStatement: PAnsiChar; nBytes: integer; out hStmt: TSqliteStmt; out pzTail: PAnsiChar): integer; cdecl; external SQLiteDLL name 'sqlite3_prepare_v2';
+function SQLite3_ColumnCount(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_column_count';
+function SQLite3_ColumnName(hStmt: TSqliteStmt; ColNum: integer): PAnsiChar; cdecl; external SQLiteDLL name 'sqlite3_column_name';
+function SQLite3_ColumnDeclType(hStmt: TSqliteStmt; ColNum: integer): PAnsiChar; cdecl; external SQLiteDLL name 'sqlite3_column_decltype';
+function SQLite3_Step(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_step';
+function SQLite3_DataCount(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_data_count';
+
+function SQLite3_ColumnBlob(hStmt: TSqliteStmt; ColNum: integer): pointer; cdecl; external SQLiteDLL name 'sqlite3_column_blob';
+function SQLite3_ColumnBytes(hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_column_bytes';
+function SQLite3_ColumnDouble(hStmt: TSqliteStmt; ColNum: integer): double; cdecl; external SQLiteDLL name 'sqlite3_column_double';
+function SQLite3_ColumnInt(hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_column_int';
+function SQLite3_ColumnText(hStmt: TSqliteStmt; ColNum: integer): PAnsiChar; cdecl; external SQLiteDLL name 'sqlite3_column_text';
+function SQLite3_ColumnType(hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_column_type';
+function SQLite3_ColumnInt64(hStmt: TSqliteStmt; ColNum: integer): Int64; cdecl; external SQLiteDLL name 'sqlite3_column_int64';
+function SQLite3_Finalize(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_finalize';
+function SQLite3_Reset(hStmt: TSqliteStmt): integer; cdecl; external SQLiteDLL name 'sqlite3_reset';
+
+// 
+// In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(),
+// one or more literals can be replace by a wildcard "?" or ":N:" where
+// N is an integer.  These value of these wildcard literals can be set
+// using the routines listed below.
+// 
+// In every case, the first parameter is a pointer to the sqlite3_stmt
+// structure returned from sqlite3_prepare().  The second parameter is the
+// index of the wildcard.  The first "?" has an index of 1.  ":N:" wildcards
+// use the index N.
+// 
+// The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and
+//sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
+//text after SQLite has finished with it.  If the fifth argument is the
+// special value SQLITE_STATIC, then the library assumes that the information
+// is in static, unmanaged space and does not need to be freed.  If the
+// fifth argument has the value SQLITE_TRANSIENT, then SQLite makes its
+// own private copy of the data.
+// 
+// The sqlite3_bind_* routine must be called before sqlite3_step() after
+// an sqlite3_prepare() or sqlite3_reset().  Unbound wildcards are interpreted
+// as NULL.
+// 
+
+type
+  TSQLite3Destructor = procedure(Ptr: Pointer); cdecl;
+
+function sqlite3_bind_blob(hStmt: TSqliteStmt; ParamNum: integer;
+  ptrData: pointer; numBytes: integer; ptrDestructor: TSQLite3Destructor): integer;
+cdecl; external SQLiteDLL name 'sqlite3_bind_blob';
+function sqlite3_bind_text(hStmt: TSqliteStmt; ParamNum: integer;
+  Text: PAnsiChar; numBytes: integer; ptrDestructor: TSQLite3Destructor): integer;
+cdecl; external SQLiteDLL name 'sqlite3_bind_text';
+function sqlite3_bind_double(hStmt: TSqliteStmt; ParamNum: integer; Data: Double): integer;
+  cdecl; external SQLiteDLL name 'sqlite3_bind_double';
+function sqlite3_bind_int(hStmt: TSqLiteStmt; ParamNum: integer; Data: integer): integer;
+  cdecl; external SQLiteDLL name 'sqlite3_bind_int';
+function sqlite3_bind_int64(hStmt: TSqliteStmt; ParamNum: integer; Data: int64): integer;
+  cdecl; external SQLiteDLL name 'sqlite3_bind_int64';
+function sqlite3_bind_null(hStmt: TSqliteStmt; ParamNum: integer): integer;
+  cdecl; external SQLiteDLL name 'sqlite3_bind_null';
+
+function sqlite3_bind_parameter_index(hStmt: TSqliteStmt; zName: PAnsiChar): integer;
+  cdecl; external SQLiteDLL name 'sqlite3_bind_parameter_index';
+
+function sqlite3_enable_shared_cache(Value: integer): integer; cdecl; external SQLiteDLL name 'sqlite3_enable_shared_cache';
+
+//user collate definiton
+function SQLite3_create_collation(db: TSQLiteDB; Name: PAnsiChar; eTextRep: integer;
+  UserData: pointer; xCompare: TCollateXCompare): integer; cdecl; external SQLiteDLL name 'sqlite3_create_collation';
+
+function SQLiteFieldType(SQLiteFieldTypeCode: Integer): AnsiString;
+function SQLiteErrorStr(SQLiteErrorCode: Integer): AnsiString;
+
+implementation
+
+uses
+  SysUtils;
+
+function SQLiteFieldType(SQLiteFieldTypeCode: Integer): AnsiString;
+begin
+  case SQLiteFieldTypeCode of
+    SQLITE_INTEGER: Result := 'Integer';
+    SQLITE_FLOAT: Result := 'Float';
+    SQLITE_TEXT: Result := 'Text';
+    SQLITE_BLOB: Result := 'Blob';
+    SQLITE_NULL: Result := 'Null';
+  else
+    Result := 'Unknown SQLite Field Type Code "' + IntToStr(SQLiteFieldTypeCode) + '"';
+  end;
+end;
+
+function SQLiteErrorStr(SQLiteErrorCode: Integer): AnsiString;
+begin
+  case SQLiteErrorCode of
+    SQLITE_OK: Result := 'Successful result';
+    SQLITE_ERROR: Result := 'SQL error or missing database';
+    SQLITE_INTERNAL: Result := 'An internal logic error in SQLite';
+    SQLITE_PERM: Result := 'Access permission denied';
+    SQLITE_ABORT: Result := 'Callback routine requested an abort';
+    SQLITE_BUSY: Result := 'The database file is locked';
+    SQLITE_LOCKED: Result := 'A table in the database is locked';
+    SQLITE_NOMEM: Result := 'A malloc() failed';
+    SQLITE_READONLY: Result := 'Attempt to write a readonly database';
+    SQLITE_INTERRUPT: Result := 'Operation terminated by sqlite3_interrupt()';
+    SQLITE_IOERR: Result := 'Some kind of disk I/O error occurred';
+    SQLITE_CORRUPT: Result := 'The database disk image is malformed';
+    SQLITE_NOTFOUND: Result := '(Internal Only) Table or record not found';
+    SQLITE_FULL: Result := 'Insertion failed because database is full';
+    SQLITE_CANTOPEN: Result := 'Unable to open the database file';
+    SQLITE_PROTOCOL: Result := 'Database lock protocol error';
+    SQLITE_EMPTY: Result := 'Database is empty';
+    SQLITE_SCHEMA: Result := 'The database schema changed';
+    SQLITE_TOOBIG: Result := 'Too much data for one row of a table';
+    SQLITE_CONSTRAINT: Result := 'Abort due to contraint violation';
+    SQLITE_MISMATCH: Result := 'Data type mismatch';
+    SQLITE_MISUSE: Result := 'Library used incorrectly';
+    SQLITE_NOLFS: Result := 'Uses OS features not supported on host';
+    SQLITE_AUTH: Result := 'Authorization denied';
+    SQLITE_FORMAT: Result := 'Auxiliary database format error';
+    SQLITE_RANGE: Result := '2nd parameter to sqlite3_bind out of range';
+    SQLITE_NOTADB: Result := 'File opened that is not a database file';
+    SQLITE_ROW: Result := 'sqlite3_step() has another row ready';
+    SQLITE_DONE: Result := 'sqlite3_step() has finished executing';
+  else
+    Result := 'Unknown SQLite Error Code "' + IntToStr(SQLiteErrorCode) + '"';
+  end;
+end;
+
+function ColValueToStr(Value: PAnsiChar): AnsiString;
+begin
+  if (Value = nil) then
+    Result := 'NULL'
+  else
+    Result := Value;
+end;
+
+
+end.
+
diff --git a/songmanagement/src/lib/SQLite/SQLiteTable3.pas b/songmanagement/src/lib/SQLite/SQLiteTable3.pas
new file mode 100644
index 00000000..3aed54a4
--- /dev/null
+++ b/songmanagement/src/lib/SQLite/SQLiteTable3.pas
@@ -0,0 +1,1500 @@
+unit SQLiteTable3;
+
+{
+  Simple classes for using SQLite's exec and get_table.
+
+  TSQLiteDatabase wraps the calls to open and close an SQLite database.
+  It also wraps SQLite_exec for queries that do not return a result set
+
+  TSQLiteTable wraps execution of SQL query.
+  It run query and read all returned rows to internal buffer.
+  It allows accessing fields by name as well as index and can move through a
+  result set forward and backwards, or randomly to any row.
+
+  TSQLiteUniTable wraps execution of SQL query.
+  It run query as TSQLiteTable, but reading just first row only!
+  You can step to next row (until not EOF) by 'Next' method.
+  You cannot step backwards! (So, it is called as UniDirectional result set.)
+  It not using any internal buffering, this class is very close to Sqlite API.
+  It allows accessing fields by name as well as index on actual row only.
+  Very good and fast for sequentional scanning of large result sets with minimal
+    memory footprint.
+
+  Warning! Do not close TSQLiteDatabase before any TSQLiteUniTable,
+    because query is closed on TSQLiteUniTable destructor and database connection
+    is used during TSQLiteUniTable live!
+
+  SQL parameter usage:
+    You can add named parameter values by call set of AddParam* methods.
+    Parameters will be used for first next SQL statement only.
+    Parameter name must be prefixed by ':', '$' or '@' and same prefix must be
+    used in SQL statement!
+    Sample:
+      table.AddParamText(':str', 'some value');
+      s := table.GetTableString('SELECT value FROM sometable WHERE id=:str');
+
+   Notes from Andrew Retmanski on prepared queries
+   The changes are as follows:
+
+   SQLiteTable3.pas
+   - Added new boolean property Synchronised (this controls the SYNCHRONOUS pragma as I found that turning this OFF increased the write performance in my application)
+   - Added new type TSQLiteQuery (this is just a simple record wrapper around the SQL string and a TSQLiteStmt pointer)
+   - Added PrepareSQL method to prepare SQL query - returns TSQLiteQuery
+   - Added ReleaseSQL method to release previously prepared query
+   - Added overloaded BindSQL methods for Integer and String types - these set new values for the prepared query parameters
+   - Added overloaded ExecSQL method to execute a prepared TSQLiteQuery
+
+   Usage of the new methods should be self explanatory but the process is in essence:
+
+   1. Call PrepareSQL to return TSQLiteQuery 2. Call BindSQL for each parameter in the prepared query 3. Call ExecSQL to run the prepared query 4. Repeat steps 2 & 3 as required 5. Call ReleaseSQL to free SQLite resources
+
+   One other point - the Synchronised property throws an error if used inside a transaction.
+
+   Acknowledments
+   Adapted by Tim Anderson (tim@itwriting.com)
+   Originally created by Pablo Pissanetzky (pablo@myhtpc.net)
+   Modified and enhanced by Lukas Gebauer
+   Modified and enhanced by Tobias Gunkel
+}
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}{$H+}
+{$ENDIF}
+
+uses
+  {$IFDEF MSWINDOWS}
+  Windows,
+  {$ENDIF}
+  SQLite3, Classes, SysUtils;
+
+const
+
+  dtInt = 1;
+  dtNumeric = 2;
+  dtStr = 3;
+  dtBlob = 4;
+  dtNull = 5;
+
+type
+
+  ESQLiteException = class(Exception)
+  end;
+
+  TSQliteParam = class
+  public
+    name: string;
+    valuetype: integer;
+    valueinteger: int64;
+    valuefloat: double;
+    valuedata: string;
+  end;
+
+  THookQuery = procedure(Sender: TObject; SQL: String) of object;
+
+  TSQLiteQuery = record
+    SQL: String;
+    Statement: TSQLiteStmt;
+  end;
+
+  TSQLiteTable = class;
+  TSQLiteUniTable = class;
+
+  TSQLiteDatabase = class
+  private
+    fDB: TSQLiteDB;
+    fInTrans: boolean;
+    fSync: boolean;
+    fParams: TList;
+    FOnQuery: THookQuery;
+    procedure RaiseError(s: string; SQL: string);
+    procedure SetParams(Stmt: TSQLiteStmt);
+    procedure BindData(Stmt: TSQLiteStmt; const Bindings: array of const);
+    function GetRowsChanged: integer;
+  protected
+    procedure SetSynchronised(Value: boolean);
+    procedure DoQuery(value: string); 
+  public
+    constructor Create(const FileName: string);
+    destructor Destroy; override;
+    function GetTable(const SQL: Ansistring): TSQLiteTable; overload;
+    function GetTable(const SQL: Ansistring; const Bindings: array of const): TSQLiteTable; overload;
+    procedure ExecSQL(const SQL: Ansistring); overload;
+    procedure ExecSQL(const SQL: Ansistring; const Bindings: array of const); overload;
+    procedure ExecSQL(Query: TSQLiteQuery); overload;
+    function PrepareSQL(const SQL: Ansistring): TSQLiteQuery;
+    procedure BindSQL(Query: TSQLiteQuery; const Index: Integer; const Value: Integer); overload;
+    procedure BindSQL(Query: TSQLiteQuery; const Index: Integer; const Value: String); overload;
+    procedure ReleaseSQL(Query: TSQLiteQuery);
+    function GetUniTable(const SQL: Ansistring): TSQLiteUniTable; overload;
+    function GetUniTable(const SQL: Ansistring; const Bindings: array of const): TSQLiteUniTable; overload;
+    function GetTableValue(const SQL: Ansistring): int64; overload;
+    function GetTableValue(const SQL: Ansistring; const Bindings: array of const): int64; overload;
+    function GetTableString(const SQL: Ansistring): string; overload;
+    function GetTableString(const SQL: Ansistring; const Bindings: array of const): string; overload;
+    procedure GetTableStrings(const SQL: Ansistring; const Value: TStrings);
+    procedure UpdateBlob(const SQL: Ansistring; BlobData: TStream);
+    procedure BeginTransaction;
+    procedure Commit;
+    procedure Rollback;
+    function TableExists(TableName: string): boolean;
+    function ContainsColumn(Table: String; Column: String) : boolean;
+    function GetLastInsertRowID: int64;
+    function GetLastChangedRows: int64;
+    procedure SetTimeout(Value: integer);
+    function Version: string;
+    procedure AddCustomCollate(name: string; xCompare: TCollateXCompare);
+    //adds collate named SYSTEM for correct data sorting by user's locale
+    Procedure AddSystemCollate;
+    procedure ParamsClear;
+    procedure AddParamInt(name: string; value: int64);
+    procedure AddParamFloat(name: string; value: double);
+    procedure AddParamText(name: string; value: string);
+    procedure AddParamNull(name: string);
+    property DB: TSQLiteDB read fDB;
+  published
+    property IsTransactionOpen: boolean read fInTrans;
+    //database rows that were changed (or inserted or deleted) by the most recent SQL statement
+    property RowsChanged : integer read getRowsChanged;
+    property Synchronised: boolean read FSync write SetSynchronised;
+    property OnQuery: THookQuery read FOnQuery write FOnQuery;
+  end;
+
+  TSQLiteTable = class
+  private
+    fResults: TList;
+    fRowCount: cardinal;
+    fColCount: cardinal;
+    fCols: TStringList;
+    fColTypes: TList;
+    fRow: cardinal;
+    function GetFields(I: cardinal): string;
+    function GetEOF: boolean;
+    function GetBOF: boolean;
+    function GetColumns(I: integer): string;
+    function GetFieldByName(FieldName: string): string;
+    function GetFieldIndex(FieldName: string): integer;
+    function GetCount: integer;
+    function GetCountResult: integer;
+  public
+    constructor Create(DB: TSQLiteDatabase; const SQL: Ansistring); overload;
+    constructor Create(DB: TSQLiteDatabase; const SQL: Ansistring; const Bindings: array of const); overload;
+    destructor Destroy; override;
+    function FieldAsInteger(I: cardinal): int64;
+    function FieldAsBlob(I: cardinal): TMemoryStream;
+    function FieldAsBlobText(I: cardinal): string;
+    function FieldIsNull(I: cardinal): boolean;
+    function FieldAsString(I: cardinal): string;
+    function FieldAsDouble(I: cardinal): double;
+    function Next: boolean;
+    function Previous: boolean;
+    property EOF: boolean read GetEOF;
+    property BOF: boolean read GetBOF;
+    property Fields[I: cardinal]: string read GetFields;
+    property FieldByName[FieldName: string]: string read GetFieldByName;
+    property FieldIndex[FieldName: string]: integer read GetFieldIndex;
+    property Columns[I: integer]: string read GetColumns;
+    property ColCount: cardinal read fColCount;
+    property RowCount: cardinal read fRowCount;
+    property Row: cardinal read fRow;
+    function MoveFirst: boolean;
+    function MoveLast: boolean;
+    function MoveTo(position: cardinal): boolean;
+    property Count: integer read GetCount;
+    // The property CountResult is used when you execute count(*) queries.
+    // It returns 0 if the result set is empty or the value of the
+    // first field as an integer.
+    property CountResult: integer read GetCountResult;
+  end;
+
+  TSQLiteUniTable = class
+  private
+    fColCount: cardinal;
+    fCols: TStringList;
+    fRow: cardinal;
+    fEOF: boolean;
+    fStmt: TSQLiteStmt;
+    fDB: TSQLiteDatabase;
+    fSQL: string;
+    function GetFields(I: cardinal): string;
+    function GetColumns(I: integer): string;
+    function GetFieldByName(FieldName: string): string;
+    function GetFieldIndex(FieldName: string): integer;
+  public
+    constructor Create(DB: TSQLiteDatabase; const SQL: Ansistring); overload;
+    constructor Create(DB: TSQLiteDatabase; const SQL: Ansistring; const Bindings: array of const); overload;
+    destructor Destroy; override;
+    function FieldAsInteger(I: cardinal): int64;
+    function FieldAsBlob(I: cardinal): TMemoryStream;
+    function FieldAsBlobPtr(I: cardinal; out iNumBytes: integer): Pointer;
+    function FieldAsBlobText(I: cardinal): string;
+    function FieldIsNull(I: cardinal): boolean;
+    function FieldAsString(I: cardinal): string;
+    function FieldAsDouble(I: cardinal): double;
+    function Next: boolean;
+    property EOF: boolean read FEOF;
+    property Fields[I: cardinal]: string read GetFields;
+    property FieldByName[FieldName: string]: string read GetFieldByName;
+    property FieldIndex[FieldName: string]: integer read GetFieldIndex;
+    property Columns[I: integer]: string read GetColumns;
+    property ColCount: cardinal read fColCount;
+    property Row: cardinal read fRow;
+  end;
+
+procedure DisposePointer(ptr: pointer); cdecl;
+
+{$IFDEF MSWINDOWS}
+function SystemCollate(Userdta: pointer; Buf1Len: integer; Buf1: pointer;
+    Buf2Len: integer; Buf2: pointer): integer; cdecl;
+{$ENDIF}
+
+implementation
+
+procedure DisposePointer(ptr: pointer); cdecl;
+begin
+  if assigned(ptr) then
+    freemem(ptr);
+end;
+
+{$IFDEF MSWINDOWS}
+function SystemCollate(Userdta: pointer; Buf1Len: integer; Buf1: pointer;
+    Buf2Len: integer; Buf2: pointer): integer; cdecl;
+begin
+  Result := CompareStringW(LOCALE_USER_DEFAULT, 0, PWideChar(Buf1), Buf1Len,
+    PWideChar(Buf2), Buf2Len) - 2;
+end;
+{$ENDIF}
+
+//------------------------------------------------------------------------------
+// TSQLiteDatabase
+//------------------------------------------------------------------------------
+
+constructor TSQLiteDatabase.Create(const FileName: string);
+var
+  Msg: PAnsiChar;
+  iResult: integer;
+  utf8FileName: UTF8string;
+begin
+  inherited Create;
+  fParams := TList.Create;
+
+  self.fInTrans := False;
+
+  Msg := nil;
+  try
+    utf8FileName := UTF8String(FileName);
+    iResult := SQLite3_Open(PAnsiChar(utf8FileName), Fdb);
+
+    if iResult <> SQLITE_OK then
+      if Assigned(Fdb) then
+      begin
+        Msg := Sqlite3_ErrMsg(Fdb);
+        raise ESqliteException.CreateFmt('Failed to open database "%s" : %s',
+          [FileName, Msg]);
+      end
+      else
+        raise ESqliteException.CreateFmt('Failed to open database "%s" : unknown error',
+          [FileName]);
+
+//set a few configs
+//L.G. Do not call it here. Because busy handler is not setted here,
+// any share violation causing exception!
+
+//    self.ExecSQL('PRAGMA SYNCHRONOUS=NORMAL;');
+//    self.ExecSQL('PRAGMA temp_store = MEMORY;');
+
+  finally
+    if Assigned(Msg) then
+      SQLite3_Free(Msg);
+  end;
+
+end;
+
+//..............................................................................
+
+destructor TSQLiteDatabase.Destroy;
+begin
+  if self.fInTrans then
+    self.Rollback;  //assume rollback
+  if Assigned(fDB) then
+    SQLite3_Close(fDB);
+  ParamsClear;    
+  fParams.Free;
+  inherited;
+end;
+
+function TSQLiteDatabase.GetLastInsertRowID: int64;
+begin
+  Result := Sqlite3_LastInsertRowID(self.fDB);
+end;
+
+function TSQLiteDatabase.GetLastChangedRows: int64;
+begin
+  Result := SQLite3_TotalChanges(self.fDB);
+end;
+
+//..............................................................................
+
+procedure TSQLiteDatabase.RaiseError(s: string; SQL: string);
+//look up last error and raise an exception with an appropriate message
+var
+  Msg: PAnsiChar;
+  ret : integer;
+begin
+
+  Msg := nil;
+
+  ret := sqlite3_errcode(self.fDB);
+  if ret <> SQLITE_OK then
+    Msg := sqlite3_errmsg(self.fDB);
+
+  if Msg <> nil then
+    raise ESqliteException.CreateFmt(s +'.'#13'Error [%d]: %s.'#13'"%s": %s', [ret, SQLiteErrorStr(ret),SQL, Msg])
+  else
+    raise ESqliteException.CreateFmt(s, [SQL, 'No message']);
+
+end;
+
+procedure TSQLiteDatabase.SetSynchronised(Value: boolean);
+begin
+  if Value <> fSync then
+  begin
+    if Value then
+      ExecSQL('PRAGMA synchronous = ON;')
+    else
+      ExecSQL('PRAGMA synchronous = OFF;');
+    fSync := Value;
+  end;
+end;
+
+procedure TSQLiteDatabase.BindData(Stmt: TSQLiteStmt; const Bindings: array of const);
+var
+  BlobMemStream: TCustomMemoryStream;
+  BlobStdStream: TStream;
+  DataPtr: Pointer;
+  DataSize: integer;
+  AnsiStr: AnsiString;
+  AnsiStrPtr: PAnsiString;
+  I: integer;
+begin
+  for I := 0 to High(Bindings) do
+  begin
+    case Bindings[I].VType of
+      vtString,
+      vtAnsiString, vtPChar,
+      vtWideString, vtPWideChar,
+      vtChar, vtWideChar:
+      begin
+        case Bindings[I].VType of
+          vtString: begin // ShortString
+            AnsiStr := Bindings[I].VString^;
+            DataPtr := PAnsiChar(AnsiStr);
+            DataSize := Length(AnsiStr)+1;
+          end;
+          vtPChar: begin
+            DataPtr := Bindings[I].VPChar;
+            DataSize := -1;
+          end;
+          vtAnsiString: begin
+            AnsiStrPtr := PAnsiString(@Bindings[I].VAnsiString);
+            DataPtr := PAnsiChar(AnsiStrPtr^);
+            DataSize := Length(AnsiStrPtr^)+1;
+          end;
+          vtPWideChar: begin
+            AnsiStr := UTF8Encode(WideString(Bindings[I].VPWideChar));
+            DataPtr := PAnsiChar(AnsiStr);
+            DataSize := -1;
+          end;
+          vtWideString: begin
+            AnsiStr := UTF8Encode(PWideString(@Bindings[I].VWideString)^);
+            DataPtr := PAnsiChar(AnsiStr);
+            DataSize := -1;
+          end;
+          vtChar: begin
+            AnsiStr := AnsiString(Bindings[I].VChar);
+            DataPtr := PAnsiChar(AnsiStr);
+            DataSize := 2;
+          end;
+          vtWideChar: begin
+            AnsiStr := UTF8Encode(WideString(Bindings[I].VWideChar));
+            DataPtr := PAnsiChar(AnsiStr);
+            DataSize := -1;
+          end;
+          else
+            raise ESqliteException.Create('Unknown string-type');
+        end;
+        if (sqlite3_bind_text(Stmt, I+1, DataPtr, DataSize, SQLITE_STATIC) <> SQLITE_OK) then
+          RaiseError('Could not bind text', 'BindData');
+      end;
+      vtInteger:
+        if (sqlite3_bind_int(Stmt, I+1, Bindings[I].VInteger) <> SQLITE_OK) then
+          RaiseError('Could not bind integer', 'BindData');
+      vtInt64:
+        if (sqlite3_bind_int64(Stmt, I+1, Bindings[I].VInt64^) <> SQLITE_OK) then
+          RaiseError('Could not bind int64', 'BindData');
+      vtExtended:
+        if (sqlite3_bind_double(Stmt, I+1, Bindings[I].VExtended^) <> SQLITE_OK) then
+          RaiseError('Could not bind extended', 'BindData');
+      vtBoolean:
+        if (sqlite3_bind_int(Stmt, I+1, Integer(Bindings[I].VBoolean)) <> SQLITE_OK) then
+          RaiseError('Could not bind boolean', 'BindData');
+      vtPointer:
+      begin
+        if (Bindings[I].VPointer = nil) then
+        begin
+          if (sqlite3_bind_null(Stmt, I+1) <> SQLITE_OK) then
+            RaiseError('Could not bind null', 'BindData');
+        end
+        else
+          raise ESqliteException.Create('Unhandled pointer (<> nil)');
+      end;
+      vtObject:
+      begin
+        if (Bindings[I].VObject is TCustomMemoryStream) then
+        begin
+          BlobMemStream := TCustomMemoryStream(Bindings[I].VObject);
+          if (sqlite3_bind_blob(Stmt, I+1, @PAnsiChar(BlobMemStream.Memory)[BlobMemStream.Position],
+              BlobMemStream.Size-BlobMemStream.Position, SQLITE_STATIC) <> SQLITE_OK) then
+          begin
+            RaiseError('Could not bind BLOB', 'BindData');
+          end;
+        end
+        else if (Bindings[I].VObject is TStream) then
+        begin
+          BlobStdStream := TStream(Bindings[I].VObject);
+          DataSize := BlobStdStream.Size;
+
+          GetMem(DataPtr, DataSize);
+          if (DataPtr = nil) then
+            raise ESqliteException.Create('Error getting memory to save blob');
+
+          BlobStdStream.Position := 0;
+          BlobStdStream.Read(DataPtr^, DataSize);
+
+          if (sqlite3_bind_blob(stmt, I+1, DataPtr, DataSize, @DisposePointer) <> SQLITE_OK) then
+            RaiseError('Could not bind BLOB', 'BindData');
+        end
+        else             
+          raise ESqliteException.Create('Unhandled object-type in binding');
+      end
+      else 
+      begin
+        raise ESqliteException.Create('Unhandled binding');
+      end;
+    end;
+  end;
+end;
+
+procedure TSQLiteDatabase.ExecSQL(const SQL: Ansistring);
+begin
+  ExecSQL(SQL, []);
+end;
+
+procedure TSQLiteDatabase.ExecSQL(const SQL: Ansistring; const Bindings: array of const);
+var
+  Stmt: TSQLiteStmt;
+  NextSQLStatement: PAnsiChar;
+  iStepResult: integer;
+begin
+  try
+    if Sqlite3_Prepare_v2(self.fDB, PAnsiChar(SQL), -1, Stmt, NextSQLStatement) <>
+      SQLITE_OK then
+      RaiseError('Error executing SQL', SQL);
+    if (Stmt = nil) then
+      RaiseError('Could not prepare SQL statement', SQL);
+    DoQuery(SQL);
+    SetParams(Stmt);
+    BindData(Stmt, Bindings);
+
+    iStepResult := Sqlite3_step(Stmt);
+    if (iStepResult <> SQLITE_DONE) then
+      begin
+      SQLite3_reset(stmt);
+      RaiseError('Error executing SQL statement', SQL);
+      end;
+  finally
+    if Assigned(Stmt) then
+      Sqlite3_Finalize(stmt);
+  end;
+end;
+
+procedure TSQLiteDatabase.ExecSQL(Query: TSQLiteQuery);
+var
+  iStepResult: integer;
+begin
+  if Assigned(Query.Statement) then
+  begin
+    iStepResult := Sqlite3_step(Query.Statement);
+
+    if (iStepResult <> SQLITE_DONE) then
+      begin
+      SQLite3_reset(Query.Statement);
+      RaiseError('Error executing prepared SQL statement', Query.SQL);
+      end;
+    Sqlite3_Reset(Query.Statement);
+  end;
+end;
+
+function TSQLiteDatabase.PrepareSQL(const SQL: Ansistring): TSQLiteQuery;
+var
+  Stmt: TSQLiteStmt;
+  NextSQLStatement: PAnsiChar;
+begin
+  Result.SQL := SQL;
+  Result.Statement := nil;
+
+  if Sqlite3_Prepare(self.fDB, PAnsiChar(SQL), -1, Stmt, NextSQLStatement) <>
+    SQLITE_OK then
+    RaiseError('Error executing SQL', SQL)
+  else
+    Result.Statement := Stmt;
+
+  if (Result.Statement = nil) then
+    RaiseError('Could not prepare SQL statement', SQL);
+  DoQuery(SQL);
+end;
+
+procedure TSQLiteDatabase.BindSQL(Query: TSQLiteQuery; const Index: Integer; const Value: Integer);
+begin
+  if Assigned(Query.Statement) then
+    sqlite3_Bind_Int(Query.Statement, Index, Value)
+  else
+    RaiseError('Could not bind integer to prepared SQL statement', Query.SQL);
+end;
+
+procedure TSQLiteDatabase.BindSQL(Query: TSQLiteQuery; const Index: Integer; const Value: String);
+begin
+  if Assigned(Query.Statement) then
+    Sqlite3_Bind_Text(Query.Statement, Index, PAnsiChar(Value), Length(Value), Pointer(SQLITE_STATIC))
+  else
+    RaiseError('Could not bind string to prepared SQL statement', Query.SQL);
+end;
+
+procedure TSQLiteDatabase.ReleaseSQL(Query: TSQLiteQuery);
+begin
+  if Assigned(Query.Statement) then
+  begin
+    Sqlite3_Finalize(Query.Statement);
+    Query.Statement := nil;
+  end
+  else
+    RaiseError('Could not release prepared SQL statement', Query.SQL);
+end;
+
+procedure TSQLiteDatabase.UpdateBlob(const SQL: Ansistring; BlobData: TStream);
+var
+  iSize: integer;
+  ptr: pointer;
+  Stmt: TSQLiteStmt;
+  Msg: PAnsiChar;
+  NextSQLStatement: PAnsiChar;
+  iStepResult: integer;
+  iBindResult: integer;
+begin
+  //expects SQL of the form 'UPDATE MYTABLE SET MYFIELD = ? WHERE MYKEY = 1'
+  if pos('?', SQL) = 0 then
+    RaiseError('SQL must include a ? parameter', SQL);
+
+  Msg := nil;
+  try
+
+    if Sqlite3_Prepare_v2(self.fDB, PAnsiChar(SQL), -1, Stmt, NextSQLStatement) <>
+      SQLITE_OK then
+      RaiseError('Could not prepare SQL statement', SQL);
+
+    if (Stmt = nil) then
+      RaiseError('Could not prepare SQL statement', SQL);
+    DoQuery(SQL);
+
+    //now bind the blob data
+    iSize := BlobData.size;
+
+    GetMem(ptr, iSize);
+
+    if (ptr = nil) then
+      raise ESqliteException.CreateFmt('Error getting memory to save blob',
+        [SQL, 'Error']);
+
+    BlobData.position := 0;
+    BlobData.Read(ptr^, iSize);
+
+    iBindResult := SQLite3_Bind_Blob(stmt, 1, ptr, iSize, @DisposePointer);
+
+    if iBindResult <> SQLITE_OK then
+      RaiseError('Error binding blob to database', SQL);
+
+    iStepResult := Sqlite3_step(Stmt);
+
+    if (iStepResult <> SQLITE_DONE) then
+      begin
+      SQLite3_reset(stmt);
+      RaiseError('Error executing SQL statement', SQL);
+      end;
+
+  finally
+
+    if Assigned(Stmt) then
+      Sqlite3_Finalize(stmt);
+
+    if Assigned(Msg) then
+      SQLite3_Free(Msg);
+  end;
+
+end;
+
+//..............................................................................
+
+function TSQLiteDatabase.GetTable(const SQL: Ansistring): TSQLiteTable;
+begin
+  Result := TSQLiteTable.Create(Self, SQL);
+end;
+
+function TSQLiteDatabase.GetTable(const SQL: Ansistring; const Bindings: array of const): TSQLiteTable;
+begin
+  Result := TSQLiteTable.Create(Self, SQL, Bindings);
+end;
+
+function TSQLiteDatabase.GetUniTable(const SQL: Ansistring): TSQLiteUniTable;
+begin
+  Result := TSQLiteUniTable.Create(Self, SQL);
+end;
+
+function TSQLiteDatabase.GetUniTable(const SQL: Ansistring; const Bindings: array of const): TSQLiteUniTable;
+begin
+  Result := TSQLiteUniTable.Create(Self, SQL, Bindings);
+end;
+
+function TSQLiteDatabase.GetTableValue(const SQL: Ansistring): int64;
+begin
+  Result := GetTableValue(SQL, []);
+end;
+
+function TSQLiteDatabase.GetTableValue(const SQL: Ansistring; const Bindings: array of const): int64;
+var
+  Table: TSQLiteUniTable;
+begin
+  Result := 0;
+  Table := self.GetUniTable(SQL, Bindings);
+  try
+    if not Table.EOF then
+      Result := Table.FieldAsInteger(0);
+  finally
+    Table.Free;
+  end;
+end;
+
+function TSQLiteDatabase.GetTableString(const SQL: Ansistring): String;
+begin
+  Result := GetTableString(SQL, []);
+end;
+
+function TSQLiteDatabase.GetTableString(const SQL: Ansistring; const Bindings: array of const): String;
+var
+  Table: TSQLiteUniTable;
+begin
+  Result := '';
+  Table := self.GetUniTable(SQL, Bindings);
+  try
+    if not Table.EOF then
+      Result := Table.FieldAsString(0);
+  finally
+    Table.Free;
+  end;
+end;
+
+procedure TSQLiteDatabase.GetTableStrings(const SQL: Ansistring;
+  const Value: TStrings);
+var
+  Table: TSQLiteUniTable;
+begin
+  Value.Clear;
+  Table := self.GetUniTable(SQL);
+  try
+    while not table.EOF do
+    begin
+      Value.Add(Table.FieldAsString(0));
+      table.Next;
+    end;
+  finally
+    Table.Free;
+  end;
+end;
+
+procedure TSQLiteDatabase.BeginTransaction;
+begin
+  if not self.fInTrans then
+  begin
+    self.ExecSQL('BEGIN TRANSACTION');
+    self.fInTrans := True;
+  end
+  else
+    raise ESqliteException.Create('Transaction already open');
+end;
+
+procedure TSQLiteDatabase.Commit;
+begin
+  self.ExecSQL('COMMIT');
+  self.fInTrans := False;
+end;
+
+procedure TSQLiteDatabase.Rollback;
+begin
+  self.ExecSQL('ROLLBACK');
+  self.fInTrans := False;
+end;
+
+function TSQLiteDatabase.TableExists(TableName: string): boolean;
+var
+  sql: string;
+  ds: TSqliteTable;
+begin
+  //returns true if table exists in the database
+  sql := 'select [sql] from sqlite_master where [type] = ''table'' and lower(name) = ''' +
+    lowercase(TableName) + ''' ';
+  ds := self.GetTable(sql);
+  try
+    Result := (ds.Count > 0);
+  finally
+    ds.Free;
+  end;
+end;
+
+function TSQLiteDatabase.ContainsColumn(Table: String; Column: String) : boolean;
+var
+  sql: string;
+  ds: TSqliteTable;
+  i : integer;
+begin
+  sql := 'PRAGMA TABLE_INFO('+Table+');';
+  ds := self.GetTable(sql);
+  try
+    Result := false;
+    while (ds.Next() and not Result and not ds.EOF)  do
+    begin
+      if ds.FieldAsString(1) = Column then
+        Result := true;
+    end;
+  finally
+    ds.Free;
+  end;
+end;
+
+procedure TSQLiteDatabase.SetTimeout(Value: integer);
+begin
+  SQLite3_BusyTimeout(self.fDB, Value);
+end;
+
+function TSQLiteDatabase.Version: string;
+begin
+  Result := SQLite3_Version;
+end;
+
+procedure TSQLiteDatabase.AddCustomCollate(name: string;
+  xCompare: TCollateXCompare);
+begin
+  sqlite3_create_collation(fdb, PAnsiChar(name), SQLITE_UTF8, nil, xCompare);
+end;
+
+procedure TSQLiteDatabase.AddSystemCollate;
+begin
+  {$IFDEF MSWINDOWS}
+  sqlite3_create_collation(fdb, 'SYSTEM', SQLITE_UTF16LE, nil, @SystemCollate);
+  {$ENDIF}
+end;
+
+procedure TSQLiteDatabase.ParamsClear;
+var
+  n: integer;
+begin
+  for n := fParams.Count - 1 downto 0 do
+    TSQliteParam(fparams[n]).free;
+  fParams.Clear;
+end;
+
+procedure TSQLiteDatabase.AddParamInt(name: string; value: int64);
+var
+  par: TSQliteParam;
+begin
+  par := TSQliteParam.Create;
+  par.name := name;
+  par.valuetype := SQLITE_INTEGER;
+  par.valueinteger := value;
+  fParams.Add(par);
+end;
+
+procedure TSQLiteDatabase.AddParamFloat(name: string; value: double);
+var
+  par: TSQliteParam;
+begin
+  par := TSQliteParam.Create;
+  par.name := name;
+  par.valuetype := SQLITE_FLOAT;
+  par.valuefloat := value;
+  fParams.Add(par);
+end;
+
+procedure TSQLiteDatabase.AddParamText(name: string; value: string);
+var
+  par: TSQliteParam;
+begin
+  par := TSQliteParam.Create;
+  par.name := name;
+  par.valuetype := SQLITE_TEXT;
+  par.valuedata := value;
+  fParams.Add(par);
+end;
+
+procedure TSQLiteDatabase.AddParamNull(name: string);
+var
+  par: TSQliteParam;
+begin
+  par := TSQliteParam.Create;
+  par.name := name;
+  par.valuetype := SQLITE_NULL;
+  fParams.Add(par);
+end;
+
+procedure TSQLiteDatabase.SetParams(Stmt: TSQLiteStmt);
+var
+  n: integer;
+  i: integer;
+  par: TSQliteParam;
+begin
+  try
+    for n := 0 to fParams.Count - 1 do
+    begin
+      par := TSQliteParam(fParams[n]);
+      i := sqlite3_bind_parameter_index(Stmt, PAnsiChar(par.name));
+      if i > 0 then
+      begin
+        case par.valuetype of
+          SQLITE_INTEGER:
+            sqlite3_bind_int64(Stmt, i, par.valueinteger);
+          SQLITE_FLOAT:
+            sqlite3_bind_double(Stmt, i, par.valuefloat);
+          SQLITE_TEXT:
+            sqlite3_bind_text(Stmt, i, PAnsiChar(par.valuedata),
+              length(par.valuedata), SQLITE_TRANSIENT);
+          SQLITE_NULL:
+            sqlite3_bind_null(Stmt, i);
+        end;
+      end;
+    end;
+  finally
+    ParamsClear;
+  end;
+end;
+
+//database rows that were changed (or inserted or deleted) by the most recent SQL statement
+function TSQLiteDatabase.GetRowsChanged: integer;
+begin
+ Result := SQLite3_Changes(self.fDB);
+end;
+
+procedure TSQLiteDatabase.DoQuery(value: string);
+begin
+  if assigned(OnQuery) then
+    OnQuery(Self, Value);
+end;
+
+//------------------------------------------------------------------------------
+// TSQLiteTable
+//------------------------------------------------------------------------------
+
+constructor TSQLiteTable.Create(DB: TSQLiteDatabase; const SQL: Ansistring);
+begin
+  Create(DB, SQL, []);
+end;
+
+constructor TSQLiteTable.Create(DB: TSQLiteDatabase; const SQL: Ansistring; const Bindings: array of const);
+var
+  Stmt: TSQLiteStmt;
+  NextSQLStatement: PAnsiChar;
+  iStepResult: integer;
+  ptr: pointer;
+  iNumBytes: integer;
+  thisBlobValue: TMemoryStream;
+  thisStringValue: pstring;
+  thisDoubleValue: pDouble;
+  thisIntValue: pInt64;
+  thisColType: pInteger;
+  i: integer;
+  DeclaredColType: PAnsiChar;
+  ActualColType: integer;
+  ptrValue: PAnsiChar;
+begin
+  inherited create;
+  try
+    self.fRowCount := 0;
+    self.fColCount := 0;
+    //if there are several SQL statements in SQL, NextSQLStatment points to the
+    //beginning of the next one. Prepare only prepares the first SQL statement.
+    if Sqlite3_Prepare_v2(DB.fDB, PAnsiChar(SQL), -1, Stmt, NextSQLStatement) <> SQLITE_OK then
+      DB.RaiseError('Error executing SQL', SQL);
+    if (Stmt = nil) then
+      DB.RaiseError('Could not prepare SQL statement', SQL);
+    DB.DoQuery(SQL);
+    DB.SetParams(Stmt);
+    DB.BindData(Stmt, Bindings);
+
+    iStepResult := Sqlite3_step(Stmt);
+    while (iStepResult <> SQLITE_DONE) do
+    begin
+      case iStepResult of
+        SQLITE_ROW:
+          begin
+            Inc(fRowCount);
+            if (fRowCount = 1) then
+            begin
+            //get data types
+              fCols := TStringList.Create;
+              fColTypes := TList.Create;
+              fColCount := SQLite3_ColumnCount(stmt);
+              for i := 0 to Pred(fColCount) do
+                fCols.Add(AnsiUpperCase(Sqlite3_ColumnName(stmt, i)));
+              for i := 0 to Pred(fColCount) do
+              begin
+                new(thisColType);
+                DeclaredColType := Sqlite3_ColumnDeclType(stmt, i);
+                if DeclaredColType = nil then
+                  thisColType^ := Sqlite3_ColumnType(stmt, i) //use the actual column type instead
+                //seems to be needed for last_insert_rowid
+                else
+                  if (DeclaredColType = 'INTEGER') or (DeclaredColType = 'BOOLEAN') then
+                    thisColType^ := dtInt
+                  else
+                    if (DeclaredColType = 'NUMERIC') or
+                      (DeclaredColType = 'FLOAT') or
+                      (DeclaredColType = 'DOUBLE') or
+                      (DeclaredColType = 'REAL') then
+                      thisColType^ := dtNumeric
+                    else
+                      if DeclaredColType = 'BLOB' then
+                        thisColType^ := dtBlob
+                      else
+                        thisColType^ := dtStr;
+                fColTypes.Add(thiscoltype);
+              end;
+              fResults := TList.Create;
+            end;
+
+          //get column values
+            for i := 0 to Pred(ColCount) do
+            begin
+              ActualColType := Sqlite3_ColumnType(stmt, i);
+              if (ActualColType = SQLITE_NULL) then
+                fResults.Add(nil)
+              else
+                if pInteger(fColTypes[i])^ = dtInt then
+                begin
+                  new(thisintvalue);
+                  thisintvalue^ := Sqlite3_ColumnInt64(stmt, i);
+                  fResults.Add(thisintvalue);
+                end
+                else
+                  if pInteger(fColTypes[i])^ = dtNumeric then
+                  begin
+                    new(thisdoublevalue);
+                    thisdoublevalue^ := Sqlite3_ColumnDouble(stmt, i);
+                    fResults.Add(thisdoublevalue);
+                  end
+                  else
+                    if pInteger(fColTypes[i])^ = dtBlob then
+                    begin
+                      iNumBytes := Sqlite3_ColumnBytes(stmt, i);
+                      if iNumBytes = 0 then
+                        thisblobvalue := nil
+                      else
+                      begin
+                        thisblobvalue := TMemoryStream.Create;
+                        thisblobvalue.position := 0;
+                        ptr := Sqlite3_ColumnBlob(stmt, i);
+                        thisblobvalue.writebuffer(ptr^, iNumBytes);
+                      end;
+                      fResults.Add(thisblobvalue);
+                    end
+                    else
+                    begin
+                      new(thisstringvalue);
+                      ptrValue := Sqlite3_ColumnText(stmt, i);
+                      setstring(thisstringvalue^, ptrvalue, strlen(ptrvalue));
+                      fResults.Add(thisstringvalue);
+                    end;
+            end;
+          end;
+        SQLITE_BUSY:
+          raise ESqliteException.CreateFmt('Could not prepare SQL statement',
+            [SQL, 'SQLite is Busy']);
+      else
+        begin
+        SQLite3_reset(stmt);
+        DB.RaiseError('Could not retrieve data', SQL);
+        end;
+      end;
+      iStepResult := Sqlite3_step(Stmt);
+    end;
+    fRow := 0;
+  finally
+    if Assigned(Stmt) then
+      Sqlite3_Finalize(stmt);
+  end;
+end;
+
+//..............................................................................
+
+destructor TSQLiteTable.Destroy;
+var
+  i: cardinal;
+  iColNo: integer;
+begin
+  if Assigned(fResults) then
+  begin
+    for i := 0 to fResults.Count - 1 do
+    begin
+      //check for blob type
+      iColNo := (i mod fColCount);
+      case pInteger(self.fColTypes[iColNo])^ of
+        dtBlob:
+          TMemoryStream(fResults[i]).Free;
+        dtStr:
+          if fResults[i] <> nil then
+          begin
+            setstring(string(fResults[i]^), nil, 0);
+            dispose(fResults[i]);
+          end;
+      else
+        dispose(fResults[i]);
+      end;
+    end;
+    fResults.Free;
+  end;
+  if Assigned(fCols) then
+    fCols.Free;
+  if Assigned(fColTypes) then
+    for i := 0 to fColTypes.Count - 1 do
+      dispose(fColTypes[i]);
+  fColTypes.Free;
+  inherited;
+end;
+
+//..............................................................................
+
+function TSQLiteTable.GetColumns(I: integer): string;
+begin
+  Result := fCols[I];
+end;
+
+//..............................................................................
+
+function TSQLiteTable.GetCountResult: integer;
+begin
+  if not EOF then
+    Result := StrToInt(Fields[0])
+  else
+    Result := 0;
+end;
+
+function TSQLiteTable.GetCount: integer;
+begin
+  Result := FRowCount;
+end;
+
+//..............................................................................
+
+function TSQLiteTable.GetEOF: boolean;
+begin
+  Result := fRow >= fRowCount;
+end;
+
+function TSQLiteTable.GetBOF: boolean;
+begin
+  Result := fRow <= 0;
+end;
+
+//..............................................................................
+
+function TSQLiteTable.GetFieldByName(FieldName: string): string;
+begin
+  Result := GetFields(self.GetFieldIndex(FieldName));
+end;
+
+function TSQLiteTable.GetFieldIndex(FieldName: string): integer;
+begin
+  if (fCols = nil) then
+  begin
+    raise ESqliteException.Create('Field ' + fieldname + ' Not found. Empty dataset');
+    exit;
+  end;
+
+  if (fCols.count = 0) then
+  begin
+    raise ESqliteException.Create('Field ' + fieldname + ' Not found. Empty dataset');
+    exit;
+  end;
+
+  Result := fCols.IndexOf(AnsiUpperCase(FieldName));
+
+  if (result < 0) then
+  begin
+    raise ESqliteException.Create('Field not found in dataset: ' + fieldname)
+  end;
+end;
+
+//..............................................................................
+
+function TSQLiteTable.GetFields(I: cardinal): string;
+var
+  thisvalue: pstring;
+  thistype: integer;
+begin
+  Result := '';
+  if EOF then
+    raise ESqliteException.Create('Table is at End of File');
+  //integer types are not stored in the resultset
+  //as strings, so they should be retrieved using the type-specific
+  //methods
+  thistype := pInteger(self.fColTypes[I])^;
+
+  case thistype of
+    dtStr:
+      begin
+        thisvalue := self.fResults[(self.frow * self.fColCount) + I];
+        if (thisvalue <> nil) then
+          Result := thisvalue^
+        else
+          Result := '';
+      end;
+    dtInt:
+      Result := IntToStr(self.FieldAsInteger(I));
+    dtNumeric:
+      Result := FloatToStr(self.FieldAsDouble(I));
+    dtBlob:
+      Result := self.FieldAsBlobText(I);
+  else
+    Result := '';
+  end;
+end;
+
+function TSqliteTable.FieldAsBlob(I: cardinal): TMemoryStream;
+begin
+  if EOF then
+    raise ESqliteException.Create('Table is at End of File');
+  if (self.fResults[(self.frow * self.fColCount) + I] = nil) then
+    Result := nil
+  else
+    if pInteger(self.fColTypes[I])^ = dtBlob then
+      Result := TMemoryStream(self.fResults[(self.frow * self.fColCount) + I])
+    else
+      raise ESqliteException.Create('Not a Blob field');
+end;
+
+function TSqliteTable.FieldAsBlobText(I: cardinal): string;
+var
+  MemStream: TMemoryStream;
+  Buffer: PAnsiChar;
+begin
+  Result := '';
+  MemStream := self.FieldAsBlob(I);
+  if MemStream <> nil then
+    if MemStream.Size > 0 then
+      begin
+        MemStream.position := 0;
+        {$IFDEF UNICODE}
+        Buffer := AnsiStralloc(MemStream.Size + 1);
+        {$ELSE}
+        Buffer := Stralloc(MemStream.Size + 1);
+        {$ENDIF}
+        MemStream.readbuffer(Buffer[0], MemStream.Size);
+        (Buffer + MemStream.Size)^ := chr(0);
+        SetString(Result, Buffer, MemStream.size);
+        strdispose(Buffer);
+      end;
+     //do not free the TMemoryStream here; it is freed when
+     //TSqliteTable is destroyed
+
+end;
+
+
+function TSqliteTable.FieldAsInteger(I: cardinal): int64;
+begin
+  if EOF then
+    raise ESqliteException.Create('Table is at End of File');
+  if (self.fResults[(self.frow * self.fColCount) + I] = nil) then
+    Result := 0
+  else
+    if pInteger(self.fColTypes[I])^ = dtInt then
+      Result := pInt64(self.fResults[(self.frow * self.fColCount) + I])^
+    else
+      if pInteger(self.fColTypes[I])^ = dtNumeric then
+        Result := trunc(strtofloat(pString(self.fResults[(self.frow * self.fColCount) + I])^))
+      else
+        raise ESqliteException.Create('Not an integer or numeric field');
+end;
+
+function TSqliteTable.FieldAsDouble(I: cardinal): double;
+begin
+  if EOF then
+    raise ESqliteException.Create('Table is at End of File');
+  if (self.fResults[(self.frow * self.fColCount) + I] = nil) then
+    Result := 0
+  else
+    if pInteger(self.fColTypes[I])^ = dtInt then
+      Result := pInt64(self.fResults[(self.frow * self.fColCount) + I])^
+    else
+      if pInteger(self.fColTypes[I])^ = dtNumeric then
+        Result := pDouble(self.fResults[(self.frow * self.fColCount) + I])^
+      else
+        raise ESqliteException.Create('Not an integer or numeric field');
+end;
+
+function TSqliteTable.FieldAsString(I: cardinal): string;
+begin
+  if EOF then
+    raise ESqliteException.Create('Table is at End of File');
+  if (self.fResults[(self.frow * self.fColCount) + I] = nil) then
+    Result := ''
+  else
+    Result := self.GetFields(I);
+end;
+
+function TSqliteTable.FieldIsNull(I: cardinal): boolean;
+var
+  thisvalue: pointer;
+begin
+  if EOF then
+    raise ESqliteException.Create('Table is at End of File');
+  thisvalue := self.fResults[(self.frow * self.fColCount) + I];
+  Result := (thisvalue = nil);
+end;
+
+//..............................................................................
+
+function TSQLiteTable.Next: boolean;
+begin
+  Result := False;
+  if not EOF then
+  begin
+    Inc(fRow);
+    Result := True;
+  end;
+end;
+
+function TSQLiteTable.Previous: boolean;
+begin
+  Result := False;
+  if not BOF then
+  begin
+    Dec(fRow);
+    Result := True;
+  end;
+end;
+
+function TSQLiteTable.MoveFirst: boolean;
+begin
+  Result := False;
+  if self.fRowCount > 0 then
+  begin
+    fRow := 0;
+    Result := True;
+  end;
+end;
+
+function TSQLiteTable.MoveLast: boolean;
+begin
+  Result := False;
+  if self.fRowCount > 0 then
+  begin
+    fRow := fRowCount - 1;
+    Result := True;
+  end;
+end;
+
+function TSQLiteTable.MoveTo(position: cardinal): boolean;
+begin
+  Result := False;
+  if (self.fRowCount > 0) and (self.fRowCount > position) then
+  begin
+    fRow := position;
+    Result := True;
+  end;
+end;
+
+
+
+{ TSQLiteUniTable }
+
+constructor TSQLiteUniTable.Create(DB: TSQLiteDatabase; const SQL: Ansistring);
+begin
+  Create(DB, SQL, []);
+end;
+
+constructor TSQLiteUniTable.Create(DB: TSQLiteDatabase; const SQL: Ansistring; const Bindings: array of const);
+var
+  NextSQLStatement: PAnsiChar;
+  i: integer;
+begin
+  inherited create;
+  self.fDB := db;
+  self.fEOF := false;
+  self.fRow := 0;
+  self.fColCount := 0;
+  self.fSQL := SQL;
+  if Sqlite3_Prepare_v2(DB.fDB, PAnsiChar(SQL), -1, fStmt, NextSQLStatement) <> SQLITE_OK then
+    DB.RaiseError('Error executing SQL', SQL);
+  if (fStmt = nil) then
+    DB.RaiseError('Could not prepare SQL statement', SQL);
+  DB.DoQuery(SQL);
+  DB.SetParams(fStmt);
+  DB.BindData(fStmt, Bindings);
+
+  //get data types
+  fCols := TStringList.Create;
+  fColCount := SQLite3_ColumnCount(fstmt);
+  for i := 0 to Pred(fColCount) do
+    fCols.Add(AnsiUpperCase(Sqlite3_ColumnName(fstmt, i)));
+
+  Next;
+end;
+
+destructor TSQLiteUniTable.Destroy;
+begin
+  if Assigned(fStmt) then
+    Sqlite3_Finalize(fstmt);
+  if Assigned(fCols) then
+    fCols.Free;
+  inherited;
+end;
+
+function TSQLiteUniTable.FieldAsBlob(I: cardinal): TMemoryStream;
+var
+  iNumBytes: integer;
+  ptr: pointer;
+begin
+  Result := TMemoryStream.Create;
+  iNumBytes := Sqlite3_ColumnBytes(fstmt, i);
+  if iNumBytes > 0 then
+  begin
+    ptr := Sqlite3_ColumnBlob(fstmt, i);
+    Result.writebuffer(ptr^, iNumBytes);
+    Result.Position := 0;
+  end;
+end;
+
+function TSQLiteUniTable.FieldAsBlobPtr(I: cardinal; out iNumBytes: integer): Pointer;
+begin
+  iNumBytes := Sqlite3_ColumnBytes(fstmt, i);
+  Result := Sqlite3_ColumnBlob(fstmt, i);
+end;
+
+function TSQLiteUniTable.FieldAsBlobText(I: cardinal): string;
+var
+  MemStream: TMemoryStream;
+  Buffer: PAnsiChar;
+begin
+  Result := '';
+  MemStream := self.FieldAsBlob(I);
+  if MemStream <> nil then
+    try
+      if MemStream.Size > 0 then
+      begin
+        MemStream.position := 0;
+        {$IFDEF UNICODE}
+        Buffer := AnsiStralloc(MemStream.Size + 1);
+        {$ELSE}
+        Buffer := Stralloc(MemStream.Size + 1);
+        {$ENDIF}
+        MemStream.readbuffer(Buffer[0], MemStream.Size);
+        (Buffer + MemStream.Size)^ := chr(0);
+        SetString(Result, Buffer, MemStream.size);
+        strdispose(Buffer);
+      end;
+    finally
+      MemStream.Free;
+    end;
+end;
+
+function TSQLiteUniTable.FieldAsDouble(I: cardinal): double;
+begin
+  Result := Sqlite3_ColumnDouble(fstmt, i);
+end;
+
+function TSQLiteUniTable.FieldAsInteger(I: cardinal): int64;
+begin
+  Result := Sqlite3_ColumnInt64(fstmt, i);
+end;
+
+function TSQLiteUniTable.FieldAsString(I: cardinal): string;
+begin
+  Result := self.GetFields(I);
+end;
+
+function TSQLiteUniTable.FieldIsNull(I: cardinal): boolean;
+begin
+  Result := Sqlite3_ColumnText(fstmt, i) = nil;
+end;
+
+function TSQLiteUniTable.GetColumns(I: integer): string;
+begin
+  Result := fCols[I];
+end;
+
+function TSQLiteUniTable.GetFieldByName(FieldName: string): string;
+begin
+  Result := GetFields(self.GetFieldIndex(FieldName));
+end;
+
+function TSQLiteUniTable.GetFieldIndex(FieldName: string): integer;
+begin
+  if (fCols = nil) then
+  begin
+    raise ESqliteException.Create('Field ' + fieldname + ' Not found. Empty dataset');
+    exit;
+  end;
+
+  if (fCols.count = 0) then
+  begin
+    raise ESqliteException.Create('Field ' + fieldname + ' Not found. Empty dataset');
+    exit;
+  end;
+
+  Result := fCols.IndexOf(AnsiUpperCase(FieldName));
+
+  if (result < 0) then
+  begin
+    raise ESqliteException.Create('Field not found in dataset: ' + fieldname)
+  end;
+end;
+
+function TSQLiteUniTable.GetFields(I: cardinal): string;
+begin
+  Result := Sqlite3_ColumnText(fstmt, i);
+end;
+
+function TSQLiteUniTable.Next: boolean;
+var
+  iStepResult: integer;
+begin
+  fEOF := true;
+  iStepResult := Sqlite3_step(fStmt);
+  case iStepResult of
+    SQLITE_ROW:
+      begin
+        fEOF := false;
+        inc(fRow);
+      end;
+    SQLITE_DONE:
+      // we are on the end of dataset
+      // return EOF=true only
+      ;
+  else
+    begin
+    SQLite3_reset(fStmt);
+    fDB.RaiseError('Could not retrieve data', fSQL);
+    end;
+  end;
+  Result := not fEOF;
+end;
+
+end.
+
diff --git a/songmanagement/src/lib/SQLite/example/Sunset.jpg b/songmanagement/src/lib/SQLite/example/Sunset.jpg
new file mode 100644
index 00000000..860f6eec
Binary files /dev/null and b/songmanagement/src/lib/SQLite/example/Sunset.jpg differ
diff --git a/songmanagement/src/lib/SQLite/example/TestSqlite.dpr b/songmanagement/src/lib/SQLite/example/TestSqlite.dpr
new file mode 100644
index 00000000..596a3a04
--- /dev/null
+++ b/songmanagement/src/lib/SQLite/example/TestSqlite.dpr
@@ -0,0 +1,15 @@
+program TestSqlite;
+
+uses
+  Forms,
+  uTestSqlite in 'uTestSqlite.pas' {Form1},
+  SQLiteTable3 in 'SQLiteTable3.pas',
+  SQLite3 in 'SQLite3.pas';
+
+{$R *.res}
+
+begin
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.
diff --git a/songmanagement/src/lib/SQLite/example/TestSqlite.res b/songmanagement/src/lib/SQLite/example/TestSqlite.res
new file mode 100644
index 00000000..4bdd5e2e
Binary files /dev/null and b/songmanagement/src/lib/SQLite/example/TestSqlite.res differ
diff --git a/songmanagement/src/lib/SQLite/example/uTestSqlite.dfm b/songmanagement/src/lib/SQLite/example/uTestSqlite.dfm
new file mode 100644
index 00000000..6b4a2aaf
--- /dev/null
+++ b/songmanagement/src/lib/SQLite/example/uTestSqlite.dfm
@@ -0,0 +1,110 @@
+object Form1: TForm1
+  Left = 199
+  Top = 280
+  Width = 541
+  Height = 308
+  Caption = 'Test SQLite 3'
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'MS Sans Serif'
+  Font.Style = []
+  OldCreateOrder = False
+  PixelsPerInch = 96
+  TextHeight = 13
+  object Label1: TLabel
+    Left = 24
+    Top = 104
+    Width = 28
+    Height = 13
+    Caption = 'Notes'
+  end
+  object Label2: TLabel
+    Left = 24
+    Top = 44
+    Width = 28
+    Height = 13
+    Caption = 'Name'
+  end
+  object Label3: TLabel
+    Left = 24
+    Top = 72
+    Width = 40
+    Height = 13
+    Caption = 'Number:'
+  end
+  object Label4: TLabel
+    Left = 24
+    Top = 12
+    Width = 11
+    Height = 13
+    Caption = 'ID'
+  end
+  object Image1: TImage
+    Left = 272
+    Top = 12
+    Width = 241
+    Height = 165
+    Proportional = True
+    Stretch = True
+  end
+  object btnTest: TButton
+    Left = 24
+    Top = 224
+    Width = 161
+    Height = 37
+    Caption = 'Test SQLite 3'
+    TabOrder = 0
+    OnClick = btnTestClick
+  end
+  object memNotes: TMemo
+    Left = 24
+    Top = 124
+    Width = 185
+    Height = 89
+    Lines.Strings = (
+      '')
+    ScrollBars = ssVertical
+    TabOrder = 1
+  end
+  object ebName: TEdit
+    Left = 72
+    Top = 40
+    Width = 173
+    Height = 21
+    TabOrder = 2
+  end
+  object ebNumber: TEdit
+    Left = 72
+    Top = 68
+    Width = 173
+    Height = 21
+    TabOrder = 3
+  end
+  object ebID: TEdit
+    Left = 72
+    Top = 12
+    Width = 173
+    Height = 21
+    TabOrder = 4
+  end
+  object btnLoadImage: TButton
+    Left = 192
+    Top = 224
+    Width = 157
+    Height = 37
+    Caption = 'Load image'
+    TabOrder = 5
+    OnClick = btnLoadImageClick
+  end
+  object btnDisplayImage: TButton
+    Left = 360
+    Top = 224
+    Width = 157
+    Height = 37
+    Caption = 'Display image'
+    TabOrder = 6
+    OnClick = btnDisplayImageClick
+  end
+end
diff --git a/songmanagement/src/lib/SQLite/example/uTestSqlite.pas b/songmanagement/src/lib/SQLite/example/uTestSqlite.pas
new file mode 100644
index 00000000..484be71c
--- /dev/null
+++ b/songmanagement/src/lib/SQLite/example/uTestSqlite.pas
@@ -0,0 +1,233 @@
+unit uTestSqlite;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls,SQLiteTable3, ExtCtrls, jpeg;
+
+type
+  TForm1 = class(TForm)
+    btnTest: TButton;
+    memNotes: TMemo;
+    Label1: TLabel;
+    Label2: TLabel;
+    ebName: TEdit;
+    Label3: TLabel;
+    ebNumber: TEdit;
+    Label4: TLabel;
+    ebID: TEdit;
+    Image1: TImage;
+    btnLoadImage: TButton;
+    btnDisplayImage: TButton;
+    procedure btnTestClick(Sender: TObject);
+    procedure btnLoadImageClick(Sender: TObject);
+    procedure btnDisplayImageClick(Sender: TObject);
+  private
+    { Private declarations }
+  public
+    { Public declarations }
+  end;
+
+var
+  Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+procedure TForm1.btnTestClick(Sender: TObject);
+var
+slDBpath: string;
+sldb: TSQLiteDatabase;
+sltb: TSQLIteTable;
+sSQL: String;
+Notes: String;
+
+begin
+
+slDBPath := ExtractFilepath(application.exename)
++ 'test.db';
+
+sldb := TSQLiteDatabase.Create(slDBPath);
+try
+
+if sldb.TableExists('testTable') then begin
+sSQL := 'DROP TABLE testtable';
+sldb.execsql(sSQL);
+end;
+
+sSQL := 'CREATE TABLE testtable ([ID] INTEGER PRIMARY KEY,[OtherID] INTEGER NULL,';
+sSQL := sSQL + '[Name] VARCHAR (255),[Number] FLOAT, [notes] BLOB, [picture] BLOB COLLATE NOCASE);';
+
+sldb.execsql(sSQL);
+
+sldb.execsql('CREATE INDEX TestTableName ON [testtable]([Name]);');
+
+//begin a transaction
+sldb.BeginTransaction;
+
+sSQL := 'INSERT INTO testtable(Name,OtherID,Number,Notes) VALUES ("Some Name",4,587.6594,"Here are some notes");';
+//do the insert
+sldb.ExecSQL(sSQL);
+
+sSQL := 'INSERT INTO testtable(Name,OtherID,Number,Notes) VALUES ("Another Name",12,4758.3265,"More notes");';
+//do the insert
+sldb.ExecSQL(sSQL);
+
+//end the transaction
+sldb.Commit;
+
+//query the data
+sltb := slDb.GetTable('SELECT * FROM testtable');
+try
+
+if sltb.Count > 0 then
+begin
+//display first row
+
+ebName.Text := sltb.FieldAsString(sltb.FieldIndex['Name']);
+ebID.Text := inttostr(sltb.FieldAsInteger(sltb.FieldIndex['ID']));
+ebNumber.Text := floattostr( sltb.FieldAsDouble(sltb.FieldIndex['Number']));
+Notes :=  sltb.FieldAsBlobText(sltb.FieldIndex['Notes']);
+memNotes.Text := notes;
+
+end;
+
+finally
+sltb.Free;
+end;
+
+finally
+sldb.Free;
+
+end;
+
+end;
+
+procedure TForm1.btnLoadImageClick(Sender: TObject);
+var
+slDBpath: string;
+sldb: TSQLiteDatabase;
+sltb: TSQLIteTable;
+iID: integer;
+fs: TFileStream;
+
+begin
+
+slDBPath := ExtractFilepath(application.exename)
++ 'test.db';
+
+if not FileExists(slDBPath) then begin
+MessageDLg('Test.db does not exist. Click Test Sqlite 3 to create it.',mtInformation,[mbOK],0);
+exit;
+end;
+
+sldb := TSQLiteDatabase.Create(slDBPath);
+try
+
+//get an ID
+//query the data
+sltb := slDb.GetTable('SELECT ID FROM testtable');
+try
+
+if sltb.Count = 0 then begin
+MessageDLg('There are no rows in the database. Click Test Sqlite 3 to insert a row.',mtInformation,[mbOK],0);
+exit;
+end;
+
+iID := sltb.FieldAsInteger(sltb.FieldIndex['ID']);
+
+finally
+sltb.Free;
+end;
+
+//load an image
+fs := TFileStream.Create(ExtractFileDir(application.ExeName) + '\sunset.jpg',fmOpenRead);
+try
+
+//insert the image into the db
+sldb.UpdateBlob('UPDATE testtable set picture = ? WHERE ID = ' + inttostr(iID),fs);
+
+finally
+fs.Free;
+end;
+
+finally
+sldb.Free;
+
+end;
+
+end;
+
+procedure TForm1.btnDisplayImageClick(Sender: TObject);
+var
+slDBpath: string;
+sldb: TSQLiteDatabase;
+sltb: TSQLIteTable;
+iID: integer;
+ms: TMemoryStream;
+pic: TJPegImage;
+
+begin
+
+slDBPath := ExtractFilepath(application.exename)
++ 'test.db';
+
+if not FileExists(slDBPath) then begin
+MessageDLg('Test.db does not exist. Click Test Sqlite 3 to create it, then Load image to load an image.',mtInformation,[mbOK],0);
+exit;
+end;
+
+sldb := TSQLiteDatabase.Create(slDBPath);
+try
+
+//get an ID
+//query the data
+sltb := slDb.GetTable('SELECT ID FROM testtable');
+try
+
+if not sltb.Count = 0 then begin
+MessageDLg('No rows in the test database. Click Test Sqlite 3 to insert a row, then Load image to load an image.',mtInformation,[mbOK],0);
+exit;
+end;
+
+iID := sltb.FieldAsInteger(sltb.FieldIndex['ID']);
+
+finally
+sltb.Free;
+end;
+
+sltb := sldb.GetTable('SELECT picture FROM testtable where ID = ' + inttostr(iID));
+try
+
+ms := sltb.FieldAsBlob(sltb.FieldIndex['picture']);
+//note that the memory stream is freed when the TSqliteTable is destroyed.
+
+if (ms = nil) then begin
+MessageDLg('No image in the test database. Click Load image to load an image.',mtInformation,[mbOK],0);
+exit;
+end;
+
+ms.Position := 0;
+
+pic := TJPEGImage.Create;
+pic.LoadFromStream(ms);
+
+self.Image1.Picture.Graphic := pic;
+
+pic.Free;
+
+finally
+sltb.Free;
+end;
+
+finally
+sldb.Free;
+
+end;
+
+
+end;
+
+end.
diff --git a/songmanagement/src/lib/SQLite/readme.txt b/songmanagement/src/lib/SQLite/readme.txt
new file mode 100644
index 00000000..7998d17f
--- /dev/null
+++ b/songmanagement/src/lib/SQLite/readme.txt
@@ -0,0 +1,93 @@
+5 June 2008
+Updated DLL to version 3.5.9 (built with MSVC 6.0)
+Added code from Andrew Retmanski to support prepared queries (see comments in SQLIteTable3.pas
+Lukas added support for named parameters - see comments in code
+User nebula enhanced error message; also modified code to call sqlite3_reset before checking error message
+
+
+27 Aug 2007
+Amended TSQLiteDatabase constructor to convert filename to UTF8,for compatibility with latest SQLite3 DLL.
+
+Updated DLL to version 3.4.2 (built with MSVC 6.0).
+
+14 Aug 2005
+
+The following changes were made by Lukas Gebauer (geby@volny.cz). In addition, some changes from a previous D5-compatible version were merged, and the supplied sqlite3.dll is updated to version 3.2.2
+
+Notes from Lukas:
+
+- added support for delphi 4+
+
+- datatype constants matches SQlite datatypes contants. (otherwise in some situations you got bad column datatype!)
+
+- removed dependency on strutils
+
+- code is reformatted to better look (official borland formatting rules)
+
+- added some pragma's after database is open (temp is in memory)
+
+- TSQLiteDatabase.GetTableValue(const SQL: string): int64 for easy call of SQL commands what returning one number only. (like select
+count(*)...)
+
+- TSQLiteDatabase.GetTableString(const SQL: string): String for easy call of SQL commands what returning one string only. (like PRAGMA
+integrity_check)
+
+- TSQLiteDatabase.SetTimeout(Value: integer); you can set timeout for accessing to some table. Good for database sharing!
+
+- TSQLiteDatabase.version: string; returns SQLITE version string
+
+- removed bool fieldtype (it is not natural SQLite3 type)
+
+- fild type detection by Sqite3_columnType knows REAL too.
+
+- integer filedtype is based on Int64
+
+- GetFields can get data from any supported fieldtype
+
+- changed some integers to cardinal for avoid signed and unsigned mismatch
+
+- TSqliteTable.FieldAsInteger(I: cardinal): int64; returns int64
+
+
+3 May 2005 Fixed bug where strupper called on column type before checking for nil
+
+2 May 2005 Add extra check for nil in TSqliteTable.Destroy, thanks to Tim Maddrell
+
+22 Apr 2005 Revise TSqliteTable.Destroy to fix memory leak with dtStr type (thanks to
+Jose Brito)
+
+21 Apr 2005 Quick revision to fix case sensitivity in detecting column type,
+and remove PRAGMA full_column_names = 1 which is deprecated. Warning: may break code. Fix your SQL code so that all column names in a result set are unique.
+
+21 Feb 2005 Sqlite DLL now 3.1.3 
+
+19 Feb 2005 Revised for Sqlite 3.1.2 
+
+21 Dec 2004 First public release 
+
+The following notice appears in the Sqlite source code:
+
+*
+** 2001 September 15
+**
+** 
+** The author disclaims copyright to this source code.  In place of
+
+** a legal notice, here is a blessing:
+
+**
+ May you do good and not evil.
+
+** May you find forgiveness for yourself and forgive others.
+
+** May you share freely, never taking more than you give.
+
+
+For more information about SQLite, see http://www.sqlite.org
+
+For more information about this simple wrapper, see http://www.itwriting.com/sqlitesimple.php
+
+
+
+
+
diff --git a/songmanagement/src/lib/TntUnicodeControls/License.txt b/songmanagement/src/lib/TntUnicodeControls/License.txt
new file mode 100644
index 00000000..8ac7f75b
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/License.txt
@@ -0,0 +1,11 @@
+TntWare Delphi Unicode Controls
+      http://www.tntware.com/delphicontrols/unicode/
+
+Copyright (c) 2002-2007, Troy Wolbrink (www.tntware.com) 
+
+License
+Redistribution and use in binary forms, with or without modification, are permitted.  Redistribution and use in source forms, with or without modification, are permitted provided that the redistributions of source code retain the above copyright.
+
+Disclaimer
+This software is provided by the author "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the author be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
+
diff --git a/songmanagement/src/lib/TntUnicodeControls/Readme.txt b/songmanagement/src/lib/TntUnicodeControls/Readme.txt
new file mode 100644
index 00000000..a2d8f799
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/Readme.txt
@@ -0,0 +1,53 @@
+  ** Tnt Delphi UNICODE Controls Project **
+
+Website: http://tnt.ccci.org/delphi_unicode_controls/
+Email: troy.wolbrink@ccci.org
+
+These controls are provided as-is, with no implied warranty.  They are freely available for you to use in your own projects.  Please let me know if you have found them helpful.  Also, please let me know if you find any bugs or other areas of needed improvement.
+
+
+---Delphi Installation--------------------------
+
+The most simple way to install these components is by opening the appropriate design package in Delphi and clicking on the big "Install" button.  For instance, Delphi 5's design package is TntUnicodeVcl_D50.dpk.
+
+For BCB 2006 and newer, open the appropriate design package in the packages\bcbx\ folder using the Delphi personality.  After compiling and installing, you should be able to use the components in both the Delphi and BCB personality.  Remember to set the library path in menu "Tools->Options" for both the C++ Builder and the Delphi.
+
+
+---A note on fonts----------------------
+
+The default TFont uses "MS Sans Serif" which doesn't work well with most non-ANSI characters.  I'd recommend using a TrueType font such as "Tahoma" if it is installed on the machine.  To make TFont use a different font like "Tahoma" add this to the first line in the project:
+
+  Graphics.DefFontData.Name := 'Tahoma';
+
+You might have to include "Graphics" in the file's uses clauses.  Furthermore, adding this line of code to the project will cause the changed setting to only be applied at runtime, not at design time.  To make a designtime change, you'd have to add this line to the initialization section of a unit in a design package.
+
+Regarding the IDE, I use GExperts to change the font of the Object Inspector.  The Wide String List editor uses the font used by the object inspector.
+
+Also keep in mind that the font used by certain message boxes come from that set by Windows' Display properties.
+
+
+---Background----------------------------
+
+Designing software for an international audience, I've always wanted to write a full UNICODE application.  My approach so far, has been to write Unicode on the inside, and MBCS on the outside.  This has always been frustrating, because (even on Windows NT/2000/XP which provide native Unicode window controls) the WideStrings inside my application and databases were always confined to an ANSI VCL.  And, since the VCL was designed to wrap the low-level Windows details, why shouldn't the VCL hide the fact that sometimes native Unicode controls are not possible on the given version of Windows.  I believe the VCL should be written with a Unicode interface, even if it must (at times) deal with an ANSI operating system.  For example, TEdit should expose Text as a WideString, even if it has to convert the WideString to an AnsiString on the Windows 9X platform.
+
+In the past, the ANSI VCL may have made a little sense, considering that there were many more users of Windows 9X, than Windows NT.  There would have been some performance penalty to use WideStrings on the Windows 9X platform.  But with the faster computers of today, and with more people using platforms such as Windows 2000 and Windows XP, the ANSI VCL just doesn't make sense anymore.  In fact, having to use the the ANSI VCL on Windows NT/2000/XP is slower because of the constant conversion to and from UNICODE inside Windows.
+
+My coding signature is Tnt.  I will use this to denote my classes from others.
+
+For more information about me: <http://home.ccci.org/wolbrink/>
+Some of my software projects (all written in Delphi).
+    TntMPD (contact manager for missionaries)
+      <http://www.tntmpd.com/>
+    Jesus Film Screen Saver
+      <http://home.ccci.org/wolbrink/screensaver.htm>
+    ActiveX SCR control
+      <http://tnt.ccci.org/download/activex_scr/ActiveXSCR.exe>
+
+---Design Goals----------------------------
+
+I want the controls to work on Windows 95, 98, ME, NT, 2000, XP, etc.  I want a single EXE for all platforms.  Of course, full UNICODE support is only truly available on NT/2000/XP.  In other words, the controls should automatically scale to take advantage of native Unicode support when possible.
+
+I want the controls to inherit from the Delphi VCL.  I want to reuse as much code as possible.  For the most part this makes sense.  The only sticky part is where text messages get passed around.  But I believe I've gotten past this through strategic subclassing at various points in the message flow chain.  To give a rough comparison of why this is so important, check out the following chart which compares the lines of code in the VCL for a given control (4,397 in all), and the lines of code required in my descendent controls (655 in all).  Besides saving lines of code, I get the advantage of automatically inheriting new features as new versions of Delphi come out.  One such example is the AlphaBlending feature in the Delphi 6 TForm.  Even though I use Delphi 5 now, I won't have to add any code to get this new feature.
+
+---More Interesting Information----------------------------
+Case Study: Porting an MFC Application to Unicode:  It looks like the FrontPage 2002 team did the roughly the same thing to MFC as what I'm doing to the VCL.  They did this with the same goal in mind: to support Unicode as much as possible depending on the support offered by Windows.  Another goal was "Don�t abandon MFC; don�t rewrite app".  Because they still want to support Windows 9X using the same worldwide EXE used everywhere.  They couldn't just compile with the _UNICODE directive.  They had to start with the ANSI MFC, strategically subclassing window procedures at just the right places.  Hmmm... sounds familiar.
\ No newline at end of file
diff --git a/songmanagement/src/lib/TntUnicodeControls/TntClasses.pas b/songmanagement/src/lib/TntUnicodeControls/TntClasses.pas
new file mode 100644
index 00000000..f0ebd14c
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/TntClasses.pas
@@ -0,0 +1,1806 @@
+
+{*****************************************************************************}
+{                                                                             }
+{    Tnt Delphi Unicode Controls                                              }
+{      http://www.tntware.com/delphicontrols/unicode/                         }
+{        Version: 2.3.0                                                       }
+{                                                                             }
+{    Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com)       }
+{                                                                             }
+{*****************************************************************************}
+
+unit TntClasses;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$INCLUDE TntCompilers.inc}
+
+interface
+
+{ TODO: Consider: TTntRegIniFile, TTntMemIniFile (consider if UTF8 fits into this solution). }
+
+{***********************************************}
+{  WideChar-streaming implemented by Ma�l H�rz  }
+{***********************************************}
+
+uses
+  Classes, SysUtils, Windows,
+  {$IFNDEF COMPILER_10_UP}
+  TntWideStrings,
+  {$ELSE}
+  WideStrings,
+  {$ENDIF}
+  ActiveX, Contnrs;
+
+// ......... introduced .........
+type
+  TTntStreamCharSet = (csAnsi, csUnicode, csUnicodeSwapped, csUtf8);
+
+function AutoDetectCharacterSet(Stream: TStream): TTntStreamCharSet;
+
+//---------------------------------------------------------------------------------------------
+//                                 Tnt - Classes
+//---------------------------------------------------------------------------------------------
+
+{TNT-WARN ExtractStrings}
+{TNT-WARN LineStart}
+{TNT-WARN TStringStream}   // TODO: Implement a TWideStringStream
+
+// A potential implementation of TWideStringStream can be found at:
+//   http://kdsxml.cvs.sourceforge.net/kdsxml/Global/KDSClasses.pas?revision=1.10&view=markup
+
+procedure TntPersistent_AfterInherited_DefineProperties(Filer: TFiler; Instance: TPersistent);
+
+type
+{TNT-WARN TFileStream}
+  TTntFileStream = class(THandleStream)
+  public
+    constructor Create(const FileName: WideString; Mode: Word);
+    destructor Destroy; override;
+  end;
+
+{TNT-WARN TMemoryStream}
+  TTntMemoryStream = class(TMemoryStream{TNT-ALLOW TMemoryStream})
+  public
+    procedure LoadFromFile(const FileName: WideString);
+    procedure SaveToFile(const FileName: WideString);
+  end;
+
+{TNT-WARN TResourceStream}
+  TTntResourceStream = class(TCustomMemoryStream)
+  private
+    HResInfo: HRSRC;
+    HGlobal: THandle;
+    procedure Initialize(Instance: THandle; Name, ResType: PWideChar);
+  public
+    constructor Create(Instance: THandle; const ResName: WideString; ResType: PWideChar);
+    constructor CreateFromID(Instance: THandle; ResID: Word; ResType: PWideChar);
+    destructor Destroy; override;
+    function Write(const Buffer; Count: Longint): Longint; override;
+    procedure SaveToFile(const FileName: WideString);
+  end;
+
+  TTntStrings = class;
+
+{TNT-WARN TAnsiStrings}
+  TAnsiStrings{TNT-ALLOW TAnsiStrings} = class(TStrings{TNT-ALLOW TStrings})
+  public
+    procedure LoadFromFile(const FileName: WideString); reintroduce;
+    procedure SaveToFile(const FileName: WideString); reintroduce;
+    procedure LoadFromFileEx(const FileName: WideString; CodePage: Cardinal);
+    procedure SaveToFileEx(const FileName: WideString; CodePage: Cardinal);
+    procedure LoadFromStreamEx(Stream: TStream; CodePage: Cardinal); virtual; abstract;
+    procedure SaveToStreamEx(Stream: TStream; CodePage: Cardinal); virtual; abstract;
+  end;
+
+  TAnsiStringsForWideStringsAdapter = class(TAnsiStrings{TNT-ALLOW TAnsiStrings})
+  private
+    FWideStrings: TTntStrings;
+    FAdapterCodePage: Cardinal;
+  protected
+    function Get(Index: Integer): AnsiString; override;
+    procedure Put(Index: Integer; const S: AnsiString); override;
+    function GetCount: Integer; override;
+    function GetObject(Index: Integer): TObject; override;
+    procedure PutObject(Index: Integer; AObject: TObject); override;
+    procedure SetUpdateState(Updating: Boolean); override;
+    function AdapterCodePage: Cardinal; dynamic;
+  public
+    constructor Create(AWideStrings: TTntStrings; _AdapterCodePage: Cardinal = 0);
+    procedure Clear; override;
+    procedure Delete(Index: Integer); override;
+    procedure Insert(Index: Integer; const S: AnsiString); override;
+    procedure LoadFromStreamEx(Stream: TStream; CodePage: Cardinal); override;
+    procedure SaveToStreamEx(Stream: TStream; CodePage: Cardinal); override;
+  end;
+
+{TNT-WARN TStrings}
+  TTntStrings = class(TWideStrings)
+  private
+    FLastFileCharSet: TTntStreamCharSet;
+    FAnsiStrings: TAnsiStrings{TNT-ALLOW TAnsiStrings};
+    procedure SetAnsiStrings(const Value: TAnsiStrings{TNT-ALLOW TAnsiStrings});
+    procedure ReadData(Reader: TReader);
+    procedure ReadDataUTF7(Reader: TReader);
+    procedure ReadDataUTF8(Reader: TReader);
+    procedure WriteDataUTF7(Writer: TWriter);
+  protected
+    procedure DefineProperties(Filer: TFiler); override;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    procedure LoadFromFile(const FileName: WideString); override;
+    procedure LoadFromStream(Stream: TStream); override;
+    procedure LoadFromStream_BOM(Stream: TStream; WithBOM: Boolean); virtual;
+
+    procedure SaveToFile(const FileName: WideString); override;
+    procedure SaveToStream(Stream: TStream); override;
+    procedure SaveToStream_BOM(Stream: TStream; WithBOM: Boolean); virtual;
+
+    property LastFileCharSet: TTntStreamCharSet read FLastFileCharSet;
+  published
+    property AnsiStrings: TAnsiStrings{TNT-ALLOW TAnsiStrings} read FAnsiStrings write SetAnsiStrings stored False;
+  end;
+
+{ TTntStringList class }
+
+  TTntStringList = class;
+  TWideStringListSortCompare = function(List: TTntStringList; Index1, Index2: Integer): Integer;
+
+{TNT-WARN TStringList}
+  TTntStringList = class(TTntStrings)
+  private
+    FUpdating: Boolean;
+    FList: PWideStringItemList;
+    FCount: Integer;
+    FCapacity: Integer;
+    FSorted: Boolean;
+    FDuplicates: TDuplicates;
+    FCaseSensitive: Boolean;
+    FOnChange: TNotifyEvent;
+    FOnChanging: TNotifyEvent;
+    procedure ExchangeItems(Index1, Index2: Integer);
+    procedure Grow;
+    procedure QuickSort(L, R: Integer; SCompare: TWideStringListSortCompare);
+    procedure SetSorted(Value: Boolean);
+    procedure SetCaseSensitive(const Value: Boolean);
+  protected
+    procedure Changed; virtual;
+    procedure Changing; virtual;
+    function Get(Index: Integer): WideString; override;
+    function GetCapacity: Integer; override;
+    function GetCount: Integer; override;
+    function GetObject(Index: Integer): TObject; override;
+    procedure Put(Index: Integer; const S: WideString); override;
+    procedure PutObject(Index: Integer; AObject: TObject); override;
+    procedure SetCapacity(NewCapacity: Integer); override;
+    procedure SetUpdateState(Updating: Boolean); override;
+    function CompareStrings(const S1, S2: WideString): Integer; override;
+    procedure InsertItem(Index: Integer; const S: WideString; AObject: TObject); virtual;
+  public
+    destructor Destroy; override;
+    function Add(const S: WideString): Integer; override;
+    function AddObject(const S: WideString; AObject: TObject): Integer; override;
+    procedure Clear; override;
+    procedure Delete(Index: Integer); override;
+    procedure Exchange(Index1, Index2: Integer); override;
+    function Find(const S: WideString; var Index: Integer): Boolean; virtual;
+    function IndexOf(const S: WideString): Integer; override;
+    function IndexOfName(const Name: WideString): Integer; override;
+    procedure Insert(Index: Integer; const S: WideString); override;
+    procedure InsertObject(Index: Integer; const S: WideString;
+      AObject: TObject); override;
+    procedure Sort; virtual;
+    procedure CustomSort(Compare: TWideStringListSortCompare); virtual;
+    property Duplicates: TDuplicates read FDuplicates write FDuplicates;
+    property Sorted: Boolean read FSorted write SetSorted;
+    property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
+    property OnChange: TNotifyEvent read FOnChange write FOnChange;
+    property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
+  end;
+
+// ......... introduced .........
+type
+  TListTargetCompare = function (Item, Target: Pointer): Integer;
+
+function FindSortedListByTarget(List: TList; TargetCompare: TListTargetCompare;
+  Target: Pointer; var Index: Integer): Boolean;
+
+function ClassIsRegistered(const clsid: TCLSID): Boolean;
+
+var
+  RuntimeUTFStreaming: Boolean;
+
+type
+  TBufferedAnsiString = class(TObject)
+  private
+    FStringBuffer: AnsiString;
+    LastWriteIndex: Integer;
+  public
+    procedure Clear;
+    procedure AddChar(const wc: AnsiChar);
+    procedure AddString(const s: AnsiString);
+    procedure AddBuffer(Buff: PAnsiChar; Chars: Integer);
+    function Value: AnsiString;
+    function BuffPtr: PAnsiChar;
+  end;
+
+  TBufferedWideString = class(TObject)
+  private
+    FStringBuffer: WideString;
+    LastWriteIndex: Integer;
+  public
+    procedure Clear;
+    procedure AddChar(const wc: WideChar);
+    procedure AddString(const s: WideString);
+    procedure AddBuffer(Buff: PWideChar; Chars: Integer);
+    function Value: WideString;
+    function BuffPtr: PWideChar;
+  end;
+
+  TBufferedStreamReader = class(TStream)
+  private
+    FStream: TStream;
+    FStreamSize: Integer;
+    FBuffer: array of Byte;
+    FBufferSize: Integer;
+    FBufferStartPosition: Integer;
+    FVirtualPosition: Integer;
+    procedure UpdateBufferFromPosition(StartPos: Integer);
+  public
+    constructor Create(Stream: TStream; BufferSize: Integer = 1024);
+    function Read(var Buffer; Count: Longint): Longint; override;
+    function Write(const Buffer; Count: Longint): Longint; override;
+    function Seek(Offset: Longint; Origin: Word): Longint; override;
+  end;
+
+// "synced" wide string
+type TSetAnsiStrEvent = procedure(const Value: AnsiString) of object;
+function GetSyncedWideString(var WideStr: WideString; const AnsiStr: AnsiString): WideString;
+procedure SetSyncedWideString(const Value: WideString; var WideStr: WideString;
+  const AnsiStr: AnsiString; SetAnsiStr: TSetAnsiStrEvent);
+
+type
+  TWideComponentHelper = class(TComponent)
+  private
+    FComponent: TComponent;
+  protected
+    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+  public
+    constructor Create(AOwner: TComponent); override;
+    constructor CreateHelper(AOwner: TComponent; ComponentHelperList: TComponentList);
+  end;
+
+function FindWideComponentHelper(ComponentHelperList: TComponentList; Component: TComponent): TWideComponentHelper;
+
+implementation
+
+uses
+  RTLConsts, ComObj, Math,
+  Registry, TypInfo, TntSystem, TntSysUtils;
+
+{ TntPersistent }
+
+//===========================================================================
+//   The Delphi 5 Classes.pas never supported the streaming of WideStrings.
+//   The Delphi 6 Classes.pas supports WideString streaming.  But it's too bad that
+//     the Delphi 6 IDE doesn't use the updated Classes.pas.  Switching between Form/Text
+//       mode corrupts extended characters in WideStrings even under Delphi 6.
+//   Delphi 7 seems to finally get right.  But let's keep the UTF7 support at design time
+//     to enable sharing source code with previous versions of Delphi.
+//
+//   The purpose of this solution is to store WideString properties which contain
+//     non-ASCII chars in the form of UTF7 under the old property name + '_UTF7'.
+//
+//   Special thanks go to Francisco Leong for helping to develop this solution.
+//
+
+{ TTntWideStringPropertyFiler }
+type
+  TTntWideStringPropertyFiler = class
+  private
+    FInstance: TPersistent;
+    FPropInfo: PPropInfo;
+    procedure ReadDataUTF8(Reader: TReader);
+    procedure ReadDataUTF7(Reader: TReader);
+    procedure WriteDataUTF7(Writer: TWriter);
+  public
+    procedure DefineProperties(Filer: TFiler; Instance: TPersistent; PropName: AnsiString);
+  end;
+
+function ReaderNeedsUtfHelp(Reader: TReader): Boolean;
+begin
+  if Reader.Owner = nil then
+    Result := False { designtime - visual form inheritance ancestor }
+  else if csDesigning in Reader.Owner.ComponentState then
+    {$IFDEF COMPILER_7_UP}
+    Result := False { Delphi 7+: designtime - doesn't need UTF help. }
+    {$ELSE}
+    Result := True { Delphi 6: designtime - always needs UTF help. }
+    {$ENDIF}
+  else
+    Result := RuntimeUTFStreaming; { runtime }
+end;
+
+procedure TTntWideStringPropertyFiler.ReadDataUTF8(Reader: TReader);
+begin
+  if ReaderNeedsUtfHelp(Reader) then
+    SetWideStrProp(FInstance, FPropInfo, UTF8ToWideString(Reader.ReadString))
+  else
+    Reader.ReadString; { do nothing with Result }
+end;
+
+procedure TTntWideStringPropertyFiler.ReadDataUTF7(Reader: TReader);
+begin
+  if ReaderNeedsUtfHelp(Reader) then
+    SetWideStrProp(FInstance, FPropInfo, UTF7ToWideString(Reader.ReadString))
+  else
+    Reader.ReadString; { do nothing with Result }
+end;
+
+procedure TTntWideStringPropertyFiler.WriteDataUTF7(Writer: TWriter);
+begin
+  Writer.WriteString(WideStringToUTF7(GetWideStrProp(FInstance, FPropInfo)));
+end;
+
+procedure TTntWideStringPropertyFiler.DefineProperties(Filer: TFiler; Instance: TPersistent;
+  PropName: AnsiString);
+
+  {$IFNDEF COMPILER_7_UP}
+  function HasData: Boolean;
+  var
+    CurrPropValue: WideString;
+  begin
+    // must be stored
+    Result := IsStoredProp(Instance, FPropInfo);
+    if Result
+    and (Filer.Ancestor <> nil)
+    and (GetPropInfo(Filer.Ancestor, PropName, [tkWString]) <> nil) then
+    begin
+      // must be different than ancestor
+      CurrPropValue := GetWideStrProp(Instance, FPropInfo);
+      Result := CurrPropValue <> GetWideStrProp(Filer.Ancestor, GetPropInfo(Filer.Ancestor, PropName));
+    end;
+    if Result then begin
+      // must be non-blank and different than UTF8 (implies all ASCII <= 127)
+      CurrPropValue := GetWideStrProp(Instance, FPropInfo);
+      Result := (CurrPropValue <> '') and (WideStringToUTF8(CurrPropValue) <> CurrPropValue);
+    end;
+  end;
+  {$ENDIF}
+
+begin
+  FInstance := Instance;
+  FPropInfo := GetPropInfo(Instance, PropName, [tkWString]);
+  if FPropInfo <> nil then begin
+    // must be published (and of type WideString)
+    Filer.DefineProperty(PropName + 'W', ReadDataUTF8, nil, False);
+    {$IFDEF COMPILER_7_UP}
+    Filer.DefineProperty(PropName + '_UTF7', ReadDataUTF7, WriteDataUTF7, False);
+    {$ELSE}
+    Filer.DefineProperty(PropName + '_UTF7', ReadDataUTF7, WriteDataUTF7, HasData);
+    {$ENDIF}
+  end;
+  FInstance := nil;
+  FPropInfo := nil;
+end;
+
+{ TTntWideCharPropertyFiler }
+type
+  TTntWideCharPropertyFiler = class
+  private
+    FInstance: TPersistent;
+    FPropInfo: PPropInfo;
+    {$IFNDEF COMPILER_9_UP}
+    FWriter: TWriter;
+    procedure GetLookupInfo(var Ancestor: TPersistent;
+      var Root, LookupRoot, RootAncestor: TComponent);
+    {$ENDIF}
+    procedure ReadData_W(Reader: TReader);
+    procedure ReadDataUTF7(Reader: TReader);
+    procedure WriteData_W(Writer: TWriter);
+    function ReadChar(Reader: TReader): WideChar;
+  public
+    procedure DefineProperties(Filer: TFiler; Instance: TPersistent; PropName: AnsiString);
+  end;
+
+{$IFNDEF COMPILER_9_UP}
+type
+  TGetLookupInfoEvent = procedure(var Ancestor: TPersistent;
+    var Root, LookupRoot, RootAncestor: TComponent) of object;
+
+function AncestorIsValid(Ancestor: TPersistent; Root, RootAncestor: TComponent): Boolean;
+begin
+  Result := (Ancestor <> nil) and (RootAncestor <> nil) and
+            Root.InheritsFrom(RootAncestor.ClassType);
+end;
+
+function IsDefaultOrdPropertyValue(Instance: TObject; PropInfo: PPropInfo;
+  OnGetLookupInfo: TGetLookupInfoEvent): Boolean;
+var
+  Ancestor: TPersistent;
+  LookupRoot: TComponent;
+  RootAncestor: TComponent;
+  Root: TComponent;
+  AncestorValid: Boolean;
+  Value: Longint;
+  Default: LongInt;
+begin
+  Ancestor := nil;
+  Root := nil;
+  LookupRoot := nil;
+  RootAncestor := nil;
+
+  if Assigned(OnGetLookupInfo) then
+    OnGetLookupInfo(Ancestor, Root, LookupRoot, RootAncestor);
+
+  AncestorValid := AncestorIsValid(Ancestor, Root, RootAncestor);
+
+  Result := True;
+  if (PropInfo^.GetProc <> nil) and (PropInfo^.SetProc <> nil) then
+  begin
+    Value := GetOrdProp(Instance, PropInfo);
+    if AncestorValid then
+      Result := Value = GetOrdProp(Ancestor, PropInfo)
+    else
+    begin
+      Default := PPropInfo(PropInfo)^.Default;
+      Result :=  (Default <> LongInt($80000000)) and (Value = Default);
+    end;
+  end;
+end;
+
+procedure TTntWideCharPropertyFiler.GetLookupInfo(var Ancestor: TPersistent;
+  var Root, LookupRoot, RootAncestor: TComponent);
+begin
+  Ancestor := FWriter.Ancestor;
+  Root := FWriter.Root;
+  LookupRoot := FWriter.LookupRoot;
+  RootAncestor := FWriter.RootAncestor;
+end;
+{$ENDIF}
+
+function TTntWideCharPropertyFiler.ReadChar(Reader: TReader): WideChar;
+var
+  Temp: WideString;
+begin
+  case Reader.NextValue of
+    vaWString:
+      Temp := Reader.ReadWideString;
+    vaString:
+      Temp := Reader.ReadString;
+    else
+      raise EReadError.Create(SInvalidPropertyValue);
+  end;
+
+  if Length(Temp) > 1 then
+    raise EReadError.Create(SInvalidPropertyValue);
+  Result := Temp[1];
+end;
+
+procedure TTntWideCharPropertyFiler.ReadData_W(Reader: TReader);
+begin
+  SetOrdProp(FInstance, FPropInfo, Ord(ReadChar(Reader)));
+end;
+
+procedure TTntWideCharPropertyFiler.ReadDataUTF7(Reader: TReader);
+var
+  S: WideString;
+begin
+  S := UTF7ToWideString(Reader.ReadString);
+  if S = '' then
+    SetOrdProp(FInstance, FPropInfo, 0)
+  else
+    SetOrdProp(FInstance, FPropInfo, Ord(S[1]))
+end;
+
+type TAccessWriter = class(TWriter);
+
+procedure TTntWideCharPropertyFiler.WriteData_W(Writer: TWriter);
+var
+  L: Integer;
+  Temp: WideString;
+{$IFDEF FPC}
+// Workaround: the Buffer parameter of TWriter.Write() must be of a fixed size
+// type for FPC >= 2.4.0. The values vaWString, Ord(vaWString) or Integer(vaWString)
+// are not allowed anymore.
+const
+  vaWStringInt: integer = Ord(vaWString);
+{$ENDIF}
+begin
+  Temp := WideChar(GetOrdProp(FInstance, FPropInfo));
+
+  {$IFNDEF FPC}
+  TAccessWriter(Writer).WriteValue(vaWString);
+  {$ELSE}
+  TAccessWriter(Writer).Write(vaWStringInt, SizeOf(vaWString));
+  {$ENDIF}
+  L := Length(Temp);
+  Writer.Write(L, SizeOf(Integer));
+  Writer.Write(Pointer(@Temp[1])^, L * 2);
+end;
+
+procedure TTntWideCharPropertyFiler.DefineProperties(Filer: TFiler;
+  Instance: TPersistent; PropName: AnsiString);
+
+  {$IFNDEF COMPILER_9_UP}
+  function HasData: Boolean;
+  var
+    CurrPropValue: Integer;
+  begin
+    // must be stored
+    Result := IsStoredProp(Instance, FPropInfo);
+    if Result and (Filer.Ancestor <> nil) and
+      (GetPropInfo(Filer.Ancestor, PropName, [tkWChar]) <> nil) then
+    begin
+      // must be different than ancestor
+      CurrPropValue := GetOrdProp(Instance, FPropInfo);
+      Result := CurrPropValue <> GetOrdProp(Filer.Ancestor, GetPropInfo(Filer.Ancestor, PropName));
+    end;
+    if Result and (Filer is TWriter) then
+    begin
+      FWriter := TWriter(Filer);
+      Result := not IsDefaultOrdPropertyValue(Instance, FPropInfo, GetLookupInfo);
+    end;
+  end;
+  {$ENDIF}
+
+begin
+  FInstance := Instance;
+  FPropInfo := GetPropInfo(Instance, PropName, [tkWChar]);
+  if FPropInfo <> nil then
+  begin
+    // must be published (and of type WideChar)
+    {$IFDEF COMPILER_9_UP}
+    Filer.DefineProperty(PropName + 'W', ReadData_W, WriteData_W, False);
+    {$ELSE}
+    Filer.DefineProperty(PropName + 'W', ReadData_W, WriteData_W, HasData);
+    {$ENDIF}
+    Filer.DefineProperty(PropName + '_UTF7', ReadDataUTF7, nil, False);
+  end;
+  FInstance := nil;
+  FPropInfo := nil;
+end;
+
+procedure TntPersistent_AfterInherited_DefineProperties(Filer: TFiler; Instance: TPersistent);
+var
+  I, Count: Integer;
+  PropInfo: PPropInfo;
+  PropList: PPropList;
+  WideStringFiler: TTntWideStringPropertyFiler;
+  WideCharFiler: TTntWideCharPropertyFiler;
+begin
+  Count := GetTypeData(Instance.ClassInfo)^.PropCount;
+  if Count > 0 then
+  begin
+    WideStringFiler := TTntWideStringPropertyFiler.Create;
+    try
+      WideCharFiler := TTntWideCharPropertyFiler.Create;
+      try
+        GetMem(PropList, Count * SizeOf(Pointer));
+        try
+          GetPropInfos(Instance.ClassInfo, PropList);
+          for I := 0 to Count - 1 do
+          begin
+            PropInfo := PropList^[I];
+            if (PropInfo = nil) then
+              break;
+            if (PropInfo.PropType^.Kind = tkWString) then
+              WideStringFiler.DefineProperties(Filer, Instance, PropInfo.Name)
+            else if (PropInfo.PropType^.Kind = tkWChar) then
+              WideCharFiler.DefineProperties(Filer, Instance, PropInfo.Name)
+          end;
+        finally
+          FreeMem(PropList, Count * SizeOf(Pointer));
+        end;
+      finally
+        WideCharFiler.Free;
+      end;
+    finally
+      WideStringFiler.Free;
+    end;
+  end;
+end;
+
+{ TTntFileStream }
+
+{$IFDEF FPC}
+  {$DEFINE HAS_SFCREATEERROREX}
+{$ENDIF}
+{$IFDEF DELPHI_7_UP}
+  {$DEFINE HAS_SFCREATEERROREX}
+{$ENDIF}
+
+constructor TTntFileStream.Create(const FileName: WideString; Mode: Word);
+var
+  CreateHandle: Integer;
+  {$IFDEF HAS_SFCREATEERROREX}
+  ErrorMessage: WideString;
+  {$ENDIF}
+begin
+  if Mode = fmCreate then
+  begin
+    CreateHandle := WideFileCreate(FileName);
+    if CreateHandle < 0 then begin
+      {$IFDEF HAS_SFCREATEERROREX}
+      ErrorMessage := WideSysErrorMessage(GetLastError);
+      raise EFCreateError.CreateFmt(SFCreateErrorEx, [WideExpandFileName(FileName), ErrorMessage]);
+      {$ELSE}
+      raise EFCreateError.CreateFmt(SFCreateError, [WideExpandFileName(FileName)]);
+      {$ENDIF}
+    end;
+  end else
+  begin
+    CreateHandle := WideFileOpen(FileName, Mode);
+    if CreateHandle < 0 then begin
+      {$IFDEF HAS_SFCREATEERROREX}
+      ErrorMessage := WideSysErrorMessage(GetLastError);
+      raise EFOpenError.CreateFmt(SFOpenErrorEx, [WideExpandFileName(FileName), ErrorMessage]);
+      {$ELSE}
+      raise EFOpenError.CreateFmt(SFOpenError, [WideExpandFileName(FileName)]);
+      {$ENDIF}
+    end;
+  end;
+  inherited Create(CreateHandle);
+end;
+
+destructor TTntFileStream.Destroy;
+begin
+  if Handle >= 0 then FileClose(Handle);
+end;
+
+{ TTntMemoryStream }
+
+procedure TTntMemoryStream.LoadFromFile(const FileName: WideString);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+  try
+    LoadFromStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+procedure TTntMemoryStream.SaveToFile(const FileName: WideString);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmCreate);
+  try
+    SaveToStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+{ TTntResourceStream }
+
+constructor TTntResourceStream.Create(Instance: THandle; const ResName: WideString;
+  ResType: PWideChar);
+begin
+  inherited Create;
+  Initialize(Instance, PWideChar(ResName), ResType);
+end;
+
+constructor TTntResourceStream.CreateFromID(Instance: THandle; ResID: Word;
+  ResType: PWideChar);
+begin
+  inherited Create;
+  Initialize(Instance, PWideChar(ResID), ResType);
+end;
+
+procedure TTntResourceStream.Initialize(Instance: THandle; Name, ResType: PWideChar);
+
+  procedure Error;
+  begin
+    raise EResNotFound.CreateFmt(SResNotFound, [Name]);
+  end;
+
+begin
+  HResInfo := FindResourceW(Instance, Name, ResType);
+  if HResInfo = 0 then Error;
+  HGlobal := LoadResource(Instance, HResInfo);
+  if HGlobal = 0 then Error;
+  SetPointer(LockResource(HGlobal), SizeOfResource(Instance, HResInfo));
+end;
+
+destructor TTntResourceStream.Destroy;
+begin
+  UnlockResource(HGlobal);
+  FreeResource(HGlobal); { Technically this is not necessary (MS KB #193678) }
+  inherited Destroy;
+end;
+
+function TTntResourceStream.Write(const Buffer; Count: Longint): Longint;
+begin
+  raise EStreamError.CreateRes(PResStringRec(@SCantWriteResourceStreamError));
+end;
+
+procedure TTntResourceStream.SaveToFile(const FileName: WideString);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmCreate);
+  try
+    SaveToStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+{ TAnsiStrings }
+
+procedure TAnsiStrings{TNT-ALLOW TAnsiStrings}.LoadFromFile(const FileName: WideString);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+  try
+    LoadFromStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+procedure TAnsiStrings{TNT-ALLOW TAnsiStrings}.SaveToFile(const FileName: WideString);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmCreate);
+  try
+    SaveToStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+procedure TAnsiStrings{TNT-ALLOW TAnsiStrings}.LoadFromFileEx(const FileName: WideString; CodePage: Cardinal);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+  try
+    LoadFromStreamEx(Stream, CodePage);
+  finally
+    Stream.Free;
+  end;
+end;
+
+procedure TAnsiStrings{TNT-ALLOW TAnsiStrings}.SaveToFileEx(const FileName: WideString; CodePage: Cardinal);
+var
+  Stream: TStream;
+  Utf8BomPtr: PAnsiChar;
+begin
+  Stream := TTntFileStream.Create(FileName, fmCreate);
+  try
+    if (CodePage = CP_UTF8) then
+    begin
+      Utf8BomPtr := PAnsiChar(UTF8_BOM);
+      Stream.WriteBuffer(Utf8BomPtr^, Length(UTF8_BOM));
+    end;
+    SaveToStreamEx(Stream, CodePage);
+  finally
+    Stream.Free;
+  end;
+end;
+
+{ TAnsiStringsForWideStringsAdapter }
+
+constructor TAnsiStringsForWideStringsAdapter.Create(AWideStrings: TTntStrings; _AdapterCodePage: Cardinal);
+begin
+  inherited Create;
+  FWideStrings := AWideStrings;
+  FAdapterCodePage := _AdapterCodePage;
+end;
+
+function TAnsiStringsForWideStringsAdapter.AdapterCodePage: Cardinal;
+begin
+  if FAdapterCodePage = 0 then
+    Result := TntSystem.DefaultSystemCodePage
+  else
+    Result := FAdapterCodePage;
+end;
+
+procedure TAnsiStringsForWideStringsAdapter.Clear;
+begin
+  FWideStrings.Clear;
+end;
+
+procedure TAnsiStringsForWideStringsAdapter.Delete(Index: Integer);
+begin
+  FWideStrings.Delete(Index);
+end;
+
+function TAnsiStringsForWideStringsAdapter.Get(Index: Integer): AnsiString;
+begin
+  Result := WideStringToStringEx(FWideStrings.Get(Index), AdapterCodePage);
+end;
+
+procedure TAnsiStringsForWideStringsAdapter.Put(Index: Integer; const S: AnsiString);
+begin
+  FWideStrings.Put(Index, StringToWideStringEx(S, AdapterCodePage));
+end;
+
+function TAnsiStringsForWideStringsAdapter.GetCount: Integer;
+begin
+  Result := FWideStrings.GetCount;
+end;
+
+procedure TAnsiStringsForWideStringsAdapter.Insert(Index: Integer; const S: AnsiString);
+begin
+  FWideStrings.Insert(Index, StringToWideStringEx(S, AdapterCodePage));
+end;
+
+function TAnsiStringsForWideStringsAdapter.GetObject(Index: Integer): TObject;
+begin
+  Result := FWideStrings.GetObject(Index);
+end;
+
+procedure TAnsiStringsForWideStringsAdapter.PutObject(Index: Integer; AObject: TObject);
+begin
+  FWideStrings.PutObject(Index, AObject);
+end;
+
+procedure TAnsiStringsForWideStringsAdapter.SetUpdateState(Updating: Boolean);
+begin
+  FWideStrings.SetUpdateState(Updating);
+end;
+
+procedure TAnsiStringsForWideStringsAdapter.LoadFromStreamEx(Stream: TStream; CodePage: Cardinal);
+var
+  Size: Integer;
+  S: AnsiString;
+begin
+  BeginUpdate;
+  try
+    Size := Stream.Size - Stream.Position;
+    SetString(S, nil, Size);
+    Stream.Read(Pointer(S)^, Size);
+    FWideStrings.SetTextStr(StringToWideStringEx(S, CodePage));
+  finally
+    EndUpdate;
+  end;
+end;
+
+procedure TAnsiStringsForWideStringsAdapter.SaveToStreamEx(Stream: TStream; CodePage: Cardinal);
+var
+  S: AnsiString;
+begin
+  S := WideStringToStringEx(FWideStrings.GetTextStr, CodePage);
+  Stream.WriteBuffer(Pointer(S)^, Length(S));
+end;
+
+{ TTntStrings }
+
+constructor TTntStrings.Create;
+begin
+  inherited;
+  FAnsiStrings := TAnsiStringsForWideStringsAdapter.Create(Self);
+  FLastFileCharSet := csUnicode;
+end;
+
+destructor TTntStrings.Destroy;
+begin
+  FreeAndNil(FAnsiStrings);
+  inherited;
+end;
+
+procedure TTntStrings.SetAnsiStrings(const Value: TAnsiStrings{TNT-ALLOW TAnsiStrings});
+begin
+  FAnsiStrings.Assign(Value);
+end;
+
+procedure TTntStrings.DefineProperties(Filer: TFiler);
+
+  {$IFNDEF COMPILER_7_UP}
+  function DoWrite: Boolean;
+  begin
+    if Filer.Ancestor <> nil then
+    begin
+      Result := True;
+      if Filer.Ancestor is TWideStrings then
+        Result := not Equals(TWideStrings(Filer.Ancestor))
+    end
+    else Result := Count > 0;
+  end;
+
+  function DoWriteAsUTF7: Boolean;
+  var
+    i: integer;
+  begin
+    Result := False;
+    for i := 0 to Count - 1 do begin
+      if (Strings[i] <> '') and (WideStringToUTF8(Strings[i]) <> Strings[i]) then begin
+        Result := True;
+        break; { found a string with non-ASCII chars (> 127) }
+      end;
+    end;
+  end;
+  {$ENDIF}
+
+begin
+  inherited DefineProperties(Filer); { Handles main 'Strings' property.' }
+  Filer.DefineProperty('WideStrings', ReadData, nil, False);
+  Filer.DefineProperty('WideStringsW', ReadDataUTF8, nil, False);
+  {$IFDEF COMPILER_7_UP}
+  Filer.DefineProperty('WideStrings_UTF7', ReadDataUTF7, WriteDataUTF7, False);
+  {$ELSE}
+  Filer.DefineProperty('WideStrings_UTF7', ReadDataUTF7, WriteDataUTF7, DoWrite and DoWriteAsUTF7);
+  {$ENDIF}
+end;
+
+procedure TTntStrings.LoadFromFile(const FileName: WideString);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+  try
+    FLastFileCharSet := AutoDetectCharacterSet(Stream);
+    Stream.Position := 0;
+    LoadFromStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+procedure TTntStrings.LoadFromStream(Stream: TStream);
+begin
+  LoadFromStream_BOM(Stream, True);
+end;
+
+procedure TTntStrings.LoadFromStream_BOM(Stream: TStream; WithBOM: Boolean);
+var
+  DataLeft: Integer;
+  StreamCharSet: TTntStreamCharSet;
+  SW: WideString;
+  SA: AnsiString;
+begin
+  BeginUpdate;
+  try
+    if WithBOM then
+      StreamCharSet := AutoDetectCharacterSet(Stream)
+    else
+      StreamCharSet := csUnicode;
+    DataLeft := Stream.Size - Stream.Position;
+    if (StreamCharSet in [csUnicode, csUnicodeSwapped]) then
+    begin
+      // BOM indicates Unicode text stream
+      if DataLeft < SizeOf(WideChar) then
+        SW := ''
+      else begin
+        SetLength(SW, DataLeft div SizeOf(WideChar));
+        Stream.Read(PWideChar(SW)^, DataLeft);
+        if StreamCharSet = csUnicodeSwapped then
+          StrSwapByteOrder(PWideChar(SW));
+      end;
+      SetTextStr(SW);
+    end
+    else if StreamCharSet = csUtf8 then
+    begin
+      // BOM indicates UTF-8 text stream
+      SetLength(SA, DataLeft div SizeOf(AnsiChar));
+      Stream.Read(PAnsiChar(SA)^, DataLeft);
+      SetTextStr(UTF8ToWideString(SA));
+    end
+    else
+    begin
+      // without byte order mark it is assumed that we are loading ANSI text
+      SetLength(SA, DataLeft div SizeOf(AnsiChar));
+      Stream.Read(PAnsiChar(SA)^, DataLeft);
+      SetTextStr(SA);
+    end;
+  finally
+    EndUpdate;
+  end;
+end;
+
+procedure TTntStrings.ReadData(Reader: TReader);
+begin
+  if Reader.NextValue in [vaString, vaLString] then
+    SetTextStr(Reader.ReadString) {JCL compatiblity}
+  else if Reader.NextValue = vaWString then
+    SetTextStr(Reader.ReadWideString) {JCL compatiblity}
+  else begin
+    BeginUpdate;
+    try
+      Clear;
+      Reader.ReadListBegin;
+      while not Reader.EndOfList do
+        if Reader.NextValue in [vaString, vaLString] then
+          Add(Reader.ReadString) {TStrings compatiblity}
+        else
+          Add(Reader.ReadWideString);
+      Reader.ReadListEnd;
+    finally
+      EndUpdate;
+    end;
+  end;
+end;
+
+procedure TTntStrings.ReadDataUTF7(Reader: TReader);
+begin
+  Reader.ReadListBegin;
+  if ReaderNeedsUtfHelp(Reader) then
+  begin
+    BeginUpdate;
+    try
+      Clear;
+      while not Reader.EndOfList do
+        Add(UTF7ToWideString(Reader.ReadString))
+    finally
+      EndUpdate;
+    end;
+  end else begin
+    while not Reader.EndOfList do
+      Reader.ReadString; { do nothing with Result }
+  end;
+  Reader.ReadListEnd;
+end;
+
+procedure TTntStrings.ReadDataUTF8(Reader: TReader);
+begin
+  Reader.ReadListBegin;
+  if ReaderNeedsUtfHelp(Reader)
+  or (Count = 0){ Legacy support where 'WideStrings' was never written in lieu of WideStringsW }
+  then begin
+    BeginUpdate;
+    try
+      Clear;
+      while not Reader.EndOfList do
+        Add(UTF8ToWideString(Reader.ReadString))
+    finally
+      EndUpdate;
+    end;
+  end else begin
+    while not Reader.EndOfList do
+      Reader.ReadString; { do nothing with Result }
+  end;
+  Reader.ReadListEnd;
+end;
+
+procedure TTntStrings.SaveToFile(const FileName: WideString);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmCreate);
+  try
+    SaveToStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+procedure TTntStrings.SaveToStream(Stream: TStream);
+begin
+  SaveToStream_BOM(Stream, True);
+end;
+
+procedure TTntStrings.SaveToStream_BOM(Stream: TStream; WithBOM: Boolean);
+// Saves the currently loaded text into the given stream.
+// WithBOM determines whether to write a byte order mark or not.
+var
+  SW: WideString;
+  BOM: WideChar;
+begin
+  if WithBOM then begin
+    BOM := UNICODE_BOM;
+    Stream.WriteBuffer(BOM, SizeOf(WideChar));
+  end;
+  SW := GetTextStr;
+  Stream.WriteBuffer(PWideChar(SW)^, Length(SW) * SizeOf(WideChar));
+end;
+
+procedure TTntStrings.WriteDataUTF7(Writer: TWriter);
+var
+  I: Integer;
+begin
+  Writer.WriteListBegin;
+  for I := 0 to Count-1 do
+    Writer.WriteString(WideStringToUTF7(Get(I)));
+  Writer.WriteListEnd;
+end;
+
+{ TTntStringList }
+
+destructor TTntStringList.Destroy;
+begin
+  FOnChange := nil;
+  FOnChanging := nil;
+  inherited Destroy;
+  if FCount <> 0 then Finalize(FList^[0], FCount);
+  FCount := 0;
+  SetCapacity(0);
+end;
+
+function TTntStringList.Add(const S: WideString): Integer;
+begin
+  Result := AddObject(S, nil);
+end;
+
+function TTntStringList.AddObject(const S: WideString; AObject: TObject): Integer;
+begin
+  if not Sorted then
+    Result := FCount
+  else
+    if Find(S, Result) then
+      case Duplicates of
+        dupIgnore: Exit;
+        dupError: Error(PResStringRec(@SDuplicateString), 0);
+      end;
+  InsertItem(Result, S, AObject);
+end;
+
+procedure TTntStringList.Changed;
+begin
+  if (not FUpdating) and Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TTntStringList.Changing;
+begin
+  if (not FUpdating) and Assigned(FOnChanging) then
+    FOnChanging(Self);
+end;
+
+procedure TTntStringList.Clear;
+begin
+  if FCount <> 0 then
+  begin
+    Changing;
+    Finalize(FList^[0], FCount);
+    FCount := 0;
+    SetCapacity(0);
+    Changed;
+  end;
+end;
+
+procedure TTntStringList.Delete(Index: Integer);
+begin
+  if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
+  Changing;
+  Finalize(FList^[Index]);
+  Dec(FCount);
+  if Index < FCount then
+    System.Move(FList^[Index + 1], FList^[Index],
+      (FCount - Index) * SizeOf(TWideStringItem));
+  Changed;
+end;
+
+procedure TTntStringList.Exchange(Index1, Index2: Integer);
+begin
+  if (Index1 < 0) or (Index1 >= FCount) then Error(PResStringRec(@SListIndexError), Index1);
+  if (Index2 < 0) or (Index2 >= FCount) then Error(PResStringRec(@SListIndexError), Index2);
+  Changing;
+  ExchangeItems(Index1, Index2);
+  Changed;
+end;
+
+procedure TTntStringList.ExchangeItems(Index1, Index2: Integer);
+var
+  Temp: Integer;
+  Item1, Item2: PWideStringItem;
+begin
+  Item1 := @FList^[Index1];
+  Item2 := @FList^[Index2];
+  Temp := Integer(Item1^.FString);
+  Integer(Item1^.FString) := Integer(Item2^.FString);
+  Integer(Item2^.FString) := Temp;
+  Temp := Integer(Item1^.FObject);
+  Integer(Item1^.FObject) := Integer(Item2^.FObject);
+  Integer(Item2^.FObject) := Temp;
+end;
+
+function TTntStringList.Find(const S: WideString; var Index: Integer): Boolean;
+var
+  L, H, I, C: Integer;
+begin
+  Result := False;
+  L := 0;
+  H := FCount - 1;
+  while L <= H do
+  begin
+    I := (L + H) shr 1;
+    C := CompareStrings(FList^[I].FString, S);
+    if C < 0 then L := I + 1 else
+    begin
+      H := I - 1;
+      if C = 0 then
+      begin
+        Result := True;
+        if Duplicates <> dupAccept then L := I;
+      end;
+    end;
+  end;
+  Index := L;
+end;
+
+function TTntStringList.Get(Index: Integer): WideString;
+begin
+  if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
+  Result := FList^[Index].FString;
+end;
+
+function TTntStringList.GetCapacity: Integer;
+begin
+  Result := FCapacity;
+end;
+
+function TTntStringList.GetCount: Integer;
+begin
+  Result := FCount;
+end;
+
+function TTntStringList.GetObject(Index: Integer): TObject;
+begin
+  if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
+  Result := FList^[Index].FObject;
+end;
+
+procedure TTntStringList.Grow;
+var
+  Delta: Integer;
+begin
+  if FCapacity > 64 then Delta := FCapacity div 4 else
+    if FCapacity > 8 then Delta := 16 else
+      Delta := 4;
+  SetCapacity(FCapacity + Delta);
+end;
+
+function TTntStringList.IndexOf(const S: WideString): Integer;
+begin
+  if not Sorted then Result := inherited IndexOf(S) else
+    if not Find(S, Result) then Result := -1;
+end;
+
+function TTntStringList.IndexOfName(const Name: WideString): Integer;
+var
+  NameKey: WideString;
+begin
+  if not Sorted then
+    Result := inherited IndexOfName(Name)
+  else begin
+    // use sort to find index more quickly
+    NameKey := Name + NameValueSeparator;
+    Find(NameKey, Result);
+    if (Result < 0) or (Result > Count - 1) then
+      Result := -1
+    else if CompareStrings(NameKey, Copy(Strings[Result], 1, Length(NameKey))) <> 0 then
+      Result := -1
+  end;
+end;
+
+procedure TTntStringList.Insert(Index: Integer; const S: WideString);
+begin
+  InsertObject(Index, S, nil);
+end;
+
+procedure TTntStringList.InsertObject(Index: Integer; const S: WideString;
+  AObject: TObject);
+begin
+  if Sorted then Error(PResStringRec(@SSortedListError), 0);
+  if (Index < 0) or (Index > FCount) then Error(PResStringRec(@SListIndexError), Index);
+  InsertItem(Index, S, AObject);
+end;
+
+procedure TTntStringList.InsertItem(Index: Integer; const S: WideString; AObject: TObject);
+begin
+  Changing;
+  if FCount = FCapacity then Grow;
+  if Index < FCount then
+    System.Move(FList^[Index], FList^[Index + 1],
+      (FCount - Index) * SizeOf(TWideStringItem));
+  with FList^[Index] do
+  begin
+    Pointer(FString) := nil;
+    FObject := AObject;
+    FString := S;
+  end;
+  Inc(FCount);
+  Changed;
+end;
+
+procedure TTntStringList.Put(Index: Integer; const S: WideString);
+begin
+  if Sorted then Error(PResStringRec(@SSortedListError), 0);
+  if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
+  Changing;
+  FList^[Index].FString := S;
+  Changed;
+end;
+
+procedure TTntStringList.PutObject(Index: Integer; AObject: TObject);
+begin
+  if (Index < 0) or (Index >= FCount) then Error(PResStringRec(@SListIndexError), Index);
+  Changing;
+  FList^[Index].FObject := AObject;
+  Changed;
+end;
+
+procedure TTntStringList.QuickSort(L, R: Integer; SCompare: TWideStringListSortCompare);
+var
+  I, J, P: Integer;
+begin
+  repeat
+    I := L;
+    J := R;
+    P := (L + R) shr 1;
+    repeat
+      while SCompare(Self, I, P) < 0 do Inc(I);
+      while SCompare(Self, J, P) > 0 do Dec(J);
+      if I <= J then
+      begin
+        ExchangeItems(I, J);
+        if P = I then
+          P := J
+        else if P = J then
+          P := I;
+        Inc(I);
+        Dec(J);
+      end;
+    until I > J;
+    if L < J then QuickSort(L, J, SCompare);
+    L := I;
+  until I >= R;
+end;
+
+procedure TTntStringList.SetCapacity(NewCapacity: Integer);
+begin
+  ReallocMem(FList, NewCapacity * SizeOf(TWideStringItem));
+  FCapacity := NewCapacity;
+end;
+
+procedure TTntStringList.SetSorted(Value: Boolean);
+begin
+  if FSorted <> Value then
+  begin
+    if Value then Sort;
+    FSorted := Value;
+  end;
+end;
+
+procedure TTntStringList.SetUpdateState(Updating: Boolean);
+begin
+  FUpdating := Updating;
+  if Updating then Changing else Changed;
+end;
+
+function WideStringListCompareStrings(List: TTntStringList; Index1, Index2: Integer): Integer;
+begin
+  Result := List.CompareStrings(List.FList^[Index1].FString,
+                                List.FList^[Index2].FString);
+end;
+
+procedure TTntStringList.Sort;
+begin
+  CustomSort(WideStringListCompareStrings);
+end;
+
+procedure TTntStringList.CustomSort(Compare: TWideStringListSortCompare);
+begin
+  if not Sorted and (FCount > 1) then
+  begin
+    Changing;
+    QuickSort(0, FCount - 1, Compare);
+    Changed;
+  end;
+end;
+
+function TTntStringList.CompareStrings(const S1, S2: WideString): Integer;
+begin
+  if CaseSensitive then
+    Result := WideCompareStr(S1, S2)
+  else
+    Result := WideCompareText(S1, S2);
+end;
+
+procedure TTntStringList.SetCaseSensitive(const Value: Boolean);
+begin
+  if Value <> FCaseSensitive then
+  begin
+    FCaseSensitive := Value;
+    if Sorted then Sort;
+  end;
+end;
+
+//------------------------- TntClasses introduced procs ----------------------------------
+
+function AutoDetectCharacterSet(Stream: TStream): TTntStreamCharSet;
+var
+  ByteOrderMark: WideChar;
+  BytesRead: Integer;
+  Utf8Test: array[0..2] of AnsiChar;
+begin
+  // Byte Order Mark
+  ByteOrderMark := #0;
+  if (Stream.Size - Stream.Position) >= SizeOf(ByteOrderMark) then begin
+    BytesRead := Stream.Read(ByteOrderMark, SizeOf(ByteOrderMark));
+    if (ByteOrderMark <> UNICODE_BOM) and (ByteOrderMark <> UNICODE_BOM_SWAPPED) then begin
+      ByteOrderMark := #0;
+      Stream.Seek(-BytesRead, soFromCurrent);
+      if (Stream.Size - Stream.Position) >= Length(Utf8Test) * SizeOf(AnsiChar) then begin
+        BytesRead := Stream.Read(Utf8Test[0], Length(Utf8Test) * SizeOf(AnsiChar));
+        if Utf8Test <> UTF8_BOM then
+          Stream.Seek(-BytesRead, soFromCurrent);
+      end;
+    end;
+  end;
+  // Test Byte Order Mark
+  if ByteOrderMark = UNICODE_BOM then
+    Result := csUnicode
+  else if ByteOrderMark = UNICODE_BOM_SWAPPED then
+    Result := csUnicodeSwapped
+  else if Utf8Test = UTF8_BOM then
+    Result := csUtf8
+  else
+    Result := csAnsi;
+end;
+
+function FindSortedListByTarget(List: TList; TargetCompare: TListTargetCompare;
+  Target: Pointer; var Index: Integer): Boolean;
+var
+  L, H, I, C: Integer;
+begin
+  Result := False;
+  L := 0;
+  H := List.Count - 1;
+  while L <= H do
+  begin
+    I := (L + H) shr 1;
+    C := TargetCompare(List[i], Target);
+    if C < 0 then L := I + 1 else
+    begin
+      H := I - 1;
+      if C = 0 then
+      begin
+        Result := True;
+        L := I;
+      end;
+    end;
+  end;
+  Index := L;
+end;
+
+function ClassIsRegistered(const clsid: TCLSID): Boolean;
+var
+  OleStr: POleStr;
+  Reg: TRegIniFile;
+  Key, Filename: WideString;
+begin
+  // First, check to see if there is a ProgID.  This will tell if the
+  // control is registered on the machine.  No ProgID, control won't run
+  Result := ProgIDFromCLSID(clsid, OleStr) = S_OK;
+  if not Result then Exit;  //Bail as soon as anything goes wrong.
+
+  // Next, make sure that the file is actually there by rooting it out
+  // of the registry
+  Key := WideFormat('\SOFTWARE\Classes\CLSID\%s', [GUIDToString(clsid)]);
+  Reg := TRegIniFile.Create;
+  try
+    Reg.RootKey := HKEY_LOCAL_MACHINE;
+    Result := Reg.OpenKeyReadOnly(Key);
+    if not Result then Exit; // Bail as soon as anything goes wrong.
+
+    FileName := Reg.ReadString('InProcServer32', '', EmptyStr);
+    if (Filename = EmptyStr) then // try another key for the file name
+    begin
+      FileName := Reg.ReadString('InProcServer', '', EmptyStr);
+    end;
+    Result := Filename <> EmptyStr;
+    if not Result then Exit;
+    Result := WideFileExists(Filename);
+  finally
+    Reg.Free;
+  end;
+end;
+
+{ TBufferedAnsiString }
+
+procedure TBufferedAnsiString.Clear;
+begin
+  LastWriteIndex := 0;
+  if Length(FStringBuffer) > 0 then
+    FillChar(FStringBuffer[1], Length(FStringBuffer) * SizeOf(AnsiChar), 0);
+end;
+
+procedure TBufferedAnsiString.AddChar(const wc: AnsiChar);
+const
+  MIN_GROW_SIZE = 32;
+  MAX_GROW_SIZE = 256;
+var
+  GrowSize: Integer;
+begin
+  Inc(LastWriteIndex);
+  if LastWriteIndex > Length(FStringBuffer) then begin
+    GrowSize := Max(MIN_GROW_SIZE, Length(FStringBuffer));
+    GrowSize := Min(GrowSize, MAX_GROW_SIZE);
+    SetLength(FStringBuffer, Length(FStringBuffer) + GrowSize);
+    FillChar(FStringBuffer[LastWriteIndex], GrowSize * SizeOf(AnsiChar), 0);
+  end;
+  FStringBuffer[LastWriteIndex] := wc;
+end;
+
+procedure TBufferedAnsiString.AddString(const s: AnsiString);
+var
+  LenS: Integer;
+  BlockSize: Integer;
+  AllocSize: Integer;
+begin
+  LenS := Length(s);
+  if LenS > 0 then begin
+    Inc(LastWriteIndex);
+    if LastWriteIndex + LenS - 1 > Length(FStringBuffer) then begin
+      // determine optimum new allocation size
+      BlockSize := Length(FStringBuffer) div 2;
+      if BlockSize < 8 then
+        BlockSize := 8;
+      AllocSize := ((LenS div BlockSize) + 1) * BlockSize;
+      // realloc buffer
+      SetLength(FStringBuffer, Length(FStringBuffer) + AllocSize);
+      FillChar(FStringBuffer[Length(FStringBuffer) - AllocSize + 1], AllocSize * SizeOf(AnsiChar), 0);
+    end;
+    CopyMemory(@FStringBuffer[LastWriteIndex], @s[1], LenS * SizeOf(AnsiChar));
+    Inc(LastWriteIndex, LenS - 1);
+  end;
+end;
+
+procedure TBufferedAnsiString.AddBuffer(Buff: PAnsiChar; Chars: Integer);
+var
+  i: integer;
+begin
+  for i := 1 to Chars do begin
+    if Buff^ = #0 then
+      break;
+    AddChar(Buff^);
+    Inc(Buff);
+  end;
+end;
+
+function TBufferedAnsiString.Value: AnsiString;
+begin
+  Result := PAnsiChar(FStringBuffer);
+end;
+
+function TBufferedAnsiString.BuffPtr: PAnsiChar;
+begin
+  Result := PAnsiChar(FStringBuffer);
+end;
+
+{ TBufferedWideString }
+
+procedure TBufferedWideString.Clear;
+begin
+  LastWriteIndex := 0;
+  if Length(FStringBuffer) > 0 then
+    FillChar(FStringBuffer[1], Length(FStringBuffer) * SizeOf(WideChar), 0);
+end;
+
+procedure TBufferedWideString.AddChar(const wc: WideChar);
+const
+  MIN_GROW_SIZE = 32;
+  MAX_GROW_SIZE = 256;
+var
+  GrowSize: Integer;
+begin
+  Inc(LastWriteIndex);
+  if LastWriteIndex > Length(FStringBuffer) then begin
+    GrowSize := Max(MIN_GROW_SIZE, Length(FStringBuffer));
+    GrowSize := Min(GrowSize, MAX_GROW_SIZE);
+    SetLength(FStringBuffer, Length(FStringBuffer) + GrowSize);
+    FillChar(FStringBuffer[LastWriteIndex], GrowSize * SizeOf(WideChar), 0);
+  end;
+  FStringBuffer[LastWriteIndex] := wc;
+end;
+
+procedure TBufferedWideString.AddString(const s: WideString);
+var
+  i: integer;
+begin
+  for i := 1 to Length(s) do
+    AddChar(s[i]);
+end;
+
+procedure TBufferedWideString.AddBuffer(Buff: PWideChar; Chars: Integer);
+var
+  i: integer;
+begin
+  for i := 1 to Chars do begin
+    if Buff^ = #0 then
+      break;
+    AddChar(Buff^);
+    Inc(Buff);
+  end;
+end;
+
+function TBufferedWideString.Value: WideString;
+begin
+  Result := PWideChar(FStringBuffer);
+end;
+
+function TBufferedWideString.BuffPtr: PWideChar;
+begin
+  Result := PWideChar(FStringBuffer);
+end;
+
+{ TBufferedStreamReader }
+
+constructor TBufferedStreamReader.Create(Stream: TStream; BufferSize: Integer = 1024);
+begin
+  // init stream
+  FStream := Stream;
+  FStreamSize := Stream.Size;
+  // init buffer
+  FBufferSize := BufferSize;
+  SetLength(FBuffer, BufferSize);
+  FBufferStartPosition := -FBufferSize; { out of any useful range }
+  // init virtual position
+  FVirtualPosition := 0;
+end;
+
+function TBufferedStreamReader.Seek(Offset: Integer; Origin: Word): Longint;
+begin
+  case Origin of
+    soFromBeginning: FVirtualPosition := Offset;
+    soFromCurrent:   Inc(FVirtualPosition, Offset);
+    soFromEnd:       FVirtualPosition := FStreamSize + Offset;
+  end;
+  Result := FVirtualPosition;
+end;
+
+procedure TBufferedStreamReader.UpdateBufferFromPosition(StartPos: Integer);
+begin
+  try
+    FStream.Position := StartPos;
+    FStream.Read(FBuffer[0], FBufferSize);
+    FBufferStartPosition := StartPos;
+  except
+    FBufferStartPosition := -FBufferSize; { out of any useful range }
+    raise;
+  end;
+end;
+
+function TBufferedStreamReader.Read(var Buffer; Count: Integer): Longint;
+var
+  BytesLeft: Integer;
+  FirstBufferRead: Integer;
+  StreamDirectRead: Integer;
+  Buf: PAnsiChar;
+begin
+  if (FVirtualPosition >= 0) and (Count >= 0) then
+  begin
+    Result := FStreamSize - FVirtualPosition;
+    if Result > 0 then
+    begin
+      if Result > Count then
+        Result := Count;
+
+      Buf := @Buffer;
+      BytesLeft := Result;
+
+      // try to read what is left in buffer
+      FirstBufferRead := FBufferStartPosition + FBufferSize - FVirtualPosition;
+      if (FirstBufferRead < 0) or (FirstBufferRead > FBufferSize) then
+        FirstBufferRead := 0;
+      FirstBufferRead := Min(FirstBufferRead, Result);
+      if FirstBufferRead > 0 then begin
+        Move(FBuffer[FVirtualPosition - FBufferStartPosition], Buf[0], FirstBufferRead);
+        Dec(BytesLeft, FirstBufferRead);
+      end;
+
+      if BytesLeft > 0 then begin
+        // The first read in buffer was not enough
+        StreamDirectRead := (BytesLeft div FBufferSize) * FBufferSize;
+        FStream.Position := FVirtualPosition + FirstBufferRead;
+        FStream.Read(Buf[FirstBufferRead], StreamDirectRead);
+        Dec(BytesLeft, StreamDirectRead);
+
+        if BytesLeft > 0 then begin
+          // update buffer, and read what is left
+          UpdateBufferFromPosition(FStream.Position);
+          Move(FBuffer[0], Buf[FirstBufferRead + StreamDirectRead], BytesLeft);
+        end;
+      end;
+
+      Inc(FVirtualPosition, Result);
+      Exit;
+    end;
+  end;
+  Result := 0;
+end;
+
+function TBufferedStreamReader.Write(const Buffer; Count: Integer): Longint;
+begin
+  raise ETntInternalError.Create('Internal Error: class can not write.');
+  Result := 0;
+end;
+
+//-------- synced wide string -----------------
+
+function GetSyncedWideString(var WideStr: WideString; const AnsiStr: AnsiString): WideString;
+begin
+  if AnsiString(WideStr) <> (AnsiStr) then begin
+    WideStr := AnsiStr; {AnsiStr changed.  Keep WideStr in sync.}
+  end;
+  Result := WideStr;
+end;
+
+procedure SetSyncedWideString(const Value: WideString; var WideStr: WideString;
+  const AnsiStr: AnsiString; SetAnsiStr: TSetAnsiStrEvent);
+begin
+  if Value <> GetSyncedWideString(WideStr, AnsiStr) then
+  begin
+    if (not WideSameStr(Value, AnsiString(Value))) {unicode chars lost in conversion}
+    and (AnsiStr = AnsiString(Value))  {AnsiStr is not going to change}
+    then begin
+      SetAnsiStr(''); {force the change}
+    end;
+    WideStr := Value;
+    SetAnsiStr(Value);
+  end;
+end;
+
+{ TWideComponentHelper }
+
+function CompareComponentHelperToTarget(Item, Target: Pointer): Integer;
+begin
+  if PtrUInt(TWideComponentHelper(Item).FComponent) < PtrUInt(Target) then
+    Result := -1
+  else if PtrUInt(TWideComponentHelper(Item).FComponent) > PtrUInt(Target) then
+    Result := 1
+  else
+    Result := 0;
+end;
+
+function FindWideComponentHelperIndex(ComponentHelperList: TComponentList; Component: TComponent; var Index: Integer): Boolean;
+begin
+  // find Component in sorted wide caption list (list is sorted by TWideComponentHelper.FComponent)
+  Result := FindSortedListByTarget(ComponentHelperList, CompareComponentHelperToTarget, Component, Index);
+end;
+
+constructor TWideComponentHelper.Create(AOwner: TComponent);
+begin
+  raise ETntInternalError.Create('TNT Internal Error: TWideComponentHelper.Create should never be encountered.');
+end;
+
+constructor TWideComponentHelper.CreateHelper(AOwner: TComponent; ComponentHelperList: TComponentList);
+var
+  Index: Integer;
+begin
+  // don't use direct ownership for memory management
+  inherited Create(nil);
+  FComponent := AOwner;
+  FComponent.FreeNotification(Self);
+
+  // insert into list according to sort
+  FindWideComponentHelperIndex(ComponentHelperList, FComponent, Index);
+  ComponentHelperList.Insert(Index, Self);
+end;
+
+procedure TWideComponentHelper.Notification(AComponent: TComponent; Operation: TOperation);
+begin
+  inherited;
+  if (AComponent = FComponent) and (Operation = opRemove) then begin
+    FComponent := nil;
+    Free;
+  end;
+end;
+
+function FindWideComponentHelper(ComponentHelperList: TComponentList; Component: TComponent): TWideComponentHelper;
+var
+  Index: integer;
+begin
+  if FindWideComponentHelperIndex(ComponentHelperList, Component, Index) then begin
+  	Result := TWideComponentHelper(ComponentHelperList[Index]);
+    Assert(Result.FComponent = Component, 'TNT Internal Error: FindWideComponentHelperIndex failed.');
+  end else
+    Result := nil;
+end;
+
+initialization
+  RuntimeUTFStreaming := False; { Delphi 6 and higher don't need UTF help at runtime. }
+
+end.
diff --git a/songmanagement/src/lib/TntUnicodeControls/TntCompilers.inc b/songmanagement/src/lib/TntUnicodeControls/TntCompilers.inc
new file mode 100644
index 00000000..90b51ef2
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/TntCompilers.inc
@@ -0,0 +1,378 @@
+//----------------------------------------------------------------------------------------------------------------------
+// Include file to determine which compiler is currently being used to build the project/component.
+// This file uses ideas from Brad Stowers DFS.inc file (www.delphifreestuff.com).
+//
+// Portions created by Mike Lischke are Copyright
+// (C) 1999-2002 Dipl. Ing. Mike Lischke. All Rights Reserved.
+//----------------------------------------------------------------------------------------------------------------------
+// The following symbols are defined:
+//
+// COMPILER_1    : Kylix/Delphi/BCB 1.x is the compiler.
+// COMPILER_1_UP : Kylix/Delphi/BCB 1.x or higher is the compiler.
+// COMPILER_2    : Kylix/Delphi 2.x or BCB 1.x is the compiler.
+// COMPILER_2_UP : Kylix/Delphi 2.x or higher, or BCB 1.x or higher is the compiler.
+// COMPILER_3    : Kylix/Delphi/BCB 3.x is the compiler.
+// COMPILER_3_UP : Kylix/Delphi/BCB 3.x or higher is the compiler.
+// COMPILER_4    : Kylix/Delphi/BCB 4.x is the compiler.
+// COMPILER_4_UP : Kylix/Delphi/BCB 4.x or higher is the compiler.
+// COMPILER_5    : Kylix/Delphi/BCB 5.x is the compiler.
+// COMPILER_5_UP : Kylix/Delphi/BCB 5.x or higher is the compiler.
+// COMPILER_6    : Kylix/Delphi/BCB 6.x is the compiler.
+// COMPILER_6_UP : Kylix/Delphi/BCB 6.x or higher is the compiler.
+// COMPILER_7    : Kylix/Delphi/BCB 7.x is the compiler.
+// COMPILER_7_UP : Kylix/Delphi/BCB 7.x or higher is the compiler.
+//
+// Only defined if Windows is the target:
+// CPPB        : Any version of BCB is being used.
+// CPPB_1      : BCB v1.x is being used.
+// CPPB_3      : BCB v3.x is being used.
+// CPPB_3_UP   : BCB v3.x or higher is being used.
+// CPPB_4      : BCB v4.x is being used.
+// CPPB_4_UP   : BCB v4.x or higher is being used.
+// CPPB_5      : BCB v5.x is being used.
+// CPPB_5_UP   : BCB v5.x or higher is being used.
+// CPPB_6      : BCB v6.x is being used.
+// CPPB_6_UP   : BCB v6.x or higher is being used.
+//
+// Only defined if Windows is the target:
+// DELPHI      : Any version of Delphi is being used.
+// DELPHI_1    : Delphi v1.x is being used.
+// DELPHI_2    : Delphi v2.x is being used.
+// DELPHI_2_UP : Delphi v2.x or higher is being used.
+// DELPHI_3    : Delphi v3.x is being used.
+// DELPHI_3_UP : Delphi v3.x or higher is being used.
+// DELPHI_4    : Delphi v4.x is being used.
+// DELPHI_4_UP : Delphi v4.x or higher is being used.
+// DELPHI_5    : Delphi v5.x is being used.
+// DELPHI_5_UP : Delphi v5.x or higher is being used.
+// DELPHI_6    : Delphi v6.x is being used.
+// DELPHI_6_UP : Delphi v6.x or higher is being used.
+// DELPHI_7    : Delphi v7.x is being used.
+// DELPHI_7_UP : Delphi v7.x or higher is being used.
+//
+// Only defined if Linux is the target:
+// KYLIX       : Any version of Kylix is being used.
+// KYLIX_1     : Kylix 1.x is being used.
+// KYLIX_1_UP  : Kylix 1.x or higher is being used.
+// KYLIX_2     : Kylix 2.x is being used.
+// KYLIX_2_UP  : Kylix 2.x or higher is being used.
+// KYLIX_3     : Kylix 3.x is being used.
+// KYLIX_3_UP  : Kylix 3.x or higher is being used.
+//
+// Only defined if Linux is the target:
+// QT_CLX      : Trolltech's QT library is being used.
+//----------------------------------------------------------------------------------------------------------------------
+
+{$ifdef MSWINDOWS}
+
+  {$ifdef VER180}
+    {$define COMPILER_10}
+    {$define DELPHI}
+    {$define DELPHI_10}
+  {$endif}
+
+  {$ifdef VER170}
+    {$define COMPILER_9}
+    {$define DELPHI}
+    {$define DELPHI_9}
+  {$endif}
+
+  {$ifdef VER150}        
+    {$define COMPILER_7}
+    {$define DELPHI}
+    {$define DELPHI_7}
+  {$endif}
+
+  {$ifdef VER140}
+    {$define COMPILER_6}
+    {$ifdef BCB}
+      {$define CPPB}
+      {$define CPPB_6}
+    {$else}
+      {$define DELPHI}
+      {$define DELPHI_6}
+    {$endif}
+  {$endif}
+
+  {$ifdef VER130}
+    {$define COMPILER_5}
+    {$ifdef BCB}
+      {$define CPPB}
+      {$define CPPB_5}
+    {$else}
+      {$define DELPHI}
+      {$define DELPHI_5}
+    {$endif}
+  {$endif}
+
+  {$ifdef VER125}
+    {$define COMPILER_4}
+    {$define CPPB}
+    {$define CPPB_4}
+  {$endif}
+
+  {$ifdef VER120}
+    {$define COMPILER_4}
+    {$define DELPHI}
+    {$define DELPHI_4}
+  {$endif}
+
+  {$ifdef VER110}
+    {$define COMPILER_3}
+    {$define CPPB}
+    {$define CPPB_3}
+  {$endif}
+
+  {$ifdef VER100}
+    {$define COMPILER_3}
+    {$define DELPHI}
+    {$define DELPHI_3}
+  {$endif}
+
+  {$ifdef VER93}
+    {$define COMPILER_2} // C++ Builder v1 compiler is really v2 
+    {$define CPPB}
+    {$define CPPB_1}
+  {$endif}
+
+  {$ifdef VER90}
+    {$define COMPILER_2}
+    {$define DELPHI}
+    {$define DELPHI_2}
+  {$endif}
+
+  {$ifdef VER80}
+    {$define COMPILER_1}
+    {$define DELPHI}
+    {$define DELPHI_1}
+  {$endif}
+
+  {$ifdef FPC}
+    {.$define DELPHI}
+  {$endif}
+    
+  {$ifdef DELPHI_2}
+    {$define DELPHI_2_UP}
+  {$endif}
+
+  {$ifdef DELPHI_3}
+    {$define DELPHI_2_UP}
+    {$define DELPHI_3_UP}
+  {$endif}
+
+  {$ifdef DELPHI_4}
+    {$define DELPHI_2_UP}
+    {$define DELPHI_3_UP}
+    {$define DELPHI_4_UP}
+  {$endif}
+
+  {$ifdef DELPHI_5}
+    {$define DELPHI_2_UP}
+    {$define DELPHI_3_UP}
+    {$define DELPHI_4_UP}
+    {$define DELPHI_5_UP}
+  {$endif}
+
+  {$ifdef DELPHI_6}
+    {$define DELPHI_2_UP}
+    {$define DELPHI_3_UP}
+    {$define DELPHI_4_UP}
+    {$define DELPHI_5_UP}
+    {$define DELPHI_6_UP}
+  {$endif}
+
+  {$ifdef DELPHI_7}
+    {$define DELPHI_2_UP}
+    {$define DELPHI_3_UP}
+    {$define DELPHI_4_UP}
+    {$define DELPHI_5_UP}
+    {$define DELPHI_6_UP}
+    {$define DELPHI_7_UP}
+  {$endif}
+
+  {$ifdef DELPHI_9}
+    {$define DELPHI_2_UP}
+    {$define DELPHI_3_UP}
+    {$define DELPHI_4_UP}
+    {$define DELPHI_5_UP}
+    {$define DELPHI_6_UP}
+    {$define DELPHI_7_UP}
+    {$define DELPHI_9_UP}
+  {$endif}
+
+  {$ifdef DELPHI_10}
+    {$define DELPHI_2_UP}
+    {$define DELPHI_3_UP}
+    {$define DELPHI_4_UP}
+    {$define DELPHI_5_UP}
+    {$define DELPHI_6_UP}
+    {$define DELPHI_7_UP}
+    {$define DELPHI_9_UP}
+    {$define DELPHI_10_UP}
+  {$endif}
+
+  {$ifdef CPPB_3}
+    {$define CPPB_3_UP}
+  {$endif}
+
+  {$ifdef CPPB_4}
+    {$define CPPB_3_UP}
+    {$define CPPB_4_UP}
+  {$endif}
+
+  {$ifdef CPPB_5}
+    {$define CPPB_3_UP}
+    {$define CPPB_4_UP}
+    {$define CPPB_5_UP}
+  {$endif}
+
+  {$ifdef CPPB_6}
+    {$define CPPB_3_UP}
+    {$define CPPB_4_UP}
+    {$define CPPB_5_UP}
+    {$define CPPB_6_UP}
+  {$endif}
+
+  {$ifdef CPPB_3_UP}
+    // C++ Builder requires this if you use Delphi components in run-time packages.
+    {$ObjExportAll On}
+  {$endif}
+
+{$else (not Windows)}
+  // Linux is the target
+  {$define QT_CLX}
+
+  {$define KYLIX}
+  {$define KYLIX_1}
+  {$define KYLIX_1_UP}
+
+  {$ifdef VER150}
+    {$define COMPILER_7}
+    {$define KYLIX_3}
+  {$endif}
+
+  {$ifdef VER140}
+    {$define COMPILER_6}
+    {$define KYLIX_2}
+  {$endif}
+
+  {$ifdef KYLIX_2}
+    {$define KYLIX_2_UP}
+  {$endif}
+
+  {$ifdef KYLIX_3}
+    {$define KYLIX_2_UP}
+    {$define KYLIX_3_UP}
+  {$endif}
+
+{$endif}
+
+// Compiler defines common to all platforms.
+{$ifdef COMPILER_1}
+  {$define COMPILER_1_UP}
+{$endif}
+
+{$ifdef COMPILER_2}
+  {$define COMPILER_1_UP}
+  {$define COMPILER_2_UP}
+{$endif}
+
+{$ifdef COMPILER_3}
+  {$define COMPILER_1_UP}
+  {$define COMPILER_2_UP}
+  {$define COMPILER_3_UP}
+{$endif}
+
+{$ifdef COMPILER_4}
+  {$define COMPILER_1_UP}
+  {$define COMPILER_2_UP}
+  {$define COMPILER_3_UP}
+  {$define COMPILER_4_UP}
+{$endif}
+
+{$ifdef COMPILER_5}
+  {$define COMPILER_1_UP}
+  {$define COMPILER_2_UP}
+  {$define COMPILER_3_UP}
+  {$define COMPILER_4_UP}
+  {$define COMPILER_5_UP}
+{$endif}
+
+{$ifdef COMPILER_6}
+  {$define COMPILER_1_UP}
+  {$define COMPILER_2_UP}
+  {$define COMPILER_3_UP}
+  {$define COMPILER_4_UP}
+  {$define COMPILER_5_UP}
+  {$define COMPILER_6_UP}
+{$endif}
+
+{$ifdef COMPILER_7}
+  {$define COMPILER_1_UP}
+  {$define COMPILER_2_UP}
+  {$define COMPILER_3_UP}
+  {$define COMPILER_4_UP}
+  {$define COMPILER_5_UP}
+  {$define COMPILER_6_UP}
+  {$define COMPILER_7_UP}
+{$endif}
+
+{$ifdef COMPILER_9}
+  {$define COMPILER_1_UP}
+  {$define COMPILER_2_UP}
+  {$define COMPILER_3_UP}
+  {$define COMPILER_4_UP}
+  {$define COMPILER_5_UP}
+  {$define COMPILER_6_UP}
+  {$define COMPILER_7_UP}
+  {$define COMPILER_9_UP}
+{$endif}
+
+{$ifdef COMPILER_10}
+  {$define COMPILER_1_UP}
+  {$define COMPILER_2_UP}
+  {$define COMPILER_3_UP}
+  {$define COMPILER_4_UP}
+  {$define COMPILER_5_UP}
+  {$define COMPILER_6_UP}
+  {$define COMPILER_7_UP}
+  {$define COMPILER_9_UP}
+  {$define COMPILER_10_UP}
+{$endif}
+
+//----------------------------------------------------------------------------------------------------------------------
+
+{$ALIGN ON}
+{$BOOLEVAL OFF}
+
+{$ifdef COMPILER_7_UP}
+  {$define THEME_7_UP} { Allows experimental theme support on pre-Delphi 7. }
+{$endif}
+
+{$IFDEF COMPILER_6_UP}
+{$WARN SYMBOL_PLATFORM OFF} { We are going to use Win32 specific symbols! }
+{$ENDIF}
+
+{$IFDEF COMPILER_7_UP}
+{$IFDEF FPC}
+  {$DEFINE UNSAFE_WARNINGS_OFF}
+{$ENDIF}
+{$ENDIF}
+
+{$IFDEF UNSAFE_WARNINGS_OFF}
+{$WARN UNSAFE_CODE OFF} { We are not going to be "safe"! }
+{$WARN UNSAFE_TYPE OFF}
+{$WARN UNSAFE_CAST OFF}
+{$ENDIF}
+
+{$IFDEF FPC}
+{$HINTS OFF}
+{$ENDIF}
+
+{$IFNDEF FPC}
+  // Delphi system function overrides might (not tested) cause problems on
+  // CPUs with code protection (NX-bit). So disable by default. 
+  {.$DEFINE USE_SYSTEM_OVERRIDES}
+{$ENDIF}
+
+
diff --git a/songmanagement/src/lib/TntUnicodeControls/TntFormatStrUtils.pas b/songmanagement/src/lib/TntUnicodeControls/TntFormatStrUtils.pas
new file mode 100644
index 00000000..80aefd4a
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/TntFormatStrUtils.pas
@@ -0,0 +1,521 @@
+
+{*****************************************************************************}
+{                                                                             }
+{    Tnt Delphi Unicode Controls                                              }
+{      http://www.tntware.com/delphicontrols/unicode/                         }
+{        Version: 2.3.0                                                       }
+{                                                                             }
+{    Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com)       }
+{                                                                             }
+{*****************************************************************************}
+
+unit TntFormatStrUtils;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$INCLUDE TntCompilers.inc}
+
+interface
+
+// this unit provides functions to work with format strings
+
+uses
+  TntSysUtils;
+
+function GetCanonicalFormatStr(const _FormatString: WideString): WideString;
+
+{$IFNDEF FPC}
+{$IFNDEF COMPILER_9_UP}
+function ReplaceFloatingArgumentsInFormatString(const _FormatString: WideString;
+  const Args: array of const
+    {$IFDEF COMPILER_7_UP}; FormatSettings: PFormatSettings{$ENDIF}): WideString;
+{$ENDIF}
+{$ENDIF}
+procedure CompareFormatStrings(FormatStr1, FormatStr2: WideString);
+function FormatStringsAreCompatible(FormatStr1, FormatStr2: WideString): Boolean;
+
+type
+  EFormatSpecError = class(ETntGeneralError);
+
+implementation
+
+uses
+  SysUtils, Math, TntClasses;
+
+resourcestring
+  SInvalidFormatSpecifier = 'Invalid Format Specifier: %s';
+  SMismatchedArgumentTypes = 'Argument types for index %d do not match. (%s <> %s)';
+  SMismatchedArgumentCounts = 'Number of format specifiers do not match.';
+
+type
+  TFormatSpecifierType = (fstInteger, fstFloating, fstPointer, fstString);
+
+function GetFormatSpecifierType(const FormatSpecifier: WideString): TFormatSpecifierType;
+var
+  LastChar: WideChar;
+begin
+  LastChar := TntWideLastChar(FormatSpecifier);
+  case LastChar of
+    'd', 'D', 'u', 'U', 'x', 'X':
+      result := fstInteger;
+    'e', 'E', 'f', 'F', 'g', 'G', 'n', 'N', 'm', 'M':
+      result := fstFloating;
+    'p', 'P':
+      result := fstPointer;
+    's', 'S':
+      result := fstString
+    else
+      raise ETntInternalError.CreateFmt('Internal Error: Unexpected format type (%s)', [LastChar]);
+  end;
+end;
+
+type
+  TFormatStrParser = class(TObject)
+  private
+    ParsedString: TBufferedWideString;
+    PFormatString: PWideChar;
+    LastIndex: Integer;
+    ExplicitCount: Integer;
+    ImplicitCount: Integer;
+    procedure RaiseInvalidFormatSpecifier;
+    function ParseChar(c: WideChar): Boolean;
+    procedure ForceParseChar(c: WideChar);
+    function ParseDigit: Boolean;
+    function ParseInteger: Boolean;
+    procedure ForceParseType;
+    function PeekDigit: Boolean;
+    function PeekIndexSpecifier(out Index: Integer): Boolean;
+  public
+    constructor Create(const _FormatString: WideString);
+    destructor Destroy; override;
+    function ParseFormatSpecifier: Boolean;
+  end;
+
+constructor TFormatStrParser.Create(const _FormatString: WideString);
+begin
+  inherited Create;
+  PFormatString := PWideChar(_FormatString);
+  ExplicitCount := 0;
+  ImplicitCount := 0;
+  LastIndex := -1;
+  ParsedString := TBufferedWideString.Create;
+end;
+
+destructor TFormatStrParser.Destroy;
+begin
+  FreeAndNil(ParsedString);
+  inherited;
+end;
+
+procedure TFormatStrParser.RaiseInvalidFormatSpecifier;
+begin
+  raise EFormatSpecError.CreateFmt(SInvalidFormatSpecifier, [ParsedString.Value + PFormatString]);
+end;
+
+function TFormatStrParser.ParseChar(c: WideChar): Boolean;
+begin
+  result := False;
+  if PFormatString^ = c then begin
+    result := True;
+    ParsedString.AddChar(c);
+    Inc(PFormatString);
+  end;
+end;
+
+procedure TFormatStrParser.ForceParseChar(c: WideChar);
+begin
+  if not ParseChar(c) then
+    RaiseInvalidFormatSpecifier;
+end;
+
+function TFormatStrParser.PeekDigit: Boolean;
+begin
+  result := False;
+  if  (PFormatString^ <> #0)
+  and (PFormatString^ >= '0')
+  and (PFormatString^ <= '9') then
+    result := True;
+end;
+
+function TFormatStrParser.ParseDigit: Boolean;
+begin
+  result := False;
+  if PeekDigit then begin
+    result := True;
+    ForceParseChar(PFormatString^);
+  end;
+end;
+
+function TFormatStrParser.ParseInteger: Boolean;
+const
+  MAX_INT_DIGITS = 6;
+var
+  digitcount: integer;
+begin
+  digitcount := 0;
+  While ParseDigit do begin
+    inc(digitcount);
+  end;
+  result := (digitcount > 0);
+  if digitcount > MAX_INT_DIGITS then
+    RaiseInvalidFormatSpecifier;
+end;
+
+procedure TFormatStrParser.ForceParseType;
+begin
+  if PFormatString^ = #0 then
+    RaiseInvalidFormatSpecifier;
+
+  case PFormatString^ of
+    'd', 'u', 'x', 'e', 'f', 'g', 'n', 'm', 'p', 's',
+    'D', 'U', 'X', 'E', 'F', 'G', 'N', 'M', 'P', 'S':
+  begin
+    // do nothing
+  end
+  else
+    RaiseInvalidFormatSpecifier;
+  end;
+  ForceParseChar(PFormatString^);
+end;
+
+function TFormatStrParser.PeekIndexSpecifier(out Index: Integer): Boolean;
+var
+  SaveParsedString: WideString;
+  SaveFormatString: PWideChar;
+begin
+  SaveParsedString := ParsedString.Value;
+  SaveFormatString := PFormatString;
+  try
+    ParsedString.Clear;
+    Result := False;
+    Index := -1;
+    if ParseInteger then begin
+      Index := StrToInt(ParsedString.Value);
+      if ParseChar(':') then
+        Result := True;
+    end;
+  finally
+    ParsedString.Clear;
+    ParsedString.AddString(SaveParsedString);
+    PFormatString := SaveFormatString;
+  end;
+end;
+
+function TFormatStrParser.ParseFormatSpecifier: Boolean;
+var
+  ExplicitIndex: Integer;
+begin
+  Result := False;
+  // Parse entire format specifier
+  ForceParseChar('%');
+  if (PFormatString^ <> #0)
+  and (not ParseChar(' '))
+  and (not ParseChar('%')) then begin
+    if PeekIndexSpecifier(ExplicitIndex) then begin
+      Inc(ExplicitCount);
+      LastIndex := Max(LastIndex, ExplicitIndex);
+    end else begin
+      Inc(ImplicitCount);
+      Inc(LastIndex);
+      ParsedString.AddString(IntToStr(LastIndex));
+      ParsedString.AddChar(':');
+    end;
+    if ParseChar('*') then
+    begin
+      Inc(ImplicitCount);
+      Inc(LastIndex);
+      ParseChar(':');
+    end else if ParseInteger then
+      ParseChar(':');
+    ParseChar('-');
+    if ParseChar('*') then begin
+      Inc(ImplicitCount);
+      Inc(LastIndex);
+    end else
+      ParseInteger;
+    if ParseChar('.') then begin
+      if not ParseChar('*') then
+        ParseInteger;
+    end;
+    ForceParseType;
+    Result := True;
+  end;
+end;
+
+//-----------------------------------
+
+function GetCanonicalFormatStr(const _FormatString: WideString): WideString;
+var
+  PosSpec: Integer;
+begin
+  with TFormatStrParser.Create(_FormatString) do
+  try
+    // loop until no more '%'
+    PosSpec := Pos(WideString('%'), PFormatString);
+    While PosSpec <> 0 do begin
+      try
+        // delete everything up until '%'
+        ParsedString.AddBuffer(PFormatString, PosSpec - 1);
+        Inc(PFormatString, PosSpec - 1);
+        // parse format specifier
+        ParseFormatSpecifier;
+      finally
+        PosSpec := Pos(WideString('%'), PFormatString);
+      end;
+    end;
+    if ((ExplicitCount = 0) and (ImplicitCount = 1)) {simple expression}
+    or ((ExplicitCount > 0) and (ImplicitCount = 0)) {nothing converted} then
+      result := _FormatString {original}
+    else
+      result := ParsedString.Value + PFormatString;
+  finally
+    Free;
+  end;
+end;
+
+{$IFNDEF FPC}
+{$IFNDEF COMPILER_9_UP}
+function ReplaceFloatingArgumentsInFormatString(const _FormatString: WideString;
+  const Args: array of const
+    {$IFDEF COMPILER_7_UP}; FormatSettings: PFormatSettings{$ENDIF}): WideString;
+{ This function replaces floating point format specifiers with their actual formatted values.
+  It also adds index specifiers so that the other format specifiers don't lose their place.
+  The reason for this is that WideFormat doesn't correctly format floating point specifiers.
+  See QC#4254. }
+var
+  Parser: TFormatStrParser;
+  PosSpec: Integer;
+  Output: TBufferedWideString;
+begin
+  Output := TBufferedWideString.Create;
+  try
+    Parser := TFormatStrParser.Create(_FormatString);
+    with Parser do
+    try
+      // loop until no more '%'
+      PosSpec := Pos('%', PFormatString);
+      While PosSpec <> 0 do begin
+        try
+          // delete everything up until '%'
+          Output.AddBuffer(PFormatString, PosSpec - 1);
+          Inc(PFormatString, PosSpec - 1);
+          // parse format specifier
+          ParsedString.Clear;
+          if (not ParseFormatSpecifier)
+          or (GetFormatSpecifierType(ParsedString.Value) <> fstFloating) then
+            Output.AddBuffer(ParsedString.BuffPtr, MaxInt)
+          {$IFDEF COMPILER_7_UP}
+          else if Assigned(FormatSettings) then
+            Output.AddString(Format{TNT-ALLOW Format}(ParsedString.Value, Args, FormatSettings^))
+          {$ENDIF}
+          else
+            Output.AddString(Format{TNT-ALLOW Format}(ParsedString.Value, Args));
+        finally
+          PosSpec := Pos('%', PFormatString);
+        end;
+      end;
+      Output.AddString(PFormatString);
+    finally
+      Free;
+    end;
+    Result := Output.Value;
+  finally
+    Output.Free;
+  end;
+end;
+{$ENDIF}
+{$ENDIF}
+
+procedure GetFormatArgs(const _FormatString: WideString; FormatArgs: TTntStrings);
+var
+  PosSpec: Integer;
+begin
+  with TFormatStrParser.Create(_FormatString) do
+  try
+    FormatArgs.Clear;
+    // loop until no more '%'
+    PosSpec := Pos(WideString('%'), PFormatString);
+    While PosSpec <> 0 do begin
+      try
+        // delete everything up until '%'
+        Inc(PFormatString, PosSpec - 1);
+        // add format specifier to list
+        ParsedString.Clear;
+        if ParseFormatSpecifier then
+          FormatArgs.Add(ParsedString.Value);
+      finally
+        PosSpec := Pos(WideString('%'), PFormatString);
+      end;
+    end;
+  finally
+    Free;
+  end;
+end;
+
+function GetExplicitIndex(const FormatSpecifier: WideString): Integer;
+var
+  IndexStr: WideString;
+  PosColon: Integer;
+begin
+  result := -1;
+  PosColon := Pos(':', FormatSpecifier);
+  if PosColon <> 0 then begin
+    IndexStr := Copy(FormatSpecifier, 2, PosColon - 2);
+    result := StrToInt(IndexStr);
+  end;
+end;
+
+function GetMaxIndex(FormatArgs: TTntStrings): Integer;
+var
+  i: integer;
+  RunningIndex: Integer;
+  ExplicitIndex: Integer;
+begin
+  result := -1;
+  RunningIndex := -1;
+  for i := 0 to FormatArgs.Count - 1 do begin
+    ExplicitIndex := GetExplicitIndex(FormatArgs[i]);
+    if ExplicitIndex <> -1 then
+      RunningIndex := ExplicitIndex
+    else
+      inc(RunningIndex);
+    result := Max(result, RunningIndex);
+  end;
+end;
+
+function FormatSpecToObject(SpecType: TFormatSpecifierType): TObject;
+begin
+  {$IFNDEF FPC}
+  Result := TObject(SpecType);
+  {$ELSE}
+  Result := Pointer(SpecType);
+  {$ENDIF}
+end;
+
+procedure UpdateTypeList(FormatArgs, TypeList: TTntStrings);
+var
+  i: integer;
+  f: WideString;
+  SpecType: TFormatSpecifierType;
+  ExplicitIndex: Integer;
+  MaxIndex: Integer;
+  RunningIndex: Integer;
+begin
+  // set count of TypeList to accomodate maximum index
+  MaxIndex := GetMaxIndex(FormatArgs);
+  TypeList.Clear;
+  for i := 0 to MaxIndex do
+    TypeList.Add('');
+
+  // for each arg...
+  RunningIndex := -1;
+  for i := 0 to FormatArgs.Count - 1 do begin
+    f := FormatArgs[i];
+    ExplicitIndex := GetExplicitIndex(f);
+    SpecType := GetFormatSpecifierType(f);
+
+    // determine running arg index
+    if ExplicitIndex <> -1 then
+      RunningIndex := ExplicitIndex
+    else
+      inc(RunningIndex);
+
+    if TypeList[RunningIndex] <> '' then begin
+      // already exists in list, check for compatibility
+      if TypeList.Objects[RunningIndex] <> FormatSpecToObject(SpecType) then
+        raise EFormatSpecError.CreateFmt(SMismatchedArgumentTypes,
+          [RunningIndex, TypeList[RunningIndex], f]);
+    end else begin
+      // not in list so update it
+      TypeList[RunningIndex] := f;
+      TypeList.Objects[RunningIndex] := FormatSpecToObject(SpecType);
+    end;
+  end;
+end;
+
+procedure CompareFormatStrings(FormatStr1, FormatStr2: WideString);
+var
+  ArgList1: TTntStringList;
+  ArgList2: TTntStringList;
+  TypeList1: TTntStringList;
+  TypeList2: TTntStringList;
+  i: integer;
+begin
+  ArgList1 := nil;
+  ArgList2 := nil;
+  TypeList1 := nil;
+  TypeList2 := nil;
+  try
+    ArgList1 := TTntStringList.Create;
+    ArgList2 := TTntStringList.Create;
+    TypeList1 := TTntStringList.Create;
+    TypeList2 := TTntStringList.Create;
+
+    GetFormatArgs(FormatStr1, ArgList1);
+    UpdateTypeList(ArgList1, TypeList1);
+
+    GetFormatArgs(FormatStr2, ArgList2);
+    UpdateTypeList(ArgList2, TypeList2);
+
+    if TypeList1.Count <> TypeList2.Count then
+      raise EFormatSpecError.Create(SMismatchedArgumentCounts + CRLF + CRLF + '> ' + FormatStr1 + CRLF + '> ' + FormatStr2);
+
+    for i := 0 to TypeList1.Count - 1 do begin
+      if TypeList1.Objects[i] <> TypeList2.Objects[i] then begin
+        raise EFormatSpecError.CreateFmt(SMismatchedArgumentTypes,
+          [i, TypeList1[i], TypeList2[i]]);
+      end;
+    end;
+
+  finally
+    ArgList1.Free;
+    ArgList2.Free;
+    TypeList1.Free;
+    TypeList2.Free;
+  end;
+end;
+
+function FormatStringsAreCompatible(FormatStr1, FormatStr2: WideString): Boolean;
+var
+  ArgList1: TTntStringList;
+  ArgList2: TTntStringList;
+  TypeList1: TTntStringList;
+  TypeList2: TTntStringList;
+  i: integer;
+begin
+  ArgList1 := nil;
+  ArgList2 := nil;
+  TypeList1 := nil;
+  TypeList2 := nil;
+  try
+    ArgList1 := TTntStringList.Create;
+    ArgList2 := TTntStringList.Create;
+    TypeList1 := TTntStringList.Create;
+    TypeList2 := TTntStringList.Create;
+
+    GetFormatArgs(FormatStr1, ArgList1);
+    UpdateTypeList(ArgList1, TypeList1);
+
+    GetFormatArgs(FormatStr2, ArgList2);
+    UpdateTypeList(ArgList2, TypeList2);
+
+    Result := (TypeList1.Count = TypeList2.Count);
+    if Result then begin
+      for i := 0 to TypeList1.Count - 1 do begin
+        if TypeList1.Objects[i] <> TypeList2.Objects[i] then begin
+          Result := False;
+          break;
+        end;
+      end;
+    end;
+  finally
+    ArgList1.Free;
+    ArgList2.Free;
+    TypeList1.Free;
+    TypeList2.Free;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/lib/TntUnicodeControls/TntSysUtils.pas b/songmanagement/src/lib/TntUnicodeControls/TntSysUtils.pas
new file mode 100644
index 00000000..b7cf2467
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/TntSysUtils.pas
@@ -0,0 +1,1753 @@
+
+{*****************************************************************************}
+{                                                                             }
+{    Tnt Delphi Unicode Controls                                              }
+{      http://www.tntware.com/delphicontrols/unicode/                         }
+{        Version: 2.3.0                                                       }
+{                                                                             }
+{    Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com)       }
+{                                                                             }
+{*****************************************************************************}
+
+unit TntSysUtils;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$INCLUDE TntCompilers.inc}
+
+interface
+
+{ TODO: Consider: more filename functions from SysUtils }
+{ TODO: Consider: string functions from StrUtils. }
+
+uses
+  Types, SysUtils, Windows, TntWindows;
+
+//---------------------------------------------------------------------------------------------
+//                                 Tnt - Types
+//---------------------------------------------------------------------------------------------
+
+// ......... introduced .........
+type
+  // The user of the application did something plainly wrong.
+  ETntUserError = class(Exception);
+  // A general error occured. (ie. file didn't exist, server didn't return data, etc.)
+  ETntGeneralError = class(Exception);
+  // Like Assert().  An error occured that should never have happened, send me a bug report now!
+  ETntInternalError = class(Exception);
+
+{$IFNDEF FPC}
+type
+  PtrInt = LongInt;
+  PtrUInt = LongWord;
+{$ENDIF}
+
+//---------------------------------------------------------------------------------------------
+//                                 Tnt - SysUtils
+//---------------------------------------------------------------------------------------------
+
+// ......... SBCS and MBCS functions with WideString replacements in SysUtils.pas .........
+
+{TNT-WARN CompareStr}                   {TNT-WARN AnsiCompareStr}
+{TNT-WARN SameStr}                      {TNT-WARN AnsiSameStr}
+{TNT-WARN SameText}                     {TNT-WARN AnsiSameText}
+{TNT-WARN CompareText}                  {TNT-WARN AnsiCompareText}
+{TNT-WARN UpperCase}                    {TNT-WARN AnsiUpperCase}
+{TNT-WARN LowerCase}                    {TNT-WARN AnsiLowerCase}
+
+{TNT-WARN AnsiPos}  { --> Pos() supports WideString. }
+{TNT-WARN FmtStr}
+{TNT-WARN Format}
+{TNT-WARN FormatBuf}
+
+// ......... MBCS Byte Type Procs .........
+
+{TNT-WARN ByteType}
+{TNT-WARN StrByteType}
+{TNT-WARN ByteToCharIndex}
+{TNT-WARN ByteToCharLen}
+{TNT-WARN CharToByteIndex}
+{TNT-WARN CharToByteLen}
+
+// ........ null-terminated string functions .........
+
+{TNT-WARN StrEnd}
+{TNT-WARN StrLen}
+{TNT-WARN StrLCopy}
+{TNT-WARN StrCopy}
+{TNT-WARN StrECopy}
+{TNT-WARN StrPLCopy}
+{TNT-WARN StrPCopy}
+{TNT-WARN StrLComp}
+{TNT-WARN AnsiStrLComp}
+{TNT-WARN StrComp}
+{TNT-WARN AnsiStrComp}
+{TNT-WARN StrLIComp}
+{TNT-WARN AnsiStrLIComp}
+{TNT-WARN StrIComp}
+{TNT-WARN AnsiStrIComp}
+{TNT-WARN StrLower}
+{TNT-WARN AnsiStrLower}
+{TNT-WARN StrUpper}
+{TNT-WARN AnsiStrUpper}
+{TNT-WARN StrPos}
+{TNT-WARN AnsiStrPos}
+{TNT-WARN StrScan}
+{TNT-WARN AnsiStrScan}
+{TNT-WARN StrRScan}
+{TNT-WARN AnsiStrRScan}
+{TNT-WARN StrLCat}
+{TNT-WARN StrCat}
+{TNT-WARN StrMove}
+{TNT-WARN StrPas}
+{TNT-WARN StrAlloc}
+{TNT-WARN StrBufSize}
+{TNT-WARN StrNew}
+{TNT-WARN StrDispose}
+
+{TNT-WARN AnsiExtractQuotedStr}
+{TNT-WARN AnsiLastChar}
+{TNT-WARN AnsiStrLastChar}
+{TNT-WARN QuotedStr}
+{TNT-WARN AnsiQuotedStr}
+{TNT-WARN AnsiDequotedStr}
+
+// ........ string functions .........
+
+{$IFNDEF FPC}
+{$IFNDEF COMPILER_9_UP}
+  //
+  // pre-Delphi 9 issues w/ WideFormatBuf, WideFmtStr and WideFormat
+  //
+
+  {$IFDEF COMPILER_7_UP}
+  type
+    PFormatSettings = ^TFormatSettings;
+  {$ENDIF}
+
+  // SysUtils.WideFormatBuf doesn't correctly handle numeric specifiers.
+  function Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
+    FmtLen: Cardinal; const Args: array of const): Cardinal; {$IFDEF COMPILER_7_UP} overload; {$ENDIF}
+
+  {$IFDEF COMPILER_7_UP}
+  function Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
+    FmtLen: Cardinal; const Args: array of const;
+      const FormatSettings: TFormatSettings): Cardinal; overload;
+  {$ENDIF}
+
+  // SysUtils.WideFmtStr doesn't handle string lengths > 4096.
+  procedure Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
+    const Args: array of const); {$IFDEF COMPILER_7_UP} overload; {$ENDIF}
+
+  {$IFDEF COMPILER_7_UP}
+  procedure Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
+    const Args: array of const; const FormatSettings: TFormatSettings); overload;
+  {$ENDIF}
+
+  {----------------------------------------------------------------------------------------
+    Without the FormatSettings parameter, Tnt_WideFormat is *NOT* necessary...
+      TntSystem.InstallTntSystemUpdates([tsFixWideFormat]);
+        will fix WideFormat as well as WideFmtStr.
+  ----------------------------------------------------------------------------------------}
+  function Tnt_WideFormat(const FormatStr: WideString; const Args: array of const): WideString; {$IFDEF COMPILER_7_UP} overload; {$ENDIF}
+
+  {$IFDEF COMPILER_7_UP}
+  function Tnt_WideFormat(const FormatStr: WideString; const Args: array of const;
+    const FormatSettings: TFormatSettings): WideString; overload;
+  {$ENDIF}
+
+{$ENDIF}
+{$ENDIF}
+
+{TNT-WARN WideUpperCase} // SysUtils.WideUpperCase is broken on Win9x for D6, D7, D9.
+function Tnt_WideUpperCase(const S: WideString): WideString;
+{TNT-WARN WideLowerCase} // SysUtils.WideLowerCase is broken on Win9x for D6, D7, D9.
+function Tnt_WideLowerCase(const S: WideString): WideString;
+
+function TntWideLastChar(const S: WideString): WideChar;
+
+{TNT-WARN StringReplace}
+{TNT-WARN WideStringReplace} // <-- WideStrUtils.WideStringReplace uses SysUtils.WideUpperCase which is broken on Win9x.
+function Tnt_WideStringReplace(const S, OldPattern, NewPattern: WideString;
+  Flags: TReplaceFlags; WholeWord: Boolean = False): WideString;
+
+{TNT-WARN AdjustLineBreaks}
+type TTntTextLineBreakStyle = (tlbsLF, tlbsCRLF, tlbsCR);
+function TntAdjustLineBreaksLength(const S: WideString; Style: TTntTextLineBreakStyle = tlbsCRLF): Integer;
+function TntAdjustLineBreaks(const S: WideString; Style: TTntTextLineBreakStyle = tlbsCRLF): WideString;
+
+{TNT-WARN WrapText}
+function WideWrapText(const Line, BreakStr: WideString; const BreakChars: TSysCharSet;
+  MaxCol: Integer): WideString; overload;
+function WideWrapText(const Line: WideString; MaxCol: Integer): WideString; overload;
+
+// ........ filename manipulation .........
+
+{TNT-WARN SameFileName}           // doesn't apply to Unicode filenames, use WideSameText
+{TNT-WARN AnsiCompareFileName}    // doesn't apply to Unicode filenames, use WideCompareText
+{TNT-WARN AnsiLowerCaseFileName}  // doesn't apply to Unicode filenames, use WideLowerCase
+{TNT-WARN AnsiUpperCaseFileName}  // doesn't apply to Unicode filenames, use WideUpperCase
+
+{TNT-WARN IncludeTrailingBackslash}
+function WideIncludeTrailingBackslash(const S: WideString): WideString;
+{TNT-WARN IncludeTrailingPathDelimiter}
+function WideIncludeTrailingPathDelimiter(const S: WideString): WideString;
+{TNT-WARN ExcludeTrailingBackslash}
+function WideExcludeTrailingBackslash(const S: WideString): WideString;
+{TNT-WARN ExcludeTrailingPathDelimiter}
+function WideExcludeTrailingPathDelimiter(const S: WideString): WideString;
+{TNT-WARN IsDelimiter}
+function WideIsDelimiter(const Delimiters, S: WideString; Index: Integer): Boolean;
+{TNT-WARN IsPathDelimiter}
+function WideIsPathDelimiter(const S: WideString; Index: Integer): Boolean;
+{TNT-WARN LastDelimiter}
+function WideLastDelimiter(const Delimiters, S: WideString): Integer;
+{TNT-WARN ChangeFileExt}
+function WideChangeFileExt(const FileName, Extension: WideString): WideString;
+{TNT-WARN ExtractFilePath}
+function WideExtractFilePath(const FileName: WideString): WideString;
+{TNT-WARN ExtractFileDir}
+function WideExtractFileDir(const FileName: WideString): WideString;
+{TNT-WARN ExtractFileDrive}
+function WideExtractFileDrive(const FileName: WideString): WideString;
+{TNT-WARN ExtractFileName}
+function WideExtractFileName(const FileName: WideString): WideString;
+{TNT-WARN ExtractFileExt}
+function WideExtractFileExt(const FileName: WideString): WideString;
+{TNT-WARN ExtractRelativePath}
+function WideExtractRelativePath(const BaseName, DestName: WideString): WideString;
+
+// ........ file management routines .........
+
+{TNT-WARN ExpandFileName}
+function WideExpandFileName(const FileName: WideString): WideString;
+{TNT-WARN ExtractShortPathName}
+function WideExtractShortPathName(const FileName: WideString): WideString;
+{TNT-WARN FileCreate}
+function WideFileCreate(const FileName: WideString): Integer;
+{TNT-WARN FileOpen}
+function WideFileOpen(const FileName: WideString; Mode: LongWord): Integer;
+{TNT-WARN FileAge}
+function WideFileAge(const FileName: WideString): Integer; overload;
+function WideFileAge(const FileName: WideString; out FileDateTime: TDateTime): Boolean; overload;
+{TNT-WARN DirectoryExists}
+function WideDirectoryExists(const Name: WideString): Boolean;
+{TNT-WARN FileExists}
+function WideFileExists(const Name: WideString): Boolean;
+{TNT-WARN FileGetAttr}
+function WideFileGetAttr(const FileName: WideString): Cardinal;
+{TNT-WARN FileSetAttr}
+function WideFileSetAttr(const FileName: WideString; Attr: Integer): Boolean;
+{TNT-WARN FileIsReadOnly}
+function WideFileIsReadOnly(const FileName: WideString): Boolean;
+{TNT-WARN FileSetReadOnly}
+function WideFileSetReadOnly(const FileName: WideString; ReadOnly: Boolean): Boolean;
+{TNT-WARN ForceDirectories}
+function WideForceDirectories(Dir: WideString): Boolean;
+{TNT-WARN FileSearch}
+function WideFileSearch(const Name, DirList: WideString): WideString;
+{TNT-WARN RenameFile}
+function WideRenameFile(const OldName, NewName: WideString): Boolean;
+{TNT-WARN DeleteFile}
+function WideDeleteFile(const FileName: WideString): Boolean;
+{TNT-WARN CopyFile}
+function WideCopyFile(const FromFile, ToFile: WideString; FailIfExists: Boolean): Boolean;
+
+
+{TNT-WARN TFileName}
+type
+  TWideFileName = type WideString;
+
+{TNT-WARN TSearchRec} // <-- FindFile - warning on TSearchRec is all that is necessary
+type
+  TSearchRecW = record
+    Time: Integer;
+    Size: Int64;
+    Attr: Integer;
+    Name: TWideFileName;
+    ExcludeAttr: Integer;
+    FindHandle: THandle;
+    FindData: TWin32FindDataW;
+  end;
+function WideFindFirst(const Path: WideString; Attr: Integer; var F: TSearchRecW): Integer;
+function WideFindNext(var F: TSearchRecW): Integer;
+procedure WideFindClose(var F: TSearchRecW);
+
+{TNT-WARN CreateDir}
+function WideCreateDir(const Dir: WideString): Boolean;
+{TNT-WARN RemoveDir}
+function WideRemoveDir(const Dir: WideString): Boolean;
+{TNT-WARN GetCurrentDir}
+function WideGetCurrentDir: WideString;
+{TNT-WARN SetCurrentDir}
+function WideSetCurrentDir(const Dir: WideString): Boolean;
+
+
+// ........ date/time functions .........
+
+{TNT-WARN TryStrToDateTime}
+function TntTryStrToDateTime(Str: WideString; out DateTime: TDateTime): Boolean;
+{TNT-WARN TryStrToDate}
+function TntTryStrToDate(Str: WideString; out DateTime: TDateTime): Boolean;
+{TNT-WARN TryStrToTime}
+function TntTryStrToTime(Str: WideString; out DateTime: TDateTime): Boolean;
+
+{ introduced }
+function ValidDateTimeStr(Str: WideString): Boolean;
+function ValidDateStr(Str: WideString): Boolean;
+function ValidTimeStr(Str: WideString): Boolean;
+
+{TNT-WARN StrToDateTime}
+function TntStrToDateTime(Str: WideString): TDateTime;
+{TNT-WARN StrToDate}
+function TntStrToDate(Str: WideString): TDateTime;
+{TNT-WARN StrToTime}
+function TntStrToTime(Str: WideString): TDateTime;
+{TNT-WARN StrToDateTimeDef}
+function TntStrToDateTimeDef(Str: WideString; Default: TDateTime): TDateTime;
+{TNT-WARN StrToDateDef}
+function TntStrToDateDef(Str: WideString; Default: TDateTime): TDateTime;
+{TNT-WARN StrToTimeDef}
+function TntStrToTimeDef(Str: WideString; Default: TDateTime): TDateTime;
+
+{TNT-WARN CurrToStr}
+{TNT-WARN CurrToStrF}
+function TntCurrToStr(Value: Currency; lpFormat: PCurrencyFmtW = nil): WideString;
+{TNT-WARN StrToCurr}
+function TntStrToCurr(const S: WideString): Currency;
+{TNT-WARN StrToCurrDef}
+function ValidCurrencyStr(const S: WideString): Boolean;
+function TntStrToCurrDef(const S: WideString; const Default: Currency): Currency;
+function GetDefaultCurrencyFmt: TCurrencyFmtW;
+
+// ........ misc functions .........
+
+{TNT-WARN GetLocaleStr}
+function WideGetLocaleStr(LocaleID: LCID; LocaleType: Integer; const Default: WideString): WideString;
+{TNT-WARN SysErrorMessage}
+function WideSysErrorMessage(ErrorCode: Integer): WideString;
+
+// ......... introduced .........
+
+function WideLibraryErrorMessage(const LibName: WideString; Dll: THandle; ErrorCode: Integer): WideString;
+
+const
+  CR = WideChar(#13);
+  LF = WideChar(#10);
+  CRLF = WideString(#13#10);
+  WideLineSeparator = WideChar($2028);
+
+var
+  Win32PlatformIsUnicode: Boolean;
+  Win32PlatformIsXP: Boolean;
+  Win32PlatformIs2003: Boolean;
+  Win32PlatformIsVista: Boolean;
+
+{$IFNDEF FPC}
+{$IFNDEF COMPILER_7_UP}
+function CheckWin32Version(AMajor: Integer; AMinor: Integer = 0): Boolean;
+{$ENDIF}
+{$ENDIF}
+function WinCheckH(RetVal: Cardinal): Cardinal;
+function WinCheckFileH(RetVal: Cardinal): Cardinal;
+function WinCheckP(RetVal: Pointer): Pointer;
+
+function WideGetModuleFileName(Instance: HModule): WideString;
+function WideSafeLoadLibrary(const Filename: Widestring;
+  ErrorMode: UINT = SEM_NOOPENFILEERRORBOX): HMODULE;
+{$IFNDEF FPC}
+function WideLoadPackage(const Name: Widestring): HMODULE;
+{$ENDIF}
+
+function IsWideCharUpper(WC: WideChar): Boolean;
+function IsWideCharLower(WC: WideChar): Boolean;
+function IsWideCharDigit(WC: WideChar): Boolean;
+function IsWideCharSpace(WC: WideChar): Boolean;
+function IsWideCharPunct(WC: WideChar): Boolean;
+function IsWideCharCntrl(WC: WideChar): Boolean;
+function IsWideCharBlank(WC: WideChar): Boolean;
+function IsWideCharXDigit(WC: WideChar): Boolean;
+function IsWideCharAlpha(WC: WideChar): Boolean;
+function IsWideCharAlphaNumeric(WC: WideChar): Boolean;
+
+function WideTextPos(const SubStr, S: WideString): Integer;
+
+function ExtractStringArrayStr(P: PWideChar): WideString;
+function ExtractStringFromStringArray(var P: PWideChar; Separator: WideChar = #0): WideString;
+function ExtractStringsFromStringArray(P: PWideChar; Separator: WideChar = #0): TWideStringDynArray;
+
+function IsWideCharMappableToAnsi(const WC: WideChar): Boolean;
+function IsWideStringMappableToAnsi(const WS: WideString): Boolean;
+function IsRTF(const Value: WideString): Boolean;
+
+function ENG_US_FloatToStr(Value: Extended): WideString;
+function ENG_US_StrToFloat(const S: WideString): Extended;
+
+//---------------------------------------------------------------------------------------------
+//                                 Tnt - Variants
+//---------------------------------------------------------------------------------------------
+
+// ........ Variants.pas has WideString versions of these functions .........
+{TNT-WARN VarToStr}
+{TNT-WARN VarToStrDef}
+
+var
+  _SettingChangeTime: Cardinal;
+
+implementation
+
+uses
+  ActiveX, ComObj, SysConst,
+  {$IFDEF COMPILER_9_UP} WideStrUtils, {$ENDIF} TntWideStrUtils,
+  TntSystem, TntFormatStrUtils;
+
+//---------------------------------------------------------------------------------------------
+//                                 Tnt - SysUtils
+//---------------------------------------------------------------------------------------------
+
+{$IFNDEF FPC}
+{$IFNDEF COMPILER_9_UP}
+
+  function _Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
+    FmtLen: Cardinal; const Args: array of const
+      {$IFDEF COMPILER_7_UP}; const FormatSettings: PFormatSettings {$ENDIF}): Cardinal;
+  var
+    OldFormat: WideString;
+    NewFormat: WideString;
+  begin
+    SetString(OldFormat, PWideChar(@FormatStr), FmtLen);
+    { The reason for this is that WideFormat doesn't correctly format floating point specifiers.
+      See QC#4254. }
+    NewFormat := ReplaceFloatingArgumentsInFormatString(OldFormat, Args{$IFDEF COMPILER_7_UP}, FormatSettings{$ENDIF});
+    {$IFDEF COMPILER_7_UP}
+    if FormatSettings <> nil then
+      Result := WideFormatBuf(Buffer, BufLen, Pointer(NewFormat)^,
+        Length(NewFormat), Args, FormatSettings^)
+    else
+    {$ENDIF}
+      Result := WideFormatBuf(Buffer, BufLen, Pointer(NewFormat)^,
+        Length(NewFormat), Args);
+  end;
+
+  function Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
+    FmtLen: Cardinal; const Args: array of const): Cardinal;
+  begin
+    Result := _Tnt_WideFormatBuf(Buffer, BufLen, FormatStr, FmtLen, Args{$IFDEF COMPILER_7_UP}, nil{$ENDIF});
+  end;
+
+  {$IFDEF COMPILER_7_UP}
+  function Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
+    FmtLen: Cardinal; const Args: array of const; const FormatSettings: TFormatSettings): Cardinal;
+  begin
+    Result := _Tnt_WideFormatBuf(Buffer, BufLen, FormatStr, FmtLen, Args, @FormatSettings);
+  end;
+  {$ENDIF}
+
+  procedure _Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
+    const Args: array of const{$IFDEF COMPILER_7_UP}; const FormatSettings: PFormatSettings{$ENDIF});
+  var
+    Len, BufLen: Integer;
+    Buffer: array[0..4095] of WideChar;
+  begin
+    BufLen := Length(Buffer); // Fixes buffer overwrite issue. (See QC #4703, #4744)
+    if Length(FormatStr) < (Length(Buffer) - (Length(Buffer) div 4)) then
+      Len := _Tnt_WideFormatBuf(Buffer, Length(Buffer) - 1, Pointer(FormatStr)^,
+        Length(FormatStr), Args{$IFDEF COMPILER_7_UP}, FormatSettings{$ENDIF})
+    else
+    begin
+      BufLen := Length(FormatStr);
+      Len := BufLen;
+    end;
+    if Len >= BufLen - 1 then
+    begin
+      while Len >= BufLen - 1 do
+      begin
+        Inc(BufLen, BufLen);
+        Result := '';          // prevent copying of existing data, for speed
+        SetLength(Result, BufLen);
+        Len := _Tnt_WideFormatBuf(Pointer(Result)^, BufLen - 1, Pointer(FormatStr)^,
+          Length(FormatStr), Args{$IFDEF COMPILER_7_UP}, FormatSettings{$ENDIF});
+      end;
+      SetLength(Result, Len);
+    end
+    else
+      SetString(Result, Buffer, Len);
+  end;
+
+  procedure Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
+    const Args: array of const);
+  begin
+    _Tnt_WideFmtStr(Result, FormatStr, Args{$IFDEF COMPILER_7_UP}, nil{$ENDIF});
+  end;
+
+  {$IFDEF COMPILER_7_UP}
+  procedure Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
+    const Args: array of const; const FormatSettings: TFormatSettings);
+  begin
+    _Tnt_WideFmtStr(Result, FormatStr, Args, @FormatSettings);
+  end;
+  {$ENDIF}
+
+  {----------------------------------------------------------------------------------------
+    Without the FormatSettings parameter, Tnt_WideFormat is *NOT* necessary...
+      TntSystem.InstallTntSystemUpdates([tsFixWideFormat]);
+        will fix WideFormat as well as WideFmtStr.
+  ----------------------------------------------------------------------------------------}
+  function Tnt_WideFormat(const FormatStr: WideString; const Args: array of const): WideString;
+  begin
+    Tnt_WideFmtStr(Result, FormatStr, Args);
+  end;
+
+  {$IFDEF COMPILER_7_UP}
+  function Tnt_WideFormat(const FormatStr: WideString; const Args: array of const;
+    const FormatSettings: TFormatSettings): WideString;
+  begin
+    Tnt_WideFmtStr(Result, FormatStr, Args, FormatSettings);
+  end;
+  {$ENDIF}
+
+{$ENDIF}
+{$ENDIF FPC}
+
+function Tnt_WideUpperCase(const S: WideString): WideString;
+begin
+  {$IFNDEF FPC}
+  {$IFNDEF COMPILER_10_UP}
+    {$DEFINE WIDEUPPERCASE_BROKEN}
+  {$ENDIF}
+  {$ENDIF}
+  {$IFDEF WIDEUPPERCASE_BROKEN}
+  { SysUtils.WideUpperCase is broken for Win9x. }
+  Result := S;
+  if Length(Result) > 0 then
+    Tnt_CharUpperBuffW(PWideChar(Result), Length(Result));
+  {$ELSE}
+  Result := SysUtils.WideUpperCase{TNT-ALLOW WideUpperCase}(S);
+  {$ENDIF}
+end;
+
+function Tnt_WideLowerCase(const S: WideString): WideString;
+begin
+  {$IFNDEF FPC}
+  {$IFNDEF COMPILER_10_UP}
+    {$DEFINE WIDELOWERCASE_BROKEN}
+  {$ENDIF}
+  {$ENDIF}
+  {$IFDEF WIDELOWERCASE_BROKEN}
+  { SysUtils.WideLowerCase is broken for Win9x. }
+  Result := S;
+  if Length(Result) > 0 then
+    Tnt_CharLowerBuffW(PWideChar(Result), Length(Result));
+  {$ELSE}
+  Result := SysUtils.WideLowerCase{TNT-ALLOW WideLowerCase}(S);
+  {$ENDIF}
+end;
+
+function TntWideLastChar(const S: WideString): WideChar;
+var
+  P: PWideChar;
+begin
+  P := WideLastChar(S);
+  if P = nil then
+    Result := #0
+  else
+    Result := P^;
+end;
+
+function Tnt_WideStringReplace(const S, OldPattern, NewPattern: WideString;
+  Flags: TReplaceFlags; WholeWord: Boolean = False): WideString;
+
+  function IsWordSeparator(WC: WideChar): Boolean;
+  begin
+    Result := (WC = WideChar(#0))
+           or IsWideCharSpace(WC)
+           or IsWideCharPunct(WC);
+  end;
+
+var
+  SearchStr, Patt, NewStr: WideString;
+  Offset: Integer;
+  PrevChar, NextChar: WideChar;
+begin
+  if rfIgnoreCase in Flags then
+  begin
+    SearchStr := Tnt_WideUpperCase(S);
+    Patt := Tnt_WideUpperCase(OldPattern);
+  end else
+  begin
+    SearchStr := S;
+    Patt := OldPattern;
+  end;
+  NewStr := S;
+  Result := '';
+  while SearchStr <> '' do
+  begin
+    Offset := Pos(Patt, SearchStr);
+    if Offset = 0 then
+    begin
+      Result := Result + NewStr;
+      Break;
+    end; // done
+
+    if (WholeWord) then
+    begin
+      if (Offset = 1) then
+        PrevChar := TntWideLastChar(Result)
+      else
+        PrevChar := NewStr[Offset - 1];
+
+      if Offset + Length(OldPattern) <= Length(NewStr) then
+        NextChar := NewStr[Offset + Length(OldPattern)]
+      else
+        NextChar := WideChar(#0);
+
+      if (not IsWordSeparator(PrevChar))
+      or (not IsWordSeparator(NextChar)) then
+      begin
+        Result := Result + Copy(NewStr, 1, Offset + Length(OldPattern) - 1);
+        NewStr := Copy(NewStr, Offset + Length(OldPattern), MaxInt);
+        SearchStr := Copy(SearchStr, Offset + Length(Patt), MaxInt);
+        continue;
+      end;
+    end;
+
+    Result := Result + Copy(NewStr, 1, Offset - 1) + NewPattern;
+    NewStr := Copy(NewStr, Offset + Length(OldPattern), MaxInt);
+    if not (rfReplaceAll in Flags) then
+    begin
+      Result := Result + NewStr;
+      Break;
+    end;
+    SearchStr := Copy(SearchStr, Offset + Length(Patt), MaxInt);
+  end;
+end;
+
+function TntAdjustLineBreaksLength(const S: WideString; Style: TTntTextLineBreakStyle = tlbsCRLF): Integer;
+var
+  Source, SourceEnd: PWideChar;
+begin
+  Source := Pointer(S);
+  SourceEnd := Source + Length(S);
+  Result := Length(S);
+  while Source < SourceEnd do
+  begin
+    case Source^ of
+      #10, WideLineSeparator:
+        if Style = tlbsCRLF then
+          Inc(Result);
+      #13:
+        if Style = tlbsCRLF then
+          if Source[1] = #10 then
+            Inc(Source)
+          else
+            Inc(Result)
+        else
+          if Source[1] = #10 then
+            Dec(Result);
+    end;
+    Inc(Source);
+  end;
+end;
+
+function TntAdjustLineBreaks(const S: WideString; Style: TTntTextLineBreakStyle = tlbsCRLF): WideString;
+var
+  Source, SourceEnd, Dest: PWideChar;
+  DestLen: Integer;
+begin
+  Source := Pointer(S);
+  SourceEnd := Source + Length(S);
+  DestLen := TntAdjustLineBreaksLength(S, Style);
+  SetString(Result, nil, DestLen);
+  Dest := Pointer(Result);
+  while Source < SourceEnd do begin
+    case Source^ of
+      #10, WideLineSeparator:
+        begin
+          if Style in [tlbsCRLF, tlbsCR] then
+          begin
+            Dest^ := #13;
+            Inc(Dest);
+          end;
+          if Style in [tlbsCRLF, tlbsLF] then
+          begin
+            Dest^ := #10;
+            Inc(Dest);
+          end;
+          Inc(Source);
+        end;
+      #13:
+        begin
+          if Style in [tlbsCRLF, tlbsCR] then
+          begin
+            Dest^ := #13;
+            Inc(Dest);
+          end;
+          if Style in [tlbsCRLF, tlbsLF] then
+          begin
+            Dest^ := #10;
+            Inc(Dest);
+          end;
+          Inc(Source);
+          if Source^ = #10 then Inc(Source);
+        end;
+    else
+      Dest^ := Source^;
+      Inc(Dest);
+      Inc(Source);
+    end;
+  end;
+end;
+
+function WideWrapText(const Line, BreakStr: WideString; const BreakChars: TSysCharSet;
+  MaxCol: Integer): WideString;
+
+  function WideCharIn(C: WideChar; SysCharSet: TSysCharSet): Boolean;
+  begin
+    Result := (C <= High(AnsiChar)) and (AnsiChar(C) in SysCharSet);
+  end;
+
+const
+  QuoteChars = ['''', '"'];
+var
+  Col, Pos: Integer;
+  LinePos, LineLen: Integer;
+  BreakLen, BreakPos: Integer;
+  QuoteChar, CurChar: WideChar;
+  ExistingBreak: Boolean;
+begin
+  Col := 1;
+  Pos := 1;
+  LinePos := 1;
+  BreakPos := 0;
+  QuoteChar := ' ';
+  ExistingBreak := False;
+  LineLen := Length(Line);
+  BreakLen := Length(BreakStr);
+  Result := '';
+  while Pos <= LineLen do
+  begin
+    CurChar := Line[Pos];
+    if CurChar = BreakStr[1] then
+    begin
+      if QuoteChar = ' ' then
+      begin
+        ExistingBreak := WideSameText(BreakStr, Copy(Line, Pos, BreakLen));
+        if ExistingBreak then
+        begin
+          Inc(Pos, BreakLen-1);
+          BreakPos := Pos;
+        end;
+      end
+    end
+    else if WideCharIn(CurChar, BreakChars) then
+    begin
+      if QuoteChar = ' ' then BreakPos := Pos
+    end
+    else if WideCharIn(CurChar, QuoteChars) then
+    begin
+      if CurChar = QuoteChar then
+        QuoteChar := ' '
+      else if QuoteChar = ' ' then
+        QuoteChar := CurChar;
+    end;
+    Inc(Pos);
+    Inc(Col);
+    if not (WideCharIn(QuoteChar, QuoteChars)) and (ExistingBreak or
+      ((Col > MaxCol) and (BreakPos > LinePos))) then
+    begin
+      Col := Pos - BreakPos;
+      Result := Result + Copy(Line, LinePos, BreakPos - LinePos + 1);
+      if not (WideCharIn(CurChar, QuoteChars)) then
+        while Pos <= LineLen do
+        begin
+          if WideCharIn(Line[Pos], BreakChars) then
+            Inc(Pos)
+          else if Copy(Line, Pos, Length(sLineBreak)) = sLineBreak then
+            Inc(Pos, Length(sLineBreak))
+          else
+            break;
+        end;
+      if not ExistingBreak and (Pos < LineLen) then
+        Result := Result + BreakStr;
+      Inc(BreakPos);
+      LinePos := BreakPos;
+      ExistingBreak := False;
+    end;
+  end;
+  Result := Result + Copy(Line, LinePos, MaxInt);
+end;
+
+function WideWrapText(const Line: WideString; MaxCol: Integer): WideString;
+begin
+  Result := WideWrapText(Line, sLineBreak, [' ', '-', #9], MaxCol); { do not localize }
+end;
+
+function WideIncludeTrailingBackslash(const S: WideString): WideString;
+begin
+  Result := WideIncludeTrailingPathDelimiter(S);
+end;
+
+function WideIncludeTrailingPathDelimiter(const S: WideString): WideString;
+begin
+  Result := S;
+  if not WideIsPathDelimiter(Result, Length(Result)) then Result := Result + PathDelim;
+end;
+
+function WideExcludeTrailingBackslash(const S: WideString): WideString;
+begin
+  Result := WideExcludeTrailingPathDelimiter(S);
+end;
+
+function WideExcludeTrailingPathDelimiter(const S: WideString): WideString;
+begin
+  Result := S;
+  if WideIsPathDelimiter(Result, Length(Result)) then
+    SetLength(Result, Length(Result)-1);
+end;
+
+function WideIsDelimiter(const Delimiters, S: WideString; Index: Integer): Boolean;
+begin
+  Result := False;
+  if (Index <= 0) or (Index > Length(S)) then exit;
+  Result := WStrScan(PWideChar(Delimiters), S[Index]) <> nil;
+end;
+
+function WideIsPathDelimiter(const S: WideString; Index: Integer): Boolean;
+begin
+  Result := (Index > 0) and (Index <= Length(S)) and (S[Index] = PathDelim);
+end;
+
+function WideLastDelimiter(const Delimiters, S: WideString): Integer;
+var
+  P: PWideChar;
+begin
+  Result := Length(S);
+  P := PWideChar(Delimiters);
+  while Result > 0 do
+  begin
+    if (S[Result] <> #0) and (WStrScan(P, S[Result]) <> nil) then
+      Exit;
+    Dec(Result);
+  end;
+end;
+
+function WideChangeFileExt(const FileName, Extension: WideString): WideString;
+var
+  I: Integer;
+begin
+  I := WideLastDelimiter('.\:',Filename);
+  if (I = 0) or (FileName[I] <> '.') then I := MaxInt;
+  Result := Copy(FileName, 1, I - 1) + Extension;
+end;
+
+function WideExtractFilePath(const FileName: WideString): WideString;
+var
+  I: Integer;
+begin
+  I := WideLastDelimiter('\:', FileName);
+  Result := Copy(FileName, 1, I);
+end;
+
+function WideExtractFileDir(const FileName: WideString): WideString;
+var
+  I: Integer;
+begin
+  I := WideLastDelimiter(DriveDelim + PathDelim,Filename);
+  if (I > 1) and (FileName[I] = PathDelim) and
+    (not (FileName[I - 1] in [WideChar(PathDelim), WideChar(DriveDelim)])) then Dec(I);
+  Result := Copy(FileName, 1, I);
+end;
+
+function WideExtractFileDrive(const FileName: WideString): WideString;
+var
+  I, J: Integer;
+begin
+  if (Length(FileName) >= 2) and (FileName[2] = DriveDelim) then
+    Result := Copy(FileName, 1, 2)
+  else if (Length(FileName) >= 2) and (FileName[1] = PathDelim) and
+    (FileName[2] = PathDelim) then
+  begin
+    J := 0;
+    I := 3;
+    While (I < Length(FileName)) and (J < 2) do
+    begin
+      if FileName[I] = PathDelim then Inc(J);
+      if J < 2 then Inc(I);
+    end;
+    if FileName[I] = PathDelim then Dec(I);
+    Result := Copy(FileName, 1, I);
+  end else Result := '';
+end;
+
+function WideExtractFileName(const FileName: WideString): WideString;
+var
+  I: Integer;
+begin
+  I := WideLastDelimiter('\:', FileName);
+  Result := Copy(FileName, I + 1, MaxInt);
+end;
+
+function WideExtractFileExt(const FileName: WideString): WideString;
+var
+  I: Integer;
+begin
+  I := WideLastDelimiter('.\:', FileName);
+  if (I > 0) and (FileName[I] = '.') then
+    Result := Copy(FileName, I, MaxInt) else
+    Result := '';
+end;
+
+function WideExtractRelativePath(const BaseName, DestName: WideString): WideString;
+var
+  BasePath, DestPath: WideString;
+  BaseLead, DestLead: PWideChar;
+  BasePtr, DestPtr: PWideChar;
+
+  function WideExtractFilePathNoDrive(const FileName: WideString): WideString;
+  begin
+    Result := WideExtractFilePath(FileName);
+    Delete(Result, 1, Length(WideExtractFileDrive(FileName)));
+  end;
+
+  function Next(var Lead: PWideChar): PWideChar;
+  begin
+    Result := Lead;
+    if Result = nil then Exit;
+    Lead := WStrScan(Lead, PathDelim);
+    if Lead <> nil then
+    begin
+      Lead^ := #0;
+      Inc(Lead);
+    end;
+  end;
+
+begin
+  if WideSameText(WideExtractFileDrive(BaseName), WideExtractFileDrive(DestName)) then
+  begin
+    BasePath := WideExtractFilePathNoDrive(BaseName);
+    DestPath := WideExtractFilePathNoDrive(DestName);
+    BaseLead := Pointer(BasePath);
+    BasePtr := Next(BaseLead);
+    DestLead := Pointer(DestPath);
+    DestPtr := Next(DestLead);
+    while (BasePtr <> nil) and (DestPtr <> nil) and WideSameText(BasePtr, DestPtr) do
+    begin
+      BasePtr := Next(BaseLead);
+      DestPtr := Next(DestLead);
+    end;
+    Result := '';
+    while BaseLead <> nil do
+    begin
+      Result := Result + '..' + PathDelim;             { Do not localize }
+      Next(BaseLead);
+    end;
+    if (DestPtr <> nil) and (DestPtr^ <> #0) then
+      Result := Result + DestPtr + PathDelim;
+    if DestLead <> nil then
+      Result := Result + DestLead;     // destlead already has a trailing backslash
+    Result := Result + WideExtractFileName(DestName);
+  end
+  else
+    Result := DestName;
+end;
+
+function WideExpandFileName(const FileName: WideString): WideString;
+var
+  FName: PWideChar;
+  Buffer: array[0..MAX_PATH - 1] of WideChar;
+begin
+  SetString(Result, Buffer, Tnt_GetFullPathNameW(PWideChar(FileName), MAX_PATH, Buffer, FName));
+end;
+
+function WideExtractShortPathName(const FileName: WideString): WideString;
+var
+  Buffer: array[0..MAX_PATH - 1] of WideChar;
+begin
+  SetString(Result, Buffer, Tnt_GetShortPathNameW(PWideChar(FileName), Buffer, MAX_PATH));
+end;
+
+function WideFileCreate(const FileName: WideString): Integer;
+begin
+  Result := Integer(Tnt_CreateFileW(PWideChar(FileName), GENERIC_READ or GENERIC_WRITE,
+    0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0))
+end;
+
+function WideFileOpen(const FileName: WideString; Mode: LongWord): Integer;
+const
+  AccessMode: array[0..2] of LongWord = (
+    GENERIC_READ,
+    GENERIC_WRITE,
+    GENERIC_READ or GENERIC_WRITE);
+  ShareMode: array[0..4] of LongWord = (
+    0,
+    0,
+    FILE_SHARE_READ,
+    FILE_SHARE_WRITE,
+    FILE_SHARE_READ or FILE_SHARE_WRITE);
+begin
+  Result := Integer(Tnt_CreateFileW(PWideChar(FileName), AccessMode[Mode and 3],
+    ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING,
+      FILE_ATTRIBUTE_NORMAL, 0));
+end;
+
+function WideFileAge(const FileName: WideString): Integer;
+var
+  Handle: THandle;
+  FindData: TWin32FindDataW;
+  LocalFileTime: TFileTime;
+begin
+  Handle := Tnt_FindFirstFileW(PWideChar(FileName), FindData);
+  if Handle <> INVALID_HANDLE_VALUE then
+  begin
+    Windows.FindClose(Handle);
+    if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
+    begin
+      FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
+      if FileTimeToDosDateTime(LocalFileTime, LongRec(Result).Hi, LongRec(Result).Lo) then
+        Exit
+    end;
+  end;
+  Result := -1;
+end;
+
+function WideFileAge(const FileName: WideString; out FileDateTime: TDateTime): Boolean;
+var
+  Handle: THandle;
+  FindData: TWin32FindDataW;
+  LSystemTime: TSystemTime;
+  LocalFileTime: TFileTime;
+begin
+  Result := False;
+  Handle := Tnt_FindFirstFileW(PWideChar(FileName), FindData);
+  if Handle <> INVALID_HANDLE_VALUE then
+  begin
+    Windows.FindClose(Handle);
+    if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
+    begin
+      Result := True;
+      FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
+      FileTimeToSystemTime(LocalFileTime, LSystemTime);
+      with LSystemTime do
+        FileDateTime := EncodeDate(wYear, wMonth, wDay) +
+          EncodeTime(wHour, wMinute, wSecond, wMilliSeconds);
+    end;
+  end;
+end;
+
+function WideDirectoryExists(const Name: WideString): Boolean;
+var
+  Code: Cardinal;
+begin
+  Code := WideFileGetAttr(Name);
+  Result := (Code <> INVALID_FILE_ATTRIBUTES) and ((FILE_ATTRIBUTE_DIRECTORY and Code) <> 0);
+end;
+
+function WideFileExists(const Name: WideString): Boolean;
+var
+  Code: Cardinal;
+begin
+  Code := WideFileGetAttr(Name);
+  Result := (Code <> INVALID_FILE_ATTRIBUTES) and ((FILE_ATTRIBUTE_DIRECTORY and Code) = 0);
+end;
+
+function WideFileGetAttr(const FileName: WideString): Cardinal;
+begin
+  Result := Tnt_GetFileAttributesW(PWideChar(FileName));
+end;
+
+function WideFileSetAttr(const FileName: WideString; Attr: Integer): Boolean;
+begin
+  Result := Tnt_SetFileAttributesW(PWideChar(FileName), Attr)
+end;
+
+function WideFileIsReadOnly(const FileName: WideString): Boolean;
+begin
+  Result := (Tnt_GetFileAttributesW(PWideChar(FileName)) and faReadOnly) <> 0;
+end;
+
+function WideFileSetReadOnly(const FileName: WideString; ReadOnly: Boolean): Boolean;
+var
+  Flags: Integer;
+begin
+  Result := False;
+  Flags := Tnt_GetFileAttributesW(PWideChar(FileName));
+  if Flags = -1 then Exit;
+  if ReadOnly then
+    Flags := Flags or faReadOnly
+  else
+    Flags := Flags and not faReadOnly;
+  Result := Tnt_SetFileAttributesW(PWideChar(FileName), Flags);
+end;
+
+function WideForceDirectories(Dir: WideString): Boolean;
+begin
+  Result := True;
+  if Length(Dir) = 0 then
+    raise ETntGeneralError.Create(
+      {$IFNDEF FPC} SCannotCreateDir {$ELSE} SCannotCreateEmptyDir {$ENDIF});
+  Dir := WideExcludeTrailingBackslash(Dir);
+  if (Length(Dir) < 3) or WideDirectoryExists(Dir)
+    or (WideExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
+  Result := WideForceDirectories(WideExtractFilePath(Dir));
+  if Result then
+    Result := Tnt_CreateDirectoryW(PWideChar(Dir), nil)
+end;
+
+function WideFileSearch(const Name, DirList: WideString): WideString;
+var
+  I, P, L: Integer;
+  C: WideChar;
+begin
+  Result := Name;
+  P := 1;
+  L := Length(DirList);
+  while True do
+  begin
+    if WideFileExists(Result) then Exit;
+    while (P <= L) and (DirList[P] = PathSep) do Inc(P);
+    if P > L then Break;
+    I := P;
+    while (P <= L) and (DirList[P] <> PathSep) do
+      Inc(P);
+    Result := Copy(DirList, I, P - I);
+    C := TntWideLastChar(Result);
+    if (C <> DriveDelim) and (C <> PathDelim) then
+      Result := Result + PathDelim;
+    Result := Result + Name;
+  end;
+  Result := '';
+end;
+
+function WideRenameFile(const OldName, NewName: WideString): Boolean;
+begin
+  Result := Tnt_MoveFileW(PWideChar(OldName), PWideChar(NewName))
+end;
+
+function WideDeleteFile(const FileName: WideString): Boolean;
+begin
+  Result := Tnt_DeleteFileW(PWideChar(FileName))
+end;
+
+function WideCopyFile(const FromFile, ToFile: WideString; FailIfExists: Boolean): Boolean;
+begin
+  Result := Tnt_CopyFileW(PWideChar(FromFile), PWideChar(ToFile), FailIfExists)
+end;
+
+function _WideFindMatchingFile(var F: TSearchRecW): Integer;
+var
+  LocalFileTime: TFileTime;
+begin
+  with F do
+  begin
+    while FindData.dwFileAttributes and ExcludeAttr <> 0 do
+      if not Tnt_FindNextFileW(FindHandle, FindData) then
+      begin
+        Result := GetLastError;
+        Exit;
+      end;
+    FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
+    FileTimeToDosDateTime(LocalFileTime, LongRec(Time).Hi, LongRec(Time).Lo);
+    Size := (Int64(FindData.nFileSizeHigh) shl 32) + FindData.nFileSizeLow;
+    Attr := FindData.dwFileAttributes;
+    Name := FindData.cFileName;
+  end;
+  Result := 0;
+end;
+
+function WideFindFirst(const Path: WideString; Attr: Integer; var F: TSearchRecW): Integer;
+const
+  faSpecial = faHidden or faSysFile {$IFNDEF COMPILER_9_UP} or faVolumeID {$ENDIF} or faDirectory;
+begin
+  F.ExcludeAttr := not Attr and faSpecial;
+  F.FindHandle := Tnt_FindFirstFileW(PWideChar(Path), F.FindData);
+  if F.FindHandle <> INVALID_HANDLE_VALUE then
+  begin
+    Result := _WideFindMatchingFile(F);
+    if Result <> 0 then WideFindClose(F);
+  end else
+    Result := GetLastError;
+end;
+
+function WideFindNext(var F: TSearchRecW): Integer;
+begin
+  if Tnt_FindNextFileW(F.FindHandle, F.FindData) then
+    Result := _WideFindMatchingFile(F) else
+    Result := GetLastError;
+end;
+
+procedure WideFindClose(var F: TSearchRecW);
+begin
+  if F.FindHandle <> INVALID_HANDLE_VALUE then
+  begin
+    Windows.FindClose(F.FindHandle);
+    F.FindHandle := INVALID_HANDLE_VALUE;
+  end;
+end;
+
+function WideCreateDir(const Dir: WideString): Boolean;
+begin
+  Result := Tnt_CreateDirectoryW(PWideChar(Dir), nil);
+end;
+
+function WideRemoveDir(const Dir: WideString): Boolean;
+begin
+  Result := Tnt_RemoveDirectoryW(PWideChar(Dir));
+end;
+
+function WideGetCurrentDir: WideString;
+begin
+  SetLength(Result, MAX_PATH);
+  Tnt_GetCurrentDirectoryW(MAX_PATH, PWideChar(Result));
+  Result := PWideChar(Result);
+end;
+
+function WideSetCurrentDir(const Dir: WideString): Boolean;
+begin
+  Result := Tnt_SetCurrentDirectoryW(PWideChar(Dir));
+end;
+
+//=============================================================================================
+//==  DATE/TIME STRING PARSING ================================================================
+//=============================================================================================
+
+{$IFDEF FPC}
+const
+  VAR_TIMEVALUEONLY = 1;
+  VAR_DATEVALUEONLY = 2;
+{$ENDIF}
+
+function _IntTryStrToDateTime(Str: WideString; Flags: Integer; out DateTime: TDateTime): HResult;
+begin
+  Result := VarDateFromStr(
+      {$IFDEF FPC} POLECHAR(Str) {$ELSE} Str {$ENDIF},
+      GetThreadLocale, Flags, Double(DateTime));
+  if (not Succeeded(Result)) then begin
+    if (Flags = VAR_TIMEVALUEONLY)
+    and SysUtils.TryStrToTime{TNT-ALLOW TryStrToTime}(Str, DateTime) then
+      Result := S_OK // SysUtils seems confident (works for date = "dd.MM.yy" and time = "H.mm.ss")
+    else if (Flags = VAR_DATEVALUEONLY)
+    and SysUtils.TryStrToDate{TNT-ALLOW TryStrToDate}(Str, DateTime) then
+      Result := S_OK // SysUtils seems confident
+    else if (Flags = 0)
+    and SysUtils.TryStrToDateTime{TNT-ALLOW TryStrToDateTime}(Str, DateTime) then
+      Result := S_OK // SysUtils seems confident
+  end;
+end;
+
+function TntTryStrToDateTime(Str: WideString; out DateTime: TDateTime): Boolean;
+begin
+  Result := Succeeded(_IntTryStrToDateTime(Str, 0, DateTime));
+end;
+
+function TntTryStrToDate(Str: WideString; out DateTime: TDateTime): Boolean;
+begin
+  Result := Succeeded(_IntTryStrToDateTime(Str, VAR_DATEVALUEONLY, DateTime));
+end;
+
+function TntTryStrToTime(Str: WideString; out DateTime: TDateTime): Boolean;
+begin
+  Result := Succeeded(_IntTryStrToDateTime(Str, VAR_TIMEVALUEONLY, DateTime));
+end;
+
+function ValidDateTimeStr(Str: WideString): Boolean;
+var
+  Temp: TDateTime;
+begin
+  Result := Succeeded(_IntTryStrToDateTime(Str, 0, Temp));
+end;
+
+function ValidDateStr(Str: WideString): Boolean;
+var
+  Temp: TDateTime;
+begin
+  Result := Succeeded(_IntTryStrToDateTime(Str, VAR_DATEVALUEONLY, Temp));
+end;
+
+function ValidTimeStr(Str: WideString): Boolean;
+var
+  Temp: TDateTime;
+begin
+  Result := Succeeded(_IntTryStrToDateTime(Str, VAR_TIMEVALUEONLY, Temp));
+end;
+
+function TntStrToDateTimeDef(Str: WideString; Default: TDateTime): TDateTime;
+begin
+  if not TntTryStrToDateTime(Str, Result) then
+    Result := Default;
+end;
+
+function TntStrToDateDef(Str: WideString; Default: TDateTime): TDateTime;
+begin
+  if not TntTryStrToDate(Str, Result) then
+    Result := Default;
+end;
+
+function TntStrToTimeDef(Str: WideString; Default: TDateTime): TDateTime;
+begin
+  if not TntTryStrToTime(Str, Result) then
+    Result := Default;
+end;
+
+function _IntStrToDateTime(Str: WideString; Flags: Integer; ErrorFormatStr: WideString): TDateTime;
+begin
+  try
+    OleCheck(_IntTryStrToDateTime(Str, Flags, Result));
+  except
+    on E: Exception do begin
+      E.Message := E.Message + CRLF + WideFormat(ErrorFormatStr, [Str]);
+      raise EConvertError.Create(E.Message);
+    end;
+  end;
+end;
+
+function TntStrToDateTime(Str: WideString): TDateTime;
+begin
+  Result := _IntStrToDateTime(Str, 0, SInvalidDateTime);
+end;
+
+function TntStrToDate(Str: WideString): TDateTime;
+begin
+  Result := _IntStrToDateTime(Str, VAR_DATEVALUEONLY,
+      {$IFNDEF FPC} SInvalidDate {$ELSE} SInvalidDateTime {$ENDIF});
+end;
+
+function TntStrToTime(Str: WideString): TDateTime;
+begin
+  Result := _IntStrToDateTime(Str, VAR_TIMEVALUEONLY,
+      {$IFNDEF FPC} SInvalidTime {$ELSE} SInvalidDateTime {$ENDIF});
+end;
+
+//=============================================================================================
+//==  CURRENCY STRING PARSING =================================================================
+//=============================================================================================
+
+function TntCurrToStr(Value: Currency; lpFormat: PCurrencyFmtW = nil): WideString;
+const
+  MAX_BUFF_SIZE = 64; // can a currency string actually be larger?
+var
+  ValueStr: WideString;
+begin
+  // format lpValue using ENG-US settings
+  ValueStr := ENG_US_FloatToStr(Value);
+  // get currency format
+  SetLength(Result, MAX_BUFF_SIZE);
+  if 0 = Tnt_GetCurrencyFormatW(GetThreadLocale, 0, PWideChar(ValueStr),
+    lpFormat, PWideChar(Result), Length(Result))
+  then begin
+    RaiseLastOSError;
+  end;
+  Result := PWideChar(Result);
+end;
+
+function TntStrToCurr(const S: WideString): Currency;
+begin
+  try
+    OleCheck(VarCyFromStr(
+        {$IFDEF FPC} POLECHAR(S) {$ELSE} S {$ENDIF},
+        GetThreadLocale, 0, Result));
+  except
+    on E: Exception do begin
+      E.Message := E.Message + CRLF + WideFormat(SInvalidCurrency, [S]);
+      raise EConvertError.Create(E.Message);
+    end;
+  end;
+end;
+
+function ValidCurrencyStr(const S: WideString): Boolean;
+var
+  Dummy: Currency;
+begin
+  Result := Succeeded(VarCyFromStr(
+      {$IFDEF FPC} POLECHAR(S) {$ELSE} S {$ENDIF},
+      GetThreadLocale, 0, Dummy));
+end;
+
+function TntStrToCurrDef(const S: WideString; const Default: Currency): Currency;
+begin
+  if not Succeeded(VarCyFromStr(
+      {$IFDEF FPC} POLECHAR(S) {$ELSE} S {$ENDIF},
+      GetThreadLocale, 0, Result)) then
+    Result := Default;
+end;
+
+threadvar
+  Currency_DecimalSep: WideString;
+  Currency_ThousandSep: WideString;
+  Currency_CurrencySymbol: WideString;
+
+function GetDefaultCurrencyFmt: TCurrencyFmtW;
+begin
+  ZeroMemory(@Result, SizeOf(Result));
+  Result.NumDigits := StrToIntDef(WideGetLocaleStr(GetThreadLocale, LOCALE_ICURRDIGITS, '2'), 2);
+  Result.LeadingZero := StrToIntDef(WideGetLocaleStr(GetThreadLocale, LOCALE_ILZERO, '1'), 1);
+  Result.Grouping := StrToIntDef(Copy(WideGetLocaleStr(GetThreadLocale, LOCALE_SMONGROUPING, '3;0'), 1, 1), 3);
+  Currency_DecimalSep := WideGetLocaleStr(GetThreadLocale, LOCALE_SMONDECIMALSEP, '.');
+  Result.lpDecimalSep := {$IFNDEF FPC} PWideChar(Currency_DecimalSep)
+                         {$ELSE}       LPTSTR(PWideChar(Currency_DecimalSep)) {$ENDIF};
+  Currency_ThousandSep := WideGetLocaleStr(GetThreadLocale, LOCALE_SMONTHOUSANDSEP, ',');
+  Result.lpThousandSep := {$IFNDEF FPC} PWideChar(Currency_ThousandSep)
+                          {$ELSE}       LPTSTR(PWideChar(Currency_ThousandSep)) {$ENDIF};
+  Result.NegativeOrder := StrToIntDef(WideGetLocaleStr(GetThreadLocale, LOCALE_INEGCURR, '0'), 0);
+  Result.PositiveOrder := StrToIntDef(WideGetLocaleStr(GetThreadLocale, LOCALE_ICURRENCY, '0'), 0);
+  Currency_CurrencySymbol := WideGetLocaleStr(GetThreadLocale, LOCALE_SCURRENCY, '');
+  Result.lpCurrencySymbol := {$IFNDEF FPC} PWideChar(Currency_CurrencySymbol)
+                             {$ELSE}       LPTSTR(PWideChar(Currency_CurrencySymbol)) {$ENDIF};
+end;
+
+//=============================================================================================
+
+{$IFDEF FPC}
+function GetLocaleStr(Locale, LocaleType: Integer; const Default: string): string;
+var
+  L: Integer;
+  Buffer: array[0..255] of Char;
+begin
+  L := GetLocaleInfo(Locale, LocaleType, Buffer, SizeOf(Buffer));
+  if L > 0 then SetString(Result, Buffer, L - 1) else Result := Default;
+end;
+{$ENDIF}
+
+function WideGetLocaleStr(LocaleID: LCID; LocaleType: Integer; const Default: WideString): WideString;
+var
+  L: Integer;
+begin
+  if (not Win32PlatformIsUnicode) then
+    Result := GetLocaleStr{TNT-ALLOW GetLocaleStr}(LocaleID, LocaleType, Default)
+  else begin
+    SetLength(Result, 255);
+    L := GetLocaleInfoW(LocaleID, LocaleType, PWideChar(Result), Length(Result));
+    if L > 0 then
+      SetLength(Result, L - 1)
+    else
+      Result := Default;
+  end;
+end;
+
+function WideSysErrorMessage(ErrorCode: Integer): WideString;
+begin
+  Result := WideLibraryErrorMessage('system', 0, ErrorCode);
+end;
+
+function WideLibraryErrorMessage(const LibName: WideString; Dll: THandle; ErrorCode: Integer): WideString;
+var
+  Len: Integer;
+  AnsiResult: AnsiString;
+  Flags: Cardinal;
+begin
+  Flags := FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_ARGUMENT_ARRAY;
+  if Dll <> 0 then
+    Flags := Flags or FORMAT_MESSAGE_FROM_HMODULE;
+  if Win32PlatformIsUnicode then begin
+    SetLength(Result, 256);
+    Len := FormatMessageW(Flags, Pointer(Dll), ErrorCode, 0, PWideChar(Result), Length(Result), nil);
+    SetLength(Result, Len);
+  end else begin
+    SetLength(AnsiResult, 256);
+    Len := FormatMessageA(Flags, Pointer(Dll), ErrorCode, 0, PAnsiChar(AnsiResult), Length(AnsiResult), nil);
+    SetLength(AnsiResult, Len);
+    Result := AnsiResult;
+  end;
+  if Trim(Result) = '' then
+    Result := WideFormat('Unspecified error (%d) from %s.', [ErrorCode, LibName]);
+end;
+
+{$IFNDEF COMPILER_7_UP}
+function CheckWin32Version(AMajor: Integer; AMinor: Integer = 0): Boolean;
+begin
+  Result := (Win32MajorVersion > AMajor) or
+            ((Win32MajorVersion = AMajor) and
+             (Win32MinorVersion >= AMinor));
+end;
+{$ENDIF}
+
+function WinCheckH(RetVal: Cardinal): Cardinal;
+begin
+  if RetVal = 0 then RaiseLastOSError;
+  Result := RetVal;
+end;
+
+function WinCheckFileH(RetVal: Cardinal): Cardinal;
+begin
+  if RetVal = INVALID_HANDLE_VALUE then RaiseLastOSError;
+  Result := RetVal;
+end;
+
+function WinCheckP(RetVal: Pointer): Pointer;
+begin
+  if RetVal = nil then RaiseLastOSError;
+  Result := RetVal;
+end;
+
+function WideGetModuleFileName(Instance: HModule): WideString;
+begin
+  SetLength(Result, MAX_PATH);
+  WinCheckH(Tnt_GetModuleFileNameW(Instance, PWideChar(Result), Length(Result)));
+  Result := PWideChar(Result)
+end;
+
+function WideSafeLoadLibrary(const Filename: Widestring; ErrorMode: UINT): HMODULE;
+var
+  OldMode: UINT;
+  FPUControlWord: Word;
+begin
+  OldMode := SetErrorMode(ErrorMode);
+  try
+    asm
+      FNSTCW  FPUControlWord
+    end;
+    try
+      Result := Tnt_LoadLibraryW(PWideChar(Filename));
+    finally
+      asm
+        FNCLEX
+        FLDCW FPUControlWord
+      end;
+    end;
+  finally
+    SetErrorMode(OldMode);
+  end;
+end;
+
+{$IFNDEF FPC}
+function WideLoadPackage(const Name: Widestring): HMODULE;
+begin
+  Result := WideSafeLoadLibrary(Name);
+  if Result = 0 then
+  begin
+    raise EPackageError.CreateFmt(sErrorLoadingPackage, [Name, WideSysErrorMessage(GetLastError)]);
+  end;
+  try
+    InitializePackage(Result);
+  except
+    FreeLibrary(Result);
+    raise;
+  end;
+end;
+{$ENDIF}
+
+function _WideCharType(WC: WideChar; dwInfoType: Cardinal): Word;
+begin
+  Win32Check(Tnt_GetStringTypeExW(GetThreadLocale, dwInfoType, PWideChar(@WC), 1, Result))
+end;
+
+function IsWideCharUpper(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and C1_UPPER) <> 0;
+end;
+
+function IsWideCharLower(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and C1_LOWER) <> 0;
+end;
+
+function IsWideCharDigit(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and C1_DIGIT) <> 0;
+end;
+
+function IsWideCharSpace(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and C1_SPACE) <> 0;
+end;
+
+function IsWideCharPunct(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and C1_PUNCT) <> 0;
+end;
+
+function IsWideCharCntrl(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and C1_CNTRL) <> 0;
+end;
+
+function IsWideCharBlank(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and C1_BLANK) <> 0;
+end;
+
+function IsWideCharXDigit(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and C1_XDIGIT) <> 0;
+end;
+
+function IsWideCharAlpha(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and C1_ALPHA) <> 0;
+end;
+
+function IsWideCharAlphaNumeric(WC: WideChar): Boolean;
+begin
+  Result := (_WideCharType(WC, CT_CTYPE1) and (C1_ALPHA + C1_DIGIT)) <> 0;
+end;
+
+function WideTextPos(const SubStr, S: WideString): Integer;
+begin
+  Result := Pos(Tnt_WideUpperCase(SubStr), Tnt_WideUpperCase(S));
+end;
+
+function FindDoubleTerminator(P: PWideChar): PWideChar;
+begin
+  Result := P;
+  while True do begin
+    Result := WStrScan(Result, #0);
+    Inc(Result);
+    if Result^ = #0 then begin
+      Dec(Result);
+      break;
+    end;
+  end;
+end;
+
+function ExtractStringArrayStr(P: PWideChar): WideString;
+var
+  PEnd: PWideChar;
+begin
+  PEnd := FindDoubleTerminator(P);
+  Inc(PEnd, 2); // move past #0#0
+  SetString(Result, P, PEnd - P);
+end;
+
+function ExtractStringFromStringArray(var P: PWideChar; Separator: WideChar = #0): WideString;
+var
+  Start: PWideChar;
+begin
+  Start := P;
+  P := WStrScan(Start, Separator);
+  if P = nil then begin
+    Result := Start;
+    P := WStrEnd(Start);
+  end else begin
+    SetString(Result, Start, P - Start);
+    Inc(P);
+  end;
+end;
+
+function ExtractStringsFromStringArray(P: PWideChar; Separator: WideChar = #0): TWideStringDynArray;
+const
+  GROW_COUNT = 256;
+var
+  Count: Integer;
+  Item: WideString;
+begin
+  Count := 0;
+  SetLength(Result, GROW_COUNT);
+  Item := ExtractStringFromStringArray(P, Separator);
+  While Item <> '' do begin
+    if Count > High(Result) then
+      SetLength(Result, Length(Result) + GROW_COUNT);
+    Result[Count] := Item;
+    Inc(Count);
+    Item := ExtractStringFromStringArray(P, Separator);
+  end;
+  SetLength(Result, Count);
+end;
+
+function IsWideCharMappableToAnsi(const WC: WideChar): Boolean;
+var
+  UsedDefaultChar: BOOL;
+begin
+  WideCharToMultiByte(DefaultSystemCodePage, 0, PWideChar(@WC), 1, nil, 0, nil, @UsedDefaultChar);
+  Result := not UsedDefaultChar;
+end;
+
+function IsWideStringMappableToAnsi(const WS: WideString): Boolean;
+var
+  UsedDefaultChar: BOOL;
+begin
+  WideCharToMultiByte(DefaultSystemCodePage, 0, PWideChar(WS), Length(WS), nil, 0, nil, @UsedDefaultChar);
+  Result := not UsedDefaultChar;
+end;
+
+function IsRTF(const Value: WideString): Boolean;
+const
+  RTF_BEGIN_1  = WideString('{\RTF');
+  RTF_BEGIN_2  = WideString('{URTF');
+begin
+  Result := (WideTextPos(RTF_BEGIN_1, Value) = 1)
+         or (WideTextPos(RTF_BEGIN_2, Value) = 1);
+end;
+
+{$IFDEF COMPILER_7_UP}
+var
+  Cached_ENG_US_FormatSettings: TFormatSettings;
+  Cached_ENG_US_FormatSettings_Time: Cardinal;
+
+function ENG_US_FormatSettings: TFormatSettings;
+begin
+  if Cached_ENG_US_FormatSettings_Time = _SettingChangeTime then
+    Result := Cached_ENG_US_FormatSettings
+  else begin
+    GetLocaleFormatSettings(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)), Result);
+    Result.DecimalSeparator := '.'; // ignore overrides
+    Cached_ENG_US_FormatSettings := Result;
+    Cached_ENG_US_FormatSettings_Time := _SettingChangeTime;
+  end;
+ end;
+
+function ENG_US_FloatToStr(Value: Extended): WideString;
+begin
+  Result := FloatToStr(Value, ENG_US_FormatSettings);
+end;
+
+function ENG_US_StrToFloat(const S: WideString): Extended;
+begin
+  if not TextToFloat(PAnsiChar(AnsiString(S)), Result, fvExtended, ENG_US_FormatSettings) then
+    Result := StrToFloat(S); // try using native format
+end;
+
+{$ELSE}
+
+function ENG_US_FloatToStr(Value: Extended): WideString;
+var
+  SaveDecimalSep: AnsiChar;
+begin
+  SaveDecimalSep := SysUtils.DecimalSeparator;
+  try
+    SysUtils.DecimalSeparator := '.';
+    Result := FloatToStr(Value);
+  finally
+    SysUtils.DecimalSeparator := SaveDecimalSep;
+  end;
+end;
+
+function ENG_US_StrToFloat(const S: WideString): Extended;
+var
+  SaveDecimalSep: AnsiChar;
+begin
+  try
+    SaveDecimalSep := SysUtils.DecimalSeparator;
+    try
+      SysUtils.DecimalSeparator := '.';
+      Result := StrToFloat(S);
+    finally
+      SysUtils.DecimalSeparator := SaveDecimalSep;
+    end;
+  except
+    if SysUtils.DecimalSeparator <> '.' then
+      Result := StrToFloat(S) // try using native format
+    else
+      raise;
+  end;
+end;
+{$ENDIF}
+
+//---------------------------------------------------------------------------------------------
+//                                 Tnt - Variants
+//---------------------------------------------------------------------------------------------
+
+initialization
+  Win32PlatformIsUnicode := (Win32Platform = VER_PLATFORM_WIN32_NT);
+  Win32PlatformIsXP := ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))
+                    or  (Win32MajorVersion > 5);
+  Win32PlatformIs2003 := ((Win32MajorVersion = 5) and (Win32MinorVersion >= 2))
+                    or  (Win32MajorVersion > 5);
+  Win32PlatformIsVista := (Win32MajorVersion >= 6);
+
+finalization
+  Currency_DecimalSep := ''; {make memory sleuth happy}
+  Currency_ThousandSep := ''; {make memory sleuth happy}
+  Currency_CurrencySymbol := ''; {make memory sleuth happy}
+
+end.
diff --git a/songmanagement/src/lib/TntUnicodeControls/TntSystem.pas b/songmanagement/src/lib/TntUnicodeControls/TntSystem.pas
new file mode 100644
index 00000000..e613ce0c
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/TntSystem.pas
@@ -0,0 +1,1427 @@
+
+{*****************************************************************************}
+{                                                                             }
+{    Tnt Delphi Unicode Controls                                              }
+{      http://www.tntware.com/delphicontrols/unicode/                         }
+{        Version: 2.3.0                                                       }
+{                                                                             }
+{    Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com)       }
+{                                                                             }
+{*****************************************************************************}
+
+unit TntSystem;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$INCLUDE TntCompilers.inc}
+
+{*****************************************************************************}
+{  Special thanks go to Francisco Leong for originating the design for        }
+{    WideString-enabled resourcestrings.                                      }
+{*****************************************************************************}
+
+interface
+
+uses
+  Windows;
+
+// These functions should not be used by Delphi code since conversions are implicit.
+{TNT-WARN WideCharToString}
+{TNT-WARN WideCharLenToString}
+{TNT-WARN WideCharToStrVar}
+{TNT-WARN WideCharLenToStrVar}
+{TNT-WARN StringToWideChar}
+
+// ................ ANSI TYPES ................
+{TNT-WARN Char}
+{TNT-WARN PChar}
+{TNT-WARN String}
+
+{TNT-WARN CP_ACP} // <-- use DefaultSystemCodePage
+function DefaultSystemCodePage: Cardinal; // implicitly used when converting AnsiString <--> WideString.
+
+{$IFNDEF FPC}
+var
+  WideCustomLoadResString: function(ResStringRec: PResStringRec; var Value: WideString): Boolean;
+{$ENDIF}
+
+{TNT-WARN LoadResString}
+function WideLoadResString(ResStringRec: PResStringRec): WideString;
+{TNT-WARN ParamCount}
+function WideParamCount: Integer;
+{TNT-WARN ParamStr}
+function WideParamStr(Index: Integer): WideString;
+
+// ......... introduced .........
+
+const
+  { Each Unicode stream should begin with the code U+FEFF,  }
+  {   which the standard defines as the *byte order mark*.  }
+  UNICODE_BOM = WideChar($FEFF);
+  UNICODE_BOM_SWAPPED = WideChar($FFFE);
+  UTF8_BOM = AnsiString(#$EF#$BB#$BF);
+
+function WideStringToUTF8(const S: WideString): AnsiString;
+function UTF8ToWideString(const S: AnsiString): WideString;
+
+function WideStringToUTF7(const W: WideString): AnsiString;
+function UTF7ToWideString(const S: AnsiString): WideString;
+
+function StringToWideStringEx(const S: AnsiString; CodePage: Cardinal): WideString;
+function WideStringToStringEx(const WS: WideString; CodePage: Cardinal): AnsiString;
+
+function UCS2ToWideString(const Value: AnsiString): WideString;
+function WideStringToUCS2(const Value: WideString): AnsiString;
+
+function CharSetToCodePage(ciCharset: UINT): Cardinal;
+function LCIDToCodePage(ALcid: LCID): Cardinal;
+function KeyboardCodePage: Cardinal;
+function KeyUnicode(CharCode: Word): WideChar;
+
+procedure StrSwapByteOrder(Str: PWideChar);
+
+{$IFDEF USE_SYSTEM_OVERRIDES}
+
+type
+  TTntSystemUpdate =
+    (tsWideResourceStrings
+     {$IFNDEF COMPILER_9_UP}, tsFixImplicitCodePage, tsFixWideStrConcat, tsFixWideFormat {$ENDIF}
+    );
+  TTntSystemUpdateSet = set of TTntSystemUpdate;
+
+const
+  AllTntSystemUpdates = [Low(TTntSystemUpdate)..High(TTntSystemUpdate)];
+
+procedure InstallTntSystemUpdates(Updates: TTntSystemUpdateSet = AllTntSystemUpdates);
+
+{$ENDIF USE_SYSTEM_OVERRIDES}
+
+implementation
+
+uses
+  SysUtils, Variants, TntWindows, TntSysUtils;
+
+var
+  GDefaultSystemCodePage: Cardinal;
+
+function DefaultSystemCodePage: Cardinal;
+begin
+  Result := GDefaultSystemCodePage;
+end;
+
+{$IFDEF USE_SYSTEM_OVERRIDES}
+var
+  IsDebugging: Boolean;
+{$ENDIF USE_SYSTEM_OVERRIDES}
+
+function WideLoadResStringDetect(ResStringRec: PResStringRec): WideString;
+var
+  PCustom: PAnsiChar;
+begin
+  // custom string pointer
+  PCustom := PAnsiChar(ResStringRec); { I would like to use PWideChar, but this would break legacy code. }
+  if  (StrLen{TNT-ALLOW StrLen}(PCustom) > Cardinal(Length(UTF8_BOM)))
+  and CompareMem(PCustom, PAnsiChar(UTF8_BOM), Length(UTF8_BOM)) then
+    // detected UTF8
+    Result := UTF8ToWideString(PAnsiChar(PCustom + Length(UTF8_BOM)))
+  else
+    // normal
+    Result := PCustom;
+end;
+
+{$IFNDEF FPC}
+
+function WideLoadResString(ResStringRec: PResStringRec): WideString;
+const
+  MAX_RES_STRING_SIZE = 4097; { MSDN documents this as the maximum size of a string in table. }
+var
+  Buffer: array [0..MAX_RES_STRING_SIZE] of WideChar; { Buffer leaves room for null terminator. }
+begin
+  if Assigned(WideCustomLoadResString) and WideCustomLoadResString(ResStringRec, Result) then
+    exit; { a custom resourcestring has been loaded. }
+
+  if ResStringRec = nil then
+    Result := ''
+  else if ResStringRec.Identifier < 64*1024 then
+    SetString(Result, Buffer,
+      Tnt_LoadStringW(FindResourceHInstance(ResStringRec.Module^),
+        ResStringRec.Identifier, Buffer, MAX_RES_STRING_SIZE))
+  else begin
+    Result := WideLoadResStringDetect(ResStringRec);
+  end;
+end;
+
+{$ELSE}
+
+function WideLoadResString(ResStringRec: PResStringRec): WideString;
+begin
+  Result := WideLoadResStringDetect(ResStringRec);
+end;
+
+{$ENDIF}
+
+function WideGetParamStr(P: PWideChar; var Param: WideString): PWideChar;
+var
+  i, Len: Integer;
+  Start, S, Q: PWideChar;
+begin
+  while True do
+  begin
+    while (P[0] <> #0) and (P[0] <= ' ') do
+      Inc(P);
+    if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break;
+  end;
+  Len := 0;
+  Start := P;
+  while P[0] > ' ' do
+  begin
+    if P[0] = '"' then
+    begin
+      Inc(P);
+      while (P[0] <> #0) and (P[0] <> '"') do
+      begin
+        Q := P + 1;
+        Inc(Len, Q - P);
+        P := Q;
+      end;
+      if P[0] <> #0 then
+        Inc(P);
+    end
+    else
+    begin
+      Q := P + 1;
+      Inc(Len, Q - P);
+      P := Q;
+    end;
+  end;
+
+  SetLength(Param, Len);
+
+  P := Start;
+  S := PWideChar(Param);
+  i := 0;
+  while P[0] > ' ' do
+  begin
+    if P[0] = '"' then
+    begin
+      Inc(P);
+      while (P[0] <> #0) and (P[0] <> '"') do
+      begin
+        Q := P + 1;
+        while P < Q do
+        begin
+          S[i] := P^;
+          Inc(P);
+          Inc(i);
+        end;
+      end;
+      if P[0] <> #0 then Inc(P);
+    end
+    else
+    begin
+      Q := P + 1;
+      while P < Q do
+      begin
+        S[i] := P^;
+        Inc(P);
+        Inc(i);
+      end;
+    end;
+  end;
+
+  Result := P;
+end;
+
+function WideParamCount: Integer;
+var
+  P: PWideChar;
+  S: WideString;
+begin
+  P := WideGetParamStr(GetCommandLineW, S);
+  Result := 0;
+  while True do
+  begin
+    P := WideGetParamStr(P, S);
+    if S = '' then Break;
+    Inc(Result);
+  end;
+end;
+
+function WideParamStr(Index: Integer): WideString;
+var
+  P: PWideChar;
+begin
+  if Index = 0 then
+    Result := WideGetModuleFileName(0)
+  else
+  begin
+    P := GetCommandLineW;
+    while True do
+    begin
+      P := WideGetParamStr(P, Result);
+      if (Index = 0) or (Result = '') then Break;
+      Dec(Index);
+    end;
+  end;
+end;
+
+function WideStringToUTF8(const S: WideString): AnsiString;
+begin
+  Result := UTF8Encode(S);
+end;
+
+function UTF8ToWideString(const S: AnsiString): WideString;
+begin
+  Result := UTF8Decode(S);
+end;
+
+  { ======================================================================= }
+  { Original File:   ConvertUTF7.c                                          }
+  { Author: David B. Goldsmith                                              }
+  { Copyright (C) 1994, 1996 Taligent, Inc. All rights reserved.            }
+  {                                                                         }
+  { This code is copyrighted. Under the copyright laws, this code may not   }
+  { be copied, in whole or part, without prior written consent of Taligent. }
+  {                                                                         }
+  { Taligent grants the right to use this code as long as this ENTIRE       }
+  { copyright notice is reproduced in the code.  The code is provided       }
+  { AS-IS, AND TALIGENT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR         }
+  { IMPLIED, INCLUDING, BUT NOT LIMITED TO IMPLIED WARRANTIES OF            }
+  { MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT      }
+  { WILL TALIGENT BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING,          }
+  { WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS      }
+  { INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY          }
+  { LOSS) ARISING OUT OF THE USE OR INABILITY TO USE THIS CODE, EVEN        }
+  { IF TALIGENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.        }
+  { BECAUSE SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF         }
+  { LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE            }
+  { LIMITATION MAY NOT APPLY TO YOU.                                        }
+  {                                                                         }
+  { RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the        }
+  { government is subject to restrictions as set forth in subparagraph      }
+  { (c)(l)(ii) of the Rights in Technical Data and Computer Software        }
+  { clause at DFARS 252.227-7013 and FAR 52.227-19.                         }
+  {                                                                         }
+  { This code may be protected by one or more U.S. and International        }
+  { Patents.                                                                }
+  {                                                                         }
+  { TRADEMARKS: Taligent and the Taligent Design Mark are registered        }
+  { trademarks of Taligent, Inc.                                            }
+  { ======================================================================= }
+
+type UCS2 = Word;
+
+const
+  _base64: AnsiString = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+  _direct: AnsiString = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789''(),-./:?';
+  _optional: AnsiString = '!"#$%&*;<=>@[]^_`{|}';
+  _spaces: AnsiString = #9#13#10#32;
+
+var
+  base64: PAnsiChar;
+  invbase64: array[0..127] of SmallInt;
+  direct: PAnsiChar;
+  optional: PAnsiChar;
+  spaces: PAnsiChar;
+  mustshiftsafe: array[0..127] of AnsiChar;
+  mustshiftopt: array[0..127] of AnsiChar;
+
+var
+  needtables: Boolean = True;
+
+procedure Initialize_UTF7_Data;
+begin
+  base64 := PAnsiChar(_base64);
+  direct := PAnsiChar(_direct);
+  optional := PAnsiChar(_optional);
+  spaces := PAnsiChar(_spaces);
+end;
+
+procedure tabinit;
+var
+  i: Integer;
+  limit: Integer;
+begin
+  i := 0;
+  while (i < 128) do
+  begin
+    mustshiftopt[i] := #1;
+    mustshiftsafe[i] := #1;
+    invbase64[i] := -1;
+    Inc(i);
+  end { For };
+  limit := Length(_Direct);
+  i := 0;
+  while (i < limit) do
+  begin
+    mustshiftopt[Integer(direct[i])] := #0;
+    mustshiftsafe[Integer(direct[i])] := #0;
+    Inc(i);
+  end { For };
+  limit := Length(_Spaces);
+  i := 0;
+  while (i < limit) do
+  begin
+    mustshiftopt[Integer(spaces[i])] := #0;
+    mustshiftsafe[Integer(spaces[i])] := #0;
+    Inc(i);
+  end { For };
+  limit := Length(_Optional);
+  i := 0;
+  while (i < limit) do
+  begin
+    mustshiftopt[Integer(optional[i])] := #0;
+    Inc(i);
+  end { For };
+  limit := Length(_Base64);
+  i := 0;
+  while (i < limit) do
+  begin
+    invbase64[Integer(base64[i])] := i;
+    Inc(i);
+  end { For };
+  needtables := False;
+end; { tabinit }
+
+function WRITE_N_BITS(x: UCS2; n: Integer; var BITbuffer: Cardinal; var bufferbits: Integer): Integer;
+begin
+  BITbuffer := BITbuffer or (x and (not (-1 shl n))) shl (32 - n - bufferbits);
+  bufferbits := bufferbits + n;
+  Result := bufferbits;
+end; { WRITE_N_BITS }
+
+function READ_N_BITS(n: Integer; var BITbuffer: Cardinal; var bufferbits: Integer): UCS2;
+var
+  buffertemp: Cardinal;
+begin
+  buffertemp := BITbuffer shr (32 - n);
+  BITbuffer := BITbuffer shl n;
+  bufferbits := bufferbits - n;
+  Result := UCS2(buffertemp);
+end; { READ_N_BITS }
+
+function ConvertUCS2toUTF7(var sourceStart: PWideChar; sourceEnd: PWideChar;
+  var targetStart: PAnsiChar; targetEnd: PAnsiChar; optional: Boolean;
+    verbose: Boolean): Integer;
+var
+  r: UCS2;
+  target: PAnsiChar;
+  source: PWideChar;
+  BITbuffer: Cardinal;
+  bufferbits: Integer;
+  shifted: Boolean;
+  needshift: Boolean;
+  done: Boolean;
+  mustshift: PAnsiChar;
+begin
+  Initialize_UTF7_Data;
+  Result := 0;
+  BITbuffer := 0;
+  bufferbits := 0;
+  shifted := False;
+  source := sourceStart;
+  target := targetStart;
+  r := 0;
+  if needtables then
+    tabinit;
+  if optional then
+    mustshift := @mustshiftopt[0]
+  else
+    mustshift := @mustshiftsafe[0];
+  repeat
+    done := source >= sourceEnd;
+    if not Done then
+    begin
+      r := Word(source^);
+      Inc(Source);
+    end { If };
+    needshift := (not done) and ((r > $7F) or (mustshift[r] <> #0));
+    if needshift and (not shifted) then
+    begin
+      if (Target >= TargetEnd) then
+      begin
+        Result := 2;
+        break;
+      end { If };
+      target^ := '+';
+      Inc(target);
+      { Special case handling of the SHIFT_IN character }
+      if (r = UCS2('+')) then
+      begin
+        if (target >= targetEnd) then
+        begin
+          Result := 2;
+          break;
+        end;
+        target^ := '-';
+        Inc(target);
+      end
+      else
+        shifted := True;
+    end { If };
+    if shifted then
+    begin
+      { Either write the character to the bit buffer, or pad }
+      { the bit buffer out to a full base64 character. }
+      { }
+      if needshift then
+        WRITE_N_BITS(r, 16, BITbuffer, bufferbits)
+      else
+        WRITE_N_BITS(0, (6 - (bufferbits mod 6)) mod 6, BITbuffer,
+          bufferbits);
+      { Flush out as many full base64 characters as possible }
+      { from the bit buffer. }
+      { }
+      while (target < targetEnd) and (bufferbits >= 6) do
+      begin
+        Target^ := base64[READ_N_BITS(6, BITbuffer, bufferbits)];
+        Inc(Target);
+      end { While };
+      if (bufferbits >= 6) then
+      begin
+        if (target >= targetEnd) then
+        begin
+          Result := 2;
+          break;
+        end { If };
+      end { If };
+      if (not needshift) then
+      begin
+        { Write the explicit shift out character if }
+        { 1) The caller has requested we always do it, or }
+        { 2) The directly encoded character is in the }
+        { base64 set, or }
+        { 3) The directly encoded character is SHIFT_OUT. }
+        { }
+        if verbose or ((not done) and ((invbase64[r] >= 0) or (r =
+          Integer('-')))) then
+        begin
+          if (target >= targetEnd) then
+          begin
+            Result := 2;
+            Break;
+          end { If };
+          Target^ := '-';
+          Inc(Target);
+        end { If };
+        shifted := False;
+      end { If };
+      { The character can be directly encoded as ASCII. }
+    end { If };
+    if (not needshift) and (not done) then
+    begin
+      if (target >= targetEnd) then
+      begin
+        Result := 2;
+        break;
+      end { If };
+      Target^ := AnsiChar(r);
+      Inc(Target);
+    end { If };
+  until (done);
+  sourceStart := source;
+  targetStart := target;
+end; { ConvertUCS2toUTF7 }
+
+function ConvertUTF7toUCS2(var sourceStart: PAnsiChar; sourceEnd: PAnsiChar;
+  var targetStart: PWideChar; targetEnd: PWideChar): Integer;
+var
+  target: PWideChar { Register };
+  source: PAnsiChar { Register };
+  BITbuffer: Cardinal { & "Address Of" Used };
+  bufferbits: Integer { & "Address Of" Used };
+  shifted: Boolean { Used In Boolean Context };
+  first: Boolean { Used In Boolean Context };
+  wroteone: Boolean;
+  base64EOF: Boolean;
+  base64value: Integer;
+  done: Boolean;
+  c: UCS2;
+  prevc: UCS2;
+  junk: UCS2 { Used In Boolean Context };
+begin
+  Initialize_UTF7_Data;
+  Result := 0;
+  BITbuffer := 0;
+  bufferbits := 0;
+  shifted := False;
+  first := False;
+  wroteone := False;
+  source := sourceStart;
+  target := targetStart;
+  c := 0;
+  if needtables then
+    tabinit;
+  repeat
+    { read an ASCII character c }
+    done := Source >= SourceEnd;
+    if (not done) then
+    begin
+      c := Word(Source^);
+      Inc(Source);
+    end { If };
+    if shifted then
+    begin
+      { We're done with a base64 string if we hit EOF, it's not a valid }
+      { ASCII character, or it's not in the base64 set. }
+      { }
+      base64value := invbase64[c];
+      base64EOF := (done or (c > $7F)) or (base64value < 0);
+      if base64EOF then
+      begin
+        shifted := False;
+        { If the character causing us to drop out was SHIFT_IN or }
+        { SHIFT_OUT, it may be a special escape for SHIFT_IN. The }
+        { test for SHIFT_IN is not necessary, but allows an alternate }
+        { form of UTF-7 where SHIFT_IN is escaped by SHIFT_IN. This }
+        { only works for some values of SHIFT_IN. }
+        { }
+        if ((not done) and ((c = Integer('+')) or (c = Integer('-')))) then
+        begin
+          { get another character c }
+          prevc := c;
+          Done := Source >= SourceEnd;
+          if (not Done) then
+          begin
+            c := Word(Source^);
+            Inc(Source);
+            { If no base64 characters were encountered, and the }
+            { character terminating the shift sequence was }
+            { SHIFT_OUT, then it's a special escape for SHIFT_IN. }
+            { }
+          end;
+          if first and (prevc = Integer('-')) then
+          begin
+            { write SHIFT_IN unicode }
+            if (target >= targetEnd) then
+            begin
+              Result := 2;
+              break;
+            end { If };
+            Target^ := WideChar('+');
+            Inc(Target);
+          end
+          else
+          begin
+            if (not wroteone) then
+            begin
+              Result := 1;
+            end { If };
+          end { Else };
+          ;
+        end { If }
+        else
+        begin
+          if (not wroteone) then
+          begin
+            Result := 1;
+          end { If };
+        end { Else };
+      end { If }
+      else
+      begin
+        { Add another 6 bits of base64 to the bit buffer. }
+        WRITE_N_BITS(base64value, 6, BITbuffer,
+          bufferbits);
+        first := False;
+      end { Else };
+      { Extract as many full 16 bit characters as possible from the }
+      { bit buffer. }
+      { }
+      while (bufferbits >= 16) and (target < targetEnd) do
+      begin
+        { write a unicode }
+        Target^ := WideChar(READ_N_BITS(16, BITbuffer, bufferbits));
+        Inc(Target);
+        wroteone := True;
+      end { While };
+      if (bufferbits >= 16) then
+      begin
+        if (target >= targetEnd) then
+        begin
+          Result := 2;
+          Break;
+        end;
+      end { If };
+      if (base64EOF) then
+      begin
+        junk := READ_N_BITS(bufferbits, BITbuffer, bufferbits);
+        if (junk <> 0) then
+        begin
+          Result := 1;
+        end { If };
+      end { If };
+    end { If };
+    if (not shifted) and (not done) then
+    begin
+      if (c = Integer('+')) then
+      begin
+        shifted := True;
+        first := True;
+        wroteone := False;
+      end { If }
+      else
+      begin
+        { It must be a directly encoded character. }
+        if (c > $7F) then
+        begin
+          Result := 1;
+        end { If };
+        if (target >= targetEnd) then
+        begin
+          Result := 2;
+          break;
+        end { If };
+        Target^ := WideChar(c);
+        Inc(Target);
+      end { Else };
+    end { If };
+  until (done);
+  sourceStart := source;
+  targetStart := target;
+end; { ConvertUTF7toUCS2 }
+
+  {*****************************************************************************}
+  { Thanks to Francisco Leong for providing the Pascal conversion of            }
+  {   ConvertUTF7.c (by David B. Goldsmith)                                     }
+  {*****************************************************************************}
+
+resourcestring
+  SBufferOverflow = 'Buffer overflow';
+  SInvalidUTF7 = 'Invalid UTF7';
+
+function WideStringToUTF7(const W: WideString): AnsiString;
+var
+  SourceStart, SourceEnd: PWideChar;
+  TargetStart, TargetEnd: PAnsiChar;
+begin
+  if W = '' then
+    Result := ''
+  else
+  begin
+    SetLength(Result, Length(W) * 7); // Assume worst case
+    SourceStart := PWideChar(@W[1]);
+    SourceEnd := PWideChar(@W[Length(W)]) + 1;
+    TargetStart := PAnsiChar(@Result[1]);
+    TargetEnd := PAnsiChar(@Result[Length(Result)]) + 1;
+    if ConvertUCS2toUTF7(SourceStart, SourceEnd, TargetStart,
+      TargetEnd, True, False) <> 0
+    then
+      raise ETntInternalError.Create(SBufferOverflow);
+    SetLength(Result, TargetStart - PAnsiChar(@Result[1]));
+  end;
+end;
+
+function UTF7ToWideString(const S: AnsiString): WideString;
+var
+  SourceStart, SourceEnd: PAnsiChar;
+  TargetStart, TargetEnd: PWideChar;
+begin
+  if (S = '') then
+    Result := ''
+  else
+  begin
+    SetLength(Result, Length(S)); // Assume Worst case
+    SourceStart := PAnsiChar(@S[1]);
+    SourceEnd := PAnsiChar(@S[Length(S)]) + 1;
+    TargetStart := PWideChar(@Result[1]);
+    TargetEnd := PWideChar(@Result[Length(Result)]) + 1;
+    case ConvertUTF7toUCS2(SourceStart, SourceEnd, TargetStart,
+      TargetEnd) of
+      1: raise ETntGeneralError.Create(SInvalidUTF7);
+      2: raise ETntInternalError.Create(SBufferOverflow);
+    end;
+    SetLength(Result, TargetStart - PWideChar(@Result[1]));
+  end;
+end;
+
+function StringToWideStringEx(const S: AnsiString; CodePage: Cardinal): WideString;
+var
+  InputLength,
+  OutputLength: Integer;
+begin
+  if CodePage = CP_UTF7 then
+    Result := UTF7ToWideString(S) // CP_UTF7 not supported on Windows 95
+  else if CodePage = CP_UTF8 then
+    Result := UTF8ToWideString(S) // CP_UTF8 not supported on Windows 95
+  else begin
+    InputLength := Length(S);
+    OutputLength := MultiByteToWideChar(CodePage, 0, PAnsiChar(S), InputLength, nil, 0);
+    SetLength(Result, OutputLength);
+    MultiByteToWideChar(CodePage, 0, PAnsiChar(S), InputLength, PWideChar(Result), OutputLength);
+  end;
+end;
+
+function WideStringToStringEx(const WS: WideString; CodePage: Cardinal): AnsiString;
+var
+  InputLength,
+  OutputLength: Integer;
+begin
+  if CodePage = CP_UTF7 then
+    Result := WideStringToUTF7(WS) // CP_UTF7 not supported on Windows 95
+  else if CodePage = CP_UTF8 then
+    Result := WideStringToUTF8(WS) // CP_UTF8 not supported on Windows 95
+  else begin
+    InputLength := Length(WS);
+    OutputLength := WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, nil, 0, nil, nil);
+    SetLength(Result, OutputLength);
+    WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, PAnsiChar(Result), OutputLength, nil, nil);
+  end;
+end;
+
+function UCS2ToWideString(const Value: AnsiString): WideString;
+begin
+  if Length(Value) = 0 then
+    Result := ''
+  else
+    SetString(Result, PWideChar(@Value[1]), Length(Value) div SizeOf(WideChar))
+end;
+
+function WideStringToUCS2(const Value: WideString): AnsiString;
+begin
+  if Length(Value) = 0 then
+    Result := ''
+  else
+    SetString(Result, PAnsiChar(@Value[1]), Length(Value) * SizeOf(WideChar))
+end;
+
+{ Windows.pas doesn't declare TranslateCharsetInfo() correctly. }
+function TranslateCharsetInfo(lpSrc: PDWORD; var lpCs: TCharsetInfo; dwFlags: DWORD): BOOL; stdcall; external gdi32 name 'TranslateCharsetInfo';
+
+function CharSetToCodePage(ciCharset: UINT): Cardinal;
+var
+  C: TCharsetInfo;
+begin
+  Win32Check(TranslateCharsetInfo(PDWORD(ciCharset), C, TCI_SRCCHARSET));
+  Result := C.ciACP
+end;
+
+function LCIDToCodePage(ALcid: LCID): Cardinal;
+var
+  Buf: array[0..6] of AnsiChar;
+begin
+  GetLocaleInfo(ALcid, LOCALE_IDefaultAnsiCodePage, Buf, 6);
+  Result := StrToIntDef(Buf, GetACP);
+end;
+
+function KeyboardCodePage: Cardinal;
+begin
+  Result := LCIDToCodePage(GetKeyboardLayout(0) and $FFFF);
+end;
+
+function KeyUnicode(CharCode: Word): WideChar;
+var
+  AChar: AnsiChar;
+begin
+  // converts the given character (as it comes with a WM_CHAR message) into its
+  // corresponding Unicode character depending on the active keyboard layout
+  if CharCode <= Word(High(AnsiChar)) then begin
+    AChar := AnsiChar(CharCode);
+    MultiByteToWideChar(KeyboardCodePage, MB_USEGLYPHCHARS, @AChar, 1, @Result, 1);
+  end else
+    Result := WideChar(CharCode);
+end;
+
+procedure StrSwapByteOrder(Str: PWideChar);
+var
+  P: PWord;
+begin
+  P := PWord(Str);
+  While (P^ <> 0) do begin
+    P^ := MakeWord(HiByte(P^), LoByte(P^));
+    Inc(P);
+  end;
+end;
+
+{$IFDEF USE_SYSTEM_OVERRIDES}
+
+//--------------------------------------------------------------------
+//                LoadResString()
+//
+//  This system function is used to retrieve a resourcestring and
+//   return the result as an AnsiString.  If we believe that the result
+//    is only a temporary value, and that it will be immediately
+//     assigned to a WideString or a Variant, then we will save the
+//      Unicode result as well as a reference to the original Ansi string.
+//       WStrFromPCharLen() or VarFromLStr() will return this saved
+//        Unicode string if it appears to receive the most recent result
+//         of LoadResString.
+//--------------------------------------------------------------------
+
+
+  //===========================================================================================
+  //
+  //    function CodeMatchesPatternForUnicode(...);
+  //
+  //    GIVEN:  SomeWideString := SSomeResString;  { WideString := resourcestring }
+  //
+  //    Delphi will compile this statement into the following:
+  //    -------------------------------------------------
+  //    TempAnsiString := LoadResString(@SSomeResString);
+  //      LINE 1:  lea edx,[SomeTempAnsiString]
+  //      LINE 2:  mov eax,[@SomeResString]
+  //      LINE 3:  call LoadResString
+  //
+  //    WStrFromLStr(SomeWideString, TempAnsiString);  { SomeWideString := TempAnsiString }
+  //      LINE 4:  mov edx,[SomeTempAnsiString]
+  //      LINE 5:  mov/lea eax [@SomeWideString]
+  //      LINE 6:  call @WStrFromLStr
+  //    -------------------------------------------------
+  //
+  //    The order in which the parameters are prepared for WStrFromLStr (ie LINE 4 & 5) is
+  //      reversed when assigning a non-temporary AnsiString to a WideString.
+  //
+  //    This code, for example, results in LINE 4 and LINE 5 being swapped.
+  //
+  //      SomeAnsiString := SSomeResString;
+  //      SomeWideString := SomeAnsiString;
+  //
+  //    Since we know the "signature" used by the compiler, we can detect this pattern.
+  //     If we believe it is only temporary, we can save the Unicode results for later
+  //      retrieval from WStrFromLStr.
+  //
+  //    One final note:  When assigning a resourcestring to a Variant, the same patterns exist.
+  //===========================================================================================
+
+function CodeMatchesPatternForUnicode(PLine4: PAnsiChar): Boolean;
+const
+  SIZEOF_OPCODE = 1 {byte};
+  MOV_16_OPCODE = AnsiChar($8B); { we'll assume operand size is 16 bits }
+  MOV_32_OPCODE = AnsiChar($B8); { we'll assume operand size is 32 bits }
+  LEA_OPCODE    = AnsiChar($8D); { operand size can be 16 or 40 bits }
+  CALL_OPCODE   = AnsiChar($E8); { assumed operand size is 32 bits }
+  BREAK_OPCODE  = AnsiChar($CC); {in a breakpoint}
+var
+  PLine1: PAnsiChar;
+  PLine2: PAnsiChar;
+  PLine3: PAnsiChar;
+  DataSize: Integer; // bytes in first LEA operand
+begin
+  Result := False;
+
+  PLine3 := PLine4 - SizeOf(CALL_OPCODE) - 4;
+  PLine2 := PLine3 - SizeOf(MOV_32_OPCODE) - 4;
+
+  // figure PLine1 and operand size
+  DataSize := 2; { try 16 bit operand for line 1 }
+  PLine1 := PLine2 - DataSize - SizeOf(LEA_OPCODE);
+  if (PLine1^ <> LEA_OPCODE) and (not (IsDebugging and (PLine1^ = BREAK_OPCODE))) then
+  begin
+    DataSize := 5; { try 40 bit operand for line 1 }
+    PLine1 := PLine2 - DataSize - SizeOf(LEA_OPCODE);
+  end;
+  if (PLine1^ = LEA_OPCODE) or (IsDebugging and (PLine1^ = BREAK_OPCODE)) then
+  begin
+    if CompareMem(PLine1 + SIZEOF_OPCODE, PLine4 + SIZEOF_OPCODE, DataSize) then
+    begin
+      // After this check, it seems to match the WideString <- (temp) AnsiString pattern
+      Result := True; // It is probably OK. (The side effects of being wrong aren't very bad.)
+    end;
+  end;
+end;
+
+threadvar
+  PLastResString: PAnsiChar;
+  LastResStringValue: AnsiString;
+  LastWideResString: WideString;
+
+procedure FreeTntSystemThreadVars;
+begin
+  LastResStringValue := '';
+  LastWideResString := '';
+end;
+
+procedure Custom_System_EndThread(ExitCode: Integer);
+begin
+  FreeTntSystemThreadVars;
+  {$IFDEF COMPILER_10_UP}
+  if Assigned(SystemThreadEndProc) then
+    SystemThreadEndProc(ExitCode);
+  {$ENDIF}
+  ExitThread(ExitCode);
+end;
+
+function Custom_System_LoadResString(ResStringRec: PResStringRec): AnsiString;
+var
+  ReturnAddr: Pointer;
+begin
+  // get return address
+  asm
+    PUSH   ECX
+    MOV    ECX, [EBP + 4]
+    MOV    ReturnAddr, ECX
+    POP    ECX
+  end;
+  // check calling code pattern
+  if CodeMatchesPatternForUnicode(ReturnAddr) then begin
+    // result will probably be assigned to an intermediate AnsiString
+    //   on its way to either a WideString or Variant.
+    LastWideResString := WideLoadResString(ResStringRec);
+    Result := LastWideResString;
+    LastResStringValue := Result;
+    if Result = '' then
+      PLastResString := nil
+    else
+      PLastResString := PAnsiChar(Result);
+  end else begin
+    // result will probably be assigned to an actual AnsiString variable.
+    PLastResString := nil;
+    Result := WideLoadResString(ResStringRec);
+  end;
+end;
+
+//--------------------------------------------------------------------
+//                WStrFromPCharLen()
+//
+//  This system function is used to assign an AnsiString to a WideString.
+//   It has been modified to assign Unicode results from LoadResString.
+//     Another purpose of this function is to specify the code page.
+//--------------------------------------------------------------------
+
+procedure Custom_System_WStrFromPCharLen(var Dest: WideString; Source: PAnsiChar; Length: Integer);
+var
+  DestLen: Integer;
+  Buffer: array[0..2047] of WideChar;
+  Local_PLastResString: Pointer;
+begin
+  Local_PLastResString := PLastResString;
+  if  (Local_PLastResString <> nil)
+  and (Local_PLastResString = Source)
+  and (System.Length(LastResStringValue) = Length)
+  and (LastResStringValue = Source) then begin
+    // use last unicode resource string
+    PLastResString := nil; { clear for further use }
+    Dest := LastWideResString;
+  end else begin
+    if Local_PLastResString <> nil then
+      PLastResString := nil; { clear for further use }
+    if Length <= 0 then
+    begin
+      Dest := '';
+      Exit;
+    end;
+    if Length + 1 < High(Buffer) then
+    begin
+      DestLen := MultiByteToWideChar(DefaultSystemCodePage, 0, Source, Length, Buffer,
+        High(Buffer));
+      if DestLen > 0 then
+      begin
+        SetLength(Dest, DestLen);
+        Move(Pointer(@Buffer[0])^, Pointer(Dest)^, DestLen * SizeOf(WideChar));
+        Exit;
+      end;
+    end;
+    DestLen := (Length + 1);
+    SetLength(Dest, DestLen); // overallocate, trim later
+    DestLen := MultiByteToWideChar(DefaultSystemCodePage, 0, Source, Length, Pointer(Dest),
+      DestLen);
+    if DestLen < 0 then
+      DestLen := 0;
+    SetLength(Dest, DestLen);
+  end;
+end;
+
+{$IFNDEF COMPILER_9_UP}
+
+//--------------------------------------------------------------------
+//                LStrFromPWCharLen()
+//
+//  This system function is used to assign an WideString to an AnsiString.
+//   It has not been modified from its original purpose other than to specify the code page.
+//--------------------------------------------------------------------
+
+procedure Custom_System_LStrFromPWCharLen(var Dest: AnsiString; Source: PWideChar; Length: Integer);
+var
+  DestLen: Integer;
+  Buffer: array[0..4095] of AnsiChar;
+begin
+  if Length <= 0 then
+  begin
+    Dest := '';
+    Exit;
+  end;
+  if Length + 1 < (High(Buffer) div sizeof(WideChar)) then
+  begin
+    DestLen := WideCharToMultiByte(DefaultSystemCodePage, 0, Source,
+      Length, Buffer, High(Buffer),
+      nil, nil);
+    if DestLen >= 0 then
+    begin
+      SetLength(Dest, DestLen);
+      Move(Pointer(@Buffer[0])^, PAnsiChar(Dest)^, DestLen);
+      Exit;
+    end;
+  end;
+
+  DestLen := (Length + 1) * sizeof(WideChar);
+  SetLength(Dest, DestLen); // overallocate, trim later
+  DestLen := WideCharToMultiByte(DefaultSystemCodePage, 0, Source, Length, Pointer(Dest), DestLen,
+    nil, nil);
+  if DestLen < 0 then
+    DestLen := 0;
+  SetLength(Dest, DestLen);
+end;
+
+//--------------------------------------------------------------------
+//                WStrToString()
+//
+//  This system function is used to assign an WideString to an short string.
+//   It has not been modified from its original purpose other than to specify the code page.
+//--------------------------------------------------------------------
+
+procedure Custom_System_WStrToString(Dest: PShortString; const Source: WideString; MaxLen: Integer);
+var
+  SourceLen, DestLen: Integer;
+  Buffer: array[0..511] of AnsiChar;
+begin
+  if MaxLen > 255 then MaxLen := 255;
+  SourceLen := Length(Source);
+  if SourceLen >= MaxLen then SourceLen := MaxLen;
+  if SourceLen = 0 then
+    DestLen := 0
+  else begin
+    DestLen := WideCharToMultiByte(DefaultSystemCodePage, 0, Pointer(Source), SourceLen,
+      Buffer, SizeOf(Buffer), nil, nil);
+    if DestLen > MaxLen then DestLen := MaxLen;
+  end;
+  Dest^[0] := Chr(DestLen);
+  if DestLen > 0 then Move(Buffer, Dest^[1], DestLen);
+end;
+
+{$ENDIF}
+
+//--------------------------------------------------------------------
+//                VarFromLStr()
+//
+//  This system function is used to assign an AnsiString to a Variant.
+//   It has been modified to assign Unicode results from LoadResString.
+//--------------------------------------------------------------------
+
+procedure Custom_System_VarFromLStr(var V: TVarData; const Value: AnsiString);
+const
+  varDeepData = $BFE8;
+var
+  Local_PLastResString: Pointer;
+begin
+  if (V.VType and varDeepData) <> 0 then
+    VarClear(PVariant(@V)^);
+
+  Local_PLastResString := PLastResString;
+  if  (Local_PLastResString <> nil)
+  and (Local_PLastResString = PAnsiChar(Value))
+  and (LastResStringValue = Value) then begin
+    // use last unicode resource string
+    PLastResString := nil; { clear for further use }
+    V.VOleStr := nil;
+    V.VType := varOleStr;
+    WideString(Pointer(V.VOleStr)) := Copy(LastWideResString, 1, MaxInt);
+  end else begin
+    if Local_PLastResString <> nil then
+      PLastResString := nil; { clear for further use }
+    V.VString := nil;
+    V.VType := varString;
+    AnsiString(V.VString) := Value;
+  end;
+end;
+
+{$IFNDEF COMPILER_9_UP}
+
+//--------------------------------------------------------------------
+//                WStrCat3()     A := B + C;
+//
+//  This system function is used to concatenate two strings into one result.
+//    This function is added because A := '' + '' doesn't necessarily result in A = '';
+//--------------------------------------------------------------------
+
+procedure Custom_System_WStrCat3(var Dest: WideString; const Source1, Source2: WideString);
+
+  function NewWideString(CharLength: Longint): Pointer;
+  var
+    _NewWideString: function(CharLength: Longint): Pointer;
+  begin
+    asm
+      PUSH   ECX
+      MOV    ECX, offset System.@NewWideString;
+      MOV    _NewWideString, ECX
+      POP    ECX
+    end;
+    Result := _NewWideString(CharLength);
+  end;
+
+  procedure WStrSet(var S: WideString; P: PWideChar);
+  var
+    Temp: Pointer;
+  begin
+    Temp := Pointer(InterlockedExchange(Integer(S), Integer(P)));
+    if Temp <> nil then
+      WideString(Temp) := '';
+  end;
+
+var
+  Source1Len, Source2Len: Integer;
+  NewStr: PWideChar;
+begin
+  Source1Len := Length(Source1);
+  Source2Len := Length(Source2);
+  if (Source1Len <> 0) or (Source2Len <> 0) then
+  begin
+    NewStr := NewWideString(Source1Len + Source2Len);
+    Move(Pointer(Source1)^, Pointer(NewStr)^, Source1Len * sizeof(WideChar));
+    Move(Pointer(Source2)^, NewStr[Source1Len], Source2Len * sizeof(WideChar));
+    WStrSet(Dest, NewStr);
+  end else
+    Dest := '';
+end;
+
+{$ENDIF}
+
+//--------------------------------------------------------------------
+//                System proc replacements
+//--------------------------------------------------------------------
+
+type
+  POverwrittenData = ^TOverwrittenData;
+  TOverwrittenData = record
+    Location: Pointer;
+    OldCode: array[0..6] of Byte;
+  end;
+
+procedure OverwriteProcedure(OldProcedure, NewProcedure: pointer; Data: POverwrittenData = nil);
+{ OverwriteProcedure originally from Igor Siticov }
+{ Modified by Jacques Garcia Vazquez }
+var
+  x: PAnsiChar;
+  y: integer;
+  ov2, ov: cardinal;
+  p: pointer;
+begin
+  if Assigned(Data) and (Data.Location <> nil) then
+    exit; { procedure already overwritten }
+
+  // need six bytes in place of 5
+  x := PAnsiChar(OldProcedure);
+  if not VirtualProtect(Pointer(x), 6, PAGE_EXECUTE_READWRITE, @ov) then
+    RaiseLastOSError;
+
+  // if a jump is present then a redirect is found
+  // $FF25 = jmp dword ptr [xxx]
+  // This redirect is normally present in bpl files, but not in exe files
+  p := OldProcedure;
+
+  if Word(p^) = $25FF then
+  begin
+    Inc(Integer(p), 2); // skip the jump
+    // get the jump address p^ and dereference it p^^
+    p := Pointer(Pointer(p^)^);
+
+    // release the memory
+    if not VirtualProtect(Pointer(x), 6, ov, @ov2) then
+      RaiseLastOSError;
+
+    // re protect the correct one
+    x := PAnsiChar(p);
+    if not VirtualProtect(Pointer(x), 6, PAGE_EXECUTE_READWRITE, @ov) then
+      RaiseLastOSError;
+  end;
+
+  if Assigned(Data) then
+  begin
+    Move(x^, Data.OldCode, 6);
+    { Assign Location last so that Location <> nil only if OldCode is properly initialized. }
+    Data.Location := x;
+  end;
+
+  x[0] := AnsiChar($E9);
+  y := integer(NewProcedure) - integer(p) - 5;
+  x[1] := AnsiChar(y and 255);
+  x[2] := AnsiChar((y shr 8) and 255);
+  x[3] := AnsiChar((y shr 16) and 255);
+  x[4] := AnsiChar((y shr 24) and 255);
+
+  if not VirtualProtect(Pointer(x), 6, ov, @ov2) then
+    RaiseLastOSError;
+end;
+
+procedure RestoreProcedure(OriginalProc: Pointer; Data: TOverwrittenData);
+var
+  ov, ov2: Cardinal;
+begin
+  if Data.Location <> nil then begin
+    if not VirtualProtect(Data.Location, 6, PAGE_EXECUTE_READWRITE, @ov) then
+      RaiseLastOSError;
+    Move(Data.OldCode, Data.Location^, 6);
+    if not VirtualProtect(Data.Location, 6, ov, @ov2) then
+      RaiseLastOSError;
+  end;
+end;
+
+function Addr_System_EndThread: Pointer;
+begin
+  Result := @System.EndThread;
+end;
+
+function Addr_System_LoadResString: Pointer;
+begin
+  Result := @System.LoadResString{TNT-ALLOW LoadResString};
+end;
+
+function Addr_System_WStrFromPCharLen: Pointer;
+asm
+  mov eax, offset System.@WStrFromPCharLen;
+end;
+
+{$IFNDEF COMPILER_9_UP}
+function Addr_System_LStrFromPWCharLen: Pointer;
+asm
+  mov eax, offset System.@LStrFromPWCharLen;
+end;
+
+function Addr_System_WStrToString: Pointer;
+asm
+  mov eax, offset System.@WStrToString;
+end;
+{$ENDIF}
+
+function Addr_System_VarFromLStr: Pointer;
+asm
+  mov eax, offset System.@VarFromLStr;
+end;
+
+function Addr_System_WStrCat3: Pointer;
+asm
+  mov eax, offset System.@WStrCat3;
+end;
+
+var
+  System_EndThread_Code,
+  System_LoadResString_Code,
+  System_WStrFromPCharLen_Code,
+  {$IFNDEF COMPILER_9_UP}
+  System_LStrFromPWCharLen_Code,
+  System_WStrToString_Code,
+  {$ENDIF}
+  System_VarFromLStr_Code
+  {$IFNDEF COMPILER_9_UP}
+  ,
+  System_WStrCat3_Code,
+  SysUtils_WideFmtStr_Code
+  {$ENDIF}
+  : TOverwrittenData;
+
+procedure InstallEndThreadOverride;
+begin
+  OverwriteProcedure(Addr_System_EndThread,  @Custom_System_EndThread,  @System_EndThread_Code);
+end;
+
+procedure InstallStringConversionOverrides;
+begin
+  OverwriteProcedure(Addr_System_WStrFromPCharLen,  @Custom_System_WStrFromPCharLen,  @System_WStrFromPCharLen_Code);
+  {$IFNDEF COMPILER_9_UP}
+  OverwriteProcedure(Addr_System_LStrFromPWCharLen, @Custom_System_LStrFromPWCharLen, @System_LStrFromPWCharLen_Code);
+  OverwriteProcedure(Addr_System_WStrToString,      @Custom_System_WStrToString,      @System_WStrToString_Code);
+  {$ENDIF}
+end;
+
+procedure InstallWideResourceStrings;
+begin
+  OverwriteProcedure(Addr_System_LoadResString,     @Custom_System_LoadResString,     @System_LoadResString_Code);
+  OverwriteProcedure(Addr_System_VarFromLStr,       @Custom_System_VarFromLStr,       @System_VarFromLStr_Code);
+end;
+
+{$IFNDEF COMPILER_9_UP}
+procedure InstallWideStringConcatenationFix;
+begin
+  OverwriteProcedure(Addr_System_WStrCat3,          @Custom_System_WStrCat3,          @System_WStrCat3_Code);
+end;
+
+procedure InstallWideFormatFixes;
+begin
+  OverwriteProcedure(@SysUtils.WideFmtStr, @TntSysUtils.Tnt_WideFmtStr, @SysUtils_WideFmtStr_Code);
+end;
+{$ENDIF}
+
+procedure InstallTntSystemUpdates(Updates: TTntSystemUpdateSet = AllTntSystemUpdates);
+begin
+  InstallEndThreadOverride;
+  if tsWideResourceStrings in Updates then begin
+    InstallStringConversionOverrides;
+    InstallWideResourceStrings;
+  end;
+  {$IFNDEF COMPILER_9_UP}
+    if tsFixImplicitCodePage in Updates then begin
+      InstallStringConversionOverrides;
+      { CP_ACP is the code page used by the non-Unicode Windows API. }
+      GDefaultSystemCodePage := CP_ACP{TNT-ALLOW CP_ACP};
+    end;
+    if tsFixWideStrConcat in Updates then begin
+      InstallWideStringConcatenationFix;
+    end;
+    if tsFixWideFormat in Updates then begin
+      InstallWideFormatFixes;
+    end;
+  {$ENDIF}
+end;
+
+{$IFNDEF COMPILER_9_UP}
+var
+  StartupDefaultUserCodePage: Cardinal;
+{$ENDIF}
+
+procedure UninstallSystemOverrides;
+begin
+  RestoreProcedure(Addr_System_EndThread,  System_EndThread_Code);
+  // String Conversion
+  RestoreProcedure(Addr_System_WStrFromPCharLen,  System_WStrFromPCharLen_Code);
+  {$IFNDEF COMPILER_9_UP}
+  RestoreProcedure(Addr_System_LStrFromPWCharLen, System_LStrFromPWCharLen_Code);
+  RestoreProcedure(Addr_System_WStrToString,      System_WStrToString_Code);
+  GDefaultSystemCodePage := StartupDefaultUserCodePage;
+  {$ENDIF}
+  // Wide resourcestring
+  RestoreProcedure(Addr_System_LoadResString,     System_LoadResString_Code);
+  RestoreProcedure(Addr_System_VarFromLStr,       System_VarFromLStr_Code);
+  {$IFNDEF COMPILER_9_UP}
+  // WideString concat fix
+  RestoreProcedure(Addr_System_WStrCat3,          System_WStrCat3_Code);
+  // WideFormat fixes
+  RestoreProcedure(@SysUtils.WideFmtStr, SysUtils_WideFmtStr_Code);
+  {$ENDIF}
+end;
+
+{$ENDIF USE_SYSTEM_OVERRIDES}
+
+initialization
+  {$IFDEF COMPILER_9_UP}
+    {$DEFINE USE_GETACP}
+  {$ENDIF}
+  {$IFDEF FPC}
+    {$DEFINE USE_GETACP}
+  {$ENDIF}
+  {$IFDEF USE_GETACP}
+  GDefaultSystemCodePage := GetACP;
+  {$ELSE}
+    {$IFDEF COMPILER_7_UP}
+    if (Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion >= 5) then
+      GDefaultSystemCodePage := CP_THREAD_ACP // Win 2K/XP/...
+    else
+      GDefaultSystemCodePage := LCIDToCodePage(GetThreadLocale); // Win NT4/95/98/ME
+    {$ELSE}
+    GDefaultSystemCodePage := CP_ACP{TNT-ALLOW CP_ACP};
+    {$ENDIF}
+  {$ENDIF}
+  {$IFDEF USE_SYSTEM_OVERRIDES}
+  {$IFNDEF COMPILER_9_UP}
+  StartupDefaultUserCodePage := DefaultSystemCodePage;
+  {$ENDIF}
+  IsDebugging := DebugHook > 0;
+  {$ENDIF USE_SYSTEM_OVERRIDES}
+
+finalization
+  {$IFDEF USE_SYSTEM_OVERRIDES}
+  UninstallSystemOverrides;
+  FreeTntSystemThreadVars; { Make MemorySleuth happy. }
+  {$ENDIF USE_SYSTEM_OVERRIDES}
+
+end.
diff --git a/songmanagement/src/lib/TntUnicodeControls/TntWideStrUtils.pas b/songmanagement/src/lib/TntUnicodeControls/TntWideStrUtils.pas
new file mode 100644
index 00000000..99f63aea
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/TntWideStrUtils.pas
@@ -0,0 +1,455 @@
+
+{*****************************************************************************}
+{                                                                             }
+{    Tnt Delphi Unicode Controls                                              }
+{      http://www.tntware.com/delphicontrols/unicode/                         }
+{        Version: 2.3.0                                                       }
+{                                                                             }
+{    Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com)       }
+{                                                                             }
+{*****************************************************************************}
+
+unit TntWideStrUtils;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$INCLUDE TntCompilers.inc}
+
+interface
+
+{ Wide string manipulation functions }
+
+{$IFNDEF COMPILER_9_UP}
+function WStrAlloc(Size: Cardinal): PWideChar;
+function WStrBufSize(const Str: PWideChar): Cardinal;
+{$ENDIF}
+{$IFNDEF COMPILER_10_UP}
+function WStrMove(Dest: PWideChar; const Source: PWideChar; Count: Cardinal): PWideChar;
+{$ENDIF}
+{$IFNDEF COMPILER_9_UP}
+function WStrNew(const Str: PWideChar): PWideChar;
+procedure WStrDispose(Str: PWideChar);
+{$ENDIF}
+//---------------------------------------------------------------------------------------------
+{$IFNDEF COMPILER_9_UP}
+function WStrLen(Str: PWideChar): Cardinal;
+function WStrEnd(Str: PWideChar): PWideChar;
+{$ENDIF}
+{$IFNDEF COMPILER_10_UP}
+function WStrCat(Dest: PWideChar; const Source: PWideChar): PWideChar;
+{$ENDIF}
+{$IFNDEF COMPILER_9_UP}
+function WStrCopy(Dest, Source: PWideChar): PWideChar;
+function WStrLCopy(Dest, Source: PWideChar; MaxLen: Cardinal): PWideChar;
+function WStrPCopy(Dest: PWideChar; const Source: WideString): PWideChar;
+function WStrPLCopy(Dest: PWideChar; const Source: WideString; MaxLen: Cardinal): PWideChar;
+{$ENDIF}
+{$IFNDEF COMPILER_10_UP}
+function WStrScan(const Str: PWideChar; Chr: WideChar): PWideChar;
+// WStrComp and WStrPos were introduced as broken in Delphi 2006, but fixed in Delphi 2006 Update 2
+function WStrComp(Str1, Str2: PWideChar): Integer;
+function WStrPos(Str, SubStr: PWideChar): PWideChar;
+{$ENDIF}
+function Tnt_WStrComp(Str1, Str2: PWideChar): Integer; deprecated;
+function Tnt_WStrPos(Str, SubStr: PWideChar): PWideChar; deprecated;
+
+{ ------------ introduced --------------- }
+function WStrECopy(Dest, Source: PWideChar): PWideChar;
+function WStrLComp(Str1, Str2: PWideChar; MaxLen: Cardinal): Integer;
+function WStrLIComp(Str1, Str2: PWideChar; MaxLen: Cardinal): Integer;
+function WStrIComp(Str1, Str2: PWideChar): Integer;
+function WStrLower(Str: PWideChar): PWideChar;
+function WStrUpper(Str: PWideChar): PWideChar;
+function WStrRScan(const Str: PWideChar; Chr: WideChar): PWideChar;
+function WStrLCat(Dest: PWideChar; const Source: PWideChar; MaxLen: Cardinal): PWideChar;
+function WStrPas(const Str: PWideChar): WideString;
+
+{ SysUtils.pas } //-------------------------------------------------------------------------
+
+{$IFNDEF COMPILER_10_UP}
+function WideLastChar(const S: WideString): PWideChar;
+function WideQuotedStr(const S: WideString; Quote: WideChar): WideString;
+{$ENDIF}
+{$IFNDEF COMPILER_9_UP}
+function WideExtractQuotedStr(var Src: PWideChar; Quote: WideChar): Widestring;
+{$ENDIF}
+{$IFNDEF COMPILER_10_UP}
+function WideDequotedStr(const S: WideString; AQuote: WideChar): WideString;
+{$ENDIF}
+
+implementation
+
+uses
+  {$IFDEF COMPILER_9_UP} WideStrUtils, {$ENDIF} Math, Windows, TntWindows;
+
+{$IFNDEF COMPILER_9_UP}
+function WStrAlloc(Size: Cardinal): PWideChar;
+begin
+  Size := SizeOf(Cardinal) + (Size * SizeOf(WideChar));
+  GetMem(Result, Size);
+  PCardinal(Result)^ := Size;
+  Inc(PAnsiChar(Result), SizeOf(Cardinal));
+end;
+
+function WStrBufSize(const Str: PWideChar): Cardinal;
+var
+  P: PWideChar;
+begin
+  P := Str;
+  Dec(PAnsiChar(P), SizeOf(Cardinal));
+  Result := PCardinal(P)^ - SizeOf(Cardinal);
+  Result := Result div SizeOf(WideChar);
+end;
+{$ENDIF}
+
+{$IFNDEF COMPILER_10_UP}
+function WStrMove(Dest: PWideChar; const Source: PWideChar; Count: Cardinal): PWideChar;
+var
+  Length: Integer;
+begin
+  Result := Dest;
+  Length := Count * SizeOf(WideChar);
+  Move(Source^, Dest^, Length);
+end;
+{$ENDIF}
+
+{$IFNDEF COMPILER_9_UP}
+function WStrNew(const Str: PWideChar): PWideChar;
+var
+  Size: Cardinal;
+begin
+  if Str = nil then Result := nil else
+  begin
+    Size := WStrLen(Str) + 1;
+    Result := WStrMove(WStrAlloc(Size), Str, Size);
+  end;
+end;
+
+procedure WStrDispose(Str: PWideChar);
+begin
+  if Str <> nil then
+  begin
+    Dec(PAnsiChar(Str), SizeOf(Cardinal));
+    FreeMem(Str, Cardinal(Pointer(Str)^));
+  end;
+end;
+{$ENDIF}
+
+//---------------------------------------------------------------------------------------------
+
+{$IFNDEF COMPILER_9_UP}
+function WStrLen(Str: PWideChar): Cardinal;
+begin
+  Result := WStrEnd(Str) - Str;
+end;
+
+function WStrEnd(Str: PWideChar): PWideChar;
+begin
+  // returns a pointer to the end of a null terminated string
+  Result := Str;
+  While Result^ <> #0 do
+    Inc(Result);
+end;
+{$ENDIF}
+
+{$IFNDEF COMPILER_10_UP}
+function WStrCat(Dest: PWideChar; const Source: PWideChar): PWideChar;
+begin
+  Result := Dest;
+  WStrCopy(WStrEnd(Dest), Source);
+end;
+{$ENDIF}
+
+{$IFNDEF COMPILER_9_UP}
+function WStrCopy(Dest, Source: PWideChar): PWideChar;
+begin
+  Result := WStrLCopy(Dest, Source, MaxInt);
+end;
+
+function WStrLCopy(Dest, Source: PWideChar; MaxLen: Cardinal): PWideChar;
+var
+  Count: Cardinal;
+begin
+  // copies a specified maximum number of characters from Source to Dest
+  Result := Dest;
+  Count := 0;
+  While (Count < MaxLen) and (Source^ <> #0) do begin
+    Dest^ := Source^;
+    Inc(Source);
+    Inc(Dest);
+    Inc(Count);
+  end;
+  Dest^ := #0;
+end;
+
+function WStrPCopy(Dest: PWideChar; const Source: WideString): PWideChar;
+begin
+  Result := WStrLCopy(Dest, PWideChar(Source), Length(Source));
+end;
+
+function WStrPLCopy(Dest: PWideChar; const Source: WideString; MaxLen: Cardinal): PWideChar;
+begin
+  Result := WStrLCopy(Dest, PWideChar(Source), MaxLen);
+end;
+{$ENDIF}
+
+{$IFNDEF COMPILER_10_UP}
+function WStrScan(const Str: PWideChar; Chr: WideChar): PWideChar;
+begin
+  Result := Str;
+  while Result^ <> Chr do
+  begin
+    if Result^ = #0 then
+    begin
+      Result := nil;
+      Exit;
+    end;
+    Inc(Result);
+  end;
+end;
+
+function WStrComp(Str1, Str2: PWideChar): Integer;
+begin
+  Result := WStrLComp(Str1, Str2, MaxInt);
+end;
+
+function WStrPos(Str, SubStr: PWideChar): PWideChar;
+var
+  PSave: PWideChar;
+  P: PWideChar;
+  PSub: PWideChar;
+begin
+  // returns a pointer to the first occurance of SubStr in Str
+  Result := nil;
+  if (Str <> nil) and (Str^ <> #0) and (SubStr <> nil) and (SubStr^ <> #0) then begin
+    P := Str;
+    While P^ <> #0 do begin
+      if P^ = SubStr^ then begin
+        // investigate possibility here
+        PSave := P;
+        PSub := SubStr;
+        While (P^ = PSub^) do begin
+          Inc(P);
+          Inc(PSub);
+          if (PSub^ = #0) then begin
+            Result := PSave;
+            exit; // found a match
+          end;
+          if (P^ = #0) then
+            exit; // no match, hit end of string
+        end;
+        P := PSave;
+      end;
+      Inc(P);
+    end;
+  end;
+end;
+{$ENDIF}
+
+function Tnt_WStrComp(Str1, Str2: PWideChar): Integer; deprecated;
+begin
+  Result := WStrComp(Str1, Str2);
+end;
+
+function Tnt_WStrPos(Str, SubStr: PWideChar): PWideChar; deprecated;
+begin
+  Result := WStrPos(Str, SubStr);
+end;
+
+//------------------------------------------------------------------------------
+
+function WStrECopy(Dest, Source: PWideChar): PWideChar;
+begin
+  Result := WStrEnd(WStrCopy(Dest, Source));
+end;
+
+function WStrComp_EX(Str1, Str2: PWideChar; MaxLen: Cardinal; dwCmpFlags: Cardinal): Integer;
+var
+  Len1, Len2: Integer;
+begin
+  if MaxLen = Cardinal(MaxInt) then begin
+    Len1 := -1;
+    Len2 := -1;
+  end else begin
+    Len1 := Min(WStrLen(Str1), MaxLen);
+    Len2 := Min(WStrLen(Str2), MaxLen);
+  end;
+  Result := Tnt_CompareStringW(GetThreadLocale, dwCmpFlags, Str1, Len1, Str2, Len2) - 2;
+end;
+
+function WStrLComp(Str1, Str2: PWideChar; MaxLen: Cardinal): Integer;
+begin
+  Result := WStrComp_EX(Str1, Str2, MaxLen, 0);
+end;
+
+function WStrLIComp(Str1, Str2: PWideChar; MaxLen: Cardinal): Integer;
+begin
+  Result := WStrComp_EX(Str1, Str2, MaxLen, NORM_IGNORECASE);
+end;
+
+function WStrIComp(Str1, Str2: PWideChar): Integer;
+begin
+  Result := WStrLIComp(Str1, Str2, MaxInt);
+end;
+
+function WStrLower(Str: PWideChar): PWideChar;
+begin
+  Result := Str;
+  Tnt_CharLowerBuffW(Str, WStrLen(Str))
+end;
+
+function WStrUpper(Str: PWideChar): PWideChar;
+begin
+  Result := Str;
+  Tnt_CharUpperBuffW(Str, WStrLen(Str))
+end;
+
+function WStrRScan(const Str: PWideChar; Chr: WideChar): PWideChar;
+var
+  MostRecentFound: PWideChar;
+begin
+  if Chr = #0 then
+    Result := WStrEnd(Str)
+  else
+  begin
+    Result := nil;
+    MostRecentFound := Str;
+    while True do
+    begin
+      while MostRecentFound^ <> Chr do
+      begin
+        if MostRecentFound^ = #0 then
+          Exit;
+        Inc(MostRecentFound);
+      end;
+      Result := MostRecentFound;
+      Inc(MostRecentFound);
+    end;
+  end;
+end;
+
+function WStrLCat(Dest: PWideChar; const Source: PWideChar; MaxLen: Cardinal): PWideChar;
+begin
+  Result := Dest;
+  WStrLCopy(WStrEnd(Dest), Source, MaxLen - WStrLen(Dest));
+end;
+
+function WStrPas(const Str: PWideChar): WideString;
+begin
+  Result := Str;
+end;
+
+//---------------------------------------------------------------------------------------------
+
+{$IFNDEF COMPILER_10_UP}
+function WideLastChar(const S: WideString): PWideChar;
+begin
+  if S = '' then
+    Result := nil
+  else
+    Result := @S[Length(S)];
+end;
+
+function WideQuotedStr(const S: WideString; Quote: WideChar): WideString;
+var
+  P, Src,
+  Dest: PWideChar;
+  AddCount: Integer;
+begin
+  AddCount := 0;
+  P := WStrScan(PWideChar(S), Quote);
+  while (P <> nil) do
+  begin
+    Inc(P);
+    Inc(AddCount);
+    P := WStrScan(P, Quote);
+  end;
+
+  if AddCount = 0 then
+    Result := Quote + S + Quote
+  else
+  begin
+    SetLength(Result, Length(S) + AddCount + 2);
+    Dest := PWideChar(Result);
+    Dest^ := Quote;
+    Inc(Dest);
+    Src := PWideChar(S);
+    P := WStrScan(Src, Quote);
+    repeat
+      Inc(P);
+      Move(Src^, Dest^, 2 * (P - Src));
+      Inc(Dest, P - Src);
+      Dest^ := Quote;
+      Inc(Dest);
+      Src := P;
+      P := WStrScan(Src, Quote);
+    until P = nil;
+    P := WStrEnd(Src);
+    Move(Src^, Dest^, 2 * (P - Src));
+    Inc(Dest, P - Src);
+    Dest^ := Quote;
+  end;
+end;
+{$ENDIF}
+
+{$IFNDEF COMPILER_9_UP}
+function WideExtractQuotedStr(var Src: PWideChar; Quote: WideChar): Widestring;
+var
+  P, Dest: PWideChar;
+  DropCount: Integer;
+begin
+  Result := '';
+  if (Src = nil) or (Src^ <> Quote) then Exit;
+  Inc(Src);
+  DropCount := 1;
+  P := Src;
+  Src := WStrScan(Src, Quote);
+  while Src <> nil do   // count adjacent pairs of quote chars
+  begin
+    Inc(Src);
+    if Src^ <> Quote then Break;
+    Inc(Src);
+    Inc(DropCount);
+    Src := WStrScan(Src, Quote);
+  end;
+  if Src = nil then Src := WStrEnd(P);
+  if ((Src - P) <= 1) then Exit;
+  if DropCount = 1 then
+    SetString(Result, P, Src - P - 1)
+  else
+  begin
+    SetLength(Result, Src - P - DropCount);
+    Dest := PWideChar(Result);
+    Src := WStrScan(P, Quote);
+    while Src <> nil do
+    begin
+      Inc(Src);
+      if Src^ <> Quote then Break;
+      Move(P^, Dest^, (Src - P) * SizeOf(WideChar));
+      Inc(Dest, Src - P);
+      Inc(Src);
+      P := Src;
+      Src := WStrScan(Src, Quote);
+    end;
+    if Src = nil then Src := WStrEnd(P);
+    Move(P^, Dest^, (Src - P - 1) * SizeOf(WideChar));
+  end;
+end;
+{$ENDIF}
+
+{$IFNDEF COMPILER_10_UP}
+function WideDequotedStr(const S: WideString; AQuote: WideChar): WideString;
+var
+  LText : PWideChar;
+begin
+  LText := PWideChar(S);
+  Result := WideExtractQuotedStr(LText, AQuote);
+  if Result = '' then
+    Result := S;
+end;
+{$ENDIF}
+
+
+end.
diff --git a/songmanagement/src/lib/TntUnicodeControls/TntWideStrings.pas b/songmanagement/src/lib/TntUnicodeControls/TntWideStrings.pas
new file mode 100644
index 00000000..75132d22
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/TntWideStrings.pas
@@ -0,0 +1,846 @@
+
+{*****************************************************************************}
+{                                                                             }
+{    Tnt Delphi Unicode Controls                                              }
+{      http://www.tntware.com/delphicontrols/unicode/                         }
+{        Version: 2.3.0                                                       }
+{                                                                             }
+{    Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com)       }
+{                                                                             }
+{*****************************************************************************}
+
+unit TntWideStrings;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$INCLUDE TntCompilers.inc}
+
+interface
+
+{$IFDEF COMPILER_10_UP}
+  {$MESSAGE FATAL 'Do not refer to TntWideStrings.pas.  It works correctly in Delphi 2006.'}
+{$ENDIF}
+
+uses
+  Classes;
+
+{******************************************************************************}
+{                                                                              }
+{  Delphi 2005 introduced TWideStrings in WideStrings.pas.                     }
+{    Unfortunately, it was not ready for prime time.                           }
+{      Setting CommaText is not consistent, and it relies on CharNextW         }
+{         Which is only available on Windows NT+.                              }
+{                                                                              }
+{******************************************************************************}
+
+type
+  TWideStrings = class;
+
+{ IWideStringsAdapter interface }
+{ Maintains link between TWideStrings and IWideStrings implementations }
+
+  IWideStringsAdapter = interface
+    ['{25FE0E3B-66CB-48AA-B23B-BCFA67E8F5DA}']
+    procedure ReferenceStrings(S: TWideStrings);
+    procedure ReleaseStrings;
+  end;
+
+  TWideStringsEnumerator = class
+  private
+    FIndex: Integer;
+    FStrings: TWideStrings;
+  public
+    constructor Create(AStrings: TWideStrings);
+    function GetCurrent: WideString;
+    function MoveNext: Boolean;
+    property Current: WideString read GetCurrent;
+  end;
+
+{$IFDEF FPC}
+  TStringsDefined = set of (
+    sdDelimiter, sdQuoteChar, sdNameValueSeparator, sdLineBreak,
+    sdStrictDelimiter);
+{$ENDIF}
+
+{$DEFINE NAMEVALUESEPARATOR_RW}
+{$IFNDEF COMPILER_7_UP}
+  {$UNDEF NAMEVALUESEPARATOR_RW}
+{$ENDIF}
+
+{ TWideStrings class }
+
+  TWideStrings = class(TPersistent)
+  private
+    FDefined: TStringsDefined;
+    FDelimiter: WideChar;
+    FQuoteChar: WideChar;
+    {$IFDEF NAMEVALUESEPARATOR_RW}
+    FNameValueSeparator: WideChar;
+    {$ENDIF}
+    FUpdateCount: Integer;
+    FAdapter: IWideStringsAdapter;
+    function GetCommaText: WideString;
+    function GetDelimitedText: WideString;
+    function GetName(Index: Integer): WideString;
+    function GetValue(const Name: WideString): WideString;
+    procedure ReadData(Reader: TReader);
+    procedure SetCommaText(const Value: WideString);
+    procedure SetDelimitedText(const Value: WideString);
+    procedure SetStringsAdapter(const Value: IWideStringsAdapter);
+    procedure SetValue(const Name, Value: WideString);
+    procedure WriteData(Writer: TWriter);
+    function GetDelimiter: WideChar;
+    procedure SetDelimiter(const Value: WideChar);
+    function GetQuoteChar: WideChar;
+    procedure SetQuoteChar(const Value: WideChar);
+    function GetNameValueSeparator: WideChar;
+    {$IFDEF NAMEVALUESEPARATOR_RW}
+    procedure SetNameValueSeparator(const Value: WideChar);
+    {$ENDIF}
+    function GetValueFromIndex(Index: Integer): WideString;
+    procedure SetValueFromIndex(Index: Integer; const Value: WideString);
+  protected
+    procedure AssignTo(Dest: TPersistent); override;
+    procedure DefineProperties(Filer: TFiler); override;
+    procedure Error(const Msg: WideString; Data: Integer); overload;
+    procedure Error(Msg: PResStringRec; Data: Integer); overload;
+    function ExtractName(const S: WideString): WideString;
+    function Get(Index: Integer): WideString; virtual; abstract;
+    function GetCapacity: Integer; virtual;
+    function GetCount: Integer; virtual; abstract;
+    function GetObject(Index: Integer): TObject; virtual;
+    function GetTextStr: WideString; virtual;
+    procedure Put(Index: Integer; const S: WideString); virtual;
+    procedure PutObject(Index: Integer; AObject: TObject); virtual;
+    procedure SetCapacity(NewCapacity: Integer); virtual;
+    procedure SetTextStr(const Value: WideString); virtual;
+    procedure SetUpdateState(Updating: Boolean); virtual;
+    property UpdateCount: Integer read FUpdateCount;
+    function CompareStrings(const S1, S2: WideString): Integer; virtual;
+  public
+    destructor Destroy; override;
+    function Add(const S: WideString): Integer; virtual;
+    function AddObject(const S: WideString; AObject: TObject): Integer; virtual;
+    procedure Append(const S: WideString);
+    procedure AddStrings(Strings: TStrings{TNT-ALLOW TStrings}); overload; virtual;
+    procedure AddStrings(Strings: TWideStrings); overload; virtual;
+    procedure Assign(Source: TPersistent); override;
+    procedure BeginUpdate;
+    procedure Clear; virtual; abstract;
+    procedure Delete(Index: Integer); virtual; abstract;
+    procedure EndUpdate;
+    function Equals(Strings: TWideStrings): Boolean;
+    procedure Exchange(Index1, Index2: Integer); virtual;
+    function GetEnumerator: TWideStringsEnumerator;
+    function GetTextW: PWideChar; virtual;
+    function IndexOf(const S: WideString): Integer; virtual;
+    function IndexOfName(const Name: WideString): Integer; virtual;
+    function IndexOfObject(AObject: TObject): Integer; virtual;
+    procedure Insert(Index: Integer; const S: WideString); virtual; abstract;
+    procedure InsertObject(Index: Integer; const S: WideString;
+      AObject: TObject); virtual;
+    procedure LoadFromFile(const FileName: WideString); virtual;
+    procedure LoadFromStream(Stream: TStream); virtual;
+    procedure Move(CurIndex, NewIndex: Integer); virtual;
+    procedure SaveToFile(const FileName: WideString); virtual;
+    procedure SaveToStream(Stream: TStream); virtual;
+    procedure SetTextW(const Text: PWideChar); virtual;
+    property Capacity: Integer read GetCapacity write SetCapacity;
+    property CommaText: WideString read GetCommaText write SetCommaText;
+    property Count: Integer read GetCount;
+    property Delimiter: WideChar read GetDelimiter write SetDelimiter;
+    property DelimitedText: WideString read GetDelimitedText write SetDelimitedText;
+    property Names[Index: Integer]: WideString read GetName;
+    property Objects[Index: Integer]: TObject read GetObject write PutObject;
+    property QuoteChar: WideChar read GetQuoteChar write SetQuoteChar;
+    property Values[const Name: WideString]: WideString read GetValue write SetValue;
+    property ValueFromIndex[Index: Integer]: WideString read GetValueFromIndex write SetValueFromIndex;
+    property NameValueSeparator: WideChar read GetNameValueSeparator {$IFDEF NAMEVALUESEPARATOR_RW} write SetNameValueSeparator {$ENDIF};
+    property Strings[Index: Integer]: WideString read Get write Put; default;
+    property Text: WideString read GetTextStr write SetTextStr;
+    property StringsAdapter: IWideStringsAdapter read FAdapter write SetStringsAdapter;
+  end;
+
+  PWideStringItem = ^TWideStringItem;
+  TWideStringItem = record
+    FString: WideString;
+    FObject: TObject;
+  end;
+
+  PWideStringItemList = ^TWideStringItemList;
+  TWideStringItemList = array[0..MaxListSize] of TWideStringItem;
+
+implementation
+
+uses
+  Windows, SysUtils, TntSystem, {$IFDEF COMPILER_9_UP} WideStrUtils, {$ELSE} TntWideStrUtils, {$ENDIF}
+  TntSysUtils, TntClasses;
+
+{ TWideStringsEnumerator }
+
+constructor TWideStringsEnumerator.Create(AStrings: TWideStrings);
+begin
+  inherited Create;
+  FIndex := -1;
+  FStrings := AStrings;
+end;
+
+function TWideStringsEnumerator.GetCurrent: WideString;
+begin
+  Result := FStrings[FIndex];
+end;
+
+function TWideStringsEnumerator.MoveNext: Boolean;
+begin
+  Result := FIndex < FStrings.Count - 1;
+  if Result then
+    Inc(FIndex);
+end;
+
+{ TWideStrings }
+
+destructor TWideStrings.Destroy;
+begin
+  StringsAdapter := nil;
+  inherited;
+end;
+
+function TWideStrings.Add(const S: WideString): Integer;
+begin
+  Result := GetCount;
+  Insert(Result, S);
+end;
+
+function TWideStrings.AddObject(const S: WideString; AObject: TObject): Integer;
+begin
+  Result := Add(S);
+  PutObject(Result, AObject);
+end;
+
+procedure TWideStrings.Append(const S: WideString);
+begin
+  Add(S);
+end;
+
+procedure TWideStrings.AddStrings(Strings: TStrings{TNT-ALLOW TStrings});
+var
+  I: Integer;
+begin
+  BeginUpdate;
+  try
+    for I := 0 to Strings.Count - 1 do
+      AddObject(Strings[I], Strings.Objects[I]);
+  finally
+    EndUpdate;
+  end;
+end;
+
+procedure TWideStrings.AddStrings(Strings: TWideStrings);
+var
+  I: Integer;
+begin
+  BeginUpdate;
+  try
+    for I := 0 to Strings.Count - 1 do
+      AddObject(Strings[I], Strings.Objects[I]);
+  finally
+    EndUpdate;
+  end;
+end;
+
+procedure TWideStrings.Assign(Source: TPersistent);
+begin
+  if Source is TWideStrings then
+  begin
+    BeginUpdate;
+    try
+      Clear;
+      FDefined := TWideStrings(Source).FDefined;
+      {$IFDEF NAMEVALUESEPARATOR_RW}
+      FNameValueSeparator := TWideStrings(Source).FNameValueSeparator;
+      {$ENDIF}
+      FQuoteChar := TWideStrings(Source).FQuoteChar;
+      FDelimiter := TWideStrings(Source).FDelimiter;
+      AddStrings(TWideStrings(Source));
+    finally
+      EndUpdate;
+    end;
+  end
+  else if Source is TStrings{TNT-ALLOW TStrings} then
+  begin
+    BeginUpdate;
+    try
+      Clear;
+      {$IFDEF NAMEVALUESEPARATOR_RW}
+      FNameValueSeparator := WideChar(TStrings{TNT-ALLOW TStrings}(Source).NameValueSeparator);
+      {$ENDIF}
+      FQuoteChar := WideChar(TStrings{TNT-ALLOW TStrings}(Source).QuoteChar);
+      FDelimiter := WideChar(TStrings{TNT-ALLOW TStrings}(Source).Delimiter);
+      AddStrings(TStrings{TNT-ALLOW TStrings}(Source));
+    finally
+      EndUpdate;
+    end;
+  end
+  else
+    inherited Assign(Source);
+end;
+
+procedure TWideStrings.AssignTo(Dest: TPersistent);
+var
+  I: Integer;
+begin
+  if Dest is TWideStrings then Dest.Assign(Self)
+  else if Dest is TStrings{TNT-ALLOW TStrings} then
+  begin
+    TStrings{TNT-ALLOW TStrings}(Dest).BeginUpdate;
+    try
+      TStrings{TNT-ALLOW TStrings}(Dest).Clear;
+      {$IFDEF NAMEVALUESEPARATOR_RW}
+      TStrings{TNT-ALLOW TStrings}(Dest).NameValueSeparator := AnsiChar(NameValueSeparator);
+      {$ENDIF}
+      TStrings{TNT-ALLOW TStrings}(Dest).QuoteChar := AnsiChar(QuoteChar);
+      TStrings{TNT-ALLOW TStrings}(Dest).Delimiter := AnsiChar(Delimiter);
+      for I := 0 to Count - 1 do
+        TStrings{TNT-ALLOW TStrings}(Dest).AddObject(Strings[I], Objects[I]);
+    finally
+      TStrings{TNT-ALLOW TStrings}(Dest).EndUpdate;
+    end;
+  end
+  else
+    inherited AssignTo(Dest);
+end;
+
+procedure TWideStrings.BeginUpdate;
+begin
+  if FUpdateCount = 0 then SetUpdateState(True);
+  Inc(FUpdateCount);
+end;
+
+procedure TWideStrings.DefineProperties(Filer: TFiler);
+
+  function DoWrite: Boolean;
+  begin
+    if Filer.Ancestor <> nil then
+    begin
+      Result := True;
+      if Filer.Ancestor is TWideStrings then
+        Result := not Equals(TWideStrings(Filer.Ancestor))
+    end
+    else Result := Count > 0;
+  end;
+
+begin
+  Filer.DefineProperty('Strings', ReadData, WriteData, DoWrite);
+end;
+
+procedure TWideStrings.EndUpdate;
+begin
+  Dec(FUpdateCount);
+  if FUpdateCount = 0 then SetUpdateState(False);
+end;
+
+function TWideStrings.Equals(Strings: TWideStrings): Boolean;
+var
+  I, Count: Integer;
+begin
+  Result := False;
+  Count := GetCount;
+  if Count <> Strings.GetCount then Exit;
+  for I := 0 to Count - 1 do if Get(I) <> Strings.Get(I) then Exit;
+  Result := True;
+end;
+
+procedure TWideStrings.Error(const Msg: WideString; Data: Integer);
+
+  function ReturnAddr: Pointer;
+  asm
+          MOV     EAX,[EBP+4]
+  end;
+
+begin
+  raise EStringListError.CreateFmt(Msg, [Data]) at ReturnAddr;
+end;
+
+procedure TWideStrings.Error(Msg: PResStringRec; Data: Integer);
+begin
+  Error(WideLoadResString(Msg), Data);
+end;
+
+procedure TWideStrings.Exchange(Index1, Index2: Integer);
+var
+  TempObject: TObject;
+  TempString: WideString;
+begin
+  BeginUpdate;
+  try
+    TempString := Strings[Index1];
+    TempObject := Objects[Index1];
+    Strings[Index1] := Strings[Index2];
+    Objects[Index1] := Objects[Index2];
+    Strings[Index2] := TempString;
+    Objects[Index2] := TempObject;
+  finally
+    EndUpdate;
+  end;
+end;
+
+function TWideStrings.ExtractName(const S: WideString): WideString;
+var
+  P: Integer;
+begin
+  Result := S;
+  P := Pos(NameValueSeparator, Result);
+  if P <> 0 then
+    SetLength(Result, P-1) else
+    SetLength(Result, 0);
+end;
+
+function TWideStrings.GetCapacity: Integer;
+begin  // descendents may optionally override/replace this default implementation
+  Result := Count;
+end;
+
+function TWideStrings.GetCommaText: WideString;
+var
+  LOldDefined: TStringsDefined;
+  LOldDelimiter: WideChar;
+  LOldQuoteChar: WideChar;
+begin
+  LOldDefined := FDefined;
+  LOldDelimiter := FDelimiter;
+  LOldQuoteChar := FQuoteChar;
+  Delimiter := ',';
+  QuoteChar := '"';
+  try
+    Result := GetDelimitedText;
+  finally
+    FDelimiter := LOldDelimiter;
+    FQuoteChar := LOldQuoteChar;
+    FDefined := LOldDefined;
+  end;
+end;
+
+function TWideStrings.GetDelimitedText: WideString;
+var
+  S: WideString;
+  P: PWideChar;
+  I, Count: Integer;
+begin
+  Count := GetCount;
+  if (Count = 1) and (Get(0) = '') then
+    Result := WideString(QuoteChar) + QuoteChar
+  else
+  begin
+    Result := '';
+    for I := 0 to Count - 1 do
+    begin
+      S := Get(I);
+      P := PWideChar(S);
+      while not ((P^ in [WideChar(#0)..WideChar(' ')]) or (P^ = QuoteChar) or (P^ = Delimiter)) do
+        Inc(P);
+      if (P^ <> #0) then S := WideQuotedStr(S, QuoteChar);
+      Result := Result + S + Delimiter;
+    end;
+    System.Delete(Result, Length(Result), 1);
+  end;
+end;
+
+function TWideStrings.GetName(Index: Integer): WideString;
+begin
+  Result := ExtractName(Get(Index));
+end;
+
+function TWideStrings.GetObject(Index: Integer): TObject;
+begin
+  Result := nil;
+end;
+
+function TWideStrings.GetEnumerator: TWideStringsEnumerator;
+begin
+  Result := TWideStringsEnumerator.Create(Self);
+end;
+
+function TWideStrings.GetTextW: PWideChar;
+begin
+  Result := WStrNew(PWideChar(GetTextStr));
+end;
+
+function TWideStrings.GetTextStr: WideString;
+var
+  I, L, Size, Count: Integer;
+  P: PWideChar;
+  S, LB: WideString;
+begin
+  Count := GetCount;
+  Size := 0;
+  LB := sLineBreak;
+  for I := 0 to Count - 1 do Inc(Size, Length(Get(I)) + Length(LB));
+  SetString(Result, nil, Size);
+  P := Pointer(Result);
+  for I := 0 to Count - 1 do
+  begin
+    S := Get(I);
+    L := Length(S);
+    if L <> 0 then
+    begin
+      System.Move(Pointer(S)^, P^, L * SizeOf(WideChar));
+      Inc(P, L);
+    end;
+    L := Length(LB);
+    if L <> 0 then
+    begin
+      System.Move(Pointer(LB)^, P^, L * SizeOf(WideChar));
+      Inc(P, L);
+    end;
+  end;
+end;
+
+function TWideStrings.GetValue(const Name: WideString): WideString;
+var
+  I: Integer;
+begin
+  I := IndexOfName(Name);
+  if I >= 0 then
+    Result := Copy(Get(I), Length(Name) + 2, MaxInt) else
+    Result := '';
+end;
+
+function TWideStrings.IndexOf(const S: WideString): Integer;
+begin
+  for Result := 0 to GetCount - 1 do
+    if CompareStrings(Get(Result), S) = 0 then Exit;
+  Result := -1;
+end;
+
+function TWideStrings.IndexOfName(const Name: WideString): Integer;
+var
+  P: Integer;
+  S: WideString;
+begin
+  for Result := 0 to GetCount - 1 do
+  begin
+    S := Get(Result);
+    P := Pos(NameValueSeparator, S);
+    if (P <> 0) and (CompareStrings(Copy(S, 1, P - 1), Name) = 0) then Exit;
+  end;
+  Result := -1;
+end;
+
+function TWideStrings.IndexOfObject(AObject: TObject): Integer;
+begin
+  for Result := 0 to GetCount - 1 do
+    if GetObject(Result) = AObject then Exit;
+  Result := -1;
+end;
+
+procedure TWideStrings.InsertObject(Index: Integer; const S: WideString;
+  AObject: TObject);
+begin
+  Insert(Index, S);
+  PutObject(Index, AObject);
+end;
+
+procedure TWideStrings.LoadFromFile(const FileName: WideString);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+  try
+    LoadFromStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+procedure TWideStrings.LoadFromStream(Stream: TStream);
+var
+  Size: Integer;
+  S: WideString;
+begin
+  BeginUpdate;
+  try
+    Size := Stream.Size - Stream.Position;
+    SetString(S, nil, Size div SizeOf(WideChar));
+    Stream.Read(Pointer(S)^, Length(S) * SizeOf(WideChar));
+    SetTextStr(S);
+  finally
+    EndUpdate;
+  end;
+end;
+
+procedure TWideStrings.Move(CurIndex, NewIndex: Integer);
+var
+  TempObject: TObject;
+  TempString: WideString;
+begin
+  if CurIndex <> NewIndex then
+  begin
+    BeginUpdate;
+    try
+      TempString := Get(CurIndex);
+      TempObject := GetObject(CurIndex);
+      Delete(CurIndex);
+      InsertObject(NewIndex, TempString, TempObject);
+    finally
+      EndUpdate;
+    end;
+  end;
+end;
+
+procedure TWideStrings.Put(Index: Integer; const S: WideString);
+var
+  TempObject: TObject;
+begin
+  TempObject := GetObject(Index);
+  Delete(Index);
+  InsertObject(Index, S, TempObject);
+end;
+
+procedure TWideStrings.PutObject(Index: Integer; AObject: TObject);
+begin
+end;
+
+procedure TWideStrings.ReadData(Reader: TReader);
+begin
+  if Reader.NextValue in [vaString, vaLString] then
+    SetTextStr(Reader.ReadString) {JCL compatiblity}
+  else if Reader.NextValue = vaWString then
+    SetTextStr(Reader.ReadWideString) {JCL compatiblity}
+  else begin
+    BeginUpdate;
+    try
+      Clear;
+      Reader.ReadListBegin;
+      while not Reader.EndOfList do
+        if Reader.NextValue in [vaString, vaLString] then
+          Add(Reader.ReadString) {TStrings compatiblity}
+        else
+          Add(Reader.ReadWideString);
+      Reader.ReadListEnd;
+    finally
+      EndUpdate;
+    end;
+  end;
+end;
+
+procedure TWideStrings.SaveToFile(const FileName: WideString);
+var
+  Stream: TStream;
+begin
+  Stream := TTntFileStream.Create(FileName, fmCreate);
+  try
+    SaveToStream(Stream);
+  finally
+    Stream.Free;
+  end;
+end;
+
+procedure TWideStrings.SaveToStream(Stream: TStream);
+var
+  SW: WideString;
+begin
+  SW := GetTextStr;
+  Stream.WriteBuffer(PWideChar(SW)^, Length(SW) * SizeOf(WideChar));
+end;
+
+procedure TWideStrings.SetCapacity(NewCapacity: Integer);
+begin
+  // do nothing - descendents may optionally implement this method
+end;
+
+procedure TWideStrings.SetCommaText(const Value: WideString);
+begin
+  Delimiter := ',';
+  QuoteChar := '"';
+  SetDelimitedText(Value);
+end;
+
+procedure TWideStrings.SetStringsAdapter(const Value: IWideStringsAdapter);
+begin
+  if FAdapter <> nil then FAdapter.ReleaseStrings;
+  FAdapter := Value;
+  if FAdapter <> nil then FAdapter.ReferenceStrings(Self);
+end;
+
+procedure TWideStrings.SetTextW(const Text: PWideChar);
+begin
+  SetTextStr(Text);
+end;
+
+procedure TWideStrings.SetTextStr(const Value: WideString);
+var
+  P, Start: PWideChar;
+  S: WideString;
+begin
+  BeginUpdate;
+  try
+    Clear;
+    P := Pointer(Value);
+    if P <> nil then
+      while P^ <> #0 do
+      begin
+        Start := P;
+        while not (P^ in [WideChar(#0), WideChar(#10), WideChar(#13)]) and (P^ <> WideLineSeparator) do
+          Inc(P);
+        SetString(S, Start, P - Start);
+        Add(S);
+        if P^ = #13 then Inc(P);
+        if P^ = #10 then Inc(P);
+        if P^ = WideLineSeparator then Inc(P);
+      end;
+  finally
+    EndUpdate;
+  end;
+end;
+
+procedure TWideStrings.SetUpdateState(Updating: Boolean);
+begin
+end;
+
+procedure TWideStrings.SetValue(const Name, Value: WideString);
+var
+  I: Integer;
+begin
+  I := IndexOfName(Name);
+  if Value <> '' then
+  begin
+    if I < 0 then I := Add('');
+    Put(I, Name + NameValueSeparator + Value);
+  end else
+  begin
+    if I >= 0 then Delete(I);
+  end;
+end;
+
+procedure TWideStrings.WriteData(Writer: TWriter);
+var
+  I: Integer;
+begin
+  Writer.WriteListBegin;
+  for I := 0 to Count-1 do begin
+    Writer.WriteWideString(Get(I));
+  end;
+  Writer.WriteListEnd;
+end;
+
+procedure TWideStrings.SetDelimitedText(const Value: WideString);
+var
+  P, P1: PWideChar;
+  S: WideString;
+begin
+  BeginUpdate;
+  try
+    Clear;
+    P := PWideChar(Value);
+    while P^ in [WideChar(#1)..WideChar(' ')] do
+      Inc(P);
+    while P^ <> #0 do
+    begin
+      if P^ = QuoteChar then
+        S := WideExtractQuotedStr(P, QuoteChar)
+      else
+      begin
+        P1 := P;
+        while (P^ > ' ') and (P^ <> Delimiter) do
+          Inc(P);
+        SetString(S, P1, P - P1);
+      end;
+      Add(S);
+      while P^ in [WideChar(#1)..WideChar(' ')] do
+        Inc(P);
+      if P^ = Delimiter then
+      begin
+        P1 := P;
+        Inc(P1);
+        if P1^ = #0 then
+          Add('');
+        repeat
+          Inc(P);
+        until not (P^ in [WideChar(#1)..WideChar(' ')]);
+      end;
+    end;
+  finally
+    EndUpdate;
+  end;
+end;
+
+function TWideStrings.GetDelimiter: WideChar;
+begin
+  if not (sdDelimiter in FDefined) then
+    Delimiter := ',';
+  Result := FDelimiter;
+end;
+
+function TWideStrings.GetQuoteChar: WideChar;
+begin
+  if not (sdQuoteChar in FDefined) then
+    QuoteChar := '"';
+  Result := FQuoteChar;
+end;
+
+procedure TWideStrings.SetDelimiter(const Value: WideChar);
+begin
+  if (FDelimiter <> Value) or not (sdDelimiter in FDefined) then
+  begin
+    Include(FDefined, sdDelimiter);
+    FDelimiter := Value;
+  end
+end;
+
+procedure TWideStrings.SetQuoteChar(const Value: WideChar);
+begin
+  if (FQuoteChar <> Value) or not (sdQuoteChar in FDefined) then
+  begin
+    Include(FDefined, sdQuoteChar);
+    FQuoteChar := Value;
+  end
+end;
+
+function TWideStrings.CompareStrings(const S1, S2: WideString): Integer;
+begin
+  Result := WideCompareText(S1, S2);
+end;
+
+function TWideStrings.GetNameValueSeparator: WideChar;
+begin
+  {$IFDEF NAMEVALUESEPARATOR_RW}
+  if not (sdNameValueSeparator in FDefined) then
+    NameValueSeparator := '=';
+  Result := FNameValueSeparator;
+  {$ELSE}
+  Result := '=';
+  {$ENDIF}
+end;
+
+{$IFDEF NAMEVALUESEPARATOR_RW}
+procedure TWideStrings.SetNameValueSeparator(const Value: WideChar);
+begin
+  if (FNameValueSeparator <> Value) or not (sdNameValueSeparator in FDefined) then
+  begin
+    Include(FDefined, sdNameValueSeparator);
+    FNameValueSeparator := Value;
+  end
+end;
+{$ENDIF}
+
+function TWideStrings.GetValueFromIndex(Index: Integer): WideString;
+begin
+  if Index >= 0 then
+    Result := Copy(Get(Index), Length(Names[Index]) + 2, MaxInt) else
+    Result := '';
+end;
+
+procedure TWideStrings.SetValueFromIndex(Index: Integer; const Value: WideString);
+begin
+  if Value <> '' then
+  begin
+    if Index < 0 then Index := Add('');
+    Put(Index, Names[Index] + NameValueSeparator + Value);
+  end
+  else
+    if Index >= 0 then Delete(Index);
+end;
+
+end.
diff --git a/songmanagement/src/lib/TntUnicodeControls/TntWindows.pas b/songmanagement/src/lib/TntUnicodeControls/TntWindows.pas
new file mode 100644
index 00000000..8fd7ec88
--- /dev/null
+++ b/songmanagement/src/lib/TntUnicodeControls/TntWindows.pas
@@ -0,0 +1,1501 @@
+
+{*****************************************************************************}
+{                                                                             }
+{    Tnt Delphi Unicode Controls                                              }
+{      http://www.tntware.com/delphicontrols/unicode/                         }
+{        Version: 2.3.0                                                       }
+{                                                                             }
+{    Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com)       }
+{                                                                             }
+{*****************************************************************************}
+
+unit TntWindows;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$INCLUDE TntCompilers.inc}
+
+interface
+
+uses
+  Windows, ShellApi, ShlObj;
+
+// ......... compatibility
+
+const
+  DT_NOFULLWIDTHCHARBREAK = $00080000;
+
+const
+  INVALID_FILE_ATTRIBUTES = DWORD(-1);
+
+// ................ ANSI TYPES ................
+{TNT-WARN LPSTR}
+{TNT-WARN PLPSTR}
+{TNT-WARN LPCSTR}
+{TNT-WARN LPCTSTR}
+{TNT-WARN LPTSTR}
+
+// ........ EnumResourceTypesW, EnumResourceNamesW and EnumResourceLanguagesW are supposed ....
+// ........ to work on Win95/98/ME but have caused access violations in testing on Win95 ......
+// .. TNT--WARN EnumResourceTypes ..
+// .. TNT--WARN EnumResourceTypesA ..
+// .. TNT--WARN EnumResourceNames ..
+// .. TNT--WARN EnumResourceNamesA ..
+// .. TNT--WARN EnumResourceLanguages ..
+// .. TNT--WARN EnumResourceLanguagesA ..
+
+//------------------------------------------------------------------------------------------
+
+// ......... The Unicode form of these functions are supported on Windows 95/98/ME .........
+{TNT-WARN ExtTextOut}
+{TNT-WARN ExtTextOutA}
+{TNT-WARN Tnt_ExtTextOutW}
+
+{TNT-WARN FindResource}
+{TNT-WARN FindResourceA}
+{TNT-WARN Tnt_FindResourceW}
+
+{TNT-WARN FindResourceEx}
+{TNT-WARN FindResourceExA}
+{TNT-WARN Tnt_FindResourceExW}
+
+{TNT-WARN GetCharWidth}
+{TNT-WARN GetCharWidthA}
+{TNT-WARN Tnt_GetCharWidthW}
+
+{TNT-WARN GetCommandLine}
+{TNT-WARN GetCommandLineA}
+{TNT-WARN Tnt_GetCommandLineW}
+
+{TNT-WARN GetTextExtentPoint}
+{TNT-WARN GetTextExtentPointA}
+{TNT-WARN Tnt_GetTextExtentPointW}
+
+{TNT-WARN GetTextExtentPoint32}
+{TNT-WARN GetTextExtentPoint32A}
+{TNT-WARN Tnt_GetTextExtentPoint32W}
+
+{TNT-WARN lstrcat}
+{TNT-WARN lstrcatA}
+{TNT-WARN Tnt_lstrcatW}
+
+{TNT-WARN lstrcpy}
+{TNT-WARN lstrcpyA}
+{TNT-WARN Tnt_lstrcpyW}
+
+{TNT-WARN lstrlen}
+{TNT-WARN lstrlenA}
+{TNT-WARN Tnt_lstrlenW}
+
+{TNT-WARN MessageBox}
+{TNT-WARN MessageBoxA}
+{TNT-WARN Tnt_MessageBoxW}
+
+{TNT-WARN MessageBoxEx}
+{TNT-WARN MessageBoxExA}
+{TNT-WARN Tnt_MessageBoxExA}
+
+{TNT-WARN TextOut}
+{TNT-WARN TextOutA}
+{TNT-WARN Tnt_TextOutW}
+
+//------------------------------------------------------------------------------------------
+
+{TNT-WARN LOCALE_USER_DEFAULT} // <-- use GetThreadLocale
+{TNT-WARN LOCALE_SYSTEM_DEFAULT} // <-- use GetThreadLocale
+
+//------------------------------------------------------------------------------------------
+//                                     compatiblity
+//------------------------------------------------------------------------------------------
+{$IFNDEF COMPILER_9_UP}
+type
+  {$IFDEF FPC}
+  TStartupInfoA = STARTUPINFO;
+  TStartupInfoW = STARTUPINFO;
+  {$ELSE}
+  TStartupInfoA = _STARTUPINFOA;
+  TStartupInfoW = record
+    cb: DWORD;
+    lpReserved: PWideChar;
+    lpDesktop: PWideChar;
+    lpTitle: PWideChar;
+    dwX: DWORD;
+    dwY: DWORD;
+    dwXSize: DWORD;
+    dwYSize: DWORD;
+    dwXCountChars: DWORD;
+    dwYCountChars: DWORD;
+    dwFillAttribute: DWORD;
+    dwFlags: DWORD;
+    wShowWindow: Word;
+    cbReserved2: Word;
+    lpReserved2: PByte;
+    hStdInput: THandle;
+    hStdOutput: THandle;
+    hStdError: THandle;
+  end;
+  {$ENDIF}
+
+function CreateProcessW{TNT-ALLOW CreateProcessW}(lpApplicationName: PWideChar; lpCommandLine: PWideChar;
+  lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
+  bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
+  lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfoW;
+  var lpProcessInformation: TProcessInformation): BOOL; stdcall; external kernel32 name 'CreateProcessW';
+
+{$ENDIF}
+
+{$IFDEF FPC}
+type
+  TCurrencyFmtA = CURRENCYFMT;
+  TCurrencyFmtW = CURRENCYFMT;
+  PCurrencyFmtA = ^TCurrencyFmtA;
+  PCurrencyFmtW = ^TCurrencyFmtW;
+{$ENDIF}
+
+//------------------------------------------------------------------------------------------
+
+{TNT-WARN SetWindowText}
+{TNT-WARN SetWindowTextA}
+{TNT-WARN SetWindowTextW}
+function Tnt_SetWindowTextW(hWnd: HWND; lpString: PWideChar): BOOL;
+
+{TNT-WARN RemoveDirectory}
+{TNT-WARN RemoveDirectoryA}
+{TNT-WARN RemoveDirectoryW}
+function Tnt_RemoveDirectoryW(lpPathName: PWideChar): BOOL;
+
+{TNT-WARN GetShortPathName}
+{TNT-WARN GetShortPathNameA}
+{TNT-WARN GetShortPathNameW}
+function Tnt_GetShortPathNameW(lpszLongPath: PWideChar; lpszShortPath: PWideChar;
+  cchBuffer: DWORD): DWORD;
+
+{TNT-WARN GetFullPathName}
+{TNT-WARN GetFullPathNameA}
+{TNT-WARN GetFullPathNameW}
+function Tnt_GetFullPathNameW(lpFileName: PWideChar; nBufferLength: DWORD;
+  lpBuffer: PWideChar; var lpFilePart: PWideChar): DWORD;
+
+{TNT-WARN CreateFile}
+{TNT-WARN CreateFileA}
+{TNT-WARN CreateFileW}
+function Tnt_CreateFileW(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD;
+  lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD;
+    hTemplateFile: THandle): THandle;
+
+{TNT-WARN FindFirstFile}
+{TNT-WARN FindFirstFileA}
+{TNT-WARN FindFirstFileW}
+function Tnt_FindFirstFileW(lpFileName: PWideChar; var lpFindFileData: TWIN32FindDataW): THandle;
+
+{TNT-WARN FindNextFile}
+{TNT-WARN FindNextFileA}
+{TNT-WARN FindNextFileW}
+function Tnt_FindNextFileW(hFindFile: THandle; var lpFindFileData: TWIN32FindDataW): BOOL;
+
+{TNT-WARN GetFileAttributes}
+{TNT-WARN GetFileAttributesA}
+{TNT-WARN GetFileAttributesW}
+function Tnt_GetFileAttributesW(lpFileName: PWideChar): DWORD;
+
+{TNT-WARN SetFileAttributes}
+{TNT-WARN SetFileAttributesA}
+{TNT-WARN SetFileAttributesW}
+function Tnt_SetFileAttributesW(lpFileName: PWideChar; dwFileAttributes: DWORD): BOOL;
+
+{TNT-WARN CreateDirectory}
+{TNT-WARN CreateDirectoryA}
+{TNT-WARN CreateDirectoryW}
+function Tnt_CreateDirectoryW(lpPathName: PWideChar;
+  lpSecurityAttributes: PSecurityAttributes): BOOL;
+
+{TNT-WARN MoveFile}
+{TNT-WARN MoveFileA}
+{TNT-WARN MoveFileW}
+function Tnt_MoveFileW(lpExistingFileName, lpNewFileName: PWideChar): BOOL;
+
+{TNT-WARN CopyFile}
+{TNT-WARN CopyFileA}
+{TNT-WARN CopyFileW}
+function Tnt_CopyFileW(lpExistingFileName, lpNewFileName: PWideChar; bFailIfExists: BOOL): BOOL;
+
+{TNT-WARN DeleteFile}
+{TNT-WARN DeleteFileA}
+{TNT-WARN DeleteFileW}
+function Tnt_DeleteFileW(lpFileName: PWideChar): BOOL;
+
+{TNT-WARN DrawText}
+{TNT-WARN DrawTextA}
+{TNT-WARN DrawTextW}
+function Tnt_DrawTextW(hDC: HDC; lpString: PWideChar; nCount: Integer;
+  var lpRect: TRect; uFormat: UINT): Integer;
+
+{TNT-WARN GetDiskFreeSpace}
+{TNT-WARN GetDiskFreeSpaceA}
+{TNT-WARN GetDiskFreeSpaceW}
+function Tnt_GetDiskFreeSpaceW(lpRootPathName: PWideChar; var lpSectorsPerCluster,
+  lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters: DWORD): BOOL;
+
+{TNT-WARN GetVolumeInformation}
+{TNT-WARN GetVolumeInformationA}
+{TNT-WARN GetVolumeInformationW}  
+function Tnt_GetVolumeInformationW(lpRootPathName: PWideChar; lpVolumeNameBuffer: PWideChar;
+  nVolumeNameSize: DWORD; lpVolumeSerialNumber: PDWORD;
+    var lpMaximumComponentLength, lpFileSystemFlags: DWORD; lpFileSystemNameBuffer: PWideChar;
+      nFileSystemNameSize: DWORD): BOOL;
+
+{TNT-WARN GetModuleFileName}
+{TNT-WARN GetModuleFileNameA}
+{TNT-WARN GetModuleFileNameW}
+function Tnt_GetModuleFileNameW(hModule: HINST; lpFilename: PWideChar; nSize: DWORD): DWORD;
+
+{TNT-WARN GetTempPath}
+{TNT-WARN GetTempPathA}
+{TNT-WARN GetTempPathW}
+function Tnt_GetTempPathW(nBufferLength: DWORD; lpBuffer: PWideChar): DWORD;
+
+{TNT-WARN GetTempFileName}
+{TNT-WARN GetTempFileNameA}
+{TNT-WARN GetTempFileNameW}
+function Tnt_GetTempFileNameW(lpPathName, lpPrefixString: PWideChar; uUnique: UINT;
+  lpTempFileName: PWideChar): UINT;
+
+{TNT-WARN GetWindowsDirectory}
+{TNT-WARN GetWindowsDirectoryA}
+{TNT-WARN GetWindowsDirectoryW}
+function Tnt_GetWindowsDirectoryW(lpBuffer: PWideChar; uSize: UINT): UINT;
+
+{TNT-WARN GetSystemDirectory}
+{TNT-WARN GetSystemDirectoryA}
+{TNT-WARN GetSystemDirectoryW}
+function Tnt_GetSystemDirectoryW(lpBuffer: PWideChar; uSize: UINT): UINT;
+
+{TNT-WARN GetCurrentDirectory}
+{TNT-WARN GetCurrentDirectoryA}
+{TNT-WARN GetCurrentDirectoryW}
+function Tnt_GetCurrentDirectoryW(nBufferLength: DWORD; lpBuffer: PWideChar): DWORD;
+
+{TNT-WARN SetCurrentDirectory}
+{TNT-WARN SetCurrentDirectoryA}
+{TNT-WARN SetCurrentDirectoryW}
+function Tnt_SetCurrentDirectoryW(lpPathName: PWideChar): BOOL;
+
+{TNT-WARN GetComputerName}
+{TNT-WARN GetComputerNameA}
+{TNT-WARN GetComputerNameW}
+function Tnt_GetComputerNameW(lpBuffer: PWideChar; var nSize: DWORD): BOOL;
+
+{TNT-WARN GetUserName}
+{TNT-WARN GetUserNameA}
+{TNT-WARN GetUserNameW}
+function Tnt_GetUserNameW(lpBuffer: PWideChar; var nSize: DWORD): BOOL;
+
+{TNT-WARN ShellExecute}
+{TNT-WARN ShellExecuteA}
+{TNT-WARN ShellExecuteW}
+function Tnt_ShellExecuteW(hWnd: HWND; Operation, FileName, Parameters,
+  Directory: PWideChar; ShowCmd: Integer): HINST;
+
+{TNT-WARN LoadLibrary}
+{TNT-WARN LoadLibraryA}
+{TNT-WARN LoadLibraryW}
+function Tnt_LoadLibraryW(lpLibFileName: PWideChar): HMODULE;
+
+{TNT-WARN LoadLibraryEx}
+{TNT-WARN LoadLibraryExA}
+{TNT-WARN LoadLibraryExW}
+function Tnt_LoadLibraryExW(lpLibFileName: PWideChar; hFile: THandle; dwFlags: DWORD): HMODULE;
+
+{TNT-WARN CreateProcess}
+{TNT-WARN CreateProcessA}
+{TNT-WARN CreateProcessW}
+function Tnt_CreateProcessW(lpApplicationName: PWideChar; lpCommandLine: PWideChar;
+  lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
+    bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
+      lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfoW;
+        var lpProcessInformation: TProcessInformation): BOOL;
+
+{TNT-WARN GetCurrencyFormat}
+{TNT-WARN GetCurrencyFormatA}
+{TNT-WARN GetCurrencyFormatW}
+function Tnt_GetCurrencyFormatW(Locale: LCID; dwFlags: DWORD; lpValue: PWideChar;
+  lpFormat: PCurrencyFmtW; lpCurrencyStr: PWideChar; cchCurrency: Integer): Integer;
+
+{TNT-WARN CompareString}
+{TNT-WARN CompareStringA}
+{TNT-WARN CompareStringW}
+function Tnt_CompareStringW(Locale: LCID; dwCmpFlags: DWORD; lpString1: PWideChar;
+  cchCount1: Integer; lpString2: PWideChar; cchCount2: Integer): Integer;
+
+{TNT-WARN CharUpper}
+{TNT-WARN CharUpperA}
+{TNT-WARN CharUpperW}
+function Tnt_CharUpperW(lpsz: PWideChar): PWideChar;
+
+{TNT-WARN CharUpperBuff}
+{TNT-WARN CharUpperBuffA}
+{TNT-WARN CharUpperBuffW}
+function Tnt_CharUpperBuffW(lpsz: PWideChar; cchLength: DWORD): DWORD;
+
+{TNT-WARN CharLower}
+{TNT-WARN CharLowerA}
+{TNT-WARN CharLowerW}
+function Tnt_CharLowerW(lpsz: PWideChar): PWideChar;
+
+{TNT-WARN CharLowerBuff}
+{TNT-WARN CharLowerBuffA}
+{TNT-WARN CharLowerBuffW}
+function Tnt_CharLowerBuffW(lpsz: PWideChar; cchLength: DWORD): DWORD;
+
+{TNT-WARN GetStringTypeEx}
+{TNT-WARN GetStringTypeExA}
+{TNT-WARN GetStringTypeExW}
+function Tnt_GetStringTypeExW(Locale: LCID; dwInfoType: DWORD;
+  lpSrcStr: PWideChar; cchSrc: Integer; var lpCharType): BOOL;
+
+{TNT-WARN LoadString}
+{TNT-WARN LoadStringA}
+{TNT-WARN LoadStringW}
+function Tnt_LoadStringW(hInstance: HINST; uID: UINT; lpBuffer: PWideChar; nBufferMax: Integer): Integer;
+
+{$IFDEF FPC}
+type
+  TMenuItemInfoW   = TMENUITEMINFO;
+  tagMenuItemINFOW = tagMENUITEMINFO;
+{$ENDIF}
+
+{TNT-WARN InsertMenuItem}
+{TNT-WARN InsertMenuItemA}
+{TNT-WARN InsertMenuItemW}
+function Tnt_InsertMenuItemW(hMenu: HMENU; uItem: DWORD; fByPosition: BOOL; lpmii: tagMenuItemINFOW): BOOL;
+
+{TNT-WARN ExtractIconEx}
+{TNT-WARN ExtractIconExA}
+{TNT-WARN ExtractIconExW}
+function Tnt_ExtractIconExW(lpszFile: PWideChar; nIconIndex: Integer;
+  var phiconLarge, phiconSmall: HICON; nIcons: UINT): UINT;
+
+{TNT-WARN ExtractAssociatedIcon}
+{TNT-WARN ExtractAssociatedIconA}
+{TNT-WARN ExtractAssociatedIconW}
+function Tnt_ExtractAssociatedIconW(hInst: HINST; lpIconPath: PWideChar;
+  var lpiIcon: Word): HICON;
+
+{TNT-WARN GetFileVersionInfoSize}
+{TNT-WARN GetFileVersionInfoSizeA}
+{TNT-WARN GetFileVersionInfoSizeW}
+function Tnt_GetFileVersionInfoSizeW(lptstrFilename: PWideChar; var lpdwHandle: DWORD): DWORD;
+
+{TNT-WARN GetFileVersionInfo}
+{TNT-WARN GetFileVersionInfoA}
+{TNT-WARN GetFileVersionInfoW}
+function Tnt_GetFileVersionInfoW(lptstrFilename: PWideChar; dwHandle, dwLen: DWORD;
+  lpData: Pointer): BOOL;
+
+const
+  VQV_FIXEDFILEINFO = '\';
+  VQV_VARFILEINFO_TRANSLATION = '\VarFileInfo\Translation';
+  VQV_STRINGFILEINFO = '\StringFileInfo';
+
+  VER_COMMENTS         = 'Comments';
+  VER_INTERNALNAME     = 'InternalName';
+  VER_PRODUCTNAME      = 'ProductName';
+  VER_COMPANYNAME      = 'CompanyName';
+  VER_LEGALCOPYRIGHT   = 'LegalCopyright';
+  VER_PRODUCTVERSION   = 'ProductVersion';
+  VER_FILEDESCRIPTION  = 'FileDescription';
+  VER_LEGALTRADEMARKS  = 'LegalTrademarks';
+  VER_PRIVATEBUILD     = 'PrivateBuild';
+  VER_FILEVERSION      = 'FileVersion';
+  VER_ORIGINALFILENAME = 'OriginalFilename';
+  VER_SPECIALBUILD     = 'SpecialBuild';
+
+{TNT-WARN VerQueryValue}
+{TNT-WARN VerQueryValueA}
+{TNT-WARN VerQueryValueW}
+function Tnt_VerQueryValueW(pBlock: Pointer; lpSubBlock: PWideChar;
+  var lplpBuffer: Pointer; var puLen: UINT): BOOL;
+
+type
+{$IFDEF FPC}
+  PSHNAMEMAPPINGA = ^SHNAMEMAPPINGA;
+  SHNAMEMAPPINGA = record
+    pszOldPath : LPSTR;
+    pszNewPath : LPSTR;
+    cchOldPath : longint;
+    cchNewPath : longint;
+  end;
+
+  PSHNAMEMAPPINGW = ^SHNAMEMAPPINGW;
+  SHNAMEMAPPINGW = record
+    pszOldPath : LPWSTR;
+    pszNewPath : LPWSTR;
+    cchOldPath : longint;
+    cchNewPath : longint;
+  end;
+{$ENDIF}
+
+  TSHNameMappingHeaderA = record
+   cNumOfMappings: Cardinal;
+   lpNM: PSHNAMEMAPPINGA;
+  end;
+  PSHNameMappingHeaderA = ^TSHNameMappingHeaderA;
+
+  TSHNameMappingHeaderW = record
+   cNumOfMappings: Cardinal;
+   lpNM: PSHNAMEMAPPINGW;
+  end;
+  PSHNameMappingHeaderW = ^TSHNameMappingHeaderW;
+
+{TNT-WARN SHFileOperation}
+{TNT-WARN SHFileOperationA}
+{TNT-WARN SHFileOperationW} // <-- no stub on early Windows 95
+function Tnt_SHFileOperationW(var lpFileOp: TSHFileOpStructW): Integer;
+
+{TNT-WARN SHFreeNameMappings}
+procedure Tnt_SHFreeNameMappings(hNameMappings: THandle);
+
+{TNT-WARN SHBrowseForFolder}
+{TNT-WARN SHBrowseForFolderA}
+{TNT-WARN SHBrowseForFolderW} // <-- no stub on early Windows 95
+function Tnt_SHBrowseForFolderW(var lpbi: TBrowseInfoW): PItemIDList;
+
+{TNT-WARN SHGetPathFromIDList}
+{TNT-WARN SHGetPathFromIDListA}
+{TNT-WARN SHGetPathFromIDListW} // <-- no stub on early Windows 95
+function Tnt_SHGetPathFromIDListW(pidl: PItemIDList; pszPath: PWideChar): BOOL;
+
+{TNT-WARN SHGetFileInfo}
+{TNT-WARN SHGetFileInfoA}
+{TNT-WARN SHGetFileInfoW} // <-- no stub on early Windows 95
+function Tnt_SHGetFileInfoW(pszPath: PWideChar; dwFileAttributes: DWORD;
+  var psfi: TSHFileInfoW; cbFileInfo, uFlags: UINT): DWORD;
+
+// ......... introduced .........
+function Tnt_Is_IntResource(ResStr: LPCWSTR): Boolean;
+
+function LANGIDFROMLCID(lcid: LCID): WORD;
+function MAKELANGID(usPrimaryLanguage, usSubLanguage: WORD): WORD;
+function MAKELCID(wLanguageID: WORD; wSortID: WORD = SORT_DEFAULT): LCID;
+function PRIMARYLANGID(lgid: WORD): WORD;
+function SORTIDFROMLCID(lcid: LCID): WORD;
+function SUBLANGID(lgid: WORD): WORD;
+
+implementation
+
+uses
+  SysUtils, Math, TntSysUtils,
+  {$IFDEF COMPILER_9_UP} WideStrUtils, {$ENDIF} TntWideStrUtils;
+
+function _PAnsiCharWithNil(const S: AnsiString): PAnsiChar;
+begin
+  if S = '' then
+    Result := nil {Win9x needs nil for some parameters instead of empty strings}
+  else
+    Result := PAnsiChar(S);
+end;
+
+function _PWideCharWithNil(const S: WideString): PWideChar;
+begin
+  if S = '' then
+    Result := nil {Win9x needs nil for some parameters instead of empty strings}
+  else
+    Result := PWideChar(S);
+end;
+
+function _WStr(lpString: PWideChar; cchCount: Integer): WideString;
+begin
+  if cchCount = -1 then
+    Result := lpString
+  else
+    Result := Copy(WideString(lpString), 1, cchCount);
+end;
+
+procedure _MakeWideWin32FindData(var WideFindData: TWIN32FindDataW; AnsiFindData: TWIN32FindDataA);
+begin
+  CopyMemory(@WideFindData, @AnsiFindData,
+    PtrUInt(@WideFindData.cFileName) - PtrUInt(@WideFindData));
+  WStrPCopy(WideFindData.cFileName, AnsiFindData.cFileName);
+  WStrPCopy(WideFindData.cAlternateFileName, AnsiFindData.cAlternateFileName);
+end;
+
+function Tnt_SetWindowTextW(hWnd: HWND; lpString: PWideChar): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := SetWindowTextW{TNT-ALLOW SetWindowTextW}(hWnd, lpString)
+  else
+    Result := SetWindowTextA{TNT-ALLOW SetWindowTextA}(hWnd, PAnsiChar(AnsiString(lpString)));
+end;
+
+//-----------------------------
+
+type
+  TPathLengthResultOption = (poAllowDirectoryMode, poZeroSmallBuff, poExactCopy, poExactCopySubPaths);
+  TPathLengthResultOptions = set of TPathLengthResultOption;
+
+procedure _ExactStrCopyW(pDest, pSource: PWideChar; Count: Integer);
+var
+  i: integer;
+begin
+  for i := 1 to Count do begin
+    pDest^ := pSource^;
+    Inc(PSource);
+    Inc(pDest);
+  end;
+end;
+
+procedure _ExactCopySubPaths(pDest, pSource: PWideChar; Count: Integer);
+var
+  i: integer;
+  OriginalSource: PWideChar;
+  PNextSlash: PWideChar;
+begin
+  if Count >= 4 then begin
+    OriginalSource := pSource;
+    PNextSlash := WStrScan(pSource, '\');
+    for i := 1 to Count - 1 do begin
+      // determine next path delimiter
+      if pSource > pNextSlash then begin
+        PNextSlash := WStrScan(pSource, '\');
+      end;
+      // leave if no more sub paths
+      if (PNextSlash = nil)
+      or ((pNextSlash - OriginalSource) >= Count) then begin
+        exit;
+      end;
+      // copy char
+      pDest^ := pSource^;
+      Inc(PSource);
+      Inc(pDest);
+    end;
+  end;
+end;
+
+function _HandlePathLengthResult(nBufferLength: DWORD; lpBuffer: PWideChar; const AnsiBuff: AnsiString; Options: TPathLengthResultOptions): Integer;
+var
+  WideBuff: WideString;
+begin
+  WideBuff := AnsiBuff;
+  if nBufferLength > Cardinal(Length(WideBuff)) then begin
+    // normal
+    Result := Length(WideBuff);
+    WStrLCopy(lpBuffer, PWideChar(WideBuff), nBufferLength);
+  end else if (poExactCopy in Options) then begin
+    // exact
+    Result := nBufferLength;
+    _ExactStrCopyW(lpBuffer, PWideChar(WideBuff), nBufferLength);
+  end else begin
+    // other
+    if (poAllowDirectoryMode in Options)
+    and (nBufferLength = Cardinal(Length(WideBuff))) then begin
+      Result := Length(WideBuff) + 1;
+      WStrLCopy(lpBuffer, PWideChar(WideBuff), nBufferLength - 1);
+    end else begin
+      Result := Length(WideBuff) + 1;
+      if (nBufferLength > 0) then begin
+        if (poZeroSmallBuff in Options) then
+          lpBuffer^ := #0
+        else if (poExactCopySubPaths in Options) then
+          _ExactCopySubPaths(lpBuffer, PWideChar(WideBuff), nBufferLength);
+      end;
+    end;
+  end;
+end;
+
+function _HandleStringLengthResult(nBufferLength: DWORD; lpBuffer: PWideChar; const AnsiBuff: AnsiString; Options: TPathLengthResultOptions): Integer;
+var
+  WideBuff: WideString;
+begin
+  WideBuff := AnsiBuff;
+  if nBufferLength >= Cardinal(Length(WideBuff)) then begin
+    // normal
+    Result := Length(WideBuff);
+    WStrLCopy(lpBuffer, PWideChar(WideBuff), nBufferLength);
+  end else if nBufferLength = 0 then
+    Result := Length(WideBuff)
+  else
+    Result := 0;
+end;
+
+//-------------------------------------------
+
+function Tnt_RemoveDirectoryW(lpPathName: PWideChar): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := RemoveDirectoryW{TNT-ALLOW RemoveDirectoryW}(PWideChar(lpPathName))
+  else
+    Result := RemoveDirectoryA{TNT-ALLOW RemoveDirectoryA}(PAnsiChar(AnsiString(lpPathName)));
+end;
+
+function Tnt_GetShortPathNameW(lpszLongPath: PWideChar; lpszShortPath: PWideChar;
+  cchBuffer: DWORD): DWORD;
+var
+  AnsiBuff: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetShortPathNameW{TNT-ALLOW GetShortPathNameW}(lpszLongPath, lpszShortPath, cchBuffer)
+  else begin
+    SetLength(AnsiBuff, MAX_PATH * 2);
+    SetLength(AnsiBuff, GetShortPathNameA{TNT-ALLOW GetShortPathNameA}(PAnsiChar(AnsiString(lpszLongPath)),
+      PAnsiChar(AnsiBuff), Length(AnsiBuff)));
+    Result := _HandlePathLengthResult(cchBuffer, lpszShortPath, AnsiBuff, [poExactCopySubPaths]);
+  end;
+end;
+
+function Tnt_GetFullPathNameW(lpFileName: PWideChar; nBufferLength: DWORD;
+  lpBuffer: PWideChar; var lpFilePart: PWideChar): DWORD;
+var
+  AnsiBuff: AnsiString;
+  AnsiFilePart: PAnsiChar;
+  AnsiLeadingChars: Integer;
+  WideLeadingChars: Integer;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetFullPathNameW{TNT-ALLOW GetFullPathNameW}(lpFileName, nBufferLength, lpBuffer, lpFilePart)
+  else begin
+    SetLength(AnsiBuff, MAX_PATH * 2);
+    SetLength(AnsiBuff, GetFullPathNameA{TNT-ALLOW GetFullPathNameA}(PAnsiChar(AnsiString(lpFileName)),
+      Length(AnsiBuff), PAnsiChar(AnsiBuff), AnsiFilePart));
+    Result := _HandlePathLengthResult(nBufferLength, lpBuffer, AnsiBuff, [poZeroSmallBuff]);
+    // deal w/ lpFilePart
+    if (AnsiFilePart = nil) or (nBufferLength < Result) then
+      lpFilePart := nil
+    else begin
+      AnsiLeadingChars := AnsiFilePart - PAnsiChar(AnsiBuff);
+      WideLeadingChars := Length(WideString(Copy(AnsiBuff, 1, AnsiLeadingChars)));
+      lpFilePart := lpBuffer + WideLeadingChars;
+    end;
+  end;
+end;
+
+function Tnt_CreateFileW(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD;
+  lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD;
+    hTemplateFile: THandle): THandle;
+begin
+  if Win32PlatformIsUnicode then
+    Result := CreateFileW{TNT-ALLOW CreateFileW}(lpFileName, dwDesiredAccess, dwShareMode,
+      lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
+  else
+    Result := CreateFileA{TNT-ALLOW CreateFileA}(PAnsiChar(AnsiString(lpFileName)), dwDesiredAccess, dwShareMode,
+      lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
+end;
+
+function Tnt_FindFirstFileW(lpFileName: PWideChar; var lpFindFileData: TWIN32FindDataW): THandle;
+var
+  Ansi_lpFindFileData: TWIN32FindDataA;
+begin
+  if Win32PlatformIsUnicode then
+    Result := FindFirstFileW{TNT-ALLOW FindFirstFileW}(lpFileName, lpFindFileData)
+  else begin
+    Result := FindFirstFileA{TNT-ALLOW FindFirstFileA}(PAnsiChar(AnsiString(lpFileName)),
+      Ansi_lpFindFileData);
+    if Result <> INVALID_HANDLE_VALUE then
+      _MakeWideWin32FindData(lpFindFileData, Ansi_lpFindFileData);
+  end;
+end;
+
+function Tnt_FindNextFileW(hFindFile: THandle; var lpFindFileData: TWIN32FindDataW): BOOL;
+var
+  Ansi_lpFindFileData: TWIN32FindDataA;
+begin
+  if Win32PlatformIsUnicode then
+    Result := FindNextFileW{TNT-ALLOW FindNextFileW}(hFindFile, lpFindFileData)
+  else begin
+    Result := FindNextFileA{TNT-ALLOW FindNextFileA}(hFindFile, Ansi_lpFindFileData);
+    if Result then
+      _MakeWideWin32FindData(lpFindFileData, Ansi_lpFindFileData);
+  end;
+end;
+
+function Tnt_GetFileAttributesW(lpFileName: PWideChar): DWORD;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetFileAttributesW{TNT-ALLOW GetFileAttributesW}(lpFileName)
+  else
+    Result := GetFileAttributesA{TNT-ALLOW GetFileAttributesA}(PAnsiChar(AnsiString(lpFileName)));
+end;
+
+function Tnt_SetFileAttributesW(lpFileName: PWideChar; dwFileAttributes: DWORD): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := SetFileAttributesW{TNT-ALLOW SetFileAttributesW}(lpFileName, dwFileAttributes)
+  else
+    Result := SetFileAttributesA{TNT-ALLOW SetFileAttributesA}(PAnsiChar(AnsiString(lpFileName)), dwFileAttributes);
+end;
+
+function Tnt_CreateDirectoryW(lpPathName: PWideChar;
+  lpSecurityAttributes: PSecurityAttributes): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := CreateDirectoryW{TNT-ALLOW CreateDirectoryW}(lpPathName, lpSecurityAttributes)
+  else
+    Result := CreateDirectoryA{TNT-ALLOW CreateDirectoryA}(PAnsiChar(AnsiString(lpPathName)), lpSecurityAttributes);
+end;
+
+function Tnt_MoveFileW(lpExistingFileName, lpNewFileName: PWideChar): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := MoveFileW{TNT-ALLOW MoveFileW}(lpExistingFileName, lpNewFileName)
+  else
+    Result := MoveFileA{TNT-ALLOW MoveFileA}(PAnsiChar(AnsiString(lpExistingFileName)), PAnsiChar(AnsiString(lpNewFileName)));
+end;
+
+function Tnt_CopyFileW(lpExistingFileName, lpNewFileName: PWideChar; bFailIfExists: BOOL): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := CopyFileW{TNT-ALLOW CopyFileW}(lpExistingFileName, lpNewFileName, bFailIfExists)
+  else
+    Result := CopyFileA{TNT-ALLOW CopyFileA}(PAnsiChar(AnsiString(lpExistingFileName)),
+      PAnsiChar(AnsiString(lpNewFileName)), bFailIfExists);
+end;
+
+function Tnt_DeleteFileW(lpFileName: PWideChar): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := DeleteFileW{TNT-ALLOW DeleteFileW}(lpFileName)
+  else
+    Result := DeleteFileA{TNT-ALLOW DeleteFileA}(PAnsiChar(AnsiString(lpFileName)));
+end;
+
+function Tnt_DrawTextW(hDC: HDC; lpString: PWideChar; nCount: Integer;
+  var lpRect: TRect; uFormat: UINT): Integer;
+begin
+  if Win32PlatformIsUnicode then
+    Result := DrawTextW{TNT-ALLOW DrawTextW}(hDC, lpString, nCount, lpRect, uFormat)
+  else
+    Result := DrawTextA{TNT-ALLOW DrawTextA}(hDC,
+      PAnsiChar(AnsiString(_WStr(lpString, nCount))), -1, lpRect, uFormat);
+end;
+
+function Tnt_GetDiskFreeSpaceW(lpRootPathName: PWideChar; var lpSectorsPerCluster,
+  lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters: DWORD): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetDiskFreeSpaceW{TNT-ALLOW GetDiskFreeSpaceW}(lpRootPathName,
+      lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters)
+  else
+    Result := GetDiskFreeSpaceA{TNT-ALLOW GetDiskFreeSpaceA}(PAnsiChar(AnsiString(lpRootPathName)),
+      lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters)
+end;
+
+function Tnt_GetVolumeInformationW(lpRootPathName: PWideChar; lpVolumeNameBuffer: PWideChar;
+  nVolumeNameSize: DWORD; lpVolumeSerialNumber: PDWORD;
+    var lpMaximumComponentLength, lpFileSystemFlags: DWORD; lpFileSystemNameBuffer: PWideChar;
+      nFileSystemNameSize: DWORD): BOOL;
+var
+  AnsiFileSystemNameBuffer: AnsiString;
+  AnsiVolumeNameBuffer: AnsiString;
+  AnsiBuffLen: DWORD;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetVolumeInformationW{TNT-ALLOW GetVolumeInformationW}(lpRootPathName, lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, lpFileSystemNameBuffer, nFileSystemNameSize)
+  else begin
+    SetLength(AnsiVolumeNameBuffer, MAX_COMPUTERNAME_LENGTH + 1);
+    SetLength(AnsiFileSystemNameBuffer, MAX_COMPUTERNAME_LENGTH + 1);
+    AnsiBuffLen := Length(AnsiFileSystemNameBuffer);
+    Result := GetVolumeInformationA{TNT-ALLOW GetVolumeInformationA}(PAnsiChar(AnsiString(lpRootPathName)), PAnsiChar(AnsiVolumeNameBuffer), AnsiBuffLen, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, PAnsiChar(AnsiFileSystemNameBuffer), AnsiBuffLen);
+    if Result then begin
+      SetLength(AnsiFileSystemNameBuffer, AnsiBuffLen);
+      if (nFileSystemNameSize <= AnsiBuffLen) or (Length(AnsiFileSystemNameBuffer) = 0) then
+        Result := False
+      else begin
+        WStrPLCopy(lpFileSystemNameBuffer, AnsiFileSystemNameBuffer, nFileSystemNameSize);
+        WStrPLCopy(lpVolumeNameBuffer, AnsiVolumeNameBuffer, nVolumeNameSize);
+      end;
+    end;
+  end;
+end;
+
+function Tnt_GetModuleFileNameW(hModule: HINST; lpFilename: PWideChar; nSize: DWORD): DWORD;
+var
+  AnsiBuff: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetModuleFileNameW{TNT-ALLOW GetModuleFileNameW}(hModule, lpFilename, nSize)
+  else begin
+    SetLength(AnsiBuff, MAX_PATH);
+    SetLength(AnsiBuff, GetModuleFileNameA{TNT-ALLOW GetModuleFileNameA}(hModule, PAnsiChar(AnsiBuff), Length(AnsiBuff)));
+    Result := _HandlePathLengthResult(nSize, lpFilename, AnsiBuff, [poExactCopy]);
+  end;
+end;
+
+function Tnt_GetTempPathW(nBufferLength: DWORD; lpBuffer: PWideChar): DWORD;
+var
+  AnsiBuff: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetTempPathW{TNT-ALLOW GetTempPathW}(nBufferLength, lpBuffer)
+  else begin
+    SetLength(AnsiBuff, MAX_PATH);
+    SetLength(AnsiBuff, GetTempPathA{TNT-ALLOW GetTempPathA}(Length(AnsiBuff), PAnsiChar(AnsiBuff)));
+    Result := _HandlePathLengthResult(nBufferLength, lpBuffer, AnsiBuff, [poAllowDirectoryMode, poZeroSmallBuff]);
+  end;
+end;
+
+function Tnt_GetTempFileNameW(lpPathName, lpPrefixString: PWideChar; uUnique: UINT;
+  lpTempFileName: PWideChar): UINT;
+var
+  AnsiBuff: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetTempFileNameW{TNT-ALLOW GetTempFileNameW}(lpPathName, lpPrefixString, uUnique, lpTempFileName)
+  else begin
+    SetLength(AnsiBuff, MAX_PATH);
+    Result := GetTempFileNameA{TNT-ALLOW GetTempFileNameA}(PAnsiChar(AnsiString(lpPathName)), PAnsiChar(lpPrefixString), uUnique, PAnsiChar(AnsiBuff));
+    AnsiBuff := PAnsiChar(AnsiBuff);
+    _HandlePathLengthResult(MAX_PATH, lpTempFileName, AnsiBuff, [poZeroSmallBuff]);
+  end;
+end;
+
+function Tnt_GetWindowsDirectoryW(lpBuffer: PWideChar; uSize: UINT): UINT;
+var
+  AnsiBuff: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetWindowsDirectoryW{TNT-ALLOW GetWindowsDirectoryW}(lpBuffer, uSize)
+  else begin
+    SetLength(AnsiBuff, MAX_PATH);
+    SetLength(AnsiBuff, GetWindowsDirectoryA{TNT-ALLOW GetWindowsDirectoryA}(PAnsiChar(AnsiBuff), Length(AnsiBuff)));
+    Result := _HandlePathLengthResult(uSize, lpBuffer, AnsiBuff, []);
+  end;
+end;
+
+function Tnt_GetSystemDirectoryW(lpBuffer: PWideChar; uSize: UINT): UINT;
+var
+  AnsiBuff: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetSystemDirectoryW{TNT-ALLOW GetSystemDirectoryW}(lpBuffer, uSize)
+  else begin
+    SetLength(AnsiBuff, MAX_PATH);
+    SetLength(AnsiBuff, GetSystemDirectoryA{TNT-ALLOW GetSystemDirectoryA}(PAnsiChar(AnsiBuff), Length(AnsiBuff)));
+    Result := _HandlePathLengthResult(uSize, lpBuffer, AnsiBuff, []);
+  end;
+end;
+
+function Tnt_GetCurrentDirectoryW(nBufferLength: DWORD; lpBuffer: PWideChar): DWORD;
+var
+  AnsiBuff: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetCurrentDirectoryW{TNT-ALLOW GetCurrentDirectoryW}(nBufferLength, lpBuffer)
+  else begin
+    SetLength(AnsiBuff, MAX_PATH);
+    SetLength(AnsiBuff, GetCurrentDirectoryA{TNT-ALLOW GetCurrentDirectoryA}(Length(AnsiBuff), PAnsiChar(AnsiBuff)));
+    Result := _HandlePathLengthResult(nBufferLength, lpBuffer, AnsiBuff, [poAllowDirectoryMode, poZeroSmallBuff]);
+  end;
+end;
+
+function Tnt_SetCurrentDirectoryW(lpPathName: PWideChar): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := SetCurrentDirectoryW{TNT-ALLOW SetCurrentDirectoryW}(lpPathName)
+  else
+    Result := SetCurrentDirectoryA{TNT-ALLOW SetCurrentDirectoryA}(PAnsiChar(AnsiString(lpPathName)));
+end;
+
+function Tnt_GetComputerNameW(lpBuffer: PWideChar; var nSize: DWORD): BOOL;
+var
+  AnsiBuff: AnsiString;
+  AnsiBuffLen: DWORD;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetComputerNameW{TNT-ALLOW GetComputerNameW}(lpBuffer, nSize)
+  else begin
+    SetLength(AnsiBuff, MAX_COMPUTERNAME_LENGTH + 1);
+    AnsiBuffLen := Length(AnsiBuff);
+    Result := GetComputerNameA{TNT-ALLOW GetComputerNameA}(PAnsiChar(AnsiBuff), AnsiBuffLen);
+    if Result then begin
+      SetLength(AnsiBuff, AnsiBuffLen);
+      if (nSize <= AnsiBuffLen) or (Length(AnsiBuff) = 0) then begin
+        nSize := AnsiBuffLen + 1;
+        Result := False;
+      end else begin
+        WStrPLCopy(lpBuffer, AnsiBuff, nSize);
+        nSize := WStrLen(lpBuffer);
+      end;
+    end;
+  end;
+end;
+
+function Tnt_GetUserNameW(lpBuffer: PWideChar; var nSize: DWORD): BOOL;
+var
+  AnsiBuff: AnsiString;
+  AnsiBuffLen: DWORD;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetUserNameW{TNT-ALLOW GetUserNameW}(lpBuffer, nSize)
+  else begin
+    SetLength(AnsiBuff, 255);
+    AnsiBuffLen := Length(AnsiBuff);
+    Result := GetUserNameA{TNT-ALLOW GetUserNameA}(PAnsiChar(AnsiBuff), AnsiBuffLen);
+    if Result then begin
+      SetLength(AnsiBuff, AnsiBuffLen);
+      if (nSize <= AnsiBuffLen) or (Length(AnsiBuff) = 0) then begin
+        nSize := AnsiBuffLen + 1;
+        Result := False;
+      end else begin
+        WStrPLCopy(lpBuffer, AnsiBuff, nSize);
+        nSize := WStrLen(lpBuffer);
+      end;
+    end;
+  end;
+end;
+
+function Tnt_ShellExecuteW(hWnd: HWND; Operation, FileName, Parameters,
+  Directory: PWideChar; ShowCmd: Integer): HINST;
+begin
+  if Win32PlatformIsUnicode then
+    Result := ShellExecuteW{TNT-ALLOW ShellExecuteW}(hWnd, _PWideCharWithNil(WideString(Operation)),
+      FileName, Parameters,
+        Directory, ShowCmd)
+  else begin
+    Result := ShellExecuteA{TNT-ALLOW ShellExecuteA}(hWnd, _PAnsiCharWithNil(AnsiString(Operation)),
+      _PAnsiCharWithNil(AnsiString(FileName)), _PAnsiCharWithNil(AnsiString(Parameters)),
+        _PAnsiCharWithNil(AnsiString(Directory)), ShowCmd)
+  end;
+end;
+
+function Tnt_LoadLibraryW(lpLibFileName: PWideChar): HMODULE;
+begin
+  if Win32PlatformIsUnicode then
+    Result := LoadLibraryW{TNT-ALLOW LoadLibraryW}(lpLibFileName)
+  else
+    Result := LoadLibraryA{TNT-ALLOW LoadLibraryA}(PAnsiChar(AnsiString(lpLibFileName)));
+end;
+
+function Tnt_LoadLibraryExW(lpLibFileName: PWideChar; hFile: THandle; dwFlags: DWORD): HMODULE;
+begin
+  if Win32PlatformIsUnicode then
+    Result := LoadLibraryExW{TNT-ALLOW LoadLibraryExW}(lpLibFileName, hFile, dwFlags)
+  else
+    Result := LoadLibraryExA{TNT-ALLOW LoadLibraryExA}(PAnsiChar(AnsiString(lpLibFileName)), hFile, dwFlags);
+end;
+
+function Tnt_CreateProcessW(lpApplicationName: PWideChar; lpCommandLine: PWideChar;
+  lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
+    bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
+      lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfoW;
+        var lpProcessInformation: TProcessInformation): BOOL;
+var
+  AnsiStartupInfo: TStartupInfoA;
+begin
+  if Win32PlatformIsUnicode then begin
+    Result := CreateProcessW{TNT-ALLOW CreateProcessW}(lpApplicationName, lpCommandLine,
+      lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
+        lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
+  end else begin
+    CopyMemory(@AnsiStartupInfo, @lpStartupInfo, SizeOf(TStartupInfo));
+    AnsiStartupInfo.lpReserved := _PAnsiCharWithNil(AnsiString(lpStartupInfo.lpReserved));
+    AnsiStartupInfo.lpDesktop := _PAnsiCharWithNil(AnsiString(lpStartupInfo.lpDesktop));
+    AnsiStartupInfo.lpTitle := _PAnsiCharWithNil(AnsiString(lpStartupInfo.lpTitle));
+    Result := CreateProcessA{TNT-ALLOW CreateProcessA}(_PAnsiCharWithNil(AnsiString(lpApplicationName)),
+      _PAnsiCharWithNil(AnsiString(lpCommandLine)),
+        lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
+          _PAnsiCharWithNil(AnsiString(lpCurrentDirectory)), AnsiStartupInfo, lpProcessInformation);
+  end;
+end;
+
+function Tnt_GetCurrencyFormatW(Locale: LCID; dwFlags: DWORD; lpValue: PWideChar;
+  lpFormat: PCurrencyFmtW; lpCurrencyStr: PWideChar; cchCurrency: Integer): Integer;
+const
+  MAX_ANSI_BUFF_SIZE = 64; // can a currency string actually be larger?
+var
+  AnsiFormat: TCurrencyFmtA;
+  PAnsiFormat: PCurrencyFmtA;
+  AnsiBuff: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetCurrencyFormatW{TNT-ALLOW GetCurrencyFormatW}(Locale, dwFlags, lpValue,
+        {$IFNDEF FPC} lpFormat {$ELSE} PCurrencyFmt(lpFormat) {$ENDIF},
+        lpCurrencyStr, cchCurrency)
+  else begin
+    if lpFormat = nil then
+      PAnsiFormat := nil
+    else begin
+      ZeroMemory(@AnsiFormat, SizeOf(AnsiFormat));
+      AnsiFormat.NumDigits        := lpFormat.NumDigits;
+      AnsiFormat.LeadingZero      := lpFormat.LeadingZero;
+      AnsiFormat.Grouping         := lpFormat.Grouping;
+      AnsiFormat.lpDecimalSep     := PAnsiChar(AnsiString(lpFormat.lpDecimalSep));
+      AnsiFormat.lpThousandSep    := PAnsiChar(AnsiString(lpFormat.lpThousandSep));
+      AnsiFormat.NegativeOrder    := lpFormat.NegativeOrder;
+      AnsiFormat.PositiveOrder    := lpFormat.PositiveOrder;
+      AnsiFormat.lpCurrencySymbol := PAnsiChar(AnsiString(lpFormat.lpCurrencySymbol));
+      PAnsiFormat := @AnsiFormat;
+    end;
+    SetLength(AnsiBuff, MAX_ANSI_BUFF_SIZE);
+    SetLength(AnsiBuff, GetCurrencyFormatA{TNT-ALLOW GetCurrencyFormatA}(Locale, dwFlags,
+      PAnsiChar(AnsiString(lpValue)), PAnsiFormat, PAnsiChar(AnsiBuff), MAX_ANSI_BUFF_SIZE));
+    Result := _HandleStringLengthResult(cchCurrency, lpCurrencyStr, AnsiBuff, []);
+  end;
+end;
+
+function Tnt_CompareStringW(Locale: LCID; dwCmpFlags: DWORD; lpString1: PWideChar;
+  cchCount1: Integer; lpString2: PWideChar; cchCount2: Integer): Integer;
+var
+  WideStr1, WideStr2: WideString;
+  AnsiStr1, AnsiStr2: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := CompareStringW{TNT-ALLOW CompareStringW}(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2)
+  else begin
+    WideStr1 := _WStr(lpString1, cchCount1);
+    WideStr2 := _WStr(lpString2, cchCount2);
+    if (dwCmpFlags = 0) then begin
+      // binary comparison
+      if WideStr1 < WideStr2 then
+        Result := 1
+      else if WideStr1 = WideStr2 then
+        Result := 2
+      else
+        Result := 3;
+    end else begin
+      AnsiStr1 := WideStr1;
+      AnsiStr2 := WideStr2;
+      Result := CompareStringA{TNT-ALLOW CompareStringA}(Locale, dwCmpFlags,
+        PAnsiChar(AnsiStr1), -1, PAnsiChar(AnsiStr2), -1);
+    end;
+  end;
+end;
+
+function Tnt_CharUpperW(lpsz: PWideChar): PWideChar;
+var
+  AStr: AnsiString;
+  WStr: WideString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := CharUpperW{TNT-ALLOW CharUpperW}(lpsz)
+  else begin
+    if HiWord(Cardinal(lpsz)) = 0 then begin
+      // literal char mode
+      Result := lpsz;
+      if IsWideCharMappableToAnsi(WideChar(lpsz)) then begin
+        AStr := WideChar(lpsz); // single character may be more than one byte
+        CharUpperA{TNT-ALLOW CharUpperA}(PAnsiChar(AStr));
+        WStr := AStr; // should always be single wide char
+        if Length(WStr) = 1 then
+          Result := PWideChar(WStr[1]);
+      end
+    end else begin
+      // null-terminated string mode
+      Result := lpsz;
+      while lpsz^ <> #0 do begin
+        lpsz^ := WideChar(Tnt_CharUpperW(PWideChar(lpsz^)));
+        Inc(lpsz);
+      end;
+    end;
+  end;
+end;
+
+function Tnt_CharUpperBuffW(lpsz: PWideChar; cchLength: DWORD): DWORD;
+var
+  i: integer;
+begin
+  if Win32PlatformIsUnicode then
+    Result := CharUpperBuffW{TNT-ALLOW CharUpperBuffW}(lpsz, cchLength)
+  else begin
+    Result := cchLength;
+    for i := 1 to cchLength do begin
+      lpsz^ := WideChar(Tnt_CharUpperW(PWideChar(lpsz^)));
+      Inc(lpsz);
+    end;
+  end;
+end;
+
+function Tnt_CharLowerW(lpsz: PWideChar): PWideChar;
+var
+  AStr: AnsiString;
+  WStr: WideString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := CharLowerW{TNT-ALLOW CharLowerW}(lpsz)
+  else begin
+    if HiWord(Cardinal(lpsz)) = 0 then begin
+      // literal char mode
+      Result := lpsz;
+      if IsWideCharMappableToAnsi(WideChar(lpsz)) then begin
+        AStr := WideChar(lpsz); // single character may be more than one byte
+        CharLowerA{TNT-ALLOW CharLowerA}(PAnsiChar(AStr));
+        WStr := AStr; // should always be single wide char
+        if Length(WStr) = 1 then
+          Result := PWideChar(WStr[1]);
+      end
+    end else begin
+      // null-terminated string mode
+      Result := lpsz;
+      while lpsz^ <> #0 do begin
+        lpsz^ := WideChar(Tnt_CharLowerW(PWideChar(lpsz^)));
+        Inc(lpsz);
+      end;
+    end;
+  end;
+end;
+
+function Tnt_CharLowerBuffW(lpsz: PWideChar; cchLength: DWORD): DWORD;
+var
+  i: integer;
+begin
+  if Win32PlatformIsUnicode then
+    Result := CharLowerBuffW{TNT-ALLOW CharLowerBuffW}(lpsz, cchLength)
+  else begin
+    Result := cchLength;
+    for i := 1 to cchLength do begin
+      lpsz^ := WideChar(Tnt_CharLowerW(PWideChar(lpsz^)));
+      Inc(lpsz);
+    end;
+  end;
+end;
+
+function Tnt_GetStringTypeExW(Locale: LCID; dwInfoType: DWORD;
+  lpSrcStr: PWideChar; cchSrc: Integer; var lpCharType): BOOL; 
+var
+  AStr: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetStringTypeExW{TNT-ALLOW GetStringTypeExW}(Locale, dwInfoType, lpSrcStr, cchSrc, lpCharType)
+  else begin
+    AStr := _WStr(lpSrcStr, cchSrc);
+    Result := GetStringTypeExA{TNT-ALLOW GetStringTypeExA}(Locale, dwInfoType,
+      PAnsiChar(AStr), -1, lpCharType);
+  end;
+end;
+
+function Win9x_LoadStringW(hInstance: HINST; uID: UINT; lpBuffer: PWideChar; nBufferMax: Integer): Integer;
+// This function originated by the WINE Project.
+//   It was translated to Pascal by Francisco Leong.
+//     It was further modified by Troy Wolbrink.
+var
+  hmem: HGLOBAL;
+  hrsrc: THandle;
+  p: PWideChar;
+  string_num, i: Integer;
+  block: Integer;
+begin
+  Result := 0;
+  // Netscape v3 fix...
+  if (HIWORD(uID) = $FFFF) then begin
+    uID := UINT(-(Integer(uID)));
+  end;
+  // figure block, string_num
+  block := ((uID shr 4) and $FFFF) + 1; // bits 4 - 19, mask out bits 20 - 31, inc by 1
+  string_num := uID and $000F;
+  // get handle & pointer to string block
+  hrsrc := FindResource{TNT-ALLOW FindResource}(hInstance, MAKEINTRESOURCE(block), RT_STRING);
+  if (hrsrc <> 0) then
+  begin
+    hmem := LoadResource(hInstance, hrsrc);
+    if (hmem <> 0) then
+    begin
+      p := LockResource(hmem);
+      // walk the block to the requested string
+      for i := 0 to string_num - 1 do begin
+        p := p + Integer(p^) + 1;
+      end;
+      Result := Integer(p^); { p points to the length of string }
+      Inc(p); { p now points to the actual string }
+      if (lpBuffer <> nil) and (nBufferMax > 0) then
+      begin
+        Result := min(nBufferMax - 1, Result); { max length to copy }
+        if (Result > 0) then begin
+          CopyMemory(lpBuffer, p, Result * sizeof(WideChar));
+        end;
+        lpBuffer[Result] := WideChar(0); { null terminate }
+      end;
+    end;
+  end;
+end;
+
+function Tnt_LoadStringW(hInstance: HINST; uID: UINT; lpBuffer: PWideChar; nBufferMax: Integer): Integer;
+begin
+  if Win32PlatformIsUnicode then
+    Result := Windows.LoadStringW{TNT-ALLOW LoadStringW}(hInstance, uID, lpBuffer, nBufferMax)
+  else
+    Result := Win9x_LoadStringW(hInstance, uID, lpBuffer, nBufferMax);
+end;
+
+function Tnt_InsertMenuItemW(hMenu: HMENU; uItem: DWORD; fByPosition: BOOL; lpmii: TMenuItemInfoW): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := InsertMenuItemW{TNT-ALLOW InsertMenuItemW}(hMenu, uItem, fByPosition,
+        {$IFDEF FPC}@{$ENDIF}lpmii)
+  else begin
+    TMenuItemInfoA(lpmii).dwTypeData := PAnsiChar(AnsiString(lpmii.dwTypeData));
+    Result := InsertMenuItemA{TNT-ALLOW InsertMenuItemA}(hMenu, uItem, fByPosition,
+        {$IFDEF FPC}@{$ENDIF}TMenuItemInfoA(lpmii));
+  end;
+end;
+
+function Tnt_ExtractIconExW(lpszFile: PWideChar; nIconIndex: Integer;
+  var phiconLarge, phiconSmall: HICON; nIcons: UINT): UINT;
+begin
+  if Win32PlatformIsUnicode then
+    Result := ExtractIconExW{TNT-ALLOW ExtractIconExW}(lpszFile,
+      nIconIndex, phiconLarge, phiconSmall, nIcons)
+  else
+    Result := ExtractIconExA{TNT-ALLOW ExtractIconExA}(PAnsiChar(AnsiString(lpszFile)),
+      nIconIndex, phiconLarge, phiconSmall, nIcons);
+end;
+
+function Tnt_ExtractAssociatedIconW(hInst: HINST; lpIconPath: PWideChar;
+  var lpiIcon: Word): HICON;
+begin
+  if Win32PlatformIsUnicode then
+    Result := ExtractAssociatedIconW{TNT-ALLOW ExtractAssociatedIconW}(hInst,
+      lpIconPath, {$IFDEF FPC}@{$ENDIF}lpiIcon)
+  else
+    Result := ExtractAssociatedIconA{TNT-ALLOW ExtractAssociatedIconA}(hInst,
+      PAnsiChar(AnsiString(lpIconPath)), {$IFDEF FPC}@{$ENDIF}lpiIcon)
+end;
+
+function Tnt_GetFileVersionInfoSizeW(lptstrFilename: PWideChar; var lpdwHandle: DWORD): DWORD;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetFileVersionInfoSizeW{TNT-ALLOW GetFileVersionInfoSizeW}(lptstrFilename, lpdwHandle)
+  else
+    Result := GetFileVersionInfoSizeA{TNT-ALLOW GetFileVersionInfoSizeA}(PAnsiChar(AnsiString(lptstrFilename)), lpdwHandle);
+end;
+
+function Tnt_GetFileVersionInfoW(lptstrFilename: PWideChar; dwHandle, dwLen: DWORD;
+  lpData: Pointer): BOOL;
+begin
+  if Win32PlatformIsUnicode then
+    Result := GetFileVersionInfoW{TNT-ALLOW GetFileVersionInfoW}(lptstrFilename, dwHandle, dwLen, lpData)
+  else
+    Result := GetFileVersionInfoA{TNT-ALLOW GetFileVersionInfoA}(PAnsiChar(AnsiString(lptstrFilename)), dwHandle, dwLen, lpData);
+end;
+
+var
+  Last_VerQueryValue_String: WideString;
+
+function Tnt_VerQueryValueW(pBlock: Pointer; lpSubBlock: PWideChar;
+  var lplpBuffer: Pointer; var puLen: UINT): BOOL;
+var
+  AnsiBuff: AnsiString;
+begin
+  if Win32PlatformIsUnicode then
+    Result := VerQueryValueW{TNT-ALLOW VerQueryValueW}(pBlock, lpSubBlock, lplpBuffer, puLen)
+  else begin
+    Result := VerQueryValueA{TNT-ALLOW VerQueryValueA}(pBlock, PAnsiChar(AnsiString(lpSubBlock)), lplpBuffer, puLen);
+    if WideTextPos(VQV_STRINGFILEINFO, lpSubBlock) <> 1 then
+    else begin
+      {  /StringFileInfo, convert ansi result to unicode }
+      SetString(AnsiBuff, PAnsiChar(lplpBuffer), puLen);
+      Last_VerQueryValue_String := AnsiBuff;
+      lplpBuffer := PWideChar(Last_VerQueryValue_String);
+      puLen := Length(Last_VerQueryValue_String);
+    end;
+  end;
+end;
+
+//---------------------------------------------------------------------------------------
+//  Wide functions from Shell32.dll should be loaded dynamically (no stub on early Win95)
+//---------------------------------------------------------------------------------------
+
+type
+  TSHFileOperationW = function(var lpFileOp: TSHFileOpStructW): Integer; stdcall;
+  TSHBrowseForFolderW = function(var lpbi: TBrowseInfoW): PItemIDList; stdcall;
+  TSHGetPathFromIDListW = function(pidl: PItemIDList; pszPath: PWideChar): BOOL; stdcall;
+  TSHGetFileInfoW = function(pszPath: PWideChar; dwFileAttributes: DWORD;
+    var psfi: TSHFileInfoW; cbFileInfo, uFlags: UINT): DWORD; stdcall;
+
+var
+  Safe_SHFileOperationW: TSHFileOperationW = nil;
+  Safe_SHBrowseForFolderW: TSHBrowseForFolderW = nil;
+  Safe_SHGetPathFromIDListW: TSHGetPathFromIDListW = nil;
+  Safe_SHGetFileInfoW: TSHGetFileInfoW = nil;
+
+var Shell32DLL: HModule = 0;
+
+procedure LoadWideShell32Procs;
+begin
+  if Shell32DLL = 0 then begin
+    Shell32DLL := WinCheckH(Tnt_LoadLibraryW('shell32.dll'));
+    Safe_SHFileOperationW := WinCheckP(GetProcAddress(Shell32DLL, 'SHFileOperationW'));
+    Safe_SHBrowseForFolderW := WinCheckP(GetProcAddress(Shell32DLL, 'SHBrowseForFolderW'));
+    Safe_SHGetPathFromIDListW := WinCheckP(GetProcAddress(Shell32DLL, 'SHGetPathFromIDListW'));
+    Safe_SHGetFileInfoW := WinCheckP(GetProcAddress(Shell32DLL, 'SHGetFileInfoW'));
+  end;
+end;
+
+function Tnt_SHFileOperationW(var lpFileOp: TSHFileOpStructW): Integer;
+var
+  AnsiFileOp: TSHFileOpStructA;
+  MapCount: Integer;
+  PAnsiMap: PSHNameMappingA;
+  PWideMap: PSHNameMappingW;
+  OldPath: WideString;
+  NewPath: WideString;
+  i: integer;
+begin
+  if Win32PlatformIsUnicode then begin
+    LoadWideShell32Procs;
+    Result := Safe_SHFileOperationW(lpFileOp);
+  end else begin
+    AnsiFileOp := TSHFileOpStructA(lpFileOp);
+    // convert PChar -> PWideChar
+    if lpFileOp.pFrom = nil then
+      AnsiFileOp.pFrom := nil
+    else
+      AnsiFileOp.pFrom := PAnsiChar(AnsiString(ExtractStringArrayStr(lpFileOp.pFrom)));
+    if lpFileOp.pTo = nil then
+      AnsiFileOp.pTo := nil
+    else
+      AnsiFileOp.pTo := PAnsiChar(AnsiString(ExtractStringArrayStr(lpFileOp.pTo)));
+    AnsiFileOp.lpszProgressTitle := PAnsiChar(AnsiString(lpFileOp.lpszProgressTitle));
+    Result := SHFileOperationA{TNT-ALLOW SHFileOperationA}(
+        {$IFDEF FPC}@{$ENDIF}AnsiFileOp);
+    // return struct results
+    lpFileOp.fAnyOperationsAborted := AnsiFileOp.fAnyOperationsAborted;
+    lpFileOp.hNameMappings := nil;
+    if (AnsiFileOp.hNameMappings <> nil)
+    and ((FOF_WANTMAPPINGHANDLE and AnsiFileOp.fFlags) <> 0) then begin
+      // alloc mem
+      MapCount := PSHNameMappingHeaderA(AnsiFileOp.hNameMappings).cNumOfMappings;
+      lpFileOp.hNameMappings :=
+        AllocMem(SizeOf({hNameMappings}Cardinal) + SizeOf(TSHNameMappingW) * MapCount);
+      PSHNameMappingHeaderW(lpFileOp.hNameMappings).cNumOfMappings := MapCount;
+      // init pointers
+      PAnsiMap := PSHNameMappingHeaderA(AnsiFileOp.hNameMappings).lpNM;
+      PWideMap := PSHNameMappingHeaderW(lpFileOp.hNameMappings).lpNM;
+      for i := 1 to MapCount do begin
+        // old path
+        OldPath := Copy(PAnsiMap.pszOldPath, 1, PAnsiMap.cchOldPath);
+        PWideMap.pszOldPath := WStrNew(PWideChar(OldPath));
+        PWideMap.cchOldPath := WStrLen(PWideMap.pszOldPath);
+        // new path
+        NewPath := Copy(PAnsiMap.pszNewPath, 1, PAnsiMap.cchNewPath);
+        PWideMap.pszNewPath := WStrNew(PWideChar(NewPath));
+        PWideMap.cchNewPath := WStrLen(PWideMap.pszNewPath);
+        // next record
+        Inc(PAnsiMap);
+        Inc(PWideMap);
+      end;
+    end;
+  end;
+end;
+
+procedure Tnt_SHFreeNameMappings(hNameMappings: THandle);
+var
+  i: integer;
+  MapCount: Integer;
+  PWideMap: PSHNameMappingW;
+begin
+  if Win32PlatformIsUnicode then
+    SHFreeNameMappings{TNT-ALLOW SHFreeNameMappings}(hNameMappings)
+  else begin
+    // free strings
+    MapCount := PSHNameMappingHeaderW(hNameMappings).cNumOfMappings;
+    PWideMap := PSHNameMappingHeaderW(hNameMappings).lpNM;
+    for i := 1 to MapCount do begin
+      WStrDispose(PWideMap.pszOldPath);
+      WStrDispose(PWideMap.pszNewPath);
+      Inc(PWideMap);
+    end;
+    // free struct
+    FreeMem(Pointer(hNameMappings));
+  end;
+end;
+
+function Tnt_SHBrowseForFolderW(var lpbi: TBrowseInfoW): PItemIDList;
+var
+  AnsiInfo: TBrowseInfoA;
+  AnsiBuffer: array[0..MAX_PATH] of AnsiChar;
+begin
+  if Win32PlatformIsUnicode then begin
+    LoadWideShell32Procs;
+    Result := Safe_SHBrowseForFolderW(lpbi);
+  end else begin
+    AnsiInfo := TBrowseInfoA(lpbi);
+    AnsiInfo.lpszTitle := PAnsiChar(AnsiString(lpbi.lpszTitle));
+    if lpbi.pszDisplayName <> nil then
+      AnsiInfo.pszDisplayName := AnsiBuffer;
+    Result := SHBrowseForFolderA{TNT-ALLOW SHBrowseForFolderA}(
+        {$IFDEF FPC}@{$ENDIF}AnsiInfo);
+    if lpbi.pszDisplayName <> nil then
+      WStrPCopy(lpbi.pszDisplayName, AnsiInfo.pszDisplayName);
+    lpbi.iImage := AnsiInfo.iImage;
+  end;
+end;
+
+function Tnt_SHGetPathFromIDListW(pidl: PItemIDList; pszPath: PWideChar): BOOL;
+var
+  AnsiPath: AnsiString;
+begin
+  if Win32PlatformIsUnicode then begin
+    LoadWideShell32Procs;
+    Result := Safe_SHGetPathFromIDListW(pidl, pszPath);
+  end else begin
+    SetLength(AnsiPath, MAX_PATH);
+    Result := SHGetPathFromIDListA{TNT-ALLOW SHGetPathFromIDListA}(pidl, PAnsiChar(AnsiPath));
+    if Result then
+      WStrPCopy(pszPath, PAnsiChar(AnsiPath))
+  end;
+end;
+
+function Tnt_SHGetFileInfoW(pszPath: PWideChar; dwFileAttributes: DWORD;
+  var psfi: TSHFileInfoW; cbFileInfo, uFlags: UINT): DWORD;
+var
+  SHFileInfoA: TSHFileInfoA;
+begin
+  if Win32PlatformIsUnicode then begin
+    LoadWideShell32Procs;
+    Result := Safe_SHGetFileInfoW(pszPath, dwFileAttributes, psfi, cbFileInfo, uFlags)
+  end else begin
+    Result := SHGetFileInfoA{TNT-ALLOW SHGetFileInfoA}(PAnsiChar(AnsiString(pszPath)),
+      dwFileAttributes, SHFileInfoA, SizeOf(TSHFileInfoA), uFlags);
+    // update pfsi...
+    ZeroMemory(@psfi, SizeOf(TSHFileInfoW));
+    psfi.hIcon := SHFileInfoA.hIcon;
+    psfi.iIcon := SHFileInfoA.iIcon;
+    psfi.dwAttributes := SHFileInfoA.dwAttributes;
+    WStrPLCopy(psfi.szDisplayName, SHFileInfoA.szDisplayName, MAX_PATH);
+    WStrPLCopy(psfi.szTypeName, SHFileInfoA.szTypeName, 80);
+  end;
+end;
+
+
+function Tnt_Is_IntResource(ResStr: LPCWSTR): Boolean;
+begin
+  Result := HiWord(Cardinal(ResStr)) = 0;
+end;
+
+function LANGIDFROMLCID(lcid: LCID): WORD;
+begin
+  Result := LoWord(lcid);
+end;
+
+function MAKELANGID(usPrimaryLanguage, usSubLanguage: WORD): WORD;
+begin
+  Result := (usSubLanguage shl 10) or usPrimaryLanguage;
+end;
+
+function MAKELCID(wLanguageID: WORD; wSortID: WORD = SORT_DEFAULT): LCID;
+begin
+  Result := MakeLong(wLanguageID, wSortID);
+end;
+
+function PRIMARYLANGID(lgid: WORD): WORD;
+begin
+  Result := lgid and $03FF;
+end;
+
+function SORTIDFROMLCID(lcid: LCID): WORD;
+begin
+  Result := HiWord(lcid);
+end;
+
+function SUBLANGID(lgid: WORD): WORD;
+begin
+  Result := lgid shr 10;
+end;
+
+initialization
+
+finalization
+  if Shell32DLL <> 0 then
+    FreeLibrary(Shell32DLL);
+
+end.
diff --git a/songmanagement/src/lib/bass/bass.chm b/songmanagement/src/lib/bass/bass.chm
new file mode 100644
index 00000000..8071fb0b
Binary files /dev/null and b/songmanagement/src/lib/bass/bass.chm differ
diff --git a/songmanagement/src/lib/bass/bass.txt b/songmanagement/src/lib/bass/bass.txt
new file mode 100644
index 00000000..381519e1
--- /dev/null
+++ b/songmanagement/src/lib/bass/bass.txt
@@ -0,0 +1,1734 @@
+BASS 2.4
+Copyright (c) 1999-2009 Un4seen Developments Ltd. All rights reserved.
+
+Files that you should have found in the BASS package
+====================================================
+Win32 version
+-------------
+BASS.TXT        This file
+BASS.DLL        The BASS module
+BASS.CHM        BASS documentation
+MP3-FREE
+  BASS.DLL        BASS module using the Windows MP3 decoder
+C\              C/C++ API and examples...
+  BASS.H          BASS C/C++ header file
+  BASS.LIB        BASS import library
+  BASS.DSW        Visual C++ workspace for examples
+  MAKEFILE        Makefile for all examples
+  MAKEFILE.IN     Makefile helper macros
+  3DTEST\         3D/EAX example
+    3DTEST.C
+    3DTEST.RC
+    3DTEST.DSP
+    MAKEFILE
+  BASSTEST\       Simple playback example
+    BASSTEST.C
+    BASSTEST.RC
+    BASSTEST.DSP
+    MAKEFILE
+  CONTEST\        Console example
+    CONTEST.C
+    CONTEST.DSP
+    MAKEFILE
+  CUSTLOOP\       Custom looping example
+    CUSTLOOP.C
+    CUSTLOOP.DSP
+    MAKEFILE
+  DSPTEST\        DSP example
+    DSPTEST.C
+    DSPTEST.RC
+    DSPTEST.DSP
+    MAKEFILE
+  FXTEST\         DX8 effect example
+    FXTEST.C
+    FXTEST.RC
+    FXTEST.DSP
+    MAKEFILE
+  LIVEFX\         Full-duplex example
+    LIVEFX.C
+    LIVEFX.RC
+    LIVEFX.DSP
+    MAKEFILE
+  LIVESPEC\       "Live" version of spectrum analyser example
+    LIVESPEC.C
+    LIVESPEC.DSP
+    MAKEFILE
+  MULTI\          Multiple device example
+    MULTI.C
+    MULTI.RC
+    MULTI.DSP
+    MAKEFILE
+  NETRADIO\       Internet streaming example
+    NETRADIO.C
+    NETRADIO.RC
+    NETRADIO.DSP
+    MAKEFILE
+  PLUGINS\        Plugins example
+    PLUGINS.C
+    PLUGINS.RC
+    PLUGINS.DSP
+    MAKEFILE
+  RECTEST\        Recording example
+    RECTEST.C
+    RECTEST.RC
+    RECTEST.DSP
+    MAKEFILE
+  SPEAKERS\       Multi-speaker example
+    SPEAKERS.C
+    SPEAKERS.RC
+    SPEAKERS.DSP
+    MAKEFILE
+  SPECTRUM\       Spectrum analyser example
+    SPECTRUM.C
+    SPECTRUM.DSP
+    MAKEFILE
+  SYNTH\          Synth example
+    SYNTH.C
+    SYNTH.DSP
+    MAKEFILE
+  WRITEWAV\       WAVE writer example
+    WRITEWAV.C
+    WRITEWAV.DSP
+    MAKEFILE
+  BIN\            Precompiled examples
+    3DTEST.EXE
+    BASSTEST.EXE
+    CONTEST.EXE
+    CUSTLOOP.EXE
+    DSPTEST.EXE
+    FXTEST.EXE
+    LIVEFX.EXE
+    LIVESPEC.EXE
+    MULTI.EXE
+    NETRADIO.EXE
+    RECTEST.EXE
+    SPEAKERS.EXE
+    SPECTRUM.EXE
+    SYNTH.EXE
+    WRITEWAV.EXE
+VB\             Visual Basic API and examples...
+  BASS.BAS        BASS Visual Basic module
+  3DTEST\         3D/EAX example
+    PRJ3DTEST.VBP
+    PRJ3DTEST.FRM
+    PRJDEVICE.FRM
+  BASSTEST\       Simple playback example
+    PRJBASSTEST.VBP
+    FRMBASSTEST.FRM
+  CUSTLOOP\       Custom looping example
+    PRJCUSTLOOP.VBP
+    FRMCUSTLOOP.FRM
+    MODCUSTLOOP.BAS
+  DSPTEST\        DSP example
+    PRJDSPTEST.VBP
+    FRMDSPTEST.FRM
+    MODDSPTEST.BAS
+  FXTEST\         DX8 effect example
+    PRJFXTEST.VBP
+    FRMFXTEST.FRM
+  LIVEFX\         Full-duplex example
+    PRJLIVEFX.VBP
+    FRMLIVEFX.FRM
+    MODLIVEFX.BAS
+  LIVESPEC\       "Live" version of spectrum analyser example
+    PRJLIVESPEC.VBP
+    FRMLIVESPEC.FRM
+    MODLIVESPEC.BAS
+  MULTI\          Multiple device example
+    PRJMULTI.VBP
+    FRMMULTI.FRM
+    FRMDEVICE.FRM
+  NETRADIO\       Internet streaming example
+    PRJNETRADIO.VBP
+    FRMNETRADIO.FRM
+    MODNETRADIO.BAS
+    CLSFILEIO.CLS
+  PLUGINS\        Plugins example
+    PRJPLUGINS.VBP
+    FRMPLUGINS.FRM
+  RECTEST\        Recording example
+    PRJRECTEST.VBP
+    FRMRECTEST.FRM
+    MODRECTEST.BAS
+  SPEAKERS\       Multi-speaker example
+    PRJSPEAKERS.VBP
+    FRMSPEAKERS.FRM
+  SPECTRUM\       Spectrum analyser example
+    PRJSPECTRUM.VBP
+    FRMSPECTRUM.FRM
+    MODSPECTRUM.BAS
+  SYNTH\          Synth example
+    PRJSYNTH.VBP
+    FRMSYNTH.FRM
+    MODSYNTH.BAS
+  WRITEWAV\       WAVE writer example
+    PRJWRITEWAVE.VBP
+    PRJWRITEWAVE.FRM
+  MEMORY\         Playing from memory example by Jobnik
+    PRJMEMORY.VBP
+    FRMMEMORY.FRM
+    SYNCTEST.BAS
+    CBASS_TIME.CLS
+DELPHI\         Delphi API and examples...
+  BASS.PAS        BASS Delphi unit
+  3DTEST\         3D/EAX example
+    D3TEST.DPR
+    DTMAIN.PAS
+    DTMAIN.DFM
+    DTSELECT.PAS
+    DTSELECT.DFM
+  BASSTEST\       Simple playback example
+    BASSTEST.DPR
+    BTMAIN.PAS
+    BTMAIN.DFM
+  CONTEST\        Console example
+    CONTEST.DPR
+  CUSTLOOP\       Custom looping example
+    CUSTLOOP.DPR
+    UNIT1.PAS
+    UNIT1.DFM
+  DSPTEST\        DSP example
+    DSPTEST.DPR
+    DTMAIN.PAS
+    DTMAIN.DFM
+  FXTEST\         DX8 effect example
+    FXTEST.DPR
+    TEST.PAS
+    TEST.DFM
+  LIVEFX\         Full-duplex example
+    LIVEFX.DPR
+    UNIT1.PAS
+    UNIT1.DFM
+  LIVESPEC\       "Live" version of spectrum analyser example
+    LIVESPEC.DPR
+  MULTI\          Multiple device example
+    MULTI.DPR
+    UNIT1.PAS
+    UNIT1.DFM
+    UNIT2.PAS
+    UNIT2.DFM
+  NETRADIO\       Internet streaming example
+    NETRADIO.DPR
+    UNIT1.PAS
+    UNIT1.DFM
+  PLUGINS\        Plugins example
+    PLUGINS.DPR
+    UNIT1.PAS
+    UNIT1.DFM
+  RECORDTEST\     Recording example
+    RECORDTEST.DPR
+    UNIT1.PAS
+    UNIT1.DFM
+  SAMPLEVIS\      Visualisation example
+    SAMPLEVIS.DPR
+    MAIN.PAS
+    MAIN.DFM
+    SPECTRUM_VIS.PAS
+    CIRCLE_VIS.PAS
+    OSC_VIS.PAS
+    COMMONTYPES.PAS
+  SPEAKERS\       Multi-speaker example
+    SPEAKERS.DPR
+    UNIT1.PAS
+    UNIT1.DFM
+  SPECTRUM\       Spectrum analyser example
+    SPECTRUM.DPR
+    UNIT1.PAS
+    COMMON.INC
+  STREAMTEST\     User stream example
+    STREAMTEST.DPR
+    STMAIN.PAS
+    STMAIN.DFM
+  WRITEWAV\       WAVE writer example
+    WRITEWAV.DPR
+    UNITMAIN.PAS
+    UNITMAIN.DFM
+  DYNAMIC\        Dynamic-loading Delphi API
+    DYNAMIC_BASS.PAS  Dynamic-loading Delphi unit
+MASM\           MASM API and examples...
+  BASS.INC        BASS MASM include file
+  PLAYER\         Example MOD player
+    PLAYER.EXE
+    PLAYER.ASM
+    RSRC.RC
+    TOOLBAR.BMP
+    COMPILE.BAT
+
+NOTE: To run the example EXEs, first you will have to copy BASS.DLL into the
+      same directory as them.
+
+NOTE: To avoid unnecessary bloatage, the BASS DLLs are not digitally signed.
+      Signed versions are available on request (email: bass@un4seen.com).
+
+MacOSX version
+--------------
+BASS.TXT        This file
+LIBBASS.DYLIB   The BASS module
+BASS.CHM        BASS documentation
+CHMOX.APP       CHM file viewer
+BASS.H          BASS C/C++ header file
+MAKEFILE        Makefile for all examples
+MAKEFILE.IN     Makefile helper macros
+MP3-FREE
+  LIBBASS.DYLIB   BASS module using the OSX MP3 decoder
+3DTEST\         3D example
+  3DTEST.C
+  MAKEFILE
+  3DTEST.NIB
+BASSTEST\       Simple playback example
+  BASSTEST.C
+  MAKEFILE
+  BASSTEST.NIB
+CONTEST\        Console example
+  CONTEST.C
+  MAKEFILE
+CUSTLOOP\       Custom looping example
+  CUSTLOOP.C
+  MAKEFILE
+DSPTEST\        DSP example
+  DSPTEST.C
+  MAKEFILE
+  DSPTEST.NIB
+FXTEST\         DX8 effect example
+  FXTEST.C
+  MAKEFILE
+  FXTEST.NIB
+LIVESPEC\       "Live" version of spectrum analyser example
+  LIVESPEC.C
+  MAKEFILE
+MULTI\          Multiple device example
+  MULTI.C
+  MAKEFILE
+  MULTI.NIB
+NETRADIO\       Internet streaming example
+  NETRADIO.C
+  MAKEFILE
+  NETRADIO.NIB
+PLUGINS\        Plugins example
+  PLUGINS.C
+  MAKEFILE
+  PLUGINS.NIB
+RECTEST\        Recording example
+  RECTEST.C
+  MAKEFILE
+  RECTEST.NIB
+SPEAKERS\       Multi-speaker example
+  SPEAKERS.C
+  MAKEFILE
+  SPEAKERS.NIB
+SPECTRUM\       Spectrum analyser example
+  SPECTRUM.C
+  MAKEFILE
+WRITEWAV\       WAVE writer example
+  WRITEWAV.C
+  MAKEFILE
+
+
+What's the point?
+=================
+BASS is an audio library for use in Windows and MacOSX software. Its
+purpose is to provide the most powerful and efficient (yet easy to use),
+sample, stream, MOD music, and recording functions. All in a tiny DLL,
+under 100KB in size.
+
+See the documentation for descriptions of all the BASS functions. You
+should also look at the included example program source-codes for some
+examples of how to use BASS in your own programs.
+
+
+Requirements
+============
+Win32 version
+-------------
+BASS requires DirectX 3 or above for output. BASS does not require that a
+soundcard with DirectSound/DirectSound3D hardware accelerated drivers is
+installed, but it does improve performance if there is one. BASS also takes
+advantage of MMX, which improves the performance of the MOD music playback.
+
+MacOSX version
+--------------
+OSX 10.3 or above is recommended. BASS uses CoreAudio for output, so there
+are no special library/driver requirements. BASS supports both PowerPC and
+Intel Macs.
+
+
+Main Features
+=============
+* Samples
+  supports WAV/AIFF/MP3/MP2/MP1/OGG and custom generated samples
+
+* Sample streams
+  stream any sample data in 8/16/32 bit, with both "push" and "pull" systems
+
+* File streams
+  MP3/MP2/MP1/OGG/WAV/AIFF file streaming
+
+* Internet file streaming
+  stream files from the internet, including Shout/Icecast
+
+* User file streaming
+  stream files from anywhere using any delivery method
+
+* Multi-channel streaming
+  support for more than plain stereo, including multi-channel OGG/WAV/AIFF files
+
+* MOD music
+  uses the same engine as XMPlay = best accuracy, speed, and quality
+
+* MO3 music
+  MP3/OGG compressed MOD music
+
+* Add-on system
+  support for more formats is available via add-ons (aka plugins)
+
+* Multiple outputs
+  simultaneously use multiple soundcards, and move channels between them
+
+* Recording
+  flexible recording system, with support for multiple devices
+
+* Decode without playback
+  streams and MOD musics can be outputted in any way you want
+
+* Speaker assignment
+  assign streams and MOD musics to specific speakers
+
+* High precision synchronization
+  synchronize events in your software to the streams and MOD musics
+
+* DirectX 8 effects
+  chorus/compressor/distortion/echo/flanger/gargle/parameq/reverb
+
+* User defined DSP functions
+  custom effects may be applied to musics and streams
+
+* 32 bit floating-point decoding and processing
+  floating-point stream/music decoding, DSP, FX, and recording
+
+* 3D sound
+  play samples/streams/musics in any 3D position, with EAX support
+
+* Small
+  BASS is under 100KB (on Windows), so won't bloat your distribution
+
+
+Using BASS
+==========
+There is no guarantee that all future BASS versions will be compatible
+with all previous versions, so your program should use BASS_GetVersion
+to check the version that is loaded. This also means that you should
+put the BASS module in the same directory as your executable (not just
+somewhere in the path), to avoid the possibility of a wrong version being
+loaded.
+
+If you are updating your software from a previous BASS version, then
+you should check the "History" section (below), to see if any of the
+functions that you are using have been affected by a change.
+
+Win32 version
+-------------
+C/C++, Visual Basic, Delphi and MASM APIs are provided, to use BASS with
+another language you'll first have to convert the header file. Or, as a
+last resort, you could use LoadLibrary and GetProcAddress.
+
+The downside is that you have to manually import each function that you
+use, with the GetProcAddress function. But it has been made a lot simpler
+to import BASS this way by the use of the BASSDEF #define. Here's a small
+example:
+
+#define BASSDEF(f) (WINAPI *f) // define the functions as pointers
+#include "bass.h"
+...
+HINSTANCE bass=LoadLibrary("BASS.DLL"); // load BASS
+BASS_Init=GetProcAddress(bass,"BASS_Init"); // get BASS_Init
+BASS_Init(-1,44100,0,hWnd,NULL); // call BASS_Init
+
+To use BASS with Borland C++ Builder, you'll first have to create a
+Borland C++ Builder import library for it. This is done by using the
+IMPLIB tool that comes with Borland C++ Builder. Simply execute this:
+
+	IMPLIB BASSBCB.LIB BASS.DLL
+
+... and then use BASSBCB.LIB in your projects to import BASS.
+
+To use BASS with LCC-Win32, you'll first have to create a compatible
+import library for it. This is done by using the PEDUMP and BUILDLIB
+tools that come with LCC-Win32. Run these 2 commands:
+
+	PEDUMP /EXP BASS.LIB > BASSLCC.EXP
+	BUILDLIB BASSLCC.EXP BASSLCC.LIB
+
+... and then use BASSLCC.LIB in your projects to import BASS.
+
+For the BASS functions that return strings (char*), VB users should use
+the VBStrFromAnsiPtr function to convert the returned pointer into a VB
+string.
+
+MacOSX version
+--------------
+A separate "LIB" file is not required for OSX. Using XCode, you can simply
+add the DYLIB file to the project. Or using a makefile, you can build your
+programs like this, for example:
+
+	gcc yoursource -L. -lbass -o yourprog
+
+The LIBBASS.DYLIB file must be put in the same directory as the executable
+(it can't just be somewhere in the path). See the example makefiles.
+
+LIBBASS.DYLIB is a universal binary, with support for both PowerPC and
+Intel Macs. If you want PowerPC-only or Intel-only versions, the included
+makefile can create them for you, by typing "make ppc" or "make i386". It
+will also process any BASS add-ons placed in the same directory.
+
+
+Latest Version
+==============
+The latest version of BASS can always be found at the BASS website:
+
+	www.un4seen.com
+
+
+Licence
+=======
+BASS is free for non-commercial use. If you are a non-commercial entity
+(eg. an individual) and you are not charging for your product, and the
+product has no other commercial purpose, then you can use BASS in it
+for free. If you wish to use BASS in commercial products, then please
+also see the next section.
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, BASS IS PROVIDED
+"AS IS", WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND/OR FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS SHALL NOT BE HELD
+LIABLE FOR ANY DAMAGE THAT MAY RESULT FROM THE USE OF BASS. YOU USE
+BASS ENTIRELY AT YOUR OWN RISK.
+
+Usage of BASS indicates that you agree to the above conditions.
+
+All trademarks and other registered names contained in the BASS
+package are the property of their respective owners.
+
+Commercial licensing
+--------------------
+BASS is available for use in your commercial products. The licence
+types available are as follows:
+
+SHAREWARE: Allows the usage of BASS in an unlimited number of your
+shareware products, which must sell for no more than 40 Euros each.
+If you are an individual (not a corporation) making and selling your
+own software (and its price is within the limit), this is the licence
+for you.
+
+SINGLE COMMERCIAL: Allows the usage of BASS in a single commercial
+product.
+
+UNLIMITED COMMERCIAL: Allows the usage of BASS in an unlimited number
+of your commercial products. This licence is on a per site basis. So
+if your company has two sites that use BASS, then two licences are
+required.
+
+Please note the products must be end-user products, eg. not components
+used by other products. 
+
+These licences only cover your own software, not the publishing of
+other's software. If you publish other's software, its developers (or
+the software itself) will need to be licensed to use BASS.
+
+These licences are on a per-platform basis, with reductions available
+when licensing for both platforms. In all cases there are no royalties
+to pay, and you can use future BASS updates without further cost. One
+licence covers one person or entity and is not transferable.
+
+These licences do not allow reselling/sublicensing of BASS. For example,
+if a product is a development system, the users of said product are not
+licensed to use BASS in their productions; they will need their own
+licences.
+
+If the standard licences do not meet your requirements, or if you have
+any questions, please get in touch (email: bass@un4seen.com).
+
+Visit the BASS website for the latest pricing:
+
+	www.un4seen.com
+
+MP3
+---
+MP3 technology is patented, and Thomson license the use of their and
+Fraunhofer's patents. The inclusion of an MP3 decoder (eg. BASS) in a
+commercial product requires an MP3 patent licence. Contact Thomson for
+details:
+
+	www.mp3licensing.com
+
+Alternatively, the "MP3-FREE" BASS version does not include its own MP3
+decoder but instead makes use of the operating system's already licensed
+decoder.
+
+NOTE: When using the OS's MP3 decoder, BASS still does the file handling
+      so all the usual features are still supported, including streaming,
+      tag reading, pre-scanning, gapless playback, etc...
+
+
+History
+=======
+These are the major (and not so major) changes at each version stage.
+There are of course bug fixes and other little improvements made along
+the way too! To make upgrading simpler, all functions affected by a
+change to the BASS interface are listed.
+
+2.4.5 - 18/12/2009
+------------------
+* Support for little-endian AIFF files
+	BASS_StreamCreateFile/User/Url
+	BASS_SampleLoad
+* Support for 64-bit floating-point WAVE/AIFF files
+	BASS_StreamCreateFile/User/Url
+	BASS_SampleLoad
+* Input volume retrieval failure results in a reading of -1 instead of 1
+	BASS_RecordGetInput
+	RECTEST example updated
+* Input volume support on OSX
+	BASS_RecordSetInput
+	BASS_RecordGetInput
+	RECTEST example updated
+* Fix for deferred input settings on Vista
+	BASS_RecordSetInput
+* Windows MP3 codec given preference over other installed MP3 codecs (MP3-FREE version)
+	BASS_StreamCreateFile/User/Url
+	BASS_SampleLoad
+
+2.4.4 - 13/10/2009
+------------------
+* RIFF/BWF "radio traffic" tag retrieval
+	BASS_TAG_RIFF_CART (BASS_ChannelGetTags type)
+	TAG_CART structure
+* Support for ID3v2 tags in RIFF/WAVE/AIFF files ("ID3 " chunk)
+	BASS_TAG_ID3V2 (BASS_ChannelGetTags type)
+* Pushed fractional samples are refused rather than discarded
+	BASS_StreamPutData
+* DX8 effect emulation on OSX
+	BASS_FX_DX8_CHORUS/DISTORTION/ECHO/FLANGER/PARAMEQ/REVERB (BASS_ChannelSetFX types)
+	FXTEST example added
+* UTF-16 support on OSX
+	BASS_UNICODE (BASS_StreamCreateFile/SampleLoad/MusicLoad/PluginLoad flag)
+
+2.4.3 - 8/5/2009
+----------------
+* MOD order list retrieval
+	BASS_TAG_MUSIC_ORDERS (BASS_ChannelGetTags type)
+* Support for ID3v2 tags in RIFF/WAVE files ("id3 " chunk)
+	BASS_TAG_ID3V2 (BASS_ChannelGetTags type)
+* Improved position reporting precision on Vista
+	BASS_ChannelGetPosition
+* Length retrieval when streaming in blocks (BASS_STREAM_BLOCK)
+	BASS_ChannelGetLength
+* Support for CoreAudio codecs on OSX
+	BASS_StreamCreateFile/User
+	BASS_SampleLoad
+	BASS_TAG_CA_CODEC (BASS_ChannelGetTags type)
+	TAG_CA_CODEC structure
+* 3D algorithm option support on OSX
+	BASS_CONFIG_3DALGORITHM (BASS_SetConfig option)
+
+2.4.2 - 18/9/2008
+-----------------
+* RF64 support
+	BASS_StreamCreateFile/User
+* RIFF/BWF "Broadcast Audio Extension" tag retrieval
+	BASS_TAG_RIFF_BEXT (BASS_ChannelGetTags type)
+	TAG_BEXT structure
+* ID3v1 tag structure
+	TAG_ID3 structure
+* Multiple simultaneous recordings per device on Vista & OSX (as on XP)
+	BASS_RecordStart
+* DX8 effect parameter defaults updated/corrected in documentation
+
+2.4 - 2/4/2008
+--------------
+* "Push" streaming
+	STREAMPROC_PUSH (BASS_StreamCreate "proc")
+	BASS_StreamPutData
+	LIVEFX and MULTI examples updated
+* "Push" buffered file streaming
+	STREAMFILE_BUFFERPUSH (BASS_StreamCreateFileUser system)
+	BASS_StreamPutFileData
+* STREAMFILEPROC replaced by table of callbacks for each file operation
+	BASS_FILEPROCS (FILECLOSEPROC/FILELENPROC/FILEREADPROC/FILESEEKPROC)
+	STREAMFILEPROC *removed*
+* 64-bit file positioning
+	BASS_SampleLoad
+	BASS_MusicLoad
+	BASS_StreamCreateFile
+	BASS_StreamGetFilePosition
+* File buffer level retrieval
+	BASS_FILEPOS_BUFFER (BASS_StreamGetFilePosition mode)
+* Sinc interpolated MOD music mixing
+	BASS_MUSIC_SINCINTER (BASS_MusicLoad flag)
+* MO3 2.4 support
+	BASS_MusicLoad
+* MOD orders positioning incorporated into channel functions
+	BASS_ChannelGetLength
+	BASS_ChannelSetPosition
+	BASS_ChannelGetPosition
+	BASS_MusicGetOrderPosition *removed*
+	BASS_MusicGetOrders *removed*
+* Channel attribute functions consolidated
+	BASS_ChannelSetAttribute
+	BASS_ChannelGetAttribute
+	BASS_ChannelSlideAttribute
+	BASS_ChannelIsSliding
+	BASS_ChannelSetAttributes *removed*
+	BASS_ChannelGetAttributes *removed*
+	BASS_ChannelSlideAttributes *removed*
+	BASS_ChannelSetEAXMix *removed*
+	BASS_ChannelGetEAXMix *removed*
+	BASS_MusicSetAttribute *removed*
+	BASS_MusicGetAttribute *removed*
+* Floating-point volume and panning
+	BASS_SetVolume
+	BASS_GetVolume
+	BASS_RecordSetInput
+	BASS_RecordGetInput
+	BASS_ATTRIB_PAN/VOL (BASS_ChannelGet/Set/SlideAttribute options)
+	BASS_ATTRIB_MUSIC_VOL_CHAN/INST (BASS_ChannelGet/Set/SlideAttribute options)
+	BASS_SAMPLE (volume/pan/outvol members)
+	BASS_CONFIG_MAXVOL *removed*
+	BASSTEST and RECTEST examples updated
+* Output device volume control on Vista (as on other OS)
+	BASS_SetVolume
+	BASS_GetVolume
+* Multiple update threads
+	BASS_CONFIG_UPDATETHREADS
+	BASSTEST example updated
+* Global volume range increased to 10000
+	BASS_CONFIG_GVOL_SAMPLE/STREAM/MUSIC (BASS_SetConfig options)
+	BASSTEST example updated
+* Setting and retrieving of a sample's data
+	BASS_SampleSetData
+	BASS_SampleGetData
+	BASS_SampleCreate
+	BASS_SampleCreateDone *removed*
+* Channel flag setting mask
+	BASS_ChannelFlags
+	BASS_ChannelSetFlags *removed*
+	SPEAKERS example updated
+* 256 sample FFT
+	BASS_DATA_FFT256 (BASS_ChannelGetData flag)
+* Channel locking to prevent access by other threads
+	BASS_ChannelLock
+* Manual channel buffer updating
+	BASS_ChannelUpdate
+	BASS_ChannelPreBuf *removed*
+* Configurable manual update length
+	BASS_Update
+* Extended device information retrieval and detection of new/removed devices
+	BASS_GetDeviceInfo
+	BASS_RecordGetDeviceInfo
+	BASS_DEVICEINFO structure
+	BASS_GetDeviceDescription *removed*
+	BASS_RecordGetDeviceDescription *removed*
+	BASS_INFO (driver member) *removed*
+	BASS_RECORDINFO (driver member) *removed*
+	MULTI example updated
+* Default device change tracking on Windows (as on OSX)
+	BASS_Init
+	BASS_RecordInit
+* Speaker detection from Windows control panel
+	BASS_DEVICE_CPSPEAKERS (BASS_Init flag)
+* Channel automatically stopped & resumed for DX8 effects
+	BASS_ChannelSetFX
+	BASS_ChannelRemoveFX
+* "double" precision position conversion
+	BASS_ChannelBytes2Seconds
+	BASS_ChannelSeconds2Bytes
+* Separate config functions for pointers
+	BASS_SetConfigPtr
+	BASS_GetConfigPtr
+	BASS_CONFIG_NET_AGENT/PROXY (BASS_SetConfigPtr options)
+* Configurable file format verification length
+	BASS_CONFIG_VERIFY (BASS_SetConfig option)
+* Stream filename retrieval
+	BASS_CHANNELINFO (file member)
+* Channel sample retrieval
+	BASS_CHANNELINFO (sample member)
+* META syncs no longer receive metadata in the "data" parameter
+	BASS_SYNC_META (BASS_ChannelSetSync type)
+* Separate sync for OGG logical bitstream changes (instead of BASS_SYNC_META)
+	BASS_SYNC_OGG_CHANGE (BASS_ChannelSetSync type)
+	NETRADIO example updated (C version)
+* Message syncing removed (use PostMessage instead)
+	BASS_SYNC_MESSAGE (BASS_ChannelSetSync flag) *removed*
+* Data retrieval from stopped/paused channels
+	BASS_ChannelGetData
+* Callback "user" parameters changed to pointers
+	BASS_StreamCreate / STREAMPROC
+	BASS_StreamCreateFileUser
+	BASS_StreamCreateURL / DOWNLOADPROC
+	BASS_RecordStart / RECORDPROC
+	BASS_ChannelSetDSP / DSPPROC
+	BASS_ChannelSetSync / SYNCPROC
+
+2.3.0.3 - 30/7/2007
+-------------------
+* FX state resetting
+	BASS_FXReset
+* PLS/M3U playlist URL processing
+	BASS_CONFIG_NET_PLAYLIST
+	NETRADIO example updated
+* Internet stream connection status retrieval
+	BASS_FILEPOS_CONNECTED (BASS_StreamGetFilePosition mode)
+* Lyrics3v2 tags
+	BASS_TAG_LYRICS3 (BASS_ChannelGetTags type)
+* IT virtual channel configuration
+	BASS_CONFIG_MUSIC_VIRTUAL
+* Accurate speaker detection on Vista
+	BASS_INFO (speakers member)
+* Device output/input rate retrieval on Vista
+	BASS_INFO (freq member)
+	BASS_RECORDINFO (freq member)
+* Syncing upon position changes
+	BASS_SYNC_SETPOS (BASS_ChannelSetSync type)
+* Improved stall handling
+	BASS_SYNC_STALL
+* Invalid decoding channel flags produce an error instead of being ignored
+	BASS_StreamCreate/File/User/Url
+	BASS_MusicLoad
+
+2.3.0.2 - 22/1/2007
+-------------------
+* Retrieval of a sample's existing channel handles
+	BASS_SampleGetChannels
+* 8192 sample FFT
+	BASS_DATA_FFT8192 (BASS_ChannelGetData flag)
+* Adjustable recording buffer
+	BASS_CONFIG_REC_BUFFER (BASS_SetConfig option)
+* Stopping decoding channels before the end
+	BASS_ChannelStop
+* Sample channels created paused to prevent overriding before playback
+	BASS_SampleGetChannel
+* Separate "MP3-FREE" version using the OS's MP3 decoder
+	BASS_CONFIG_MP3_CODEC *removed*
+
+2.3.0.1 - 12/6/2006
+-------------------
+* Ability to move a channel to another device
+	BASS_ChannelSetDevice
+	MULTI example updated
+* Support for ID3v2.4 tags at end of file
+	BASS_TAG_ID3V2 (BASS_ChannelGetTags type)
+
+2.3 - 21/5/2006
+---------------
+* MOD message/instrument/sample text retrieval, merged with stream tag retrieval function
+	BASS_ChannelGetTags
+	BASS_TAG_MUSIC_NAME/MESSAGE/INST/SAMPLE (BASS_ChannelGetTags types)
+	BASS_MusicGetName *removed*
+	BASS_StreamGetTags *removed*
+* Plugin information retrieval
+	BASS_PluginGetInfo
+	BASS_PLUGININFO/FORM structures
+	BASS_CHANNELINFO (plugin member)
+	PLUGINS example updated
+* RIFF/WAVE "INFO" tag retrieval
+	BASS_TAG_RIFF_INFO (BASS_StreamGetTags type)
+* More specific WAVE format information
+	BASS_CTYPE_STREAM_WAV_PCM/FLOAT (channel types)
+	BASS_CTYPE_STREAM_WAV (channel type flag)
+* Proxy server configuration
+	BASS_CONFIG_NET_PROXY (BASS_SetConfig option)
+	BASS_CONFIG_NET_NOPROXY *removed*
+	NETRADIO example updated
+* Passive FTP mode
+	BASS_CONFIG_NET_PASSIVE (BASS_SetConfig option)
+* Agent changes take immediate effect
+	BASS_CONFIG_NET_AGENT (BASS_SetConfig option)
+* Minimum time gap between creating new sample channels
+	BASS_SAMPLE (mingap member)
+	BASS_SampleGetChannel
+* Support for Unicode plugin filenames
+	BASS_PluginLoad
+* Device output/input rate retrieval (MacOSX only)
+	BASS_INFO (freq member)
+	BASS_RECORDINFO (freq member)
+* Extended version info (minor revision)
+	BASS_GetVersion
+* Unsupported codec error code
+	BASS_ERROR_CODEC
+* Optional use of the Windows MP3 codec
+	BASS_CONFIG_MP3_CODEC (BASS_SetConfig option)
+* 3D support for MacOSX
+	BASS_Set3DFactors
+	BASS_Get3DFactors
+	BASS_Set3DPosition
+	BASS_Get3DPosition
+	BASS_Apply3D
+	BASS_ChannelSet3DAttributes
+	BASS_ChannelGet3DAttributes
+	BASS_ChannelSet3DPosition
+	BASS_ChannelGet3DPosition
+	3DTEST example added (Win32 example also updated)
+* VB version of SYNTH example added
+
+2.2 - 2/10/2005
+---------------
+* Add-on plugin system
+	BASS_PluginLoad
+	BASS_PluginFree
+	BASS_StreamCreateFile/User/Url
+	BASS_SampleLoad
+	PLUGINS example added
+* MOD position & syncing in bytes
+	BASS_ChannelSetPosition
+	BASS_ChannelGetPosition
+	BASS_MusicGetOrderPosition added for orders position
+	BASS_SYNC_MUSICPOS added for orders syncing
+	MAKEMUSICPOS macro/define
+	CUSTLOOP example updated
+* Stream/MOD "length" functions combined (also works with samples), new MOD orders length function
+	BASS_ChannelGetLength
+	BASS_MusicGetOrders
+	BASS_StreamGetLength *removed*
+	BASS_MusicGetLength *removed*
+* Support for AIFF files
+	BASS_StreamCreateFile/User/Url
+	BASS_SampleLoad
+* Support for 24 and 32-bit (integer) WAV files
+	BASS_StreamCreateFile/User/Url
+	BASS_SampleLoad
+* WAV files are no longer converted to the "device" resolution
+	BASS_StreamCreateFile/User/Url
+* Recording master control
+	BASS_RecordGetInput
+	BASS_RecordSetInput
+* Adjustable prebuffering
+	BASS_ChannelPreBuf
+* Floating-point data retrieval
+	BASS_DATA_FLOAT (BASS_ChannelGetData flag)
+* Support for floating-point samples
+	BASS_SampleLoad
+	BASS_SampleCreate
+* Multi-channel samples
+	BASS_SampleLoad/Create
+	BASS_SAMPLE (chans member)
+* Sample lengths given in bytes
+	BASS_SampleCreate
+	BASS_SAMPLE (length member)
+* MOD music 8-bit resolution option
+	BASS_MusicLoad
+* OGG vendor tag retrieval
+	BASS_TAG_VENDOR (BASS_StreamGetTags type)
+* Configurable "User-Agent" header for internet streams
+	BASS_CONFIG_NET_AGENT (BASS_SetConfig option)
+* Shoutcast metadata is now requested automatically
+	BASS_STREAM_META flag *removed*
+* Download callbacks receive all data from start of file/stream (including any non-audio data)
+	DOWNLOADPROC
+* Length when streaming in blocks is unavailable (BASS_ERROR_NOTAVAIL, not just 0)
+	BASS_ChannelGetLength
+* Support for growing custom file streams
+	BASS_FILE_LEN (STREAMFILEPROC action)
+* Query file action removed
+	BASS_FILE_QUERY *removed*
+* Recording channel syncing
+	BASS_ChannelSetSync
+* Info structure "size" members removed
+	BASS_INFO structure
+	BASS_RECORDINFO structure
+* Little bit of flag reshuffling
+	BASS_MP3_SETPOS renamed to BASS_STREAM_PRESCAN
+	BASS_MUSIC_CALCLEN value changed and renamed to BASS_MUSIC_PRESCAN
+	BASS_MUSIC_POSRESET value changed
+* Add-on API enhancements
+* MacOSX port introduced
+
+2.1 - 28/11/2004
+----------------
+* Improved "mixtime" sync system, allowing custom looping
+	SYNCPROC
+	CUSTLOOP example added
+* FX can now be in the DSP chain, so can be prioritized and applied in floating-point
+	BASS_ChannelSetFX
+	BASS_CONFIG_FLOATDSP (BASS_SetConfig option)
+* Ability to set channel flags (eg. looping) independent of playback
+	BASS_ChannelSetFlags
+	SPEAKERS example updated
+* Stream/MOD "play" and channel "resume" functions combined
+	BASS_ChannelPlay
+	BASS_StreamPlay *removed*
+	BASS_MusicPlay *removed*
+	BASS_MusicPlayEx *removed*
+	BASS_ChannelResume *removed*
+* Stream/MOD prebuffering functions combined
+	BASS_ChannelPreBuf
+	BASS_StreamPreBuf *removed*
+	BASS_MusicPreBuf *removed*
+* MOD attribute functions combined, with added BPM/speed/globalvolume options
+	BASS_MusicSetAttribute
+	BASS_MusicGetAttribute
+	BASS_MUSIC_ATTRIB_AMPLIFY
+	BASS_MUSIC_ATTRIB_PANSEP
+	BASS_MUSIC_ATTRIB_PSCALER
+	BASS_MUSIC_ATTRIB_BPM
+	BASS_MUSIC_ATTRIB_SPEED
+	BASS_MUSIC_ATTRIB_VOL_GLOBAL
+	BASS_MUSIC_ATTRIB_VOL_CHAN
+	BASS_MUSIC_ATTRIB_VOL_INST
+	BASS_MusicSetAmplify *removed*
+	BASS_MusicSetPanSep *removed*
+	BASS_MusicSetPositionScaler *removed*
+	BASS_MusicSetVolume *removed*
+	BASS_MusicGetVolume *removed*
+* Flag to reset bpm/etc as well as notes when seeking in MOD musics
+	BASS_MUSIC_POSRESETEX (BASS_MusicLoad & BASS_ChannelSetFlags flag)
+* More flexible and concise sample channel creation system
+	BASS_SampleGetChannel
+	BASS_SamplePlay *removed*
+	BASS_SamplePlayEx *removed*
+	BASS_SamplePlay3D *removed*
+	BASS_SamplePlay3DEx *removed*
+* Support for up to 30 speakers
+	BASS_SPEAKER_N macro/define
+* More precise level measurement
+	BASS_ChannelGetLevel
+* Level can now be retrieved from decoding channels
+	BASS_ChannelGetLevel
+* Retrieval of a sample/channel's original sample resolution
+	BASS_SAMPLE (origres member)
+	BASS_CHANNELINFO (origres member)
+* Support for streaming WAV files in "blocks"
+	BASS_StreamCreateURL
+	BASS_StreamCreateFileUser
+* Status info (HTTP/ICY tags) available during connection to server
+	BASS_STREAM_STATUS (BASS_StreamCreateURL flag)
+	DOWNLOADPROC
+	NETRADIO example updated (Delphi version also added)
+* Adjustable internet stream prebuffering
+	BASS_CONFIG_NET_PREBUF (BASS_SetConfig option)
+* Option to bypass proxy server
+	BASS_CONFIG_NET_NOPROXY (BASS_SetConfig option)
+* Option whether to allow channels to be played after BASS_Pause
+	BASS_CONFIG_PAUSE_NOPLAY (BASS_SetConfig option)
+* Recording channel count now a separate parameter
+	BASS_RecordStart (chans parameter)
+* Synchronizer for when a channel is freed
+	BASS_SYNC_FREE (BASS_ChannelSetSync type)
+* Data start file position retrieval
+	BASS_FILEPOS_START (BASS_StreamGetFilePosition mode)
+* Performance improvements
+	MP2 decoding ~20% faster
+	MP3/MP1 decoding & FFT processing all up to 10% faster
+	OGG decoding ~3% faster
+* C/C++ examples reorganised, with makefiles & VC++ projects
+* Add-on API enhancements
+* More DLL shrinkage :)
+
+2.0 - 31/10/2003
+----------------
+* Multiple output device support
+	BASS_Init (device number changes)
+	BASS_SetDevice
+	BASS_GetDevice
+	BASS_ChannelGetDevice
+	MULTI example updated (VB version also added)
+* Multiple recording device support
+	BASS_RecordSetDevice
+	BASS_RecordGetDevice
+	BASS_RecordStart
+	BASS_ChannelGetDevice
+	HRECORD handle
+	RECORDPROC (handle parameter)
+* Recording with DSP/FX
+	BASS_ChannelSetDSP
+	BASS_ChannelSetFX
+* Recording position retrieval
+	BASS_ChannelGetPosition
+* Start recording paused
+	BASS_RECORD_PAUSE (BASS_RecordStart flag)
+* Multi-channel streams, inc. support for multichannel OGG & WAV files
+	BASS_StreamCreate
+	BASS_StreamCreateFile/User/Url
+* FFT for individual channels, inc. multi-channel streams
+	BASS_DATA_FFT_INDIVIDUAL (BASS_ChannelGetData flag)
+	BASS_DATA_FFT512S/1024S/2048S/4096S *removed*
+* DSP prioritizing
+	BASS_ChannelSetDSP
+	DSPTEST example updated
+* Seeking in internet streamed files
+	BASS_ChannelSetPosition
+* Enhanced custom file stream systems
+	BASS_StreamCreateFileUser
+	BASS_FILE_SEEK (STREAMFILEPROC action)
+	BASS_STREAM_FILEPROC flag *removed*
+* Enhanced custom stream system with automatic stalling/resuming
+	STREAMPROC
+	BASS_STREAMPROC_END (STREAMPROC flag)
+* Synchronizer for stalled/resumed playback 
+	BASS_SYNC_STALL (BASS_ChannelSetSync type)
+* Synchronizer for completed download
+	BASS_SYNC_DOWNLOAD (BASS_ChannelSetSync type)
+* End sync support for custom streams
+	BASS_SYNC_END (BASS_ChannelSetSync type)
+* Synchronizer support for decoding channels
+	BASS_ChannelSetSync
+* Unified configuration function
+	BASS_SetConfig
+	BASS_GetConfig
+	BASS_SetBufferLength *removed*
+	BASS_SetNetConfig *removed*
+	BASS_SetGlobalVolumes *removed*
+	BASS_GetGlobalVolumes *removed*
+	BASS_SetLogCurves *removed*
+	BASS_Set3DAlgorithm *removed*
+	BASS_DEVICE_FLOATDSP flag *removed*
+* Internet stream saving to disk replaced by more flexible callback
+	BASS_StreamCreateURL
+	DOWNLOADPROC
+	VB NETRADIO example updated
+* Buffer length retrieval when "streaming in blocks"
+	BASS_FILEPOS_END (BASS_StreamGetFilePosition mode)
+* Individual sample rate setting for MOD musics
+	BASS_MusicLoad
+* Channel type and default sample rate retrieval
+	BASS_ChannelGetInfo (replaces BASS_ChannelGetFlags)
+	BASS_CHANNELINFO
+* MOD music flag retrieval
+	BASS_CHANNELINFO (flags member)
+* Adjustable instrument volumes in MOD musics
+	BASS_MusicSetVolume (replaces BASS_MusicSetChannelVol)
+	BASS_MusicGetVolume (replaces BASS_MusicGetChannelVol)
+* Automatically free a MOD music when it stops or ends
+	BASS_MUSIC_AUTOFREE (BASS_MusicLoad flag)
+* Class GUID added to initialization parameters
+	BASS_Init
+	BASS_SetCLSID *removed*
+* Update period adjustable at any time
+	BASS_CONFIG_UPDATEPERIOD (BASS_SetConfig option)
+	BASS_DEVICE_NOTHREAD flag *removed*
+* Customizable maximum volume setting
+	BASS_CONFIG_MAXVOL (BASS_SetConfig option)
+	BASS_DEVICE_VOL1000 flag *removed*
+* Device volume is now always left as it is during init/freeing
+	BASS_DEVICE_LEAVEVOL flag *removed*
+* Device driver name retrieval
+	BASS_INFO (driver member)
+	BASS_RECORDINFO (driver member)
+* Error codes are local to the current thread
+	BASS_ErrorGetCode
+* Performance improvements
+	MP2 decoding 15-20% faster
+	MP3 decoding ~5% faster
+* Built-in CD functions removed (replaced in BASSCD)
+	BASS_CDDoor *removed*
+	BASS_CDFree *removed*
+	BASS_CDGetID *removed*
+	BASS_CDGetTrackLength *removed*
+	BASS_CDGetTracks *removed*
+	BASS_CDInDrive *removed*
+	BASS_CDInit *removed*
+	BASS_CDPlay *removed*
+* Force channels to use software mixing
+	BASS_SAMPLE_SOFTWARE (BASS_StreamCreate/File/User/URL & BASS_MusicLoad flag)
+* Support for high-pass filter and forward/reverse (S9E/F) IT/MPT effects
+* BASS_MUSIC flags rearranged to mirror BASS_SAMPLE/STREAM counterparts
+* Output automatically started during initialization
+* BASS_ChannelGetData once again accepts any "length" param
+* All function comments have been removed from the API headers to avoid
+  outdated/incorrect information - the BASS.CHM documentation should be used.
+* TMT Pascal API removed from main distribution - now available on the website
+* A few more 'K' knocked off the DLL size :)
+
+1.8a - 18/6/2003
+----------------
+* Tweaks 'n' fixes, including...
+	Fixed seeking bug on 32-bit OGG streams
+	Fixed seeking on a decoding channel after it has reached the end
+	Low FPU precision (eg. when using Direct3D) issue addressed
+	Improved speakers (BASS_INFO) detection
+	BASS_ChannelSeconds2Bytes return value is rounded down to nearest sample
+	BASS_ChannelGetData "length" param must equal a whole number of samples
+	Slide syncs are triggered by "-2" volume slides on "autofree" streams
+* Support for UNICODE filenames
+	BASS_UNICODE (BASS_SampleLoad/BASS_StreamCreateFile/BASS_MusicLoad flag)
+* 4096 sample FFT
+	BASS_DATA_FFT4096/S (BASS_ChannelGetData flags)
+* Another 'K' knocked off the DLL size
+
+1.8 - 9/3/2003
+--------------
+* 32-bit floating-point channels
+	BASS_SAMPLE_FLOAT (BASS_StreamCreate/URL/File flag)
+	BASS_MUSIC_FLOAT (BASS_MusicLoad flag)
+	BASS_SAMPLE_FLOAT (BASS_RecordStart flag)
+	BASS_DEVICE_FLOATDSP (BASS_Init flag)
+	DSPTEST example updated
+* Support for 32-bit floating-point (type 3) WAV files
+	BASS_StreamCreateFile/URL
+	BASS_SampleLoad
+* Channel speaker assignment
+	BASS_SPEAKER_FRONT (BASS_MusicLoad/BASS_StreamCreate/File/URL flag)
+	BASS_SPEAKER_REAR                       "
+	BASS_SPEAKER_CENLFE                     "
+	BASS_SPEAKER_REAR2                      "
+	BASS_SPEAKER_FRONTLEFT                  "
+	BASS_SPEAKER_FRONTRIGHT                 "
+	BASS_SPEAKER_REARLEFT                   "
+	BASS_SPEAKER_REARRIGHT                  "
+	BASS_SPEAKER_CENTER                     "
+	BASS_SPEAKER_LFE                        "
+	BASS_SPEAKER_REAR2LEFT                  "
+	BASS_SPEAKER_REAR2RIGHT                 "
+	BASS_INFO (speakers member)
+	BASS_DEVICE_SPEAKERS (BASS_Init flag)
+	4SPEAKER example replaced by SPEAKERS example
+* Recording input type retrieval
+	BASS_INPUT_TYPE_xxx (BASS_RecordGetInput)
+	RECTEST example updated
+* Non-interpolated MOD mixing
+	BASS_MUSIC_NONINTER (BASS_MusicLoad/PlayEx flag)
+* Performance improvements
+	FFT up to 100% faster!
+	MP3(MPEG2/2.5) decoding up to 60% faster
+	MMX mixers 5-10% faster
+	MP3(MPEG1)/MP2/MP1/OGG decoding all ~5% faster
+* Optional disabling of FFT windowing
+	BASS_DATA_FFT_NOWINDOW (BASS_ChannelGetData flag)
+* BASS_ERROR_FILEFORM - error code to distinguish between file and sample format
+	BASS_MusicLoad
+	BASS_SampleLoad
+	BASS_StreamCreate/File/URL
+* BASS_StreamGetFilePosition mode flags added
+	BASS_FILEPOS_DECODE/DOWNLOAD/END
+* DirectX 9 detection
+	BASS_INFO (dsver member)
+* Initialization flags retrieval
+	BASS_INFO (initflags member)
+* Half-rate MP3 playback option removed
+	BASS_MP3_HALFRATE flag *removed*
+* New internal "plugin" system - BASSWMA is further integrated as a result
+* Improved documentation - integrated with BASSWMA, search option added
+* VB version of DSPTEST example added
+* Delphi RECORDTEST example added
+* Guess what... reduced DLL size again :)
+
+1.7 - 27/10/2002
+----------------
+* New alternative DX8 (DMO) effects implementation
+	BASS_StreamCreate/File/URL
+	BASS_MusicLoad
+	BASS_ChannelSetFX
+	SYNTH example updated
+* User file streaming
+	BASS_STREAM_FILEPROC (BASS_StreamCreate flag)
+	STREAMFILEPROC
+* DSP & FX support for decoding channels
+	BASS_ChannelSetDSP
+	BASS_ChannelSetFX
+* Support for DX8 (DMO) effects in IT/XM/MO3 files
+	BASS_MusicLoad
+* Support for chained OGG streaming (and syncing)
+	BASS_StreamCreateURL
+	BASS_SYNC_META (BASS_ChannelSetSync type)
+* Attribute (volume/frequency/pan) sliding
+	BASS_ChannelSlideAttributes
+	BASS_ChannelIsSliding
+	BASS_SYNC_SLIDE (BASS_ChannelSetSync type)
+* Recording without a callback function
+	BASS_RecordStart
+	LIVEFX example added
+* Query a channel's buffered data
+	BASS_DATA_AVAILABLE (BASS_ChannelGetData flag)
+* Discard data from the recording buffer
+	BASS_ChannelGetData
+* Adjustable internet stream config (timeout/buffer lengths)
+	BASS_SetNetConfig
+* Recommended minimum buffer length
+	BASS_INFO (minbuf member)
+* MOD music flags adjustment without changing playback position
+	BASS_MusicPlayEx
+	PLAYER (MASM) example updated
+* More functions are now useable in MOD music "mixtime" syncs
+	SYNCPROC
+	BASS_ChannelSetPosition
+	BASS_MusicPlayEx
+	BASS_MusicSetAmplify
+	BASS_MusicSetPanSep
+* Maximum buffer length increased to 5 seconds
+	BASS_SetBufferLength
+* Support for extended filter range in IT files
+	BASS_MusicLoad
+* Speedier MOD music file verification
+	BASS_MusicLoad
+* Delphi 3DTEST example fixed
+* Magically reduced DLL size again :)
+
+1.6a - 25/8/2002
+----------------
+* OGG support updated to 1.0
+* Stereo FFT
+	BASS_DATA_FFT512S/1024S/2048S (BASS_ChannelGetData flags)
+* Support for "Invert Loop" (EFx) MOD effect
+* Reduced DLL size
+* New Delphi examples
+	WRITEWAV - WAVE writer example
+	SAMPLEVIS - Visualisation example
+
+1.6 - 13/6/2002
+---------------
+* 64-bit stream lengths and positions
+	BASS_StreamGetLength
+	BASS_ChannelBytes2Seconds
+	BASS_ChannelSeconds2Bytes
+	BASS_ChannelGetPosition
+	BASS_ChannelSetPosition
+	BASS_ChannelSetSync
+* Recording input selection
+	BASS_RECORDINFO (inputs & singlein members)
+	BASS_RecordGetInputName
+	BASS_RecordGetInput
+	BASS_RecordSetInput
+* Adjustable recording update period
+	BASS_RecordStart
+* Load OGG files as samples
+	BASS_SampleLoad
+* CD drive door opening & closing
+	BASS_CDDoor
+* CDDB2 ID retrieval
+	BASS_CDID_CDDB2 (BASS_CDGetID flag)
+* Streaming beyond initial file length
+	BASS_StreamCreateFile
+* Recording position bytes<->seconds translation
+	BASS_ChannelBytes2Seconds
+	BASS_ChannelSeconds2Bytes
+* Improved multi-threaded support (play from any thread)
+	BASS_MusicPlay/Ex
+	BASS_SamplePlay/3D/Ex
+	BASS_StreamPlay
+	BASS_DEVICE_NOSYNC flag *removed*
+* Paused channel status
+	BASS_ACTIVE_PAUSED (BASS_ChannelIsActive)
+* Integrated WMA stream freeing
+	BASS_StreamFree
+	BASS_Free
+* Pin-point accurate OGG seeking without BASS_MP3_SETPOS flag
+* Win2k DS buffer bug fix
+
+1.5a - 14/4/2002
+----------------
+* NT4 fix (also enables "nosound" device without DX installed)
+	BASS_ERROR_DX error code
+* MOD music loading without the samples
+	BASS_MUSIC_NOSAMPLE (BASS_MusicLoad flag)
+* Custom decoding channels
+	BASS_STREAM_DECODE (BASS_StreamCreate flag)
+* 5 second HTTP connection timeout
+	BASS_ERROR_TIMEOUT (BASS_StreamCreateURL error code)
+
+1.5 - 31/3/2002
+---------------
+* Improved performance
+	MMX mixers lot faster (over 50% faster in some cases!)
+	OGG decoding 15-20% faster
+	MP3 decoding 5-10% faster
+* Recording
+	BASS_RecordGetDeviceDescription
+	BASS_RecordInit
+	BASS_RecordFree
+	BASS_RecordGetInfo
+	BASS_RecordStart
+* OGG support built-in (OGG/VORBIS DLLs not required)
+	BASS_DEVICE_OGG flag *removed*
+* MOD music seeking in seconds
+	BASS_MusicPlayEx
+	BASS_ChannelSetPosition
+* Shoutcast metadata retrieval
+	BASS_STREAM_META (BASS_StreamCreateURL flag)
+	BASS_TAG_META (BASS_StreamGetTags type)
+	BASS_SYNC_META (BASS_ChannelSetSync type)
+* 1000 volume levels
+	BASS_DEVICE_VOL1000 (BASS_Init/CDInit flag)
+* CDDB ID retrieval
+	BASS_CDID_CDDB (BASS_CDGetID flag)
+* Leave the CD volume as it is during init/closing
+	BASS_DEVICE_LEAVEVOL (BASS_CDInit flag)
+* FFT enabled on decoding channels
+	BASS_ChannelGetData
+* Left level duplicated on right for mono channels
+	BASS_ChannelGetLevel
+* Improved MPEG length estimation without BASS_MP3_SETPOS flag
+	BASS_StreamGetLength
+* Support for Modplug/ADPCM compressed files
+	BASS_MusicLoad
+* Device description function parameter change
+	BASS_GetDeviceDescription
+* MASM API
+
+1.4 - 30/1/2002
+---------------
+* Channel decoding without playback
+	BASS_MUSIC_DECODE (BASS_MusicLoad flag)
+	BASS_STREAM_DECODE (BASS_StreamCreateFile/URL flag)
+	BASS_ChannelGetData
+* Windows message sync callbacks
+	BASS_SYNC_MESSAGE (BASS_ChannelSetSync flag)
+* Adjustable channel volumes in MOD musics
+	BASS_MusicSetChannelVol
+	BASS_MusicGetChannelVol
+* Customizable DirectSound initialization object
+	BASS_SetCLSID
+* Retrieve HMUSIC/HSTREAM/HCHANNEL IDirectSoundBuffer interfaces
+	BASS_GetDSoundObject
+* A3D functions removed (use BASS_SetCLSID/BASS_GetDSoundObject to access A3D)
+	BASS_DEVICE_A3D (BASS_Init flag)
+	BASS_SetA3DResManager
+	BASS_GetA3DResManager
+	BASS_SetA3DHFAbsorbtion
+	BASS_GetA3DHFAbsorbtion
+* Callback functions now work in VB6
+	DSPPROC
+	STREAMPROC
+	SYNCPROC
+* Improved PCM WAVE streaming performance
+	BASS_StreamCreateFile
+	BASS_StreamCreateURL
+* OGG modules updated to RC3
+* Stereo sample support in MO3 format
+* MO3 encoder now distributed separately from BASS
+
+1.3 - 17/11/2001
+----------------
+* Manual buffer updating
+	BASS_DEVICE_NOTHREAD (BASS_Init flag)
+	BASS_Update
+* Adjustable buffer update period (allows small buffer sizes)
+	BASS_Init
+* Output device latency retrieval
+	BASS_INFO (latency member)
+* MPEG/OGG seeking without BASS_MP3_SETPOS flag
+	BASS_ChannelSetPosition
+* Internet file streaming from offsets
+	BASS_StreamCreateURL
+* File stream tag/comment retrieval (ID3/ID3v2/OGG/HTTP/ICY tags)
+	BASS_StreamGetTags
+* Byte<->time position translation
+	BASS_ChannelBytes2Seconds
+	BASS_ChannelSeconds2Bytes
+* UMX (Unreal/Tournament music package) format support
+	BASS_MusicLoad
+* S3M/IT sync fx changed to S2x (S0x conflicted with S00)
+	BASS_SYNC_MUSICFX
+* Stereo sample support in IT/XM/S3M formats
+* MO3: OGG compression supported
+
+1.2 - 25/9/2001
+---------------
+* OGG (Ogg Vorbis) stream support
+	BASS_DEVICE_OGG (BASS_Init flag)
+	BASS_StreamCreateFile
+	BASS_StreamCreateURL
+* Channel linking (start/stop/pause/resume channels together)
+	BASS_ChannelSetLink
+	BASS_ChannelRemoveLink
+* MOD music playback length calculation
+	BASS_MUSIC_CALCLEN (BASS_MusicLoad flag)
+	BASS_MusicGetLength
+* Pre-buffering
+	BASS_MusicPreBuf
+	BASS_StreamPreBuf
+* Samples with single simultaneous playbacks have same HSAMPLE/HCHANNEL handle
+	BASS_SamplePlay/Ex
+* Stopping a custom stream flushes its buffer contents
+	BASS_ChannelStop
+
+1.1a - 31/8/2001
+----------------
+* NT4 bug fixed
+* XM Wxx effect syncing
+	BASS_SYNC_MUSICFX
+* MP3/2/1 rewinding without BASS_MP3_SETPOS
+	BASS_ChannelSetPosition
+
+1.1 - 11/8/2001
+---------------
+* DX8 (DMO) effects
+	BASS_SAMPLE_FX (BASS_StreamCreate/File/URL flag)
+	BASS_MUSIC_FX (BASS_MusicLoad flag)
+	BASS_ChannelSetFX
+	BASS_ChannelRemoveFX
+	BASS_FXSetParameters
+	BASS_FXGetParameters
+	BASS_FXCHORUS structure
+	BASS_FXCOMPRESSOR structure
+	BASS_FXDISTORTION structure
+	BASS_FXECHO structure
+	BASS_FXFLANGER structure
+	BASS_FXGARGLE structure
+	BASS_FXI3DL2REVERB structure
+	BASS_FXPARAMEQ structure
+	BASS_FXREVERB structure
+* Internet file streaming in blocks (inc. Shoutcast/Icecast stream support)
+	BASS_STREAM_BLOCK (BASS_StreamCreateURL flag)
+* 512/1024/2048 sample FFT
+	BASS_DATA_FFT512/1024/2048 (BASS_ChannelGetData flags)
+* CD identification
+	BASS_CDGetID
+* Improved DX version detection
+	BASS_INFO (dsver member)
+
+1.0 - 20/6/2001
+---------------
+* Load MP3/MP2/MP1 files as samples
+	BASS_SampleLoad
+* Internet file streaming from FTP servers
+	BASS_StreamCreateURL
+* Save a local copy of internet file streams
+	BASS_StreamCreateURL
+* Sample accurate file stream seeking
+	BASS_ChannelSetPosition
+	BASS_StreamGetBlockLength *removed*
+* Stream position synchronizer
+	BASS_SYNC_POS
+* Increased synchronizer precision
+* Improved MPEG file detection and error detection
+* Stop MOD musics on a backwards jump effect
+	BASS_MUSIC_STOPBACK (BASS_MusicLoad/PlayEx flag)
+* Leave the volume as it is during closing (as well as initialization)
+	BASS_DEVICE_LEAVEVOL (BASS_Init flag)
+* Optional automatic use of foreground window handle during initialization
+	BASS_Init
+* Reduced DLL size
+* VB API fixes
+
+0.9 - 18/4/2001
+---------------
+* Internet file streaming
+	BASS_StreamCreateURL
+* MP1 & MP2 (MPEG layer 1 & 2) support
+	BASS_StreamCreateFile/URL
+* MPEG 2.5 support (12000/11025/8000hz sample rates)
+	BASS_StreamCreateFile/URL
+* Decoding/download/end file stream position retrieval
+	BASS_StreamGetFilePosition
+* XMPlay surround sound for MOD musics
+	BASS_MUSIC_SURROUND (BASS_MusicLoad/PlayEx flag)
+	BASS_MUSIC_SURROUND2 (BASS_MusicLoad/PlayEx flag)
+* Restrict the download rate of internet file streams
+	BASS_STREAM_RESTRATE (BASS_StreamCreateURL flag)
+* Check if an internet file stream is stalled
+	BASS_ChannelIsActive
+* Automatically free a stream when it stops or ends
+	BASS_STREAM_AUTOFREE (BASS_StreamCreate/File/URL flag)
+* Leave the volume as it is during initialization
+	BASS_DEVICE_LEAVEVOL (BASS_Init flag)
+* Number of CD tracks retrieval
+	BASS_CDGetTracks
+* CD track length retrieval
+	BASS_CDGetTrackLength
+* Exact stream length set after whole file is streamed
+	BASS_StreamGetLength
+* TMT Pascal API and samples
+* Dynamic-loading Delphi API
+
+0.8a - 28/2/2000
+----------------
+* Updated Delphi API and samples
+
+0.8 - 24/1/2000
+---------------
+* Improved MP3 performance on P2/K6 and above CPUs
+* User DSP functions on streams and MOD musics
+	BASS_ChannelSetDSP
+	BASS_ChannelRemoveDSP
+* DX7 voice allocation & management
+	BASS_SAMPLE_VAM (BASS_SampleLoad/Create flag)
+	BASS_VAM_xxx flags
+	BASS_SAMPLE (vam & priority members)
+* DX7 software 3D algorithm selection
+	BASS_Set3DAlgorithm
+* DirectSound interface retrieval
+	BASS_GetDSoundObject
+* Log/linear volume & panning curves
+	BASS_SetLogCurves
+* User data passed to callback functions
+	STREAMPROC - BASS_StreamCreate
+	SYNCPROC - BASS_ChannelSetSync
+* New synchronizer
+	BASS_SYNC_MUSICFX
+* New synchronizer flag
+	BASS_SYNC_MIXTIME
+* Disable synchronizers option - saves a little CPU time
+	BASS_DEVICE_NOSYNC (BASS_Init flag)
+* Hi-res floating-point CPU usage monitoring
+	BASS_GetCPU
+* Wait for playback to start when playing a CD
+	BASS_CDPlay
+* DirectSound (dsound.dll) version retrieval
+	BASS_INFO (dsver member)
+* Removed volume sliding functions (they were fairly pointless)
+	BASS_SlideVolume
+	BASS_IsSliding
+* MO3: read/write encoder settings
+* MO3: remove inst/samp/message texts now optional
+* MO3: LAME encoder settings
+
+0.7 - 3/10/1999
+---------------
+* MO3 (MP3 compressed MODs)
+* A3D functions
+	BASS_DEVICE_A3D (BASS_Init flag)
+	BASS_INFO (a3d member)
+	BASS_SetA3DResManager
+	BASS_GetA3DResManager
+	BASS_SetA3DHFAbsorbtion
+	BASS_GetA3DHFAbsorbtion
+* Music/stream immediate sample data retrieval
+	BASS_ChannelGetData
+* File stream (WAV/MP3) length retrieval
+	BASS_StreamGetLength
+	BASS_StreamGetBlockLength
+* File stream seeking
+	BASS_ChannelSetPosition
+* Mono MP3 option (lower CPU usage)
+	BASS_StreamCreateFile
+* Music length retrieval
+	BASS_MusicGetLength
+* Music name retrieval
+	BASS_MusicGetName
+* Stop notes when moving MOD music position
+	BASS_MUSIC_POSRESET (BASS_MusicLoad/BASS_MusicPlayEx flag)
+* BASS_ERROR_FREQ - invalid sample rate error code
+	BASS_SampleCreate
+	BASS_SamplePlayEx
+	BASS_SamplePlay3DEx
+	BASS_StreamCreate
+	BASS_ChannelSetAttributes
+* Delphi and VB APIs
+
+0.6a - 26/7/1999
+----------------
+* Half rate MP3 option (lower CPU usage)
+	BASS_MP3_HALFRATE
+* Loading/streaming from file offsets
+	BASS_MusicLoad
+	BASS_SampleLoad
+	BASS_StreamCreateFile
+* Global music/sample/stream volume levels
+	BASS_SetGlobalVolumes
+	BASS_GetGlobalVolumes
+* Other new function
+	BASS_SampleStop
+* New synchronizer
+	BASS_SYNC_END
+* New sample overrider
+	BASS_SAMPLE_OVER_DIST
+* LoadLibrary/GetProcAddress instructions and example
+
+0.5 - 4/7/1999
+--------------
+* Documentation!
+* File streaming (MP3 and WAV)
+	BASS_StreamCreateFile
+* Custom generated samples
+	BASS_SampleCreate
+	BASS_SampleCreateDone
+* Other new function
+	BASS_MusicSetPositionScaler
+* Renamed function
+	BASS_ChannelClearSync -> BASS_ChannelRemoveSync
+* Alterations made to
+	BASS_ChannelGetPosition
+	BASS_SampleLoad
+	BASS_StreamPlay
+
+0.4 - 30/3/1999
+---------------
+* Compressed WAV samples support (using audio CODECs)
+* Updated CD volume handling - now works with SB Live
+* More linear channel volume/pan scales (were slightly off before)
+* "no sound" device option
+* 3D sound functions
+	BASS_Set3DFactors
+	BASS_Get3DFactors
+	BASS_Set3DPosition
+	BASS_Get3DPosition
+	BASS_Apply3D
+	BASS_SamplePlay3D
+	BASS_SamplePlay3DEx
+	BASS_ChannelSet3DAttributes
+	BASS_ChannelGet3DAttributes
+	BASS_ChannelSet3DPosition
+	BASS_ChannelGet3DPosition
+* EAX functions
+	BASS_SetEAXParameters
+	BASS_GetEAXParameters
+	BASS_ChannelSetEAXMix
+	BASS_ChannelGetEAXMix
+* Other new functions
+	BASS_GetDeviceDescription
+	BASS_SetBufferLen
+	BASS_ChannelGetFlags
+	BASS_ChannelPause
+	BASS_ChannelResume
+	BASS_ChannelSetPosition
+* Replaced function
+	BASS_CDResume -> BASS_ChannelResume
+* Alterations made to
+	BASS_Init
+	BASS_CDInit
+	BASS_SampleLoad
+	BASS_StreamPlay
+	BASS_INFO structure
+	BASS_SAMPLE structure
+	BASS_DEVICE_xxx flags
+	BASS_SAMPLE_xxx flags
+
+0.3 - 8/3/1999
+--------------
+* Synchronization functions
+	BASS_ChannelSetSync
+	BASS_ChannelClearSync
+* Other new functions
+	BASS_GetVersion
+	BASS_ChannelGetPosition
+	BASS_ChannelGetLevel
+	BASS_ChannelGetAttributes
+	BASS_ChannelSetAttributes
+* Replaced functions
+	BASS_MusicStop -> BASS_ChannelStop
+	BASS_MusicSetVolume -> BASS_ChannelSetAttributes
+	BASS_CDStop -> BASS_ChannelStop
+	BASS_CDSetVolume -> BASS_ChannelSetAttributes
+	BASS_CDGetVolume -> BASS_ChannelGetAttributes
+	BASS_ChannelUpdate -> BASS_ChannelSetAttributes
+* Alterations made to
+	BASS_MusicPlayEx
+	BASS_StreamPlay
+	BASS_INFO structure
+
+0.2 - 28/2/1999
+---------------
+* First public release
+
+
+Credits
+=======
+Ogg Vorbis decoding is based on libogg/vorbis,
+Copyright (c) 2002-2004 Xiph.org Foundation
+
+CHMOX is (c) 2004 St�phane Boisson, http://chmox.sourceforge.net/
+
+API/Sample contributors
+-----------------------
+Visual Basic: Adam Hoult, Hendrik Knaepen, Arthur Aminov,
+              Peter Hebels
+Delphi: Titus Miloi, Rogier Timmermans, Alessandro Cappellozza,
+        Jesse Naranjo, Chris Troesken, Evgeny Melnikov
+MASM: Octavian Chis
+
+
+Bug reports, Suggestions, Comments, Enquiries, etc...
+=====================================================
+If you have any of the aforementioned please visit the BASS forum at
+the website. If you can't find an answer there, you can also email:
+
+	bass@un4seen.com
+
diff --git a/songmanagement/src/lib/bass/delphi/bass-macosx.patch b/songmanagement/src/lib/bass/delphi/bass-macosx.patch
new file mode 100644
index 00000000..f79b3925
--- /dev/null
+++ b/songmanagement/src/lib/bass/delphi/bass-macosx.patch
@@ -0,0 +1,368 @@
+--- D:/daten/bass.pas	Sun Mar 23 18:58:56 2008
++++ D:/daten/Projekte/UltraStarDX/Kopie von trunk/Game/Code/lib/bass/delphi/bass.pas	Sat May 03 03:52:56 2008
+@@ -13,8 +13,20 @@
+ 
+ interface
+ 
++{$IFDEF FPC}
++  {$PACKRECORDS C}
++{$ENDIF}
++
++{$IFDEF MSWINDOWS}
++  {$DEFINE DLL_STDCALL}
++{$ELSE}
++  {$DEFINE DLL_CDECL}
++{$ENDIF}
++
++{$IFDEF MSWINDOWS}
+ uses
+   Windows;
++{$ENDIF}
+ 
+ const
+   BASSVERSION = $204;             // API version
+@@ -231,6 +243,7 @@
+   BASS_3DALG_FULL         = 2;
+   BASS_3DALG_LIGHT        = 3;
+ 
++{$IFDEF MSWINDOWS}
+   // EAX environments, use with BASS_SetEAXParameters
+   EAX_ENVIRONMENT_GENERIC           = 0;
+   EAX_ENVIRONMENT_PADDEDCELL        = 1;
+@@ -260,6 +273,7 @@
+   EAX_ENVIRONMENT_PSYCHOTIC         = 25;
+   // total number of environments
+   EAX_ENVIRONMENT_COUNT             = 26;
++{$ENDIF}
+ 
+   BASS_STREAMPROC_END = $80000000; // end of user stream flag
+ 
+@@ -487,10 +501,10 @@
+   end;
+ 
+   // User file stream callback functions
+-  FILECLOSEPROC = procedure(user: Pointer); stdcall;
+-  FILELENPROC = function(user: Pointer): QWORD; stdcall;
+-  FILEREADPROC = function(buffer: Pointer; length: DWORD; user: Pointer): DWORD; stdcall;
+-  FILESEEKPROC = function(offset: QWORD; user: Pointer): BOOL; stdcall;
++  FILECLOSEPROC = procedure(user: Pointer); {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
++  FILELENPROC = function(user: Pointer): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
++  FILEREADPROC = function(buffer: Pointer; length: DWORD; user: Pointer): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
++  FILESEEKPROC = function(offset: QWORD; user: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+ 
+   BASS_FILEPROCS = record
+     close: FILECLOSEPROC;
+@@ -578,7 +592,7 @@
+   end;
+ 
+   // callback function types
+-  STREAMPROC = function(handle: HSTREAM; buffer: Pointer; length: DWORD; user: Pointer): DWORD; stdcall;
++  STREAMPROC = function(handle: HSTREAM; buffer: Pointer; length: DWORD; user: Pointer): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+   {
+     User stream callback function. NOTE: A stream function should obviously be as
+     quick as possible, other streams (and MOD musics) can't be mixed until
+@@ -593,12 +607,12 @@
+ 
+ const
+   // special STREAMPROCs
+-  STREAMPROC_DUMMY : STREAMPROC = STREAMPROC(0);  // "dummy" stream
+-  STREAMPROC_PUSH  : STREAMPROC = STREAMPROC(-1); // push stream
++  STREAMPROC_DUMMY {: STREAMPROC} = Pointer(0);  // "dummy" stream
++  STREAMPROC_PUSH  {: STREAMPROC} = Pointer(-1); // push stream
+ 
+ type
+ 
+-  DOWNLOADPROC = procedure(buffer: Pointer; length: DWORD; user: Pointer); stdcall;
++  DOWNLOADPROC = procedure(buffer: Pointer; length: DWORD; user: Pointer); {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+   {
+     Internet stream download callback function.
+     buffer : Buffer containing the downloaded data... NULL=end of download
+@@ -606,7 +620,7 @@
+     user   : The 'user' parameter value given when calling BASS_StreamCreateURL
+   }
+ 
+-  SYNCPROC = procedure(handle: HSYNC; channel, data: DWORD; user: Pointer); stdcall;
++  SYNCPROC = procedure(handle: HSYNC; channel, data: DWORD; user: Pointer); {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+   {
+     Sync callback function. NOTE: a sync callback function should be very
+     quick as other syncs cannot be processed until it has finished. If the
+@@ -618,7 +632,7 @@
+     user   : The 'user' parameter given when calling BASS_ChannelSetSync
+   }
+ 
+-  DSPPROC = procedure(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: Pointer); stdcall;
++  DSPPROC = procedure(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: Pointer); {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+   {
+     DSP callback function. NOTE: A DSP function should obviously be as quick
+     as possible... other DSP functions, streams and MOD musics can not be
+@@ -630,7 +644,7 @@
+     user   : The 'user' parameter given when calling BASS_ChannelSetDSP
+   }
+ 
+-  RECORDPROC = function(handle: HRECORD; buffer: Pointer; length: DWORD; user: Pointer): BOOL; stdcall;
++  RECORDPROC = function(handle: HRECORD; buffer: Pointer; length: DWORD; user: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+   {
+     Recording callback function.
+     handle : The recording handle
+@@ -643,116 +657,130 @@
+ 
+ // Functions
+ const
++{$IFDEF MSWINDOWS}
+   bassdll = 'bass.dll';
+-
+-function BASS_SetConfig(option, value: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_GetConfig(option: DWORD): DWORD; stdcall; external bassdll;
+-function BASS_SetConfigPtr(option: DWORD; value: Pointer): BOOL; stdcall; external bassdll;
+-function BASS_GetConfigPtr(option: DWORD): Pointer; stdcall; external bassdll;
+-function BASS_GetVersion: DWORD; stdcall; external bassdll;
+-function BASS_ErrorGetCode: Integer; stdcall; external bassdll;
+-function BASS_GetDeviceInfo(device: DWORD; var info: BASS_DEVICEINFO): BOOL; stdcall; external bassdll;
+-function BASS_Init(device: Integer; freq, flags: DWORD; win: HWND; clsid: PGUID): BOOL; stdcall; external bassdll;
+-function BASS_SetDevice(device: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_GetDevice: DWORD; stdcall; external bassdll;
+-function BASS_Free: BOOL; stdcall; external bassdll;
+-function BASS_GetDSoundObject(obj: DWORD): Pointer; stdcall; external bassdll;
+-function BASS_GetInfo(var info: BASS_INFO): BOOL; stdcall; external bassdll;
+-function BASS_Update(length: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_GetCPU: FLOAT; stdcall; external bassdll;
+-function BASS_Start: BOOL; stdcall; external bassdll;
+-function BASS_Stop: BOOL; stdcall; external bassdll;
+-function BASS_Pause: BOOL; stdcall; external bassdll;
+-function BASS_SetVolume(volume: FLOAT): BOOL; stdcall; external bassdll;
+-function BASS_GetVolume: FLOAT; stdcall; external bassdll;
+-
+-function BASS_PluginLoad(filename: PChar; flags: DWORD): HPLUGIN; stdcall; external bassdll;
+-function BASS_PluginFree(handle: HPLUGIN): BOOL; stdcall; external bassdll;
+-function BASS_PluginGetInfo(handle: HPLUGIN): PBASS_PLUGININFO; stdcall; external bassdll;
+-
+-function BASS_Set3DFactors(distf, rollf, doppf: FLOAT): BOOL; stdcall; external bassdll;
+-function BASS_Get3DFactors(var distf, rollf, doppf: FLOAT): BOOL; stdcall; external bassdll;
+-function BASS_Set3DPosition(var pos, vel, front, top: BASS_3DVECTOR): BOOL; stdcall; external bassdll;
+-function BASS_Get3DPosition(var pos, vel, front, top: BASS_3DVECTOR): BOOL; stdcall; external bassdll;
+-procedure BASS_Apply3D; stdcall; external bassdll;
+-function BASS_SetEAXParameters(env: Integer; vol, decay, damp: FLOAT): BOOL; stdcall; external bassdll;
+-function BASS_GetEAXParameters(var env: DWORD; var vol, decay, damp: FLOAT): BOOL; stdcall; external bassdll;
+-
+-function BASS_MusicLoad(mem: BOOL; f: Pointer; offset: QWORD; length, flags, freq: DWORD): HMUSIC; stdcall; external bassdll;
+-function BASS_MusicFree(handle: HMUSIC): BOOL; stdcall; external bassdll;
+-
+-function BASS_SampleLoad(mem: BOOL; f: Pointer; offset: QWORD; length, max, flags: DWORD): HSAMPLE; stdcall; external bassdll;
+-function BASS_SampleCreate(length, freq, chans, max, flags: DWORD): HSAMPLE; stdcall; external bassdll;
+-function BASS_SampleFree(handle: HSAMPLE): BOOL; stdcall; external bassdll;
+-function BASS_SampleSetData(handle: HSAMPLE; buffer: Pointer): BOOL; stdcall; external bassdll;
+-function BASS_SampleGetData(handle: HSAMPLE; buffer: Pointer): BOOL; stdcall; external bassdll;
+-function BASS_SampleGetInfo(handle: HSAMPLE; var info: BASS_SAMPLE): BOOL; stdcall; external bassdll;
+-function BASS_SampleSetInfo(handle: HSAMPLE; var info: BASS_SAMPLE): BOOL; stdcall; external bassdll;
+-function BASS_SampleGetChannel(handle: HSAMPLE; onlynew: BOOL): HCHANNEL; stdcall; external bassdll;
+-function BASS_SampleGetChannels(handle: HSAMPLE; channels: Pointer): DWORD; stdcall; external bassdll;
+-function BASS_SampleStop(handle: HSAMPLE): BOOL; stdcall; external bassdll;
+-
+-function BASS_StreamCreate(freq, chans, flags: DWORD; proc: STREAMPROC; user: Pointer): HSTREAM; stdcall; external bassdll;
+-function BASS_StreamCreateFile(mem: BOOL; f: Pointer; offset, length: QWORD; flags: DWORD): HSTREAM; stdcall; external bassdll;
+-function BASS_StreamCreateURL(url: PChar; offset: DWORD; flags: DWORD; proc: DOWNLOADPROC; user: Pointer):HSTREAM; stdcall; external bassdll;
+-function BASS_StreamCreateFileUser(system, flags: DWORD; var procs: BASS_FILEPROCS; user: Pointer): HSTREAM; stdcall; external bassdll;
+-function BASS_StreamFree(handle: HSTREAM): BOOL; stdcall; external bassdll;
+-function BASS_StreamGetFilePosition(handle: HSTREAM; mode: DWORD): QWORD; stdcall; external bassdll;
+-function BASS_StreamPutData(handle: HSTREAM; buffer: Pointer; length: DWORD): DWORD; stdcall; external bassdll;
+-function BASS_StreamPutFileData(handle: HSTREAM; buffer: Pointer; length: DWORD): DWORD; stdcall; external bassdll;
+-
+-function BASS_RecordGetDeviceInfo(device: DWORD; var info: BASS_DEVICEINFO): BOOL; stdcall; external bassdll;
+-function BASS_RecordInit(device: Integer):BOOL; stdcall; external bassdll;
+-function BASS_RecordSetDevice(device: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_RecordGetDevice: DWORD; stdcall; external bassdll;
+-function BASS_RecordFree: BOOL; stdcall; external bassdll;
+-function BASS_RecordGetInfo(var info: BASS_RECORDINFO): BOOL; stdcall; external bassdll;
+-function BASS_RecordGetInputName(input: Integer): PChar; stdcall; external bassdll;
+-function BASS_RecordSetInput(input: Integer; flags: DWORD; volume: FLOAT): BOOL; stdcall; external bassdll;
+-function BASS_RecordGetInput(input: Integer; var volume: FLOAT): DWORD; stdcall; external bassdll;
+-function BASS_RecordStart(freq, chans, flags: DWORD; proc: RECORDPROC; user: Pointer): HRECORD; stdcall; external bassdll;
+-
+-function BASS_ChannelBytes2Seconds(handle: DWORD; pos: QWORD): Double; stdcall;external bassdll;
+-function BASS_ChannelSeconds2Bytes(handle: DWORD; pos: Double): QWORD; stdcall;external bassdll;
+-function BASS_ChannelGetDevice(handle: DWORD): DWORD; stdcall; external bassdll;
+-function BASS_ChannelSetDevice(handle, device: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_ChannelIsActive(handle: DWORD): DWORD; stdcall;external bassdll;
+-function BASS_ChannelGetInfo(handle: DWORD; var info: BASS_CHANNELINFO):BOOL;stdcall;external bassdll;
+-function BASS_ChannelGetTags(handle: HSTREAM; tags: DWORD): PChar; stdcall; external bassdll;
+-function BASS_ChannelFlags(handle, flags, mask: DWORD): DWORD; stdcall; external bassdll;
+-function BASS_ChannelUpdate(handle, length: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_ChannelLock(handle: DWORD; lock: BOOL): BOOL; stdcall; external bassdll;
+-function BASS_ChannelPlay(handle: DWORD; restart: BOOL): BOOL; stdcall; external bassdll;
+-function BASS_ChannelStop(handle: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_ChannelPause(handle: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_ChannelSetAttribute(handle, attrib: DWORD; value: FLOAT): BOOL; stdcall; external bassdll;
+-function BASS_ChannelGetAttribute(handle, attrib: DWORD; var value: FLOAT): BOOL; stdcall; external bassdll;
+-function BASS_ChannelSlideAttribute(handle, attrib: DWORD; value: FLOAT; time: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_ChannelIsSliding(handle, attrib: DWORD): BOOL; stdcall;external bassdll;
+-function BASS_ChannelSet3DAttributes(handle: DWORD; mode: Integer; min, max: FLOAT; iangle, oangle, outvol: Integer): BOOL; stdcall; external bassdll;
+-function BASS_ChannelGet3DAttributes(handle: DWORD; var mode: DWORD; var min, max: FLOAT; var iangle, oangle, outvol: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_ChannelSet3DPosition(handle: DWORD; var pos, orient, vel: BASS_3DVECTOR): BOOL; stdcall; external bassdll;
+-function BASS_ChannelGet3DPosition(handle: DWORD; var pos, orient, vel: BASS_3DVECTOR): BOOL; stdcall; external bassdll;
+-function BASS_ChannelGetLength(handle, mode: DWORD): QWORD; stdcall; external bassdll;
+-function BASS_ChannelSetPosition(handle: DWORD; pos: QWORD; mode: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_ChannelGetPosition(handle, mode: DWORD): QWORD; stdcall; external bassdll;
+-function BASS_ChannelGetLevel(handle: DWORD): DWORD; stdcall; external bassdll;
+-function BASS_ChannelGetData(handle: DWORD; buffer: Pointer; length: DWORD): DWORD; stdcall; external bassdll;
+-function BASS_ChannelSetSync(handle: DWORD; type_: DWORD; param: QWORD; proc: SYNCPROC; user: Pointer): HSYNC; stdcall; external bassdll;
+-function BASS_ChannelRemoveSync(handle: DWORD; sync: HSYNC): BOOL; stdcall; external bassdll;
+-function BASS_ChannelSetDSP(handle: DWORD; proc: DSPPROC; user: Pointer; priority: Integer): HDSP; stdcall; external bassdll;
+-function BASS_ChannelRemoveDSP(handle: DWORD; dsp: HDSP): BOOL; stdcall; external bassdll;
+-function BASS_ChannelSetLink(handle, chan: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_ChannelRemoveLink(handle, chan: DWORD): BOOL; stdcall; external bassdll;
+-function BASS_ChannelSetFX(handle, type_: DWORD; priority: Integer): HFX; stdcall; external bassdll;
+-function BASS_ChannelRemoveFX(handle: DWORD; fx: HFX): BOOL; stdcall; external bassdll;
+-
+-function BASS_FXSetParameters(handle: HFX; par: Pointer): BOOL; stdcall; external bassdll;
+-function BASS_FXGetParameters(handle: HFX; par: Pointer): BOOL; stdcall; external bassdll;
+-function BASS_FXReset(handle: HFX): BOOL; stdcall; external bassdll;
++{$ENDIF}
++{$IFDEF DARWIN}
++  bassdll = 'libbass.dylib';
++{$ENDIF}
++
++function BASS_SetConfig(option, value: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_GetConfig(option: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SetConfigPtr(option: DWORD; value: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_GetConfigPtr(option: DWORD): Pointer; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_GetVersion: DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ErrorGetCode: Integer; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_GetDeviceInfo(device: DWORD; var info: BASS_DEVICEINFO): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++{$IFDEF MSWINDOWS}
++function BASS_Init(device: Integer; freq, flags: DWORD; win: HWND; clsid: PGUID): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++{$ELSE}
++function BASS_Init(device: Integer; freq, flags: DWORD; win: Pointer; clsid: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++{$ENDIF}
++function BASS_SetDevice(device: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_GetDevice: DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_Free: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++{$IFDEF MSWINDOWS}
++function BASS_GetDSoundObject(obj: DWORD): Pointer; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++{$ENDIF}
++function BASS_GetInfo(var info: BASS_INFO): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_Update(length: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_GetCPU: FLOAT; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_Start: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_Stop: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_Pause: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SetVolume(volume: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_GetVolume: FLOAT; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++
++function BASS_PluginLoad(filename: PChar; flags: DWORD): HPLUGIN; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_PluginFree(handle: HPLUGIN): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_PluginGetInfo(handle: HPLUGIN): PBASS_PLUGININFO; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++
++function BASS_Set3DFactors(distf, rollf, doppf: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_Get3DFactors(var distf, rollf, doppf: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_Set3DPosition(var pos, vel, front, top: BASS_3DVECTOR): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_Get3DPosition(var pos, vel, front, top: BASS_3DVECTOR): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++procedure BASS_Apply3D; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++{$IFDEF MSWINDOWS}
++function BASS_SetEAXParameters(env: Integer; vol, decay, damp: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_GetEAXParameters(var env: DWORD; var vol, decay, damp: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++{$ENDIF}
++
++function BASS_MusicLoad(mem: BOOL; f: Pointer; offset: QWORD; length, flags, freq: DWORD): HMUSIC; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_MusicFree(handle: HMUSIC): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++
++function BASS_SampleLoad(mem: BOOL; f: Pointer; offset: QWORD; length, max, flags: DWORD): HSAMPLE; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SampleCreate(length, freq, chans, max, flags: DWORD): HSAMPLE; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SampleFree(handle: HSAMPLE): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SampleSetData(handle: HSAMPLE; buffer: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SampleGetData(handle: HSAMPLE; buffer: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SampleGetInfo(handle: HSAMPLE; var info: BASS_SAMPLE): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SampleSetInfo(handle: HSAMPLE; var info: BASS_SAMPLE): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SampleGetChannel(handle: HSAMPLE; onlynew: BOOL): HCHANNEL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SampleGetChannels(handle: HSAMPLE; channels: Pointer): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_SampleStop(handle: HSAMPLE): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++
++function BASS_StreamCreate(freq, chans, flags: DWORD; proc: STREAMPROC; user: Pointer): HSTREAM; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_StreamCreateFile(mem: BOOL; f: Pointer; offset, length: QWORD; flags: DWORD): HSTREAM; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_StreamCreateURL(url: PChar; offset: DWORD; flags: DWORD; proc: DOWNLOADPROC; user: Pointer):HSTREAM; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_StreamCreateFileUser(system, flags: DWORD; var procs: BASS_FILEPROCS; user: Pointer): HSTREAM; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_StreamFree(handle: HSTREAM): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_StreamGetFilePosition(handle: HSTREAM; mode: DWORD): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_StreamPutData(handle: HSTREAM; buffer: Pointer; length: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_StreamPutFileData(handle: HSTREAM; buffer: Pointer; length: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++
++function BASS_RecordGetDeviceInfo(device: DWORD; var info: BASS_DEVICEINFO): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_RecordInit(device: Integer):BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_RecordSetDevice(device: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_RecordGetDevice: DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_RecordFree: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_RecordGetInfo(var info: BASS_RECORDINFO): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_RecordGetInputName(input: Integer): PChar; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_RecordSetInput(input: Integer; flags: DWORD; volume: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_RecordGetInput(input: Integer; var volume: FLOAT): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_RecordStart(freq, chans, flags: DWORD; proc: RECORDPROC; user: Pointer): HRECORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++
++function BASS_ChannelBytes2Seconds(handle: DWORD; pos: QWORD): Double; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
++function BASS_ChannelSeconds2Bytes(handle: DWORD; pos: Double): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
++function BASS_ChannelGetDevice(handle: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelSetDevice(handle, device: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelIsActive(handle: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
++function BASS_ChannelGetInfo(handle: DWORD; var info: BASS_CHANNELINFO):BOOL;{$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
++function BASS_ChannelGetTags(handle: HSTREAM; tags: DWORD): PChar; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelFlags(handle, flags, mask: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelUpdate(handle, length: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelLock(handle: DWORD; lock: BOOL): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelPlay(handle: DWORD; restart: BOOL): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelStop(handle: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelPause(handle: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelSetAttribute(handle, attrib: DWORD; value: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelGetAttribute(handle, attrib: DWORD; var value: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelSlideAttribute(handle, attrib: DWORD; value: FLOAT; time: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelIsSliding(handle, attrib: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
++function BASS_ChannelSet3DAttributes(handle: DWORD; mode: Integer; min, max: FLOAT; iangle, oangle, outvol: Integer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelGet3DAttributes(handle: DWORD; var mode: DWORD; var min, max: FLOAT; var iangle, oangle, outvol: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelSet3DPosition(handle: DWORD; var pos, orient, vel: BASS_3DVECTOR): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelGet3DPosition(handle: DWORD; var pos, orient, vel: BASS_3DVECTOR): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelGetLength(handle, mode: DWORD): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelSetPosition(handle: DWORD; pos: QWORD; mode: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelGetPosition(handle, mode: DWORD): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelGetLevel(handle: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelGetData(handle: DWORD; buffer: Pointer; length: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelSetSync(handle: DWORD; type_: DWORD; param: QWORD; proc: SYNCPROC; user: Pointer): HSYNC; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelRemoveSync(handle: DWORD; sync: HSYNC): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelSetDSP(handle: DWORD; proc: DSPPROC; user: Pointer; priority: Integer): HDSP; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelRemoveDSP(handle: DWORD; dsp: HDSP): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelSetLink(handle, chan: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelRemoveLink(handle, chan: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelSetFX(handle, type_: DWORD; priority: Integer): HFX; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_ChannelRemoveFX(handle: DWORD; fx: HFX): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++
++function BASS_FXSetParameters(handle: HFX; par: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_FXGetParameters(handle: HFX; par: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
++function BASS_FXReset(handle: HFX): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+ 
+ 
+ function BASS_SPEAKER_N(n: DWORD): DWORD;
++{$IFDEF MSWINDOWS}
+ function BASS_SetEAXPreset(env: Integer): BOOL;
+ {
+   This function is defined in the implementation part of this unit.
+@@ -760,7 +788,7 @@
+   to set the predefined EAX environments.
+   env    : a EAX_ENVIRONMENT_xxx constant
+ }
+-
++{$ENDIF}
+ 
+ implementation
+ 
+@@ -769,6 +797,7 @@
+   Result := n shl 24;
+ end;
+ 
++{$IFDEF MSWINDOWS}
+ function BASS_SetEAXPreset(env: Integer): BOOL;
+ begin
+   case (env) of
+@@ -828,6 +857,7 @@
+       Result := FALSE;
+   end;
+ end;
++{$ENDIF}
+ 
+ end.
+ // END OF FILE /////////////////////////////////////////////////////////////////
diff --git a/songmanagement/src/lib/bass/delphi/bass.pas b/songmanagement/src/lib/bass/delphi/bass.pas
new file mode 100644
index 00000000..e87b05f5
--- /dev/null
+++ b/songmanagement/src/lib/bass/delphi/bass.pas
@@ -0,0 +1,941 @@
+{
+  BASS 2.4 Delphi unit
+  Copyright (c) 1999-2009 Un4seen Developments Ltd.
+
+  See the BASS.CHM file for more detailed documentation
+
+  How to install
+  --------------
+  Copy BASS.PAS to the \LIB subdirectory of your Delphi path or your project dir
+
+  NOTE: Delphi 2009 users should use the BASS_UNICODE flag where possible
+}
+
+unit Bass;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$PACKRECORDS C}
+{$ENDIF}
+
+{$IFDEF MSWINDOWS}
+  {$DEFINE DLL_STDCALL}
+{$ELSE}
+  {$DEFINE DLL_CDECL}
+{$ENDIF}
+
+{$IFDEF MSWINDOWS}
+uses
+  Windows;
+{$ENDIF}
+
+const
+  BASSVERSION = $204;             // API version
+  BASSVERSIONTEXT = '2.4';
+
+  // Use these to test for error from functions that return a DWORD or QWORD
+  DW_ERROR = LongWord(-1); // -1 (DWORD)
+  QW_ERROR = Int64(-1);    // -1 (QWORD)
+
+  // Error codes returned by BASS_ErrorGetCode()
+  BASS_OK                 = 0;    // all is OK
+  BASS_ERROR_MEM          = 1;    // memory error
+  BASS_ERROR_FILEOPEN     = 2;    // can't open the file
+  BASS_ERROR_DRIVER       = 3;    // can't find a free sound driver
+  BASS_ERROR_BUFLOST      = 4;    // the sample buffer was lost
+  BASS_ERROR_HANDLE       = 5;    // invalid handle
+  BASS_ERROR_FORMAT       = 6;    // unsupported sample format
+  BASS_ERROR_POSITION     = 7;    // invalid position
+  BASS_ERROR_INIT         = 8;    // BASS_Init has not been successfully called
+  BASS_ERROR_START        = 9;    // BASS_Start has not been successfully called
+  BASS_ERROR_ALREADY      = 14;   // already initialized/paused/whatever
+  BASS_ERROR_NOCHAN       = 18;   // can't get a free channel
+  BASS_ERROR_ILLTYPE      = 19;   // an illegal type was specified
+  BASS_ERROR_ILLPARAM     = 20;   // an illegal parameter was specified
+  BASS_ERROR_NO3D         = 21;   // no 3D support
+  BASS_ERROR_NOEAX        = 22;   // no EAX support
+  BASS_ERROR_DEVICE       = 23;   // illegal device number
+  BASS_ERROR_NOPLAY       = 24;   // not playing
+  BASS_ERROR_FREQ         = 25;   // illegal sample rate
+  BASS_ERROR_NOTFILE      = 27;   // the stream is not a file stream
+  BASS_ERROR_NOHW         = 29;   // no hardware voices available
+  BASS_ERROR_EMPTY        = 31;   // the MOD music has no sequence data
+  BASS_ERROR_NONET        = 32;   // no internet connection could be opened
+  BASS_ERROR_CREATE       = 33;   // couldn't create the file
+  BASS_ERROR_NOFX         = 34;   // effects are not enabled
+  BASS_ERROR_NOTAVAIL     = 37;   // requested data is not available
+  BASS_ERROR_DECODE       = 38;   // the channel is a "decoding channel"
+  BASS_ERROR_DX           = 39;   // a sufficient DirectX version is not installed
+  BASS_ERROR_TIMEOUT      = 40;   // connection timedout
+  BASS_ERROR_FILEFORM     = 41;   // unsupported file format
+  BASS_ERROR_SPEAKER      = 42;   // unavailable speaker
+  BASS_ERROR_VERSION      = 43;   // invalid BASS version (used by add-ons)
+  BASS_ERROR_CODEC        = 44;   // codec is not available/supported
+  BASS_ERROR_ENDED        = 45;   // the channel/file has ended
+  BASS_ERROR_UNKNOWN      = -1;   // some other mystery problem
+
+  // BASS_SetConfig options
+  BASS_CONFIG_BUFFER        = 0;
+  BASS_CONFIG_UPDATEPERIOD  = 1;
+  BASS_CONFIG_GVOL_SAMPLE   = 4;
+  BASS_CONFIG_GVOL_STREAM   = 5;
+  BASS_CONFIG_GVOL_MUSIC    = 6;
+  BASS_CONFIG_CURVE_VOL     = 7;
+  BASS_CONFIG_CURVE_PAN     = 8;
+  BASS_CONFIG_FLOATDSP      = 9;
+  BASS_CONFIG_3DALGORITHM   = 10;
+  BASS_CONFIG_NET_TIMEOUT   = 11;
+  BASS_CONFIG_NET_BUFFER    = 12;
+  BASS_CONFIG_PAUSE_NOPLAY  = 13;
+  BASS_CONFIG_NET_PREBUF    = 15;
+  BASS_CONFIG_NET_PASSIVE   = 18;
+  BASS_CONFIG_REC_BUFFER    = 19;
+  BASS_CONFIG_NET_PLAYLIST  = 21;
+  BASS_CONFIG_MUSIC_VIRTUAL = 22;
+  BASS_CONFIG_VERIFY        = 23;
+  BASS_CONFIG_UPDATETHREADS = 24;
+  {$IFDEF LINUX}
+  BASS_CONFIG_DEV_BUFFER    = 27;
+  {$ENDIF}
+
+  // BASS_SetConfigPtr options
+  BASS_CONFIG_NET_AGENT     = 16;
+  BASS_CONFIG_NET_PROXY     = 17;
+
+  // Initialization flags
+  BASS_DEVICE_8BITS       = 1;    // use 8 bit resolution, else 16 bit
+  BASS_DEVICE_MONO        = 2;    // use mono, else stereo
+  BASS_DEVICE_3D          = 4;    // enable 3D functionality
+  BASS_DEVICE_LATENCY     = 256;  // calculate device latency (BASS_INFO struct)
+  BASS_DEVICE_CPSPEAKERS  = 1024; // detect speakers via Windows control panel
+  BASS_DEVICE_SPEAKERS    = 2048; // force enabling of speaker assignment
+  BASS_DEVICE_NOSPEAKER   = 4096; // ignore speaker arrangement
+  {$IFDEF LINUX}
+  BASS_DEVICE_DMIX        = 8192; // use "dmix" (shared) output
+  {$ENDIF}
+
+  // DirectSound interfaces (for use with BASS_GetDSoundObject)
+  BASS_OBJECT_DS          = 1;   // IDirectSound
+  BASS_OBJECT_DS3DL       = 2;   // IDirectSound3DListener
+
+  // BASS_DEVICEINFO flags
+  BASS_DEVICE_ENABLED     = 1;
+  BASS_DEVICE_DEFAULT     = 2;
+  BASS_DEVICE_INIT        = 4;
+
+  // BASS_INFO flags (from DSOUND.H)
+  DSCAPS_CONTINUOUSRATE   = $00000010;     // supports all sample rates between min/maxrate
+  DSCAPS_EMULDRIVER       = $00000020;     // device does NOT have hardware DirectSound support
+  DSCAPS_CERTIFIED        = $00000040;     // device driver has been certified by Microsoft
+  DSCAPS_SECONDARYMONO    = $00000100;     // mono
+  DSCAPS_SECONDARYSTEREO  = $00000200;     // stereo
+  DSCAPS_SECONDARY8BIT    = $00000400;     // 8 bit
+  DSCAPS_SECONDARY16BIT   = $00000800;     // 16 bit
+
+  // BASS_RECORDINFO flags (from DSOUND.H)
+  DSCCAPS_EMULDRIVER = DSCAPS_EMULDRIVER;  // device does NOT have hardware DirectSound recording support
+  DSCCAPS_CERTIFIED = DSCAPS_CERTIFIED;    // device driver has been certified by Microsoft
+
+  // defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H)
+  WAVE_FORMAT_1M08       = $00000001;      // 11.025 kHz, Mono,   8-bit
+  WAVE_FORMAT_1S08       = $00000002;      // 11.025 kHz, Stereo, 8-bit
+  WAVE_FORMAT_1M16       = $00000004;      // 11.025 kHz, Mono,   16-bit
+  WAVE_FORMAT_1S16       = $00000008;      // 11.025 kHz, Stereo, 16-bit
+  WAVE_FORMAT_2M08       = $00000010;      // 22.05  kHz, Mono,   8-bit
+  WAVE_FORMAT_2S08       = $00000020;      // 22.05  kHz, Stereo, 8-bit
+  WAVE_FORMAT_2M16       = $00000040;      // 22.05  kHz, Mono,   16-bit
+  WAVE_FORMAT_2S16       = $00000080;      // 22.05  kHz, Stereo, 16-bit
+  WAVE_FORMAT_4M08       = $00000100;      // 44.1   kHz, Mono,   8-bit
+  WAVE_FORMAT_4S08       = $00000200;      // 44.1   kHz, Stereo, 8-bit
+  WAVE_FORMAT_4M16       = $00000400;      // 44.1   kHz, Mono,   16-bit
+  WAVE_FORMAT_4S16       = $00000800;      // 44.1   kHz, Stereo, 16-bit
+
+  BASS_SAMPLE_8BITS       = 1;   // 8 bit
+  BASS_SAMPLE_FLOAT       = 256; // 32-bit floating-point
+  BASS_SAMPLE_MONO        = 2;   // mono
+  BASS_SAMPLE_LOOP        = 4;   // looped
+  BASS_SAMPLE_3D          = 8;   // 3D functionality
+  BASS_SAMPLE_SOFTWARE    = 16;  // not using hardware mixing
+  BASS_SAMPLE_MUTEMAX     = 32;  // mute at max distance (3D only)
+  BASS_SAMPLE_VAM         = 64;  // DX7 voice allocation & management
+  BASS_SAMPLE_FX          = 128; // old implementation of DX8 effects
+  BASS_SAMPLE_OVER_VOL    = $10000; // override lowest volume
+  BASS_SAMPLE_OVER_POS    = $20000; // override longest playing
+  BASS_SAMPLE_OVER_DIST   = $30000; // override furthest from listener (3D only)
+
+  BASS_STREAM_PRESCAN     = $20000; // enable pin-point seeking/length (MP3/MP2/MP1)
+  BASS_MP3_SETPOS         = BASS_STREAM_PRESCAN;
+  BASS_STREAM_AUTOFREE	  = $40000; // automatically free the stream when it stop/ends
+  BASS_STREAM_RESTRATE	  = $80000; // restrict the download rate of internet file streams
+  BASS_STREAM_BLOCK       = $100000;// download/play internet file stream in small blocks
+  BASS_STREAM_DECODE      = $200000;// don't play the stream, only decode (BASS_ChannelGetData)
+  BASS_STREAM_STATUS      = $800000;// give server status info (HTTP/ICY tags) in DOWNLOADPROC
+
+  BASS_MUSIC_FLOAT        = BASS_SAMPLE_FLOAT;
+  BASS_MUSIC_MONO         = BASS_SAMPLE_MONO;
+  BASS_MUSIC_LOOP         = BASS_SAMPLE_LOOP;
+  BASS_MUSIC_3D           = BASS_SAMPLE_3D;
+  BASS_MUSIC_FX           = BASS_SAMPLE_FX;
+  BASS_MUSIC_AUTOFREE     = BASS_STREAM_AUTOFREE;
+  BASS_MUSIC_DECODE       = BASS_STREAM_DECODE;
+  BASS_MUSIC_PRESCAN      = BASS_STREAM_PRESCAN; // calculate playback length
+  BASS_MUSIC_CALCLEN      = BASS_MUSIC_PRESCAN;
+  BASS_MUSIC_RAMP         = $200;  // normal ramping
+  BASS_MUSIC_RAMPS        = $400;  // sensitive ramping
+  BASS_MUSIC_SURROUND     = $800;  // surround sound
+  BASS_MUSIC_SURROUND2    = $1000; // surround sound (mode 2)
+  BASS_MUSIC_FT2MOD       = $2000; // play .MOD as FastTracker 2 does
+  BASS_MUSIC_PT1MOD       = $4000; // play .MOD as ProTracker 1 does
+  BASS_MUSIC_NONINTER     = $10000; // non-interpolated sample mixing
+  BASS_MUSIC_SINCINTER    = $800000; // sinc interpolated sample mixing
+  BASS_MUSIC_POSRESET     = $8000; // stop all notes when moving position
+  BASS_MUSIC_POSRESETEX   = $400000; // stop all notes and reset bmp/etc when moving position
+  BASS_MUSIC_STOPBACK     = $80000; // stop the music on a backwards jump effect
+  BASS_MUSIC_NOSAMPLE     = $100000; // don't load the samples
+
+  // Speaker assignment flags
+  BASS_SPEAKER_FRONT      = $1000000;  // front speakers
+  BASS_SPEAKER_REAR       = $2000000;  // rear/side speakers
+  BASS_SPEAKER_CENLFE     = $3000000;  // center & LFE speakers (5.1)
+  BASS_SPEAKER_REAR2      = $4000000;  // rear center speakers (7.1)
+  BASS_SPEAKER_LEFT       = $10000000; // modifier: left
+  BASS_SPEAKER_RIGHT      = $20000000; // modifier: right
+  BASS_SPEAKER_FRONTLEFT  = BASS_SPEAKER_FRONT or BASS_SPEAKER_LEFT;
+  BASS_SPEAKER_FRONTRIGHT = BASS_SPEAKER_FRONT or BASS_SPEAKER_RIGHT;
+  BASS_SPEAKER_REARLEFT   = BASS_SPEAKER_REAR or BASS_SPEAKER_LEFT;
+  BASS_SPEAKER_REARRIGHT  = BASS_SPEAKER_REAR or BASS_SPEAKER_RIGHT;
+  BASS_SPEAKER_CENTER     = BASS_SPEAKER_CENLFE or BASS_SPEAKER_LEFT;
+  BASS_SPEAKER_LFE        = BASS_SPEAKER_CENLFE or BASS_SPEAKER_RIGHT;
+  BASS_SPEAKER_REAR2LEFT  = BASS_SPEAKER_REAR2 or BASS_SPEAKER_LEFT;
+  BASS_SPEAKER_REAR2RIGHT = BASS_SPEAKER_REAR2 or BASS_SPEAKER_RIGHT;
+
+  BASS_UNICODE            = $80000000;
+
+  BASS_RECORD_PAUSE       = $8000; // start recording paused
+
+  // DX7 voice allocation & management flags
+  BASS_VAM_HARDWARE       = 1;
+  BASS_VAM_SOFTWARE       = 2;
+  BASS_VAM_TERM_TIME      = 4;
+  BASS_VAM_TERM_DIST      = 8;
+  BASS_VAM_TERM_PRIO      = 16;
+
+  // BASS_CHANNELINFO types
+  BASS_CTYPE_SAMPLE       = 1;
+  BASS_CTYPE_RECORD       = 2;
+  BASS_CTYPE_STREAM       = $10000;
+  BASS_CTYPE_STREAM_OGG   = $10002;
+  BASS_CTYPE_STREAM_MP1   = $10003;
+  BASS_CTYPE_STREAM_MP2   = $10004;
+  BASS_CTYPE_STREAM_MP3   = $10005;
+  BASS_CTYPE_STREAM_AIFF  = $10006;
+  BASS_CTYPE_STREAM_CA    = $10007;
+  BASS_CTYPE_STREAM_WAV   = $40000; // WAVE flag, LOWORD=codec
+  BASS_CTYPE_STREAM_WAV_PCM = $50001;
+  BASS_CTYPE_STREAM_WAV_FLOAT = $50003;
+  BASS_CTYPE_MUSIC_MOD    = $20000;
+  BASS_CTYPE_MUSIC_MTM    = $20001;
+  BASS_CTYPE_MUSIC_S3M    = $20002;
+  BASS_CTYPE_MUSIC_XM     = $20003;
+  BASS_CTYPE_MUSIC_IT     = $20004;
+  BASS_CTYPE_MUSIC_MO3    = $00100; // MO3 flag
+
+  // 3D channel modes
+  BASS_3DMODE_NORMAL      = 0; // normal 3D processing
+  BASS_3DMODE_RELATIVE    = 1; // position is relative to the listener
+  BASS_3DMODE_OFF         = 2; // no 3D processing
+
+  // software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM)
+  BASS_3DALG_DEFAULT      = 0;
+  BASS_3DALG_OFF          = 1;
+  BASS_3DALG_FULL         = 2;
+  BASS_3DALG_LIGHT        = 3;
+
+  // EAX environments, use with BASS_SetEAXParameters
+  EAX_ENVIRONMENT_GENERIC           = 0;
+  EAX_ENVIRONMENT_PADDEDCELL        = 1;
+  EAX_ENVIRONMENT_ROOM              = 2;
+  EAX_ENVIRONMENT_BATHROOM          = 3;
+  EAX_ENVIRONMENT_LIVINGROOM        = 4;
+  EAX_ENVIRONMENT_STONEROOM         = 5;
+  EAX_ENVIRONMENT_AUDITORIUM        = 6;
+  EAX_ENVIRONMENT_CONCERTHALL       = 7;
+  EAX_ENVIRONMENT_CAVE              = 8;
+  EAX_ENVIRONMENT_ARENA             = 9;
+  EAX_ENVIRONMENT_HANGAR            = 10;
+  EAX_ENVIRONMENT_CARPETEDHALLWAY   = 11;
+  EAX_ENVIRONMENT_HALLWAY           = 12;
+  EAX_ENVIRONMENT_STONECORRIDOR     = 13;
+  EAX_ENVIRONMENT_ALLEY             = 14;
+  EAX_ENVIRONMENT_FOREST            = 15;
+  EAX_ENVIRONMENT_CITY              = 16;
+  EAX_ENVIRONMENT_MOUNTAINS         = 17;
+  EAX_ENVIRONMENT_QUARRY            = 18;
+  EAX_ENVIRONMENT_PLAIN             = 19;
+  EAX_ENVIRONMENT_PARKINGLOT        = 20;
+  EAX_ENVIRONMENT_SEWERPIPE         = 21;
+  EAX_ENVIRONMENT_UNDERWATER        = 22;
+  EAX_ENVIRONMENT_DRUGGED           = 23;
+  EAX_ENVIRONMENT_DIZZY             = 24;
+  EAX_ENVIRONMENT_PSYCHOTIC         = 25;
+  // total number of environments
+  EAX_ENVIRONMENT_COUNT             = 26;
+
+  BASS_STREAMPROC_END = $80000000; // end of user stream flag
+
+
+  // BASS_StreamCreateFileUser file systems
+  STREAMFILE_NOBUFFER     = 0;
+  STREAMFILE_BUFFER       = 1;
+  STREAMFILE_BUFFERPUSH   = 2;
+
+  // BASS_StreamPutFileData options
+  BASS_FILEDATA_END       = 0; // end & close the file
+
+  // BASS_StreamGetFilePosition modes
+  BASS_FILEPOS_CURRENT    = 0;
+  BASS_FILEPOS_DECODE     = BASS_FILEPOS_CURRENT;
+  BASS_FILEPOS_DOWNLOAD   = 1;
+  BASS_FILEPOS_END        = 2;
+  BASS_FILEPOS_START      = 3;
+  BASS_FILEPOS_CONNECTED  = 4;
+  BASS_FILEPOS_BUFFER     = 5;
+
+  // BASS_ChannelSetSync types
+  BASS_SYNC_POS           = 0;
+  BASS_SYNC_END           = 2;
+  BASS_SYNC_META          = 4;
+  BASS_SYNC_SLIDE         = 5;
+  BASS_SYNC_STALL         = 6;
+  BASS_SYNC_DOWNLOAD      = 7;
+  BASS_SYNC_FREE          = 8;
+  BASS_SYNC_SETPOS        = 11;
+  BASS_SYNC_MUSICPOS      = 10;
+  BASS_SYNC_MUSICINST     = 1;
+  BASS_SYNC_MUSICFX       = 3;
+  BASS_SYNC_OGG_CHANGE    = 12;
+  BASS_SYNC_MIXTIME       = $40000000; // FLAG: sync at mixtime, else at playtime
+  BASS_SYNC_ONETIME       = $80000000; // FLAG: sync only once, else continuously
+
+  // BASS_ChannelIsActive return values
+  BASS_ACTIVE_STOPPED = 0;
+  BASS_ACTIVE_PLAYING = 1;
+  BASS_ACTIVE_STALLED = 2;
+  BASS_ACTIVE_PAUSED  = 3;
+
+  // Channel attributes
+  BASS_ATTRIB_FREQ                  = 1;
+  BASS_ATTRIB_VOL                   = 2;
+  BASS_ATTRIB_PAN                   = 3;
+  BASS_ATTRIB_EAXMIX                = 4;
+  BASS_ATTRIB_MUSIC_AMPLIFY         = $100;
+  BASS_ATTRIB_MUSIC_PANSEP          = $101;
+  BASS_ATTRIB_MUSIC_PSCALER         = $102;
+  BASS_ATTRIB_MUSIC_BPM             = $103;
+  BASS_ATTRIB_MUSIC_SPEED           = $104;
+  BASS_ATTRIB_MUSIC_VOL_GLOBAL      = $105;
+  BASS_ATTRIB_MUSIC_VOL_CHAN        = $200; // + channel #
+  BASS_ATTRIB_MUSIC_VOL_INST        = $300; // + instrument #
+
+  // BASS_ChannelGetData flags
+  BASS_DATA_AVAILABLE = 0;        // query how much data is buffered
+  BASS_DATA_FLOAT     = $40000000; // flag: return floating-point sample data
+  BASS_DATA_FFT256    = $80000000; // 256 sample FFT
+  BASS_DATA_FFT512    = $80000001; // 512 FFT
+  BASS_DATA_FFT1024   = $80000002; // 1024 FFT
+  BASS_DATA_FFT2048   = $80000003; // 2048 FFT
+  BASS_DATA_FFT4096   = $80000004; // 4096 FFT
+  BASS_DATA_FFT8192   = $80000005; // 8192 FFT
+  BASS_DATA_FFT_INDIVIDUAL = $10; // FFT flag: FFT for each channel, else all combined
+  BASS_DATA_FFT_NOWINDOW = $20;   // FFT flag: no Hanning window
+
+  // BASS_ChannelGetTags types : what's returned
+  BASS_TAG_ID3        = 0; // ID3v1 tags : TAG_ID3 structure
+  BASS_TAG_ID3V2      = 1; // ID3v2 tags : variable length block
+  BASS_TAG_OGG        = 2; // OGG comments : series of null-terminated UTF-8 strings
+  BASS_TAG_HTTP       = 3; // HTTP headers : series of null-terminated ANSI strings
+  BASS_TAG_ICY        = 4; // ICY headers : series of null-terminated ANSI strings
+  BASS_TAG_META       = 5; // ICY metadata : ANSI string
+  BASS_TAG_VENDOR     = 9; // OGG encoder : UTF-8 string
+  BASS_TAG_LYRICS3    = 10; // Lyric3v2 tag : ASCII string
+  BASS_TAG_CA_CODEC   = 11; // CoreAudio codec info : TAG_CA_CODEC structure
+  BASS_TAG_RIFF_INFO  = $100; // RIFF "INFO" tags : series of null-terminated ANSI strings
+  BASS_TAG_RIFF_BEXT  = $101; // RIFF/BWF "bext" tags : TAG_BEXT structure
+  BASS_TAG_RIFF_CART  = $102; // RIFF/BWF "cart" tags : TAG_CART structure
+  BASS_TAG_MUSIC_NAME = $10000;	// MOD music name : ANSI string
+  BASS_TAG_MUSIC_MESSAGE = $10001; // MOD message : ANSI string
+  BASS_TAG_MUSIC_ORDERS = $10002; // MOD order list : BYTE array of pattern numbers
+  BASS_TAG_MUSIC_INST = $10100;	// + instrument #, MOD instrument name : ANSI string
+  BASS_TAG_MUSIC_SAMPLE = $10300; // + sample #, MOD sample name : ANSI string
+
+  // BASS_ChannelGetLength/GetPosition/SetPosition modes
+  BASS_POS_BYTE           = 0; // byte position
+  BASS_POS_MUSIC_ORDER    = 1; // order.row position, MAKELONG(order,row)
+  BASS_POS_DECODE         = $10000000; // flag: get the decoding (not playing) position
+  
+  // BASS_RecordSetInput flags
+  BASS_INPUT_OFF    = $10000;
+  BASS_INPUT_ON     = $20000;
+
+  BASS_INPUT_TYPE_MASK    = $FF000000;
+  BASS_INPUT_TYPE_UNDEF   = $00000000;
+  BASS_INPUT_TYPE_DIGITAL = $01000000;
+  BASS_INPUT_TYPE_LINE    = $02000000;
+  BASS_INPUT_TYPE_MIC     = $03000000;
+  BASS_INPUT_TYPE_SYNTH   = $04000000;
+  BASS_INPUT_TYPE_CD      = $05000000;
+  BASS_INPUT_TYPE_PHONE   = $06000000;
+  BASS_INPUT_TYPE_SPEAKER = $07000000;
+  BASS_INPUT_TYPE_WAVE    = $08000000;
+  BASS_INPUT_TYPE_AUX     = $09000000;
+  BASS_INPUT_TYPE_ANALOG  = $0A000000;
+
+  BASS_FX_DX8_CHORUS	  = 0;
+  BASS_FX_DX8_COMPRESSOR  = 1;
+  BASS_FX_DX8_DISTORTION  = 2;
+  BASS_FX_DX8_ECHO        = 3;
+  BASS_FX_DX8_FLANGER     = 4;
+  BASS_FX_DX8_GARGLE      = 5;
+  BASS_FX_DX8_I3DL2REVERB = 6;
+  BASS_FX_DX8_PARAMEQ     = 7;
+  BASS_FX_DX8_REVERB      = 8;
+
+  BASS_DX8_PHASE_NEG_180 = 0;
+  BASS_DX8_PHASE_NEG_90  = 1;
+  BASS_DX8_PHASE_ZERO    = 2;
+  BASS_DX8_PHASE_90      = 3;
+  BASS_DX8_PHASE_180     = 4;
+
+type
+  DWORD = LongWord;
+  BOOL = LongBool;
+  FLOAT = Single;
+  QWORD = Int64;
+
+  HMUSIC = DWORD;       // MOD music handle
+  HSAMPLE = DWORD;      // sample handle
+  HCHANNEL = DWORD;     // playing sample's channel handle
+  HSTREAM = DWORD;      // sample stream handle
+  HRECORD = DWORD;      // recording handle
+  HSYNC = DWORD;        // synchronizer handle
+  HDSP = DWORD;         // DSP handle
+  HFX = DWORD;          // DX8 effect handle
+  HPLUGIN = DWORD;      // Plugin handle
+
+  // Device info structure
+  BASS_DEVICEINFO = record
+    name: PAnsiChar;    // description
+    driver: PAnsiChar;  // driver
+    flags: DWORD;
+  end;
+
+  BASS_INFO = record
+    flags: DWORD;       // device capabilities (DSCAPS_xxx flags)
+    hwsize: DWORD;      // size of total device hardware memory
+    hwfree: DWORD;      // size of free device hardware memory
+    freesam: DWORD;     // number of free sample slots in the hardware
+    free3d: DWORD;      // number of free 3D sample slots in the hardware
+    minrate: DWORD;     // min sample rate supported by the hardware
+    maxrate: DWORD;     // max sample rate supported by the hardware
+    eax: BOOL;          // device supports EAX? (always FALSE if BASS_DEVICE_3D was not used)
+    minbuf: DWORD;      // recommended minimum buffer length in ms (requires BASS_DEVICE_LATENCY)
+    dsver: DWORD;       // DirectSound version
+    latency: DWORD;     // delay (in ms) before start of playback (requires BASS_DEVICE_LATENCY)
+    initflags: DWORD;   // BASS_Init "flags" parameter
+    speakers: DWORD;    // number of speakers available
+    freq: DWORD;        // current output rate (OSX only)
+  end;
+
+  // Recording device info structure
+  BASS_RECORDINFO = record
+    flags: DWORD;       // device capabilities (DSCCAPS_xxx flags)
+    formats: DWORD;     // supported standard formats (WAVE_FORMAT_xxx flags)
+    inputs: DWORD;      // number of inputs
+    singlein: BOOL;     // only 1 input can be set at a time
+    freq: DWORD;        // current input rate (OSX only)
+  end;
+
+  // Sample info structure
+  BASS_SAMPLE = record
+    freq: DWORD;        // default playback rate
+    volume: FLOAT;      // default volume (0-100)
+    pan: FLOAT;         // default pan (-100=left, 0=middle, 100=right)
+    flags: DWORD;       // BASS_SAMPLE_xxx flags
+    length: DWORD;      // length (in samples, not bytes)
+    max: DWORD;         // maximum simultaneous playbacks
+    origres: DWORD;     // original resolution
+    chans: DWORD;       // number of channels
+    mingap: DWORD;      // minimum gap (ms) between creating channels
+    mode3d: DWORD;      // BASS_3DMODE_xxx mode
+    mindist: FLOAT;     // minimum distance
+    maxdist: FLOAT;     // maximum distance
+    iangle: DWORD;      // angle of inside projection cone
+    oangle: DWORD;      // angle of outside projection cone
+    outvol: FLOAT;      // delta-volume outside the projection cone
+    vam: DWORD;         // voice allocation/management flags (BASS_VAM_xxx)
+    priority: DWORD;    // priority (0=lowest, $ffffffff=highest)
+  end;
+
+  // Channel info structure
+  BASS_CHANNELINFO = record
+    freq: DWORD;        // default playback rate
+    chans: DWORD;       // channels
+    flags: DWORD;       // BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags
+    ctype: DWORD;       // type of channel
+    origres: DWORD;     // original resolution
+    plugin: HPLUGIN;    // plugin
+    sample: HSAMPLE;    // sample
+    filename: PChar;    // filename
+  end;
+
+  BASS_PLUGINFORM = record
+    ctype: DWORD;       // channel type
+    name: PAnsiChar;    // format description
+    exts: PAnsiChar;    // file extension filter (*.ext1;*.ext2;etc...)
+  end;
+  PBASS_PLUGINFORMS = ^TBASS_PLUGINFORMS;
+  TBASS_PLUGINFORMS = array[0..maxInt div sizeOf(BASS_PLUGINFORM) - 1] of BASS_PLUGINFORM;
+
+  BASS_PLUGININFO = record
+    version: DWORD;             // version (same form as BASS_GetVersion)
+    formatc: DWORD;             // number of formats
+    formats: PBASS_PLUGINFORMS; // the array of formats
+  end;
+  PBASS_PLUGININFO = ^BASS_PLUGININFO;
+
+  // 3D vector (for 3D positions/velocities/orientations)
+  BASS_3DVECTOR = record
+    x: FLOAT;           // +=right, -=left
+    y: FLOAT;           // +=up, -=down
+    z: FLOAT;           // +=front, -=behind
+  end;
+
+  // User file stream callback functions
+  FILECLOSEPROC = procedure(user: Pointer); {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+  FILELENPROC = function(user: Pointer): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+  FILEREADPROC = function(buffer: Pointer; length: DWORD; user: Pointer): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+  FILESEEKPROC = function(offset: QWORD; user: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+
+  BASS_FILEPROCS = record
+    close: FILECLOSEPROC;
+    length: FILELENPROC;
+    read: FILEREADPROC;
+    seek: FILESEEKPROC;
+  end;
+
+  // ID3v1 tag structure
+  TAG_ID3 = record
+    id: Array[0..2] of AnsiChar;
+    title: Array[0..29] of AnsiChar;
+    artist: Array[0..29] of AnsiChar;
+    album: Array[0..29] of AnsiChar;
+    year: Array[0..3] of AnsiChar;
+    comment: Array[0..29] of AnsiChar;
+    genre: Byte;
+  end;
+
+  // BWF "bext" tag structure
+  TAG_BEXT = record
+    Description: Array[0..255] of AnsiChar;     // description
+    Originator: Array[0..31] of AnsiChar;       // name of the originator
+    OriginatorReference: Array[0..31] of AnsiChar; // reference of the originator
+    OriginationDate: Array[0..9] of AnsiChar;   // date of creation (yyyy-mm-dd)
+    OriginationTime: Array[0..7] of AnsiChar;   // time of creation (hh-mm-ss)
+    TimeReference: QWORD;                       // first sample count since midnight (little-endian)
+    Version: Word;                              // BWF version (little-endian)
+    UMID: Array[0..63] of Byte;                 // SMPTE UMID
+    Reserved: Array[0..189] of Byte;
+    CodingHistory: Array of AnsiChar;           // history
+  end;
+
+  // BWF "cart" tag structures
+  TAG_CART_TIMER = record
+	dwUsage: DWORD;					// FOURCC timer usage ID
+	dwValue: DWORD;					// timer value in samples from head
+  end;
+
+  TAG_CART = record
+	Version: array [0..3] of AnsiChar;				// version of the data structure
+	Title: array [0..63] of AnsiChar;				// title of cart audio sequence
+	Artist: array [0..63] of AnsiChar;				// artist or creator name
+	CutID: array [0..63] of AnsiChar;				// cut number identification
+	ClientID: array [0..63] of AnsiChar;			// client identification
+	Category: array [0..63] of AnsiChar;			// category ID, PSA, NEWS, etc
+	Classification: array [0..63] of AnsiChar;		// classification or auxiliary key
+	OutCue: array [0..63] of AnsiChar;				// out cue text
+	StartDate: array [0..9] of AnsiChar;			// yyyy-mm-dd
+	StartTime: array [0..7] of AnsiChar;			// hh:mm:ss
+	EndDate: array [0..9] of AnsiChar;				// yyyy-mm-dd
+	EndTime: array [0..7] of AnsiChar;				// hh:mm:ss
+	ProducerAppID: array [0..63] of AnsiChar;		// name of vendor or application
+	ProducerAppVersion: array [0..63] of AnsiChar;	// version of producer application
+	UserDef: array [0..63] of AnsiChar;				// user defined text
+	dwLevelReference: DWORD;						// sample value for 0 dB reference
+	PostTimer: array [0..7] of TAG_CART_TIMER;		// 8 time markers after head
+	Reserved: array [0..275] of AnsiChar;
+	URL: array [0..1023] of AnsiChar;				// uniform resource locator
+	TagText: array [0..0] of AnsiChar;				// free form text for scripts or tags
+  end;
+  
+  // CoreAudio codec info structure
+  TAG_CA_CODEC = record
+	ftype: DWORD;					// file format
+	atype: DWORD;					// audio format
+	name: {const} PAnsiChar;		// description
+  end;
+  
+  BASS_DX8_CHORUS = record
+    fWetDryMix: FLOAT;
+    fDepth: FLOAT;
+    fFeedback: FLOAT;
+    fFrequency: FLOAT;
+    lWaveform: DWORD;   // 0=triangle, 1=sine
+    fDelay: FLOAT;
+    lPhase: DWORD;      // BASS_DX8_PHASE_xxx
+  end;
+
+  BASS_DX8_COMPRESSOR = record
+    fGain: FLOAT;
+    fAttack: FLOAT;
+    fRelease: FLOAT;
+    fThreshold: FLOAT;
+    fRatio: FLOAT;
+    fPredelay: FLOAT;
+  end;
+
+  BASS_DX8_DISTORTION = record
+    fGain: FLOAT;
+    fEdge: FLOAT;
+    fPostEQCenterFrequency: FLOAT;
+    fPostEQBandwidth: FLOAT;
+    fPreLowpassCutoff: FLOAT;
+  end;
+
+  BASS_DX8_ECHO = record
+    fWetDryMix: FLOAT;
+    fFeedback: FLOAT;
+    fLeftDelay: FLOAT;
+    fRightDelay: FLOAT;
+    lPanDelay: BOOL;
+  end;
+
+  BASS_DX8_FLANGER = record
+    fWetDryMix: FLOAT;
+    fDepth: FLOAT;
+    fFeedback: FLOAT;
+    fFrequency: FLOAT;
+    lWaveform: DWORD;   // 0=triangle, 1=sine
+    fDelay: FLOAT;
+    lPhase: DWORD;      // BASS_DX8_PHASE_xxx
+  end;
+
+  BASS_DX8_GARGLE = record
+    dwRateHz: DWORD;               // Rate of modulation in hz
+    dwWaveShape: DWORD;            // 0=triangle, 1=square
+  end;
+
+  BASS_DX8_I3DL2REVERB = record
+    lRoom: LongInt;                // [-10000, 0]      default: -1000 mB
+    lRoomHF: LongInt;              // [-10000, 0]      default: 0 mB
+    flRoomRolloffFactor: FLOAT;    // [0.0, 10.0]      default: 0.0
+    flDecayTime: FLOAT;            // [0.1, 20.0]      default: 1.49s
+    flDecayHFRatio: FLOAT;         // [0.1, 2.0]       default: 0.83
+    lReflections: LongInt;         // [-10000, 1000]   default: -2602 mB
+    flReflectionsDelay: FLOAT;     // [0.0, 0.3]       default: 0.007 s
+    lReverb: LongInt;              // [-10000, 2000]   default: 200 mB
+    flReverbDelay: FLOAT;          // [0.0, 0.1]       default: 0.011 s
+    flDiffusion: FLOAT;            // [0.0, 100.0]     default: 100.0 %
+    flDensity: FLOAT;              // [0.0, 100.0]     default: 100.0 %
+    flHFReference: FLOAT;          // [20.0, 20000.0]  default: 5000.0 Hz
+  end;
+
+  BASS_DX8_PARAMEQ = record
+    fCenter: FLOAT;
+    fBandwidth: FLOAT;
+    fGain: FLOAT;
+  end;
+
+  BASS_DX8_REVERB = record
+    fInGain: FLOAT;                // [-96.0,0.0]            default: 0.0 dB
+    fReverbMix: FLOAT;             // [-96.0,0.0]            default: 0.0 db
+    fReverbTime: FLOAT;            // [0.001,3000.0]         default: 1000.0 ms
+    fHighFreqRTRatio: FLOAT;       // [0.001,0.999]          default: 0.001
+  end;
+
+  // callback function types
+  STREAMPROC = function(handle: HSTREAM; buffer: Pointer; length: DWORD; user: Pointer): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+  {
+    User stream callback function. NOTE: A stream function should obviously be as
+    quick as possible, other streams (and MOD musics) can't be mixed until
+    it's finished.
+    handle : The stream that needs writing
+    buffer : Buffer to write the samples in
+    length : Number of bytes to write
+    user   : The 'user' parameter value given when calling BASS_StreamCreate
+    RETURN : Number of bytes written. Set the BASS_STREAMPROC_END flag to end
+             the stream.
+  }
+
+const
+  // special STREAMPROCs
+  STREAMPROC_DUMMY {: STREAMPROC} = Pointer(0);  // "dummy" stream
+  STREAMPROC_PUSH  {: STREAMPROC} = Pointer(-1); // push stream
+
+type
+
+  DOWNLOADPROC = procedure(buffer: Pointer; length: DWORD; user: Pointer); {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+  {
+    Internet stream download callback function.
+    buffer : Buffer containing the downloaded data... NULL=end of download
+    length : Number of bytes in the buffer
+    user   : The 'user' parameter value given when calling BASS_StreamCreateURL
+  }
+
+  SYNCPROC = procedure(handle: HSYNC; channel, data: DWORD; user: Pointer); {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+  {
+    Sync callback function. NOTE: a sync callback function should be very
+    quick as other syncs cannot be processed until it has finished. If the
+    sync is a "mixtime" sync, then other streams and MOD musics can not be
+    mixed until it's finished either.
+    handle : The sync that has occured
+    channel: Channel that the sync occured in
+    data   : Additional data associated with the sync's occurance
+    user   : The 'user' parameter given when calling BASS_ChannelSetSync
+  }
+
+  DSPPROC = procedure(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: Pointer); {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+  {
+    DSP callback function. NOTE: A DSP function should obviously be as quick
+    as possible... other DSP functions, streams and MOD musics can not be
+    processed until it's finished.
+    handle : The DSP handle
+    channel: Channel that the DSP is being applied to
+    buffer : Buffer to apply the DSP to
+    length : Number of bytes in the buffer
+    user   : The 'user' parameter given when calling BASS_ChannelSetDSP
+  }
+
+  RECORDPROC = function(handle: HRECORD; buffer: Pointer; length: DWORD; user: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}
+  {
+    Recording callback function.
+    handle : The recording handle
+    buffer : Buffer containing the recorded sample data
+    length : Number of bytes
+    user   : The 'user' parameter value given when calling BASS_RecordStart
+    RETURN : TRUE = continue recording, FALSE = stop
+  }
+
+
+// Functions
+const
+{$IFDEF MSWINDOWS}
+  bassdll = 'bass.dll';
+{$ENDIF}
+{$IFDEF LINUX}
+  bassdll = 'bass';
+{$ENDIF}
+{$IFDEF DARWIN}
+  bassdll = 'libbass.dylib';
+  {$linklib libbass}
+{$ENDIF}
+
+function BASS_SetConfig(option, value: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_GetConfig(option: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SetConfigPtr(option: DWORD; value: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_GetConfigPtr(option: DWORD): Pointer; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_GetVersion: DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ErrorGetCode: LongInt; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_GetDeviceInfo(device: DWORD; var info: BASS_DEVICEINFO): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+{$IFDEF MSWINDOWS}
+function BASS_Init(device: LongInt; freq, flags: DWORD; win: HWND; clsid: PGUID): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+{$ELSE}
+function BASS_Init(device: LongInt; freq, flags: DWORD; win: Pointer; clsid: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+{$ENDIF}
+function BASS_SetDevice(device: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_GetDevice: DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_Free: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+{$IFDEF MSWINDOWS}
+function BASS_GetDSoundObject(obj: DWORD): Pointer; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+{$ENDIF}
+function BASS_GetInfo(var info: BASS_INFO): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_Update(length: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_GetCPU: FLOAT; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_Start: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_Stop: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_Pause: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SetVolume(volume: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_GetVolume: FLOAT; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+
+function BASS_PluginLoad(filename: PChar; flags: DWORD): HPLUGIN; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_PluginFree(handle: HPLUGIN): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_PluginGetInfo(handle: HPLUGIN): PBASS_PLUGININFO; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+
+function BASS_Set3DFactors(distf, rollf, doppf: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_Get3DFactors(var distf, rollf, doppf: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_Set3DPosition(var pos, vel, front, top: BASS_3DVECTOR): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_Get3DPosition(var pos, vel, front, top: BASS_3DVECTOR): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+procedure BASS_Apply3D; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+{$IFDEF MSWINDOWS}
+function BASS_SetEAXParameters(env: LongInt; vol, decay, damp: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_GetEAXParameters(var env: DWORD; var vol, decay, damp: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+{$ENDIF}
+
+function BASS_MusicLoad(mem: BOOL; f: Pointer; offset: QWORD; length, flags, freq: DWORD): HMUSIC; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_MusicFree(handle: HMUSIC): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+
+function BASS_SampleLoad(mem: BOOL; f: Pointer; offset: QWORD; length, max, flags: DWORD): HSAMPLE; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SampleCreate(length, freq, chans, max, flags: DWORD): HSAMPLE; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SampleFree(handle: HSAMPLE): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SampleSetData(handle: HSAMPLE; buffer: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SampleGetData(handle: HSAMPLE; buffer: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SampleGetInfo(handle: HSAMPLE; var info: BASS_SAMPLE): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SampleSetInfo(handle: HSAMPLE; var info: BASS_SAMPLE): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SampleGetChannel(handle: HSAMPLE; onlynew: BOOL): HCHANNEL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SampleGetChannels(handle: HSAMPLE; channels: Pointer): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_SampleStop(handle: HSAMPLE): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+
+function BASS_StreamCreate(freq, chans, flags: DWORD; proc: STREAMPROC; user: Pointer): HSTREAM; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_StreamCreateFile(mem: BOOL; f: Pointer; offset, length: QWORD; flags: DWORD): HSTREAM; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_StreamCreateURL(url: PAnsiChar; offset: DWORD; flags: DWORD; proc: DOWNLOADPROC; user: Pointer):HSTREAM; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_StreamCreateFileUser(system, flags: DWORD; var procs: BASS_FILEPROCS; user: Pointer): HSTREAM; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_StreamFree(handle: HSTREAM): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_StreamGetFilePosition(handle: HSTREAM; mode: DWORD): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_StreamPutData(handle: HSTREAM; buffer: Pointer; length: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_StreamPutFileData(handle: HSTREAM; buffer: Pointer; length: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+
+function BASS_RecordGetDeviceInfo(device: DWORD; var info: BASS_DEVICEINFO): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_RecordInit(device: LongInt):BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_RecordSetDevice(device: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_RecordGetDevice: DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_RecordFree: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_RecordGetInfo(var info: BASS_RECORDINFO): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_RecordGetInputName(input: LongInt): PAnsiChar; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_RecordSetInput(input: LongInt; flags: DWORD; volume: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_RecordGetInput(input: LongInt; var volume: FLOAT): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_RecordStart(freq, chans, flags: DWORD; proc: RECORDPROC; user: Pointer): HRECORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+
+function BASS_ChannelBytes2Seconds(handle: DWORD; pos: QWORD): Double; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
+function BASS_ChannelSeconds2Bytes(handle: DWORD; pos: Double): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
+function BASS_ChannelGetDevice(handle: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelSetDevice(handle, device: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelIsActive(handle: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
+function BASS_ChannelGetInfo(handle: DWORD; var info: BASS_CHANNELINFO):BOOL;{$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
+function BASS_ChannelGetTags(handle: HSTREAM; tags: DWORD): PAnsiChar; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelFlags(handle, flags, mask: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelUpdate(handle, length: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelLock(handle: DWORD; lock: BOOL): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelPlay(handle: DWORD; restart: BOOL): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelStop(handle: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelPause(handle: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelSetAttribute(handle, attrib: DWORD; value: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelGetAttribute(handle, attrib: DWORD; var value: FLOAT): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelSlideAttribute(handle, attrib: DWORD; value: FLOAT; time: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelIsSliding(handle, attrib: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF}external bassdll;
+function BASS_ChannelSet3DAttributes(handle: DWORD; mode: LongInt; min, max: FLOAT; iangle, oangle, outvol: LongInt): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelGet3DAttributes(handle: DWORD; var mode: DWORD; var min, max: FLOAT; var iangle, oangle, outvol: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelSet3DPosition(handle: DWORD; var pos, orient, vel: BASS_3DVECTOR): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelGet3DPosition(handle: DWORD; var pos, orient, vel: BASS_3DVECTOR): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelGetLength(handle, mode: DWORD): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelSetPosition(handle: DWORD; pos: QWORD; mode: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelGetPosition(handle, mode: DWORD): QWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelGetLevel(handle: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelGetData(handle: DWORD; buffer: Pointer; length: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelSetSync(handle: DWORD; type_: DWORD; param: QWORD; proc: SYNCPROC; user: Pointer): HSYNC; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelRemoveSync(handle: DWORD; sync: HSYNC): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelSetDSP(handle: DWORD; proc: DSPPROC; user: Pointer; priority: LongInt): HDSP; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelRemoveDSP(handle: DWORD; dsp: HDSP): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelSetLink(handle, chan: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelRemoveLink(handle, chan: DWORD): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelSetFX(handle, type_: DWORD; priority: LongInt): HFX; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_ChannelRemoveFX(handle: DWORD; fx: HFX): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+
+function BASS_FXSetParameters(handle: HFX; par: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_FXGetParameters(handle: HFX; par: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+function BASS_FXReset(handle: HFX): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+
+
+function BASS_SPEAKER_N(n: DWORD): DWORD;
+{$IFDEF MSWINDOWS}
+function BASS_SetEAXPreset(env: LongInt): BOOL;
+{
+  This function is defined in the implementation part of this unit.
+  It is not part of BASS.DLL but an extra function which makes it easier
+  to set the predefined EAX environments.
+  env    : a EAX_ENVIRONMENT_xxx constant
+}
+{$ENDIF}
+
+implementation
+
+function BASS_SPEAKER_N(n: DWORD): DWORD;
+begin
+  Result := n shl 24;
+end;
+
+{$IFDEF MSWINDOWS}
+function BASS_SetEAXPreset(env: LongInt): BOOL;
+begin
+  case (env) of
+    EAX_ENVIRONMENT_GENERIC:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_GENERIC, 0.5, 1.493, 0.5);
+    EAX_ENVIRONMENT_PADDEDCELL:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_PADDEDCELL, 0.25, 0.1, 0);
+    EAX_ENVIRONMENT_ROOM:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_ROOM, 0.417, 0.4, 0.666);
+    EAX_ENVIRONMENT_BATHROOM:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_BATHROOM, 0.653, 1.499, 0.166);
+    EAX_ENVIRONMENT_LIVINGROOM:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_LIVINGROOM, 0.208, 0.478, 0);
+    EAX_ENVIRONMENT_STONEROOM:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_STONEROOM, 0.5, 2.309, 0.888);
+    EAX_ENVIRONMENT_AUDITORIUM:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_AUDITORIUM, 0.403, 4.279, 0.5);
+    EAX_ENVIRONMENT_CONCERTHALL:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_CONCERTHALL, 0.5, 3.961, 0.5);
+    EAX_ENVIRONMENT_CAVE:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_CAVE, 0.5, 2.886, 1.304);
+    EAX_ENVIRONMENT_ARENA:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_ARENA, 0.361, 7.284, 0.332);
+    EAX_ENVIRONMENT_HANGAR:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_HANGAR, 0.5, 10.0, 0.3);
+    EAX_ENVIRONMENT_CARPETEDHALLWAY:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153, 0.259, 2.0);
+    EAX_ENVIRONMENT_HALLWAY:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_HALLWAY, 0.361, 1.493, 0);
+    EAX_ENVIRONMENT_STONECORRIDOR:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_STONECORRIDOR, 0.444, 2.697, 0.638);
+    EAX_ENVIRONMENT_ALLEY:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_ALLEY, 0.25, 1.752, 0.776);
+    EAX_ENVIRONMENT_FOREST:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_FOREST, 0.111, 3.145, 0.472);
+    EAX_ENVIRONMENT_CITY:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_CITY, 0.111, 2.767, 0.224);
+    EAX_ENVIRONMENT_MOUNTAINS:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_MOUNTAINS, 0.194, 7.841, 0.472);
+    EAX_ENVIRONMENT_QUARRY:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_QUARRY, 1, 1.499, 0.5);
+    EAX_ENVIRONMENT_PLAIN:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_PLAIN, 0.097, 2.767, 0.224);
+    EAX_ENVIRONMENT_PARKINGLOT:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_PARKINGLOT, 0.208, 1.652, 1.5);
+    EAX_ENVIRONMENT_SEWERPIPE:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_SEWERPIPE, 0.652, 2.886, 0.25);
+    EAX_ENVIRONMENT_UNDERWATER:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_UNDERWATER, 1, 1.499, 0);
+    EAX_ENVIRONMENT_DRUGGED:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_DRUGGED, 0.875, 8.392, 1.388);
+    EAX_ENVIRONMENT_DIZZY:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_DIZZY, 0.139, 17.234, 0.666);
+    EAX_ENVIRONMENT_PSYCHOTIC:
+      Result := BASS_SetEAXParameters(EAX_ENVIRONMENT_PSYCHOTIC, 0.486, 7.563, 0.806);
+    else
+      Result := FALSE;
+  end;
+end;
+{$ENDIF}
+
+end.
+// END OF FILE /////////////////////////////////////////////////////////////////
+
diff --git a/songmanagement/src/lib/collections/CollArray.pas b/songmanagement/src/lib/collections/CollArray.pas
new file mode 100644
index 00000000..a10ba905
--- /dev/null
+++ b/songmanagement/src/lib/collections/CollArray.pas
@@ -0,0 +1,183 @@
+unit CollArray;
+
+(*****************************************************************************
+ * Copyright 2003 by Matthew Greet
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details. (http://opensource.org/licenses/lgpl-license.php)
+ * 
+ * See http://www.warmachine.u-net.com/delphi_collections for updates and downloads.
+ *
+ * $Version: v1.0.3 $
+ * $Revision: 1.2 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollArray.qbt $
+ * 
+ *   Colllection implementations based on arrays.
+ * 
+ * Revision 1.2  by: Matthew Greet  Rev date: 12/06/04 20:02:16
+ *   Capacity property.
+ * 
+ * Revision 1.1  by: Matthew Greet  Rev date: 06/04/03 10:30:36
+ *   Size property dropped. 
+ *   Unused abstract functions still implemented.
+ * 
+ * Revision 1.0  by: Matthew Greet  Rev date: 01/03/03 10:50:02
+ *   Initial revision.
+ *
+ * FPC compatibility fixes by: UltraStar Deluxe Team
+ *
+ * $Endlog$
+ *****************************************************************************)
+
+{$IFDEF FPC}
+  {$MODE Delphi}{$H+}
+{$ENDIF}
+ 
+interface
+
+uses
+    Collections;
+
+type
+    TArray = class(TAbstractList)
+    private
+        FArray: array of ICollectable;
+    protected
+        function TrueGetItem(Index: Integer): ICollectable; override;
+        procedure TrueSetItem(Index: Integer; const Value: ICollectable); override;
+        procedure TrueAppend(const Item: ICollectable); override;
+        procedure TrueClear; override;
+        function TrueDelete(Index: Integer): ICollectable; override;
+        procedure TrueInsert(Index: Integer; const Item: ICollectable); override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean = false); override;
+        constructor Create(Size: Integer; NaturalItemsOnly: Boolean = false); overload; virtual;
+        constructor Create(const Collection: ICollection); override;
+        destructor Destroy; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetFixedSize: Boolean; override;
+        function GetSize: Integer; override;
+    end;
+
+implementation
+
+constructor TArray.Create(NaturalItemsOnly: Boolean);
+begin
+    Create(0, NaturalItemsOnly);
+end;
+
+constructor TArray.Create(Size: Integer; NaturalItemsOnly: Boolean = false);
+begin
+    inherited Create(NaturalItemsOnly);
+    SetLength(FArray, Size);
+end;
+
+constructor TArray.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+var
+    Item: ICollectable;
+    ItemError: TCollectionError;
+    I: Integer;
+begin
+    inherited Create(ItemArray, NaturalItemsOnly);
+    SetLength(FArray, Length(ItemArray));
+    for I := Low(ItemArray) to High(ItemArray) do
+    begin
+        Item := ItemArray[I];
+        ItemError := ItemAllowed(Item);
+        if ItemError <> ceOK then
+        begin
+            CollectionError(ItemError);
+        end
+        else
+            Items[I] := Item;
+    end;
+end;
+
+constructor TArray.Create(const Collection: ICollection);
+var
+    Iterator: IIterator;
+    I: Integer;
+begin
+    inherited Create(Collection);
+    SetLength(FArray, Collection.GetSize);
+    Iterator := Collection.GetIterator;
+    I := 0;
+    while not Iterator.EOF do
+    begin
+        Items[I] := Iterator.CurrentItem;
+        Inc(I);
+        Iterator.Next;
+    end;
+end;
+
+destructor TArray.Destroy;
+var
+    I: Integer;
+begin
+    // Delete interface references to all items
+    for I := Low(FArray) to High(FArray) do
+    begin
+        FArray[I] := nil;
+    end;
+    inherited Destroy;
+end;
+
+function TArray.TrueGetItem(Index: Integer): ICollectable;
+begin
+    Result := FArray[Index];
+end;
+
+procedure TArray.TrueSetItem(Index: Integer; const Value: ICollectable);
+begin
+    FArray[Index] := Value;
+end;
+
+procedure TArray.TrueAppend(const Item: ICollectable);
+begin
+    // Ignored as collection is fixed size
+end;
+
+procedure TArray.TrueClear;
+begin
+    // Ignored as collection is fixed size
+end;
+
+function TArray.TrueDelete(Index: Integer): ICollectable;
+begin
+    // Ignored as collection is fixed size
+end;
+
+procedure TArray.TrueInsert(Index: Integer; const Item: ICollectable);
+begin
+    // Ignored as collection is fixed size
+end;
+
+function TArray.GetCapacity: Integer;
+begin
+    Result := Size;
+end;
+
+procedure TArray.SetCapacity(Value: Integer);
+begin
+    // Ignored
+end;
+
+function TArray.GetFixedSize: Boolean;
+begin
+    Result := true;
+end;
+
+function TArray.GetSize: Integer;
+begin
+    Result := Length(FArray);
+end;
+
+end.
diff --git a/songmanagement/src/lib/collections/CollHash.pas b/songmanagement/src/lib/collections/CollHash.pas
new file mode 100644
index 00000000..796fc740
--- /dev/null
+++ b/songmanagement/src/lib/collections/CollHash.pas
@@ -0,0 +1,1497 @@
+unit CollHash;
+
+(*****************************************************************************
+ * Copyright 2003 by Matthew Greet
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details. (http://opensource.org/licenses/lgpl-license.php)
+ * 
+ * See http://www.warmachine.u-net.com/delphi_collections for updates and downloads.
+ *
+ * $Version: v1.0.3 $
+ * $Revision: 1.1.1.2 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollHash.qbt $
+ * 
+ *   Collection implementations based on hash tables.
+ * 
+ * Revision 1.1.1.2  by: Matthew Greet  Rev date: 12/06/04 20:04:30
+ *   Capacity property.
+ * 
+ * Revision 1.1.1.1  by: Matthew Greet  Rev date: 24/10/03 16:48:16
+ *   v1.0 branch.
+ * 
+ * Revision 1.1  by: Matthew Greet  Rev date: 06/04/03 10:40:16
+ *   Added integer map and string map versions. 
+ *   THashSet uses its own implementation, not THashMap. 
+ *   DefaulMaxLoadFactor changed.
+ * 
+ * Revision 1.0  by: Matthew Greet  Rev date: 01/03/03 10:50:02
+ *   Initial revision.
+ * 
+ * FPC compatibility fixes by: UltraStar Deluxe Team
+ *
+ * $Endlog$
+ *****************************************************************************)
+
+{$IFDEF FPC}
+  {$MODE Delphi}{$H+}
+{$ENDIF}
+ 
+interface
+
+uses
+    Classes, Math,
+    Collections;
+
+const
+    DefaultTableSize = 100;
+    MaxLoadFactorMin = 0.01;        // Minimum allowed value for MaxLoadFactor property.
+    DefaultMaxLoadFactor = 5.0;
+
+type
+    THashMap = class(TAbstractMap)
+    private
+        FArray: TListArray;
+        FCapacity: Integer;
+        FMaxLoadFactor: Double;
+        FSize: Integer;
+        FTableSize: Integer;
+    protected
+        function GetAssociationIterator: IMapIterator; override;
+        procedure SetMaxLoadFactor(Value: Double); virtual;
+        procedure SetTableSize(Value: Integer); virtual;
+        procedure ChangeCapacity(Value: TListArray); virtual;
+        procedure CheckLoadFactor(AlwaysChangeCapacity: Boolean); virtual;
+        function GetHash(const Key: ICollectable): Integer; virtual;
+        function GetKeyPosition(const Key: ICollectable): TCollectionPosition; override;
+        procedure Rehash;
+        procedure TrueClear; override;
+        function TrueGet(Position: TCollectionPosition): IAssociation; override;
+        function TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation; override;
+        function TrueRemove2(Position: TCollectionPosition): IAssociation; override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); override;
+        destructor Destroy; override;
+        class function GetAlwaysNaturalKeys: Boolean; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetNaturalKeyIID: TGUID; override;
+        function GetSize: Integer; override;
+        property MaxLoadFactor: Double read FMaxLoadFactor write SetMaxLoadFactor;
+        property TableSize: Integer read FTableSize write SetTableSize;
+    end;
+
+    THashSet = class(TAbstractSet)
+    private
+        FArray: TListArray;
+        FCapacity: Integer;
+        FMaxLoadFactor: Double;
+        FSize: Integer;
+        FTableSize: Integer;
+    protected
+        procedure SetMaxLoadFactor(Value: Double); virtual;
+        procedure SetTableSize(Value: Integer); virtual;
+        procedure ChangeCapacity(Value: TListArray); virtual;
+        procedure CheckLoadFactor(AlwaysChangeCapacity: Boolean); virtual;
+        function GetHash(const Item: ICollectable): Integer; virtual;
+        function GetPosition(const Item: ICollectable): TCollectionPosition; override;
+        procedure Rehash;
+        procedure TrueAdd2(Position: TCollectionPosition; const Item: ICollectable); override;
+        procedure TrueClear; override;
+        function TrueGet(Position: TCollectionPosition): ICollectable; override;
+        procedure TrueRemove2(Position: TCollectionPosition); override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        destructor Destroy; override;
+        class function GetAlwaysNaturalItems: Boolean; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetIterator: IIterator; override;
+        function GetNaturalItemIID: TGUID; override;
+        function GetSize: Integer; override;
+        property MaxLoadFactor: Double read FMaxLoadFactor write SetMaxLoadFactor;
+        property TableSize: Integer read FTableSize write SetTableSize;
+    end;
+
+    THashIntegerMap = class(TAbstractIntegerMap)
+    private
+        FArray: TListArray;
+        FCapacity: Integer;
+        FMaxLoadFactor: Double;
+        FSize: Integer;
+        FTableSize: Integer;
+    protected
+        function GetAssociationIterator: IIntegerMapIterator; override;
+        procedure SetMaxLoadFactor(Value: Double); virtual;
+        procedure SetTableSize(Value: Integer); virtual;
+        procedure ChangeCapacity(Value: TListArray); virtual;
+        procedure CheckLoadFactor(AlwaysChangeCapacity: Boolean); virtual;
+        function GetHash(const Key: Integer): Integer; virtual;
+        function GetKeyPosition(const Key: Integer): TCollectionPosition; override;
+        procedure Rehash;
+        procedure TrueClear; override;
+        function TrueGet(Position: TCollectionPosition): IIntegerAssociation; override;
+        function TruePut(Position: TCollectionPosition; const Association: IIntegerAssociation): IIntegerAssociation; override;
+        function TrueRemove2(Position: TCollectionPosition): IIntegerAssociation; override;
+    public
+        constructor Create; override;
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        constructor Create(NaturalItemsOnly: Boolean; TableSize: Integer; MaxLoadFactor: Double = DefaultMaxLoadFactor); overload; virtual;
+        destructor Destroy; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetSize: Integer; override;
+        property MaxLoadFactor: Double read FMaxLoadFactor write SetMaxLoadFactor;
+        property TableSize: Integer read FTableSize write SetTableSize;
+    end;
+
+    THashStringMap = class(TAbstractStringMap)
+    private
+        FArray: TListArray;
+        FCapacity: Integer;
+        FMaxLoadFactor: Double;
+        FSize: Integer;
+        FTableSize: Integer;
+    protected
+        function GetAssociationIterator: IStringMapIterator; override;
+        procedure SetMaxLoadFactor(Value: Double); virtual;
+        procedure SetTableSize(Value: Integer); virtual;
+        procedure ChangeCapacity(Value: TListArray); virtual;
+        procedure CheckLoadFactor(AlwaysChangeCapacity: Boolean); virtual;
+        function GetHash(const Key: String): Integer; virtual;
+        function GetKeyPosition(const Key: String): TCollectionPosition; override;
+        procedure Rehash;
+        procedure TrueClear; override;
+        function TrueGet(Position: TCollectionPosition): IStringAssociation; override;
+        function TruePut(Position: TCollectionPosition; const Association: IStringAssociation): IStringAssociation; override;
+        function TrueRemove2(Position: TCollectionPosition): IStringAssociation; override;
+    public
+        constructor Create; override;
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        constructor Create(NaturalItemsOnly: Boolean; TableSize: Integer; MaxLoadFactor: Double = DefaultMaxLoadFactor); overload; virtual;
+        destructor Destroy; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetSize: Integer; override;
+        property MaxLoadFactor: Double read FMaxLoadFactor write SetMaxLoadFactor;
+        property TableSize: Integer read FTableSize write SetTableSize;
+    end;
+
+implementation
+
+const
+    (* (sqrt(5) - 1)/2
+        See Introduction to Algorithms in Pascal, 1995, by Thomas W. Parsons,
+        published by John Wiley & Sons, Inc, ISBN 0-471-11600-9
+    *)
+    HashFactor = 0.618033988749894848204586834365638;
+
+type
+    THashIterator = class(TAbstractIterator)
+    private
+        FHashSet: THashSet;
+        FHash: Integer;
+        FChainIndex: Integer;
+    protected
+        constructor Create(HashSet: THashSet);
+        function TrueFirst: ICollectable; override;
+        function TrueNext: ICollectable; override;
+        procedure TrueRemove; override;
+    end;
+
+    THashAssociationIterator = class(TAbstractAssociationIterator)
+    private
+        FHashMap: THashMap;
+        FHash: Integer;
+        FChainIndex: Integer;
+    protected
+        constructor Create(HashMap: THashMap);
+        function TrueFirst: IAssociation; override;
+        function TrueNext: IAssociation; override;
+        procedure TrueRemove; override;
+    end;
+
+    THashIntegerIterator = class(TAbstractIntegerAssociationIterator)
+    private
+        FHashIntegerMap: THashIntegerMap;
+        FHash: Integer;
+        FChainIndex: Integer;
+    protected
+        constructor Create(HashIntegerMap: THashIntegerMap);
+        function TrueFirst: IIntegerAssociation; override;
+        function TrueNext: IIntegerAssociation; override;
+        procedure TrueRemove; override;
+    end;
+
+    THashStringIterator = class(TAbstractStringAssociationIterator)
+    private
+        FHashStringMap: THashStringMap;
+        FHash: Integer;
+        FChainIndex: Integer;
+    protected
+        constructor Create(HashStringMap: THashStringMap);
+        function TrueFirst: IStringAssociation; override;
+        function TrueNext: IStringAssociation; override;
+        procedure TrueRemove; override;
+    end;
+
+    THashPosition = class(TCollectionPosition)
+    private
+        FChain: TList;
+        FIndex: Integer;
+    public
+        constructor Create(Found: Boolean; Chain: TList; Index: Integer);
+        property Chain: TList read FChain;
+        property Index: Integer read FIndex;
+    end;
+
+{ THashMap }
+constructor THashMap.Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+var
+    I: Integer;
+begin
+    // Force use of natural keys
+    inherited Create(NaturalItemsOnly, true);
+    FTableSize := DefaultTableSize;
+    FMaxLoadFactor := DefaultMaxLoadFactor;
+    SetLength(FArray, FTableSize);
+    for I := Low(FArray) to High(FArray) do
+        FArray[I] := TList.Create;
+    FCapacity := 0;
+    FSize := 0;
+    ChangeCapacity(FArray);
+end;
+
+destructor THashMap.Destroy;
+var
+    I: Integer;
+begin
+    for I := Low(FArray) to High(FArray) do
+        FArray[I].Free;
+    FArray := nil;
+    inherited Destroy;
+end;
+
+class function THashMap.GetAlwaysNaturalKeys: Boolean;
+begin
+    Result := true;
+end;
+
+function THashMap.GetNaturalKeyIID: TGUID;
+begin
+    Result := HashableIID;
+end;
+
+function THashMap.GetAssociationIterator: IMapIterator;
+begin
+    Result := THashAssociationIterator.Create(Self);
+end;
+
+procedure THashMap.SetTableSize(Value: Integer);
+begin
+    if (FTableSize <> Value) and (Value >= 1) then
+    begin
+        FTableSize := Value;
+        Rehash;
+    end;
+end;
+
+procedure THashMap.SetMaxLoadFactor(Value: Double);
+begin
+    if (FMaxLoadFactor <> Value) and (Value >= MaxLoadFactorMin) then
+    begin
+        FMaxLoadFactor := Value;
+        CheckLoadFactor(false);
+    end;
+end;
+
+procedure THashMap.ChangeCapacity(Value: TListArray);
+var
+    Chain: TList;
+    I, Total, ChainCapacity: Integer;
+begin
+    if FCapacity mod FTableSize = 0 then
+        ChainCapacity := Trunc(FCapacity / FTableSize)
+    else
+        ChainCapacity := Trunc(FCapacity / FTableSize) + 1;
+    Total := 0;
+    for I := Low(Value) to High(Value) do
+    begin
+        Chain := Value[I];
+        Chain.Capacity := ChainCapacity;
+        Total := Total + Chain.Capacity;
+    end;
+    FCapacity := Total;
+end;
+
+procedure THashMap.CheckLoadFactor(AlwaysChangeCapacity: Boolean);
+var
+    LoadFactor: Double;
+begin
+    LoadFactor := Capacity / TableSize;
+    if LoadFactor > MaxLoadFactor then
+        TableSize := Trunc(Capacity / Max(MaxLoadFactor, MaxLoadFactorMin))
+    else if AlwaysChangeCapacity then
+        ChangeCapacity(FArray);
+end;
+
+function THashMap.GetHash(const Key: ICollectable): Integer;
+var
+    Hashable: IHashable;
+    HashCode: Cardinal;
+begin
+    Key.QueryInterface(IHashable, Hashable);
+    HashCode := Hashable.HashCode;
+    Result := Trunc(Frac(HashCode * HashFactor) * TableSize);
+end;
+
+function THashMap.GetKeyPosition(const Key: ICollectable): TCollectionPosition;
+var
+    Chain: TList;
+    I: Integer;
+    Success: Boolean;
+begin
+    Chain := FArray[GetHash(Key)];
+    Success := false;
+    for I := 0 to Chain.Count - 1 do
+    begin
+        Success := KeyComparator.Equals(Key, IAssociation(Chain[I]).GetKey);
+        if Success then
+            Break;
+    end;
+    Result := THashPosition.Create(Success, Chain, I);
+end;
+
+procedure THashMap.Rehash;
+var
+    NewArray: TListArray;
+    OldChain, NewChain: TList;
+    Association: IAssociation;
+    Total: Integer;
+    I, J: Integer;
+    Hash: Integer;
+begin
+    // Create new chains
+    SetLength(NewArray, TableSize);
+    for I := Low(NewArray) to High(NewArray) do
+    begin
+        NewChain := TList.Create;
+        NewArray[I] := NewChain;
+    end;
+    ChangeCapacity(NewArray);
+
+    // Transfer from old chains to new and drop old
+    for I := Low(FArray) to High(FArray) do
+    begin
+        OldChain := FArray[I];
+        for J := 0 to OldChain.Count - 1 do
+        begin
+            Association := IAssociation(OldChain[J]);
+            Hash := GetHash(Association.GetKey);
+            NewArray[Hash].Add(Pointer(Association));
+        end;
+        OldChain.Free;
+    end;
+    FArray := NewArray;
+
+    // Find actual, new capacity
+    Total := 0;
+    for I := Low(FArray) to High(FArray) do
+    begin
+        NewChain := FArray[I];
+        Total := Total + NewChain.Capacity;
+    end;
+    FCapacity := Total;
+end;
+
+procedure THashMap.TrueClear;
+var
+    Association: IAssociation;
+    Chain: TList;
+    I, J: Integer;
+begin
+    for I := Low(FArray) to High(FArray) do
+    begin
+        Chain := FArray[I];
+        for J := 0 to Chain.Count - 1 do
+        begin
+            Association := IAssociation(Chain[J]);
+            Chain[J] := nil;
+            // Storing interface reference as a pointer does not update reference
+            // count automatically, so this must be done manually
+            Association._Release;
+        end;
+        Chain.Clear;
+    end;
+    FSize := 0;
+end;
+
+function THashMap.TrueGet(Position: TCollectionPosition): IAssociation;
+var
+    HashPosition: THashPosition;
+begin
+    HashPosition := THashPosition(Position);
+    Result := IAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+end;
+
+function THashMap.TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation;
+var
+    HashPosition: THashPosition;
+    OldAssociation: IAssociation;
+begin
+    HashPosition := THashPosition(Position);
+    if HashPosition.Found then
+    begin
+        OldAssociation := IAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+        HashPosition.Chain.Items[HashPosition.Index] := Pointer(Association);
+        Result := OldAssociation;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        Association._AddRef;
+        OldAssociation._Release;
+    end
+    else
+    begin
+        HashPosition.Chain.Add(Pointer(Association));
+        Inc(FSize);
+        Result := nil;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        Association._AddRef;
+    end;
+end;
+
+function THashMap.TrueRemove2(Position: TCollectionPosition): IAssociation;
+var
+    Association: IAssociation;
+    HashPosition: THashPosition;
+begin
+    HashPosition := THashPosition(Position);
+    Association := IAssociation(TrueGet(Position));
+    HashPosition.Chain.Delete(HashPosition.Index);
+    Dec(FSize);
+    Result := Association;
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Association._Release;
+end;
+
+function THashMap.GetCapacity;
+begin
+    Result := FCapacity;
+end;
+
+procedure THashMap.SetCapacity(Value: Integer);
+begin
+    FCapacity := Value;
+    CheckLoadFactor(true);
+end;
+
+function THashMap.GetSize: Integer;
+begin
+    Result := FSize;
+end;
+
+{ THashSet }
+constructor THashSet.Create(NaturalItemsOnly: Boolean);
+var
+    I: Integer;
+begin
+    // Force use of natural items
+    inherited Create(true);
+    FTableSize := DefaultTableSize;
+    FMaxLoadFactor := DefaultMaxLoadFactor;
+    SetLength(FArray, FTableSize);
+    for I := Low(FArray) to High(FArray) do
+        FArray[I] := TList.Create;
+    FSize := 0;
+end;
+
+destructor THashSet.Destroy;
+var
+    I: Integer;
+begin
+    for I := Low(FArray) to High(FArray) do
+        FArray[I].Free;
+    FArray := nil;
+    inherited Destroy;
+end;
+
+procedure THashSet.SetTableSize(Value: Integer);
+begin
+    if (FTableSize <> Value) and (Value >= 1) then
+    begin
+        FTableSize := Value;
+        Rehash;
+    end;
+end;
+
+procedure THashSet.SetMaxLoadFactor(Value: Double);
+begin
+    if (FMaxLoadFactor <> Value) and (Value >= MaxLoadFactorMin) then
+    begin
+        FMaxLoadFactor := Value;
+        CheckLoadFactor(false);
+    end;
+end;
+
+procedure THashSet.ChangeCapacity(Value: TListArray);
+var
+    Chain: TList;
+    I, Total, ChainCapacity: Integer;
+begin
+    if FCapacity mod FTableSize = 0 then
+        ChainCapacity := Trunc(FCapacity / FTableSize)
+    else
+        ChainCapacity := Trunc(FCapacity / FTableSize) + 1;
+    Total := 0;
+    for I := Low(Value) to High(Value) do
+    begin
+        Chain := Value[I];
+        Chain.Capacity := ChainCapacity;
+        Total := Total + Chain.Capacity;
+    end;
+    FCapacity := Total;
+end;
+
+procedure THashSet.CheckLoadFactor(AlwaysChangeCapacity: Boolean);
+var
+    LoadFactor: Double;
+begin
+    LoadFactor := Capacity / TableSize;
+    if LoadFactor > MaxLoadFactor then
+        TableSize := Trunc(Capacity / Max(MaxLoadFactor, MaxLoadFactorMin))
+    else if AlwaysChangeCapacity then
+        ChangeCapacity(FArray);
+end;
+
+function THashSet.GetHash(const Item: ICollectable): Integer;
+var
+    Hashable: IHashable;
+    HashCode: Cardinal;
+begin
+    Item.QueryInterface(IHashable, Hashable);
+    HashCode := Hashable.HashCode;
+    Result := Trunc(Frac(HashCode * HashFactor) * TableSize);
+end;
+
+function THashSet.GetPosition(const Item: ICollectable): TCollectionPosition;
+var
+    Chain: TList;
+    I: Integer;
+    Success: Boolean;
+begin
+    Chain := FArray[GetHash(Item)];
+    Success := false;
+    for I := 0 to Chain.Count - 1 do
+    begin
+        Success := Comparator.Equals(Item, ICollectable(Chain[I]));
+        if Success then
+            Break;
+    end;
+    Result := THashPosition.Create(Success, Chain, I);
+end;
+
+procedure THashSet.Rehash;
+var
+    NewArray: TListArray;
+    OldChain, NewChain: TList;
+    Item: ICollectable;
+    Total: Integer;
+    I, J: Integer;
+    Hash: Integer;
+begin
+    // Create new chains
+    SetLength(NewArray, TableSize);
+    for I := Low(NewArray) to High(NewArray) do
+    begin
+        NewChain := TList.Create;
+        NewArray[I] := NewChain;
+    end;
+    ChangeCapacity(NewArray);
+
+    // Transfer from old chains to new and drop old
+    for I := Low(FArray) to High(FArray) do
+    begin
+        OldChain := FArray[I];
+        for J := 0 to OldChain.Count - 1 do
+        begin
+            Item := ICollectable(OldChain[J]);
+            Hash := GetHash(Item);
+            NewArray[Hash].Add(Pointer(Item));
+        end;
+        OldChain.Free;
+    end;
+    FArray := NewArray;
+
+    // Find actual, new capacity
+    Total := 0;
+    for I := Low(FArray) to High(FArray) do
+    begin
+        NewChain := FArray[I];
+        Total := Total + NewChain.Capacity;
+    end;
+    FCapacity := Total;
+end;
+
+procedure THashSet.TrueAdd2(Position: TCollectionPosition; const Item: ICollectable);
+var
+    HashPosition: THashPosition;
+begin
+    HashPosition := THashPosition(Position);
+    HashPosition.Chain.Add(Pointer(Item));
+    Inc(FSize);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Item._AddRef;
+end;
+
+procedure THashSet.TrueClear;
+var
+    Item: ICollectable;
+    Chain: TList;
+    I, J: Integer;
+begin
+    for I := Low(FArray) to High(FArray) do
+    begin
+        Chain := FArray[I];
+        for J := 0 to Chain.Count - 1 do
+        begin
+            Item := ICollectable(Chain[J]);
+            Chain[J] := nil;
+            // Storing interface reference as a pointer does not update reference
+            // count automatically, so this must be done manually
+            Item._Release;
+        end;
+        Chain.Clear;
+    end;
+    FSize := 0;
+end;
+
+function THashSet.TrueGet(Position: TCollectionPosition): ICollectable;
+var
+    HashPosition: THashPosition;
+begin
+    HashPosition := THashPosition(Position);
+    Result := ICollectable(HashPosition.Chain.Items[HashPosition.Index]);
+end;
+
+procedure THashSet.TrueRemove2(Position: TCollectionPosition);
+var
+    Item: ICollectable;
+    HashPosition: THashPosition;
+begin
+    HashPosition := THashPosition(Position);
+    Item := TrueGet(Position);
+    HashPosition.Chain.Delete(HashPosition.Index);
+    Dec(FSize);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Item._Release;
+end;
+
+class function THashSet.GetAlwaysNaturalItems: Boolean;
+begin
+    Result := true;
+end;
+
+function THashSet.GetIterator: IIterator;
+begin
+    Result := THashIterator.Create(Self);
+end;
+
+function THashSet.GetNaturalItemIID: TGUID;
+begin
+    Result := HashableIID;
+end;
+
+function THashSet.GetCapacity;
+begin
+    Result := FCapacity;
+end;
+
+procedure THashSet.SetCapacity(Value: Integer);
+begin
+    FCapacity := Value;
+    CheckLoadFactor(true);
+end;
+
+function THashSet.GetSize: Integer;
+begin
+    Result := FSize;
+end;
+
+{ THashIntegerMap }
+constructor THashIntegerMap.Create;
+begin
+    Create(false, DefaultTableSize, DefaultMaxLoadFactor);
+end;
+
+constructor THashIntegerMap.Create(NaturalItemsOnly: Boolean);
+begin
+    Create(NaturalItemsOnly, DefaultTableSize, DefaultMaxLoadFactor);
+end;
+
+constructor THashIntegerMap.Create(NaturalItemsOnly: Boolean; TableSize: Integer; MaxLoadFactor: Double = DefaultMaxLoadFactor);
+var
+    I: Integer;
+begin
+    inherited Create(NaturalItemsOnly);
+    SetLength(FArray, TableSize);
+    for I := Low(FArray) to High(FArray) do
+        FArray[I] := TList.Create;
+    FTableSize := TableSize;
+    FMaxLoadFactor := MaxLoadFactor;
+    FSize := 0;
+end;
+
+destructor THashIntegerMap.Destroy;
+var
+    I: Integer;
+begin
+    for I := Low(FArray) to High(FArray) do
+        FArray[I].Free;
+    FArray := nil;
+    inherited Destroy;
+end;
+
+function THashIntegerMap.GetAssociationIterator: IIntegerMapIterator;
+begin
+    Result := THashIntegerIterator.Create(Self);
+end;
+
+procedure THashIntegerMap.SetTableSize(Value: Integer);
+begin
+    if (FTableSize <> Value) and (Value >= 1) then
+    begin
+        FTableSize := Value;
+        Rehash;
+    end;
+end;
+
+procedure THashIntegerMap.SetMaxLoadFactor(Value: Double);
+begin
+    if (FMaxLoadFactor <> Value) and (Value >= MaxLoadFactorMin) then
+    begin
+        FMaxLoadFactor := Value;
+        CheckLoadFactor(false);
+    end;
+end;
+
+procedure THashIntegerMap.ChangeCapacity;
+var
+    Chain: TList;
+    I, Total, ChainCapacity: Integer;
+begin
+    if FCapacity mod FTableSize = 0 then
+        ChainCapacity := Trunc(FCapacity / FTableSize)
+    else
+        ChainCapacity := Trunc(FCapacity / FTableSize) + 1;
+    Total := 0;
+    for I := Low(Value) to High(Value) do
+    begin
+        Chain := Value[I];
+        Chain.Capacity := ChainCapacity;
+        Total := Total + Chain.Capacity;
+    end;
+    FCapacity := Total;
+end;
+
+procedure THashIntegerMap.CheckLoadFactor(AlwaysChangeCapacity: Boolean);
+var
+    LoadFactor: Double;
+begin
+    LoadFactor := Capacity / TableSize;
+    if LoadFactor > MaxLoadFactor then
+        TableSize := Trunc(Capacity / Max(MaxLoadFactor, MaxLoadFactorMin))
+    else if AlwaysChangeCapacity then
+        ChangeCapacity(FArray);
+end;
+
+function THashIntegerMap.GetHash(const Key: Integer): Integer;
+begin
+    Result := Trunc(Frac(Cardinal(Key) * HashFactor) * TableSize);
+end;
+
+function THashIntegerMap.GetKeyPosition(const Key: Integer): TCollectionPosition;
+var
+    Chain: TList;
+    I: Integer;
+    Success: Boolean;
+begin
+    Chain := FArray[GetHash(Key)];
+    Success := false;
+    for I := 0 to Chain.Count - 1 do
+    begin
+        Success := (Key = IIntegerAssociation(Chain[I]).GetKey);
+        if Success then
+            Break;
+    end;
+    Result := THashPosition.Create(Success, Chain, I);
+end;
+
+procedure THashIntegerMap.Rehash;
+var
+    NewArray: TListArray;
+    OldChain, NewChain: TList;
+    Association: IIntegerAssociation;
+    Total: Integer;
+    I, J: Integer;
+    Hash: Integer;
+begin
+    // Create new chains
+    SetLength(NewArray, TableSize);
+    for I := Low(NewArray) to High(NewArray) do
+    begin
+        NewChain := TList.Create;
+        NewArray[I] := NewChain;
+    end;
+    ChangeCapacity(NewArray);
+
+    // Transfer from old chains to new and drop old
+    for I := Low(FArray) to High(FArray) do
+    begin
+        OldChain := FArray[I];
+        for J := 0 to OldChain.Count - 1 do
+        begin
+            Association := IIntegerAssociation(OldChain[J]);
+            Hash := GetHash(Association.GetKey);
+            NewArray[Hash].Add(Pointer(Association));
+        end;
+        OldChain.Free;
+    end;
+    FArray := NewArray;
+
+    // Find actual, new capacity
+    Total := 0;
+    for I := Low(FArray) to High(FArray) do
+    begin
+        NewChain := FArray[I];
+        Total := Total + NewChain.Capacity;
+    end;
+    FCapacity := Total;
+end;
+
+procedure THashIntegerMap.TrueClear;
+var
+    Association: IIntegerAssociation;
+    Chain: TList;
+    I, J: Integer;
+begin
+    for I := Low(FArray) to High(FArray) do
+    begin
+        Chain := FArray[I];
+        for J := 0 to Chain.Count - 1 do
+        begin
+            Association := IIntegerAssociation(Chain[J]);
+            Chain[J] := nil;
+            // Storing interface reference as a pointer does not update reference
+            // count automatically, so this must be done manually
+            Association._Release;
+        end;
+        Chain.Clear;
+    end;
+    FSize := 0;
+end;
+
+function THashIntegerMap.TrueGet(Position: TCollectionPosition): IIntegerAssociation;
+var
+    HashPosition: THashPosition;
+begin
+    HashPosition := THashPosition(Position);
+    Result := IIntegerAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+end;
+
+function THashIntegerMap.TruePut(Position: TCollectionPosition; const Association: IIntegerAssociation): IIntegerAssociation;
+var
+    HashPosition: THashPosition;
+    OldAssociation: IIntegerAssociation;
+begin
+    HashPosition := THashPosition(Position);
+    if HashPosition.Found then
+    begin
+        OldAssociation := IIntegerAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+        HashPosition.Chain.Items[HashPosition.Index] := Pointer(Association);
+        Result := OldAssociation;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        Association._AddRef;
+        OldAssociation._Release;
+    end
+    else
+    begin
+        HashPosition.Chain.Add(Pointer(Association));
+        Inc(FSize);
+        Result := nil;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        Association._AddRef;
+    end;
+end;
+
+function THashIntegerMap.TrueRemove2(Position: TCollectionPosition): IIntegerAssociation;
+var
+    Association: IIntegerAssociation;
+    HashPosition: THashPosition;
+begin
+    HashPosition := THashPosition(Position);
+    Association := IIntegerAssociation(TrueGet(Position));
+    HashPosition.Chain.Delete(HashPosition.Index);
+    Dec(FSize);
+    Result := Association;
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Association._Release;
+end;
+
+function THashIntegerMap.GetCapacity;
+begin
+    Result := FCapacity;
+end;
+
+procedure THashIntegerMap.SetCapacity(Value: Integer);
+begin
+    FCapacity := Value;
+    CheckLoadFactor(true);
+end;
+
+function THashIntegerMap.GetSize: Integer;
+begin
+    Result := FSize;
+end;
+
+{ THashStringMap }
+constructor THashStringMap.Create;
+begin
+    Create(false, DefaultTableSize, DefaultMaxLoadFactor);
+end;
+
+constructor THashStringMap.Create(NaturalItemsOnly: Boolean);
+begin
+    Create(NaturalItemsOnly, DefaultTableSize, DefaultMaxLoadFactor);
+end;
+
+constructor THashStringMap.Create(NaturalItemsOnly: Boolean; TableSize: Integer; MaxLoadFactor: Double = DefaultMaxLoadFactor);
+var
+    I: Integer;
+begin
+    inherited Create(NaturalItemsOnly);
+    SetLength(FArray, TableSize);
+    for I := Low(FArray) to High(FArray) do
+        FArray[I] := TList.Create;
+    FTableSize := TableSize;
+    FMaxLoadFactor := MaxLoadFactor;
+    FSize := 0;
+end;
+
+destructor THashStringMap.Destroy;
+var
+    I: Integer;
+begin
+    for I := Low(FArray) to High(FArray) do
+        FArray[I].Free;
+    FArray := nil;
+    inherited Destroy;
+end;
+
+function THashStringMap.GetAssociationIterator: IStringMapIterator;
+begin
+    Result := THashStringIterator.Create(Self);
+end;
+
+procedure THashStringMap.SetTableSize(Value: Integer);
+begin
+    if (FTableSize <> Value) and (Value >= 1) then
+    begin
+        FTableSize := Value;
+        Rehash;
+    end;
+end;
+
+procedure THashStringMap.SetMaxLoadFactor(Value: Double);
+begin
+    if (FMaxLoadFactor <> Value) and (Value >= MaxLoadFactorMin) then
+    begin
+        FMaxLoadFactor := Value;
+        CheckLoadFactor(false);
+    end;
+end;
+
+procedure THashStringMap.ChangeCapacity;
+var
+    Chain: TList;
+    I, Total, ChainCapacity: Integer;
+begin
+    if FCapacity mod FTableSize = 0 then
+        ChainCapacity := Trunc(FCapacity / FTableSize)
+    else
+        ChainCapacity := Trunc(FCapacity / FTableSize) + 1;
+    Total := 0;
+    for I := Low(Value) to High(Value) do
+    begin
+        Chain := Value[I];
+        Chain.Capacity := ChainCapacity;
+        Total := Total + Chain.Capacity;
+    end;
+    FCapacity := Total;
+end;
+
+procedure THashStringMap.CheckLoadFactor(AlwaysChangeCapacity: Boolean);
+var
+    LoadFactor: Double;
+begin
+    LoadFactor := Capacity / TableSize;
+    if LoadFactor > MaxLoadFactor then
+        TableSize := Trunc(Capacity / Max(MaxLoadFactor, MaxLoadFactorMin))
+    else if AlwaysChangeCapacity then
+        ChangeCapacity(FArray);
+end;
+
+function THashStringMap.GetHash(const Key: String): Integer;
+var
+    HashCode: Cardinal;
+    I: Integer;
+begin
+    HashCode := 0;
+    for I := 1 to Length(Key) do
+        HashCode := (HashCode shl 1) xor Ord(Key[I]);
+    Result := Trunc(Frac(HashCode * HashFactor) * TableSize);
+end;
+
+function THashStringMap.GetKeyPosition(const Key: String): TCollectionPosition;
+var
+    Chain: TList;
+    I: Integer;
+    Success: Boolean;
+begin
+    Chain := FArray[GetHash(Key)];
+    Success := false;
+    for I := 0 to Chain.Count - 1 do
+    begin
+        Success := (Key = IStringAssociation(Chain[I]).GetKey);
+        if Success then
+            Break;
+    end;
+    Result := THashPosition.Create(Success, Chain, I);
+end;
+
+procedure THashStringMap.Rehash;
+var
+    NewArray: TListArray;
+    OldChain, NewChain: TList;
+    Association: IStringAssociation;
+    Total: Integer;
+    I, J: Integer;
+    Hash: Integer;
+begin
+    // Create new chains
+    SetLength(NewArray, TableSize);
+    for I := Low(NewArray) to High(NewArray) do
+    begin
+        NewChain := TList.Create;
+        NewArray[I] := NewChain;
+    end;
+    ChangeCapacity(NewArray);
+
+    // Transfer from old chains to new and drop old
+    for I := Low(FArray) to High(FArray) do
+    begin
+        OldChain := FArray[I];
+        for J := 0 to OldChain.Count - 1 do
+        begin
+            Association := IStringAssociation(OldChain[J]);
+            Hash := GetHash(Association.GetKey);
+            NewArray[Hash].Add(Pointer(Association));
+        end;
+        OldChain.Free;
+    end;
+    FArray := NewArray;
+
+    // Find actual, new capacity
+    Total := 0;
+    for I := Low(FArray) to High(FArray) do
+    begin
+        NewChain := FArray[I];
+        Total := Total + NewChain.Capacity;
+    end;
+    FCapacity := Total;
+end;
+
+procedure THashStringMap.TrueClear;
+var
+    Association: IStringAssociation;
+    Chain: TList;
+    I, J: Integer;
+begin
+    for I := Low(FArray) to High(FArray) do
+    begin
+        Chain := FArray[I];
+        for J := 0 to Chain.Count - 1 do
+        begin
+            Association := IStringAssociation(Chain[J]);
+            Chain[J] := nil;
+            // Storing interface reference as a pointer does not update reference
+            // count automatically, so this must be done manually
+            Association._Release;
+        end;
+        Chain.Clear;
+    end;
+    FSize := 0;
+end;
+
+function THashStringMap.TrueGet(Position: TCollectionPosition): IStringAssociation;
+var
+    HashPosition: THashPosition;
+begin
+    HashPosition := THashPosition(Position);
+    Result := IStringAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+end;
+
+function THashStringMap.TruePut(Position: TCollectionPosition; const Association: IStringAssociation): IStringAssociation;
+var
+    HashPosition: THashPosition;
+    OldAssociation: IStringAssociation;
+begin
+    HashPosition := THashPosition(Position);
+    if HashPosition.Found then
+    begin
+        OldAssociation := IStringAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+        HashPosition.Chain.Items[HashPosition.Index] := Pointer(Association);
+        Result := OldAssociation;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        Association._AddRef;
+        OldAssociation._Release;
+    end
+    else
+    begin
+        HashPosition.Chain.Add(Pointer(Association));
+        Inc(FSize);
+        Result := nil;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        Association._AddRef;
+    end;
+end;
+
+function THashStringMap.TrueRemove2(Position: TCollectionPosition): IStringAssociation;
+var
+    Association: IStringAssociation;
+    HashPosition: THashPosition;
+begin
+    HashPosition := THashPosition(Position);
+    Association := IStringAssociation(TrueGet(Position));
+    HashPosition.Chain.Delete(HashPosition.Index);
+    Dec(FSize);
+    Result := Association;
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Association._Release;
+end;
+
+function THashStringMap.GetCapacity;
+begin
+    Result := FCapacity;
+end;
+
+procedure THashStringMap.SetCapacity(Value: Integer);
+begin
+    FCapacity := Value;
+    CheckLoadFactor(true);
+end;
+
+function THashStringMap.GetSize: Integer;
+begin
+    Result := FSize;
+end;
+
+{ THashPosition }
+constructor THashPosition.Create(Found: Boolean; Chain: TList; Index: Integer);
+begin
+    inherited Create(Found);
+    FChain := Chain;
+    FIndex := Index;
+end;
+
+{ THashIterator }
+constructor THashIterator.Create(HashSet: THashSet);
+begin
+    inherited Create(true);
+    FHashSet := HashSet;
+    First;
+end;
+
+function THashIterator.TrueFirst: ICollectable;
+var
+    Chain: TList;
+    Success: Boolean;
+begin
+    FHash := 0;
+    FChainIndex := 0;
+    Success := false;
+    while FHash < FHashSet.TableSize do
+    begin
+        Chain := FHashSet.FArray[FHash];
+        Success := Chain.Count > 0;
+        if Success then
+            Break;
+        Inc(FHash);
+    end;
+    if Success then
+        Result := ICollectable(FHashSet.FArray[FHash].Items[FChainIndex])
+    else
+        Result := nil;
+end;
+
+function THashIterator.TrueNext: ICollectable;
+var
+    Chain: TList;
+    Success: Boolean;
+begin
+    Success := false;
+    Chain := FHashSet.FArray[FHash];
+    repeat
+        Inc(FChainIndex);
+        if FChainIndex >= Chain.Count then
+        begin
+            Inc(FHash);
+            FChainIndex := -1;
+            if FHash < FHashSet.TableSize then
+                Chain := FHashSet.FArray[FHash];
+        end
+        else
+            Success := true;
+    until Success or (FHash >= FHashSet.TableSize);
+    if Success then
+        Result := ICollectable(FHashSet.FArray[FHash].Items[FChainIndex])
+    else
+        Result := nil;
+end;
+
+procedure THashIterator.TrueRemove;
+var
+    Item: ICollectable;
+begin
+    Item := ICollectable(FHashSet.FArray[FHash].Items[FChainIndex]);
+    FHashSet.FArray[FHash].Delete(FChainIndex);
+    Dec(FChainIndex);
+    Dec(FHashSet.FSize);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Item._Release;
+end;
+
+
+{ THashAssociationIterator }
+constructor THashAssociationIterator.Create(HashMap: THashMap);
+begin
+    inherited Create(true);
+    FHashMap := HashMap;
+    First;
+end;
+
+function THashAssociationIterator.TrueFirst: IAssociation;
+var
+    Chain: TList;
+    Success: Boolean;
+begin
+    FHash := 0;
+    FChainIndex := 0;
+    Success := false;
+    while FHash < FHashMap.TableSize do
+    begin
+        Chain := FHashMap.FArray[FHash];
+        Success := Chain.Count > 0;
+        if Success then
+            Break;
+        Inc(FHash);
+    end;
+    if Success then
+        Result := IAssociation(FHashMap.FArray[FHash].Items[FChainIndex])
+    else
+        Result := nil;
+end;
+
+function THashAssociationIterator.TrueNext: IAssociation;
+var
+    Chain: TList;
+    Success: Boolean;
+begin
+    Success := false;
+    Chain := FHashMap.FArray[FHash];
+    repeat
+        Inc(FChainIndex);
+        if FChainIndex >= Chain.Count then
+        begin
+            Inc(FHash);
+            FChainIndex := -1;
+            if FHash < FHashMap.TableSize then
+                Chain := FHashMap.FArray[FHash];
+        end
+        else
+            Success := true;
+    until Success or (FHash >= FHashMap.TableSize);
+    if Success then
+        Result := IAssociation(FHashMap.FArray[FHash].Items[FChainIndex])
+    else
+        Result := nil;
+end;
+
+procedure THashAssociationIterator.TrueRemove;
+var
+    Association: IAssociation;
+begin
+    Association := IAssociation(FHashMap.FArray[FHash].Items[FChainIndex]);
+    FHashMap.FArray[FHash].Delete(FChainIndex);
+    Dec(FChainIndex);
+    Dec(FHashMap.FSize);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Association._Release;
+end;
+
+
+{ THashIntegerIterator }
+constructor THashIntegerIterator.Create(HashIntegerMap: THashIntegerMap);
+begin
+    inherited Create(true);
+    FHashIntegerMap := HashIntegerMap;
+    First;
+end;
+
+function THashIntegerIterator.TrueFirst: IIntegerAssociation;
+var
+    Chain: TList;
+    Success: Boolean;
+begin
+    FHash := 0;
+    FChainIndex := 0;
+    Success := false;
+    while FHash < FHashIntegerMap.TableSize do
+    begin
+        Chain := FHashIntegerMap.FArray[FHash];
+        Success := Chain.Count > 0;
+        if Success then
+            Break;
+        Inc(FHash);
+    end;
+    if Success then
+        Result := IIntegerAssociation(FHashIntegerMap.FArray[FHash].Items[FChainIndex])
+    else
+        Result := nil;
+end;
+
+function THashIntegerIterator.TrueNext: IIntegerAssociation;
+var
+    Chain: TList;
+    Success: Boolean;
+begin
+    Success := false;
+    Chain := FHashIntegerMap.FArray[FHash];
+    repeat
+        Inc(FChainIndex);
+        if FChainIndex >= Chain.Count then
+        begin
+            Inc(FHash);
+            FChainIndex := -1;
+            if FHash < FHashIntegerMap.TableSize then
+                Chain := FHashIntegerMap.FArray[FHash];
+        end
+        else
+            Success := true;
+    until Success or (FHash >= FHashIntegerMap.TableSize);
+    if Success then
+        Result := IIntegerAssociation(FHashIntegerMap.FArray[FHash].Items[FChainIndex])
+    else
+        Result := nil;
+end;
+
+procedure THashIntegerIterator.TrueRemove;
+var
+    Association: IIntegerAssociation;
+begin
+    Association := IIntegerAssociation(FHashIntegerMap.FArray[FHash].Items[FChainIndex]);
+    FHashIntegerMap.FArray[FHash].Delete(FChainIndex);
+    Dec(FChainIndex);
+    Dec(FHashIntegerMap.FSize);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Association._Release;
+end;
+
+{ THashStringIterator }
+constructor THashStringIterator.Create(HashStringMap: THashStringMap);
+begin
+    inherited Create(true);
+    FHashStringMap := HashStringMap;
+    First;
+end;
+
+function THashStringIterator.TrueFirst: IStringAssociation;
+var
+    Chain: TList;
+    Success: Boolean;
+begin
+    FHash := 0;
+    FChainIndex := 0;
+    Success := false;
+    while FHash < FHashStringMap.TableSize do
+    begin
+        Chain := FHashStringMap.FArray[FHash];
+        Success := Chain.Count > 0;
+        if Success then
+            Break;
+        Inc(FHash);
+    end;
+    if Success then
+        Result := IStringAssociation(FHashStringMap.FArray[FHash].Items[FChainIndex])
+    else
+        Result := nil;
+end;
+
+function THashStringIterator.TrueNext: IStringAssociation;
+var
+    Chain: TList;
+    Success: Boolean;
+begin
+    Success := false;
+    Chain := FHashStringMap.FArray[FHash];
+    repeat
+        Inc(FChainIndex);
+        if FChainIndex >= Chain.Count then
+        begin
+            Inc(FHash);
+            FChainIndex := -1;
+            if FHash < FHashStringMap.TableSize then
+                Chain := FHashStringMap.FArray[FHash];
+        end
+        else
+            Success := true;
+    until Success or (FHash >= FHashStringMap.TableSize);
+    if Success then
+        Result := IStringAssociation(FHashStringMap.FArray[FHash].Items[FChainIndex])
+    else
+        Result := nil;
+end;
+
+procedure THashStringIterator.TrueRemove;
+var
+    Association: IStringAssociation;
+begin
+    Association := IStringAssociation(FHashStringMap.FArray[FHash].Items[FChainIndex]);
+    FHashStringMap.FArray[FHash].Delete(FChainIndex);
+    Dec(FChainIndex);
+    Dec(FHashStringMap.FSize);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Association._Release;
+end;
+
+
+end.
diff --git a/songmanagement/src/lib/collections/CollLibrary.pas b/songmanagement/src/lib/collections/CollLibrary.pas
new file mode 100644
index 00000000..b7e3d268
--- /dev/null
+++ b/songmanagement/src/lib/collections/CollLibrary.pas
@@ -0,0 +1,131 @@
+unit CollLibrary;
+
+(*****************************************************************************
+ * Copyright 2003 by Matthew Greet
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details. (http://opensource.org/licenses/lgpl-license.php)
+ * 
+ * See http://www.warmachine.u-net.com/delphi_collections for updates and downloads.
+ *
+ * $Version: v1.0.3 $
+ * $Revision: 1.0.1.1 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollLibrary.qbt $
+ * 
+ *   Initial version.
+ * 
+ * Revision 1.0.1.1  by: Matthew Greet  Rev date: 24/10/03 16:48:16
+ *   v1.0 branch.
+ * 
+ * Revision 1.0  by: Matthew Greet  Rev date: 06/04/03 10:40:32
+ *   Initial revision.
+ * 
+ * FPC compatibility fixes by: UltraStar Deluxe Team
+ *
+ * $Endlog$
+ *****************************************************************************)
+
+{$IFDEF FPC}
+  {$MODE Delphi}{$H+}
+{$ENDIF}
+ 
+interface
+
+uses
+    Collections, CollArray, CollHash, CollList, CollPArray, CollWrappers;
+
+type
+    TMiscCollectionLibrary = class
+    public
+        class function ClassNameToClassType(ClassName: String): TAbstractCollectionClass;
+        class function EqualIID(const IID1, IID2: TGUID): Boolean;
+        class function HashCode(Value: String): Integer;
+        class procedure ShuffleArray(var ItemArray: array of ICollectable);
+        class procedure ShuffleList(const List: IList);
+    end;
+
+implementation
+
+{ TMiscCollectionLibrary }
+class function TMiscCollectionLibrary.ClassNameToClassType(ClassName: String): TAbstractCollectionClass;
+begin
+    if ClassName = 'TArray' then
+        Result := TArray
+    else if ClassName = 'THashSet' then
+        Result := THashSet
+    else if ClassName = 'THashMap' then
+        Result := THashMap
+    else if ClassName = 'THashIntegerMap' then
+        Result := THashIntegerMap
+    else if ClassName = 'THashStringMap' then
+        Result := THashStringMap
+    else if ClassName = 'TListSet' then
+        Result := TListSet
+    else if ClassName = 'TListMap' then
+        Result := TListMap
+    else if ClassName = 'TPArrayBag' then
+        Result := TPArrayBag
+    else if ClassName = 'TPArraySet' then
+        Result := TPArraySet
+    else if ClassName = 'TPArrayList' then
+        Result := TPArrayList
+    else if ClassName = 'TPArrayMap' then
+        Result := TPArrayMap
+    else
+        Result := nil;
+end;
+
+class function TMiscCollectionLibrary.EqualIID(const IID1, IID2: TGUID): Boolean;
+begin
+    Result := (IID1.D1 = IID2.D1) and (IID1.D2 = IID2.D2) and (IID1.D3 = IID2.D3) and
+        (IID1.D4[0] = IID2.D4[0]) and (IID1.D4[1] = IID2.D4[1]) and
+        (IID1.D4[2] = IID2.D4[2]) and (IID1.D4[3] = IID2.D4[3]) and
+        (IID1.D4[4] = IID2.D4[4]) and (IID1.D4[5] = IID2.D4[5]) and
+        (IID1.D4[6] = IID2.D4[6]) and (IID1.D4[7] = IID2.D4[7]);
+end;
+
+class function TMiscCollectionLibrary.HashCode(Value: String): Integer;
+var
+    I: Integer;
+begin
+    Result := 0;
+    for I := 1 to Length(Value) do
+        Result := (Result shl 1) xor Ord(Value[I]);
+end;
+
+class procedure TMiscCollectionLibrary.ShuffleArray(var ItemArray: array of ICollectable);
+var
+    Item: ICollectable;
+    ArraySize, I, Index: Integer;
+begin
+    Randomize;
+    ArraySize := Length(ItemArray);
+    for I := 0 to ArraySize - 1 do
+    begin
+        Index := (I + Random(ArraySize - 1) + 1) mod ArraySize;
+        Item := ItemArray[I];
+        ItemArray[I] := ItemArray[Index];
+        ItemArray[Index] := Item;
+    end;
+end;
+
+class procedure TMiscCollectionLibrary.ShuffleList(const List: IList);
+var
+    ListSize, I: Integer;
+begin
+    Randomize;
+    ListSize := List.GetSize;
+    for I := 0 to ListSize - 1 do
+    begin
+        List.Exchange(I, (I + Random(ListSize - 1) + 1) mod ListSize);
+    end;
+end;
+
+
+end.
diff --git a/songmanagement/src/lib/collections/CollList.pas b/songmanagement/src/lib/collections/CollList.pas
new file mode 100644
index 00000000..68aa0d66
--- /dev/null
+++ b/songmanagement/src/lib/collections/CollList.pas
@@ -0,0 +1,270 @@
+unit CollList;
+
+(*****************************************************************************
+ * Copyright 2003 by Matthew Greet
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details. (http://opensource.org/licenses/lgpl-license.php)
+ * 
+ * See http://www.warmachine.u-net.com/delphi_collections for updates and downloads.
+ *
+ * $Version: v1.0.3 $
+ * $Revision: 1.1.1.2 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollList.qbt $
+ * 
+ *   Collection implementations based on sorted TPArrayList instances.
+ * 
+ * Revision 1.1.1.2  by: Matthew Greet  Rev date: 12/06/04 20:05:54
+ *   Capacity property.
+ * 
+ * Revision 1.1.1.1  by: Matthew Greet  Rev date: 14/02/04 17:45:38
+ *   v1.0 branch.
+ * 
+ * Revision 1.1  by: Matthew Greet  Rev date: 06/04/03 10:41:52
+ *   Uses TExposedPArrayList to improve performance.
+ * 
+ * Revision 1.0  by: Matthew Greet  Rev date: 01/03/03 10:50:02
+ *   Initial revision.
+ * 
+ * FPC compatibility fixes by: UltraStar Deluxe Team
+ *
+ * $Endlog$
+ *****************************************************************************)
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}{$H+}
+{$ENDIF}
+
+uses
+    Collections, CollPArray;
+
+type
+    TListSet = class(TAbstractSet)
+    private
+        FList: TExposedPArrayList;
+    protected
+        function GetPosition(const Item: ICollectable): TCollectionPosition; override;
+        procedure TrueAdd2(Position: TCollectionPosition; const Item: ICollectable); override;
+        procedure TrueClear; override;
+        function TrueGet(Position: TCollectionPosition): ICollectable; override;
+        procedure TrueRemove2(Position: TCollectionPosition); override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        destructor Destroy; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetIterator: IIterator; override;
+        function GetNaturalItemIID: TGUID; override;
+        function GetSize: Integer; override;
+    end;
+
+    TListMap = class(TAbstractMap)
+    private
+        FList: TExposedPArrayList;
+    protected
+        function GetAssociationIterator: IMapIterator; override;
+        function GetKeyPosition(const Key: ICollectable): TCollectionPosition; override;
+        procedure TrueClear; override;
+        function TrueGet(Position: TCollectionPosition): IAssociation; override;
+        function TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation; override;
+        function TrueRemove2(Position: TCollectionPosition): IAssociation; override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); override;
+        destructor Destroy; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        procedure SetKeyComparator(const Value: IComparator); override;
+        function GetNaturalKeyIID: TGUID; override;
+        function GetSize: Integer; override;
+    end;
+
+implementation
+
+type
+    TListPosition = class(TCollectionPosition)
+    private
+        FSearchResult: TSearchResult;
+    public
+        constructor Create(Found: Boolean; SearchResult: TSearchResult);
+        property SearchResult: TSearchResult read FSearchResult;
+    end;
+
+constructor TListSet.Create(NaturalItemsOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly);
+    FList := TExposedPArrayList.Create(NaturalItemsOnly);
+    FList.Comparator := Comparator;
+    FList.Sort;
+end;
+
+destructor TListSet.Destroy;
+begin
+    FList.Free;
+    inherited Destroy;
+end;
+
+function TListSet.GetPosition(const Item: ICollectable): TCollectionPosition;
+var
+    SearchResult: TSearchResult;
+begin
+    SearchResult := FList.Search(Item);
+    Result := TListPosition.Create((SearchResult.ResultType = srFoundAtIndex), SearchResult);
+end;
+
+procedure TListSet.TrueAdd2(Position: TCollectionPosition; const Item: ICollectable);
+var
+    SearchResult: TSearchResult;
+    Index: Integer;
+begin
+    SearchResult := TListPosition(Position).SearchResult;
+    Index := SearchResult.Index;
+    if SearchResult.ResultType = srBeforeIndex then
+        FList.TrueInsert(Index, Item)
+    else
+        FList.TrueAppend(Item);
+end;
+
+procedure TListSet.TrueClear;
+begin
+    FList.Clear;
+end;
+
+function TListSet.TrueGet(Position: TCollectionPosition): ICollectable;
+begin
+    Result := FList.Items[TListPosition(Position).SearchResult.Index];
+end;
+
+procedure TListSet.TrueRemove2(Position: TCollectionPosition);
+begin
+    FList.Delete(TListPosition(Position).SearchResult.Index);
+end;
+
+function TListSet.GetCapacity: Integer;
+begin
+    Result := FList.Capacity;
+end;
+
+procedure TListSet.SetCapacity(Value: Integer);
+begin
+    FList.Capacity := Value;
+end;
+
+function TListSet.GetIterator: IIterator;
+begin
+    Result := FList.GetIterator;
+end;
+
+function TListSet.GetNaturalItemIID: TGUID;
+begin
+    Result := ComparableIID;
+end;
+
+function TListSet.GetSize: Integer;
+begin
+    Result := FList.Size;
+end;
+
+constructor TListMap.Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly, NaturalKeysOnly);
+    FList := TExposedPArrayList.Create(false);
+    FList.Comparator := AssociationComparator;
+    FList.Sort;
+end;
+
+destructor TListMap.Destroy;
+begin
+    FList.Free;
+    inherited Destroy;
+end;
+
+function TListMap.GetAssociationIterator: IMapIterator;
+begin
+    Result := TAssociationIterator.Create(FList.GetIterator);
+end;
+
+function TListMap.GetKeyPosition(const Key: ICollectable): TCollectionPosition;
+var
+    Association: IAssociation;
+    SearchResult: TSearchResult;
+begin
+    Association := TAssociation.Create(Key, nil);
+    SearchResult := FList.Search(Association);
+    Result := TListPosition.Create((SearchResult.ResultType = srFoundAtIndex), SearchResult);
+end;
+
+procedure TListMap.TrueClear;
+begin
+    FList.Clear;
+end;
+
+function TListMap.TrueGet(Position: TCollectionPosition): IAssociation;
+begin
+    Result := (FList.Items[TListPosition(Position).SearchResult.Index]) as IAssociation;
+end;
+
+function TListMap.TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation;
+var
+    SearchResult: TSearchResult;
+    Index: Integer;
+begin
+    SearchResult := TListPosition(Position).SearchResult;
+    Index := SearchResult.Index;
+    if SearchResult.ResultType = srFoundAtIndex then
+    begin
+        Result := (FList.Items[Index]) as IAssociation;
+        FList.Items[Index] := Association;
+    end
+    else if SearchResult.ResultType = srBeforeIndex then
+        FList.TrueInsert(Index, Association)
+    else
+        FList.TrueAppend(Association);
+end;
+
+function TListMap.TrueRemove2(Position: TCollectionPosition): IAssociation;
+begin
+    Result := (FList.Items[TListPosition(Position).SearchResult.Index]) as IAssociation;
+    FList.Delete(TListPosition(Position).SearchResult.Index);
+end;
+
+procedure TListMap.SetKeyComparator(const Value: IComparator);
+begin
+    inherited SetKeyComparator(Value);
+    FList.Sort;
+end;
+
+function TListMap.GetCapacity: Integer;
+begin
+    Result := FList.Capacity;
+end;
+
+procedure TListMap.SetCapacity(Value: Integer);
+begin
+    FList.Capacity := Value;
+end;
+
+function TListMap.GetNaturalKeyIID: TGUID;
+begin
+    Result := ComparableIID;
+end;
+
+function TListMap.GetSize: Integer;
+begin
+    Result := FList.Size;
+end;
+
+constructor TListPosition.Create(Found: Boolean; SearchResult: TSearchResult);
+begin
+    inherited Create(Found);
+    FSearchResult := SearchResult;
+end;
+
+end.
diff --git a/songmanagement/src/lib/collections/CollPArray.pas b/songmanagement/src/lib/collections/CollPArray.pas
new file mode 100644
index 00000000..5ebd534b
--- /dev/null
+++ b/songmanagement/src/lib/collections/CollPArray.pas
@@ -0,0 +1,689 @@
+unit CollPArray;
+
+(*****************************************************************************
+ * Copyright 2003 by Matthew Greet
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details. (http://opensource.org/licenses/lgpl-license.php)
+ * 
+ * See http://www.warmachine.u-net.com/delphi_collections for updates and downloads.
+ *
+ * $Version: v1.0.3 $
+ * $Revision: 1.2.1.2 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollPArray.qbt $
+ * 
+ *   Collection implementations based on TList.
+ * 
+ * Revision 1.2.1.2  by: Matthew Greet  Rev date: 12/06/04 20:08:30
+ *   Capacity property.
+ * 
+ * Revision 1.2.1.1  by: Matthew Greet  Rev date: 14/02/04 17:46:10
+ *   v1.0 branch.
+ * 
+ * Revision 1.2  by: Matthew Greet  Rev date: 28/04/03 15:07:14
+ *   Correctly handles nil items.
+ * 
+ * Revision 1.1  by: Matthew Greet  Rev date: 06/04/03 10:43:16
+ *   Added TPArrayMap and TExposedPArrayList.
+ * 
+ * Revision 1.0  by: Matthew Greet  Rev date: 01/03/03 10:50:02
+ *   Initial revision.
+ * 
+ * FPC compatibility fixes by: UltraStar Deluxe Team
+ *
+ * $Endlog$
+ *****************************************************************************)
+
+{$IFDEF FPC}
+  {$MODE Delphi}{$H+}
+{$ENDIF}
+ 
+interface
+
+uses
+    Classes,
+    Collections;
+
+type
+    TPArrayBag = class(TAbstractBag)
+    private
+        FList: TList;
+    protected
+        function TrueAdd(const Item: ICollectable): Boolean; override;
+        procedure TrueClear; override;
+        function TrueRemove(const Item: ICollectable): ICollectable; override;
+        function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        destructor Destroy; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetIterator: IIterator; override;
+        function GetSize: Integer; override;
+        function TrueContains(const Item: ICollectable): Boolean; override;
+    end;
+
+    TPArraySet = class(TAbstractSet)
+    private
+        FList: TList;
+    protected
+        function GetPosition(const Item: ICollectable): TCollectionPosition; override;
+        procedure TrueAdd2(Position: TCollectionPosition; const Item: ICollectable); override;
+        procedure TrueClear; override;
+        function TrueGet(Position: TCollectionPosition): ICollectable; override;
+        procedure TrueRemove2(Position: TCollectionPosition); override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        destructor Destroy; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetIterator: IIterator; override;
+        function GetSize: Integer; override;
+    end;
+
+    TPArrayList = class(TAbstractList)
+    private
+        FList: TList;
+    protected
+        function TrueGetItem(Index: Integer): ICollectable; override;
+        procedure TrueSetItem(Index: Integer; const Item: ICollectable); override;
+        procedure TrueAppend(const Item: ICollectable); override;
+        procedure TrueClear; override;
+        function TrueDelete(Index: Integer): ICollectable; override;
+        procedure TrueInsert(Index: Integer; const Item: ICollectable); override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        destructor Destroy; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetIterator: IIterator; override;
+        function GetSize: Integer; override;
+    end;
+
+    TPArrayMap = class(TAbstractMap)
+    private
+        FList: TList;
+    protected
+        function GetAssociationIterator: IMapIterator; override;
+        function GetKeyPosition(const Key: ICollectable): TCollectionPosition; override;
+        procedure TrueClear; override;
+        function TrueGet(Position: TCollectionPosition): IAssociation; override;
+        function TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation; override;
+        function TrueRemove2(Position: TCollectionPosition): IAssociation; override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); override;
+        destructor Destroy; override;
+        function GetCapacity: Integer; override;
+        procedure SetCapacity(Value: Integer); override;
+        function GetSize: Integer; override;
+    end;
+
+    // Same as TPArrayList but raises method visibilities so items can be manually
+    // appended or inserted without resetting sort flag.
+    TExposedPArrayList = class(TPArrayList)
+    public
+        procedure TrueAppend(const Item: ICollectable); override;
+        procedure TrueInsert(Index: Integer; const Item: ICollectable); override;
+    end;
+
+
+implementation
+
+type
+    TPArrayIterator = class(TAbstractIterator)
+    private
+        FList: TList;
+        FIndex: Integer;
+    protected
+        constructor Create(List: TList; AllowRemove: Boolean);
+        function TrueFirst: ICollectable; override;
+        function TrueNext: ICollectable; override;
+        procedure TrueRemove; override;
+    end;
+
+    TPArrayAssociationIterator = class(TAbstractAssociationIterator)
+    private
+        FList: TList;
+        FIndex: Integer;
+    protected
+        constructor Create(List: TList; AllowRemove: Boolean);
+        function TrueFirst: IAssociation; override;
+        function TrueNext: IAssociation; override;
+        procedure TrueRemove; override;
+    end;
+
+    TPArrayPosition = class(TCollectionPosition)
+    private
+        FIndex: Integer;
+    public
+        constructor Create(Found: Boolean; Index: Integer);
+        property Index: Integer read FIndex;
+    end;
+
+constructor TPArrayBag.Create(NaturalItemsOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly);
+    FList := TList.Create;
+end;
+
+destructor TPArrayBag.Destroy;
+begin
+    FList.Free;
+    inherited Destroy;
+end;
+
+function TPArrayBag.TrueAdd(const Item: ICollectable): Boolean;
+begin
+    FList.Add(Pointer(Item));
+    Result := true;
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    if Item <> nil then
+        Item._AddRef;
+end;
+
+procedure TPArrayBag.TrueClear;
+var
+    Item: ICollectable;
+    I: Integer;
+begin
+    // Delete all interface references
+    for I := 0 to FList.Count - 1 do
+    begin
+        Item := ICollectable(FList[I]);
+        FList[I] := nil;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        if Item <> nil then
+            Item._Release;
+    end;
+    FList.Clear;
+end;
+
+function TPArrayBag.TrueContains(const Item: ICollectable): Boolean;
+var
+    I: Integer;
+    Success: Boolean;
+begin
+    // Sequential search
+    I := 0;
+    Success := false;
+    while (I < FList.Count) and not Success do
+    begin
+        Success := Comparator.Equals(Item, ICollectable(FList[I]));
+        Inc(I);
+    end;
+    Result := Success;
+end;
+
+function TPArrayBag.TrueRemove(const Item: ICollectable): ICollectable;
+var
+    Item2: ICollectable;
+    I: Integer;
+    Found: Boolean;
+begin
+    // Sequential search
+    I := 0;
+    Found := false;
+    Result := nil;
+    while (I < FList.Count) and not Found do
+    begin
+        Item2 := ICollectable(FList[I]);
+        if Comparator.Equals(Item, Item2) then
+        begin
+            Found := true;
+            Result := Item2;
+            FList.Delete(I);
+            // Storing interface reference as a pointer does not update reference
+            // count automatically, so this must be done manually
+            if Item2 <> nil then
+                Item2._Release;
+        end
+        else
+            Inc(I);
+    end;
+end;
+
+function TPArrayBag.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+    ResultCollection: TPArrayBag;
+    Item2: ICollectable;
+    I: Integer;
+begin
+    // Sequential search
+    I := 0;
+    ResultCollection := TPArrayBag.Create;
+    while I < FList.Count do
+    begin
+        Item2 := ICollectable(FList[I]);
+        if Comparator.Equals(Item, Item2) then
+        begin
+            ResultCollection.Add(Item2);
+            FList.Delete(I);
+            // Storing interface reference as a pointer does not update reference
+            // count automatically, so this must be done manually
+            if Item <> nil then
+                Item._Release;
+        end
+        else
+            Inc(I);
+    end;
+    Result := ResultCollection;
+end;
+
+function TPArrayBag.GetCapacity: Integer;
+begin
+    Result := FList.Capacity;
+end;
+
+procedure TPArrayBag.SetCapacity(Value: Integer);
+begin
+    FList.Capacity := Value;
+end;
+
+function TPArrayBag.GetIterator: IIterator;
+begin
+    Result := TPArrayIterator.Create(FList, true);
+end;
+
+function TPArrayBag.GetSize: Integer;
+begin
+    Result := FList.Count;
+end;
+
+constructor TPArraySet.Create(NaturalItemsOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly);
+    FList := TList.Create;
+end;
+
+destructor TPArraySet.Destroy;
+begin
+    FList.Free;
+    inherited Destroy;
+end;
+
+function TPArraySet.GetPosition(const Item: ICollectable): TCollectionPosition;
+var
+    I: Integer;
+    Success: Boolean;
+begin
+    // Sequential search
+    I := 0;
+    Success := false;
+    while (I < FList.Count) do
+    begin
+        Success := Comparator.Equals(Item, ICollectable(FList[I]));
+        if Success then
+            break;
+        Inc(I);
+    end;
+    Result := TPArrayPosition.Create(Success, I);
+end;
+
+procedure TPArraySet.TrueAdd2(Position: TCollectionPosition; const Item: ICollectable);
+begin
+    FList.Add(Pointer(Item));
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Item._AddRef;
+end;
+
+procedure TPArraySet.TrueClear;
+var
+    Item: ICollectable;
+    I: Integer;
+begin
+    // Delete all interface references
+    for I := 0 to FList.Count - 1 do
+    begin
+        Item := ICollectable(FList[I]);
+        FList[I] := nil;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        Item._Release;
+    end;
+    FList.Clear;
+end;
+
+function TPArraySet.TrueGet(Position: TCollectionPosition): ICollectable;
+begin
+    Result := ICollectable(FList.Items[TPArrayPosition(Position).Index]);
+end;
+
+procedure TPArraySet.TrueRemove2(Position: TCollectionPosition);
+var
+    Item: ICollectable;
+begin
+    Item := ICollectable(FList[TPArrayPosition(Position).Index]);
+    FList.Delete(TPArrayPosition(Position).Index);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Item._Release;
+end;
+
+function TPArraySet.GetCapacity: Integer;
+begin
+    Result := FList.Capacity;
+end;
+
+procedure TPArraySet.SetCapacity(Value: Integer);
+begin
+    FList.Capacity := Value;
+end;
+
+function TPArraySet.GetIterator: IIterator;
+begin
+    Result := TPArrayIterator.Create(FList, true);
+end;
+
+function TPArraySet.GetSize: Integer;
+begin
+    Result := FList.Count;
+end;
+
+constructor TPArrayList.Create(NaturalItemsOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly);
+    FList := TList.Create;
+end;
+
+destructor TPArrayList.Destroy;
+begin
+    FList.Free;
+    inherited Destroy;
+end;
+
+function TPArrayList.TrueGetItem(Index: Integer): ICollectable;
+begin
+    Result := ICollectable(FList.Items[Index]);
+end;
+
+procedure TPArrayList.TrueSetItem(Index: Integer; const Item: ICollectable);
+var
+    OldItem: ICollectable;
+begin
+    OldItem := ICollectable(FList[Index]);
+    FList[Index] := Pointer(Item);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    if Item <> nil then
+        Item._AddRef;
+    if OldItem <> nil then
+        OldItem._Release;
+end;
+
+procedure TPArrayList.TrueAppend(const Item: ICollectable);
+begin
+    FList.Add(Pointer(Item));
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    if Item <> nil then
+        Item._AddRef;
+end;
+
+procedure TPArrayList.TrueClear;
+var
+    Item: ICollectable;
+    I: Integer;
+begin
+    // Delete all interface references
+    for I := 0 to FList.Count - 1 do
+    begin
+        Item := ICollectable(FList[I]);
+        FList[I] := nil;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        if Item <> nil then
+            Item._Release;
+    end;
+    FList.Clear;
+end;
+
+function TPArrayList.TrueDelete(Index: Integer): ICollectable;
+begin
+    Result := ICollectable(FList[Index]);
+    FList.Delete(Index);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    if Result <> nil then
+        Result._Release;
+end;
+
+procedure TPArrayList.TrueInsert(Index: Integer; const Item: ICollectable);
+begin
+    FList.Insert(Index, Pointer(Item));
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    if Item <> nil then
+        Item._AddRef;
+end;
+
+function TPArrayList.GetCapacity: Integer;
+begin
+    Result := FList.Capacity;
+end;
+
+procedure TPArrayList.SetCapacity(Value: Integer);
+begin
+    FList.Capacity := Value;
+end;
+
+function TPArrayList.GetIterator: IIterator;
+begin
+    Result := TPArrayIterator.Create(FList, true);
+end;
+
+function TPArrayList.GetSize: Integer;
+begin
+    Result := FList.Count;
+end;
+
+constructor TPArrayMap.Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly, NaturalKeysOnly);
+    FList := TList.Create;
+end;
+
+destructor TPArrayMap.Destroy;
+begin
+    FList.Free;
+    inherited Destroy;
+end;
+
+function TPArrayMap.GetAssociationIterator: IMapIterator;
+begin
+    Result := TPArrayAssociationIterator.Create(FList, true);
+end;
+
+function TPArrayMap.GetKeyPosition(const Key: ICollectable): TCollectionPosition;
+var
+    I: Integer;
+    Success: Boolean;
+begin
+    // Sequential search
+    I := 0;
+    Success := false;
+    while (I < FList.Count) do
+    begin
+        Success := KeyComparator.Equals(Key, IAssociation(FList[I]).GetKey);
+        if Success then
+            break;
+        Inc(I);
+    end;
+    Result := TPArrayPosition.Create(Success, I);
+end;
+
+procedure TPArrayMap.TrueClear;
+var
+    Association: IAssociation;
+    I: Integer;
+begin
+    // Delete all interface references
+    for I := 0 to FList.Count - 1 do
+    begin
+        Association := IAssociation(FList[I]);
+        FList[I] := nil;
+        // Storing interface reference as a pointer does not update reference
+        // count automatically, so this must be done manually
+        Association._Release;
+    end;
+    FList.Clear;
+end;
+
+function TPArrayMap.TrueGet(Position: TCollectionPosition): IAssociation;
+begin
+    Result := IAssociation(FList.Items[TPArrayPosition(Position).Index]);
+end;
+
+function TPArrayMap.TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation;
+var
+    OldAssociation: IAssociation;
+    Index: Integer;
+begin
+    if Position.Found then
+    begin
+        Index := (Position as TPArrayPosition).Index;
+        OldAssociation := IAssociation(FList[Index]);
+        FList[Index] := Pointer(Association);
+    end
+    else
+    begin
+        OldAssociation := nil;
+        FList.Add(Pointer(Association));
+    end;
+    Result := OldAssociation;
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Association._AddRef;
+    if OldAssociation <> nil then
+        OldAssociation._Release;
+end;
+
+function TPArrayMap.TrueRemove2(Position: TCollectionPosition): IAssociation;
+var
+    OldAssociation: IAssociation;
+begin
+    OldAssociation := IAssociation(FList[TPArrayPosition(Position).Index]);
+    FList.Delete(TPArrayPosition(Position).Index);
+    Result := OldAssociation;
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    OldAssociation._Release;
+end;
+
+function TPArrayMap.GetCapacity: Integer;
+begin
+    Result := FList.Capacity;
+end;
+
+procedure TPArrayMap.SetCapacity(Value: Integer);
+begin
+    FList.Capacity := Value;
+end;
+
+function TPArrayMap.GetSize: Integer;
+begin
+    Result := FList.Count;
+end;
+
+procedure TExposedPArrayList.TrueAppend(const Item: ICollectable);
+begin
+    inherited TrueAppend(Item);
+end;
+
+procedure TExposedPArrayList.TrueInsert(Index: Integer; const Item: ICollectable);
+begin
+    inherited TrueInsert(Index, Item);
+end;
+
+{ TPArrayIterator }
+constructor TPArrayIterator.Create(List: TList; AllowRemove: Boolean);
+begin
+    inherited Create(AllowRemove);
+    FList := List;
+    FIndex := -1;
+end;
+
+function TPArrayIterator.TrueFirst: ICollectable;
+begin
+    FIndex := 0;
+    if FIndex < FList.Count then
+        Result := ICollectable(FList[FIndex])
+    else
+        Result := nil;
+end;
+
+function TPArrayIterator.TrueNext: ICollectable;
+begin
+    Inc(FIndex);
+    if FIndex < FList.Count then
+        Result := ICollectable(FList[FIndex])
+    else
+        Result := nil;
+end;
+
+procedure TPArrayIterator.TrueRemove;
+var
+    Item: ICollectable;
+begin
+    Item := ICollectable(FList[FIndex]);
+    FList.Delete(FIndex);
+    Dec(FIndex);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Item._Release;
+end;
+
+{ TPArrayAssociationIterator }
+constructor TPArrayAssociationIterator.Create(List: TList; AllowRemove: Boolean);
+begin
+    inherited Create(AllowRemove);
+    FList := List;
+    FIndex := -1;
+end;
+
+function TPArrayAssociationIterator.TrueFirst: IAssociation;
+begin
+    FIndex := 0;
+    if FIndex < FList.Count then
+        Result := IAssociation(FList[FIndex])
+    else
+        Result := nil;
+end;
+
+function TPArrayAssociationIterator.TrueNext: IAssociation;
+begin
+    Inc(FIndex);
+    if FIndex < FList.Count then
+        Result := IAssociation(FList[FIndex])
+    else
+        Result := nil;
+end;
+
+procedure TPArrayAssociationIterator.TrueRemove;
+var
+    Association: IAssociation;
+begin
+    Association := IAssociation(FList[FIndex]);
+    FList.Delete(FIndex);
+    Dec(FIndex);
+    // Storing interface reference as a pointer does not update reference
+    // count automatically, so this must be done manually
+    Association._Release;
+end;
+
+{ TPArrayPosition }
+constructor TPArrayPosition.Create(Found: Boolean; Index: Integer);
+begin
+    inherited Create(Found);
+    FIndex := Index;
+end;
+
+end.
diff --git a/songmanagement/src/lib/collections/CollWrappers.pas b/songmanagement/src/lib/collections/CollWrappers.pas
new file mode 100644
index 00000000..513103a2
--- /dev/null
+++ b/songmanagement/src/lib/collections/CollWrappers.pas
@@ -0,0 +1,876 @@
+unit CollWrappers;
+
+(*****************************************************************************
+ * Copyright 2003 by Matthew Greet
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details. (http://opensource.org/licenses/lgpl-license.php)
+ *
+ * See http://www.warmachine.u-net.com/delphi_collections for updates and downloads.
+ *
+ * $Version: v1.0.3 $
+ * $Revision: 1.1.1.1 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollWrappers.qbt $
+ * 
+ *   Various primitive type wrappers, adapters and abstract base classes for
+ *   natural items.
+ * 
+ * Revision 1.1.1.1  by: Matthew Greet  Rev date: 24/10/03 16:48:16
+ *   v1.0 branch.
+ * 
+ * Revision 1.1  by: Matthew Greet  Rev date: 06/04/03 10:51:04
+ *   Primitive type wrapper interfaces added. 
+ *   Abstract, template classes added. 
+ *   All classes implement reference counting by descending from
+ *   TInterfacedObject. 
+ *   
+ * 
+ * Revision 1.0  by: Matthew Greet  Rev date: 01/03/03 10:50:02
+ *   Initial revision.
+ * 
+ * FPC compatibility fixes by: UltraStar Deluxe Team
+ *
+ * $Endlog$
+ *****************************************************************************)
+
+{$IFDEF FPC}
+  {$MODE Delphi}{$H+}
+{$ENDIF}
+ 
+interface
+
+uses
+    SysUtils,
+    Collections;
+
+type
+    IAssociationWrapper = interface
+        ['{54DF42E0-64F2-11D7-8120-0002E3165EF8}']
+        function GetAutoDestroy: Boolean;
+        procedure SetAutoDestroy(Value: Boolean);
+        function GetKey: ICollectable;
+        function GetValue: TObject;
+        property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+        property Key: ICollectable read GetKey;
+        property Value: TObject read GetValue;
+    end;
+
+    IBoolean = interface
+        ['{62D1D160-64F2-11D7-8120-0002E3165EF8}']
+        function GetValue: Boolean;
+        property Value: Boolean read GetValue;
+    end;
+
+    ICardinal = interface
+        ['{6AF7B1C0-64F2-11D7-8120-0002E3165EF8}']
+        function GetValue: Cardinal;
+        property Value: Cardinal read GetValue;
+    end;
+
+    IChar = interface
+        ['{73AD00E0-64F2-11D7-8120-0002E3165EF8}']
+        function GetValue: Char;
+        property Value: Char read GetValue;
+    end;
+
+    IClass = interface
+        ['{7A84B660-64F2-11D7-8120-0002E3165EF8}']
+        function GetValue: TClass;
+        property Value: TClass read GetValue;
+    end;
+
+    IDouble = interface
+        ['{815C6BE0-64F2-11D7-8120-0002E3165EF8}']
+        function GetValue: Double;
+        property Value: Double read GetValue;
+    end;
+
+    IInteger = interface
+        ['{88ECC300-64F2-11D7-8120-0002E3165EF8}']
+        function GetValue: Integer;
+        property Value: Integer read GetValue;
+    end;
+
+    IIntegerAssociationWrapper = interface
+        ['{8F582220-64F2-11D7-8120-0002E3165EF8}']
+        function GetAutoDestroy: Boolean;
+        procedure SetAutoDestroy(Value: Boolean);
+        function GetKey: Integer;
+        function GetValue: TObject;
+        property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+        property Key: Integer read GetKey;
+        property Value: TObject read GetValue;
+    end;
+
+    IInterfaceWrapper = interface
+        ['{962E5100-64F2-11D7-8120-0002E3165EF8}']
+        function GetValue: IUnknown;
+        property Value: IUnknown read GetValue;
+    end;
+
+    IObject = interface
+        ['{9C675580-64F2-11D7-8120-0002E3165EF8}']
+        function GetAutoDestroy: Boolean;
+        procedure SetAutoDestroy(Value: Boolean);
+        function GetValue: TObject;
+        property Value: TObject read GetValue;
+    end;
+
+    IString = interface
+        ['{A420DF80-64F2-11D7-8120-0002E3165EF8}']
+        function GetValue: String;
+        property Value: String read GetValue;
+    end;
+
+    IStringAssociationWrapper = interface
+        ['{AB98CCA0-64F2-11D7-8120-0002E3165EF8}']
+        function GetAutoDestroy: Boolean;
+        procedure SetAutoDestroy(Value: Boolean);
+        function GetKey: String;
+        function GetValue: TObject;
+        property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+        property Key: String read GetKey;
+        property Value: TObject read GetValue;
+    end;
+
+    TAbstractItem = class(TInterfacedObject, ICollectable)
+    public
+        function GetInstance: TObject; virtual;
+    end;
+
+    TAbstractIntegerMappable = class(TAbstractItem, IEquatable, IIntegerMappable)
+    private
+        FKey: Integer;
+    protected
+        function MakeKey: Integer; virtual; abstract;
+    public
+        procedure AfterConstruction; override;
+        function Equals(const Item: ICollectable): Boolean; virtual;
+        function GetKey: Integer; virtual;
+    end;
+
+    TAbstractMappable = class(TAbstractItem, IEquatable, IMappable)
+    private
+        FKey: ICollectable;
+    protected
+        function MakeKey: ICollectable; virtual; abstract;
+    public
+        destructor Destroy; override;
+        procedure AfterConstruction; override;
+        function Equals(const Item: ICollectable): Boolean; virtual;
+        function GetKey: ICollectable; virtual;
+    end;
+
+    TAbstractStringMappable = class(TAbstractItem, IEquatable, IStringMappable)
+    private
+        FKey: String;
+    protected
+        function MakeKey: String; virtual; abstract;
+    public
+        procedure AfterConstruction; override;
+        function Equals(const Item: ICollectable): Boolean; virtual;
+        function GetKey: String; virtual;
+    end;
+
+    TAssociationWrapper = class(TAbstractItem, IEquatable, IMappable, IAssociationWrapper)
+    private
+        FAutoDestroy: Boolean;
+        FKey: ICollectable;
+        FValue: TObject;
+    public
+        constructor Create(const Key: ICollectable; Value: TObject); overload;
+        constructor Create(Key: Integer; Value: TObject); overload;
+        constructor Create(Key: String; Value: TObject); overload;
+        constructor Create(Key, Value: TObject; AutoDestroyKey: Boolean = true); overload;
+        destructor Destroy; override;
+        function GetAutoDestroy: Boolean;
+        procedure SetAutoDestroy(Value: Boolean);
+        function GetKey: ICollectable;
+        function GetValue: TObject;
+        function Equals(const Item: ICollectable): Boolean;
+        property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+        property Key: ICollectable read GetKey;
+        property Value: TObject read GetValue;
+    end;
+
+    TBooleanWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IBoolean)
+    private
+        FValue: Boolean;
+    public
+        constructor Create(Value: Boolean);
+        function GetValue: Boolean;
+        function CompareTo(const Item: ICollectable): Integer;
+        function Equals(const Item: ICollectable): Boolean;
+        function HashCode: Integer;
+        property Value: Boolean read GetValue;
+    end;
+
+    TCardinalWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, ICardinal)
+    private
+        FValue: Cardinal;
+    public
+        constructor Create(Value: Cardinal);
+        function GetValue: Cardinal;
+        function Equals(const Item: ICollectable): Boolean;
+        function HashCode: Integer;
+        function CompareTo(const Item: ICollectable): Integer;
+        property Value: Cardinal read GetValue;
+    end;
+
+    TCharWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IChar)
+    private
+        FValue: Char;
+    public
+        constructor Create(Value: Char);
+        function GetValue: Char;
+        function Equals(const Item: ICollectable): Boolean;
+        function HashCode: Integer;
+        function CompareTo(const Item: ICollectable): Integer;
+        property Value: Char read GetValue;
+    end;
+
+    TClassWrapper = class(TAbstractItem, IEquatable, IHashable, IClass)
+    private
+        FValue: TClass;
+    public
+        constructor Create(Value: TClass);
+        function GetValue: TClass;
+        function Equals(const Item: ICollectable): Boolean;
+        function HashCode: Integer;
+        property Value: TClass read GetValue;
+    end;
+
+    TDoubleWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IDouble)
+    private
+        FValue: Double;
+    public
+        constructor Create(Value: Double);
+        function GetValue: Double;
+        function Equals(const Item: ICollectable): Boolean;
+        function HashCode: Integer;
+        function CompareTo(const Item: ICollectable): Integer;
+        property Value: Double read GetValue;
+    end;
+
+    TIntegerWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IInteger)
+    private
+        FValue: Integer;
+    public
+        constructor Create(Value: Integer);
+        function GetValue: Integer;
+        function Equals(const Item: ICollectable): Boolean;
+        function HashCode: Integer;
+        function CompareTo(const Item: ICollectable): Integer;
+        property Value: Integer read GetValue;
+    end;
+
+    TIntegerAssociationWrapper = class(TAbstractItem, IEquatable, IIntegerMappable, IIntegerAssociationWrapper)
+    private
+        FAutoDestroy: Boolean;
+        FKey: Integer;
+        FValue: TObject;
+    public
+        constructor Create(const Key: Integer; Value: TObject); overload;
+        destructor Destroy; override;
+        function Equals(const Item: ICollectable): Boolean;
+        function GetAutoDestroy: Boolean;
+        procedure SetAutoDestroy(Value: Boolean);
+        function GetKey: Integer;
+        function GetValue: TObject;
+        property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+        property Key: Integer read GetKey;
+        property Value: TObject read GetValue;
+    end;
+
+    TInterfaceWrapper = class(TAbstractItem, IHashable, IEquatable, IInterfaceWrapper)
+    private
+        FValue: IUnknown;
+    public
+        constructor Create(const Value: IUnknown);
+        destructor Destroy; override;
+        function GetValue: IUnknown;
+        function Equals(const Item: ICollectable): Boolean;
+        function HashCode: Integer;
+        property Value: IUnknown read GetValue;
+    end;
+
+    TObjectWrapper = class(TAbstractItem, IEquatable, IComparable, IHashable, IObject)
+    private
+        FAutoDestroy: Boolean;
+        FValue: TObject;
+    public
+        constructor Create(Value: TObject); overload;
+        destructor Destroy; override;
+        function GetAutoDestroy: Boolean;
+        procedure SetAutoDestroy(Value: Boolean);
+        function GetValue: TObject;
+        function CompareTo(const Item: ICollectable): Integer;
+        function Equals(const Item: ICollectable): Boolean;
+        function HashCode: Integer;
+        property AutoDestroy: Boolean read FAutoDestroy write FAutoDestroy;
+        property Value: TObject read GetValue;
+    end;
+
+    TStringWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IString)
+    private
+        FValue: String;
+    public
+        constructor Create(Value: String);
+        function GetValue: String;
+        function Equals(const Item: ICollectable): Boolean;
+        function HashCode: Integer;
+        function CompareTo(const Item: ICollectable): Integer;
+        property Value: String read FValue;
+    end;
+
+    TStringAssociationWrapper = class(TAbstractItem, IEquatable, IStringMappable, IStringAssociationWrapper)
+    private
+        FAutoDestroy: Boolean;
+        FKey: String;
+        FValue: TObject;
+    public
+        constructor Create(const Key: String; Value: TObject); overload;
+        destructor Destroy; override;
+        function GetAutoDestroy: Boolean;
+        procedure SetAutoDestroy(Value: Boolean);
+        function GetKey: String;
+        function GetValue: TObject;
+        function Equals(const Item: ICollectable): Boolean;
+        property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+        property Key: String read GetKey;
+        property Value: TObject read GetValue;
+    end;
+
+implementation
+
+{ TAbstractItem }
+function TAbstractItem.GetInstance: TObject;
+begin
+    Result := Self;
+end;
+
+
+{ TAbstractIntegerMappable }
+procedure TAbstractIntegerMappable.AfterConstruction;
+begin
+    inherited AfterConstruction;
+    FKey := MakeKey;
+end;
+
+function TAbstractIntegerMappable.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self = Item.GetInstance);
+end;
+
+function TAbstractIntegerMappable.GetKey: Integer;
+begin
+    Result := FKey;
+end;
+
+{ TAbstractMappable }
+destructor TAbstractMappable.Destroy;
+begin
+    FKey := nil;
+    inherited Destroy;
+end;
+
+procedure TAbstractMappable.AfterConstruction;
+begin
+    inherited AfterConstruction;
+    FKey := MakeKey;
+end;
+
+function TAbstractMappable.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self = Item.GetInstance);
+end;
+
+function TAbstractMappable.GetKey: ICollectable;
+begin
+    Result := FKey;
+end;
+
+{ TAbstractStringMappable }
+procedure TAbstractStringMappable.AfterConstruction;
+begin
+    inherited AfterConstruction;
+    FKey := MakeKey;
+end;
+
+function TAbstractStringMappable.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self = Item.GetInstance);
+end;
+
+function TAbstractStringMappable.GetKey: String;
+begin
+    Result := FKey;
+end;
+
+{ TAssociationWrapper }
+constructor TAssociationWrapper.Create(const Key: ICollectable; Value: TObject);
+begin
+    inherited Create;
+    FAutoDestroy := true;
+    FKey := Key;
+    FValue := Value;
+end;
+
+constructor TAssociationWrapper.Create(Key: Integer; Value: TObject);
+begin
+    Create(TIntegerWrapper.Create(Key) as ICollectable, Value);
+end;
+
+constructor TAssociationWrapper.Create(Key: String; Value: TObject);
+begin
+    Create(TStringWrapper.Create(Key) as ICollectable, Value);
+end;
+
+constructor TAssociationWrapper.Create(Key, Value: TObject; AutoDestroyKey: Boolean);
+var
+    KeyWrapper: TObjectWrapper;
+begin
+    KeyWrapper := TObjectWrapper.Create(Key);
+    KeyWrapper.AutoDestroy := AutoDestroyKey;
+    Create(KeyWrapper as ICollectable, Value);
+end;
+
+destructor TAssociationWrapper.Destroy;
+begin
+    if FAutoDestroy then
+        FValue.Free;
+    FKey := nil;
+    inherited Destroy;
+end;
+
+function TAssociationWrapper.GetAutoDestroy: Boolean;
+begin
+    Result := FAutoDestroy;
+end;
+
+procedure TAssociationWrapper.SetAutoDestroy(Value: Boolean);
+begin
+    FAutoDestroy := Value;
+end;
+
+function TAssociationWrapper.GetKey: ICollectable;
+begin
+    Result := FKey;
+end;
+
+function TAssociationWrapper.GetValue: TObject;
+begin
+    Result := FValue;
+end;
+
+function TAssociationWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TAssociationWrapper).Value)
+end;
+
+{ TCardinalWrapper }
+constructor TCardinalWrapper.Create(Value: Cardinal);
+begin
+    inherited Create;
+    FValue := Value;
+end;
+
+function TCardinalWrapper.GetValue: Cardinal;
+begin
+    Result := FValue;
+end;
+
+function TCardinalWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TCardinalWrapper).Value)
+end;
+
+function TCardinalWrapper.HashCode: Integer;
+begin
+    Result := FValue;
+end;
+
+function TCardinalWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+    Value2: Cardinal;
+begin
+    Value2 := (Item.GetInstance as TCardinalWrapper).Value;
+    if Value < Value2 then
+        Result := -1
+    else if Value > Value2 then
+        Result := 1
+    else
+        Result := 0;
+end;
+
+{ TBooleanWrapper }
+constructor TBooleanWrapper.Create(Value: Boolean);
+begin
+    inherited Create;
+    FValue := Value;
+end;
+
+function TBooleanWrapper.GetValue: Boolean;
+begin
+    Result := FValue;
+end;
+
+function TBooleanWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TBooleanWrapper).Value)
+end;
+
+function TBooleanWrapper.HashCode: Integer;
+begin
+    Result := Ord(FValue);
+end;
+
+function TBooleanWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+    Value2: Boolean;
+begin
+    Value2 := (Item.GetInstance as TBooleanWrapper).Value;
+    if not Value and Value2 then
+        Result := -1
+    else if Value and not Value2 then
+        Result := 1
+    else
+        Result := 0;
+end;
+
+{ TCharWrapper }
+constructor TCharWrapper.Create(Value: Char);
+begin
+    inherited Create;
+    FValue := Value;
+end;
+
+function TCharWrapper.GetValue: Char;
+begin
+    Result := FValue;
+end;
+
+function TCharWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TCharWrapper).Value)
+end;
+
+function TCharWrapper.HashCode: Integer;
+begin
+    Result := Integer(FValue);
+end;
+
+function TCharWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+    Value2: Char;
+begin
+    Value2 := (Item.GetInstance as TCharWrapper).Value;
+    if Value < Value2 then
+        Result := -1
+    else if Value > Value2 then
+        Result := 1
+    else
+        Result := 0;
+end;
+
+{ TClassWrapper }
+constructor TClassWrapper.Create(Value: TClass);
+begin
+    inherited Create;
+    FValue := Value;
+end;
+
+function TClassWrapper.GetValue: TClass;
+begin
+    Result := FValue;
+end;
+
+function TClassWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TClassWrapper).Value)
+end;
+
+function TClassWrapper.HashCode: Integer;
+begin
+    Result := Integer(FValue.ClassInfo);
+end;
+
+{ TDoubleWrapper }
+constructor TDoubleWrapper.Create(Value: Double);
+begin
+    inherited Create;
+    FValue := Value;
+end;
+
+function TDoubleWrapper.GetValue: Double;
+begin
+    Result := FValue;
+end;
+
+function TDoubleWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TDoubleWrapper).Value)
+end;
+
+function TDoubleWrapper.HashCode: Integer;
+var
+    DblAsInt: array[0..1] of Integer;
+begin
+    Double(DblAsInt) := Value;
+    Result := DblAsInt[0] xor DblAsInt[1];
+end;
+
+function TDoubleWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+    Value2: Double;
+begin
+    Value2 := (Item.GetInstance as TDoubleWrapper).Value;
+    if Value < Value2 then
+        Result := -1
+    else if Value > Value2 then
+        Result := 1
+    else
+        Result := 0;
+end;
+
+{ TIntegerWrapper }
+constructor TIntegerWrapper.Create(Value: Integer);
+begin
+    inherited Create;
+    FValue := Value;
+end;
+
+function TIntegerWrapper.GetValue: Integer;
+begin
+    Result := FValue;
+end;
+
+function TIntegerWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TIntegerWrapper).Value)
+end;
+
+function TIntegerWrapper.HashCode: Integer;
+begin
+    Result := FValue;
+end;
+
+function TIntegerWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+    Value2: Integer;
+begin
+    Value2 := (Item.GetInstance as TIntegerWrapper).Value;
+    if Value < Value2 then
+        Result := -1
+    else if Value > Value2 then
+        Result := 1
+    else
+        Result := 0;
+end;
+
+{ TIntegerAssociationWrapper }
+constructor TIntegerAssociationWrapper.Create(const Key: Integer; Value: TObject);
+begin
+    inherited Create;
+    FAutoDestroy := true;
+    FKey := Key;
+    FValue := Value;
+end;
+
+destructor TIntegerAssociationWrapper.Destroy;
+begin
+    if FAutoDestroy then
+        FValue.Free;
+    inherited Destroy;
+end;
+
+function TIntegerAssociationWrapper.GetAutoDestroy: Boolean;
+begin
+    Result := FAutoDestroy;
+end;
+
+procedure TIntegerAssociationWrapper.SetAutoDestroy(Value: Boolean);
+begin
+    FAutoDestroy := Value;
+end;
+
+function TIntegerAssociationWrapper.GetValue: TObject;
+begin
+    Result := FValue;
+end;
+
+function TIntegerAssociationWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TIntegerAssociationWrapper).Value)
+end;
+
+function TIntegerAssociationWrapper.GetKey: Integer;
+begin
+    Result := FKey;
+end;
+
+{ TStringAssociationWrapper }
+constructor TStringAssociationWrapper.Create(const Key: String; Value: TObject);
+begin
+    inherited Create;
+    FAutoDestroy := true;
+    FKey := Key;
+    FValue := Value;
+end;
+
+destructor TStringAssociationWrapper.Destroy;
+begin
+    if FAutoDestroy then
+        FValue.Free;
+    inherited Destroy;
+end;
+
+function TStringAssociationWrapper.GetAutoDestroy: Boolean;
+begin
+    Result := FAutoDestroy;
+end;
+
+procedure TStringAssociationWrapper.SetAutoDestroy(Value: Boolean);
+begin
+    FAutoDestroy := Value;
+end;
+
+function TStringAssociationWrapper.GetValue: TObject;
+begin
+    Result := FValue;
+end;
+
+function TStringAssociationWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TStringAssociationWrapper).Value)
+end;
+
+function TStringAssociationWrapper.GetKey: String;
+begin
+    Result := FKey;
+end;
+
+{ TInterfaceWrapper }
+constructor TInterfaceWrapper.Create(const Value: IUnknown);
+begin
+    inherited Create;
+    FValue := Value;
+end;
+
+destructor TInterfaceWrapper.Destroy;
+begin
+    FValue := nil;
+    inherited Destroy;
+end;
+
+function TInterfaceWrapper.GetValue: IUnknown;
+begin
+    Result := FValue;
+end;
+
+function TInterfaceWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TInterfaceWrapper).Value)
+end;
+
+function TInterfaceWrapper.HashCode: Integer;
+begin
+    Result := Integer(Pointer(FValue));
+end;
+
+{ TObjectWrapper }
+constructor TObjectWrapper.Create(Value: TObject);
+begin
+    inherited Create;
+    FAutoDestroy := true;
+    FValue := Value;
+end;
+
+destructor TObjectWrapper.Destroy;
+begin
+    if FAutoDestroy then
+        FValue.Free;
+    inherited Destroy;
+end;
+
+function TObjectWrapper.GetAutoDestroy: Boolean;
+begin
+    Result := FAutoDestroy;
+end;
+
+procedure TObjectWrapper.SetAutoDestroy(Value: Boolean);
+begin
+    FAutoDestroy := Value;
+end;
+
+function TObjectWrapper.GetValue: TObject;
+begin
+    Result := FValue;
+end;
+
+function TObjectWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+    Value1, Value2: Integer;
+begin
+    Value1 := Integer(Pointer(Self));
+    if Item <> nil then
+        Value2 := Integer(Pointer(Item))
+    else
+        Value2 := Low(Integer);
+    if (Value1 < Value2) then
+        Result := -1
+    else if (Value1 > Value2) then
+        Result := 1
+    else
+        Result := 0;
+end;
+
+function TObjectWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TObjectWrapper).Value)
+end;
+
+function TObjectWrapper.HashCode: Integer;
+begin
+    Result := Integer(Pointer(FValue));
+end;
+
+{ TStringWrapper }
+constructor TStringWrapper.Create(Value: String);
+begin
+    inherited Create;
+    FValue := Value;
+end;
+
+function TStringWrapper.GetValue: String;
+begin
+    Result := FValue;
+end;
+
+function TStringWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+    Result := (Self.Value = (Item.GetInstance as TStringWrapper).Value)
+end;
+
+function TStringWrapper.HashCode: Integer;
+var
+    I: Integer;
+begin
+    Result := 0;
+    for I := 1 to Length(FValue) do
+        Result := (Result shl 1) xor Ord(FValue[I]);
+end;
+
+function TStringWrapper.CompareTo(const Item: ICollectable): Integer;
+begin
+    Result := CompareStr(Self.Value, (Item.GetInstance as TStringWrapper).Value)
+end;
+
+
+end.
diff --git a/songmanagement/src/lib/collections/Collections.pas b/songmanagement/src/lib/collections/Collections.pas
new file mode 100644
index 00000000..0c94173d
--- /dev/null
+++ b/songmanagement/src/lib/collections/Collections.pas
@@ -0,0 +1,5318 @@
+unit Collections;
+(*****************************************************************************
+ * Copyright 2003 by Matthew Greet
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details. (http://opensource.org/licenses/lgpl-license.php)
+ * 
+ * See http://www.warmachine.u-net.com/delphi_collections for updates and downloads.
+ *
+ * $Version: v1.0 $
+ * $Revision: 1.1.1.4 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\Collections.qbt $
+ * 
+ *   Main unit containing all interface and abstract class definitions.
+ * 
+ * Revision 1.1.1.4  by: Matthew Greet  Rev date: 14/03/05 23:26:32
+ *   Fixed RemoveAll for TAbstractList for sorted lists.
+ * 
+ * Revision 1.1.1.3  by: Matthew Greet  Rev date: 14/10/04 16:31:18
+ *   Fixed memory lean in ContainsKey of TAbstractStringMap and
+ *   TAbstractIntegerMap.
+ * 
+ * Revision 1.1.1.2  by: Matthew Greet  Rev date: 12/06/04 20:03:26
+ *   Capacity property. 
+ *   Memory leak fixed.
+ * 
+ * Revision 1.1.1.1  by: Matthew Greet  Rev date: 13/02/04 16:12:10
+ *   v1.0 branch.
+ * 
+ * Revision 1.1  by: Matthew Greet  Rev date: 06/04/03 10:36:30
+ *   Added integer map and string map collection types with supporting
+ *   classes. 
+ *   Add clone and filter functions with supporting classes. 
+ *   Added nil not allowed collection error. 
+ *   Properties appear in collection interfaces as well as abstract
+ *   classes.
+ * 
+ * Revision 1.0  by: Matthew Greet  Rev date: 01/03/03 10:50:02
+ *   Initial revision.
+ * 
+ * FPC compatibility fixes by: UltraStar Deluxe Team
+ *
+ * $Endlog$
+ *****************************************************************************)
+
+{$IFDEF FPC}
+  {$MODE Delphi}{$H+}
+{$ENDIF}
+ 
+interface
+
+uses
+    Classes, SysUtils;
+
+const
+    EquatableIID: TGUID = '{EAC823A7-0B90-11D7-8120-0002E3165EF8}';
+    HashableIID: TGUID = '{98998440-4C3E-11D7-8120-0002E3165EF8}';
+    ComparableIID: TGUID = '{9F4C96C0-0CF0-11D7-8120-0002E3165EF8}';
+    MappableIID: TGUID = '{DAEC8CA0-0DBB-11D7-8120-0002E3165EF8}';
+    StringMappableIID: TGUID = '{3CC61F40-5F92-11D7-8120-0002E3165EF8}';
+    IntegerMappableIID: TGUID = '{774FC760-5F92-11D7-8120-0002E3165EF8}';
+
+type
+    TDefaultComparator = class;
+    TNaturalComparator = class;
+    ICollectable = interface;
+
+    TCollectableArray = array of ICollectable;
+    TIntegerArray = array of Integer;
+    TStringArray = array of String;
+    TListArray = array of TList;
+
+    TCollectionError = (ceOK, ceDuplicate, ceDuplicateKey, ceFixedSize, ceNilNotAllowed, ceNotNaturalItem, ceOutOfRange);
+    TCollectionErrors = set of TCollectionError;
+
+    TSearchResultType = (srNotFound, srFoundAtIndex, srBeforeIndex, srAfterEnd);
+
+    TCollectionType = (ctBag, ctSet, ctList, ctMap, ctIntegerMap, ctStringMap);
+
+    TCollectionFilterFunc = function (const Item: ICollectable): Boolean of object;
+    TCollectionCompareFunc = function (const Item1, Item2: ICollectable): Integer of object;
+
+    TSearchResult = record
+        ResultType: TSearchResultType;
+        Index: Integer;
+    end;
+
+    ICollectable = interface
+        ['{98998441-4C3E-11D7-8120-0002E3165EF8}']
+        function GetInstance: TObject;
+    end;
+
+    IEquatable = interface
+        ['{EAC823A7-0B90-11D7-8120-0002E3165EF8}']
+        function GetInstance: TObject;
+        function Equals(const Item: ICollectable): Boolean;
+    end;
+
+    IHashable = interface(IEquatable)
+        ['{98998440-4C3E-11D7-8120-0002E3165EF8}']
+        function HashCode: Integer;
+    end;
+
+    IComparable = interface(IEquatable)
+        ['{9F4C96C0-0CF0-11D7-8120-0002E3165EF8}']
+        function CompareTo(const Item: ICollectable): Integer;
+    end;
+
+    IMappable = interface(IEquatable)
+        ['{DAEC8CA0-0DBB-11D7-8120-0002E3165EF8}']
+        function GetKey: ICollectable;
+    end;
+
+    IStringMappable = interface(IEquatable)
+        ['{3CC61F40-5F92-11D7-8120-0002E3165EF8}']
+        function GetKey: String;
+    end;
+
+    IIntegerMappable = interface(IEquatable)
+        ['{774FC760-5F92-11D7-8120-0002E3165EF8}']
+        function GetKey: Integer;
+    end;
+
+    IComparator = interface
+        ['{1F20CD60-10FE-11D7-8120-0002E3165EF8}']
+        function GetInstance: TObject;
+        function Compare(const Item1, Item2: ICollectable): Integer;
+        function Equals(const Item1, Item2: ICollectable): Boolean; overload;
+        function Equals(const Comparator: IComparator): Boolean; overload;
+    end;
+
+    IFilter = interface
+        ['{27FE44C0-638E-11D7-8120-0002E3165EF8}']
+        function Accept(const Item: ICollectable): Boolean;
+    end;
+
+    IIterator = interface
+        ['{F6930500-1113-11D7-8120-0002E3165EF8}']
+        function GetAllowRemoval: Boolean;
+        function CurrentItem: ICollectable;
+        function EOF: Boolean;
+        function First: ICollectable;
+        function Next: ICollectable;
+        function Remove: Boolean;
+    end;
+
+    IMapIterator = interface(IIterator)
+        ['{848CC0E0-2A31-11D7-8120-0002E3165EF8}']
+        function CurrentKey: ICollectable;
+    end;
+
+    IIntegerMapIterator = interface(IIterator)
+        ['{C7169780-606C-11D7-8120-0002E3165EF8}']
+        function CurrentKey: Integer;
+    end;
+
+    IStringMapIterator = interface(IIterator)
+        ['{1345ED20-5F93-11D7-8120-0002E3165EF8}']
+        function CurrentKey: String;
+    end;
+
+    IAssociation = interface(ICollectable)
+        ['{556CD700-4DB3-11D7-8120-0002E3165EF8}']
+        function GetKey: ICollectable;
+        function GetValue: ICollectable;
+    end;
+
+    IIntegerAssociation = interface(ICollectable)
+        ['{ED954420-5F94-11D7-8120-0002E3165EF8}']
+        function GetKey: Integer;
+        function GetValue: ICollectable;
+    end;
+
+    IStringAssociation = interface(ICollectable)
+        ['{FB87D2A0-5F94-11D7-8120-0002E3165EF8}']
+        function GetKey: String;
+        function GetValue: ICollectable;
+    end;
+
+    IAssociationComparator = interface(IComparator)
+        ['{EA9BE6E0-A852-11D8-B93A-0002E3165EF8}']
+        function GetKeyComparator: IComparator;
+        procedure SetKeyComparator(Value: IComparator);
+        property KeyComparator: IComparator read GetKeyComparator write SetKeyComparator;
+    end;
+
+    IIntegerAssociationComparator = interface(IComparator)
+        ['{EA9BE6E1-A852-11D8-B93A-0002E3165EF8}']
+    end;
+
+    IStringAssociationComparator = interface(IComparator)
+        ['{EA9BE6E2-A852-11D8-B93A-0002E3165EF8}']
+    end;
+
+    ICollection = interface
+        ['{EAC823AC-0B90-11D7-8120-0002E3165EF8}']
+        function GetAsArray: TCollectableArray;
+        function GetCapacity: Integer;
+        procedure SetCapacity(Value: Integer);
+        function GetComparator: IComparator;
+        procedure SetComparator(const Value: IComparator);
+        function GetDuplicates: Boolean;
+        function GetFixedSize: Boolean;
+        function GetIgnoreErrors: TCollectionErrors;
+        procedure SetIgnoreErrors(Value: TCollectionErrors);
+        function GetInstance: TObject;
+        function GetIterator: IIterator; overload;
+        function GetIterator(const Filter: IFilter): IIterator; overload;
+        function GetIterator(FilterFunc: TCollectionFilterFunc): IIterator; overload;
+        function GetNaturalItemIID: TGUID;
+        function GetNaturalItemsOnly: Boolean;
+        function GetSize: Integer;
+        function GetType: TCollectionType;
+        function Add(const Item: ICollectable): Boolean; overload;
+        function Add(const ItemArray: array of ICollectable): Integer; overload;
+        function Add(const Collection: ICollection): Integer; overload;
+        function Clear: Integer;
+        function Clone: ICollection;
+        function Contains(const Item: ICollectable): Boolean; overload;
+        function Contains(const ItemArray: array of ICollectable): Boolean; overload;
+        function Contains(const Collection: ICollection): Boolean; overload;
+        function Equals(const Collection: ICollection): Boolean;
+        function Find(const Filter: IFilter): ICollectable; overload;
+        function Find(FilterFunc: TCollectionFilterFunc): ICollectable; overload;
+        function FindAll(const Filter: IFilter = nil): ICollection; overload;
+        function FindAll(FilterFunc: TCollectionFilterFunc): ICollection; overload;
+        function IsEmpty: Boolean;
+        function IsNaturalItem(const Item: ICollectable): Boolean;
+        function IsNilAllowed: Boolean;
+        function ItemAllowed(const Item: ICollectable): TCollectionError;
+        function ItemCount(const Item: ICollectable): Integer; overload;
+        function ItemCount(const ItemArray: array of ICollectable): Integer; overload;
+        function ItemCount(const Collection: ICollection): Integer; overload;
+        function Matching(const ItemArray: array of ICollectable): ICollection; overload;
+        function Matching(const Collection: ICollection): ICollection; overload;
+        function Remove(const Item: ICollectable): ICollectable; overload;
+        function Remove(const ItemArray: array of ICollectable): ICollection; overload;
+        function Remove(const Collection: ICollection): ICollection; overload;
+        function RemoveAll(const Item: ICollectable): ICollection; overload;
+        function RemoveAll(const ItemArray: array of ICollectable): ICollection; overload;
+        function RemoveAll(const Collection: ICollection): ICollection; overload;
+        function Retain(const ItemArray: array of ICollectable): ICollection; overload;
+        function Retain(const Collection: ICollection): ICollection; overload;
+        property AsArray: TCollectableArray read GetAsArray;
+        property Capacity: Integer read GetCapacity write SetCapacity;
+        property Comparator: IComparator read GetComparator write SetComparator;
+        property FixedSize: Boolean read GetFixedSize;
+        property IgnoreErrors: TCollectionErrors read GetIgnoreErrors write SetIgnoreErrors;
+        property NaturalItemIID: TGUID read GetNaturalItemIID;
+        property NaturalItemsOnly: Boolean read GetNaturalItemsOnly;
+        property Size: Integer read GetSize;
+    end;
+
+    IBag = interface(ICollection)
+        ['{C29C9560-2D59-11D7-8120-0002E3165EF8}']
+        function CloneAsBag: IBag;
+    end;
+
+    ISet = interface(ICollection)
+        ['{DD7888E2-0BB1-11D7-8120-0002E3165EF8}']
+        function CloneAsSet: ISet;
+        function Complement(const Universe: ISet): ISet;
+        function Intersect(const Set2: ISet): ISet;
+        function Union(const Set2: ISet): ISet;
+    end;
+
+    IList = interface(ICollection)
+        ['{EE81AB60-0B9F-11D7-8120-0002E3165EF8}']
+        function GetDuplicates: Boolean;
+        procedure SetDuplicates(Value: Boolean);
+        function GetItem(Index: Integer): ICollectable;
+        procedure SetItem(Index: Integer; const Item: ICollectable);
+        function GetSorted: Boolean;
+        procedure SetSorted(Value: Boolean);
+        function CloneAsList: IList;
+        function Delete(Index: Integer): ICollectable;
+        procedure Exchange(Index1, Index2: Integer);
+        function First: ICollectable;
+        function IndexOf(const Item: ICollectable): Integer;
+        function Insert(Index: Integer; const Item: ICollectable): Boolean; overload;
+        function Insert(Index: Integer; const ItemArray: array of ICollectable): Integer; overload;
+        function Insert(Index: Integer; const Collection: ICollection): Integer; overload;
+        function Last: ICollectable;
+        procedure Sort(const Comparator: IComparator); overload;
+        procedure Sort(CompareFunc: TCollectionCompareFunc); overload;
+        property Duplicates: Boolean read GetDuplicates write SetDuplicates;
+        property Items[Index: Integer]: ICollectable read GetItem write SetItem; default;
+        property Sorted: Boolean read GetSorted write SetSorted;
+    end;
+
+    IMap = interface(ICollection)
+        ['{AD458280-2A6B-11D7-8120-0002E3165EF8}']
+        function GetItem(const Key: ICollectable): ICollectable;
+        procedure SetItem(const Key, Item: ICollectable);
+        function GetKeyComparator: IComparator;
+        procedure SetKeyComparator(const Value: IComparator);
+        function GetKeyIterator: IIterator;
+        function GetKeys: ISet;
+        function GetMapIterator: IMapIterator;
+        function GetMapIteratorByKey(const Filter: IFilter): IMapIterator; overload;
+        function GetMapIteratorByKey(FilterFunc: TCollectionFilterFunc): IMapIterator; overload;
+        function GetNaturalKeyIID: TGUID;
+        function GetNaturalKeysOnly: Boolean;
+        function GetValues: ICollection;
+        function CloneAsMap: IMap;
+        function ContainsKey(const Key: ICollectable): Boolean; overload;
+        function ContainsKey(const KeyArray: array of ICollectable): Boolean; overload;
+        function ContainsKey(const Collection: ICollection): Boolean; overload;
+        function Get(const Key: ICollectable): ICollectable;
+        function IsNaturalKey(const Key: ICollectable): Boolean;
+        function KeyAllowed(const Key: ICollectable): TCollectionError;
+        function MatchingKey(const KeyArray: array of ICollectable): ICollection; overload;
+        function MatchingKey(const Collection: ICollection): ICollection; overload;
+        function Put(const Item: ICollectable): ICollectable; overload;
+        function Put(const Key, Item: ICollectable): ICollectable; overload;
+        function Put(const ItemArray: array of ICollectable): ICollection; overload;
+        function Put(const Collection: ICollection): ICollection; overload;
+        function Put(const Map: IMap): ICollection; overload;
+        function RemoveKey(const Key: ICollectable): ICollectable; overload;
+        function RemoveKey(const KeyArray: array of ICollectable): ICollection; overload;
+        function RemoveKey(const Collection: ICollection): ICollection; overload;
+        function RetainKey(const KeyArray: array of ICollectable): ICollection; overload;
+        function RetainKey(const Collection: ICollection): ICollection; overload;
+        property KeyComparator: IComparator read GetKeyComparator write SetKeyComparator;
+        property Items[const Key: ICollectable]: ICollectable read GetItem write SetItem; default;
+        property NaturalKeyIID: TGUID read GetNaturalKeyIID;
+        property NaturalKeysOnly: Boolean read GetNaturalKeysOnly;
+    end;
+
+    IIntegerMap = interface(ICollection)
+        ['{93DBA9A0-606C-11D7-8120-0002E3165EF8}']
+        function GetItem(const Key: Integer): ICollectable;
+        procedure SetItem(const Key: Integer; const Item: ICollectable);
+        function GetKeys: ISet;
+        function GetMapIterator: IIntegerMapIterator;
+        function GetValues: ICollection;
+        function CloneAsIntegerMap: IIntegerMap;
+        function ContainsKey(const Key: Integer): Boolean; overload;
+        function ContainsKey(const KeyArray: array of Integer): Boolean; overload;
+        function Get(const Key: Integer): ICollectable;
+        function Put(const Item: ICollectable): ICollectable; overload;
+        function Put(const Key: Integer; const Item: ICollectable): ICollectable; overload;
+        function Put(const ItemArray: array of ICollectable): ICollection; overload;
+        function Put(const Collection: ICollection): ICollection; overload;
+        function Put(const Map: IIntegerMap): ICollection; overload;
+        function RemoveKey(const Key: Integer): ICollectable; overload;
+        function RemoveKey(const KeyArray: array of Integer): ICollection; overload;
+        function RetainKey(const KeyArray: array of Integer): ICollection; overload;
+        property Items[const Key: Integer]: ICollectable read GetItem write SetItem; default;
+    end;
+
+    IStringMap = interface(ICollection)
+        ['{20531A20-5F92-11D7-8120-0002E3165EF8}']
+        function GetItem(const Key: String): ICollectable;
+        procedure SetItem(const Key: String; const Item: ICollectable);
+        function GetKeys: ISet;
+        function GetMapIterator: IStringMapIterator;
+        function GetValues: ICollection;
+        function CloneAsStringMap: IStringMap;
+        function ContainsKey(const Key: String): Boolean; overload;
+        function ContainsKey(const KeyArray: array of String): Boolean; overload;
+        function Get(const Key: String): ICollectable;
+        function Put(const Item: ICollectable): ICollectable; overload;
+        function Put(const Key: String; const Item: ICollectable): ICollectable; overload;
+        function Put(const ItemArray: array of ICollectable): ICollection; overload;
+        function Put(const Collection: ICollection): ICollection; overload;
+        function Put(const Map: IStringMap): ICollection; overload;
+        function RemoveKey(const Key: String): ICollectable; overload;
+        function RemoveKey(const KeyArray: array of String): ICollection; overload;
+        function RetainKey(const KeyArray: array of String): ICollection; overload;
+        property Items[const Key: String]: ICollectable read GetItem write SetItem; default;
+    end;
+
+    TCollectionPosition = class
+    private
+        FFound: Boolean;
+    public
+        constructor Create(Found: Boolean);
+        property Found: Boolean read FFound;
+    end;
+
+    TAbstractComparator = class(TInterfacedObject, IComparator)
+    public
+        class function GetDefaultComparator: IComparator;
+        class function GetNaturalComparator: IComparator;
+        class function GetReverseNaturalComparator: IComparator;
+        function GetInstance: TObject;
+        function Compare(const Item1, Item2: ICollectable): Integer; virtual; abstract;
+        function Equals(const Item1, Item2: ICollectable): Boolean; overload; virtual; abstract;
+        function Equals(const Comparator: IComparator): Boolean; overload; virtual;
+    end;
+
+    TDefaultComparator = class(TAbstractComparator)
+    protected
+        constructor Create;
+    public
+        function Compare(const Item1, Item2: ICollectable): Integer; override;
+        function Equals(const Item1, Item2: ICollectable): Boolean; override;
+    end;
+
+    TNaturalComparator = class(TAbstractComparator)
+    protected
+        constructor Create;
+    public
+        function Compare(const Item1, Item2: ICollectable): Integer; override;
+        function Equals(const Item1, Item2: ICollectable): Boolean; override;
+    end;
+
+    TReverseNaturalComparator = class(TAbstractComparator)
+    protected
+        constructor Create;
+    public
+        function Compare(const Item1, Item2: ICollectable): Integer; override;
+        function Equals(const Item1, Item2: ICollectable): Boolean; override;
+    end;
+
+    TAssociation = class(TInterfacedObject, ICollectable, IAssociation)
+    private
+        FKey: ICollectable;
+        FValue: ICollectable;
+    public
+        constructor Create(const Key, Value: ICollectable); virtual;
+        destructor Destroy; override;
+        function GetInstance: TObject; virtual;
+        function GetKey: ICollectable;
+        function GetValue: ICollectable;
+    end;
+
+    TIntegerAssociation = class(TInterfacedObject, ICollectable, IIntegerAssociation)
+    private
+        FKey: Integer;
+        FValue: ICollectable;
+    public
+        constructor Create(const Key: Integer; const Value: ICollectable); virtual;
+        destructor Destroy; override;
+        function GetInstance: TObject; virtual;
+        function GetKey: Integer;
+        function GetValue: ICollectable;
+    end;
+
+    TStringAssociation = class(TInterfacedObject, ICollectable, IStringAssociation)
+    private
+        FKey: String;
+        FValue: ICollectable;
+    public
+        constructor Create(const Key: String; const Value: ICollectable); virtual;
+        destructor Destroy; override;
+        function GetInstance: TObject; virtual;
+        function GetKey: String;
+        function GetValue: ICollectable;
+    end;
+
+    TAssociationComparator = class(TAbstractComparator, IAssociationComparator)
+    private
+        FKeyComparator: IComparator;
+    public
+        constructor Create(NaturalKeys: Boolean = false);
+        destructor Destroy; override;
+        function GetKeyComparator: IComparator;
+        procedure SetKeyComparator(Value: IComparator);
+        function Compare(const Item1, Item2: ICollectable): Integer; override;
+        function Equals(const Item1, Item2: ICollectable): Boolean; override;
+        property KeyComparator: IComparator read GetKeyComparator write SetKeyComparator;
+    end;
+
+    TIntegerAssociationComparator = class(TAbstractComparator, IIntegerAssociationComparator)
+    public
+        constructor Create;
+        destructor Destroy; override;
+        function Compare(const Item1, Item2: ICollectable): Integer; override;
+        function Equals(const Item1, Item2: ICollectable): Boolean; override;
+    end;
+
+    TStringAssociationComparator = class(TAbstractComparator, IStringAssociationComparator)
+    public
+        constructor Create;
+        destructor Destroy; override;
+        function Compare(const Item1, Item2: ICollectable): Integer; override;
+        function Equals(const Item1, Item2: ICollectable): Boolean; override;
+    end;
+
+
+
+    TAbstractCollection = class(TInterfacedObject, ICollection)
+    private
+        FCreated: Boolean;          // Required to avoid passing destroyed object reference to exception
+        FComparator: IComparator;
+        FIgnoreErrors: TCollectionErrors;
+        FNaturalItemsOnly: Boolean;
+    protected
+        procedure CollectionError(ErrorType: TCollectionError);
+        procedure InitFrom(const Collection: ICollection); overload; virtual;
+        function TrueAdd(const Item: ICollectable): Boolean; virtual; abstract;
+        procedure TrueClear; virtual; abstract;
+        function TrueContains(const Item: ICollectable): Boolean; virtual; abstract;
+        function TrueItemCount(const Item: ICollectable): Integer; virtual;
+        function TrueRemove(const Item: ICollectable): ICollectable; virtual; abstract;
+        function TrueRemoveAll(const Item: ICollectable): ICollection; virtual; abstract;
+    public
+        constructor Create; overload; virtual;
+        constructor Create(NaturalItemsOnly: Boolean); overload; virtual;
+        constructor Create(const ItemArray: array of ICollectable); overload; virtual;
+        constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; virtual;
+        constructor Create(const Collection: ICollection); overload; virtual;
+        destructor Destroy; override;
+        class function GetAlwaysNaturalItems: Boolean; virtual;
+        function GetAsArray: TCollectableArray; virtual;
+        function GetCapacity: Integer; virtual; abstract;
+        procedure SetCapacity(Value: Integer); virtual; abstract;
+        function GetComparator: IComparator; virtual;
+        procedure SetComparator(const Value: IComparator); virtual;
+        function GetDuplicates: Boolean; virtual;
+        function GetFixedSize: Boolean; virtual;
+        function GetIgnoreErrors: TCollectionErrors;
+        procedure SetIgnoreErrors(Value: TCollectionErrors);
+        function GetInstance: TObject;
+        function GetIterator: IIterator; overload; virtual; abstract;
+        function GetIterator(const Filter: IFilter): IIterator; overload; virtual;
+        function GetIterator(FilterFunc: TCollectionFilterFunc): IIterator; overload; virtual;
+        function GetNaturalItemIID: TGUID; virtual; abstract;
+        function GetNaturalItemsOnly: Boolean; virtual;
+        function GetSize: Integer; virtual; abstract;
+        function GetType: TCollectionType; virtual; abstract;
+        function Add(const Item: ICollectable): Boolean; overload; virtual;
+        function Add(const ItemArray: array of ICollectable): Integer; overload; virtual;
+        function Add(const Collection: ICollection): Integer; overload; virtual;
+        procedure AfterConstruction; override;
+        procedure BeforeDestruction; override;
+        function Clear: Integer; virtual;
+        function Clone: ICollection; virtual;
+        function Contains(const Item: ICollectable): Boolean; overload; virtual;
+        function Contains(const ItemArray: array of ICollectable): Boolean; overload; virtual;
+        function Contains(const Collection: ICollection): Boolean; overload; virtual;
+        function Equals(const Collection: ICollection): Boolean; virtual;
+        function Find(const Filter: IFilter): ICollectable; overload; virtual;
+        function Find(FilterFunc: TCollectionFilterFunc): ICollectable; overload; virtual;
+        function FindAll(const Filter: IFilter): ICollection; overload; virtual;
+        function FindAll(FilterFunc: TCollectionFilterFunc): ICollection; overload; virtual;
+        function IsEmpty: Boolean; virtual;
+        function IsNaturalItem(const Item: ICollectable): Boolean; virtual;
+        function IsNilAllowed: Boolean; virtual; abstract;
+        function ItemAllowed(const Item: ICollectable): TCollectionError; virtual;
+        function ItemCount(const Item: ICollectable): Integer; overload; virtual;
+        function ItemCount(const ItemArray: array of ICollectable): Integer; overload; virtual;
+        function ItemCount(const Collection: ICollection): Integer; overload; virtual;
+        function Matching(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+        function Matching(const Collection: ICollection): ICollection; overload; virtual;
+        function Remove(const Item: ICollectable): ICollectable; overload; virtual;
+        function Remove(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+        function Remove(const Collection: ICollection): ICollection; overload; virtual;
+        function RemoveAll(const Item: ICollectable): ICollection; overload; virtual;
+        function RemoveAll(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+        function RemoveAll(const Collection: ICollection): ICollection; overload; virtual;
+        function Retain(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+        function Retain(const Collection: ICollection): ICollection; overload; virtual;
+        property AsArray: TCollectableArray read GetAsArray;
+        property Capacity: Integer read GetCapacity write SetCapacity;
+        property Comparator: IComparator read GetComparator write SetComparator;
+        property FixedSize: Boolean read GetFixedSize;
+        property IgnoreErrors: TCollectionErrors read GetIgnoreErrors write SetIgnoreErrors;
+        property NaturalItemIID: TGUID read GetNaturalItemIID;
+        property NaturalItemsOnly: Boolean read GetNaturalItemsOnly;
+        property Size: Integer read GetSize;
+    end;
+
+    TAbstractBag = class(TAbstractCollection, IBag)
+    public
+        function CloneAsBag: IBag; virtual;
+        function GetNaturalItemIID: TGUID; override;
+        function GetType: TCollectionType; override;
+        function IsNilAllowed: Boolean; override;
+    end;
+
+    TAbstractSet = class (TAbstractCollection, ISet)
+    protected
+        function GetPosition(const Item: ICollectable): TCollectionPosition; virtual; abstract;
+        function TrueAdd(const Item: ICollectable): Boolean; override;
+        procedure TrueAdd2(Position: TCollectionPosition; const Item: ICollectable); virtual; abstract;
+        function TrueContains(const Item: ICollectable): Boolean; override;
+        function TrueGet(Position: TCollectionPosition): ICollectable; virtual; abstract;
+        function TrueRemove(const Item: ICollectable): ICollectable; override;
+        procedure TrueRemove2(Position: TCollectionPosition); virtual; abstract;
+        function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+    public
+        function GetDuplicates: Boolean; override;
+        function GetNaturalItemIID: TGUID; override;
+        function GetType: TCollectionType; override;
+        function CloneAsSet: ISet; virtual;
+        function Complement(const Universe: ISet): ISet; overload; virtual;
+        function Intersect(const Set2: ISet): ISet; overload; virtual;
+        function IsNilAllowed: Boolean; override;
+        function Union(const Set2: ISet): ISet; overload; virtual;
+    end;
+
+    TAbstractList = class(TAbstractCollection, IList)
+    private
+        FDuplicates: Boolean;
+        FSorted: Boolean;
+    protected
+        function BinarySearch(const Item: ICollectable): TSearchResult; virtual;
+        procedure InitFrom(const Collection: ICollection); override;
+        procedure QuickSort(Lo, Hi: Integer; const Comparator: IComparator); overload; virtual;
+        procedure QuickSort(Lo, Hi: Integer; CompareFunc: TCollectionCompareFunc); overload; virtual;
+        function SequentialSearch(const Item: ICollectable; const SearchComparator: IComparator = nil): TSearchResult; virtual;
+        function TrueContains(const Item: ICollectable): Boolean; override;
+        function TrueGetItem(Index: Integer): ICollectable; virtual; abstract;
+        procedure TrueSetItem(Index: Integer; const Item: ICollectable); virtual; abstract;
+        function TrueAdd(const Item: ICollectable): Boolean; override;
+        procedure TrueAppend(const Item: ICollectable); virtual; abstract;
+        function TrueDelete(Index: Integer): ICollectable; virtual; abstract;
+        procedure TrueInsert(Index: Integer; const Item: ICollectable); virtual; abstract;
+        function TrueItemCount(const Item: ICollectable): Integer; override;
+        function TrueRemove(const Item: ICollectable): ICollectable; override;
+        function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+    public
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        function GetDuplicates: Boolean; override;
+        procedure SetDuplicates(Value: Boolean); virtual;
+        function GetItem(Index: Integer): ICollectable; virtual;
+        procedure SetItem(Index: Integer; const Item: ICollectable); virtual;
+        function GetIterator: IIterator; override;
+        function GetNaturalItemIID: TGUID; override;
+        function GetSorted: Boolean; virtual;
+        procedure SetSorted(Value: Boolean); virtual;
+        function GetType: TCollectionType; override;
+        function CloneAsList: IList; virtual;
+        function Delete(Index: Integer): ICollectable; virtual;
+        procedure Exchange(Index1, Index2: Integer); virtual;
+        function First: ICollectable; virtual;
+        function IndexOf(const Item: ICollectable): Integer; virtual;
+        function Insert(Index: Integer; const Item: ICollectable): Boolean; overload; virtual;
+        function Insert(Index: Integer; const ItemArray: array of ICollectable): Integer; overload; virtual;
+        function Insert(Index: Integer; const Collection: ICollection): Integer; overload; virtual;
+        function IsNilAllowed: Boolean; override;
+        function Last: ICollectable; virtual;
+        function Search(const Item: ICollectable; const SearchComparator: IComparator = nil): TSearchResult; virtual;
+        procedure Sort(const SortComparator: IComparator = nil); overload; virtual;
+        procedure Sort(CompareFunc: TCollectionCompareFunc); overload; virtual;
+        property Duplicates: Boolean read GetDuplicates write SetDuplicates;
+        property Items[Index: Integer]: ICollectable read GetItem write SetItem; default;
+        property Sorted: Boolean read GetSorted write SetSorted;
+    end;
+
+    TAbstractMap = class(TAbstractCollection, IMap)
+    private
+        FAssociationComparator: IAssociationComparator;
+        FKeyComparator: IComparator;
+        FNaturalKeysOnly: Boolean;
+    protected
+        function GetAssociationIterator: IMapIterator; virtual; abstract;
+        function GetKeyPosition(const Key: ICollectable): TCollectionPosition; virtual; abstract;
+        procedure InitFrom(const Collection: ICollection); override;
+        function TrueAdd(const Item: ICollectable): Boolean; override;
+        function TrueContains(const Item: ICollectable): Boolean; override;
+        function TrueGet(Position: TCollectionPosition): IAssociation; virtual; abstract;
+        function TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation; virtual; abstract;
+        function TrueRemove(const Item: ICollectable): ICollectable; override;
+        function TrueRemove2(Position: TCollectionPosition): IAssociation; virtual; abstract;
+        function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+        property AssociationComparator: IAssociationComparator read FAssociationComparator;
+    public
+        constructor Create; override;
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        constructor Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); overload; virtual;
+        constructor Create(const ItemArray: array of ICollectable); overload; override;
+        constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; override;
+        constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); overload; virtual;
+        constructor Create(const KeyArray, ItemArray: array of ICollectable); overload; virtual;
+        constructor Create(const KeyArray, ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; virtual;
+        constructor Create(const KeyArray, ItemArray: array of ICollectable; NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); overload; virtual;
+//      Don't use this parameter signature as it hits a compiler bug in D5.
+//        constructor Create(const KeyArray, ItemArray: TCollectableArray; NaturalItemsOnly: Boolean = false; NaturalKeysOnly: Boolean = true); overload; virtual;
+        constructor Create(const Map: IMap); overload; virtual;
+        destructor Destroy; override;
+        class function GetAlwaysNaturalKeys: Boolean; virtual;
+        function GetItem(const Key: ICollectable): ICollectable; virtual;
+        procedure SetItem(const Key, Item: ICollectable); virtual;
+        function GetIterator: IIterator; override;
+        function GetKeyComparator: IComparator; virtual;
+        procedure SetKeyComparator(const Value: IComparator); virtual;
+        function GetKeyIterator: IIterator; virtual;
+        function GetKeys: ISet; virtual;
+        function GetMapIterator: IMapIterator; virtual;
+        function GetMapIteratorByKey(const Filter: IFilter): IMapIterator; overload; virtual;
+        function GetMapIteratorByKey(FilterFunc: TCollectionFilterFunc): IMapIterator; overload; virtual;
+        function GetNaturalItemIID: TGUID; override;
+        function GetNaturalKeyIID: TGUID; virtual;
+        function GetNaturalKeysOnly: Boolean; virtual;
+        function GetType: TCollectionType; override;
+        function GetValues: ICollection; virtual;
+        function Clone: ICollection; override;
+        function CloneAsMap: IMap; virtual;
+        function ContainsKey(const Key: ICollectable): Boolean; overload; virtual;
+        function ContainsKey(const KeyArray: array of ICollectable): Boolean; overload; virtual;
+        function ContainsKey(const Collection: ICollection): Boolean; overload; virtual;
+        function Get(const Key: ICollectable): ICollectable; virtual;
+        function KeyAllowed(const Key: ICollectable): TCollectionError; virtual;
+        function IsNaturalKey(const Key: ICollectable): Boolean; virtual;
+        function IsNilAllowed: Boolean; override;
+        function MatchingKey(const KeyArray: array of ICollectable): ICollection; overload; virtual;
+        function MatchingKey(const Collection: ICollection): ICollection; overload; virtual;
+        function Put(const Item: ICollectable): ICollectable; overload; virtual;
+        function Put(const Key, Item: ICollectable): ICollectable; overload; virtual;
+        function Put(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+        function Put(const Collection: ICollection): ICollection; overload; virtual;
+        function Put(const Map: IMap): ICollection; overload; virtual;
+        function RemoveKey(const Key: ICollectable): ICollectable; overload; virtual;
+        function RemoveKey(const KeyArray: array of ICollectable): ICollection; overload; virtual;
+        function RemoveKey(const Collection: ICollection): ICollection; overload; virtual;
+        function RetainKey(const KeyArray: array of ICollectable): ICollection; overload; virtual;
+        function RetainKey(const Collection: ICollection): ICollection; overload; virtual;
+        property KeyComparator: IComparator read GetKeyComparator write SetKeyComparator;
+        property Items[const Key: ICollectable]: ICollectable read GetItem write SetItem; default;
+        property NaturalKeyIID: TGUID read GetNaturalKeyIID;
+        property NaturalKeysOnly: Boolean read GetNaturalKeysOnly;
+    end;
+
+    TAbstractIntegerMap = class(TAbstractCollection, IIntegerMap)
+    private
+        FAssociationComparator: IIntegerAssociationComparator;
+    protected
+        function GetAssociationIterator: IIntegerMapIterator; virtual; abstract;
+        function GetKeyPosition(const Key: Integer): TCollectionPosition; virtual; abstract;
+        function TrueAdd(const Item: ICollectable): Boolean; override;
+        function TrueContains(const Item: ICollectable): Boolean; override;
+        function TrueGet(Position: TCollectionPosition): IIntegerAssociation; virtual; abstract;
+        function TruePut(Position: TCollectionPosition; const Association: IIntegerAssociation): IIntegerAssociation; virtual; abstract;
+        function TrueRemove(const Item: ICollectable): ICollectable; override;
+        function TrueRemove2(Position: TCollectionPosition): IIntegerAssociation; virtual; abstract;
+        function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+        property AssociationComparator: IIntegerAssociationComparator read FAssociationComparator;
+    public
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        constructor Create(const ItemArray: array of ICollectable); overload; override;
+        constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; override;
+        constructor Create(const KeyArray: array of Integer; const ItemArray: array of ICollectable); overload; virtual;
+        constructor Create(const KeyArray: array of Integer; const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; virtual;
+        constructor Create(const Map: IIntegerMap); overload; virtual;
+        destructor Destroy; override;
+        function GetItem(const Key: Integer): ICollectable; virtual;
+        procedure SetItem(const Key: Integer; const Item: ICollectable); virtual;
+        function GetIterator: IIterator; override;
+        function GetKeys: ISet; virtual;
+        function GetMapIterator: IIntegerMapIterator; virtual;
+        function GetNaturalItemIID: TGUID; override;
+        function GetType: TCollectionType; override;
+        function GetValues: ICollection; virtual;
+        function Clone: ICollection; override;
+        function CloneAsIntegerMap: IIntegerMap; virtual;
+        function ContainsKey(const Key: Integer): Boolean; overload; virtual;
+        function ContainsKey(const KeyArray: array of Integer): Boolean; overload; virtual;
+        function Get(const Key: Integer): ICollectable; virtual;
+        function IsNilAllowed: Boolean; override;
+        function Put(const Item: ICollectable): ICollectable; overload; virtual;
+        function Put(const Key: Integer; const Item: ICollectable): ICollectable; overload; virtual;
+        function Put(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+        function Put(const Collection: ICollection): ICollection; overload; virtual;
+        function Put(const Map: IIntegerMap): ICollection; overload; virtual;
+        function RemoveKey(const Key: Integer): ICollectable; overload; virtual;
+        function RemoveKey(const KeyArray: array of Integer): ICollection; overload; virtual;
+        function RetainKey(const KeyArray: array of Integer): ICollection; overload; virtual;
+        property Items[const Key: Integer]: ICollectable read GetItem write SetItem; default;
+    end;
+
+    TAbstractStringMap = class(TAbstractCollection, IStringMap)
+    private
+        FAssociationComparator: IStringAssociationComparator;
+    protected
+        function GetAssociationIterator: IStringMapIterator; virtual; abstract;
+        function GetKeyPosition(const Key: String): TCollectionPosition; virtual; abstract;
+        function TrueAdd(const Item: ICollectable): Boolean; override;
+        function TrueContains(const Item: ICollectable): Boolean; override;
+        function TrueGet(Position: TCollectionPosition): IStringAssociation; virtual; abstract;
+        function TruePut(Position: TCollectionPosition; const Association: IStringAssociation): IStringAssociation; virtual; abstract;
+        function TrueRemove(const Item: ICollectable): ICollectable; override;
+        function TrueRemove2(Position: TCollectionPosition): IStringAssociation; virtual; abstract;
+        function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+        property AssociationComparator: IStringAssociationComparator read FAssociationComparator;
+    public
+        constructor Create(NaturalItemsOnly: Boolean); override;
+        constructor Create(const ItemArray: array of ICollectable); overload; override;
+        constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; override;
+        constructor Create(const KeyArray: array of String; const ItemArray: array of ICollectable); overload; virtual;
+        constructor Create(const KeyArray: array of String; const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; virtual;
+        constructor Create(const Map: IStringMap); overload; virtual;
+        destructor Destroy; override;
+        function GetItem(const Key: String): ICollectable; virtual;
+        procedure SetItem(const Key: String; const Item: ICollectable); virtual;
+        function GetIterator: IIterator; override;
+        function GetKeys: ISet; virtual;
+        function GetMapIterator: IStringMapIterator; virtual;
+        function GetNaturalItemIID: TGUID; override;
+        function GetType: TCollectionType; override;
+        function GetValues: ICollection; virtual;
+        function Clone: ICollection; override;
+        function CloneAsStringMap: IStringMap; virtual;
+        function ContainsKey(const Key: String): Boolean; overload; virtual;
+        function ContainsKey(const KeyArray: array of String): Boolean; overload; virtual;
+        function Get(const Key: String): ICollectable; virtual;
+        function IsNilAllowed: Boolean; override;
+        function Put(const Item: ICollectable): ICollectable; overload; virtual;
+        function Put(const Key: String; const Item: ICollectable): ICollectable; overload; virtual;
+        function Put(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+        function Put(const Collection: ICollection): ICollection; overload; virtual;
+        function Put(const Map: IStringMap): ICollection; overload; virtual;
+        function RemoveKey(const Key: String): ICollectable; overload; virtual;
+        function RemoveKey(const KeyArray: array of String): ICollection; overload; virtual;
+        function RetainKey(const KeyArray: array of String): ICollection; overload; virtual;
+        property Items[const Key: String]: ICollectable read GetItem write SetItem; default;
+    end;
+
+    TAbstractCollectionClass = class of TAbstractCollection;
+    TAbstractBagClass = class of TAbstractBag;
+    TAbstractSetClass = class of TAbstractSet;
+    TAbstractListClass = class of TAbstractList;
+    TAbstractMapClass = class of TAbstractMap;
+    TAbstractIntegerMapClass = class of TAbstractIntegerMap;
+    TAbstractStringMapClass = class of TAbstractStringMap;
+
+    TAbstractIterator = class(TInterfacedObject, IIterator)
+    private
+        FAllowRemoval: Boolean;
+        FEOF: Boolean;
+        FItem: ICollectable;
+    protected
+        constructor Create(AllowRemoval: Boolean = true);
+        function TrueFirst: ICollectable; virtual; abstract;
+        function TrueNext: ICollectable; virtual; abstract;
+        procedure TrueRemove; virtual; abstract;
+    public
+        procedure AfterConstruction; override;
+        function GetAllowRemoval: Boolean; virtual;
+        function CurrentItem: ICollectable; virtual;
+        function EOF: Boolean; virtual;
+        function First: ICollectable; virtual;
+        function Next: ICollectable; virtual;
+        function Remove: Boolean; virtual;
+        property AllowRemoval: Boolean read GetAllowRemoval;
+    end;
+
+    TAbstractListIterator = class(TAbstractIterator)
+    private
+        FCollection: TAbstractList;
+        FIndex: Integer;
+    protected
+        constructor Create(Collection: TAbstractList);
+        function TrueFirst: ICollectable; override;
+        function TrueNext: ICollectable; override;
+        procedure TrueRemove; override;
+    end;
+
+    TAbstractMapIterator = class(TAbstractIterator, IMapIterator)
+    public
+        function CurrentKey: ICollectable; virtual; abstract;
+    end;
+
+    TAbstractAssociationIterator = class(TInterfacedObject, IIterator, IMapIterator)
+    private
+        FAllowRemoval: Boolean;
+        FEOF: Boolean;
+        FAssociation: IAssociation;
+    protected
+        constructor Create(AllowRemoval: Boolean = true);
+        function TrueFirst: IAssociation; virtual; abstract;
+        function TrueNext: IAssociation; virtual; abstract;
+        procedure TrueRemove; virtual; abstract;
+    public
+        procedure AfterConstruction; override;
+        function GetAllowRemoval: Boolean; virtual;
+        function CurrentKey: ICollectable; virtual;
+        function CurrentItem: ICollectable; virtual;
+        function EOF: Boolean; virtual;
+        function First: ICollectable; virtual;
+        function Next: ICollectable; virtual;
+        function Remove: Boolean; virtual;
+        property AllowRemoval: Boolean read GetAllowRemoval;
+    end;
+
+    TAbstractIntegerAssociationIterator = class(TInterfacedObject, IIterator, IIntegerMapIterator)
+    private
+        FAllowRemoval: Boolean;
+        FEOF: Boolean;
+        FAssociation: IIntegerAssociation;
+    protected
+        constructor Create(AllowRemoval: Boolean = true);
+        function TrueFirst: IIntegerAssociation; virtual; abstract;
+        function TrueNext: IIntegerAssociation; virtual; abstract;
+        procedure TrueRemove; virtual; abstract;
+    public
+        procedure AfterConstruction; override;
+        function GetAllowRemoval: Boolean; virtual;
+        function CurrentKey: Integer; virtual;
+        function CurrentItem: ICollectable; virtual;
+        function EOF: Boolean; virtual;
+        function First: ICollectable; virtual;
+        function Next: ICollectable; virtual;
+        function Remove: Boolean; virtual;
+        property AllowRemoval: Boolean read GetAllowRemoval;
+    end;
+
+    TAbstractStringAssociationIterator = class(TInterfacedObject, IIterator, IStringMapIterator)
+    private
+        FAllowRemoval: Boolean;
+        FEOF: Boolean;
+        FAssociation: IStringAssociation;
+    protected
+        constructor Create(AllowRemoval: Boolean = true);
+        function TrueFirst: IStringAssociation; virtual; abstract;
+        function TrueNext: IStringAssociation; virtual; abstract;
+        procedure TrueRemove; virtual; abstract;
+    public
+        procedure AfterConstruction; override;
+        function GetAllowRemoval: Boolean; virtual;
+        function CurrentKey: String; virtual;
+        function CurrentItem: ICollectable; virtual;
+        function EOF: Boolean; virtual;
+        function First: ICollectable; virtual;
+        function Next: ICollectable; virtual;
+        function Remove: Boolean; virtual;
+        property AllowRemoval: Boolean read GetAllowRemoval;
+    end;
+
+    TAssociationIterator = class(TAbstractIterator, IMapIterator)
+    private
+        FIterator: IIterator;
+    protected
+        function TrueFirst: ICollectable; override;
+        function TrueNext: ICollectable; override;
+        procedure TrueRemove; override;
+    public
+        constructor Create(const Iterator: IIterator);
+        destructor Destroy; override;
+        function CurrentItem: ICollectable; override;
+        function CurrentKey: ICollectable; virtual;
+    end;
+
+    TAssociationKeyIterator = class(TAbstractIterator)
+    private
+        FIterator: IMapIterator;
+    protected
+        function TrueFirst: ICollectable; override;
+        function TrueNext: ICollectable; override;
+        procedure TrueRemove; override;
+    public
+        constructor Create(const Iterator: IMapIterator);
+        destructor Destroy; override;
+    end;
+
+    TAbstractFilter = class(TInterfacedObject, IFilter)
+    public
+        function Accept(const Item: ICollectable): Boolean; virtual; abstract;
+    end;
+
+    TFilterIterator = class(TAbstractIterator)
+    private
+        FIterator: IIterator;
+        FFilter: IFilter;
+    protected
+        function TrueFirst: ICollectable; override;
+        function TrueNext: ICollectable; override;
+        procedure TrueRemove; override;
+    public
+        constructor Create(const Iterator: IIterator; const Filter: IFilter; AllowRemoval: Boolean = true); virtual;
+        destructor Destroy; override;
+    end;
+
+    TFilterFuncIterator = class(TAbstractIterator)
+    private
+        FIterator: IIterator;
+        FFilterFunc: TCollectionFilterFunc;
+    protected
+        function TrueFirst: ICollectable; override;
+        function TrueNext: ICollectable; override;
+        procedure TrueRemove; override;
+    public
+        constructor Create(const Iterator: IIterator; FilterFunc: TCollectionFilterFunc; AllowRemoval: Boolean = true); virtual;
+        destructor Destroy; override;
+    end;
+
+    TKeyFilterMapIterator = class(TAbstractMapIterator)
+    private
+        FIterator: IMapIterator;
+        FFilter: IFilter;
+    protected
+        function TrueFirst: ICollectable; override;
+        function TrueNext: ICollectable; override;
+        procedure TrueRemove; override;
+    public
+        constructor Create(const Iterator: IMapIterator; const Filter: IFilter; AllowRemoval: Boolean = true); virtual;
+        destructor Destroy; override;
+        function CurrentKey: ICollectable; override;
+    end;
+
+    TKeyFilterFuncMapIterator = class(TAbstractMapIterator)
+    private
+        FIterator: IMapIterator;
+        FFilterFunc: TCollectionFilterFunc;
+    protected
+        function TrueFirst: ICollectable; override;
+        function TrueNext: ICollectable; override;
+        procedure TrueRemove; override;
+    public
+        constructor Create(const Iterator: IMapIterator; FilterFunc: TCollectionFilterFunc; AllowRemoval: Boolean = true); virtual;
+        destructor Destroy; override;
+        function CurrentKey: ICollectable; override;
+    end;
+
+
+    ECollectionError = class(Exception)
+    private
+        FCollection: ICollection;
+        FErrorType: TCollectionError;
+    public
+        constructor Create(const Msg: String; const Collection: ICollection; ErrorType: TCollectionError);
+        property Collection: ICollection read FCollection;
+        property ErrorType: TCollectionError read FErrorType;
+    end;
+
+implementation
+
+uses
+    Math,
+    CollArray, CollHash, CollList, CollPArray, CollWrappers;
+
+var
+    FDefaultComparator: IComparator;
+    FNaturalComparator: IComparator;
+    FReverseNaturalComparator: IComparator;
+
+{ TCollectionPosition }
+constructor TCollectionPosition.Create(Found: Boolean);
+begin
+    FFound := Found;
+end;
+
+{ TAbstractComparator }
+class function TAbstractComparator.GetDefaultComparator: IComparator;
+begin
+    if FDefaultComparator = nil then
+        FDefaultComparator := TDefaultComparator.Create;
+    Result := FDefaultComparator;
+end;
+
+class function TAbstractComparator.GetNaturalComparator: IComparator;
+begin
+    if FNaturalComparator = nil then
+        FNaturalComparator := TNaturalComparator.Create;
+    Result := FNaturalComparator;
+end;
+
+class function TAbstractComparator.GetReverseNaturalComparator: IComparator;
+begin
+    if FReverseNaturalComparator = nil then
+        FReverseNaturalComparator := TReverseNaturalComparator.Create;
+    Result := FReverseNaturalComparator;
+end;
+
+function TAbstractComparator.GetInstance: TObject;
+begin
+    Result := Self;
+end;
+
+function TAbstractComparator.Equals(const Comparator: IComparator): Boolean;
+begin
+    Result := (Self = Comparator.GetInstance); 
+end;
+
+{ TDefaultComparator }
+constructor TDefaultComparator.Create;
+begin
+    // Empty
+end;
+
+function TDefaultComparator.Compare(const Item1, Item2: ICollectable): Integer;
+var
+    Value1, Value2: Integer;
+begin
+    if Item1 <> nil then
+        Value1 := Integer(Pointer(Item1))
+    else
+        Value1 := Low(Integer);
+    if Item2 <> nil then
+        Value2 := Integer(Pointer(Item2))
+    else
+        Value2 := Low(Integer);
+    if (Value1 < Value2) then
+        Result := -1
+    else if (Value1 > Value2) then
+        Result := 1
+    else
+        Result := 0;
+end;
+
+function TDefaultComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+    Result := (Item1 = Item2);
+end;
+
+{ TNaturalComparator }
+constructor TNaturalComparator.Create;
+begin
+    // Empty
+end;
+
+function TNaturalComparator.Compare(const Item1, Item2: ICollectable): Integer;
+begin
+    if (Item1 = nil) and (Item2 <> nil) then
+        Result := -1
+    else if (Item1 <> nil) and (Item2 = nil) then
+        Result := 1
+    else if (Item1 = nil) and (Item2 = nil) then
+        Result := 0
+    else
+        Result := (Item1 as IComparable).CompareTo(Item2);
+end;
+
+function TNaturalComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+    if (Item1 = nil) or (Item2 = nil) then
+        Result := (Item1 = Item2)
+    else
+    begin
+        Result := (Item1 as IEquatable).Equals(Item2);
+    end;
+end;
+
+{ TReverseNaturalComparator }
+constructor TReverseNaturalComparator.Create;
+begin
+    // Empty
+end;
+
+function TReverseNaturalComparator.Compare(const Item1, Item2: ICollectable): Integer;
+begin
+    if (Item1 = nil) and (Item2 <> nil) then
+        Result := 1
+    else if (Item1 <> nil) and (Item2 = nil) then
+        Result := -1
+    else if (Item1 = nil) and (Item2 = nil) then
+        Result := 0
+    else
+        Result := -(Item1 as IComparable).CompareTo(Item2);
+end;
+
+function TReverseNaturalComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+    if (Item1 = nil) or (Item2 = nil) then
+        Result := (Item1 = Item2)
+    else
+        Result := (Item1 as IEquatable).Equals(Item2);
+end;
+
+{ TAssociation }
+constructor TAssociation.Create(const Key, Value: ICollectable);
+begin
+    FKey := Key;
+    FValue := Value;
+end;
+
+destructor TAssociation.Destroy;
+begin
+    FKey := nil;
+    FValue := nil;
+    inherited Destroy;
+end;
+
+function TAssociation.GetInstance: TObject;
+begin
+    Result := Self;
+end;
+
+function TAssociation.GetKey: ICollectable;
+begin
+    Result := FKey;
+end;
+
+function TAssociation.GetValue: ICollectable;
+begin
+    Result := FValue;
+end;
+
+
+{ TIntegerAssociation }
+constructor TIntegerAssociation.Create(const Key: Integer; const Value: ICollectable);
+begin
+    FKey := Key;
+    FValue := Value;
+end;
+
+destructor TIntegerAssociation.Destroy;
+begin
+    FValue := nil;
+    inherited Destroy;
+end;
+
+function TIntegerAssociation.GetInstance: TObject;
+begin
+    Result := Self;
+end;
+
+function TIntegerAssociation.GetKey: Integer;
+begin
+    Result := FKey;
+end;
+
+function TIntegerAssociation.GetValue: ICollectable;
+begin
+    Result := FValue;
+end;
+
+
+{ TStringAssociation }
+constructor TStringAssociation.Create(const Key: String; const Value: ICollectable);
+begin
+    FKey := Key;
+    FValue := Value;
+end;
+
+destructor TStringAssociation.Destroy;
+begin
+    FValue := nil;
+    inherited Destroy;
+end;
+
+function TStringAssociation.GetInstance: TObject;
+begin
+    Result := Self;
+end;
+
+function TStringAssociation.GetKey: String;
+begin
+    Result := FKey;
+end;
+
+function TStringAssociation.GetValue: ICollectable;
+begin
+    Result := FValue;
+end;
+
+
+{ TAbstractIterator }
+constructor TAbstractIterator.Create(AllowRemoval: Boolean);
+begin
+    inherited Create;
+    FAllowRemoval := AllowRemoval;
+    FEOF := true;
+    FItem := nil;
+end;
+
+procedure TAbstractIterator.AfterConstruction;
+begin
+    inherited AfterConstruction;
+    First;
+end;
+
+function TAbstractIterator.GetAllowRemoval: Boolean;
+begin
+    Result := FAllowRemoval;
+end;
+
+function TAbstractIterator.CurrentItem: ICollectable;
+begin
+    Result := FItem;
+end;
+
+function TAbstractIterator.EOF: Boolean;
+begin
+    Result := FEOF;
+end;
+
+function TAbstractIterator.First: ICollectable;
+begin
+    FEOF := false;
+    FItem := TrueFirst;
+    if FItem = nil then
+        FEOF := true;
+    Result := FItem;
+end;
+
+function TAbstractIterator.Next: ICollectable;
+begin
+    if not FEOF then
+    begin
+        FItem := TrueNext;
+        if FItem = nil then
+            FEOF := true;
+    end;
+    Result := FItem;
+end;
+
+function TAbstractIterator.Remove: Boolean;
+begin
+    if (FItem <> nil) and FAllowRemoval then
+    begin
+        TrueRemove;
+        FItem := nil;
+        Result := true;
+    end
+    else
+        Result := false;
+end;
+
+{ TAbstractAssociationIterator }
+constructor TAbstractAssociationIterator.Create(AllowRemoval: Boolean);
+begin
+    inherited Create;
+    FAllowRemoval := AllowRemoval;
+    FEOF := true;
+    FAssociation := nil;
+end;
+
+procedure TAbstractAssociationIterator.AfterConstruction;
+begin
+    inherited AfterConstruction;
+    First;
+end;
+
+function TAbstractAssociationIterator.GetAllowRemoval: Boolean;
+begin
+    Result := FAllowRemoval;
+end;
+
+function TAbstractAssociationIterator.CurrentKey: ICollectable;
+begin
+    if FAssociation <> nil then
+        Result := FAssociation.GetKey
+    else
+        Result := nil;
+end;
+
+function TAbstractAssociationIterator.CurrentItem: ICollectable;
+begin
+    if FAssociation <> nil then
+        Result := FAssociation.GetValue
+    else
+        Result := nil;
+end;
+
+function TAbstractAssociationIterator.EOF: Boolean;
+begin
+    Result := FEOF;
+end;
+
+function TAbstractAssociationIterator.First: ICollectable;
+begin
+    FAssociation := TrueFirst;
+    if FAssociation <> nil then
+    begin
+        Result := FAssociation.GetValue;
+        FEOF := false;
+    end
+    else
+    begin
+        Result := nil;
+        FEOF := true;
+    end;
+end;
+
+function TAbstractAssociationIterator.Next: ICollectable;
+begin
+    if not FEOF then
+    begin
+        FAssociation := TrueNext;
+        if FAssociation <> nil then
+            Result := FAssociation.GetValue
+        else
+        begin
+            Result := nil;
+            FEOF := true;
+        end;
+    end;
+end;
+
+function TAbstractAssociationIterator.Remove: Boolean;
+begin
+    if (FAssociation <> nil) and FAllowRemoval then
+    begin
+        TrueRemove;
+        FAssociation := nil;
+        Result := true;
+    end
+    else
+        Result := false;
+end;
+
+{ TAbstractIntegerAssociationIterator }
+constructor TAbstractIntegerAssociationIterator.Create(AllowRemoval: Boolean);
+begin
+    inherited Create;
+    FAllowRemoval := AllowRemoval;
+    FEOF := true;
+    FAssociation := nil;
+end;
+
+procedure TAbstractIntegerAssociationIterator.AfterConstruction;
+begin
+    inherited AfterConstruction;
+    First;
+end;
+
+function TAbstractIntegerAssociationIterator.GetAllowRemoval: Boolean;
+begin
+    Result := FAllowRemoval;
+end;
+
+function TAbstractIntegerAssociationIterator.CurrentKey: Integer;
+begin
+    if FAssociation <> nil then
+        Result := FAssociation.GetKey
+    else
+        Result := 0;
+end;
+
+function TAbstractIntegerAssociationIterator.CurrentItem: ICollectable;
+begin
+    if FAssociation <> nil then
+        Result := FAssociation.GetValue
+    else
+        Result := nil;
+end;
+
+function TAbstractIntegerAssociationIterator.EOF: Boolean;
+begin
+    Result := FEOF;
+end;
+
+function TAbstractIntegerAssociationIterator.First: ICollectable;
+begin
+    FAssociation := TrueFirst;
+    if FAssociation <> nil then
+    begin
+        Result := FAssociation.GetValue;
+        FEOF := false;
+    end
+    else
+    begin
+        Result := nil;
+        FEOF := true;
+    end;
+end;
+
+function TAbstractIntegerAssociationIterator.Next: ICollectable;
+begin
+    if not FEOF then
+    begin
+        FAssociation := TrueNext;
+        if FAssociation <> nil then
+            Result := FAssociation.GetValue
+        else
+        begin
+            Result := nil;
+            FEOF := true;
+        end;
+    end;
+end;
+
+function TAbstractIntegerAssociationIterator.Remove: Boolean;
+begin
+    if (FAssociation <> nil) and FAllowRemoval then
+    begin
+        TrueRemove;
+        FAssociation := nil;
+        Result := true;
+    end
+    else
+        Result := false;
+end;
+
+{ TAbstractStringAssociationIterator }
+constructor TAbstractStringAssociationIterator.Create(AllowRemoval: Boolean);
+begin
+    inherited Create;
+    FAllowRemoval := AllowRemoval;
+    FEOF := true;
+    FAssociation := nil;
+end;
+
+procedure TAbstractStringAssociationIterator.AfterConstruction;
+begin
+    inherited AfterConstruction;
+    First;
+end;
+
+function TAbstractStringAssociationIterator.GetAllowRemoval: Boolean;
+begin
+    Result := FAllowRemoval;
+end;
+
+function TAbstractStringAssociationIterator.CurrentKey: String;
+begin
+    if FAssociation <> nil then
+        Result := FAssociation.GetKey
+    else
+        Result := '';
+end;
+
+function TAbstractStringAssociationIterator.CurrentItem: ICollectable;
+begin
+    if FAssociation <> nil then
+        Result := FAssociation.GetValue
+    else
+        Result := nil;
+end;
+
+function TAbstractStringAssociationIterator.EOF: Boolean;
+begin
+    Result := FEOF;
+end;
+
+function TAbstractStringAssociationIterator.First: ICollectable;
+begin
+    FAssociation := TrueFirst;
+    if FAssociation <> nil then
+    begin
+        Result := FAssociation.GetValue;
+        FEOF := false;
+    end
+    else
+    begin
+        Result := nil;
+        FEOF := true;
+    end;
+end;
+
+function TAbstractStringAssociationIterator.Next: ICollectable;
+begin
+    if not FEOF then
+    begin
+        FAssociation := TrueNext;
+        if FAssociation <> nil then
+            Result := FAssociation.GetValue
+        else
+        begin
+            Result := nil;
+            FEOF := true;
+        end;
+    end;
+end;
+
+function TAbstractStringAssociationIterator.Remove: Boolean;
+begin
+    if (FAssociation <> nil) and FAllowRemoval then
+    begin
+        TrueRemove;
+        FAssociation := nil;
+        Result := true;
+    end
+    else
+        Result := false;
+end;
+
+{ TAssociationIterator }
+constructor TAssociationIterator.Create(const Iterator: IIterator);
+begin
+    inherited Create(Iterator.GetAllowRemoval);
+    FIterator := Iterator;
+end;
+
+destructor TAssociationIterator.Destroy;
+begin
+    FIterator := nil;
+    inherited Destroy;
+end;
+
+function TAssociationIterator.TrueFirst: ICollectable;
+var
+    Association: IAssociation;
+begin
+    Association := FIterator.First as IAssociation;
+    if Association <> nil then
+        Result := Association.GetValue
+    else
+        Result := nil;
+end;
+
+function TAssociationIterator.TrueNext: ICollectable;
+var
+    Association: IAssociation;
+begin
+    Association := (FIterator.Next as IAssociation);
+    if Association <> nil then
+        Result := Association.GetValue
+    else
+        Result := nil;
+end;
+
+procedure TAssociationIterator.TrueRemove;
+begin
+    FIterator.Remove;
+end;
+
+function TAssociationIterator.CurrentItem: ICollectable;
+var
+    Association: IAssociation;
+begin
+    Association := FIterator.CurrentItem as IAssociation;
+    if Association <> nil then
+        Result := Association.GetValue
+    else
+        Result := nil;
+end;
+
+function TAssociationIterator.CurrentKey: ICollectable;
+var
+    Association: IAssociation;
+begin
+    Association := FIterator.CurrentItem  as IAssociation;
+    if Association <> nil then
+        Result := Association.GetKey
+    else
+        Result := nil;
+end;
+
+{ TAssociationComparator }
+constructor TAssociationComparator.Create(NaturalKeys: Boolean);
+begin
+    inherited Create;
+    if NaturalKeys then
+        FKeyComparator := TAbstractComparator.GetNaturalComparator
+    else
+        FKeyComparator := TAbstractComparator.GetDefaultComparator;
+end;
+
+destructor TAssociationComparator.Destroy;
+begin
+    FKeyComparator := nil;
+    inherited Destroy;
+end;
+
+function TAssociationComparator.GetKeyComparator: IComparator;
+begin
+    Result := FKeyComparator;
+end;
+
+procedure TAssociationComparator.SetKeyComparator(Value: IComparator);
+begin
+    FKeyComparator := Value;
+end;
+
+function TAssociationComparator.Compare(const Item1, Item2: ICollectable): Integer;
+begin
+    Result := KeyComparator.Compare((Item1 as IAssociation).GetKey, (Item2 as IAssociation).GetKey);
+end;
+
+function TAssociationComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+    Result := KeyComparator.Equals((Item1 as IAssociation).GetKey, (Item2 as IAssociation).GetKey);
+end;
+
+{ TIntegerAssociationComparator }
+constructor TIntegerAssociationComparator.Create;
+begin
+    inherited Create;
+end;
+
+destructor TIntegerAssociationComparator.Destroy;
+begin
+    inherited Destroy;
+end;
+
+function TIntegerAssociationComparator.Compare(const Item1, Item2: ICollectable): Integer;
+var
+    Key1, Key2: Integer;
+begin
+    Key1 := (Item1 as IIntegerAssociation).GetKey;
+    Key2 := (Item2 as IIntegerAssociation).GetKey;
+    if Key1 < Key2 then
+        Result := -1
+    else if Key1 > Key2 then
+        Result := 1
+    else
+        Result := 0;
+end;
+
+function TIntegerAssociationComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+    Result := ((Item1 as IIntegerAssociation).GetKey = (Item2 as IIntegerAssociation).GetKey);
+end;
+
+{ TStringAssociationComparator }
+constructor TStringAssociationComparator.Create;
+begin
+    inherited Create;
+end;
+
+destructor TStringAssociationComparator.Destroy;
+begin
+    inherited Destroy;
+end;
+
+function TStringAssociationComparator.Compare(const Item1, Item2: ICollectable): Integer;
+var
+    Key1, Key2: String;
+begin
+    Key1 := (Item1 as IStringAssociation).GetKey;
+    Key2 := (Item2 as IStringAssociation).GetKey;
+    if Key1 < Key2 then
+        Result := -1
+    else if Key1 > Key2 then
+        Result := 1
+    else
+        Result := 0;
+end;
+
+function TStringAssociationComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+    Result := ((Item1 as IStringAssociation).GetKey = (Item2 as IStringAssociation).GetKey);
+end;
+
+{ TAssociationKeyIterator }
+constructor TAssociationKeyIterator.Create(const Iterator: IMapIterator);
+begin
+    inherited Create(Iterator.GetAllowRemoval);
+    FIterator := Iterator;
+end;
+
+destructor TAssociationKeyIterator.Destroy;
+begin
+    FIterator := nil;
+    inherited Destroy;
+end;
+
+function TAssociationKeyIterator.TrueFirst: ICollectable;
+begin
+    FIterator.First;
+    Result := FIterator.CurrentKey;
+end;
+
+function TAssociationKeyIterator.TrueNext: ICollectable;
+begin
+    FIterator.Next;
+    Result := FIterator.CurrentKey;
+end;
+
+procedure TAssociationKeyIterator.TrueRemove;
+begin
+    FIterator.Remove;
+end;
+
+{ TFilterIterator }
+constructor TFilterIterator.Create(const Iterator: IIterator; const Filter: IFilter; AllowRemoval: Boolean = true);
+begin
+    FIterator := Iterator;
+    FFilter := Filter;
+end;
+
+destructor TFilterIterator.Destroy;
+begin
+    FIterator := nil;
+    FFilter := nil;
+end;
+
+function TFilterIterator.TrueFirst: ICollectable;
+var
+    Item: ICollectable;
+begin
+    Item := FIterator.First;
+    while not FIterator.EOF do
+    begin
+        if FFilter.Accept(Item) then
+            break
+        else
+            Item := FIterator.Next;
+    end;
+    Result := Item;
+end;
+
+function TFilterIterator.TrueNext: ICollectable;
+var
+    Item: ICollectable;
+begin
+    Item := FIterator.Next;
+    while not FIterator.EOF do
+    begin
+        if FFilter.Accept(Item) then
+            break
+        else
+            Item := FIterator.Next;
+    end;
+    Result := Item;
+end;
+
+procedure TFilterIterator.TrueRemove;
+begin
+    FIterator.Remove;
+end;
+
+{ TFilterFuncIterator }
+constructor TFilterFuncIterator.Create(const Iterator: IIterator; FilterFunc: TCollectionFilterFunc; AllowRemoval: Boolean = true);
+begin
+    FIterator := Iterator;
+    FFilterFunc := FilterFunc;
+end;
+
+destructor TFilterFuncIterator.Destroy;
+begin
+    FIterator := nil;
+    FFilterFunc := nil;
+end;
+
+function TFilterFuncIterator.TrueFirst: ICollectable;
+var
+    Item: ICollectable;
+begin
+    Item := FIterator.First;
+    while not FIterator.EOF do
+    begin
+        if FFilterFunc(Item) then
+            break
+        else
+            Item := FIterator.Next;
+    end;
+    Result := Item;
+end;
+
+function TFilterFuncIterator.TrueNext: ICollectable;
+var
+    Item: ICollectable;
+begin
+    Item := FIterator.Next;
+    while not FIterator.EOF do
+    begin
+        if FFilterFunc(Item) then
+            break
+        else
+            Item := FIterator.Next;
+    end;
+    Result := Item;
+end;
+
+procedure TFilterFuncIterator.TrueRemove;
+begin
+    FIterator.Remove;
+end;
+
+{ TKeyFilterMapIterator }
+constructor TKeyFilterMapIterator.Create(const Iterator: IMapIterator; const Filter: IFilter; AllowRemoval: Boolean = true);
+begin
+    FIterator := Iterator;
+    FFilter := Filter;
+end;
+
+destructor TKeyFilterMapIterator.Destroy;
+begin
+    FIterator := nil;
+    FFilter := nil;
+end;
+
+function TKeyFilterMapIterator.TrueFirst: ICollectable;
+var
+    Key, Item: ICollectable;
+begin
+    Item := FIterator.First;
+    while not FIterator.EOF do
+    begin
+        Key := FIterator.CurrentKey;
+        if FFilter.Accept(Key) then
+            break
+        else
+            Item := FIterator.Next;
+    end;
+    Result := Item;
+end;
+
+function TKeyFilterMapIterator.TrueNext: ICollectable;
+var
+    Key, Item: ICollectable;
+begin
+    Item := FIterator.Next;
+    while not FIterator.EOF do
+    begin
+        Key := FIterator.CurrentKey;
+        if FFilter.Accept(Key) then
+            break
+        else
+            Item := FIterator.Next;
+    end;
+    Result := Item;
+end;
+
+procedure TKeyFilterMapIterator.TrueRemove;
+begin
+    FIterator.Remove;
+end;
+
+function TKeyFilterMapIterator.CurrentKey: ICollectable;
+begin
+    Result := FIterator.CurrentKey;
+end;
+
+{ TKeyFilterFuncMapIterator }
+constructor TKeyFilterFuncMapIterator.Create(const Iterator: IMapIterator; FilterFunc: TCollectionFilterFunc; AllowRemoval: Boolean = true);
+begin
+    FIterator := Iterator;
+    FFilterFunc := FilterFunc;
+end;
+
+destructor TKeyFilterFuncMapIterator.Destroy;
+begin
+    FIterator := nil;
+    FFilterFunc := nil;
+end;
+
+function TKeyFilterFuncMapIterator.TrueFirst: ICollectable;
+var
+    Key, Item: ICollectable;
+begin
+    Item := FIterator.First;
+    while not FIterator.EOF do
+    begin
+        Key := FIterator.CurrentKey;
+        if FFilterFunc(Key) then
+            break
+        else
+            Item := FIterator.Next;
+    end;
+    Result := Item;
+end;
+
+function TKeyFilterFuncMapIterator.TrueNext: ICollectable;
+var
+    Key, Item: ICollectable;
+begin
+    Item := FIterator.Next;
+    while not FIterator.EOF do
+    begin
+        Key := FIterator.CurrentKey;
+        if FFilterFunc(Key) then
+            break
+        else
+            Item := FIterator.Next;
+    end;
+    Result := Item;
+end;
+
+procedure TKeyFilterFuncMapIterator.TrueRemove;
+begin
+    FIterator.Remove;
+end;
+
+function TKeyFilterFuncMapIterator.CurrentKey: ICollectable;
+begin
+    Result := FIterator.CurrentKey;
+end;
+
+
+{ TAbstractCollection }
+constructor TAbstractCollection.Create;
+begin
+    Create(false);
+end;
+
+constructor TAbstractCollection.Create(NaturalItemsOnly: Boolean);
+begin
+    FCreated := false;
+    inherited Create;
+    FNaturalItemsOnly := NaturalItemsOnly or GetAlwaysNaturalItems;
+    if FNaturalItemsOnly then
+        FComparator := TAbstractComparator.GetNaturalComparator
+    else
+        FComparator := TAbstractComparator.GetDefaultComparator;
+    FIgnoreErrors := [ceDuplicate];
+end;
+
+constructor TAbstractCollection.Create(const ItemArray: array of ICollectable);
+begin
+    Create(ItemArray, false);
+end;
+
+// Fixed size collections must override this.
+constructor TAbstractCollection.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+var
+    I: Integer;
+begin
+    Create(NaturalItemsOnly);
+    if not FixedSize then
+    begin
+        Capacity := Length(ItemArray);
+        for I := Low(ItemArray) to High(ItemArray) do
+        begin
+            Add(ItemArray[I]);
+        end;
+    end;
+end;
+
+// Fixed size collections must override this.
+constructor TAbstractCollection.Create(const Collection: ICollection);
+var
+    Iterator: IIterator;
+begin
+    Create(Collection.GetNaturalItemsOnly);
+    InitFrom(Collection);
+    if not FixedSize then
+    begin
+        Capacity := Collection.GetSize;
+        Iterator := Collection.GetIterator;
+        while not Iterator.EOF do
+        begin
+            Add(Iterator.CurrentItem);
+            Iterator.Next;
+        end;
+    end;
+end;
+
+destructor TAbstractCollection.Destroy;
+begin
+    FCreated := false;
+    FComparator := nil;
+    inherited Destroy;
+end;
+
+procedure TAbstractCollection.CollectionError(ErrorType: TCollectionError);
+var
+    Msg: String;
+begin
+    if not (ErrorType in FIgnoreErrors) then
+    begin
+        case ErrorType of
+        ceDuplicate: Msg := 'Collection does not allow duplicates.';
+        ceDuplicateKey: Msg := 'Collection does not allow duplicate keys.';
+        ceFixedSize: Msg := 'Collection has fixed size.';
+        ceNilNotAllowed: Msg := 'Collection does not allow nil.';
+        ceNotNaturalItem: Msg := 'Collection only accepts natural items.';
+        ceOutOfRange: Msg := 'Index out of collection range.';
+        end;
+        // If exception is thrown during construction, collection cannot be
+        // passed to it as destructor is automatically called and this leaves an
+        // interface reference to a destroyed object and crashes.
+        if FCreated then
+            raise ECollectionError.Create(Msg, Self, ErrorType)
+        else
+            raise ECollectionError.Create(Msg, nil, ErrorType);
+    end;
+end;
+
+procedure TAbstractCollection.InitFrom(const Collection: ICollection);
+begin
+    Comparator := Collection.GetComparator;
+    IgnoreErrors := Collection.GetIgnoreErrors;
+end;
+
+// Implementations should override this if possible
+function TAbstractCollection.TrueItemCount(const Item: ICollectable): Integer;
+var
+    Iterator: IIterator;
+    Total: Integer;
+begin
+    Total := 0;
+    Iterator := GetIterator;
+    while not Iterator.EOF do
+    begin
+        if FComparator.Equals(Item, Iterator.CurrentItem) then
+            Inc(Total);
+        Iterator.Next;
+    end;
+    Result := Total;
+end;
+
+class function TAbstractCollection.GetAlwaysNaturalItems: Boolean;
+begin
+    Result := false;
+end;
+
+function TAbstractCollection.GetAsArray: TCollectableArray;
+var
+    Iterator: IIterator;
+    Working: TCollectableArray;
+    I: Integer;
+begin
+    SetLength(Working, Size);
+    I := 0;
+    Iterator := GetIterator;
+    while not Iterator.EOF do
+    begin
+        Working[I] := Iterator.CurrentItem;
+        Inc(I);
+        Iterator.Next;
+    end;
+    Result := Working;
+end;
+
+function TAbstractCollection.GetComparator: IComparator;
+begin
+    Result := FComparator;
+end;
+
+function TAbstractCollection.GetDuplicates: Boolean;
+begin
+    Result := true; // Sets and lists override this.
+end;
+
+procedure TAbstractCollection.SetComparator(const Value: IComparator);
+begin
+    if Value = nil then
+    begin
+        if NaturalItemsOnly then
+            FComparator := TAbstractComparator.GetNaturalComparator
+        else
+            FComparator := TAbstractComparator.GetDefaultComparator;
+    end
+    else
+        FComparator := Value;
+end;
+
+function TAbstractCollection.GetFixedSize: Boolean;
+begin
+    Result := false;
+end;
+
+function TAbstractCollection.GetIgnoreErrors: TCollectionErrors;
+begin
+    Result := FIgnoreErrors;
+end;
+
+procedure TAbstractCollection.SetIgnoreErrors(Value: TCollectionErrors);
+begin
+    FIgnoreErrors := Value;
+end;
+
+function TAbstractCollection.GetInstance: TObject;
+begin
+    Result := Self;
+end;
+
+function TAbstractCollection.GetIterator(const Filter: IFilter): IIterator;
+var
+    Iterator: IIterator;
+begin
+    Iterator := GetIterator;
+    Result := TFilterIterator.Create(Iterator, Filter, Iterator.GetAllowRemoval);
+end;
+
+function TAbstractCollection.GetIterator(FilterFunc: TCollectionFilterFunc): IIterator;
+var
+    Iterator: IIterator;
+begin
+    Iterator := GetIterator;
+    Result := TFilterFuncIterator.Create(Iterator, FilterFunc, Iterator.GetAllowRemoval);
+end;
+
+function TAbstractCollection.GetNaturalItemsOnly: Boolean;
+begin
+    Result := FNaturalItemsOnly;
+end;
+
+function TAbstractCollection.Add(const Item: ICollectable): Boolean;
+var
+    ItemError: TCollectionError;
+    Success: Boolean;
+begin
+    ItemError := ItemAllowed(Item); // Can be natural items only error or nil not allowed error
+    if ItemError <> ceOK then
+    begin
+        CollectionError(ItemError);
+        Success := false;
+    end
+    else if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+        Success := false;
+    end
+    else
+    begin
+        Success := TrueAdd(Item);
+    end;
+    Result := Success;
+end;
+
+function TAbstractCollection.Add(const ItemArray: array of ICollectable): Integer;
+var
+    Item: ICollectable;
+    ItemError: TCollectionError;
+    I, Count: Integer;
+    Success: Boolean;
+begin
+    Count := 0;
+    if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+    end
+    else
+    begin
+        for I := Low(ItemArray) to High(ItemArray) do
+        begin
+            Item := ItemArray[I];
+            ItemError := ItemAllowed(Item);
+            if ItemError <> ceOK then
+            begin
+                CollectionError(ItemError);
+                Success := false;
+            end
+            else
+            begin
+                Success := TrueAdd(Item);
+            end;
+            if Success then
+                Inc(Count);
+        end;
+    end;
+    Result := Count;
+end;
+
+function TAbstractCollection.Add(const Collection: ICollection): Integer;
+var
+    Iterator: IIterator;
+    Item: ICollectable;
+    ItemError: TCollectionError;
+    Count: Integer;
+    Success: Boolean;
+begin
+    Count := 0;
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Item := Iterator.CurrentItem;
+        ItemError := ItemAllowed(Item);
+        if ItemError <> ceOK then
+        begin
+            CollectionError(ItemError);
+            Success := false;
+        end
+        else if FixedSize then
+        begin
+            CollectionError(ceFixedSize);
+            Success := false;
+        end
+        else
+        begin
+            Success := TrueAdd(Item);
+        end;
+        if Success then
+            Inc(Count);
+        Iterator.Next;
+    end;
+    Result := Count;
+end;
+
+procedure TAbstractCollection.AfterConstruction;
+begin
+    inherited AfterConstruction;
+    FCreated := true;
+end;
+
+procedure TAbstractCollection.BeforeDestruction;
+begin
+    if not FixedSize then
+        TrueClear;
+    inherited BeforeDestruction;
+end;
+
+function TAbstractCollection.Clear: Integer;
+begin
+    if not FixedSize then
+    begin
+        Result := Size;
+        TrueClear;
+    end
+    else
+    begin
+        CollectionError(ceFixedSize);
+        Result := 0;
+    end;
+end;
+
+function TAbstractCollection.Clone: ICollection;
+begin
+    Result := (TAbstractCollectionClass(ClassType)).Create(Self);
+end;
+
+function TAbstractCollection.Contains(const Item: ICollectable): Boolean;
+var
+    ItemError: TCollectionError;
+    Success: Boolean;
+begin
+    ItemError := ItemAllowed(Item);
+    if ItemError <> ceOK then
+    begin
+        CollectionError(ItemError);
+        Success := false;
+    end
+    else
+    begin
+        Success := TrueContains(Item);
+    end;
+    Result := Success;
+end;
+
+function TAbstractCollection.Contains(const ItemArray: array of ICollectable): Boolean;
+var
+    I: Integer;
+    Success: Boolean;
+begin
+    Success := true;
+    for I := Low(ItemArray) to High(ItemArray) do
+    begin
+        Success := Success and Contains(ItemArray[I]);
+        if not Success then
+            break;
+    end;
+    Result := Success;
+end;
+
+function TAbstractCollection.Contains(const Collection: ICollection): Boolean;
+var
+    Iterator: IIterator;
+    Success: Boolean;
+begin
+    Success := true;
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Success := Success and Contains(Iterator.CurrentItem);
+        if not Success then
+            break;
+        Iterator.Next;
+    end;
+    Result := Success;
+end;
+
+function TAbstractCollection.Equals(const Collection: ICollection): Boolean;
+var
+    Iterator: IIterator;
+    Success: Boolean;
+begin
+    if Collection.GetType <> GetType then
+        Result := false
+    else if Collection.Size <> Size then
+        Result := false
+    else if not Collection.Comparator.Equals(Comparator) then
+        Result := false
+    else if not Collection.GetDuplicates and not GetDuplicates then
+    begin
+        // Not equal if any item not found in parameter collection
+        Success := true;
+        Iterator := GetIterator;
+        while not Iterator.EOF and Success do
+        begin
+            Success := Collection.Contains(Iterator.CurrentItem);
+            Iterator.Next;
+        end;
+        Result := Success;
+    end
+    else
+    begin
+        // Not equal if any item count not equal to item count in parameter collection
+        Success := true;
+        Iterator := GetIterator;
+        while not Iterator.EOF and Success do
+        begin
+            Success := (ItemCount(Iterator.CurrentItem) = Collection.ItemCount(Iterator.CurrentItem));
+            Iterator.Next;
+        end;
+        Result := Success;
+    end;
+end;
+
+function TAbstractCollection.Find(const Filter: IFilter): ICollectable;
+begin
+    Result := GetIterator(Filter).First;
+end;
+
+function TAbstractCollection.Find(FilterFunc: TCollectionFilterFunc): ICollectable;
+begin
+    Result := GetIterator(FilterFunc).First;
+end;
+
+function TAbstractCollection.FindAll(const Filter: IFilter): ICollection;
+var
+    ResultCollection: ICollection;
+    Iterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Self.GetIterator(Filter);
+    while not Iterator.EOF do
+    begin
+        ResultCollection.Add(Iterator.CurrentItem);
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractCollection.FindAll(FilterFunc: TCollectionFilterFunc): ICollection;
+var
+    ResultCollection: ICollection;
+    Iterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Self.GetIterator(FilterFunc);
+    while not Iterator.EOF do
+    begin
+        ResultCollection.Add(Iterator.CurrentItem);
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractCollection.IsEmpty: Boolean;
+begin
+    Result := (Size = 0);
+end;
+
+function TAbstractCollection.IsNaturalItem(const Item: ICollectable): Boolean;
+var
+    Temp: IUnknown;
+begin
+    if Item <> nil then
+        Result := (Item.QueryInterface(NaturalItemIID, Temp) <> E_NOINTERFACE)
+    else
+        Result := false;
+end;
+
+function TAbstractCollection.ItemAllowed(const Item: ICollectable): TCollectionError;
+begin
+    if NaturalItemsOnly and not IsNaturalItem(Item) then
+        Result := ceNotNaturalItem
+    else if not IsNilAllowed and (Item = nil) then
+        Result := ceNilNotAllowed
+    else
+        Result := ceOK;
+end;
+
+function TAbstractCollection.ItemCount(const Item: ICollectable): Integer;
+var
+    ItemError: TCollectionError;
+begin
+    ItemError := ItemAllowed(Item);
+    if ItemError <> ceOK then
+    begin
+        CollectionError(ItemError);
+        Result := 0;
+    end
+    else if GetDuplicates then
+    begin
+        Result := TrueItemCount(Item);
+    end
+    else
+    begin
+        // Where duplicates are not allowed, TrueContains will be faster than TrueItemCount.
+        if TrueContains(Item) then
+            Result := 1
+        else
+            Result := 0;
+    end;
+end;
+
+function TAbstractCollection.ItemCount(const ItemArray: array of ICollectable): Integer;
+var
+    I: Integer;
+    Total: Integer;
+begin
+    Total := 0;
+    for I := Low(ItemArray) to High(ItemArray) do
+    begin
+        Total := Total + ItemCount(ItemArray[I]);
+    end;
+    Result := Total;
+end;
+
+function TAbstractCollection.ItemCount(const Collection: ICollection): Integer;
+var
+    Iterator: IIterator;
+    Total: Integer;
+begin
+    Total := 0;
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Total := Total + ItemCount(Iterator.CurrentItem);
+        Iterator.Next;
+    end;
+    Result := Total;
+end;
+
+function TAbstractCollection.Matching(const ItemArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(ItemArray) to High(ItemArray) do
+    begin
+        if Contains(ItemArray[I]) then
+            ResultCollection.Add(ItemArray[I]);
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractCollection.Matching(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    Iterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        if Contains(Iterator.CurrentItem) then
+            ResultCollection.Add(Iterator.CurrentItem);
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractCollection.Remove(const Item: ICollectable): ICollectable;
+var
+    ItemError: TCollectionError;
+begin
+    ItemError := ItemAllowed(Item);
+    if ItemError <> ceOK then
+    begin
+        CollectionError(ItemError);
+        Result := nil;
+    end
+    else if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+        Result := nil;
+    end
+    else
+    begin
+        Result := TrueRemove(Item);
+    end;
+end;
+
+function TAbstractCollection.Remove(const ItemArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(ItemArray) to High(ItemArray) do
+    begin
+        ResultCollection.Add(Remove(ItemArray[I]));
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractCollection.Remove(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    Iterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        ResultCollection.Add(Remove(Iterator.CurrentItem));
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractCollection.RemoveAll(const Item: ICollectable): ICollection;
+var
+    ItemError: TCollectionError;
+begin
+    ItemError := ItemAllowed(Item);
+    if ItemError <> ceOK then
+    begin
+        CollectionError(ItemError);
+        Result := nil;
+    end
+    else if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+        Result := nil;
+    end
+    else
+    begin
+        Result := TrueRemoveAll(Item);
+    end;
+end;
+
+function TAbstractCollection.RemoveAll(const ItemArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(ItemArray) to High(ItemArray) do
+    begin
+        ResultCollection.Add(RemoveAll(ItemArray[I]));
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractCollection.RemoveAll(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    Iterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        ResultCollection.Add(RemoveAll(Iterator.CurrentItem));
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractCollection.Retain(const ItemArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    Iterator: IIterator;
+    Item: ICollectable;
+    I: Integer;
+    Found, Success: Boolean;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := GetIterator;
+    while not Iterator.EOF do
+    begin
+        // Converting the array to a map would be faster but I don't want to
+        // couple base class code to a complex collection.
+        Found := false;
+        for I := Low(ItemArray) to High(ItemArray) do
+        begin
+            Item := Iterator.CurrentItem;
+            Found := Comparator.Equals(Item, ItemArray[I]);
+            if Found then
+                break;
+        end;
+        if not Found then
+        begin
+            Success := Iterator.Remove;
+            if Success then
+                ResultCollection.Add(Item);
+        end;
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractCollection.Retain(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    Iterator: IIterator;
+    Item: ICollectable;
+    Success: Boolean;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := GetIterator;
+    while not Iterator.EOF do
+    begin
+        Item := Iterator.CurrentItem;
+        if not Collection.Contains(Item) then
+        begin
+            Success := Iterator.Remove;
+            if Success then
+                ResultCollection.Add(Item);
+        end;
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+{ TAbstractBag }
+function TAbstractBag.CloneAsBag: IBag;
+begin
+    Result := (TAbstractBagClass(ClassType)).Create(Self);
+end;
+
+function TAbstractBag.GetNaturalItemIID: TGUID;
+begin
+    Result := EquatableIID;
+end;
+
+function TAbstractBag.GetType: TCollectionType;
+begin
+    Result := ctBag;
+end;
+
+function TAbstractBag.IsNilAllowed: Boolean;
+begin
+    Result := true;
+end;
+
+{ TAbstractSet }
+function TAbstractSet.TrueAdd(const Item: ICollectable): Boolean;
+var
+    Position: TCollectionPosition;
+begin
+    // Adds if not already present otherwise fails
+    Position := GetPosition(Item);
+    try
+        if Position.Found then
+        begin
+            CollectionError(ceDuplicate);
+            Result := false;
+        end
+        else
+        begin
+            TrueAdd2(Position, Item);
+            Result := true;
+        end;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractSet.TrueContains(const Item: ICollectable): Boolean;
+var
+    Position: TCollectionPosition;
+begin
+    Position := GetPosition(Item);
+    try
+        Result := Position.Found;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractSet.TrueRemove(const Item: ICollectable): ICollectable;
+var
+    Position: TCollectionPosition;
+begin
+    Position := GetPosition(Item);
+    try
+        if Position.Found then
+        begin
+            Result := TrueGet(Position);
+            TrueRemove2(Position);
+        end
+        else
+            Result := nil;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractSet.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    RemovedItem: ICollectable;
+begin
+    ResultCollection := TPArrayBag.Create;
+    RemovedItem := TrueRemove(Item);
+    if RemovedItem <> nil then
+        ResultCollection.Add(RemovedItem);
+    Result := ResultCollection;
+end;
+
+function TAbstractSet.GetDuplicates: Boolean;
+begin
+    Result := false;
+end;
+
+function TAbstractSet.GetNaturalItemIID: TGUID;
+begin
+    Result := EquatableIID;
+end;
+
+function TAbstractSet.GetType: TCollectionType;
+begin
+    Result := ctSet;
+end;
+
+function TAbstractSet.CloneAsSet: ISet;
+begin
+    Result := (TAbstractSetClass(ClassType)).Create(Self);
+end;
+
+function TAbstractSet.Complement(const Universe: ISet): ISet;
+var
+    ResultSet: ISet;
+    Iterator: IIterator;
+    Item: ICollectable;
+begin
+    // Return items in universe not found in self.
+    ResultSet := TAbstractSetClass(ClassType).Create(NaturalItemsOnly);
+    Iterator := Universe.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Item := Iterator.CurrentItem;
+        if not Contains(Item) then
+            ResultSet.Add(Item);
+        Iterator.Next;
+    end;
+    Result := ResultSet;
+end;
+
+function TAbstractSet.Intersect(const Set2: ISet): ISet;
+var
+    ResultSet: ISet;
+    Iterator: IIterator;
+    Item: ICollectable;
+begin
+    // Return items found in self and parameter.
+    ResultSet := TAbstractSetClass(ClassType).Create(NaturalItemsOnly);
+    Iterator := GetIterator;
+    while not Iterator.EOF do
+    begin
+        Item := Iterator.CurrentItem;
+        if Contains(Item) and Set2.Contains(Item) then
+            ResultSet.Add(Iterator.CurrentItem);
+        Iterator.Next;
+    end;
+    Result := ResultSet;
+end;
+
+function TAbstractSet.IsNilAllowed: Boolean;
+begin
+    Result := false;
+end;
+
+function TAbstractSet.Union(const Set2: ISet): ISet;
+var
+    ResultSet: ISet;
+    Iterator: IIterator;
+    Item: ICollectable;
+begin
+    // Return items found in self or parameter.
+    ResultSet := CloneAsSet;
+    Iterator := Set2.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Item := Iterator.CurrentItem;
+        if not Contains(Item) and Set2.Contains(Item) then
+            ResultSet.Add(Iterator.CurrentItem);
+        Iterator.Next;
+    end;
+    Result := ResultSet;
+end;
+
+{ TAbstractList }
+constructor TAbstractList.Create(NaturalItemsOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly);
+    FDuplicates := true;
+    FSorted := false;
+end;
+
+procedure TAbstractList.InitFrom(const Collection: ICollection);
+var
+    List: IList;
+begin
+    inherited InitFrom(Collection);
+    if Collection.QueryInterface(IList, List) = S_OK then
+    begin
+        FDuplicates := List.GetDuplicates;
+        FSorted := List.GetSorted;
+    end;
+end;
+
+function TAbstractList.TrueAdd(const Item: ICollectable): Boolean;
+var
+    SearchResult: TSearchResult;
+begin
+    Result := True;
+    if Sorted then
+    begin
+        // Insert in appropriate place to maintain sort order, unless duplicate
+        // not allowed.
+        SearchResult := BinarySearch(Item);
+        case SearchResult.ResultType of
+        srBeforeIndex: TrueInsert(SearchResult.Index, Item);
+        srFoundAtIndex: begin
+            if Duplicates then
+                TrueInsert(SearchResult.Index, Item)
+            else
+            begin
+                CollectionError(ceDuplicate);
+                Result := false;
+            end;
+        end;
+        srAfterEnd: TrueAppend(Item);
+        end;
+    end
+    else
+    begin
+        // Add to end, unless duplicate not allowed.
+        if not Duplicates and (SequentialSearch(Item, Comparator).ResultType = srFoundAtIndex) then
+        begin
+            CollectionError(ceDuplicate);
+            Result := false;
+        end
+        else
+            TrueAppend(Item);
+    end;
+end;
+
+function TAbstractList.TrueContains(const Item: ICollectable): Boolean;
+begin
+    if Sorted then
+        Result := BinarySearch(Item).ResultType = srFoundAtIndex
+    else
+        Result := SequentialSearch(Item, Comparator).ResultType = srFoundAtIndex
+end;
+
+function TAbstractList.TrueItemCount(const Item: ICollectable): Integer;
+var
+    SearchResult: TSearchResult;
+    Count: Integer;
+begin
+    if Sorted then
+    begin
+        // If sorted, use binary search.
+        Count := 0;
+        SearchResult := BinarySearch(Item);
+        if SearchResult.ResultType = srFoundAtIndex then
+        begin
+            repeat
+                Inc(Count);
+            until not Comparator.Equals(Item, Items[SearchResult.Index]);
+        end;
+        Result := Count;
+    end
+    else
+        // Resort to sequential search for unsorted
+        Result := inherited TrueItemCount(Item);
+end;
+
+function TAbstractList.TrueRemove(const Item: ICollectable): ICollectable;
+var
+    SearchResult: TSearchResult;
+begin
+    Result := nil;
+    if Sorted then
+    begin
+        SearchResult := BinarySearch(Item);
+        if SearchResult.ResultType = srFoundAtIndex then
+        begin
+            Result := TrueDelete(SearchResult.Index);
+        end;
+    end
+    else
+    begin
+        SearchResult := SequentialSearch(Item);
+        if SearchResult.ResultType = srFoundAtIndex then
+            Result := TrueDelete(SearchResult.Index);
+    end;
+end;
+
+function TAbstractList.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    SearchResult: TSearchResult;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create;
+    if Sorted then
+    begin
+        SearchResult := BinarySearch(Item);
+        if SearchResult.ResultType = srFoundAtIndex then
+        begin
+            repeat
+                ResultCollection.Add(TrueDelete(SearchResult.Index));
+            until not Comparator.Equals(Item, Items[SearchResult.Index]);
+        end;
+    end
+    else
+    begin
+        I := 0;
+        while I < Size do
+        begin
+            if Comparator.Equals(Item, Items[I]) then
+            begin
+                ResultCollection.Add(TrueDelete(I));
+            end
+            else
+                Inc(I);
+        end;
+    end;
+    Result := ResultCollection;
+end;
+
+procedure TAbstractList.QuickSort(Lo, Hi: Integer; const Comparator: IComparator);
+var
+    I, J, Mid: Integer;
+begin
+    repeat
+        I := Lo;
+        J := Hi;
+        Mid := (Lo + Hi) div 2;
+        repeat
+            while Comparator.Compare(Items[I], Items[Mid]) < 0 do
+                Inc(I);
+            while Comparator.Compare(Items[J], Items[Mid]) > 0 do
+                Dec(J);
+            if I <= J then
+            begin
+                Exchange(I, J);
+                if Mid = I then
+                    Mid := J
+                else if Mid = J then
+                    Mid := I;
+                Inc(I);
+                Dec(J);
+            end;
+        until I > J;
+        if Lo < J then
+            QuickSort(Lo, J, Comparator);
+        Lo := I;
+    until I >= Hi;
+end;
+
+procedure TAbstractList.QuickSort(Lo, Hi: Integer; CompareFunc: TCollectionCompareFunc);
+var
+    I, J, Mid: Integer;
+begin
+    repeat
+        I := Lo;
+        J := Hi;
+        Mid := (Lo + Hi) div 2;
+        repeat
+            while CompareFunc(Items[I], Items[Mid]) < 0 do
+                Inc(I);
+            while CompareFunc(Items[J], Items[Mid]) > 0 do
+                Dec(J);
+            if I <= J then
+            begin
+                Exchange(I, J);
+                if Mid = I then
+                    Mid := J
+                else if Mid = J then
+                    Mid := I;
+                Inc(I);
+                Dec(J);
+            end;
+        until I > J;
+        if Lo < J then
+            QuickSort(Lo, J, CompareFunc);
+        Lo := I;
+    until I >= Hi;
+end;
+
+function TAbstractList.GetDuplicates: Boolean;
+begin
+    Result := FDuplicates;
+end;
+
+procedure TAbstractList.SetDuplicates(Value: Boolean);
+var
+    Iterator: IIterator;
+    Failed: Boolean;
+begin
+    Failed := false;
+    // If trying to set no duplicates, check there are no existing duplicates.
+    if not Value then
+    begin
+        Iterator := GetIterator;
+        while not Iterator.EOF and not Failed do
+        begin
+            Failed := (ItemCount(Iterator.CurrentItem) > 1);
+            Iterator.Next;
+        end;
+        if Failed then
+            CollectionError(ceDuplicate);
+    end;
+    if not Failed then
+        FDuplicates := Value;
+end;
+
+function TAbstractList.GetItem(Index: Integer): ICollectable;
+begin
+    if (Index < 0) or (Index >= Size) then
+    begin
+        CollectionError(ceOutOfRange);
+        Result := nil;
+    end
+    else
+        Result := TrueGetItem(Index);
+end;
+
+procedure TAbstractList.SetItem(Index: Integer; const Item: ICollectable);
+var
+    SearchResult: TSearchResult;
+begin
+    if (Index < 0) or (Index >= Size) then
+    begin
+        CollectionError(ceOutOfRange)
+    end
+    else if not Duplicates then
+    begin
+        // Find any duplicates
+        if Sorted then
+        begin
+            SearchResult := BinarySearch(Item);
+            case SearchResult.ResultType of
+            srBeforeIndex, srAfterEnd: begin        // If item is not present
+                FSorted := false;
+                TrueSetItem(Index, Item);
+            end;
+            srFoundAtIndex: begin                   // If item is already present
+                CollectionError(ceDuplicate);
+            end;
+            end;
+        end
+        else
+        begin
+            // If item is already present
+            if SequentialSearch(Item, Comparator).ResultType = srFoundAtIndex then
+            begin
+                CollectionError(ceDuplicate);
+            end
+            else
+            begin
+                TrueSetItem(Index, Item);
+            end;
+        end;
+    end
+    else
+    begin
+        FSorted := false;
+        TrueSetItem(Index, Item);
+    end;
+end;
+
+function TAbstractList.GetIterator: IIterator;
+begin
+    Result := TAbstractListIterator.Create(Self);
+end;
+
+function TAbstractList.GetNaturalItemIID: TGUID;
+begin
+    Result := ComparableIID;
+end;
+
+function TAbstractList.GetSorted: Boolean;
+begin
+    Result := FSorted;
+end;
+
+procedure TAbstractList.SetSorted(Value: Boolean);
+begin
+    if Value then
+        Sort;
+end;
+
+function TAbstractList.GetType: TCollectionType;
+begin
+    Result := ctList;
+end;
+
+function TAbstractList.BinarySearch(const Item: ICollectable): TSearchResult;
+var
+    Lo, Hi, Mid: Integer;
+    CompareResult: Integer;
+    Success: Boolean;
+begin
+    if Size = 0 then
+    begin
+        Result.ResultType := srAfterEnd;
+        Exit;
+    end;
+    Lo := 0;
+    Hi := Size - 1;
+    Success := false;
+    repeat
+        Mid := (Lo + Hi) div 2;
+        CompareResult := Comparator.Compare(Item, Items[Mid]);
+        if CompareResult = 0 then
+            Success := true
+        else if CompareResult > 0 then
+            Lo := Mid + 1
+        else
+            Hi := Mid - 1;
+    until (Lo > Hi) or Success;
+    if Success then
+    begin
+        // Move index back if in cluster of duplicates
+        while (Mid > 0) and Comparator.Equals(Item, Items[Mid - 1]) do
+            Dec(Mid);
+        Result.ResultType := srFoundAtIndex;
+        Result.Index := Mid;
+    end
+    else if CompareResult < 0 then
+    begin
+        Result.ResultType := srBeforeIndex;
+        Result.Index := Mid;
+    end
+    else if Hi < Size - 1 then
+    begin
+        Result.ResultType := srBeforeIndex;
+        Result.Index := Mid + 1;
+    end
+    else
+        Result.ResultType := srAfterEnd;
+end;
+
+function TAbstractList.CloneAsList: IList;
+begin
+    Result := (TAbstractListClass(ClassType)).Create(Self);
+end;
+
+function TAbstractList.Delete(Index: Integer): ICollectable;
+begin
+    if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+        Result := nil;
+    end
+    else if (Index < 0) or (Index >= Size) then
+    begin
+        CollectionError(ceOutOfRange);
+        Result := nil;
+    end
+    else
+    begin
+        Result := TrueDelete(Index);
+    end;
+end;
+
+procedure TAbstractList.Exchange(Index1, Index2: Integer);
+var
+    Item: ICollectable;
+begin
+    if (Index1 < 0) or (Index1 >= Size) then
+        CollectionError(ceOutOfRange);
+    if (Index2 < 0) or (Index2 >= Size) then
+        CollectionError(ceOutOfRange);
+    FSorted := false;
+    Item := ICollectable(Items[Index1]);
+    Items[Index1] := Items[Index2];
+    Items[Index2] := Item;
+end;
+
+function TAbstractList.First: ICollectable;
+begin
+    if Size > 0 then
+        Result := Items[0]
+    else
+        Result := nil;
+end;
+
+function TAbstractList.IndexOf(const Item: ICollectable): Integer;
+var
+    SearchResult: TSearchResult;
+begin
+    if Sorted then
+        SearchResult := BinarySearch(Item)
+    else
+        SearchResult := SequentialSearch(Item, Comparator);
+    if SearchResult.ResultType = srFoundAtIndex then
+        Result := SearchResult.Index
+    else
+        Result := -1;
+end;
+
+function TAbstractList.Insert(Index: Integer; const Item: ICollectable): Boolean;
+var
+    ItemError: TCollectionError;
+begin
+    ItemError := ItemAllowed(Item);
+    if ItemError <> ceOK then
+    begin
+        CollectionError(ItemError);
+        Result := false;
+    end
+    else if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+        Result := false;
+    end
+    else if (Index < 0) or (Index > Size) then
+    begin
+        CollectionError(ceOutOfRange);
+        Result := false;
+    end
+    else
+    begin
+        FSorted := false;
+        if Index = Size then
+            TrueAdd(Item)
+        else
+            TrueInsert(Index, Item);
+        Result := true;
+    end;
+end;
+
+function TAbstractList.Insert(Index: Integer; const ItemArray: array of ICollectable): Integer;
+var
+    Item: ICollectable;
+    ItemError: TCollectionError;
+    I, NewIndex, Count: Integer;
+    Success: Boolean;
+begin
+    Count := 0;
+    if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+    end
+    else if (Index < 0) or (Index > Size) then
+    begin
+        CollectionError(ceOutOfRange);
+    end
+    else
+    begin
+        // Insert entire array in place in correct order
+        NewIndex := Index;
+        for I := Low(ItemArray) to High(ItemArray) do
+        begin
+            Item := ItemArray[I];
+            ItemError := ItemAllowed(Item);
+            if ItemError <> ceOK then
+            begin
+                CollectionError(ItemError);
+            end
+            else
+            begin
+                Success := Insert(NewIndex, Item);
+                if Success then
+                begin
+                    Inc(NewIndex);
+                    Inc(Count);
+                end;
+            end;
+        end;
+    end;
+    Result := Count;
+end;
+
+function TAbstractList.Insert(Index: Integer; const Collection: ICollection): Integer;
+var
+    Iterator: IIterator;
+    Item: ICollectable;
+    ItemError: TCollectionError;
+    NewIndex, Count: Integer;
+    Success: Boolean;
+begin
+    Count := 0;
+    if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+    end
+    else if (Index < 0) or (Index > Size) then
+    begin
+        CollectionError(ceOutOfRange);
+    end
+    else
+    begin
+        // Insert entire collection in place in correct order
+        NewIndex := Index;
+        Iterator := Collection.GetIterator;
+        while not Iterator.EOF do
+        begin
+            Item := Iterator.CurrentItem;
+            ItemError := ItemAllowed(Item);
+            if ItemError <> ceOK then
+            begin
+                CollectionError(ItemError);
+            end
+            else
+            begin
+                Success := Insert(NewIndex, Item);
+                if Success then
+                begin
+                    Inc(NewIndex);
+                    Inc(Count);
+                end;
+            end;
+            Iterator.Next;
+        end;
+    end;
+    Result := Count;
+end;
+
+function TAbstractList.IsNilAllowed: Boolean;
+begin
+    Result := true;
+end;
+
+function TAbstractList.Last: ICollectable;
+begin
+    if Size > 0 then
+        Result := Items[Size - 1]
+    else
+        Result := nil;
+end;
+
+function TAbstractList.Search(const Item: ICollectable; const SearchComparator: IComparator = nil): TSearchResult;
+begin
+    if Sorted and (SearchComparator = nil) then
+        Result := BinarySearch(Item)
+    else
+        Result := SequentialSearch(Item, SearchComparator);
+end;
+
+function TAbstractList.SequentialSearch(const Item: ICollectable; const SearchComparator: IComparator): TSearchResult;
+var
+    WorkingComparator: IComparator;
+    I: Integer;
+    Success: Boolean;
+begin
+    if SearchComparator = nil then
+        WorkingComparator := Comparator
+    else
+        WorkingComparator := SearchComparator;
+    Result.ResultType := srNotFound;
+    I := 0;
+    Success := false;
+    while (I < Size) and not Success do
+    begin
+        if WorkingComparator.Equals(Item, Items[I]) then
+        begin
+            Result.ResultType := srFoundAtIndex;
+            Result.Index := I;
+            Success := true;
+        end
+        else
+            Inc(I);
+    end;
+end;
+
+procedure TAbstractList.Sort(const SortComparator: IComparator);
+begin
+    if SortComparator = nil then
+    begin
+        if Size > 0 then
+            QuickSort(0, Size - 1, Comparator);
+        FSorted := true;
+    end
+    else
+    begin
+        if Size > 0 then
+            QuickSort(0, Size - 1, SortComparator);
+        FSorted := false;
+    end;
+end;
+
+procedure TAbstractList.Sort(CompareFunc: TCollectionCompareFunc);
+begin
+    if Size > 0 then
+        QuickSort(0, Size - 1, CompareFunc);
+    FSorted := false;
+end;
+
+{ TAbstractMap }
+constructor TAbstractMap.Create;
+begin
+    Create(false, true);
+end;
+
+constructor TAbstractMap.Create(NaturalItemsOnly: Boolean);
+begin
+    Create(NaturalItemsOnly, true);
+end;
+
+constructor TAbstractMap.Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly);
+    FNaturalKeysOnly := NaturalKeysOnly or GetAlwaysNaturalKeys;
+    FAssociationComparator := TAssociationComparator.Create(FNaturalKeysOnly);
+    if FNaturalKeysOnly then
+        FKeyComparator := TAbstractComparator.GetNaturalComparator
+    else
+        FKeyComparator := TAbstractComparator.GetDefaultComparator;
+end;
+
+constructor TAbstractMap.Create(const ItemArray: array of ICollectable);
+begin
+    Create(ItemArray, true, true);
+end;
+
+constructor TAbstractMap.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+begin
+    Create(ItemArray, true, true);
+end;
+
+constructor TAbstractMap.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+var
+    I: Integer;
+begin
+    Create(true, NaturalKeysOnly);
+    if not FixedSize then
+    begin
+        Capacity := Length(ItemArray);
+        for I := Low(ItemArray) to High(ItemArray) do
+        begin
+            Add(ItemArray[I]);
+        end;
+    end;
+end;
+
+constructor TAbstractMap.Create(const KeyArray, ItemArray: array of ICollectable);
+begin
+    Create(KeyArray, ItemArray, false, true);
+end;
+
+constructor TAbstractMap.Create(const KeyArray, ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+begin
+    Create(KeyArray, ItemArray, NaturalItemsOnly, true);
+end;
+
+constructor TAbstractMap.Create(const KeyArray, ItemArray: array of ICollectable; NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+var
+    I, Lo, Hi: Integer;
+begin
+    Create(NaturalItemsOnly, NaturalKeysOnly);
+    if not FixedSize then
+    begin
+        Capacity := Min(Length(KeyArray), Length(ItemArray));
+        Lo := Max(Low(KeyArray), Low(ItemArray));
+        Hi := Min(High(KeyArray), High(ItemArray));
+        for I := Lo to Hi do
+        begin
+            Put(KeyArray[I], ItemArray[I]);
+        end;
+    end;
+end;
+
+constructor TAbstractMap.Create(const Map: IMap);
+var
+    MapIterator: IMapIterator;
+begin
+    Create(Map.GetNaturalItemsOnly, Map.GetNaturalKeysOnly);
+    InitFrom(Map);
+    if not FixedSize then
+    begin
+        Capacity := Map.GetSize;
+        MapIterator := Map.GetMapIterator;
+        while not MapIterator.EOF do
+        begin
+            Put(MapIterator.CurrentKey, MapIterator.CurrentItem);
+            MapIterator.Next;
+        end;
+    end;
+end;
+
+destructor TAbstractMap.Destroy;
+begin
+    FKeyComparator := nil;
+    FAssociationComparator := nil;
+    inherited Destroy;
+end;
+
+procedure TAbstractMap.InitFrom(const Collection: ICollection);
+var
+    Map: IMap;
+begin
+    inherited InitFrom(Collection);
+    if Collection.QueryInterface(IMap, Map) = S_OK then
+    begin
+        FNaturalKeysOnly := Map.GetNaturalKeysOnly or GetAlwaysNaturalKeys;
+        KeyComparator := Map.GetKeyComparator;
+    end;
+end;
+
+function TAbstractMap.TrueAdd(const Item: ICollectable): Boolean;
+var
+    Position: TCollectionPosition;
+    Mappable: IMappable;
+begin
+    if IsNaturalItem(Item) then
+    begin
+        Mappable := Item as IMappable;
+        Position := GetKeyPosition(Mappable.GetKey);
+        try
+            if Position.Found then
+            begin
+                CollectionError(ceDuplicateKey);
+                Result := false;
+            end
+            else
+            begin
+                TruePut(Position, TAssociation.Create(Mappable.GetKey, Item));
+                Result := true;
+            end;
+        finally
+            Position.Free;
+        end;
+    end
+    else
+    begin
+        CollectionError(ceNotNaturalItem);
+        Result := false;
+    end;
+end;
+
+function TAbstractMap.TrueContains(const Item: ICollectable): Boolean;
+var
+    Item2: ICollectable;
+    Success: Boolean;
+    Iterator: IIterator;
+begin
+    Iterator := GetIterator;
+    Success := false;
+    while not Iterator.EOF and not Success do
+    begin
+        Item2 := Iterator.CurrentItem;
+        if Comparator.Equals(Item, Item2) then
+            Success := true;
+        Iterator.Next;
+    end;
+    Result := Success;
+end;
+
+function TAbstractMap.TrueRemove(const Item: ICollectable): ICollectable;
+var
+    Item2: ICollectable;
+    Iterator: IMapIterator;
+    Found: Boolean;
+begin
+    // Sequential search
+    Found := false;
+    Result := nil;
+    Iterator := GetAssociationIterator;
+    while not Iterator.EOF and not Found do
+    begin
+        Item2 := Iterator.CurrentItem;
+        if Comparator.Equals(Item, Item2) then
+        begin
+            Result := Item2;
+            Iterator.Remove;
+            Found := true;
+        end;
+        Iterator.Next;
+    end;
+end;
+
+function TAbstractMap.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    Item2: ICollectable;
+    Iterator: IMapIterator;
+begin
+    // Sequential search
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := GetAssociationIterator;
+    while not Iterator.EOF do
+    begin
+        Item2 := Iterator.CurrentItem;
+        if Comparator.Equals(Item, Item2) then
+        begin
+            ResultCollection.Add(Item2);
+            Iterator.Remove;
+        end;
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+class function TAbstractMap.GetAlwaysNaturalKeys: Boolean;
+begin
+    Result := false;
+end;
+
+function TAbstractMap.GetItem(const Key: ICollectable): ICollectable;
+begin
+    Result := Get(Key);
+end;
+
+procedure TAbstractMap.SetItem(const Key, Item: ICollectable);
+begin
+    Put(Key, Item);
+end;
+
+function TAbstractMap.GetIterator: IIterator;
+begin
+    Result := GetAssociationIterator;
+end;
+
+function TAbstractMap.GetKeyComparator: IComparator;
+begin
+    Result := FKeyComparator;
+end;
+
+procedure TAbstractMap.SetKeyComparator(const Value: IComparator);
+begin
+    FKeyComparator := Value;
+    FAssociationComparator.KeyComparator := Value;
+end;
+
+function TAbstractMap.GetKeyIterator: IIterator;
+begin
+    Result := TAssociationKeyIterator.Create(GetAssociationIterator);
+end;
+
+function TAbstractMap.GetKeys: ISet;
+var
+    ResultCollection: TPArraySet;
+    KeyIterator: IIterator;
+begin
+    ResultCollection := TPArraySet.Create(NaturalKeysOnly);
+    ResultCollection.SetComparator(GetKeyComparator);
+    KeyIterator := GetKeyIterator;
+    while not KeyIterator.EOF do
+    begin
+        ResultCollection.Add(KeyIterator.CurrentItem);
+        KeyIterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractMap.GetMapIterator: IMapIterator;
+begin
+    Result := GetAssociationIterator;
+end;
+
+function TAbstractMap.GetMapIteratorByKey(const Filter: IFilter): IMapIterator;
+var
+    Iterator: IMapIterator;
+begin
+    Iterator := GetMapIterator;
+    Result := TKeyFilterMapIterator.Create(Iterator, Filter, Iterator.GetAllowRemoval);
+end;
+
+function TAbstractMap.GetMapIteratorByKey(FilterFunc: TCollectionFilterFunc): IMapIterator;
+var
+    Iterator: IMapIterator;
+begin
+    Iterator := GetMapIterator;
+    Result := TKeyFilterFuncMapIterator.Create(Iterator, FilterFunc, Iterator.GetAllowRemoval);
+end;
+
+function TAbstractMap.GetNaturalItemIID: TGUID;
+begin
+    Result := MappableIID;
+end;
+
+function TAbstractMap.GetNaturalKeyIID: TGUID;
+begin
+    Result := EquatableIID;
+end;
+
+function TAbstractMap.GetNaturalKeysOnly: Boolean;
+begin
+    Result := FNaturalKeysOnly;
+end;
+
+function TAbstractMap.GetType: TCollectionType;
+begin
+    Result := ctMap;
+end;
+
+function TAbstractMap.GetValues: ICollection;
+var
+    ResultCollection: ICollection;
+    ValueIterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    ValueIterator := GetIterator;
+    while not ValueIterator.EOF do
+    begin
+        ResultCollection.Add(ValueIterator.CurrentItem);
+        ValueIterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+// Overrides TAbstractCollection function, otherwise Create(ICollection) is
+// called, which cannot access keys.
+function TAbstractMap.Clone: ICollection;
+begin
+    Result := (TAbstractMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractMap.CloneAsMap: IMap;
+begin
+    Result := (TAbstractMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractMap.ContainsKey(const Key: ICollectable): Boolean;
+var
+    Position: TCollectionPosition;
+begin
+    Position := GetKeyPosition(Key);
+    try
+        Result := Position.Found;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractMap.ContainsKey(const KeyArray: array of ICollectable): Boolean;
+var
+    I: Integer;
+    Success: Boolean;
+begin
+    Success := true;
+    for I := Low(KeyArray) to High(KeyArray) do
+    begin
+        Success := Success and ContainsKey(KeyArray[I]);
+        if not Success then
+            break;
+    end;
+    Result := Success;
+end;
+
+function TAbstractMap.ContainsKey(const Collection: ICollection): Boolean;
+var
+    Iterator: IIterator;
+    Success: Boolean;
+begin
+    Success := true;
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Success := Success and ContainsKey(Iterator.CurrentItem);
+        if not Success then
+            break;
+        Iterator.Next;
+    end;
+    Result := Success;
+end;
+
+function TAbstractMap.Get(const Key: ICollectable): ICollectable;
+var
+    KeyError: TCollectionError;
+    Position: TCollectionPosition;
+begin
+    KeyError := KeyAllowed(Key);
+    if KeyError <> ceOK then
+    begin
+        CollectionError(KeyError);
+        Result := nil;
+    end
+    else
+    begin
+        Position := GetKeyPosition(Key);
+        try
+            if Position.Found then
+                Result := TrueGet(Position).GetValue
+            else
+                Result := nil;
+        finally
+            Position.Free;
+        end;
+    end;
+end;
+
+function TAbstractMap.KeyAllowed(const Key: ICollectable): TCollectionError;
+begin
+    if NaturalKeysOnly and not IsNaturalKey(Key) then
+        Result := ceNotNaturalItem
+    else if Key = nil then
+        Result := ceNilNotAllowed
+    else
+        Result := ceOK;
+end;
+
+function TAbstractMap.IsNaturalKey(const Key: ICollectable): Boolean;
+var
+    Temp: IUnknown;
+begin
+    if Key.QueryInterface(NaturalKeyIID, Temp) <> E_NOINTERFACE then
+        Result := true
+    else
+        Result := false;
+end;
+
+function TAbstractMap.IsNilAllowed: Boolean;
+begin
+    Result := true;
+end;
+
+function TAbstractMap.MatchingKey(const KeyArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(KeyArray) to High(KeyArray) do
+    begin
+        if ContainsKey(KeyArray[I]) then
+            ResultCollection.Add(KeyArray[I]);
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractMap.MatchingKey(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    Iterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        if ContainsKey(Iterator.CurrentItem) then
+            ResultCollection.Add(Iterator.CurrentItem);
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractMap.Put(const Item: ICollectable): ICollectable;
+var
+    Mappable: IMappable;
+    OldAssociation, NewAssociation: IAssociation;
+    Position: TCollectionPosition;
+begin
+    if not IsNaturalItem(Item) then
+    begin
+        CollectionError(ceNotNaturalItem);
+        Result := nil;
+    end
+    else
+    begin
+        Item.QueryInterface(IMappable, Mappable);
+        Position := GetKeyPosition(Mappable.GetKey);
+        try
+            NewAssociation := TAssociation.Create(Mappable.GetKey, Item);
+            OldAssociation := TruePut(Position, NewAssociation);
+            if OldAssociation <> nil then
+                Result := OldAssociation.GetValue
+            else
+                Result := nil;
+        finally
+            Position.Free;
+        end;
+    end;
+end;
+
+function TAbstractMap.Put(const Key, Item: ICollectable): ICollectable;
+var
+    OldAssociation, NewAssociation: IAssociation;
+    ItemError, KeyError: TCollectionError;
+    Position: TCollectionPosition;
+begin
+    ItemError := ItemAllowed(Item);
+    KeyError := KeyAllowed(Key);
+    if ItemError <> ceOK then
+    begin
+        CollectionError(ItemError);
+        Result := nil;
+    end
+    else if KeyError <> ceOK then
+    begin
+        CollectionError(KeyError);
+        Result := nil;
+    end
+    else
+    begin
+        // Find appropriate place, then place key-item association there
+        Position := GetKeyPosition(Key);
+        try
+            NewAssociation := TAssociation.Create(Key, Item);
+            OldAssociation := TruePut(Position, NewAssociation);
+            if OldAssociation <> nil then
+                Result := OldAssociation.GetValue
+            else
+                Result := nil;
+        finally
+            Position.Free;
+        end;
+    end;
+end;
+
+function TAbstractMap.Put(const ItemArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    Mappable: IMappable;
+    OldAssociation, NewAssociation: IAssociation;
+    Position: TCollectionPosition;
+    Item: ICollectable;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(ItemArray) to High(ItemArray) do
+    begin
+        Item := ItemArray[I];
+        if not IsNaturalItem(Item) then
+        begin
+            CollectionError(ceNotNaturalItem);
+        end
+        else
+        begin
+            // Find appropriate place, then place key-item association there
+            Item.QueryInterface(IMappable, Mappable);
+            Position := GetKeyPosition(Mappable.GetKey);
+            try
+                NewAssociation := TAssociation.Create(Mappable.GetKey, Item);
+                OldAssociation := TruePut(Position, NewAssociation);
+                if OldAssociation <> nil then
+                    ResultCollection.Add(OldAssociation.GetValue);
+            finally
+                Position.Free;
+            end;
+        end;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractMap.Put(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    Mappable: IMappable;
+    OldAssociation, NewAssociation: IAssociation;
+    Position: TCollectionPosition;
+    Iterator: IIterator;
+    Item: ICollectable;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Item := Iterator.CurrentItem;;
+        if not IsNaturalItem(Item) then
+        begin
+            CollectionError(ceNotNaturalItem);
+        end
+        else
+        begin
+            // Find appropriate place, then place key-item association there
+            Item.QueryInterface(IMappable, Mappable);
+            Position := GetKeyPosition(Mappable.GetKey);
+            try
+                NewAssociation := TAssociation.Create(Mappable.GetKey, Item);
+                OldAssociation := TruePut(Position, NewAssociation);
+                if OldAssociation <> nil then
+                    ResultCollection.Add(OldAssociation.GetValue);
+            finally
+                Position.Free;
+            end;
+        end;
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractMap.Put(const Map: IMap): ICollection;
+var
+    ResultCollection: ICollection;
+    OldAssociation, NewAssociation: IAssociation;
+    ItemError, KeyError: TCollectionError;
+    Position: TCollectionPosition;
+    MapIterator: IMapIterator;
+    Key, Item: ICollectable;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    MapIterator := Map.GetMapIterator;
+    while not MapIterator.EOF do
+    begin
+        Key := MapIterator.CurrentKey;
+        Item := MapIterator.CurrentItem;
+
+        ItemError := ItemAllowed(Item);
+        KeyError := KeyAllowed(Key);
+        if ItemError <> ceOK then
+        begin
+            CollectionError(ItemError);
+        end
+        else if KeyError <> ceOK then
+        begin
+            CollectionError(KeyError);
+        end
+        else
+        begin
+            // Find appropriate place, then place key-item association there
+            Position := GetKeyPosition(Key);
+            try
+                NewAssociation := TAssociation.Create(Key, Item);
+                OldAssociation := TruePut(Position, NewAssociation);
+                if OldAssociation <> nil then
+                    ResultCollection.Add(OldAssociation.GetValue);
+            finally
+                Position.Free;
+            end;
+        end;
+        MapIterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractMap.RemoveKey(const Key: ICollectable): ICollectable;
+var
+    KeyError: TCollectionError;
+    Position: TCollectionPosition;
+    OldAssociation: IAssociation;
+begin
+    KeyError := KeyAllowed(Key);
+    if KeyError <> ceOK then
+    begin
+        CollectionError(KeyError);
+        Result := nil;
+    end
+    else
+    begin
+        Position := GetKeyPosition(Key);
+        try
+            if Position.Found then
+            begin
+                OldAssociation := TrueRemove2(Position);
+                Result := OldAssociation.GetValue
+            end
+            else
+                Result := nil;
+        finally
+            Position.Free;
+        end;
+    end;
+end;
+
+function TAbstractMap.RemoveKey(const KeyArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    OldAssociation: IAssociation;
+    KeyError: TCollectionError;
+    Position: TCollectionPosition;
+    Key: ICollectable;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(KeyArray) to High(KeyArray) do
+    begin
+        Key := KeyArray[I];
+        KeyError := KeyAllowed(Key);
+        if KeyError <> ceOK then
+        begin
+            CollectionError(KeyError);
+        end
+        else
+        begin
+            Position := GetKeyPosition(Key);
+            try
+                if Position.Found then
+                begin
+                    OldAssociation := TrueRemove2(Position);
+                    ResultCollection.Add(OldAssociation.GetValue);
+                end;
+            finally
+                Position.Free;
+            end;
+        end;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractMap.RemoveKey(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    OldAssociation: IAssociation;
+    KeyError: TCollectionError;
+    Position: TCollectionPosition;
+    Key: ICollectable;
+    Iterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Key := Iterator.CurrentItem;
+        KeyError := KeyAllowed(Key);
+        if KeyError <> ceOK then
+        begin
+            CollectionError(KeyError);
+        end
+        else
+        begin
+            Position := GetKeyPosition(Key);
+            try
+                if Position.Found then
+                begin
+                    OldAssociation := TrueRemove2(Position);
+                    ResultCollection.Add(OldAssociation.GetValue);
+                end;
+            finally
+                Position.Free;
+            end;
+        end;
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractMap.RetainKey(const KeyArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    MapIterator: IMapIterator;
+    I: Integer;
+    Found: Boolean;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+    end
+    else
+    begin
+        MapIterator := GetMapIterator;
+        while not MapIterator.EOF do
+        begin
+            // Converting the array to a map would be faster but I don't want to
+            // couple base class code to a complex collection.
+            Found := false;
+            for I := Low(KeyArray) to High(KeyArray) do
+            begin
+                Found := KeyComparator.Equals(MapIterator.CurrentKey, KeyArray[I]);
+                if Found then
+                    break;
+            end;
+            if not Found then
+            begin
+                ResultCollection.Add(MapIterator.CurrentItem);
+                MapIterator.Remove;
+            end;
+            MapIterator.Next;
+        end;
+        Result := ResultCollection;
+    end;
+end;
+
+function TAbstractMap.RetainKey(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    MapIterator: IMapIterator;
+    Key: ICollectable;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+    end
+    else
+    begin
+        MapIterator := GetMapIterator;
+        while not MapIterator.EOF do
+        begin
+            Key := MapIterator.CurrentKey;
+            if not Collection.Contains(Key) then
+            begin
+                ResultCollection.Add(MapIterator.CurrentItem);
+                MapIterator.Remove;
+            end;
+            MapIterator.Next;
+        end;
+    end;
+    Result := ResultCollection;
+end;
+
+
+{ TAbstractIntegerMap }
+constructor TAbstractIntegerMap.Create(NaturalItemsOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly);
+    FAssociationComparator := TIntegerAssociationComparator.Create;
+end;
+
+constructor TAbstractIntegerMap.Create(const ItemArray: array of ICollectable);
+begin
+    Create(ItemArray, true);
+end;
+
+constructor TAbstractIntegerMap.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+begin
+    inherited Create(ItemArray, true);
+end;
+
+constructor TAbstractIntegerMap.Create(const KeyArray: array of Integer; const ItemArray: array of ICollectable);
+begin
+    Create(KeyArray, ItemArray, false);
+end;
+
+constructor TAbstractIntegerMap.Create(const KeyArray: array of Integer; const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+var
+    I, Lo, Hi: Integer;
+begin
+    Create(NaturalItemsOnly);
+    Capacity := Min(Length(KeyArray), Length(ItemArray));
+    if not FixedSize then
+    begin
+        Lo := Max(Low(KeyArray), Low(ItemArray));
+        Hi := Min(High(KeyArray), High(ItemArray));
+        for I := Lo to Hi do
+        begin
+            Put(KeyArray[I], ItemArray[I]);
+        end;
+    end;
+end;
+
+constructor TAbstractIntegerMap.Create(const Map: IIntegerMap);
+var
+    MapIterator: IIntegerMapIterator;
+begin
+    Create(Map.GetNaturalItemsOnly);
+    InitFrom(Map);
+    Capacity := Map.GetSize;
+    if not FixedSize then
+    begin
+        MapIterator := Map.GetMapIterator;
+        while not MapIterator.EOF do
+        begin
+            Put(MapIterator.CurrentKey, MapIterator.CurrentItem);
+            MapIterator.Next;
+        end;
+    end;
+end;
+
+destructor TAbstractIntegerMap.Destroy;
+begin
+    FAssociationComparator := nil;
+    inherited Destroy;
+end;
+
+function TAbstractIntegerMap.TrueAdd(const Item: ICollectable): Boolean;
+var
+    Position: TCollectionPosition;
+    Mappable: IIntegerMappable;
+begin
+    if IsNaturalItem(Item) then
+    begin
+        Mappable := Item as IIntegerMappable;
+        Position := GetKeyPosition(Mappable.GetKey);
+        try
+            if Position.Found then
+            begin
+                CollectionError(ceDuplicateKey);
+                Result := false;
+            end
+            else
+            begin
+                TruePut(Position, TIntegerAssociation.Create(Mappable.GetKey, Item));
+                Result := true;
+            end;
+        finally
+            Position.Free;
+        end;
+    end
+    else
+    begin
+        CollectionError(ceNotNaturalItem);
+        Result := false;
+    end;
+end;
+
+function TAbstractIntegerMap.TrueContains(const Item: ICollectable): Boolean;
+var
+    Item2: ICollectable;
+    Success: Boolean;
+    Iterator: IIterator;
+begin
+    Iterator := GetIterator;
+    Success := false;
+    while not Iterator.EOF and not Success do
+    begin
+        Item2 := Iterator.CurrentItem;
+        if Comparator.Equals(Item, Item2) then
+            Success := true;
+        Iterator.Next;
+    end;
+    Result := Success;
+end;
+
+function TAbstractIntegerMap.TrueRemove(const Item: ICollectable): ICollectable;
+var
+    Item2: ICollectable;
+    Iterator: IIntegerMapIterator;
+    Found: Boolean;
+begin
+    // Sequential search
+    Found := false;
+    Result := nil;
+    Iterator := GetAssociationIterator;
+    while not Iterator.EOF and not Found do
+    begin
+        Item2 := Iterator.CurrentItem;
+        if Comparator.Equals(Item, Item2) then
+        begin
+            Result := Item2;
+            Iterator.Remove;
+            Found := true;
+        end;
+        Iterator.Next;
+    end;
+end;
+
+function TAbstractIntegerMap.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    Item2: ICollectable;
+    Iterator: IIntegerMapIterator;
+begin
+    // Sequential search
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := GetAssociationIterator;
+    while not Iterator.EOF do
+    begin
+        Item2 := Iterator.CurrentItem;
+        if Comparator.Equals(Item, Item2) then
+        begin
+            ResultCollection.Add(Item2);
+            Iterator.Remove;
+        end;
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.GetItem(const Key: Integer): ICollectable;
+begin
+    Result := Get(Key);
+end;
+
+procedure TAbstractIntegerMap.SetItem(const Key: Integer; const Item: ICollectable);
+begin
+    Put(Key, Item);
+end;
+
+function TAbstractIntegerMap.GetIterator: IIterator;
+begin
+    Result := GetAssociationIterator;
+end;
+
+function TAbstractIntegerMap.GetKeys: ISet;
+var
+    ResultCollection: TPArraySet;
+    MapIterator: IIntegerMapIterator;
+begin
+    ResultCollection := TPArraySet.Create(true);
+    MapIterator := GetMapIterator;
+    while not MapIterator.EOF do
+    begin
+        ResultCollection.Add(TIntegerWrapper.Create(MapIterator.CurrentKey) as ICollectable);
+        MapIterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.GetMapIterator: IIntegerMapIterator;
+begin
+    Result := GetAssociationIterator;
+end;
+
+function TAbstractIntegerMap.GetNaturalItemIID: TGUID;
+begin
+    Result := IntegerMappableIID;
+end;
+
+function TAbstractIntegerMap.GetType: TCollectionType;
+begin
+    Result := ctIntegerMap;
+end;
+
+function TAbstractIntegerMap.GetValues: ICollection;
+var
+    ResultCollection: ICollection;
+    ValueIterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    ValueIterator := GetIterator;
+    while not ValueIterator.EOF do
+    begin
+        ResultCollection.Add(ValueIterator.CurrentItem);
+        ValueIterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+// Overrides TAbstractCollection function, otherwise Create(ICollection) is
+// called, which cannot access keys.
+function TAbstractIntegerMap.Clone: ICollection;
+begin
+    Result := (TAbstractIntegerMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractIntegerMap.CloneAsIntegerMap: IIntegerMap;
+begin
+    Result := (TAbstractIntegerMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractIntegerMap.ContainsKey(const Key: Integer): Boolean;
+var
+    Position: TCollectionPosition;
+begin
+    Position := GetKeyPosition(Key);
+    try
+        Result := Position.Found;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractIntegerMap.ContainsKey(const KeyArray: array of Integer): Boolean;
+var
+    I: Integer;
+    Success: Boolean;
+begin
+    Success := true;
+    for I := Low(KeyArray) to High(KeyArray) do
+    begin
+        Success := Success and ContainsKey(KeyArray[I]);
+        if not Success then
+            break;
+    end;
+    Result := Success;
+end;
+
+function TAbstractIntegerMap.Get(const Key: Integer): ICollectable;
+var
+    Position: TCollectionPosition;
+begin
+    Position := GetKeyPosition(Key);
+    try
+        if Position.Found then
+            Result := TrueGet(Position).GetValue
+        else
+            Result := nil;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractIntegerMap.IsNilAllowed: Boolean;
+begin
+    Result := true;
+end;
+
+function TAbstractIntegerMap.Put(const Item: ICollectable): ICollectable;
+var
+    Mappable: IIntegerMappable;
+    OldAssociation, NewAssociation: IIntegerAssociation;
+    Position: TCollectionPosition;
+begin
+    if not IsNaturalItem(Item) then
+    begin
+        CollectionError(ceNotNaturalItem);
+        Result := nil;
+    end
+    else
+    begin
+        Item.QueryInterface(IIntegerMappable, Mappable);
+        Position := GetKeyPosition(Mappable.GetKey);
+        try
+            NewAssociation := TIntegerAssociation.Create(Mappable.GetKey, Item);
+            OldAssociation := TruePut(Position, NewAssociation);
+            if OldAssociation <> nil then
+                Result := OldAssociation.GetValue
+            else
+                Result := nil;
+        finally
+            Position.Free;
+        end;
+    end;
+end;
+
+function TAbstractIntegerMap.Put(const Key: Integer; const Item: ICollectable): ICollectable;
+var
+    OldAssociation, NewAssociation: IIntegerAssociation;
+    ItemError: TCollectionError;
+    Position: TCollectionPosition;
+begin
+    ItemError := ItemAllowed(Item);
+    if ItemError <> ceOK then
+    begin
+        CollectionError(ItemError);
+        Result := nil;
+    end
+    else
+    begin
+        Position := GetKeyPosition(Key);
+        try
+            NewAssociation := TIntegerAssociation.Create(Key, Item);
+            OldAssociation := TruePut(Position, NewAssociation);
+            if OldAssociation <> nil then
+                Result := OldAssociation.GetValue
+            else
+                Result := nil;
+        finally
+            Position.Free;
+        end;
+    end;
+end;
+
+function TAbstractIntegerMap.Put(const ItemArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    Mappable: IIntegerMappable;
+    OldAssociation, NewAssociation: IIntegerAssociation;
+    Position: TCollectionPosition;
+    Item: ICollectable;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(ItemArray) to High(ItemArray) do
+    begin
+        Item := ItemArray[I];
+        if not IsNaturalItem(Item) then
+        begin
+            CollectionError(ceNotNaturalItem);
+        end
+        else
+        begin
+            Item.QueryInterface(IIntegerMappable, Mappable);
+            Position := GetKeyPosition(Mappable.GetKey);
+            try
+                NewAssociation := TIntegerAssociation.Create(Mappable.GetKey, Item);
+                OldAssociation := TruePut(Position, NewAssociation);
+                if OldAssociation <> nil then
+                    ResultCollection.Add(OldAssociation.GetValue);
+            finally
+                Position.Free;
+            end;
+        end;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.Put(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    Mappable: IIntegerMappable;
+    OldAssociation, NewAssociation: IIntegerAssociation;
+    Position: TCollectionPosition;
+    Iterator: IIterator;
+    Item: ICollectable;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Item := Iterator.CurrentItem;;
+        if not IsNaturalItem(Item) then
+        begin
+            CollectionError(ceNotNaturalItem);
+        end
+        else
+        begin
+            Item.QueryInterface(IIntegerMappable, Mappable);
+            Position := GetKeyPosition(Mappable.GetKey);
+            try
+                NewAssociation := TIntegerAssociation.Create(Mappable.GetKey, Item);
+                OldAssociation := TruePut(Position, NewAssociation);
+                if OldAssociation <> nil then
+                    ResultCollection.Add(OldAssociation.GetValue);
+            finally
+                Position.Free;
+            end;
+        end;
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.Put(const Map: IIntegerMap): ICollection;
+var
+    ResultCollection: ICollection;
+    OldAssociation, NewAssociation: IIntegerAssociation;
+    ItemError: TCollectionError;
+    Position: TCollectionPosition;
+    MapIterator: IIntegerMapIterator;
+    Item: ICollectable;
+    Key: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    MapIterator := Map.GetMapIterator;
+    while not MapIterator.EOF do
+    begin
+        Key := MapIterator.CurrentKey;
+        Item := MapIterator.CurrentItem;
+
+        ItemError := ItemAllowed(Item);
+        if ItemError <> ceOK then
+        begin
+            CollectionError(ItemError);
+        end
+        else
+        begin
+            Position := GetKeyPosition(Key);
+            try
+                NewAssociation := TIntegerAssociation.Create(Key, Item);
+                OldAssociation := TruePut(Position, NewAssociation);
+                if OldAssociation <> nil then
+                    ResultCollection.Add(OldAssociation.GetValue);
+            finally
+                Position.Free;
+            end;
+        end;
+        MapIterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.RemoveKey(const Key: Integer): ICollectable;
+var
+    Position: TCollectionPosition;
+    OldAssociation: IIntegerAssociation;
+begin
+    Position := GetKeyPosition(Key);
+    try
+        if Position.Found then
+        begin
+            OldAssociation := TrueRemove2(Position);
+            Result := OldAssociation.GetValue
+        end
+        else
+            Result := nil;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractIntegerMap.RemoveKey(const KeyArray: array of Integer): ICollection;
+var
+    ResultCollection: ICollection;
+    OldAssociation: IIntegerAssociation;
+    Position: TCollectionPosition;
+    Key: Integer;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(KeyArray) to High(KeyArray) do
+    begin
+        Key := KeyArray[I];
+        Position := GetKeyPosition(Key);
+        try
+            if Position.Found then
+            begin
+                OldAssociation := TrueRemove2(Position);
+                ResultCollection.Add(OldAssociation.GetValue);
+            end;
+        finally
+            Position.Free;
+        end;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.RetainKey(const KeyArray: array of Integer): ICollection;
+var
+    ResultCollection: ICollection;
+    MapIterator: IIntegerMapIterator;
+    I: Integer;
+    Found: Boolean;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+    end
+    else
+    begin
+        MapIterator := GetMapIterator;
+        while not MapIterator.EOF do
+        begin
+            // Converting the array to a map would be faster but I don't want to
+            // couple base class code to a complex collection.
+            Found := false;
+            for I := Low(KeyArray) to High(KeyArray) do
+            begin
+                Found := (MapIterator.CurrentKey = KeyArray[I]);
+                if Found then
+                    break;
+            end;
+            if not Found then
+            begin
+                ResultCollection.Add(MapIterator.CurrentItem);
+                MapIterator.Remove;
+            end;
+            MapIterator.Next;
+        end;
+        Result := ResultCollection;
+    end;
+end;
+
+
+{ TAbstractStringMap }
+constructor TAbstractStringMap.Create(NaturalItemsOnly: Boolean);
+begin
+    inherited Create(NaturalItemsOnly);
+    FAssociationComparator := TStringAssociationComparator.Create;
+end;
+
+constructor TAbstractStringMap.Create(const ItemArray: array of ICollectable);
+begin
+    Create(ItemArray, true);
+end;
+
+constructor TAbstractStringMap.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+begin
+    inherited Create(ItemArray, true);
+end;
+
+constructor TAbstractStringMap.Create(const KeyArray: array of String; const ItemArray: array of ICollectable);
+begin
+    Create(KeyArray, ItemArray, false);
+end;
+
+constructor TAbstractStringMap.Create(const KeyArray: array of String; const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+var
+    I, Lo, Hi: Integer;
+begin
+    Create(NaturalItemsOnly);
+    Capacity := Min(Length(KeyArray), Length(ItemArray));
+    if not FixedSize then
+    begin
+        Lo := Max(Low(KeyArray), Low(ItemArray));
+        Hi := Min(High(KeyArray), High(ItemArray));
+        for I := Lo to Hi do
+        begin
+            Put(KeyArray[I], ItemArray[I]);
+        end;
+    end;
+end;
+
+constructor TAbstractStringMap.Create(const Map: IStringMap);
+var
+    MapIterator: IStringMapIterator;
+begin
+    Create(Map.GetNaturalItemsOnly);
+    InitFrom(Map);
+    Capacity := Map.GetSize;
+    if not FixedSize then
+    begin
+        MapIterator := Map.GetMapIterator;
+        while not MapIterator.EOF do
+        begin
+            Put(MapIterator.CurrentKey, MapIterator.CurrentItem);
+            MapIterator.Next;
+        end;
+    end;
+end;
+
+destructor TAbstractStringMap.Destroy;
+begin
+    FAssociationComparator := nil;
+    inherited Destroy;
+end;
+
+function TAbstractStringMap.TrueAdd(const Item: ICollectable): Boolean;
+var
+    Position: TCollectionPosition;
+    Mappable: IStringMappable;
+begin
+    if IsNaturalItem(Item) then
+    begin
+        Mappable := Item as IStringMappable;
+        Position := GetKeyPosition(Mappable.GetKey);
+        try
+            if Position.Found then
+            begin
+                CollectionError(ceDuplicateKey);
+                Result := false;
+            end
+            else
+            begin
+                TruePut(Position, TStringAssociation.Create(Mappable.GetKey, Item));
+                Result := true;
+            end;
+        finally
+            Position.Free;
+        end;
+    end
+    else
+    begin
+        CollectionError(ceNotNaturalItem);
+        Result := false;
+    end;
+end;
+
+function TAbstractStringMap.TrueContains(const Item: ICollectable): Boolean;
+var
+    Item2: ICollectable;
+    Success: Boolean;
+    Iterator: IIterator;
+begin
+    Iterator := GetIterator;
+    Success := false;
+    while not Iterator.EOF and not Success do
+    begin
+        Item2 := Iterator.CurrentItem;
+        if Comparator.Equals(Item, Item2) then
+            Success := true;
+        Iterator.Next;
+    end;
+    Result := Success;
+end;
+
+function TAbstractStringMap.TrueRemove(const Item: ICollectable): ICollectable;
+var
+    Item2: ICollectable;
+    Iterator: IStringMapIterator;
+    Found: Boolean;
+begin
+    // Sequential search
+    Found := false;
+    Result := nil;
+    Iterator := GetAssociationIterator;
+    while not Iterator.EOF and not Found do
+    begin
+        Item2 := Iterator.CurrentItem;
+        if Comparator.Equals(Item, Item2) then
+        begin
+            Result := Item2;
+            Iterator.Remove;
+            Found := true;
+        end;
+        Iterator.Next;
+    end;
+end;
+
+function TAbstractStringMap.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    Item2: ICollectable;
+    Iterator: IIterator;
+begin
+    // Sequential search
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := GetAssociationIterator;
+    while not Iterator.EOF do
+    begin
+        Item2 := Iterator.CurrentItem;
+        if Comparator.Equals(Item, Item2) then
+        begin
+            ResultCollection.Add(Item2);
+            Iterator.Remove;
+        end;
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractStringMap.GetItem(const Key: String): ICollectable;
+begin
+    Result := Get(Key);
+end;
+
+procedure TAbstractStringMap.SetItem(const Key: String; const Item: ICollectable);
+begin
+    Put(Key, Item);
+end;
+
+function TAbstractStringMap.GetIterator: IIterator;
+begin
+    Result := GetAssociationIterator;
+end;
+
+function TAbstractStringMap.GetKeys: ISet;
+var
+    ResultCollection: TPArraySet;
+    MapIterator: IStringMapIterator;
+begin
+    ResultCollection := TPArraySet.Create(true);
+    MapIterator := GetMapIterator;
+    while not MapIterator.EOF do
+    begin
+        ResultCollection.Add(TStringWrapper.Create(MapIterator.CurrentKey) as ICollectable);
+        MapIterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractStringMap.GetMapIterator: IStringMapIterator;
+begin
+    Result := GetAssociationIterator;
+end;
+
+function TAbstractStringMap.GetNaturalItemIID: TGUID;
+begin
+    Result := StringMappableIID;
+end;
+
+function TAbstractStringMap.GetType: TCollectionType;
+begin
+    Result := ctStringMap;
+end;
+
+function TAbstractStringMap.GetValues: ICollection;
+var
+    ResultCollection: ICollection;
+    ValueIterator: IIterator;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    ValueIterator := GetIterator;
+    while not ValueIterator.EOF do
+    begin
+        ResultCollection.Add(ValueIterator.CurrentItem);
+        ValueIterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+// Overrides TAbstractCollection function, otherwise Create(ICollection) is
+// called, which cannot access keys.
+function TAbstractStringMap.Clone: ICollection;
+begin
+    Result := (TAbstractStringMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractStringMap.CloneAsStringMap: IStringMap;
+begin
+    Result := (TAbstractStringMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractStringMap.ContainsKey(const Key: String): Boolean;
+var
+    Position: TCollectionPosition;
+begin
+    Position := GetKeyPosition(Key);
+    try
+        Result := Position.Found;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractStringMap.ContainsKey(const KeyArray: array of String): Boolean;
+var
+    I: Integer;
+    Success: Boolean;
+begin
+    Success := true;
+    for I := Low(KeyArray) to High(KeyArray) do
+    begin
+        Success := Success and ContainsKey(KeyArray[I]);
+        if not Success then
+            break;
+    end;
+    Result := Success;
+end;
+
+function TAbstractStringMap.Get(const Key: String): ICollectable;
+var
+    Position: TCollectionPosition;
+begin
+    Position := GetKeyPosition(Key);
+    try
+        if Position.Found then
+            Result := TrueGet(Position).GetValue
+        else
+            Result := nil;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractStringMap.IsNilAllowed: Boolean;
+begin
+    Result := true;
+end;
+
+function TAbstractStringMap.Put(const Item: ICollectable): ICollectable;
+var
+    Mappable: IStringMappable;
+    OldAssociation, NewAssociation: IStringAssociation;
+    Position: TCollectionPosition;
+begin
+    if not IsNaturalItem(Item) then
+    begin
+        CollectionError(ceNotNaturalItem);
+        Result := nil;
+    end
+    else
+    begin
+        Item.QueryInterface(IStringMappable, Mappable);
+        Position := GetKeyPosition(Mappable.GetKey);
+        try
+            NewAssociation := TStringAssociation.Create(Mappable.GetKey, Item);
+            OldAssociation := TruePut(Position, NewAssociation);
+            if OldAssociation <> nil then
+                Result := OldAssociation.GetValue
+            else
+                Result := nil;
+        finally
+            Position.Free;
+        end;
+    end;
+end;
+
+function TAbstractStringMap.Put(const Key: String; const Item: ICollectable): ICollectable;
+var
+    OldAssociation, NewAssociation: IStringAssociation;
+    ItemError: TCollectionError;
+    Position: TCollectionPosition;
+begin
+    ItemError := ItemAllowed(Item);
+    if ItemError <> ceOK then
+    begin
+        CollectionError(ItemError);
+        Result := nil;
+    end
+    else
+    begin
+        Position := GetKeyPosition(Key);
+        try
+            NewAssociation := TStringAssociation.Create(Key, Item);
+            OldAssociation := TruePut(Position, NewAssociation);
+            if OldAssociation <> nil then
+                Result := OldAssociation.GetValue
+            else
+                Result := nil;
+        finally
+            Position.Free;
+        end;
+    end;
+end;
+
+function TAbstractStringMap.Put(const ItemArray: array of ICollectable): ICollection;
+var
+    ResultCollection: ICollection;
+    Mappable: IStringMappable;
+    OldAssociation, NewAssociation: IStringAssociation;
+    Position: TCollectionPosition;
+    Item: ICollectable;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(ItemArray) to High(ItemArray) do
+    begin
+        Item := ItemArray[I];
+        if not IsNaturalItem(Item) then
+        begin
+            CollectionError(ceNotNaturalItem);
+        end
+        else
+        begin
+            Item.QueryInterface(IStringMappable, Mappable);
+            Position := GetKeyPosition(Mappable.GetKey);
+            try
+                NewAssociation := TStringAssociation.Create(Mappable.GetKey, Item);
+                OldAssociation := TruePut(Position, NewAssociation);
+                if OldAssociation <> nil then
+                    ResultCollection.Add(OldAssociation.GetValue);
+            finally
+                Position.Free;
+            end;
+        end;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractStringMap.Put(const Collection: ICollection): ICollection;
+var
+    ResultCollection: ICollection;
+    Mappable: IStringMappable;
+    OldAssociation, NewAssociation: IStringAssociation;
+    Position: TCollectionPosition;
+    Iterator: IIterator;
+    Item: ICollectable;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    Iterator := Collection.GetIterator;
+    while not Iterator.EOF do
+    begin
+        Item := Iterator.CurrentItem;;
+        if not IsNaturalItem(Item) then
+        begin
+            CollectionError(ceNotNaturalItem);
+        end
+        else
+        begin
+            Item.QueryInterface(IStringMappable, Mappable);
+            Position := GetKeyPosition(Mappable.GetKey);
+            try
+                NewAssociation := TStringAssociation.Create(Mappable.GetKey, Item);
+                OldAssociation := TruePut(Position, NewAssociation);
+                if OldAssociation <> nil then
+                    ResultCollection.Add(OldAssociation.GetValue);
+            finally
+                Position.Free;
+            end;
+        end;
+        Iterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractStringMap.Put(const Map: IStringMap): ICollection;
+var
+    ResultCollection: ICollection;
+    OldAssociation, NewAssociation: IStringAssociation;
+    ItemError: TCollectionError;
+    Position: TCollectionPosition;
+    MapIterator: IStringMapIterator;
+    Item: ICollectable;
+    Key: String;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    MapIterator := Map.GetMapIterator;
+    while not MapIterator.EOF do
+    begin
+        Key := MapIterator.CurrentKey;
+        Item := MapIterator.CurrentItem;
+
+        ItemError := ItemAllowed(Item);
+        if ItemError <> ceOK then
+        begin
+            CollectionError(ItemError);
+        end
+        else
+        begin
+            Position := GetKeyPosition(Key);
+            try
+                NewAssociation := TStringAssociation.Create(Key, Item);
+                OldAssociation := TruePut(Position, NewAssociation);
+                if OldAssociation <> nil then
+                    ResultCollection.Add(OldAssociation.GetValue);
+            finally
+                Position.Free;
+            end;
+        end;
+        MapIterator.Next;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractStringMap.RemoveKey(const Key: String): ICollectable;
+var
+    Position: TCollectionPosition;
+    OldAssociation: IStringAssociation;
+begin
+    Position := GetKeyPosition(Key);
+    try
+        if Position.Found then
+        begin
+            OldAssociation := TrueRemove2(Position);
+            Result := OldAssociation.GetValue
+        end
+        else
+            Result := nil;
+    finally
+        Position.Free;
+    end;
+end;
+
+function TAbstractStringMap.RemoveKey(const KeyArray: array of String): ICollection;
+var
+    ResultCollection: ICollection;
+    OldAssociation: IStringAssociation;
+    Position: TCollectionPosition;
+    Key: String;
+    I: Integer;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    for I := Low(KeyArray) to High(KeyArray) do
+    begin
+        Key := KeyArray[I];
+        Position := GetKeyPosition(Key);
+        try
+            if Position.Found then
+            begin
+                OldAssociation := TrueRemove2(Position);
+                ResultCollection.Add(OldAssociation.GetValue);
+            end;
+        finally
+            Position.Free;
+        end;
+    end;
+    Result := ResultCollection;
+end;
+
+function TAbstractStringMap.RetainKey(const KeyArray: array of String): ICollection;
+var
+    ResultCollection: ICollection;
+    MapIterator: IStringMapIterator;
+    I: Integer;
+    Found: Boolean;
+begin
+    ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+    if FixedSize then
+    begin
+        CollectionError(ceFixedSize);
+    end
+    else
+    begin
+        MapIterator := GetMapIterator;
+        while not MapIterator.EOF do
+        begin
+            // Converting the array to a map would be faster but I don't want to
+            // couple base class code to a complex collection.
+            Found := false;
+            for I := Low(KeyArray) to High(KeyArray) do
+            begin
+                Found := (MapIterator.CurrentKey = KeyArray[I]);
+                if Found then
+                    break;
+            end;
+            if not Found then
+            begin
+                ResultCollection.Add(MapIterator.CurrentItem);
+                MapIterator.Remove;
+            end;
+            MapIterator.Next;
+        end;
+        Result := ResultCollection;
+    end;
+end;
+
+
+{ ECollectionError }
+constructor ECollectionError.Create(const Msg: String; const Collection: ICollection; ErrorType: TCollectionError);
+begin
+    inherited Create(Msg);
+    FCollection := Collection;
+    FErrorType := ErrorType;
+end;
+
+{ TAbstractListIterator }
+constructor TAbstractListIterator.Create(Collection: TAbstractList);
+begin
+    inherited Create(true);
+    FCollection := Collection;
+    First;
+end;
+
+function TAbstractListIterator.TrueFirst: ICollectable;
+begin
+    FIndex := 0;
+    if FIndex < FCollection.GetSize then
+        Result := FCollection.GetItem(FIndex)
+    else
+        Result := nil;
+end;
+
+function TAbstractListIterator.TrueNext: ICollectable;
+begin
+    Inc(FIndex);
+    if FIndex < FCollection.GetSize then
+        Result := FCollection.GetItem(FIndex)
+    else
+        Result := nil;
+end;
+
+procedure TAbstractListIterator.TrueRemove;
+begin
+    FCollection.Delete(FIndex);
+    Dec(FIndex);
+end;
+
+end.
diff --git a/songmanagement/src/lib/collections/readme.txt b/songmanagement/src/lib/collections/readme.txt
new file mode 100644
index 00000000..1f6477de
--- /dev/null
+++ b/songmanagement/src/lib/collections/readme.txt
@@ -0,0 +1,14 @@
+Delphi Collections by Matthew Greet
+http://www.warmachine.u-net.com/delphi_collections/
+
+Help files (MS .hlp format) at 
+http://www.warmachine.u-net.com/downloads/delphi_collections_1_0_help.zip
+
+Changes
+=====================
+2008-11-06  FPC compatibility fixes by UltraStar Deluxe Team
+2005-03-14  Maintenance release v1.0.5 - bug fix for sorted lists and functional tests checks unsorted and sorted lists.
+2004-10-14 	Maintenance release v1.0.4 - memory leak fixed.
+2004-06-12 	Maintenance release v1.0.3 - memory leak fixed, memory leak test, new Capacity property.
+2004-02-13 	Maintenance release v1.0.2 - expanded introduction and quick start sections in help file.
+2003-10-25 	Maintenance release v1.0.1 - packages and test harness no longer list unused packages.
\ No newline at end of file
diff --git a/songmanagement/src/lib/ctypes/ctypes.pas b/songmanagement/src/lib/ctypes/ctypes.pas
new file mode 100644
index 00000000..694552dc
--- /dev/null
+++ b/songmanagement/src/lib/ctypes/ctypes.pas
@@ -0,0 +1,72 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2004 by Marco van de Voort, member of the
+    Free Pascal development team
+
+    Implements C types for in header conversions
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+
+ **********************************************************************}
+
+unit ctypes;
+
+interface
+
+type
+  qword = int64;  // Keep h2pas "uses ctypes" headers working with delphi.
+
+  { the following type definitions are compiler dependant }
+  { and system dependant                                  }
+
+  cint8                  = shortint;           pcint8                 = ^cint8;
+  cuint8                 = byte;               pcuint8                = ^cuint8;
+  cchar                  = cint8;              pcchar                 = ^cchar;
+  cschar                 = cint8;              pcschar                = ^cschar;
+  cuchar                 = cuint8;             pcuchar                = ^cuchar;
+
+  cint16                 = smallint;           pcint16                = ^cint16;
+  cuint16                = word;               pcuint16               = ^cuint16;
+  cshort                 = cint16;             pcshort                = ^cshort;
+  csshort                = cint16;             pcsshort               = ^csshort;
+  cushort                = cuint16;            pcushort               = ^cushort;
+
+  cint32                 = longint;            pcint32                = ^cint32;
+  cuint32                = longword;           pcuint32               = ^cuint32;
+  cint                   = cint32;             pcint                  = ^cint;              { minimum range is : 32-bit    }
+  csint                  = cint32;             pcsint                 = ^csint;             { minimum range is : 32-bit    }
+  cuint                  = cuint32;            pcuint                 = ^cuint;             { minimum range is : 32-bit    }
+  csigned                = cint;               pcsigned               = ^csigned;
+  cunsigned              = cuint;              pcunsigned             = ^cunsigned;
+
+  cint64                 = int64;              pcint64                = ^cint64;
+  cuint64                = qword;              pcuint64               = ^cuint64;
+  clonglong              = cint64;             pclonglong             = ^clonglong;
+  cslonglong             = cint64;             pcslonglong            = ^cslonglong;
+  culonglong             = cuint64;            pculonglong            = ^culonglong;
+
+  cbool                  = longbool;           pcbool                 = ^cbool;
+
+{$if defined(cpu64) and not(defined(win64) and defined(cpux86_64))}
+  clong                  = int64;              pclong                 = ^clong;
+  cslong                 = int64;              pcslong                = ^cslong;
+  culong                 = qword;              pculong                = ^culong;
+{$else}
+  clong                  = longint;            pclong                 = ^clong;
+  cslong                 = longint;            pcslong                = ^cslong;
+  culong                 = cardinal;           pculong                = ^culong;
+{$ifend}
+
+  cfloat                 = single;             pcfloat                = ^cfloat;
+  cdouble                = double;             pcdouble               = ^cdouble;
+  clongdouble            = extended;           pclongdouble           = ^clongdouble;
+
+implementation
+
+end.
diff --git a/songmanagement/src/lib/ffmpeg/avcodec.pas b/songmanagement/src/lib/ffmpeg/avcodec.pas
new file mode 100644
index 00000000..0a436a48
--- /dev/null
+++ b/songmanagement/src/lib/ffmpeg/avcodec.pas
@@ -0,0 +1,5002 @@
+(*
+ * copyright (c) 2001 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * This is a part of Pascal porting of ffmpeg.
+ * - Originally by Victor Zinetz for Delphi and Free Pascal on Windows.
+ * - For Mac OS X, some modifications were made by The Creative CAT, denoted as CAT
+ *   in the source codes.
+ * - Changes and updates by the UltraStar Deluxe Team
+ *
+ * Conversion of libavcodec/avcodec.h
+ * Min. version: 51.16.0, revision  6577, Sat Oct  7 15:30:46 2006 UTC 
+ * Max. version: 52.86.1, revision 24882, Wed Aug 23 07:00:00 2010 CET
+ *
+ *)
+
+unit avcodec;
+
+{$IFDEF FPC}
+  {$MODE DELPHI }
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+  {$linklib libavcodec}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  avutil,
+  rational,
+  opt,
+  SysUtils,
+  {$IFDEF UNIX}
+  BaseUnix,
+  {$ENDIF}
+  UConfig;
+
+const
+  (*
+   * IMPORTANT: The official FFmpeg C headers change very quickly. Often some
+   * of the data structures are changed so that they become incompatible with
+   * older header files. The Pascal headers have to be adjusted to those changes,
+   * otherwise the application might crash randomly or strange bugs (not
+   * necessarily related to video or audio due to buffer overflows etc.) might
+   * occur.
+   *
+   * In the past users reported problems with USDX that took hours to fix and
+   * the problem was an unsupported version of FFmpeg. So we decided to disable
+   * support for future versions of FFmpeg until the headers are revised by us
+   * for that version as they otherwise most probably will break USDX.
+   *
+   * If the headers do not yet support your FFmpeg version you may want to
+   * adjust the max. version numbers manually but please note: it may work but
+   * in many cases it does not. The USDX team does NOT PROVIDE ANY SUPPORT
+   * for the game if the MAX. VERSION WAS CHANGED.
+   *
+   * The only safe way to support new versions of FFmpeg is to add the changes
+   * of the FFmpeg git repository C headers to the Pascal headers.
+   * You can accelerate this process by posting a patch with the git changes
+   * translated to Pascal to our bug tracker (please join our IRC chat before
+   * you start working on it). Simply adjusting the max. versions is NOT a valid
+   * fix. 
+   *)
+  (* Max. supported version by this header *)
+  LIBAVCODEC_MAX_VERSION_MAJOR   = 52;
+  LIBAVCODEC_MAX_VERSION_MINOR   = 86;
+  LIBAVCODEC_MAX_VERSION_RELEASE = 1;
+  LIBAVCODEC_MAX_VERSION = (LIBAVCODEC_MAX_VERSION_MAJOR * VERSION_MAJOR) +
+                           (LIBAVCODEC_MAX_VERSION_MINOR * VERSION_MINOR) +
+                           (LIBAVCODEC_MAX_VERSION_RELEASE * VERSION_RELEASE);
+
+  (* Min. supported version by this header *)
+  LIBAVCODEC_MIN_VERSION_MAJOR   = 51;
+  LIBAVCODEC_MIN_VERSION_MINOR   = 16;
+  LIBAVCODEC_MIN_VERSION_RELEASE = 0;
+  LIBAVCODEC_MIN_VERSION = (LIBAVCODEC_MIN_VERSION_MAJOR * VERSION_MAJOR) +
+                            (LIBAVCODEC_MIN_VERSION_MINOR * VERSION_MINOR) +
+                            (LIBAVCODEC_MIN_VERSION_RELEASE * VERSION_RELEASE);
+
+(* Check if linked versions are supported *)
+{$IF (LIBAVCODEC_VERSION < LIBAVCODEC_MIN_VERSION)}
+  {$MESSAGE Error 'Linked version of libavcodec is too old!'}
+{$IFEND}
+
+(* Check if linked version is supported *)
+{$IF (LIBAVCODEC_VERSION > LIBAVCODEC_MAX_VERSION)}
+  {$MESSAGE Error 'Linked version of libavcodec is not yet supported!'}
+{$IFEND}
+
+const
+  AV_NOPTS_VALUE: cint64  = $8000000000000000;
+  AV_TIME_BASE            = 1000000;
+  AV_TIME_BASE_Q: TAVRational = (num: 1; den: AV_TIME_BASE);
+
+(**
+ * Identify the syntax and semantics of the bitstream.
+ * The principle is roughly:
+ * Two decoders with the same ID can decode the same streams.
+ * Two encoders with the same ID can encode compatible streams.
+ * There may be slight deviations from the principle due to implementation
+ * details.
+ *
+ * If you add a codec ID to this list, add it so that
+ * 1. no value of a existing codec ID changes (that would break ABI),
+ * 2. it is as close as possible to similar codecs.
+ *)
+type
+  TCodecID = (
+    CODEC_ID_NONE,
+    
+    (* video codecs *)
+    CODEC_ID_MPEG1VIDEO,
+    CODEC_ID_MPEG2VIDEO, //* prefered ID for MPEG Video 1/2 decoding */
+    CODEC_ID_MPEG2VIDEO_XVMC,
+    CODEC_ID_H261,
+    CODEC_ID_H263,
+    CODEC_ID_RV10,
+    CODEC_ID_RV20,
+    CODEC_ID_MJPEG,
+    CODEC_ID_MJPEGB,
+    CODEC_ID_LJPEG,
+    CODEC_ID_SP5X,
+    CODEC_ID_JPEGLS,
+    CODEC_ID_MPEG4,
+    CODEC_ID_RAWVIDEO,
+    CODEC_ID_MSMPEG4V1,
+    CODEC_ID_MSMPEG4V2,
+    CODEC_ID_MSMPEG4V3,
+    CODEC_ID_WMV1,
+    CODEC_ID_WMV2,
+    CODEC_ID_H263P,
+    CODEC_ID_H263I,
+    CODEC_ID_FLV1,
+    CODEC_ID_SVQ1,
+    CODEC_ID_SVQ3,
+    CODEC_ID_DVVIDEO,
+    CODEC_ID_HUFFYUV,
+    CODEC_ID_CYUV,
+    CODEC_ID_H264,
+    CODEC_ID_INDEO3,
+    CODEC_ID_VP3,
+    CODEC_ID_THEORA,
+    CODEC_ID_ASV1,
+    CODEC_ID_ASV2,
+    CODEC_ID_FFV1,
+    CODEC_ID_4XM,
+    CODEC_ID_VCR1,
+    CODEC_ID_CLJR,
+    CODEC_ID_MDEC,
+    CODEC_ID_ROQ,
+    CODEC_ID_INTERPLAY_VIDEO,
+    CODEC_ID_XAN_WC3,
+    CODEC_ID_XAN_WC4,
+    CODEC_ID_RPZA,
+    CODEC_ID_CINEPAK,
+    CODEC_ID_WS_VQA,
+    CODEC_ID_MSRLE,
+    CODEC_ID_MSVIDEO1,
+    CODEC_ID_IDCIN,
+    CODEC_ID_8BPS,
+    CODEC_ID_SMC,
+    CODEC_ID_FLIC,
+    CODEC_ID_TRUEMOTION1,
+    CODEC_ID_VMDVIDEO,
+    CODEC_ID_MSZH,
+    CODEC_ID_ZLIB,
+    CODEC_ID_QTRLE,
+    CODEC_ID_SNOW,
+    CODEC_ID_TSCC,
+    CODEC_ID_ULTI,
+    CODEC_ID_QDRAW,
+    CODEC_ID_VIXL,
+    CODEC_ID_QPEG,
+{$IF LIBAVCODEC_VERSION_MAJOR < 53}
+    CODEC_ID_XVID,
+{$IFEND}
+    CODEC_ID_PNG,
+    CODEC_ID_PPM,
+    CODEC_ID_PBM,
+    CODEC_ID_PGM,
+    CODEC_ID_PGMYUV,
+    CODEC_ID_PAM,
+    CODEC_ID_FFVHUFF,
+    CODEC_ID_RV30,
+    CODEC_ID_RV40,
+    CODEC_ID_VC1,
+    CODEC_ID_WMV3,
+    CODEC_ID_LOCO,
+    CODEC_ID_WNV1,
+    CODEC_ID_AASC,
+    CODEC_ID_INDEO2,
+    CODEC_ID_FRAPS,
+    CODEC_ID_TRUEMOTION2,
+    CODEC_ID_BMP,
+    CODEC_ID_CSCD,
+    CODEC_ID_MMVIDEO,
+    CODEC_ID_ZMBV,
+    CODEC_ID_AVS,
+    CODEC_ID_SMACKVIDEO,
+    CODEC_ID_NUV,
+    CODEC_ID_KMVC,
+    CODEC_ID_FLASHSV,
+    CODEC_ID_CAVS,
+    CODEC_ID_JPEG2000,
+    CODEC_ID_VMNC,
+    CODEC_ID_VP5,
+    CODEC_ID_VP6,
+    CODEC_ID_VP6F,
+    CODEC_ID_TARGA,
+    CODEC_ID_DSICINVIDEO,
+    CODEC_ID_TIERTEXSEQVIDEO,
+    CODEC_ID_TIFF,
+    CODEC_ID_GIF,
+    CODEC_ID_FFH264,
+    CODEC_ID_DXA,
+    CODEC_ID_DNXHD,
+    CODEC_ID_THP,
+    CODEC_ID_SGI,
+    CODEC_ID_C93,
+    CODEC_ID_BETHSOFTVID,
+    CODEC_ID_PTX,
+    CODEC_ID_TXD,
+    CODEC_ID_VP6A,
+    CODEC_ID_AMV,
+    CODEC_ID_VB,
+    CODEC_ID_PCX,
+    CODEC_ID_SUNRAST,
+    CODEC_ID_INDEO4,
+    CODEC_ID_INDEO5,
+    CODEC_ID_MIMIC,
+    CODEC_ID_RL2,
+    CODEC_ID_8SVX_EXP,
+    CODEC_ID_8SVX_FIB,
+    CODEC_ID_ESCAPE124,
+    CODEC_ID_DIRAC,
+    CODEC_ID_BFI,
+    CODEC_ID_CMV,
+    CODEC_ID_MOTIONPIXELS,
+    CODEC_ID_TGV,
+    CODEC_ID_TGQ,
+{$IF LIBAVCODEC_VERSION >= 52012000}  // >= 52.12.0
+    CODEC_ID_TQI,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52022002}  // >= 52.22.2
+    CODEC_ID_AURA,
+    CODEC_ID_AURA2,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52027000}  // >= 52.27.0
+    CODEC_ID_V210X,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52028000}  // >= 52.28.0
+    CODEC_ID_TMV,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52029000}  // >= 52.29.0
+    CODEC_ID_V210,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52030002}  // >= 52.30.2
+    CODEC_ID_DPX,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52031002}  // >= 52.31.2
+    CODEC_ID_MAD,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52037000}  // >= 52.37.0
+    CODEC_ID_FRWU,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52041000}  // >= 52.41.0
+    CODEC_ID_FLASHSV2,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52043000}  // >= 52.43.0
+    CODEC_ID_CDGRAPHICS,
+    CODEC_ID_R210,
+{$IFEND}
+     CODEC_ID_ANM,
+{$IF LIBAVCODEC_VERSION >= 52049000}  // >= 52.49.0
+    CODEC_ID_BINKVIDEO,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52052000}  // >= 52.52.0
+    CODEC_ID_IFF_ILBM,
+    CODEC_ID_IFF_BYTERUN1,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52058000}  // >= 52.58.0
+    CODEC_ID_KGV1,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52062000}  // >= 52.62.0
+    CODEC_ID_YOP,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52067002}  // >= 52.67.2
+    CODEC_ID_VP8,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52075001}  // >= 52.75.1
+    CODEC_ID_PICTOR,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52084000}  // >= 52.84.0
+    CODEC_ID_ANSI,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52086001}  // >= 52.86.1
+    CODEC_ID_A64_MULTI,
+    CODEC_ID_A64_MULTI5,
+{$IFEND}
+
+    //* various PCM "codecs" */
+    CODEC_ID_PCM_S16LE= $10000,
+    CODEC_ID_PCM_S16BE,
+    CODEC_ID_PCM_U16LE,
+    CODEC_ID_PCM_U16BE,
+    CODEC_ID_PCM_S8,
+    CODEC_ID_PCM_U8,
+    CODEC_ID_PCM_MULAW,
+    CODEC_ID_PCM_ALAW,
+    CODEC_ID_PCM_S32LE,
+    CODEC_ID_PCM_S32BE,
+    CODEC_ID_PCM_U32LE,
+    CODEC_ID_PCM_U32BE,
+    CODEC_ID_PCM_S24LE,
+    CODEC_ID_PCM_S24BE,
+    CODEC_ID_PCM_U24LE,
+    CODEC_ID_PCM_U24BE,
+    CODEC_ID_PCM_S24DAUD,
+    CODEC_ID_PCM_ZORK,
+    CODEC_ID_PCM_S16LE_PLANAR,
+    CODEC_ID_PCM_DVD,
+    CODEC_ID_PCM_F32BE,
+    CODEC_ID_PCM_F32LE,
+    CODEC_ID_PCM_F64BE,
+    CODEC_ID_PCM_F64LE,
+{$IF LIBAVCODEC_VERSION >= 52034000} // >= 52.34.0
+    CODEC_ID_PCM_BLURAY,
+{$IFEND}
+
+    //* various ADPCM codecs */
+    CODEC_ID_ADPCM_IMA_QT= $11000,
+    CODEC_ID_ADPCM_IMA_WAV,
+    CODEC_ID_ADPCM_IMA_DK3,
+    CODEC_ID_ADPCM_IMA_DK4,
+    CODEC_ID_ADPCM_IMA_WS,
+    CODEC_ID_ADPCM_IMA_SMJPEG,
+    CODEC_ID_ADPCM_MS,
+    CODEC_ID_ADPCM_4XM,
+    CODEC_ID_ADPCM_XA,
+    CODEC_ID_ADPCM_ADX,
+    CODEC_ID_ADPCM_EA,
+    CODEC_ID_ADPCM_G726,
+    CODEC_ID_ADPCM_CT,
+    CODEC_ID_ADPCM_SWF,
+    CODEC_ID_ADPCM_YAMAHA,
+    CODEC_ID_ADPCM_SBPRO_4,
+    CODEC_ID_ADPCM_SBPRO_3,
+    CODEC_ID_ADPCM_SBPRO_2,
+    CODEC_ID_ADPCM_THP,
+    CODEC_ID_ADPCM_IMA_AMV,
+    CODEC_ID_ADPCM_EA_R1,
+    CODEC_ID_ADPCM_EA_R3,
+    CODEC_ID_ADPCM_EA_R2,
+    CODEC_ID_ADPCM_IMA_EA_SEAD,
+    CODEC_ID_ADPCM_IMA_EA_EACS,
+    CODEC_ID_ADPCM_EA_XAS,
+    CODEC_ID_ADPCM_EA_MAXIS_XA,
+    CODEC_ID_ADPCM_IMA_ISS,
+
+    //* AMR */
+    CODEC_ID_AMR_NB= $12000,
+    CODEC_ID_AMR_WB,
+
+    //* RealAudio codecs*/
+    CODEC_ID_RA_144= $13000,
+    CODEC_ID_RA_288,
+
+    //* various DPCM codecs */
+    CODEC_ID_ROQ_DPCM= $14000,
+    CODEC_ID_INTERPLAY_DPCM,
+    CODEC_ID_XAN_DPCM,
+    CODEC_ID_SOL_DPCM,
+
+    (* audio codecs *)
+    CODEC_ID_MP2= $15000,
+    CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3
+    CODEC_ID_AAC,
+    {$IF LIBAVCODEC_VERSION < 52000000} // < 52.0.0
+    _CODEC_ID_MPEG4AAC, // will be redefined to CODEC_ID_AAC below
+    {$IFEND}
+    CODEC_ID_AC3,
+    CODEC_ID_DTS,
+    CODEC_ID_VORBIS,
+    CODEC_ID_DVAUDIO,
+    CODEC_ID_WMAV1,
+    CODEC_ID_WMAV2,
+    CODEC_ID_MACE3,
+    CODEC_ID_MACE6,
+    CODEC_ID_VMDAUDIO,
+    CODEC_ID_SONIC,
+    CODEC_ID_SONIC_LS,
+    CODEC_ID_FLAC,
+    CODEC_ID_MP3ADU,
+    CODEC_ID_MP3ON4,
+    CODEC_ID_SHORTEN,
+    CODEC_ID_ALAC,
+    CODEC_ID_WESTWOOD_SND1,
+    CODEC_ID_GSM, ///< as in Berlin toast format
+    CODEC_ID_QDM2,
+    CODEC_ID_COOK,
+    CODEC_ID_TRUESPEECH,
+    CODEC_ID_TTA,
+    CODEC_ID_SMACKAUDIO,
+    CODEC_ID_QCELP,
+    CODEC_ID_WAVPACK,
+    CODEC_ID_DSICINAUDIO,
+    CODEC_ID_IMC,
+    CODEC_ID_MUSEPACK7,
+    CODEC_ID_MLP,
+    CODEC_ID_GSM_MS, { as found in WAV }
+    CODEC_ID_ATRAC3,
+    CODEC_ID_VOXWARE,
+    CODEC_ID_APE,
+    CODEC_ID_NELLYMOSER,
+    CODEC_ID_MUSEPACK8,
+    CODEC_ID_SPEEX,
+    CODEC_ID_WMAVOICE,
+    CODEC_ID_WMAPRO,
+    CODEC_ID_WMALOSSLESS,
+    CODEC_ID_ATRAC3P,
+    CODEC_ID_EAC3,
+    CODEC_ID_SIPR,
+    CODEC_ID_MP1,
+{$IF LIBAVCODEC_VERSION >= 52020000} // >= 52.20.0
+    CODEC_ID_TWINVQ,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52022000} // >= 52.22.0
+    CODEC_ID_TRUEHD,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52026000} // >= 52.26.0
+    CODEC_ID_MP4ALS,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52035000} // >= 52.35.0
+    CODEC_ID_ATRAC1,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52049000} // >= 52.49.0
+    CODEC_ID_BINKAUDIO_RDFT,
+    CODEC_ID_BINKAUDIO_DCT,
+{$IFEND}
+
+    //* subtitle codecs */
+    CODEC_ID_DVD_SUBTITLE= $17000,
+    CODEC_ID_DVB_SUBTITLE,
+    CODEC_ID_TEXT,  ///< raw UTF-8 text
+    CODEC_ID_XSUB,
+    CODEC_ID_SSA,
+    CODEC_ID_MOV_TEXT,
+{$IF LIBAVCODEC_VERSION >= 52033000} // >= 52.33.0
+    CODEC_ID_HDMV_PGS_SUBTITLE,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52037001} // >= 52.37.1
+    CODEC_ID_DVB_TELETEXT,
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52084001} // >= 52.84.1
+    CODEC_ID_SRT,
+{$IFEND}
+
+    (* other specific kind of codecs (generally used for attachments) *)
+    CODEC_ID_TTF= $18000,
+
+    CODEC_ID_PROBE= $19000, ///< codec_id is not known (like CODEC_ID_NONE) but lavf should attempt to identify it
+
+    CODEC_ID_MPEG2TS= $20000, {*< _FAKE_ codec to indicate a raw MPEG-2 TS
+                               * stream (only used by libavformat) *}
+    __CODEC_ID_4BYTE = $FFFFF  // ensure 4-byte enum
+  );
+
+{$IF LIBAVCODEC_VERSION < 52000000} // < 52.0.0
+{* CODEC_ID_MP3LAME is obsolete *}
+const
+  CODEC_ID_MP3LAME = CODEC_ID_MP3;
+  CODEC_ID_MPEG4AAC = CODEC_ID_AAC;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION_MAJOR < 53} // < 53.0.0
+type
+  TCodecType = (
+    CODEC_TYPE_UNKNOWN = -1,
+    CODEC_TYPE_VIDEO,
+    CODEC_TYPE_AUDIO,
+    CODEC_TYPE_DATA,
+    CODEC_TYPE_SUBTITLE,
+    CODEC_TYPE_ATTACHMENT,
+    CODEC_TYPE_NB
+  );
+{$IFEND}
+
+{
+  TAVMediaType moved to avutil in LIBAVUTIL_VERSION 50.14.0
+  but moving it in the pascal headers was not really necessary
+  but caused problems. So, I (KMS) left it here.
+}
+{$IF LIBAVCODEC_VERSION >= 52064000} // >= 52.64.0
+type
+  TAVMediaType = (
+    AVMEDIA_TYPE_UNKNOWN = -1,
+    AVMEDIA_TYPE_VIDEO,
+    AVMEDIA_TYPE_AUDIO,
+    AVMEDIA_TYPE_DATA,
+    AVMEDIA_TYPE_SUBTITLE,
+    AVMEDIA_TYPE_ATTACHMENT,
+    AVMEDIA_TYPE_NB
+  );
+{$IFEND}
+
+{**
+ * all in native endian
+ *}
+type
+  TSampleFormat = (
+    SAMPLE_FMT_NONE = -1,
+    SAMPLE_FMT_U8,              ///< unsigned 8 bits
+    SAMPLE_FMT_S16,             ///< signed 16 bits
+    SAMPLE_FMT_S32,             ///< signed 32 bits
+    SAMPLE_FMT_FLT,             ///< float
+    SAMPLE_FMT_DBL,             ///< double
+    SAMPLE_FMT_NB               ///< Number of sample formats. DO NOT USE if dynamically linking to libavcodec
+  );
+  _TSampleFormatArray = array [0 .. MaxInt div SizeOf(TSampleFormat)-1] of TSampleFormat;
+  PSampleFormatArray = ^_TSampleFormatArray;
+
+const
+  {* Audio channel masks *}
+  CH_FRONT_LEFT             = $00000001;
+  CH_FRONT_RIGHT            = $00000002;
+  CH_FRONT_CENTER           = $00000004;
+  CH_LOW_FREQUENCY          = $00000008;
+  CH_BACK_LEFT              = $00000010;
+  CH_BACK_RIGHT             = $00000020;
+  CH_FRONT_LEFT_OF_CENTER   = $00000040;
+  CH_FRONT_RIGHT_OF_CENTER  = $00000080;
+  CH_BACK_CENTER            = $00000100;
+  CH_SIDE_LEFT              = $00000200;
+  CH_SIDE_RIGHT             = $00000400;
+  CH_TOP_CENTER             = $00000800;
+  CH_TOP_FRONT_LEFT         = $00001000;
+  CH_TOP_FRONT_CENTER       = $00002000;
+  CH_TOP_FRONT_RIGHT        = $00004000;
+  CH_TOP_BACK_LEFT          = $00008000;
+  CH_TOP_BACK_CENTER        = $00010000;
+  CH_TOP_BACK_RIGHT         = $00020000;
+  CH_STEREO_LEFT            = $20000000;  ///< Stereo downmix.
+  CH_STEREO_RIGHT           = $40000000;  ///< See CH_STEREO_LEFT.
+{** Channel mask value used for AVCodecContext.request_channel_layout
+ *  to indicate that the user requests the channel order of the decoder output
+ *  to be the native codec channel order.
+ *}
+{$IF LIBAVCODEC_VERSION >= 52038001} // >= 52.38.1
+  CH_LAYOUT_NATIVE          = $8000000000000000;
+{$IFEND}
+
+  {* Audio channel convenience macros *}
+  CH_LAYOUT_MONO            = (CH_FRONT_CENTER);
+  CH_LAYOUT_STEREO          = (CH_FRONT_LEFT or CH_FRONT_RIGHT);
+  CH_LAYOUT_SURROUND        = (CH_LAYOUT_STEREO or CH_FRONT_CENTER);
+{$IF LIBAVCODEC_VERSION >= 52027000} // >= 52.27.0
+  CH_LAYOUT_2_1             = (CH_LAYOUT_STEREO or CH_BACK_CENTER);
+  CH_LAYOUT_4POINT0         = (CH_LAYOUT_SURROUND or CH_BACK_CENTER);
+  CH_LAYOUT_2_2             = (CH_LAYOUT_STEREO or CH_SIDE_LEFT or CH_SIDE_RIGHT);
+{$IFEND}
+  CH_LAYOUT_QUAD            = (CH_LAYOUT_STEREO or CH_BACK_LEFT or CH_BACK_RIGHT);
+  CH_LAYOUT_5POINT0         = (CH_LAYOUT_SURROUND or CH_SIDE_LEFT or CH_SIDE_RIGHT);
+  CH_LAYOUT_5POINT1         = (CH_LAYOUT_5POINT0 or CH_LOW_FREQUENCY);
+{$IF LIBAVCODEC_VERSION >= 52025000} // >= 52.25.0
+  CH_LAYOUT_5POINT0_BACK    = (CH_LAYOUT_SURROUND or CH_BACK_LEFT or 
+                               CH_BACK_RIGHT);
+  CH_LAYOUT_5POINT1_BACK    = (CH_LAYOUT_5POINT0_BACK or CH_LOW_FREQUENCY);
+{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52034000} // >= 52.34.0
+  CH_LAYOUT_7POINT0         = (CH_LAYOUT_5POINT0 or CH_BACK_LEFT or CH_BACK_RIGHT);
+{$IFEND}
+  CH_LAYOUT_7POINT1         = (CH_LAYOUT_5POINT1 or CH_BACK_LEFT or CH_BACK_RIGHT);
+{$IF LIBAVCODEC_VERSION < 52025000} // < 52.25.0
+  CH_LAYOUT_7POINT1_WIDE    = (CH_LAYOUT_SURROUND or CH_LOW_FREQUENCY or
+                               CH_BACK_LEFT or CH_BACK_RIGHT or
+{$ELSE}
+  CH_LAYOUT_7POINT1_WIDE    = (CH_LAYOUT_5POINT1_BACK or 
+{$IFEND}
+                               CH_FRONT_LEFT_OF_CENTER or
+                               CH_FRONT_RIGHT_OF_CENTER);
+  CH_LAYOUT_STEREO_DOWNMIX  = (CH_STEREO_LEFT or CH_STEREO_RIGHT);
+
+{* in bytes *}
+  AVCODEC_MAX_AUDIO_FRAME_SIZE = 192000; // 1 second of 48khz 32bit audio
+
+{$IF LIBAVCODEC_VERSION <= 52056000} // <= 52.56.0
+{**
+ * Required number of additionally allocated bytes at the end of the input bitstream for decoding.
+ * This is mainly needed because some optimized bitstream readers read
+ * 32 or 64 bit at once and could read over the end.<br>
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged
+ * MPEG bitstreams could cause overread and segfault.
+ *}
+  FF_INPUT_BUFFER_PADDING_SIZE = 8;
+{$ELSEIF LIBAVCODEC_VERSION < 52058000} // < 52.58.0
+{**
+ * Required number of additionally allocated bytes at the end of the input bitstream for decoding.
+ * The first 8 bytes are needed because some optimized bitstream readers read
+ * 32 or 64 bit at once and could read over the end. The remainder is to give
+ * decoders a reasonable amount of distance to work with before checking for
+ * buffer overreads.<br>
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged
+ * MPEG bitstreams could cause overread and segfault.
+ *}
+  FF_INPUT_BUFFER_PADDING_SIZE = 64;
+{$ELSE} // >= 52.58.0}
+{**
+ * Required number of additionally allocated bytes at the end of the input bitstream for decoding.
+ * This is mainly needed because some optimized bitstream readers read
+ * 32 or 64 bit at once and could read over the end.<br>
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged
+ * MPEG bitstreams could cause overread and segfault.
+ *}
+  FF_INPUT_BUFFER_PADDING_SIZE = 8;
+{$IFEND}
+
+{**
+ * minimum encoding buffer size.
+ * Used to avoid some checks during header writing.
+ *}
+  FF_MIN_BUFFER_SIZE = 16384;
+
+type
+{*
+ * motion estimation type.
+ *}
+  TMotion_Est_ID = (
+    ME_ZERO = 1,  ///< no search, that is use 0,0 vector whenever one is needed
+    ME_FULL,
+    ME_LOG,
+    ME_PHODS,
+    ME_EPZS,      ///< enhanced predictive zonal search
+    ME_X1,        ///< reserved for experiments
+    ME_HEX,       ///< hexagon based search
+    ME_UMH,       ///< uneven multi-hexagon search
+    ME_ITER,      ///< iterative search
+    ME_TESA       ///< transformed exhaustive search algorithm
+  );
+
+  TAVDiscard = (
+    {* We leave some space between them for extensions (drop some
+     * keyframes for intra-only or drop just some bidir frames).
+     *}
+    AVDISCARD_NONE    = -16, ///< discard nothing
+    AVDISCARD_DEFAULT =   0, ///< discard useless packets like 0 size packets in avi
+    AVDISCARD_NONREF  =   8, ///< discard all non reference
+    AVDISCARD_BIDIR   =  16, ///< discard all bidirectional frames
+    AVDISCARD_NONKEY  =  32, ///< discard all frames except keyframes
+    AVDISCARD_ALL     =  48  ///< discard all
+  );
+
+{$IF LIBAVCODEC_VERSION >= 52028000} // >= 52.28.0
+  TAVColorPrimaries = (
+    AVCOL_PRI_BT709       = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B
+    AVCOL_PRI_UNSPECIFIED = 2,
+    AVCOL_PRI_BT470M      = 4,
+    AVCOL_PRI_BT470BG     = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM
+    AVCOL_PRI_SMPTE170M   = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
+    AVCOL_PRI_SMPTE240M   = 7, ///< functionally identical to above
+    AVCOL_PRI_FILM        = 8,
+    AVCOL_PRI_NB               ///< Not part of ABI
+  );
+
+  TAVColorTransferCharacteristic = (
+    AVCOL_TRC_BT709       = 1, ///< also ITU-R BT1361
+    AVCOL_TRC_UNSPECIFIED = 2,
+    AVCOL_TRC_GAMMA22     = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
+    AVCOL_TRC_GAMMA28     = 5, ///< also ITU-R BT470BG
+    AVCOL_TRC_NB               ///< Not part of ABI
+  );
+
+  TAVColorSpace = (
+    AVCOL_SPC_RGB         = 0,
+    AVCOL_SPC_BT709       = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B
+    AVCOL_SPC_UNSPECIFIED = 2,
+    AVCOL_SPC_FCC         = 4,
+    AVCOL_SPC_BT470BG     = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
+    AVCOL_SPC_SMPTE170M   = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
+    AVCOL_SPC_SMPTE240M   = 7,
+    AVCOL_SPC_NB               ///< Not part of ABI
+  );
+
+  TAVColorRange = (
+    AVCOL_RANGE_UNSPECIFIED = 0,
+    AVCOL_RANGE_MPEG        = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges
+    AVCOL_RANGE_JPEG        = 2, ///< the normal     2^n-1   "JPEG" YUV ranges
+    AVCOL_RANGE_NB               ///< Not part of ABI
+  );
+
+(**
+ *  X   X      3 4 X      X are luma samples,
+ *             1 2        1-6 are possible chroma positions
+ *  X   X      5 6 X      0 is undefined/unknown position
+ *)
+  TAVChromaLocation = (
+    AVCHROMA_LOC_UNSPECIFIED = 0,
+    AVCHROMA_LOC_LEFT        = 1, ///< mpeg2/4, h264 default
+    AVCHROMA_LOC_CENTER      = 2, ///< mpeg1, jpeg, h263
+    AVCHROMA_LOC_TOPLEFT     = 3, ///< DV
+    AVCHROMA_LOC_TOP         = 4,
+    AVCHROMA_LOC_BOTTOMLEFT  = 5,
+    AVCHROMA_LOC_BOTTOM      = 6,
+    AVCHROMA_LOC_NB               ///< Not part of ABI
+  );
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52083000} // >= 52.83.0
+(**
+ * LPC analysis type
+ *)
+  TAVLPCType = (
+    AV_LPC_TYPE_DEFAULT     = -1, ///< use the codec default LPC type
+    AV_LPC_TYPE_NONE        =  0, ///< do not use LPC prediction or use all zero coefficients
+    AV_LPC_TYPE_FIXED       =  1, ///< fixed LPC coefficients
+    AV_LPC_TYPE_LEVINSON    =  2, ///< Levinson-Durbin recursion
+    AV_LPC_TYPE_CHOLESKY    =  3, ///< Cholesky factorization
+    AV_LPC_TYPE_NB                ///< Not part of ABI
+  );
+{$IFEND}
+
+  PRcOverride = ^TRcOverride;
+  TRcOverride = record {16}
+    start_frame:    cint;
+    end_frame:      cint;
+    qscale:         cint; // if this is 0 then quality_factor will be used instead
+    quality_factor: cfloat;
+  end;
+
+const
+  FF_MAX_B_FRAMES = 16;
+
+{* encoding support
+   These flags can be passed in AVCodecContext.flags before initialization.
+   Note: Not everything is supported yet.
+*}
+
+  CODEC_FLAG_QSCALE = $0002;  ///< Use fixed qscale.
+  CODEC_FLAG_4MV    = $0004;  ///< 4 MV per MB allowed / advanced prediction for H263.
+  CODEC_FLAG_QPEL   = $0010;  ///< use qpel MC.
+  CODEC_FLAG_GMC    = $0020;  ///< use GMC.
+  CODEC_FLAG_MV0    = $0040;  ///< always try a MB with MV=<0,0>.
+  CODEC_FLAG_PART   = $0080;  ///< Use data partitioning.
+  {**
+   * The parent program guarantees that the input for B-frames containing
+   * streams is not written to for at least s->max_b_frames+1 frames, if
+   * this is not set the input will be copied.
+   *}
+  CODEC_FLAG_INPUT_PRESERVED    = $0100;
+  CODEC_FLAG_PASS1              = $0200; ///< use internal 2pass ratecontrol in first  pass mode
+  CODEC_FLAG_PASS2              = $0400; ///< use internal 2pass ratecontrol in second pass mode
+  CODEC_FLAG_EXTERN_HUFF        = $1000; ///< use external huffman table (for mjpeg)
+  CODEC_FLAG_GRAY               = $2000; ///< only decode/encode grayscale
+  CODEC_FLAG_EMU_EDGE           = $4000; ///< don't draw edges
+  CODEC_FLAG_PSNR               = $8000; ///< error[?] variables will be set during encoding
+  CODEC_FLAG_TRUNCATED      = $00010000; //** input bitstream might be truncated at a random location instead
+                                   //         of only at frame boundaries */
+  CODEC_FLAG_NORMALIZE_AQP  = $00020000; ///< normalize adaptive quantization
+  CODEC_FLAG_INTERLACED_DCT = $00040000; ///< use interlaced dct
+  CODEC_FLAG_LOW_DELAY      = $00080000; ///< force low delay
+  CODEC_FLAG_ALT_SCAN       = $00100000; ///< use alternate scan
+  {$IF LIBAVCODEC_VERSION < 52000000} // < 52.0.0
+  CODEC_FLAG_TRELLIS_QUANT  = $00200000; ///< use trellis quantization
+  {$IFEND}
+  CODEC_FLAG_GLOBAL_HEADER  = $00400000; ///< place global headers in extradata instead of every keyframe
+  CODEC_FLAG_BITEXACT       = $00800000; ///< use only bitexact stuff (except (i)dct)
+  {* Fx : Flag for h263+ extra options *}
+  {$IF LIBAVCODEC_VERSION < 52000000} // < 52.0.0
+  CODEC_FLAG_H263P_AIC      = $01000000; ///< H263 Advanced intra coding / MPEG4 AC prediction (remove this)
+  {$IFEND}
+  CODEC_FLAG_AC_PRED        = $01000000; ///< H263 Advanced intra coding / MPEG4 AC prediction
+  CODEC_FLAG_H263P_UMV      = $02000000; ///< Unlimited motion vector
+  CODEC_FLAG_CBP_RD         = $04000000; ///< use rate distortion optimization for cbp
+  CODEC_FLAG_QP_RD          = $08000000; ///< use rate distortion optimization for qp selectioon
+  CODEC_FLAG_H263P_AIV      = $00000008; ///< H263 Alternative inter vlc
+  CODEC_FLAG_OBMC           = $00000001; ///< OBMC
+  CODEC_FLAG_LOOP_FILTER    = $00000800; ///< loop filter
+  CODEC_FLAG_H263P_SLICE_STRUCT = $10000000;
+  CODEC_FLAG_INTERLACED_ME  = $20000000; ///< interlaced motion estimation
+  CODEC_FLAG_SVCD_SCAN_OFFSET = $40000000; ///< will reserve space for SVCD scan offset user data
+  CODEC_FLAG_CLOSED_GOP     = $80000000;
+  CODEC_FLAG2_FAST          = $00000001; ///< allow non spec compliant speedup tricks
+  CODEC_FLAG2_STRICT_GOP    = $00000002; ///< strictly enforce GOP size
+  CODEC_FLAG2_NO_OUTPUT     = $00000004; ///< skip bitstream encoding
+  CODEC_FLAG2_LOCAL_HEADER  = $00000008; ///< place global headers at every keyframe instead of in extradata
+  CODEC_FLAG2_BPYRAMID      = $00000010; ///< H.264 allow b-frames to be used as references
+  CODEC_FLAG2_WPRED         = $00000020; ///< H.264 weighted biprediction for b-frames
+  CODEC_FLAG2_MIXED_REFS    = $00000040; ///< H.264 multiple references per partition
+  CODEC_FLAG2_8X8DCT        = $00000080; ///< H.264 high profile 8x8 transform
+  CODEC_FLAG2_FASTPSKIP     = $00000100; ///< H.264 fast pskip
+  CODEC_FLAG2_AUD           = $00000200; ///< H.264 access unit delimiters
+  CODEC_FLAG2_BRDO          = $00000400; ///< b-frame rate-distortion optimization
+  CODEC_FLAG2_INTRA_VLC     = $00000800; ///< use MPEG-2 intra VLC table
+  CODEC_FLAG2_MEMC_ONLY     = $00001000; ///< only do ME/MC (I frames -> ref, P frame -> ME+MC)
+  CODEC_FLAG2_DROP_FRAME_TIMECODE = $00002000; ///< timecode is in drop frame format.
+  CODEC_FLAG2_SKIP_RD       = $00004000; ///< RD optimal MB level residual skipping
+  CODEC_FLAG2_CHUNKS        = $00008000; ///< Input bitstream might be truncated at a packet boundaries instead of only at frame boundaries.
+  CODEC_FLAG2_NON_LINEAR_QUANT = $00010000; ///< Use MPEG-2 nonlinear quantizer.
+  CODEC_FLAG2_BIT_RESERVOIR = $00020000; ///< Use a bit reservoir when encoding if possible
+  {$IF LIBAVCODEC_VERSION >= 52043000}   // >= 52.43.0  
+  CODEC_FLAG2_MBTREE        = $00040000; ///< Use macroblock tree ratecontrol (x264 only)
+  {$IFEND}
+  {$IF LIBAVCODEC_VERSION >= 52061000}   // >= 52.61.0  
+  CODEC_FLAG2_PSY           = $00080000; ///< Use psycho visual optimizations.
+  CODEC_FLAG2_SSIM          = $00100000; ///< Compute SSIM during encoding, error[] values are undefined.
+  {$IFEND}
+  {$IF LIBAVCODEC_VERSION >= 52067000}   // >= 52.67.0  
+  CODEC_FLAG2_INTRA_REFRESH = $00200000; ///< Use periodic insertion of intra blocks instead of keyframes.
+  {$IFEND}
+
+(* Unsupported options :
+ *              Syntax Arithmetic coding (SAC)
+ *              Reference Picture Selection
+ *              Independant Segment Decoding *)
+(* /Fx *)
+(* codec capabilities *)
+
+  CODEC_CAP_DRAW_HORIZ_BAND = $0001; ///< decoder can use draw_horiz_band callback
+  (**
+   * Codec uses get_buffer() for allocating buffers and supports custom allocators.
+   * If not set, it might not use get_buffer() at all or use operations that
+   * assume the buffer was allocated by avcodec_default_get_buffer.
+   *)
+  CODEC_CAP_DR1             = $0002;
+  (* if 'parse_only' field is true, then avcodec_parse_frame() can be used *)
+  CODEC_CAP_PARSE_ONLY      = $0004;
+  CODEC_CAP_TRUNCATED       = $0008;
+  (* codec can export data for HW decoding (XvMC) *)
+  CODEC_CAP_HWACCEL         = $0010;
+  (**
+   * codec has a non zero delay and needs to be feeded with NULL at the end to get the delayed data.
+   * if this is not set, the codec is guranteed to never be feeded with NULL data
+   *)
+  CODEC_CAP_DELAY           = $0020;
+  (**
+   * Codec can be fed a final frame with a smaller size.
+   * This can be used to prevent truncation of the last audio samples.
+   *)
+  CODEC_CAP_SMALL_LAST_FRAME = $0040;
+
+  (**
+   * Codec can export data for HW decoding (VDPAU).
+   *)
+  CODEC_CAP_HWACCEL_VDPAU    = $0080;
+
+  {$IF LIBAVCODEC_VERSION >= 52035000} // >= 52.35.0
+  (**
+   * Codec can output multiple frames per AVPacket
+   * Normally demuxers return one frame at a time, demuxers which do not do
+   * are connected to a parser to split what they return into proper frames.
+   * This flag is reserved to the very rare category of codecs which have a
+   * bitstream that cannot be split into frames without timeconsuming
+   * operations like full decoding. Demuxers carring such bitstreams thus
+   * may return multiple frames in a packet. This has many disadvantages like
+   * prohibiting stream copy in many cases thus it should only be considered
+   * as a last resort.
+   *)
+  CODEC_CAP_SUBFRAMES        = $0100;
+  {$IFEND}
+
+  {$IF LIBAVCODEC_VERSION >= 52071000} // >= 52.71.0
+  (**
+   * Codec is experimental and is thus avoided in favor of non experimental
+   * encoders
+   *)
+  CODEC_CAP_EXPERIMENTAL     = $0200;
+  {$IFEND}
+
+   //the following defines may change, don't expect compatibility if you use them
+   MB_TYPE_INTRA4x4   = $001;
+   MB_TYPE_INTRA16x16 = $002; //FIXME h264 specific
+   MB_TYPE_INTRA_PCM  = $004; //FIXME h264 specific
+   MB_TYPE_16x16      = $008;
+   MB_TYPE_16x8       = $010;
+   MB_TYPE_8x16       = $020;
+   MB_TYPE_8x8        = $040;
+   MB_TYPE_INTERLACED = $080;
+   MB_TYPE_DIRECT2     = $100; //FIXME
+   MB_TYPE_ACPRED     = $200;
+   MB_TYPE_GMC        = $400;
+   MB_TYPE_SKIP       = $800;
+   MB_TYPE_P0L0       = $1000;
+   MB_TYPE_P1L0       = $2000;
+   MB_TYPE_P0L1       = $4000;
+   MB_TYPE_P1L1       = $8000;
+   MB_TYPE_L0         = (MB_TYPE_P0L0 or MB_TYPE_P1L0);
+   MB_TYPE_L1         = (MB_TYPE_P0L1 or MB_TYPE_P1L1);
+   MB_TYPE_L0L1       = (MB_TYPE_L0   or MB_TYPE_L1);
+   MB_TYPE_QUANT      = $0010000;
+   MB_TYPE_CBP        = $0020000;
+   //Note bits 24-31 are reserved for codec specific use (h264 ref0, mpeg1 0mv, ...)
+
+type
+(**
+ * Pan Scan area.
+ * This specifies the area which should be displayed.
+ * Note there may be multiple such areas for one frame.
+ *)
+  PAVPanScan = ^TAVPanScan;
+  TAVPanScan = record {24}
+    (*** id.
+     * - encoding: set by user.
+     * - decoding: set by libavcodec. *)
+    id: cint;
+
+    (*** width and height in 1/16 pel
+     * - encoding: set by user.
+     * - decoding: set by libavcodec. *)
+    width: cint;
+    height: cint;
+
+    (*** position of the top left corner in 1/16 pel for up to 3 fields/frames.
+     * - encoding: set by user.
+     * - decoding: set by libavcodec. *)
+    position: array [0..2] of array [0..1] of smallint;
+  end;
+
+const
+  FF_QSCALE_TYPE_MPEG1  = 0;
+  FF_QSCALE_TYPE_MPEG2  = 1;
+  FF_QSCALE_TYPE_H264   = 2;
+  {$IF LIBAVCODEC_VERSION >= 52049000} // >= 52.49.0
+  FF_QSCALE_TYPE_VP56   = 3;
+  {$IFEND}
+
+  FF_BUFFER_TYPE_INTERNAL = 1;
+  FF_BUFFER_TYPE_USER     = 2; ///< Direct rendering buffers (image is (de)allocated by user)
+  FF_BUFFER_TYPE_SHARED   = 4; ///< buffer from somewhere else, don't dealloc image (data/base), all other tables are not shared
+  FF_BUFFER_TYPE_COPY     = 8; ///< just a (modified) copy of some other buffer, don't dealloc anything.
+
+
+  FF_I_TYPE  = 1; ///< Intra
+  FF_P_TYPE  = 2; ///< Predicted
+  FF_B_TYPE  = 3; ///< Bi-dir predicted
+  FF_S_TYPE  = 4; ///< S(GMC)-VOP MPEG4
+  FF_SI_TYPE = 5; ///< Switching Intra
+  FF_SP_TYPE = 6; ///< Switching Predicted
+  FF_BI_TYPE = 7;
+
+  FF_BUFFER_HINTS_VALID    = $01; // Buffer hints value is meaningful (if 0 ignore)
+  FF_BUFFER_HINTS_READABLE = $02; // Codec will read from buffer
+  FF_BUFFER_HINTS_PRESERVE = $04; // User must not alter buffer content
+  FF_BUFFER_HINTS_REUSABLE = $08; // Codec will reuse the buffer (update)
+
+const
+  {$IF LIBAVCODEC_VERSION < 52000000} // < 52.0.0
+  DEFAULT_FRAME_RATE_BASE = 1001000;
+  {$IFEND}
+
+  FF_ASPECT_EXTENDED = 15;
+
+  FF_RC_STRATEGY_XVID = 1;
+
+  FF_BUG_AUTODETECT       = 1;  ///< autodetection
+  FF_BUG_OLD_MSMPEG4      = 2;
+  FF_BUG_XVID_ILACE       = 4;
+  FF_BUG_UMP4             = 8;
+  FF_BUG_NO_PADDING       = 16;
+  FF_BUG_AMV              = 32;
+  FF_BUG_AC_VLC           = 0;  ///< will be removed, libavcodec can now handle these non compliant files by default
+  FF_BUG_QPEL_CHROMA      = 64;
+  FF_BUG_STD_QPEL         = 128;
+  FF_BUG_QPEL_CHROMA2     = 256;
+  FF_BUG_DIRECT_BLOCKSIZE = 512;
+  FF_BUG_EDGE             = 1024;
+  FF_BUG_HPEL_CHROMA      = 2048;
+  FF_BUG_DC_CLIP          = 4096;
+  FF_BUG_MS               = 8192; ///< workaround various bugs in microsofts broken decoders
+  {$IF LIBAVCODEC_VERSION >= 52054000} // >= 52.54.0
+  FF_BUG_TRUNCATED        = 16384;
+  {$IFEND}
+  //FF_BUG_FAKE_SCALABILITY = 16 //Autodetection should work 100%.
+
+  FF_COMPLIANCE_VERY_STRICT   =  2; ///< strictly conform to an older more strict version of the spec or reference software
+  FF_COMPLIANCE_STRICT        =  1; ///< strictly conform to all the things in the spec no matter what consequences
+  FF_COMPLIANCE_NORMAL        =  0;
+  {$IF LIBAVCODEC_VERSION_MAJOR < 53} // < 53
+  FF_COMPLIANCE_INOFFICIAL    = -1; ///< Allow inofficial extensions
+  {$IFEND}
+  {$IF LIBAVCODEC_VERSION >= 52079001} // >= 52.79.1
+  FF_COMPLIANCE_UNOFFICIAL    = -1; ///< Allow unofficial extensions
+  {$IFEND}
+
+  FF_COMPLIANCE_EXPERIMENTAL  = -2; ///< allow non standarized experimental things
+
+  FF_ER_CAREFUL         = 1;
+  FF_ER_COMPLIANT       = 2;
+  FF_ER_AGGRESSIVE      = 3;
+  FF_ER_VERY_AGGRESSIVE = 4;
+
+  FF_DCT_AUTO    = 0;
+  FF_DCT_FASTINT = 1;
+  FF_DCT_INT     = 2;
+  FF_DCT_MMX     = 3;
+  FF_DCT_MLIB    = 4;
+  FF_DCT_ALTIVEC = 5;
+  FF_DCT_FAAN    = 6;
+
+  FF_IDCT_AUTO         = 0;
+  FF_IDCT_INT          = 1;
+  FF_IDCT_SIMPLE       = 2;
+  FF_IDCT_SIMPLEMMX    = 3;
+  FF_IDCT_LIBMPEG2MMX  = 4;
+  FF_IDCT_PS2          = 5;
+  FF_IDCT_MLIB         = 6;
+  FF_IDCT_ARM          = 7;
+  FF_IDCT_ALTIVEC      = 8;
+  FF_IDCT_SH4          = 9;
+  FF_IDCT_SIMPLEARM    = 10;
+  FF_IDCT_H264         = 11;
+  FF_IDCT_VP3          = 12;
+  FF_IDCT_IPP          = 13;
+  FF_IDCT_XVIDMMX      = 14;
+  FF_IDCT_CAVS         = 15;
+  FF_IDCT_SIMPLEARMV5TE= 16;
+  FF_IDCT_SIMPLEARMV6  = 17;
+  FF_IDCT_SIMPLEVIS    = 18;
+  FF_IDCT_WMV2         = 19;
+  FF_IDCT_FAAN         = 20;
+  FF_IDCT_EA           = 21;
+  FF_IDCT_SIMPLENEON   = 22;
+  FF_IDCT_SIMPLEALPHA  = 23;
+  {$IF LIBAVCODEC_VERSION >= 52055000} // >= 52.55.0
+  FF_IDCT_BINK         = 24;
+  {$IFEND}
+
+  FF_EC_GUESS_MVS   = 1;
+  FF_EC_DEBLOCK     = 2;
+
+  FF_MM_FORCE       = $80000000; (* force usage of selected flags (OR) *)
+  (* lower 16 bits - CPU features *)
+  FF_MM_MMX         = $0001; ///< standard MMX
+  FF_MM_3DNOW       = $0004; ///< AMD 3DNOW
+  {$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+  FF_MM_MMXEXT      = $0002; ///< SSE integer functions or AMD MMX ext
+  {$IFEND}
+  {$IF LIBAVCODEC_VERSION >= 52024000} // >= 52.24.0
+  FF_MM_MMX2        = $0002; ///< SSE integer functions or AMD MMX ext
+  {$IFEND}
+  FF_MM_SSE         = $0008; ///< SSE functions
+  FF_MM_SSE2        = $0010; ///< PIV SSE2 functions
+  {$IF LIBAVCODEC_VERSION >= 52084000} // >= 52.84.0
+  FF_MM_SSE2SLOW    = $40000000; ///< SSE2 supported, but usually not faster
+                                 ///< than regular MMX/SSE (e.g. Core1)
+  {$IFEND}
+  FF_MM_3DNOWEXT    = $0020; ///< AMD 3DNowExt
+  FF_MM_SSE3        = $0040; ///< Prescott SSE3 functions
+  {$IF LIBAVCODEC_VERSION >= 52084000} // >= 52.84.0
+  FF_MM_SSE3SLOW    = $20000000; ///< SSE3 supported, but usually not faster
+                                 ///< than regular MMX/SSE (e.g. Core1)
+  {$IFEND}
+  FF_MM_SSSE3       = $0080; ///< Conroe SSSE3 functions
+  {$IF LIBAVCODEC_VERSION >= 52022003} // >= 52.22.3
+  FF_MM_SSE4        = $0100; ///< Penryn SSE4.1 functions
+  FF_MM_SSE42       = $0200; ///< Nehalem SSE4.2 functions
+  {$IFEND}
+  FF_MM_IWMMXT      = $0100; ///< XScale IWMMXT
+  FF_MM_ALTIVEC     = $0001; ///< standard AltiVec
+
+  FF_PRED_LEFT   = 0;
+  FF_PRED_PLANE  = 1;
+  FF_PRED_MEDIAN = 2;
+
+  FF_DEBUG_PICT_INFO    = 1;
+  FF_DEBUG_RC           = 2;
+  FF_DEBUG_BITSTREAM    = 4;
+  FF_DEBUG_MB_TYPE      = 8;
+  FF_DEBUG_QP           = 16;
+  FF_DEBUG_MV           = 32;
+  FF_DEBUG_DCT_COEFF    = $00000040;
+  FF_DEBUG_SKIP         = $00000080;
+  FF_DEBUG_STARTCODE    = $00000100;
+  FF_DEBUG_PTS          = $00000200;
+  FF_DEBUG_ER           = $00000400;
+  FF_DEBUG_MMCO         = $00000800;
+  FF_DEBUG_BUGS         = $00001000;
+  FF_DEBUG_VIS_QP       = $00002000;
+  FF_DEBUG_VIS_MB_TYPE  = $00004000;
+  FF_DEBUG_BUFFERS      = $00008000;
+
+  FF_DEBUG_VIS_MV_P_FOR  = $00000001; //visualize forward predicted MVs of P frames
+  FF_DEBUG_VIS_MV_B_FOR  = $00000002; //visualize forward predicted MVs of B frames
+  FF_DEBUG_VIS_MV_B_BACK = $00000004; //visualize backward predicted MVs of B frames
+
+  FF_CMP_SAD    = 0;
+  FF_CMP_SSE    = 1;
+  FF_CMP_SATD   = 2;
+  FF_CMP_DCT    = 3;
+  FF_CMP_PSNR   = 4;
+  FF_CMP_BIT    = 5;
+  FF_CMP_RD     = 6;
+  FF_CMP_ZERO   = 7;
+  FF_CMP_VSAD   = 8;
+  FF_CMP_VSSE   = 9;
+  FF_CMP_NSSE   = 10;
+  FF_CMP_W53    = 11;
+  FF_CMP_W97    = 12;
+  FF_CMP_DCTMAX = 13;
+  FF_CMP_DCT264 = 14;
+  FF_CMP_CHROMA = 256;
+
+  FF_DTG_AFD_SAME         = 8;
+  FF_DTG_AFD_4_3          = 9;
+  FF_DTG_AFD_16_9         = 10;
+  FF_DTG_AFD_14_9         = 11;
+  FF_DTG_AFD_4_3_SP_14_9  = 13;
+  FF_DTG_AFD_16_9_SP_14_9 = 14;
+  FF_DTG_AFD_SP_4_3       = 15;
+
+  FF_DEFAULT_QUANT_BIAS   = 999999;
+
+  FF_LAMBDA_SHIFT   = 7;
+  FF_LAMBDA_SCALE   = (1 shl FF_LAMBDA_SHIFT);
+  FF_QP2LAMBDA      = 118; ///< factor to convert from H.263 QP to lambda
+  FF_LAMBDA_MAX     = (256 * 128 - 1);
+
+  FF_QUALITY_SCALE  = FF_LAMBDA_SCALE; //FIXME maybe remove
+
+  FF_CODER_TYPE_VLC     = 0;
+  FF_CODER_TYPE_AC      = 1;
+  FF_CODER_TYPE_RAW     = 2;
+  FF_CODER_TYPE_RLE     = 3;
+  FF_CODER_TYPE_DEFLATE = 4;
+
+  SLICE_FLAG_CODED_ORDER    = $0001; ///< draw_horiz_band() is called in coded order instead of display
+  SLICE_FLAG_ALLOW_FIELD    = $0002; ///< allow draw_horiz_band() with field slices (MPEG2 field pics)
+  SLICE_FLAG_ALLOW_PLANE    = $0004; ///< allow draw_horiz_band() with 1 component at a time (SVQ1)
+
+  FF_MB_DECISION_SIMPLE = 0;        ///< uses mb_cmp
+  FF_MB_DECISION_BITS   = 1;        ///< chooses the one which needs the fewest bits
+  FF_MB_DECISION_RD     = 2;        ///< rate distortion
+
+  FF_AA_AUTO    = 0;
+  FF_AA_FASTINT = 1; //not implemented yet
+  FF_AA_INT     = 2;
+  FF_AA_FLOAT   = 3;
+
+  FF_PROFILE_UNKNOWN  = -99;
+  FF_PROFILE_AAC_MAIN = 0;
+  FF_PROFILE_AAC_LOW  = 1;
+  FF_PROFILE_AAC_SSR  = 2;
+  FF_PROFILE_AAC_LTP  = 3;
+
+  FF_LEVEL_UNKNOWN    = -99;
+
+  X264_PART_I4X4 = $001;  (* Analyse i4x4 *)
+  X264_PART_I8X8 = $002;  (* Analyse i8x8 (requires 8x8 transform) *)
+  X264_PART_P8X8 = $010;  (* Analyse p16x8, p8x16 and p8x8 *)
+  X264_PART_P4X4 = $020;  (* Analyse p8x4, p4x8, p4x4 *)
+  X264_PART_B8X8 = $100;  (* Analyse b16x8, b8x16 and b8x8 *)
+
+  FF_COMPRESSION_DEFAULT = -1;
+
+{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+const
+  AVPALETTE_SIZE = 1024;
+  AVPALETTE_COUNT = 256;
+
+type
+(**
+ * AVPaletteControl
+ * This structure defines a method for communicating palette changes
+ * between and demuxer and a decoder.
+ *
+ * @deprecated Use AVPacket to send palette changes instead.
+ * This is totally broken.
+ *)
+  PAVPaletteControl = ^TAVPaletteControl;
+  TAVPaletteControl = record
+    (* demuxer sets this to 1 to indicate the palette has changed;
+     * decoder resets to 0 *)
+    palette_changed: cint;
+
+    (* 4-byte ARGB palette entries, stored in native byte order; note that
+     * the individual palette components should be on a 8-bit scale; if
+     * the palette data comes from a IBM VGA native format, the component
+     * data is probably 6 bits in size and needs to be scaled *)
+    palette: array [0..AVPALETTE_COUNT - 1] of cuint;
+  end; {deprecated;}
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52023000} // >= 52.23.0
+type
+  PAVPacket = ^TAVPacket;
+  TAVPacket = record
+(*
+ * Presentation timestamp in AVStream->time_base units; the time at which
+ * the decompressed packet will be presented to the user.
+ * Can be AV_NOPTS_VALUE if it is not stored in the file.
+ * pts MUST be larger or equal to dts as presentation cannot happen before
+ * decompression, unless one wants to view hex dumps. Some formats misuse
+ * the terms dts and pts/cts to mean something different. Such timestamps
+ * must be converted to true pts/dts before they are stored in AVPacket.
+ *)
+    pts:          cint64;
+(*
+ * Decompression timestamp in AVStream->time_base units; the time at which
+ * the packet is decompressed.
+ * Can be AV_NOPTS_VALUE if it is not stored in the file.
+ *)
+    dts:          cint64;
+    data:         PByteArray;
+    size:         cint;
+    stream_index: cint;
+    flags:        cint;
+(*
+ * Duration of this packet in AVStream->time_base units, 0 if unknown.
+ * Equals next_pts - this_pts in presentation order.
+ *)
+    duration:     cint;
+    destruct:     procedure (para1: PAVPacket); cdecl;
+    priv:         pointer;
+    pos:          cint64;       // byte position in stream, -1 if unknown
+
+(*
+ * Time difference in AVStream->time_base units from the pts of this
+ * packet to the point at which the output from the decoder has converged
+ * independent from the availability of previous frames. That is, the
+ * frames are virtually identical no matter if decoding started from
+ * the very first frame or from this keyframe.
+ * Is AV_NOPTS_VALUE if unknown.
+ * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY
+ * set.
+ *
+ * The purpose of this field is to allow seeking in streams that have no
+ * keyframes in the conventional sense. It corresponds to the
+ * recovery point SEI in H.264 and match_time_delta in NUT. It is also
+ * essential for some types of subtitle streams to ensure that all
+ * subtitles are correctly displayed after seeking.
+ *)
+    convergence_duration: cint64;
+  end;
+
+const
+  {$IF LIBAVCODEC_VERSION < 52030002} // < 52.30.2
+  PKT_FLAG_KEY = $0001;
+  {$ELSE}
+  AV_PKT_FLAG_KEY = $0001;
+    {$IF LIBAVCODEC_VERSION_MAJOR < 53}
+  PKT_FLAG_KEY = AV_PKT_FLAG_KEY;
+    {$IFEND}
+  {$IFEND}
+{$IFEND}
+
+type
+  PAVClass = ^TAVClass; {const}
+  PAVCodecContext = ^TAVCodecContext;
+
+  PAVCodec = ^TAVCodec;
+
+{$IF LIBAVCODEC_VERSION >= 52018000} // >= 52.18.0
+  PAVHWAccel = ^TAVHWAccel;
+{$IFEND}
+
+  // int[4]
+  PQuadIntArray = ^TQuadIntArray;
+  TQuadIntArray = array [0..3] of cint;
+  // int (*func)(struct AVCodecContext *c2, void *arg)
+  TExecuteFunc = function(c2: PAVCodecContext; arg: Pointer): cint; cdecl;
+{$IF LIBAVCODEC_VERSION >= 52037000} // >= 52.37.0
+  // int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr)
+  TExecute2Func = function(c2: PAVCodecContext; arg: Pointer; jobnr: cint; threadnr: cint): cint; cdecl;
+{$IFEND}
+  
+  TAVClass = record
+    class_name: PAnsiChar;
+    (* actually passing a pointer to an AVCodecContext
+       or AVFormatContext, which begin with an AVClass.
+       Needed because av_log is in libavcodec and has no visibility
+       of AVIn/OutputFormat *)
+    item_name: function(): PAnsiChar; cdecl;
+    option: PAVOption;
+
+{$IF LIBAVUTIL_VERSION >= 50015000} // 50.15.0
+    (**
+     * LIBAVUTIL_VERSION with which this structure was created.
+     * This is used to allow fields to be added without requiring major
+     * version bumps everywhere.
+     *)
+    version: cint;
+{$IFEND}
+
+{$IF LIBAVUTIL_VERSION >= 50015002} // 50.15.2
+    (**
+     * Offset in the structure where log_level_offset is stored.
+     * 0 means there is no such variable
+     *)
+    log_level_offset_offset: cint;
+{$IFEND}
+
+{$IF LIBAVUTIL_VERSION >= 50015003} // 50.15.3
+    (**
+     * Offset in the structure where a pointer to the parent context for loging is stored.
+     * for example a decoder that uses eval.c could pass its AVCodecContext to eval as such
+     * parent context. And a av_log() implementation could then display the parent context
+     * can be NULL of course
+     *)
+    parent_log_context_offset: cint;
+{$IFEND}
+  end;
+
+  {**
+   * Audio Video Frame.
+   * New fields can be added to the end of FF_COMMON_FRAME with minor version
+   * bumps.
+   * Removal, reordering and changes to existing fields require a major
+   * version bump. No fields should be added into AVFrame before or after
+   * FF_COMMON_FRAME!
+   * sizeof(AVFrame) must not be used outside libav*.
+   *}
+  PAVFrame = ^TAVFrame;
+  TAVFrame = record {200}
+    (**
+     * pointer to the picture planes.
+     * This might be different from the first allocated byte
+     * - encoding:
+     * - decoding:
+     *)
+    data: array [0..3] of pbyte;
+    linesize: array [0..3] of cint;
+    (**
+     * pointer to the first allocated byte of the picture. Can be used in get_buffer/release_buffer.
+     * This isn't used by libavcodec unless the default get/release_buffer() is used.
+     * - encoding:
+     * - decoding:
+     *)
+    base: array [0..3] of pbyte;
+    (**
+     * 1 -> keyframe, 0-> not
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by libavcodec.
+     *)
+    key_frame: cint;
+    (**
+     * Picture type of the frame, see ?_TYPE below.
+     * - encoding: Set by libavcodec. for coded_picture (and set by user for input).
+     * - decoding: Set by libavcodec.
+     *)
+    pict_type: cint;
+    (**
+     * presentation timestamp in time_base units (time when frame should be shown to user)
+     * If AV_NOPTS_VALUE then frame_rate = 1/time_base will be assumed.
+     * - encoding: MUST be set by user.
+     * - decoding: Set by libavcodec.
+     *)
+    pts: cint64;
+    (**
+     * picture number in bitstream order
+     * - encoding: set by
+     * - decoding: Set by libavcodec.
+     *)
+    coded_picture_number: cint;
+    (**
+     * picture number in display order
+     * - encoding: set by
+     * - decoding: Set by libavcodec.
+     *)
+    display_picture_number: cint;
+    (**
+     * quality (between 1 (good) and FF_LAMBDA_MAX (bad))
+     * - encoding: Set by libavcodec. for coded_picture (and set by user for input).
+     * - decoding: Set by libavcodec.
+     *)
+    quality: cint;
+    (**
+     * buffer age (1->was last buffer and dint change, 2->..., ...).
+     * Set to INT_MAX if the buffer has not been used yet.
+     * - encoding: unused
+     * - decoding: MUST be set by get_buffer().
+     *)
+    age: cint;
+    (**
+     * is this picture used as reference
+     * The values for this are the same as the MpegEncContext.picture_structure
+     * variable, that is 1->top field, 2->bottom field, 3->frame/both fields.
+     * Set to 4 for delayed, non-reference frames.
+     * - encoding: unused
+     * - decoding: Set by libavcodec. (before get_buffer() call)).
+     *)
+    reference: cint;
+    (**
+     * QP table
+     * - encoding: unused
+     * - decoding: Set by libavcodec.
+     *)
+    qscale_table: PShortint;
+    (**
+     * QP store stride
+     * - encoding: unused
+     * - decoding: Set by libavcodec.
+     *)
+    qstride: cint;
+    (**
+     * mbskip_table[mb]>=1 if MB didn't change
+     * stride= mb_width = (width+15)>>4
+     * - encoding: unused
+     * - decoding: Set by libavcodec.
+     *)
+    mbskip_table: pbyte;
+    (**
+     * motion vector table
+     * @code
+     * example:
+     * int mv_sample_log2= 4 - motion_subsample_log2;
+     * int mb_width= (width+15)>>4;
+     * int mv_stride= (mb_width << mv_sample_log2) + 1;
+     * motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y];
+     * @endcode
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     *)
+    //int16_t (*motion_val[2])[2];
+    motion_val: array [0..1] of pointer;
+    (**
+     * macroblock type table
+     * mb_type_base + mb_width + 2
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     *)
+    mb_type: PCuint;
+    (**
+     * log2 of the size of the block which a single vector in motion_val represents:
+     * (4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2)
+     * - encoding: unused
+     * - decoding: Set by libavcodec.
+     *)
+    motion_subsample_log2: byte;
+    (**
+     * for some private data of the user
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    opaque: pointer;
+    (**
+     * error
+     * - encoding: Set by libavcodec. if flags&CODEC_FLAG_PSNR.
+     * - decoding: unused
+     *)
+    error: array [0..3] of cuint64;
+    (**
+     * type of the buffer (to keep track of who has to deallocate data[*])
+     * - encoding: Set by the one who allocates it.
+     * - decoding: Set by the one who allocates it.
+     * Note: User allocated (direct rendering) & internal buffers cannot coexist currently.
+     *)
+    type_: cint;
+    (**
+     * When decoding, this signals how much the picture must be delayed.
+     * extra_delay = repeat_pict / (2*fps)
+     * - encoding: unused
+     * - decoding: Set by libavcodec.
+     *)
+    repeat_pict: cint;
+    (**
+     *
+     *)
+    qscale_type: cint;
+    (**
+     * The content of the picture is interlaced.
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec. (default 0)
+     *)
+    interlaced_frame: cint;
+    (**
+     * If the content is interlaced, is top field displayed first.
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     *)
+    top_field_first: cint;
+    (**
+     * Pan scan.
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     *)
+    pan_scan: PAVPanScan;
+    (**
+     * Tell user application that palette has changed from previous frame.
+     * - encoding: ??? (no palette-enabled encoder yet)
+     * - decoding: Set by libavcodec. (default 0).
+     *)
+    palette_has_changed: cint;
+    (**
+     * codec suggestion on buffer type if != 0
+     * - encoding: unused
+     * - decoding: Set by libavcodec. (before get_buffer() call)).
+     *)
+    buffer_hints: cint;
+    (**
+     * DCT coefficients
+     * - encoding: unused
+     * - decoding: Set by libavcodec.
+     *)
+    dct_coeff: PsmallInt;
+    (**
+     * motion reference frame index
+     * the order in which these are stored can depend on the codec.
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     *)
+    ref_index: array [0..1] of PShortint;
+
+    {$IF LIBAVCODEC_VERSION >= 51068000} // >= 51.68.0
+    (**
+     * reordered opaque 64bit number (generally a PTS) from AVCodecContext.reordered_opaque
+     * output in AVFrame.reordered_opaque
+     * - encoding: unused
+     * - decoding: Read by user.
+     *)
+    reordered_opaque: cint64;
+    {$IFEND}
+    
+    {$IF LIBAVCODEC_VERSION = 52021000} // = 52.21.0
+    (**
+     * hardware accelerator private data (FFmpeg allocated)
+     * - encoding: unused
+     * - decoding: Set by libavcodec
+     *)
+    hwaccel_data_private: pointer;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52022000} // >= 52.22.0
+    hwaccel_picture_private: pointer;
+    {$IFEND}
+
+  end;
+
+  (**
+   * main external API structure.
+   * New fields can be added to the end with minor version bumps.
+   * Removal, reordering and changes to existing fields require a major
+   * version bump.
+   * sizeof(AVCodecContext) must not be used outside libav*.
+   *)
+  TAVCodecContext = record {720}
+    (**
+     * information on struct for av_log
+     * - set by avcodec_alloc_context
+     *)
+    av_class: PAVClass;
+    (**
+     * the average bitrate
+     * - encoding: Set by user; unused for constant quantizer encoding.
+     * - decoding: Set by libavcodec. 0 or some bitrate if this info is available in the stream.
+     *)
+    bit_rate: cint;
+
+    (**
+     * number of bits the bitstream is allowed to diverge from the reference.
+     *           the reference can be CBR (for CBR pass1) or VBR (for pass2)
+     * - encoding: Set by user; unused for constant quantizer encoding.
+     * - decoding: unused
+     *)
+    bit_rate_tolerance: cint;
+
+    (**
+     * CODEC_FLAG_*.
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     *)
+    flags: cint;
+
+    (**
+     * Some codecs need additional format info. It is stored here.
+     * If any muxer uses this then ALL demuxers/parsers AND encoders for the
+     * specific codec MUST set it correctly otherwise stream copy breaks.
+     * In general use of this field by muxers is not recommanded.
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by libavcodec. (FIXME: Is this OK?)
+     *)
+    sub_id: cint;
+
+    (**
+     * Motion estimation algorithm used for video coding.
+     * 1 (zero), 2 (full), 3 (log), 4 (phods), 5 (epzs), 6 (x1), 7 (hex),
+     * 8 (umh), 9 (iter), 10 (tesa) [7, 8, 10 are x264 specific, 9 is snow specific]
+     * - encoding: MUST be set by user.
+     * - decoding: unused
+     *)
+    me_method: cint;
+
+    (**
+     * some codecs need / can use extradata like Huffman tables.
+     * mjpeg: Huffman tables
+     * rv10: additional flags
+     * mpeg4: global headers (they can be in the bitstream or here)
+     * The allocated memory should be FF_INPUT_BUFFER_PADDING_SIZE bytes larger
+     * than extradata_size to avoid prolems if it is read with the bitstream reader.
+     * The bytewise contents of extradata must not depend on the architecture or CPU endianness.
+     * - encoding: Set/allocated/freed by libavcodec.
+     * - decoding: Set/allocated/freed by user.
+     *)
+    extradata: pbyte;
+    extradata_size: cint;
+
+    (**
+     * This is the fundamental unit of time (in seconds) in terms
+     * of which frame timestamps are represented. For fixed-fps content,
+     * timebase should be 1/framerate and timestamp increments should be
+     * identically 1.
+     * - encoding: MUST be set by user.
+     * - decoding: Set by libavcodec.
+     *)
+    time_base: TAVRational;
+
+    (* video only *)
+    (**
+     * picture width / height.
+     * - encoding: MUST be set by user.
+     * - decoding: Set by libavcodec.
+     * Note: For compatibility it is possible to set this instead of
+     * coded_width/height before decoding.
+     *)
+    width, height: cint;
+
+    (**
+     * the number of pictures in a group of pictures, or 0 for intra_only
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    gop_size: cint;
+
+    (**
+     * Pixel format, see PIX_FMT_xxx.
+     * May be set by the demuxer if known from headers.
+     * May be overriden by the decoder if it knows better.
+     * - encoding: Set by user.
+     * - decoding: Set by user if known, overridden by libavcodec if known
+     *)
+    pix_fmt: TAVPixelFormat;
+
+    (**
+     * Frame rate emulation. If not zero, the lower layer (i.e. format handler)
+     * has to read frames at native frame rate.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    rate_emu: cint;
+
+    (**
+     * If non NULL, 'draw_horiz_band' is called by the libavcodec
+     * decoder to draw a horizontal band. It improves cache usage. Not
+     * all codecs can do that. You must check the codec capabilities
+     * beforehand.
+     * The function is also used by hardware acceleration APIs.
+     * It is called at least once during frame decoding to pass
+     * the data needed for hardware render.
+     * In that mode instead of pixel data, AVFrame points to
+     * a structure specific to the acceleration API. The application
+     * reads the structure and can change some fields to indicate progress
+     * or mark state.
+     * - encoding: unused
+     * - decoding: Set by user.
+     * @param height the height of the slice
+     * @param y the y position of the slice
+     * @param type 1->top field, 2->bottom field, 3->frame
+     * @param offset offset into the AVFrame.data from which the slice should be read
+     *)
+    draw_horiz_band: procedure (s: PAVCodecContext;
+                                src: {const} PAVFrame; offset: PQuadIntArray;
+                                y: cint; type_: cint; height: cint); cdecl;
+
+    (* audio only *)
+    sample_rate: cint; ///< samples per second
+    channels: cint;    ///< number of audio channels
+    
+    (**
+     * audio sample format
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     *)
+    sample_fmt: TSampleFormat;  ///< sample format
+
+    (* The following data should not be initialized. *)
+    (**
+     * Samples per packet, initialized when calling 'init'.
+     *)
+    frame_size: cint;
+    frame_number: cint;   ///< audio or video frame number
+{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+    real_pict_num: cint;  ///< returns the real picture number of previous encoded frame
+{$IFEND}
+
+    (**
+     * Number of frames the decoded output will be delayed relative to
+     * the encoded input.
+     * - encoding: Set by libavcodec.
+     * - decoding: unused
+     *)
+    delay: cint;
+
+    (* - encoding parameters *)
+    qcompress: cfloat;  ///< amount of qscale change between easy & hard scenes (0.0-1.0)
+    qblur: cfloat;      ///< amount of qscale smoothing over time (0.0-1.0)
+
+    (**
+     * minimum quantizer
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    qmin: cint;
+
+   (**
+     * maximum quantizer
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+   qmax: cint;
+
+    (**
+     * maximum quantizer difference between frames
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    max_qdiff: cint;
+
+    (**
+     * maximum number of B-frames between non-B-frames
+     * Note: The output will be delayed by max_b_frames+1 relative to the input.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    max_b_frames: cint;
+
+    (**
+     * qscale factor between IP and B-frames
+     * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset).
+     * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset).
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    b_quant_factor: cfloat;
+
+    (** obsolete FIXME remove *)
+    rc_strategy: cint;
+
+    b_frame_strategy: cint;
+
+    (**
+     * hurry up amount
+     * - encoding: unused
+     * - decoding: Set by user. 1-> Skip B-frames, 2-> Skip IDCT/dequant too, 5-> Skip everything except header
+     * @deprecated Deprecated in favor of skip_idct and skip_frame.
+     *)
+    hurry_up: cint;
+
+    codec: PAVCodec;
+
+    priv_data: pointer;
+
+    {$IF LIBAVCODEC_VERSION < 52000000} // 52.0.0
+    (* unused, FIXME remove*)
+    rtp_mode: cint;
+    {$IFEND}
+
+    rtp_payload_size: cint;  (* The size of the RTP payload: the coder will  *)
+                                (* do it's best to deliver a chunk with size    *)
+                                (* below rtp_payload_size, the chunk will start *)
+                                (* with a start code on some codecs like H.263  *)
+                                (* This doesn't take account of any particular  *)
+                                (* headers inside the transmited RTP payload    *)
+
+
+    (* The RTP callback: This function is called   *)
+    (* every time the encoder has a packet to send *)
+    (* Depends on the encoder if the data starts   *)
+    (* with a Start Code (it should) H.263 does.   *)
+    (* mb_nb contains the number of macroblocks    *)
+    (* encoded in the RTP payload                  *)
+    rtp_callback: procedure (avctx: PAVCodecContext; data: pointer;
+                             size: cint; mb_nb: cint); cdecl;
+
+    (* statistics, used for 2-pass encoding *)
+    mv_bits: cint;
+    header_bits: cint;
+    i_tex_bits: cint;
+    p_tex_bits: cint;
+    i_count: cint;
+    p_count: cint;
+    skip_count: cint;
+    misc_bits: cint;
+
+    (**
+     * number of bits used for the previously encoded frame
+     * - encoding: Set by libavcodec.
+     * - decoding: unused
+     *)
+    frame_bits: cint;
+
+    (**
+     * Private data of the user, can be used to carry app specific stuff.
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     *)
+    opaque: pointer;
+
+    codec_name: array [0..31] of AnsiChar;
+{$IF LIBAVCODEC_VERSION < 52064000} // < 52.64.0
+    codec_type: TCodecType; (* see CODEC_TYPE_xxx *)
+{$ELSE}
+    codec_type: TAVMediaType; (* see AVMEDIA_TYPE_xxx *)
+{$IFEND}
+    codec_id: TCodecID; (* see CODEC_ID_xxx *)
+
+    (**
+     * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
+     * This is used to work around some encoder bugs.
+     * A demuxer should set this to what is stored in the field used to identify the codec.
+     * If there are multiple such fields in a container then the demuxer should choose the one
+     * which maximizes the information about the used codec.
+     * If the codec tag field in a container is larger then 32 bits then the demuxer should
+     * remap the longer ID to 32 bits with a table or other structure. Alternatively a new
+     * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated
+     * first.
+     * - encoding: Set by user, if not then the default based on codec_id will be used.
+     * - decoding: Set by user, will be converted to uppercase by libavcodec during init.
+     *)
+    codec_tag: cuint;
+
+    (**
+     * Work around bugs in encoders which sometimes cannot be detected automatically.
+     * - encoding: Set by user
+     * - decoding: Set by user
+     *)
+    workaround_bugs: cint;
+
+    (**
+     * luma single coefficient elimination threshold
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    luma_elim_threshold: cint;
+
+    (**
+     * chroma single coeff elimination threshold
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    chroma_elim_threshold: cint;
+
+    (**
+     * strictly follow the standard (MPEG4, ...).
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     * Setting this to STRICT or higher means the encoder and decoder will
+     * generally do stupid things, whereas setting it to unofficial or lower
+     * will mean the encoder might produce output that is not supported by all
+     * spec-compliant decoders. Decoders don't differentiate between normal,
+     * unofficial and experimental (that is, they always try to decode things
+     * when they can) unless they are explicitly asked to behave stupidly
+     * (=strictly conform to the specs)
+     *)
+    strict_std_compliance: cint;
+
+    (**
+     * qscale offset between IP and B-frames
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    b_quant_offset: cfloat;
+
+    (**
+     * Error recognization; higher values will detect more errors but may
+     * misdetect some more or less valid parts as errors.
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    error_recognition: cint;
+
+    (**
+     * Called at the beginning of each frame to get a buffer for it.
+     * If pic.reference is set then the frame will be read later by libavcodec.
+     * avcodec_align_dimensions2() should be used to find the required width and
+     * height, as they normally need to be rounded up to the next multiple of 16.
+     * if CODEC_CAP_DR1 is not set then get_buffer() must call
+     * avcodec_default_get_buffer() instead of providing buffers allocated by
+     * some other means.
+     * - encoding: unused
+     * - decoding: Set by libavcodec, user can override.
+     *)
+    get_buffer: function (c: PAVCodecContext; pic: PAVFrame): cint; cdecl;
+
+    (**
+     * Called to release buffers which were allocated with get_buffer.
+     * A released buffer can be reused in get_buffer().
+     * pic.data[*] must be set to NULL.
+     * - encoding: unused
+     * - decoding: Set by libavcodec, user can override.
+     *)
+    release_buffer: procedure (c: PAVCodecContext; pic: PAVFrame); cdecl;
+
+    (**
+     * Size of the frame reordering buffer in the decoder.
+     * For MPEG-2 it is 1 IPB or 0 low delay IP.
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by libavcodec.
+     *)
+    has_b_frames: cint;
+
+    (**
+     * number of bytes per packet if constant and known or 0
+     * Used by some WAV based audio codecs.
+     *)
+    block_align: cint;
+
+    parse_only: cint; (* - decoding only: if true, only parsing is done
+                       (function avcodec_parse_frame()). The frame
+                       data is returned. Only MPEG codecs support this now. *)
+
+    (**
+     * 0-> h263 quant 1-> mpeg quant
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    mpeg_quant: cint;
+
+    (**
+     * pass1 encoding statistics output buffer
+     * - encoding: Set by libavcodec.
+     * - decoding: unused
+     *)
+    stats_out: PByteArray;
+
+    (**
+     * pass2 encoding statistics input buffer
+     * Concatenated stuff from stats_out of pass1 should be placed here.
+     * - encoding: Allocated/set/freed by user.
+     * - decoding: unused
+     *)
+    stats_in: PByteArray;
+
+    (**
+     * ratecontrol qmin qmax limiting method
+     * 0-> clipping, 1-> use a nice continous function to limit qscale wthin qmin/qmax.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    rc_qsquish: cfloat;
+
+    rc_qmod_amp: cfloat;
+    rc_qmod_freq: cint;
+
+    (**
+     * ratecontrol override, see RcOverride
+     * - encoding: Allocated/set/freed by user.
+     * - decoding: unused
+     *)
+    rc_override: PRcOverride;
+    rc_override_count: cint;
+
+    (**
+     * rate control equation
+     * - encoding: Set by user
+     * - decoding: unused
+     *)
+    rc_eq: {const} PByteArray; 
+
+    (**
+     * maximum bitrate
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    rc_max_rate: cint;
+
+    (**
+     * minimum bitrate
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    rc_min_rate: cint;
+
+    (**
+     * decoder bitstream buffer size
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    rc_buffer_size: cint;
+    rc_buffer_aggressivity: cfloat;
+
+    (**
+     * qscale factor between P and I-frames
+     * If > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset).
+     * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset).
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    i_quant_factor: cfloat;
+
+    (**
+     * qscale offset between P and I-frames
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    i_quant_offset: cfloat;
+
+    (**
+     * initial complexity for pass1 ratecontrol
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    rc_initial_cplx: cfloat;
+
+    (**
+     * DCT algorithm, see FF_DCT_* below
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    dct_algo: cint;
+
+    (**
+     * luminance masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    lumi_masking: cfloat;
+
+    (**
+     * temporary complexity masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    temporal_cplx_masking: cfloat;
+
+    (**
+     * spatial complexity masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    spatial_cplx_masking: cfloat;
+
+    (**
+     * p block masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    p_masking: cfloat;
+
+    (**
+     * darkness masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    dark_masking: cfloat;
+
+    {$IF LIBAVCODEC_VERSION < 52000000} // 52.0.0
+    (* for binary compatibility *)
+    unused: cint;
+    {$IFEND}
+
+    (**
+     * IDCT algorithm, see FF_IDCT_* below.
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     *)
+    idct_algo: cint;
+
+    (**
+     * slice count
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by user (or 0).
+     *)
+    slice_count: cint;
+
+    (**
+     * slice offsets in the frame in bytes
+     * - encoding: Set/allocated by libavcodec.
+     * - decoding: Set/allocated by user (or NULL).
+     *)
+    slice_offset: PCint;
+
+    (**
+     * error concealment flags
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    error_concealment: cint;
+
+    (**
+     * dsp_mask could be add used to disable unwanted CPU features
+     * CPU features (i.e. MMX, SSE. ...)
+     *
+     * With the FORCE flag you may instead enable given CPU features.
+     * (Dangerous: Usable in case of misdetection, improper usage however will
+     * result into program crash.)
+     *)
+    dsp_mask: cuint;
+
+    (**
+     * bits per sample/pixel from the demuxer (needed for huffyuv).
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by user.
+     *)
+     bits_per_coded_sample: cint;
+
+    (**
+     * prediction method (needed for huffyuv)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+     prediction_method: cint;
+
+    (**
+     * sample aspect ratio (0 if unknown)
+     * That is the width of a pixel divided by the height of the pixel.
+     * Numerator and denominator must be relatively prime and smaller than 256 for some video standards.
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     *)
+    sample_aspect_ratio: TAVRational;
+
+    (**
+     * the picture in the bitstream
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by libavcodec.
+     *)
+    coded_frame: PAVFrame;
+
+    (**
+     * debug
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     *)
+    debug: cint;
+
+    (**
+     * debug
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     *)
+    debug_mv: cint;
+
+    (**
+     * error
+     * - encoding: Set by libavcodec if flags&CODEC_FLAG_PSNR.
+     * - decoding: unused
+     *)
+    error: array [0..3] of cuint64;
+
+    (**
+     * minimum MB quantizer
+     * - encoding: unused
+     * - decoding: unused
+     *)
+    mb_qmin: cint;
+
+    (**
+     * maximum MB quantizer
+     * - encoding: unused
+     * - decoding: unused
+     *)
+    mb_qmax: cint;
+
+    (**
+     * motion estimation comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    me_cmp: cint;
+
+    (**
+     * subpixel motion estimation comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    me_sub_cmp: cint;
+    (**
+     * macroblock comparison function (not supported yet)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    mb_cmp: cint;
+    (**
+     * interlaced DCT comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    ildct_cmp: cint;
+
+    (**
+     * ME diamond size & shape
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    dia_size: cint;
+
+    (**
+     * amount of previous MV predictors (2a+1 x 2a+1 square)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    last_predictor_count: cint;
+
+    (**
+     * prepass for motion estimation
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    pre_me: cint;
+
+    (**
+     * motion estimation prepass comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    me_pre_cmp: cint;
+
+    (**
+     * ME prepass diamond size & shape
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    pre_dia_size: cint;
+
+    (**
+     * subpel ME quality
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    me_subpel_quality: cint;
+
+    (**
+     * callback to negotiate the pixelFormat
+     * @param fmt is the list of formats which are supported by the codec,
+     * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality.
+     * The first is always the native one.
+     * @return the chosen format
+     * - encoding: unused
+     * - decoding: Set by user, if not set the native format will be chosen.
+     *)
+    get_format: function (s: PAVCodecContext; fmt: {const} PAVPixelFormat): TAVPixelFormat; cdecl;
+
+    (**
+     * DTG active format information (additional aspect ratio
+     * information only used in DVB MPEG-2 transport streams)
+     * 0 if not set.
+     *
+     * - encoding: unused
+     * - decoding: Set by decoder.
+     *)
+    dtg_active_format: cint;
+
+    (**
+     * maximum motion estimation search range in subpel units
+     * If 0 then no limit.
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    me_range: cint;
+
+    (**
+     * intra quantizer bias
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    intra_quant_bias: cint;
+
+    (**
+     * inter quantizer bias
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    inter_quant_bias: cint;
+
+    (**
+     * color table ID
+     * - encoding: unused
+     * - decoding: Which clrtable should be used for 8bit RGB images.
+     *             Tables have to be stored somewhere. FIXME
+     *)
+    color_table_id: cint;
+
+    (**
+     * internal_buffer count
+     * Don't touch, used by libavcodec default_get_buffer().
+     *)
+    internal_buffer_count: cint;
+
+    (**
+     * internal_buffers
+     * Don't touch, used by libavcodec default_get_buffer().
+     *)
+    internal_buffer: pointer;
+
+    (**
+     * Global quality for codecs which cannot change it per frame.
+     * This should be proportional to MPEG-1/2/4 qscale.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    global_quality: cint;
+
+    (**
+     * coder type
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    coder_type: cint;
+
+    (**
+     * context model
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    context_model: cint;
+
+    {
+    (**
+     *
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    realloc: function (s: PAVCodecContext; buf: Pbyte; buf_size: cint): Pbyte; cdecl;
+    }
+
+    (**
+     * slice flags
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    slice_flags: cint;
+
+    (**
+     * XVideo Motion Acceleration
+     * - encoding: forbidden
+     * - decoding: set by decoder
+     *)
+    xvmc_acceleration: cint;
+
+    (**
+     * macroblock decision mode
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    mb_decision: cint;
+
+    (**
+     * custom intra quantization matrix
+     * - encoding: Set by user, can be NULL.
+     * - decoding: Set by libavcodec.
+     *)
+    intra_matrix: PWord;
+
+    (**
+     * custom inter quantization matrix
+     * - encoding: Set by user, can be NULL.
+     * - decoding: Set by libavcodec.
+     *)
+    inter_matrix: PWord;
+
+    (**
+     * fourcc from the AVI stream header (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
+     * This is used to work around some encoder bugs.
+     * - encoding: unused
+     * - decoding: Set by user, will be converted to uppercase by libavcodec during init.
+     *)
+    stream_codec_tag: array [0..3] of AnsiChar; //cuint;
+
+    (**
+     * scene change detection threshold
+     * 0 is default, larger means fewer detected scene changes.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    scenechange_threshold: cint;
+
+    (**
+     * minimum Lagrange multipler
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    lmin: cint;
+
+    (**
+     * maximum Lagrange multipler
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    lmax: cint;
+
+    (**
+     * palette control structure
+     * - encoding: ??? (no palette-enabled encoder yet)
+     * - decoding: Set by user.
+     *)
+    palctrl: PAVPaletteControl;
+
+    (**
+     * noise reduction strength
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    noise_reduction: cint;
+
+    (**
+     * Called at the beginning of a frame to get cr buffer for it.
+     * Buffer type (size, hints) must be the same. libavcodec won't check it.
+     * libavcodec will pass previous buffer in pic, function should return
+     * same buffer or new buffer with old frame "painted" into it.
+     * If pic.data[0] == NULL must behave like get_buffer().
+     * if CODEC_CAP_DR1 is not set then reget_buffer() must call
+     * avcodec_default_reget_buffer() instead of providing buffers allocated by
+     * some other means.
+     * - encoding: unused
+     * - decoding: Set by libavcodec, user can override
+     *)
+    reget_buffer: function (c: PAVCodecContext; pic: PAVFrame): cint; cdecl;
+
+    (**
+     * Number of bits which should be loaded into the rc buffer before decoding starts.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    rc_initial_buffer_occupancy: cint;
+
+    (**
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    inter_threshold: cint;
+
+    (**
+     * CODEC_FLAG2_*
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     *)
+    flags2: cint;
+
+    (**
+     * Simulates errors in the bitstream to test error concealment.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    error_rate: cint;
+
+    (**
+     * MP3 antialias algorithm, see FF_AA_* below.
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    antialias_algo: cint;
+
+    (**
+     * quantizer noise shaping
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    quantizer_noise_shaping: cint;
+
+    (**
+     * thread count
+     * is used to decide how many independent tasks should be passed to execute()
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     *)
+    thread_count: cint;
+
+    (**
+     * The codec may call this to execute several independent things.
+     * It will return only after finishing all tasks.
+     * The user may replace this with some multithreaded implementation,
+     * the default implementation will execute the parts serially.
+     * @param count the number of things to execute
+     * - encoding: Set by libavcodec, user can override.
+     * - decoding: Set by libavcodec, user can override.
+     *)
+    {$IF LIBAVCODEC_VERSION < 52004000} // < 52.4.0
+    execute: function (c: PAVCodecContext; func: TExecuteFunc; arg: PPointer; ret: PCint; count: cint): cint; cdecl;
+    {$ELSE}
+    execute: function (c: PAVCodecContext; func: TExecuteFunc; arg: Pointer; ret: PCint; count: cint; size: cint): cint; cdecl;
+    {$IFEND}
+
+    (**
+     * thread opaque
+     * Can be used by execute() to store some per AVCodecContext stuff.
+     * - encoding: set by execute()
+     * - decoding: set by execute()
+     *)
+    thread_opaque: pointer;
+
+    (**
+     * Motion estimation threshold below which no motion estimation is
+     * performed, but instead the user specified motion vectors are used.
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+     me_threshold: cint;
+
+    (**
+     * Macroblock threshold below which the user specified macroblock types will be used.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+     mb_threshold: cint;
+
+    (**
+     * precision of the intra DC coefficient - 8
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+     intra_dc_precision: cint;
+
+    (**
+     * noise vs. sse weight for the nsse comparsion function
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+     nsse_weight: cint;
+
+    (**
+     * Number of macroblock rows at the top which are skipped.
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+     skip_top: cint;
+
+    (**
+     * Number of macroblock rows at the bottom which are skipped.
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+     skip_bottom: cint;
+
+    (**
+     * profile
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     *)
+     profile: cint;
+
+    (**
+     * level
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     *)
+     level: cint;
+
+    (**
+     * low resolution decoding, 1-> 1/2 size, 2->1/4 size
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+     lowres: cint;
+
+    (**
+     * Bitstream width / height, may be different from width/height if lowres
+     * or other things are used.
+     * - encoding: unused
+     * - decoding: Set by user before init if known. Codec should override / dynamically change if needed.
+     *)
+    coded_width, coded_height: cint;
+
+    (**
+     * frame skip threshold
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    frame_skip_threshold: cint;
+
+    (**
+     * frame skip factor
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    frame_skip_factor: cint;
+
+    (**
+     * frame skip exponent
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    frame_skip_exp: cint;
+
+    (**
+     * frame skip comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    frame_skip_cmp: cint;
+
+    (**
+     * Border processing masking, raises the quantizer for mbs on the borders
+     * of the picture.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    border_masking: cfloat;
+
+    (**
+     * minimum MB lagrange multipler
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    mb_lmin: cint;
+
+    (**
+     * maximum MB lagrange multipler
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    mb_lmax: cint;
+
+    (**
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    me_penalty_compensation: cint;
+
+    (**
+     *
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    skip_loop_filter: TAVDiscard;
+
+    (**
+     *
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    skip_idct: TAVDiscard;
+
+    (**
+     *
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    skip_frame: TAVDiscard;
+
+    (**
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    bidir_refine: cint;
+
+    (**
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    brd_scale: cint;
+
+    (**
+     * constant rate factor - quality-based VBR - values ~correspond to qps
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    {$IF LIBAVCODEC_VERSION >= 51021000} // 51.21.0
+    crf: cfloat;
+    {$ELSE}
+    crf: cint;
+    {$IFEND}
+
+    (**
+     * constant quantization parameter rate control method
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    cqp: cint;
+
+    (**
+     * minimum GOP size
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    keyint_min: cint;
+
+    (**
+     * number of reference frames
+     * - encoding: Set by user.
+     * - decoding: Set by lavc.
+     *)
+    refs: cint;
+
+    (**
+     * chroma qp offset from luma
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    chromaoffset: cint;
+
+    (**
+     * Influences how often B-frames are used.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    bframebias: cint;
+
+    (**
+     * trellis RD quantization
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    trellis: cint;
+
+    (**
+     * Reduce fluctuations in qp (before curve compression).
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    complexityblur: cfloat;
+
+    (**
+     * in-loop deblocking filter alphac0 parameter
+     * alpha is in the range -6...6
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    deblockalpha: cint;
+
+    (**
+     * in-loop deblocking filter beta parameter
+     * beta is in the range -6...6
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    deblockbeta: cint;
+
+    (**
+     * macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    partitions: cint;
+
+    (**
+     * direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    directpred: cint;
+
+    (**
+     * Audio cutoff bandwidth (0 means "automatic")
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    cutoff: cint;
+
+    (**
+     * Multiplied by qscale for each frame and added to scene_change_score.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    scenechange_factor: cint;
+
+    (**
+     *
+     * Note: Value depends upon the compare function used for fullpel ME.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    mv0_threshold: cint;
+
+    (**
+     * Adjusts sensitivity of b_frame_strategy 1.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    b_sensitivity: cint;
+
+    (**
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    compression_level: cint;
+
+    {$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+    (**
+     * Sets whether to use LPC mode - used by FLAC encoder.
+     * - encoding: Set by user.
+     * - decoding: unused
+     * @deprecated Deprecated in favor of lpc_type and lpc_passes.
+     *)
+    use_lpc: cint;
+    {$IFEND}
+
+    (**
+     * LPC coefficient precision - used by FLAC encoder
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    lpc_coeff_precision: cint;
+
+    (**
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    min_prediction_order: cint;
+
+    (**
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    max_prediction_order: cint;
+
+    (**
+     * search method for selecting prediction order
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    prediction_order_method: cint;
+
+    (**
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    min_partition_order: cint;
+
+    (**
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    max_partition_order: cint;
+
+    {$IF LIBAVCODEC_VERSION >= 51026000} // 51.26.0
+    (**
+     * GOP timecode frame start number, in non drop frame format
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    timecode_frame_start: cint64;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 51042000} // 51.42.0
+    {$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+    (**
+     * Decoder should decode to this many channels if it can (0 for default)
+     * - encoding: unused
+     * - decoding: Set by user.
+     * @deprecated Deprecated in favor of request_channel_layout.
+     *)
+    request_channels: cint;
+    {$IFEND}
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION > 51049000} // > 51.49.0
+    (**
+     * Percentage of dynamic range compression to be applied by the decoder.
+     * The default value is 1.0, corresponding to full compression.
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    drc_scale: cfloat;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 51068000} // 51.68.0
+    (**
+     * opaque 64bit number (generally a PTS) that will be reordered and
+     * output in AVFrame.reordered_opaque
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    reordered_opaque: cint64;
+    {$IFEND}
+    
+    {$IF LIBAVCODEC_VERSION >= 51069000} // 51.69.0
+    (**
+     * Bits per sample/pixel of internal libavcodec pixel/sample format.
+     * This field is applicable only when sample_fmt is SAMPLE_FMT_S32.
+     * - encoding: set by user.
+     * - decoding: set by libavcodec.
+     *)
+    bits_per_raw_sample: cint;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52002000} // 52.2.0
+    (**
+     * Audio channel layout.
+     * - encoding: set by user.
+     * - decoding: set by libavcodec.
+     *)
+    channel_layout: cint64;
+
+    (**
+     * Request decoder to use this channel layout if it can (0 for default)
+     * - encoding: unused
+     * - decoding: Set by user.
+     *)
+    request_channel_layout: cint64;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52004000} // >= 52.4.0
+    (**
+     * Ratecontrol attempt to use, at maximum, <value> of what can be used without an underflow.
+     * - encoding: Set by user.
+     * - decoding: unused.
+     *)
+    rc_max_available_vbv_use: cfloat;
+
+    (**
+     * Ratecontrol attempt to use, at least, <value> times the amount needed to prevent a vbv overflow.
+     * - encoding: Set by user.
+     * - decoding: unused.
+     *)
+    rc_min_vbv_overflow_use: cfloat;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52018000} // >= 52.18.0
+    (**
+     * Hardware accelerator in use
+     * - encoding: unused.
+     * - decoding: Set by libavcodec
+     *)
+    hwaccel: PAVHWAccel;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52020000} // >= 52.20.0
+    (**
+     * For some codecs, the time base is closer to the field rate than the frame rate.
+     * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration
+     * if no telecine is used ...
+     *
+     * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2.
+     *)
+    ticks_per_frame: cint;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52021000} // >= 52.21.0
+    (**
+     * Hardware accelerator context.
+     * For some hardware accelerators, a global context needs to be
+     * provided by the user. In that case, this holds display-dependent
+     * data FFmpeg cannot instantiate itself. Please refer to the
+     * FFmpeg HW accelerator documentation to know how to fill this
+     * is. e.g. for VA API, this is a struct vaapi_context.
+     * - encoding: unused
+     * - decoding: Set by user
+     *)
+    hwaccel_context: pointer;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52028000} // >= 52.28.0
+    (**
+     * Chromaticity coordinates of the source primaries.
+     * - encoding: Set by user
+     * - decoding: Set by libavcodec
+     *)
+    color_primaries: TAVColorPrimaries;
+
+    (**
+     * Color Transfer Characteristic.
+     * - encoding: Set by user
+     * - decoding: Set by libavcodec
+     *)
+    color_trc: TAVColorTransferCharacteristic;
+
+    (**
+     * YUV colorspace type.
+     * - encoding: Set by user
+     * - decoding: Set by libavcodec
+     *)
+    colorspace: TAVColorSpace;
+
+    (**
+     * MPEG vs JPEG YUV range.
+     * - encoding: Set by user
+     * - decoding: Set by libavcodec
+     *)
+    color_range: TAVColorRange;
+
+    (**
+     * This defines the location of chroma samples.
+     * - encoding: Set by user
+     * - decoding: Set by libavcodec
+     *)
+     chroma_sample_location: TAVChromaLocation;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52037000} // >= 52.37.0
+    (**
+     * The codec may call this to execute several independent things.
+     * It will return only after finishing all tasks.
+     * The user may replace this with some multithreaded implementation,
+     * the default implementation will execute the parts serially.
+     * Also see avcodec_thread_init and e.g. the --enable-pthread configure option.
+     * @param c context passed also to func
+     * @param count the number of things to execute
+     * @param arg2 argument passed unchanged to func
+     * @param ret return values of executed functions, must have space for "count" values. May be NULL.
+     * @param func function that will be called count times, with jobnr from 0 to count-1.
+     *             threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no
+     *             two instances of func executing at the same time will have the same threadnr.
+     * @return always 0 currently, but code should handle a future improvement where when any call to func
+     *         returns < 0 no further calls to func may be done and < 0 is returned.
+     * - encoding: Set by libavcodec, user can override.
+     * - decoding: Set by libavcodec, user can override.
+     *)
+      execute2: function (c: PAVCodecContext; func: TExecute2Func; arg2: Pointer; ret: Pcint; count: cint): cint; cdecl;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52042000} // >= 52.42.0
+    (**
+     * explicit P-frame weighted prediction analysis method
+     * 0: off
+     * 1: fast blind weighting (one reference duplicate with -1 offset)
+     * 2: smart weighting (full fade detection analysis)
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    weighted_p_pred: cint;
+    {$IFEND}
+    
+    {$IF LIBAVCODEC_VERSION >= 52061000} // >= 52.61.0
+    (**
+     * AQ mode
+     * 0: Disabled
+     * 1: Variance AQ (complexity mask)
+     * 2: Auto-variance AQ (experimental)
+     * - encoding: Set by user
+     * - decoding: unused
+     *)
+    aq_mode: cint;
+
+    (**
+     * AQ strength
+     * Reduces blocking and blurring in flat and textured areas.
+     * - encoding: Set by user
+     * - decoding: unused
+     *)
+    aq_strength: cfloat;
+
+    (**
+     * PSY RD
+     * Strength of psychovisual optimization
+     * - encoding: Set by user
+     * - decoding: unused
+     *)
+    psy_rd: cfloat;
+
+    (**
+     * PSY trellis
+     * Strength of psychovisual optimization
+     * - encoding: Set by user
+     * - decoding: unused
+     *)
+    psy_trellis: cfloat;
+
+    (**
+     * RC lookahead
+     * Number of frames for frametype and ratecontrol lookahead
+     * - encoding: Set by user
+     * - decoding: unused
+     *)
+    rc_lookahead: cint;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52067000} // >= 52.67.0
+    (**
+     * Constant rate factor maximum
+     * With CRF encoding mode and VBV restrictions enabled, prevents quality from being worse
+     * than crf_max, even if doing so would violate VBV restrictions.
+     * - encoding: Set by user.
+     * - decoding: unused
+     *)
+    crf_max: cfloat;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52067002} // >= 52.67.2
+    log_level_offset: cint;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52083000} // >= 52.83.0
+    (**
+     * Determines which LPC analysis algorithm to use.
+     * - encoding: Set by user
+     * - decoding: unused
+     *)
+    lpc_type: TAVLPCType;
+
+    (**
+     * Number of passes to use for Cholesky factorization during LPC analysis
+     * - encoding: Set by user
+     * - decoding: unused
+     *)
+    lpc_passes: cint;
+    {$IFEND}
+  end; {TAVCodecContext}
+
+(**
+ * AVCodec.
+ *)
+  TAVCodec = record
+    name: PAnsiChar;
+{$IF LIBAVCODEC_VERSION < 52064000} // < 52.64.0
+    type_: TCodecType;
+{$ELSE}
+    type_: TAVMediaType;
+{$IFEND}
+    id: TCodecID;
+    priv_data_size: cint;
+    init: function (avctx: PAVCodecContext): cint; cdecl; (* typo corretion by the Creative CAT *)
+    encode: function (avctx: PAVCodecContext; buf: PByteArray; buf_size: cint; data: pointer): cint; cdecl;
+    close: function (avctx: PAVCodecContext): cint; cdecl;
+    decode: function (avctx: PAVCodecContext; outdata: pointer; var outdata_size: cint;
+    {$IF LIBAVCODEC_VERSION < 52025000} // 52.25.0
+                      buf: {const} PByteArray; buf_size: cint): cint; cdecl;
+    {$ELSE}
+                      avpkt: PAVPacket): cint; cdecl;
+    {$IFEND}
+    (**
+     * Codec capabilities.
+     * see CODEC_CAP_*
+     *)
+    capabilities: cint;
+    next: PAVCodec;
+    (**
+     * Flush buffers.
+     * Will be called when seeking
+     *)
+    flush: procedure (avctx: PAVCodecContext); cdecl;
+    supported_framerates: {const} PAVRational; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}
+    pix_fmts: {const} PAVPixelFormat;       ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1
+    {$IF LIBAVCODEC_VERSION >= 51055000} // 51.55.0
+    (**
+     * Descriptive name for the codec, meant to be more human readable than name.
+     * You should use the NULL_IF_CONFIG_SMALL() macro to define it.
+     *)
+    long_name: {const} PAnsiChar;
+    {$IFEND}
+    {$IF LIBAVCODEC_VERSION >= 51056000} // 51.56.0
+    supported_samplerates: {const} PCint;      ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0
+    {$IFEND}
+    {$IF LIBAVCODEC_VERSION >= 51062000} // 51.62.0
+    sample_fmts: {const} PSampleFormatArray;   ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
+    {$IFEND}
+    {$IF LIBAVCODEC_VERSION >= 52002000} // 52.2.0
+    channel_layouts: {const} PCint64;          ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
+    {$IFEND}
+    {$IF LIBAVCODEC_VERSION >= 52080000} // 52.80.0
+    max_lowres: byte;                          ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
+    {$IFEND}
+  end;
+
+{$IF LIBAVCODEC_VERSION >= 52018000} // 52.18.0
+(**
+ * AVHWAccel.
+ *)
+  TAVHWAccel = record
+    (**
+     * Name of the hardware accelerated codec.
+     * The name is globally unique among encoders and among decoders (but an
+     * encoder and a decoder can share the same name).
+     *)
+    name: PAnsiChar;
+
+{$IF LIBAVCODEC_VERSION < 52064000} // < 52.64.0
+    (**
+     * Type of codec implemented by the hardware accelerator.
+     *
+     * See CODEC_TYPE_xxx
+     *)
+    type_: TCodecType;
+{$ELSE}
+    (**
+     * Type of codec implemented by the hardware accelerator.
+     *
+     * See AVMediaType_xxx
+     *)
+    type_: TAVMediaType;
+{$IFEND}
+
+    
+    (**
+     * Codec implemented by the hardware accelerator.
+     *
+     * See CODEC_ID_xxx
+     *)
+    id: TCodecID;
+
+    (**
+     * Supported pixel format.
+     *
+     * Only hardware accelerated formats are supported here.
+     *)
+    pix_fmt: {const} PAVPixelFormat; 
+
+    (**
+     * Hardware accelerated codec capabilities.
+     * see FF_HWACCEL_CODEC_CAP_*
+     *)
+    capabilities: cint;
+
+    next: PAVCodec;
+
+    (**
+     * Called at the beginning of each frame or field picture.
+     *
+     * Meaningful frame information (codec specific) is guaranteed to
+     * be parsed at this point. This function is mandatory.
+     *
+     * Note that buf can be NULL along with buf_size set to 0.
+     * Otherwise, this means the whole frame is available at this point.
+     *
+     * @param avctx the codec context
+     * @param buf the frame data buffer base
+     * @param buf_size the size of the frame in bytes
+     * @return zero if successful, a negative value otherwise
+     *)
+    start_frame: function (avctx:    PAVCodecContext; 
+                           buf:      PByteArray; 
+                           buf_size: cint): cint; cdecl;
+
+    (**
+     * Callback for each slice.
+     *
+     * Meaningful slice information (codec specific) is guaranteed to
+     * be parsed at this point. This function is mandatory.
+     *
+     * @param avctx the codec context
+     * @param buf the slice data buffer base
+     * @param buf_size the size of the slice in bytes
+     * @return zero if successful, a negative value otherwise
+     *)
+    decode_slice: function (avctx:    PAVCodecContext;
+                            buf:      PByteArray; 
+                            buf_size: cint): cint; cdecl;
+
+    (**
+     * Called at the end of each frame or field picture.
+     *
+     * The whole picture is parsed at this point and can now be sent
+     * to the hardware accelerator. This function is mandatory.
+     *
+     * @param avctx the codec context
+     * @return zero if successful, a negative value otherwise
+     *)
+    end_frame: function (avctx: PAVCodecContext): cint; cdecl;
+        
+{$IF LIBAVCODEC_VERSION >= 52021000} // >= 52.21.0
+    (**
+     * Size of HW accelerator private data.
+     *
+     * Private data is allocated with av_mallocz() before
+     * AVCodecContext.get_buffer() and deallocated after
+     * AVCodecContext.release_buffer().
+     *)
+    priv_data_size: cint;
+{$IFEND}
+        
+  end;
+{$IFEND}
+
+(**
+ * four components are given, that's all.
+ * the last component is alpha
+ *)
+  PAVPicture = ^TAVPicture;
+  TAVPicture = record
+    data: array [0..3] of PByteArray;
+    linesize: array [0..3] of cint;       ///< number of bytes per line
+  end;
+
+type
+  TAVSubtitleType = (
+    SUBTITLE_NONE,
+
+    SUBTITLE_BITMAP,                ///< A bitmap, pict will be set
+
+    (**
+     * Plain text, the text field must be set by the decoder and is
+     * authoritative. ass and pict fields may contain approximations.
+     *)
+    SUBTITLE_TEXT,
+
+    (**
+     * Formatted text, the ass field must be set by the decoder and is
+     * authoritative. pict and text fields may contain approximations.
+     *)
+    SUBTITLE_ASS
+  );
+
+type
+  PPAVSubtitleRect = ^PAVSubtitleRect;
+  PAVSubtitleRect = ^TAVSubtitleRect;
+  {$IF LIBAVCODEC_VERSION < 52010000} // < 52.10.0
+  TAVSubtitleRect = record
+    x: cuint16;
+    y: cuint16;
+    w: cuint16;
+    h: cuint16;
+    nb_colors: cuint16;
+    linesize: cint;
+    rgba_palette: PCuint32;
+    bitmap: PCuint8;
+  end;
+  {$ELSE}
+  TAVSubtitleRect = record
+    x: cint;        ///< top left corner  of pict, undefined when pict is not set
+    y: cint;        ///< top left corner  of pict, undefined when pict is not set
+    w: cint;        ///< width            of pict, undefined when pict is not set
+    h: cint;        ///< height           of pict, undefined when pict is not set
+    nb_colors: cint; ///< number of colors in pict, undefined when pict is not set
+
+    (**
+     * data+linesize for the bitmap of this subtitle.
+     * can be set for text/ass as well once they where rendered
+     *)
+    pict: TAVPicture;
+    type_: TAVSubtitleType;
+
+    text: PAnsiChar;                     ///< 0 terminated plain UTF-8 text
+
+    (**
+     * 0 terminated ASS/SSA compatible event line.
+     * The pressentation of this is unaffected by the other values in this
+     * struct.
+     *)
+    ass: PByteArray;
+  end;
+  {$IFEND}
+
+  PPAVSubtitle = ^PAVSubtitle;
+  PAVSubtitle = ^TAVSubtitle;
+  TAVSubtitle = record
+    format: cuint16; (* 0 = graphics *)
+    start_display_time: cuint32; (* relative to packet pts, in ms *)
+    end_display_time: cuint32; (* relative to packet pts, in ms *)
+    num_rects: cuint;
+    {$IF LIBAVCODEC_VERSION < 52010000} // < 52.10.0
+    rects: PAVSubtitleRect;
+    {$ELSE}
+    rects: PPAVSubtitleRect;
+    {$IFEND}
+    {$IF LIBAVCODEC_VERSION >= 52032000} // >= 52.32.0
+    pts: cint64;     ///< Same as packet pts, in AV_TIME_BASE
+    {$IFEND}
+  end;
+
+{$IF LIBAVCODEC_VERSION >= 52025000} // 52.25.0
+{ packet functions  }
+
+(**
+ * @deprecated use NULL instead
+ *)
+procedure av_destruct_packet_nofree(pkt: PAVPacket);
+  cdecl; external av__codec;
+
+(*
+ * Default packet destructor.
+ *)
+procedure av_destruct_packet(pkt: PAVPacket);
+  cdecl; external av__codec;
+
+(*
+ * Initialize optional fields of a packet with default values.
+ *
+ * @param pkt packet
+ *)
+procedure av_init_packet(var pkt: TAVPacket);
+  cdecl; external av__codec;
+
+(*
+ * Allocate the payload of a packet and initialize its fields with
+ * default values.
+ *
+ * @param pkt packet
+ * @param size wanted payload size
+ * @return 0 if OK, AVERROR_xxx otherwise
+ *)
+function av_new_packet(pkt: PAVPacket; size: cint): cint;
+  cdecl; external av__codec;
+
+(*
+ * Reduce packet size, correctly zeroing padding
+ *
+ * @param pkt packet
+ * @param size new size
+ *)
+procedure av_shrink_packet(pkt: PAVPacket; size: cint);
+  cdecl; external av__codec;
+
+(*
+ * @warning This is a hack - the packet memory allocation stuff is broken. The
+ * packet is allocated if it was not really allocated.
+ *)
+function av_dup_packet(pkt: PAVPacket): cint;
+  cdecl; external av__codec;
+
+(*
+ * Free a packet.
+ *
+ * @param pkt packet to free
+ *)
+procedure av_free_packet(pkt: PAVPacket);
+{$IF LIBAVCODEC_VERSION >= 52028000} // 52.28.0
+  cdecl; external av__codec;
+{$IFEND}
+{$IFEND}
+
+(* resample.c *)
+type
+  PReSampleContext = pointer;
+  PAVResampleContext = pointer;
+  PImgReSampleContext = pointer;
+
+function audio_resample_init (output_channels: cint; input_channels: cint;
+                              output_rate: cint; input_rate: cint): PReSampleContext;
+  cdecl; external av__codec;
+
+function audio_resample (s: PReSampleContext; output: PSmallint; input: PSmallint; nb_samples: cint): cint;
+  cdecl; external av__codec;
+
+procedure audio_resample_close (s: PReSampleContext);
+  cdecl; external av__codec;
+
+(**
+ * Initialize an audio resampler.
+ * Note, if either rate is not an integer then simply scale both rates up so they are.
+ * @param filter_length length of each FIR filter in the filterbank relative to the cutoff freq
+ * @param log2_phase_count log2 of the number of entries in the polyphase filterbank
+ * @param linear If 1 then the used FIR filter will be linearly interpolated
+                 between the 2 closest, if 0 the closest will be used
+ * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate
+ *)
+function av_resample_init (out_rate: cint; in_rate: cint; filter_length: cint;
+                           log2_phase_count: cint; linear: cint; cutoff: cdouble): PAVResampleContext;
+  cdecl; external av__codec;
+
+(**
+ * Resample an array of samples using a previously configured context.
+ * @param src an array of unconsumed samples
+ * @param consumed the number of samples of src which have been consumed are returned here
+ * @param src_size the number of unconsumed samples available
+ * @param dst_size the amount of space in samples available in dst
+ * @param update_ctx If this is 0 then the context will not be modified, that way several channels can be resampled with the same context.
+ * @return the number of samples written in dst or -1 if an error occurred
+ *)
+function av_resample (c: PAVResampleContext; dst: PSmallint; src: PSmallint; var consumed: cint;
+                      src_size: cint; dst_size: cint; update_ctx: cint): cint;
+  cdecl; external av__codec;
+
+(**
+ * Compensate samplerate/timestamp drift. The compensation is done by changing
+ * the resampler parameters, so no audible clicks or similar distortions occur
+ * @param compensation_distance distance in output samples over which the compensation should be performed
+ * @param sample_delta number of output samples which should be output less
+ *
+ * example: av_resample_compensate(c, 10, 500)
+ * here instead of 510 samples only 500 samples would be output
+ *
+ * note, due to rounding the actual compensation might be slightly different,
+ * especially if the compensation_distance is large and the in_rate used during init is small
+ *)
+procedure av_resample_compensate (c: PAVResampleContext; sample_delta: cint;
+                                  compensation_distance: cint);
+  cdecl; external av__codec;
+
+procedure av_resample_close (c: PAVResampleContext);
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION < 52000000} // 52.0.0
+(* YUV420 format is assumed ! *)
+
+(**
+ * @deprecated Use the software scaler (swscale) instead.
+ *)
+function img_resample_init (output_width: cint; output_height: cint;
+                           input_width: cint; input_height: cint): PImgReSampleContext;
+  cdecl; external av__codec; deprecated;
+
+(**
+ * @deprecated Use the software scaler (swscale) instead.
+ *)
+function img_resample_full_init (owidth: cint; oheight: cint;
+                                    iwidth: cint; iheight: cint;
+                                    topBand: cint; bottomBand: cint;
+                                    leftBand: cint; rightBand: cint;
+                                    padtop: cint; padbottom: cint;
+                                    padleft: cint; padright: cint): PImgReSampleContext;
+  cdecl; external av__codec; deprecated;
+
+(**
+ * @deprecated Use the software scaler (swscale) instead.
+ *)
+procedure img_resample (s: PImgReSampleContext; output: PAVPicture; input: {const} PAVPicture);
+  cdecl; external av__codec; deprecated;
+
+(**
+ * @deprecated Use the software scaler (swscale) instead.
+ *)
+procedure img_resample_close (s: PImgReSampleContext);
+  cdecl; external av__codec; deprecated;
+{$IFEND}
+
+(**
+ * Allocate memory for a picture.  Call avpicture_free to free it.
+ *
+ * @param picture the picture to be filled in.
+ * @param pix_fmt the format of the picture.
+ * @param width the width of the picture.
+ * @param height the height of the picture.
+ * @return Zero if successful, a negative value if not.
+ *)
+function avpicture_alloc (picture: PAVPicture; pix_fmt: TAVPixelFormat;
+                          width: cint; height: cint): cint;
+  cdecl; external av__codec;
+
+(**
+ * Free a picture previously allocated by avpicture_alloc().
+ *
+ * @param picture the AVPicture to be freed
+ *)
+procedure avpicture_free (picture: PAVPicture);
+  cdecl; external av__codec;
+
+(**
+ * Fill in the AVPicture fields.
+ * The fields of the given AVPicture are filled in by using the 'ptr' address
+ * which points to the image data buffer. Depending on the specified picture
+ * format, one or multiple image data pointers and line sizes will be set.
+ * If a planar format is specified, several pointers will be set pointing to
+ * the different picture planes and the line sizes of the different planes
+ * will be stored in the lines_sizes array.
+ * Call with ptr == NULL to get the required size for the ptr buffer.
+ *
+ * @param picture AVPicture whose fields are to be filled in
+ * @param ptr Buffer which will contain or contains the actual image data
+ * @param pix_fmt The format in which the picture data is stored.
+ * @param width the width of the image in pixels
+ * @param height the height of the image in pixels
+ * @return size of the image data in bytes
+ *)
+function avpicture_fill (picture: PAVPicture; ptr: pointer;
+                 pix_fmt: TAVPixelFormat; width: cint; height: cint): cint;
+  cdecl; external av__codec;
+
+function avpicture_layout (src: {const} PAVPicture; pix_fmt: TAVPixelFormat;
+                   width: cint; height: cint;
+                   dest: PByteArray; dest_size: cint): cint;
+  cdecl; external av__codec;
+
+(**
+ * Calculate the size in bytes that a picture of the given width and height
+ * would occupy if stored in the given picture format.
+ * Note that this returns the size of a compact representation as generated
+ * by avpicture_layout, which can be smaller than the size required for e.g.
+ * avpicture_fill.
+ *
+ * @param pix_fmt the given picture format
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return Image data size in bytes or -1 on error (e.g. too large dimensions).
+ *)
+function avpicture_get_size (pix_fmt: TAVPixelFormat; width: cint; height: cint): cint;
+  cdecl; external av__codec;
+
+procedure avcodec_get_chroma_sub_sample (pix_fmt: TAVPixelFormat; var h_shift: cint; var v_shift: cint);
+  cdecl; external av__codec;
+
+(**
+ * Return the pixel format corresponding to the name name.
+ *
+ * If there is no pixel format with name name, then look for a
+ * pixel format with the name corresponding to the native endian
+ * format of name.
+ * For example in a little-endian system, first look for "gray16",
+ * then for "gray16le".
+ *
+ * Finally if no pixel format has been found, return PIX_FMT_NONE.
+ *)
+function avcodec_get_pix_fmt_name(pix_fmt: TAVPixelFormat): PAnsiChar;
+  cdecl; external av__codec;
+
+procedure avcodec_set_dimensions(s: PAVCodecContext; width: cint; height: cint);
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+(**
+ * Return the pixel format corresponding to the name name.
+ *
+ * If there is no pixel format with name name, then looks for a
+ * pixel format with the name corresponding to the native endian
+ * format of name.
+ * For example in a little-endian system, first looks for "gray16",
+ * then for "gray16le".
+ *
+ * Finally if no pixel format has been found, returns PIX_FMT_NONE.*
+ * @deprecated Deprecated in favor of av_get_pix_fmt().
+ *)
+function avcodec_get_pix_fmt(name: {const} PAnsiChar): TAVPixelFormat;
+  cdecl; external av__codec;
+{$IF LIBAVCODEC_VERSION >= 52049000} // >= 52.49.0
+  deprecated;
+{$IFEND}
+{$IFEND}
+
+(**
+ * Return a value representing the fourCC code associated to the
+ * pixel format pix_fmt, or 0 if no associated fourCC code can be
+ * found.
+ *)
+function avcodec_pix_fmt_to_codec_tag(pix_fmt: TAVPixelFormat): cuint;
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION >= 52073000} // 52.73.0
+(**
+ * Put a string representing the codec tag codec_tag in buf.
+ *
+ * @param buf_size size in bytes of buf
+ * @return the length of the string that would have been generated if
+ * enough space had been available, excluding the trailing null
+ *)
+function av_get_codec_tag_string(buf: PAnsiChar; buf_size: size_t; codec_tag: cuint): size_t;
+  cdecl; external av__codec;
+{$IFEND}
+
+const
+  FF_LOSS_RESOLUTION  = $0001; {**< loss due to resolution change *}
+  FF_LOSS_DEPTH       = $0002; {**< loss due to color depth change *}
+  FF_LOSS_COLORSPACE  = $0004; {**< loss due to color space conversion *}
+  FF_LOSS_ALPHA       = $0008; {**< loss of alpha bits *}
+  FF_LOSS_COLORQUANT  = $0010; {**< loss due to color quantization *}
+  FF_LOSS_CHROMA      = $0020; {**< loss of chroma (e.g. RGB to gray conversion) *}
+
+(**
+ * Compute what kind of losses will occur when converting from one specific
+ * pixel format to another.
+ * When converting from one pixel format to another, information loss may occur.
+ * For example, when converting from RGB24 to GRAY, the color information will
+ * be lost. Similarly, other losses occur when converting from some formats to
+ * other formats. These losses can involve loss of chroma, but also loss of
+ * resolution, loss of color depth, loss due to the color space conversion, loss
+ * of the alpha bits or loss due to color quantization.
+ * avcodec_get_fix_fmt_loss() informs you about the various types of losses
+ * which will occur when converting from one pixel format to another.
+ *
+ * @param[in] dst_pix_fmt destination pixel format
+ * @param[in] src_pix_fmt source pixel format
+ * @param[in] has_alpha Whether the source pixel format alpha channel is used.
+ * @return Combination of flags informing you what kind of losses will occur.
+ *)
+function avcodec_get_pix_fmt_loss (dst_pix_fmt: TAVPixelFormat; src_pix_fmt: TAVPixelFormat;
+                           has_alpha: cint): cint;
+  cdecl; external av__codec;
+
+(**
+ * Find the best pixel format to convert to given a certain source pixel
+ * format.  When converting from one pixel format to another, information loss
+ * may occur.  For example, when converting from RGB24 to GRAY, the color
+ * information will be lost. Similarly, other losses occur when converting from
+ * some formats to other formats. avcodec_find_best_pix_fmt() searches which of
+ * the given pixel formats should be used to suffer the least amount of loss.
+ * The pixel formats from which it chooses one, are determined by the
+ * pix_fmt_mask parameter.
+ *
+ * @code
+ * src_pix_fmt = PIX_FMT_YUV420P;
+ * pix_fmt_mask = (1 << PIX_FMT_YUV422P) || (1 << PIX_FMT_RGB24);
+ * dst_pix_fmt = avcodec_find_best_pix_fmt(pix_fmt_mask, src_pix_fmt, alpha, &loss);
+ * @endcode
+ *
+ * @param[in] pix_fmt_mask bitmask determining which pixel format to choose from
+ * @param[in] src_pix_fmt source pixel format
+ * @param[in] has_alpha Whether the source pixel format alpha channel is used.
+ * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur.
+ * @return The best pixel format to convert to or -1 if none was found.
+ *)
+{$IF LIBAVCODEC_VERSION >= 52000000} // 52.0.0
+function avcodec_find_best_pix_fmt(pix_fmt_mask: cint64; src_pix_fmt: TAVPixelFormat;
+                            has_alpha: cint; loss_ptr: PCint): cint;
+  cdecl; external av__codec;
+{$ELSEIF LIBAVCODEC_VERSION < 52022001}
+function avcodec_find_best_pix_fmt(pix_fmt_mask: cint; src_pix_fmt: TAVPixelFormat;
+                            has_alpha: cint; loss_ptr: PCint): cint;
+  cdecl; external av__codec;
+{$ELSE}
+function avcodec_find_best_pix_fmt(pix_fmt_mask: cint; src_pix_fmt: TAVPixelFormat;
+                            has_alpha: cint; loss_ptr: PCint): TAVPixelFormat;
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 51041000} // 51.41.0
+(**
+ * Print in buf the string corresponding to the pixel format with
+ * number pix_fmt, or an header if pix_fmt is negative.
+ *
+ * @param[in] buf the buffer where to write the string
+ * @param[in] buf_size the size of buf
+ * @param[in] pix_fmt the number of the pixel format to print the corresponding info string, or
+ * a negative value to print the corresponding header.
+ * Meaningful values for obtaining a pixel format info vary from 0 to PIX_FMT_NB -1.
+ *)
+{$IF LIBAVCODEC_VERSION < 52022001} // 52.22.1
+procedure avcodec_pix_fmt_string (buf: PAnsiChar; buf_size: cint; pix_fmt: cint);
+  cdecl; external av__codec;
+{$ELSE}
+procedure avcodec_pix_fmt_string (buf: PAnsiChar; buf_size: cint; pix_fmt: TAVPixelFormat);
+  cdecl; external av__codec;
+{$IFEND}
+{$IFEND}
+
+const
+  FF_ALPHA_TRANSP      = $0001; {* image has some totally transparent pixels *}
+  FF_ALPHA_SEMI_TRANSP = $0002; {* image has some transparent pixels *}
+
+(**
+ * Tell if an image really has transparent alpha values.
+ * @return ored mask of FF_ALPHA_xxx constants
+ *)
+function img_get_alpha_info (src: {const} PAVPicture;
+                             pix_fmt: TAVPixelFormat;
+                             width:   cint;
+                             height:  cint): cint;
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION < 52000000} // 52.0.0
+(**
+ * convert among pixel formats
+ * @deprecated Use the software scaler (swscale) instead.
+ *)
+function img_convert (dst: PAVPicture; dst_pix_fmt: TAVPixelFormat;
+              src: {const} PAVPicture; pix_fmt: TAVPixelFormat;
+              width: cint; height: cint): cint;
+  cdecl; external av__codec; deprecated;
+{$IFEND}
+
+(* deinterlace a picture *)
+(* deinterlace - if not supported return -1 *)
+function avpicture_deinterlace (dst: PAVPicture;
+                        src: {const} PAVPicture;
+                        pix_fmt: TAVPixelFormat;
+                        width:   cint;
+                        height:  cint): cint;
+  cdecl; external av__codec;
+
+{* external high level API *}
+
+{$IF LIBAVCODEC_VERSION < 52000000} // 52.0.0
+{
+var
+  first_avcodec: PAVCodec; external av__codec;
+}
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 51049000} // 51.49.0
+(**
+ * If c is NULL, returns the first registered codec,
+ * if c is non-NULL, returns the next registered codec after c,
+ * or NULL if c is the last one.
+ *)
+function av_codec_next(c: PAVCodec): PAVCodec;
+  cdecl; external av__codec;
+{$IFEND}
+
+(**
+ * Return the LIBAVCODEC_VERSION_INT constant.
+ *)
+function avcodec_version(): cuint;
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION < 52008000} // 52.8.0
+(* returns LIBAVCODEC_BUILD constant *)
+function avcodec_build(): cuint;
+  cdecl; external av__codec; deprecated;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52041000} // 52.41.0
+(**
+ * Return the libavcodec build-time configuration.
+ *)
+function avcodec_configuration(): PAnsiChar;
+  cdecl; external av__codec;
+
+(**
+ * Return the libavcodec license.
+ *)
+function avcodec_license(): PAnsiChar;
+  cdecl; external av__codec;
+{$IFEND}
+
+(**
+ * Initialize libavcodec.
+ *
+ * @warning This function must be called before any other libavcodec
+ * function.
+ *)
+procedure avcodec_init();
+  cdecl; external av__codec;
+
+(**
+ * Register the codec codec and initialize libavcodec.
+ *
+ * @see avcodec_init()
+ *)
+{$IF LIBAVCODEC_VERSION >= 52014000} // 52.14.0
+procedure avcodec_register(codec: PAVCodec);
+  cdecl; external av__codec;
+// Deprecated in favor of avcodec_register.
+procedure register_avcodec(codec: PAVCodec);
+  cdecl; external av__codec; deprecated;
+{$ELSEIF LIBAVCODEC_VERSION_MAJOR < 53}
+procedure register_avcodec(codec: PAVCodec);
+  cdecl; external av__codec;
+{$IFEND}
+(**
+ * Find a registered encoder with a matching codec ID.
+ *
+ * @param id CodecID of the requested encoder
+ * @return An encoder if one was found, NULL otherwise.
+ *)
+function avcodec_find_encoder(id: TCodecID): PAVCodec;
+  cdecl; external av__codec;
+
+(**
+ * Find a registered encoder with the specified name.
+ *
+ * @param name name of the requested encoder
+ * @return An encoder if one was found, NULL otherwise.
+ *)
+function avcodec_find_encoder_by_name(name: PAnsiChar): PAVCodec;
+  cdecl; external av__codec;
+
+(**
+ * Findsa registered decoder with a matching codec ID.
+ *
+ * @param id CodecID of the requested decoder
+ * @return A decoder if one was found, NULL otherwise.
+ *)
+function avcodec_find_decoder(id: TCodecID): PAVCodec;
+  cdecl; external av__codec;
+
+(**
+ * Find a registered decoder with the specified name.
+ *
+ * @param name name of the requested decoder
+ * @return A decoder if one was found, NULL otherwise.
+ *)
+function avcodec_find_decoder_by_name(name: PAnsiChar): PAVCodec;
+  cdecl; external av__codec;
+procedure avcodec_string(buf: PAnsiChar; buf_size: cint; enc: PAVCodecContext; encode: cint);
+  cdecl; external av__codec;
+
+(**
+ * Set the fields of the given AVCodecContext to default values.
+ *
+ * @param s The AVCodecContext of which the fields should be set to default values.
+ *)
+procedure avcodec_get_context_defaults(s: PAVCodecContext);
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION >= 51039000} // 51.39.0
+(** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API!
+ *  we WILL change its arguments and name a few times! *)
+{$IF LIBAVCODEC_VERSION < 52064000} // < 52.64.0
+procedure avcodec_get_context_defaults2(s: PAVCodecContext; ctype: TCodecType);
+  cdecl; external av__codec;
+{$ELSE}
+procedure avcodec_get_context_defaults2(s: PAVCodecContext; ctype: TAVMediaType);
+  cdecl; external av__codec;
+{$IFEND}
+{$IFEND}
+
+(**
+ * Allocate an AVCodecContext and sets it fields to default values.  The
+ * resulting struct can be deallocated by simply calling av_free().
+ *
+ * @return An AVCodecContext filled with default values or NULL on failure.
+ * @see avcodec_get_context_defaults
+ *)
+function avcodec_alloc_context(): PAVCodecContext;
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION >= 51039000} // 51.39.0
+(** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API!
+ *  we WILL change its arguments and name a few times! *)
+{$IF LIBAVCODEC_VERSION < 52064000} // < 52.64.0
+function avcodec_alloc_context2(ctype: TCodecType): PAVCodecContext;
+  cdecl; external av__codec;
+{$ELSE}
+function avcodec_alloc_context2(ctype: TAVMediaType): PAVCodecContext;
+  cdecl; external av__codec;
+{$IFEND}
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52065000} // >= 52.65.0
+(**
+ * Copy the settings of the source AVCodecContext into the destination
+ * AVCodecContext. The resulting destination codec context will be
+ * unopened, i.e. you are required to call avcodec_open() before you
+ * can use this AVCodecContext to decode/encode video/audio data.
+ *
+ * @param dest target codec context, should be initialized with
+ *             avcodec_alloc_context(), but otherwise uninitialized
+ * @param src source codec context
+ * @return AVERROR() on error (e.g. memory allocation error), 0 on success
+ *)
+function avcodec_copy_context(dest: PAVCodecContext; src: {const} PAVCodecContext): cint;
+  cdecl; external av__codec;
+{$IFEND}
+
+(**
+ * Set the fields of the given AVFrame to default values.
+ *
+ * @param pic The AVFrame of which the fields should be set to default values.
+ *)
+procedure avcodec_get_frame_defaults (pic: PAVFrame);
+  cdecl; external av__codec;
+
+(**
+ * Allocate an AVFrame and set its fields to default values.  The resulting
+ * struct can be deallocated by simply calling av_free().
+ *
+ * @return An AVFrame filled with default values or NULL on failure.
+ * @see avcodec_get_frame_defaults
+ *)
+function avcodec_alloc_frame(): PAVFrame;
+  cdecl; external av__codec;
+
+function avcodec_default_get_buffer (s: PAVCodecContext; pic: PAVFrame): cint;
+  cdecl; external av__codec;
+procedure avcodec_default_release_buffer (s: PAVCodecContext; pic: PAVFrame);
+  cdecl; external av__codec;
+function avcodec_default_reget_buffer (s: PAVCodecContext; pic: PAVFrame): cint;
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION >= 52066000} // >= 52.66.0
+(**
+ * Return the amount of padding in pixels which the get_buffer callback must
+ * provide around the edge of the image for codecs which do not have the
+ * CODEC_FLAG_EMU_EDGE flag.
+ *
+ * @return Required padding in pixels.
+ *)
+function avcodec_get_edge_width(): cuint;
+  cdecl; external av__codec;
+{$IFEND}
+
+(**
+ * Modify width and height values so that they will result in a memory
+ * buffer that is acceptable for the codec if you do not use any horizontal
+ * padding.
+ *
+ * May only be used if a codec with CODEC_CAP_DR1 has been opened.
+ * If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased
+ * according to avcodec_get_edge_width() before.
+ *)
+procedure avcodec_align_dimensions(s: PAVCodecContext; width: PCint; height: PCint);
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION_MAJOR < 53}  // < 53
+{$IF LIBAVCODEC_VERSION >= 52055000} // >= 52.55.0
+(**
+{$IF LIBAVCODEC_VERSION >= 52084003} // >= 52.84.3
+ * @deprecated Deprecated in favor of av_check_image_size().
+{$ELSE}
+ * Modifiy width and height values so that they will result in a memory
+ * buffer that is acceptable for the codec if you also ensure that all
+ * line sizes are a multiple of the respective linesize_align[i].
+ *
+ * May only be used if a codec with CODEC_CAP_DR1 has been opened.
+ * If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased
+ * according to avcodec_get_edge_width() before.
+{$IFEND}
+ *)
+procedure avcodec_align_dimensions2(s: PAVCodecContext; width: PCint; height: PCint;
+                                    linesize_align: PQuadIntArray);
+  cdecl; external av__codec;
+{$IF LIBAVCODEC_VERSION >= 52084003} // >= 52.84.3
+  deprecated;
+{$IFEND}
+{$IFEND}
+{$IFEND}
+
+(**
+ * Check if the given dimension of a picture is valid, meaning that all
+ * bytes of the picture can be addressed with a signed int.
+ *
+ * @param[in] w Width of the picture.
+ * @param[in] h Height of the picture.
+ * @return Zero if valid, a negative value if invalid.
+ *)
+function avcodec_check_dimensions(av_log_ctx: pointer; w: cuint; h: cuint): cint;
+  cdecl; external av__codec;
+
+
+function avcodec_default_get_format(s: PAVCodecContext; fmt: {const} PAVPixelFormat): TAVPixelFormat;
+  cdecl; external av__codec;
+
+function avcodec_thread_init(s: PAVCodecContext; thread_count: cint): cint;
+  cdecl; external av__codec;
+procedure avcodec_thread_free(s: PAVCodecContext);
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION < 52004000} // < 52.4.0
+function avcodec_thread_execute(s: PAVCodecContext; func: TExecuteFunc; arg: PPointer; var ret: cint; count: cint): cint;
+  cdecl; external av__codec;
+{$ELSEIF LIBAVCODEC_VERSION < 52059000} // < 52.59.0
+function avcodec_thread_execute(s: PAVCodecContext; func: TExecuteFunc; arg: Pointer; var ret: cint; count: cint; size: cint): cint;
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION < 52004000} // < 52.4.0
+function avcodec_default_execute(s: PAVCodecContext; func: TExecuteFunc; arg: PPointer; var ret: cint; count: cint): cint;
+  cdecl; external av__codec;
+{$ELSE}
+function avcodec_default_execute(s: PAVCodecContext; func: TExecuteFunc; arg: Pointer; var ret: cint; count: cint; size: cint): cint;
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52037000} // >= 52.37.0
+function avcodec_default_execute2(s: PAVCodecContext; func: TExecuteFunc; arg: Pointer; var ret: cint; count: cint): cint;
+  cdecl; external av__codec;
+{$IFEND}
+//FIXME func typedef
+
+(**
+ * Initialize the AVCodecContext to use the given AVCodec. Prior to using this
+ * function the context has to be allocated.
+ *
+ * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),
+ * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for
+ * retrieving a codec.
+ *
+ * @warning This function is not thread safe!
+ *
+ * @code
+ * avcodec_register_all();
+ * codec = avcodec_find_decoder(CODEC_ID_H264);
+ * if (!codec)
+ *     exit(1);
+ *
+ * context = avcodec_alloc_context();
+ *
+ * if (avcodec_open(context, codec) < 0)
+ *     exit(1);
+ * @endcode
+ *
+ * @param avctx The context which will be set up to use the given codec.
+ * @param codec The codec to use within the context.
+ * @return zero on success, a negative value on error
+ * @see avcodec_alloc_context, avcodec_find_decoder, avcodec_find_encoder
+ *)
+function avcodec_open(avctx: PAVCodecContext; codec: PAVCodec): cint;
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION < 52000000} // < 52.0.0
+(**
+ * @deprecated Use avcodec_decode_audio2 instead.
+ *)
+function avcodec_decode_audio(avctx: PAVCodecContext; samples: PSmallint;
+                           var frame_size_ptr: cint;
+                           buf: {const} PByteArray; buf_size: cint): cint;
+  cdecl; external av__codec; {deprecated;}
+{$IFEND}
+
+{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+{$IF LIBAVCODEC_VERSION >= 51030000} // 51.30.0
+(**
+ * Decode an audio frame from buf into samples.
+ * Wrapper function which calls avcodec_decode_audio3.
+ *
+ * @deprecated Use avcodec_decode_audio3 instead.
+ * @param avctx the codec context
+ * @param[out] samples the output buffer, sample type in avctx->sample_fmt
+ * @param[in,out] frame_size_ptr the output buffer size in bytes
+ * @param[in] buf the input buffer
+ * @param[in] buf_size the input buffer size in bytes
+ * @return On error a negative value is returned, otherwise the number of bytes
+ * used or zero if no frame could be decompressed.
+ *)
+function avcodec_decode_audio2(avctx: PAVCodecContext; samples: PSmallint;
+               var frame_size_ptr: cint;
+               buf: {const} PByteArray; buf_size: cint): cint;
+  cdecl; external av__codec; {deprecated;}
+{$IFEND}
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52025000} // 52.25.0
+(**
+ * Decode the audio frame of size avpkt->size from avpkt->data into samples.
+ * Some decoders may support multiple frames in a single AVPacket, such
+ * decoders would then just decode the first frame. In this case,
+ * avcodec_decode_audio3 has to be called again with an AVPacket that contains
+ * the remaining data in order to decode the second frame etc.
+ * If no frame
+ * could be outputted, frame_size_ptr is zero. Otherwise, it is the
+ * decompressed frame size in bytes.
+ *
+ * @warning You must set frame_size_ptr to the allocated size of the
+ * output buffer before calling avcodec_decode_audio3().
+ *
+ * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than
+ * the actual read bytes because some optimized bitstream readers read 32 or 64
+ * bits at once and could read over the end.
+ *
+ * @warning The end of the input buffer avpkt->data should be set to 0 to ensure that
+ * no overreading happens for damaged MPEG streams.
+ *
+ * @note You might have to align the input buffer avpkt->data and output buffer
+ * samples. The alignment requirements depend on the CPU: On some CPUs it isn't
+ * necessary at all, on others it won't work at all if not aligned and on others
+ * * it will work but it will have an impact on performance.
+ *
+ * In practice, avpkt->data should have 4 byte alignment at minimum and
+ * samples should be 16 byte aligned unless the CPU doesn't need it
+ * (AltiVec and SSE do).
+ *
+ * @note Some codecs have a delay between input and output, these need to be
+ * fed with avpkt->data=NULL, avpkt->size=0 at the end to return the remaining frames.
+ *
+ * @param avctx the codec context
+ * @param[out] samples the output buffer
+ * @param[in,out] frame_size_ptr the output buffer size in bytes
+ * @param[in] avpkt The input AVPacket containing the input buffer.
+ *            You can create such packet with av_init_packet() and by then setting
+ *            data and size, some decoders might in addition need other fields.
+ *            All decoders are designed to use the least fields possible though.
+ * @return On error a negative value is returned, otherwise the number of bytes
+ * used or zero if no frame data was decompressed (used) from the input AVPacket.
+ *)
+function avcodec_decode_audio3(avctx: PAVCodecContext; samples: PSmallint;
+               var frame_size_ptr: cint;
+               avpkt: PAVPacket): cint;
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+(**
+ * Decode a video frame from buf into picture.
+ * Wrapper function which calls avcodec_decode_video2.
+ *
+ * @deprecated Use avcodec_decode_video2 instead.
+ * @param avctx the codec context
+ * @param[out] picture The AVFrame in which the decoded video frame will be stored.
+ *             Use avcodec_alloc_frame to get an AVFrame, the codec will
+ *             allocate memory for the actual bitmap.
+ *             with default get/release_buffer(), the decoder frees/reuses the bitmap as it sees fit.
+ *             with overridden get/release_buffer() (needs CODEC_CAP_DR1) the user decides into what buffer the decoder
+ *                   decodes and the decoder tells the user once it does not need the data anymore,
+ *                   the user app can at this point free/reuse/keep the memory as it sees fit.
+ *
+ * @param[in] buf the input buffer
+ * @param[in] buf_size the size of the input buffer in bytes
+ * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero.
+ * @return On error a negative value is returned, otherwise the number of bytes
+ * used or zero if no frame could be decompressed.
+ *)
+function avcodec_decode_video(avctx: PAVCodecContext; picture: PAVFrame;
+                       var got_picture_ptr: cint;
+                       buf: {const} PByteArray; buf_size: cint): cint;
+  cdecl; external av__codec; {deprecated;}
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52025000} // 52.25.0
+(**
+ * Decode the video frame of size avpkt->size from avpkt->data into picture.
+ * Some decoders may support multiple frames in a single AVPacket, such
+ * decoders would then just decode the first frame.
+ *
+ * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than
+ * the actual read bytes because some optimized bitstream readers read 32 or 64
+ * bits at once and could read over the end.
+ *
+ * @warning The end of the input buffer buf should be set to 0 to ensure that
+ * no overreading happens for damaged MPEG streams.
+ *
+ * @note You might have to align the input buffer avpkt->data.
+ * The alignment requirements depend on the CPU: on some CPUs it isn't
+ * necessary at all, on others it won't work at all if not aligned and on others
+ * it will work but it will have an impact on performance.
+ *
+ * In practice, avpkt->data should have 4 byte alignment at minimum.
+ *
+ * @param avctx the codec context
+ * @param[out] picture The AVFrame in which the decoded video frame will be stored.
+ * @param[in] avpkt The input AVpacket containing the input buffer.
+ *            You can create such packet with av_init_packet() and by then setting
+ *            data and size, some decoders might in addition need other fields like
+ *            flags&AV_PKT_FLAG_KEY. All decoders are designed to use the least
+ *            fields possible.
+ * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero.
+ * @return On error a negative value is returned, otherwise the number of bytes
+ * used or zero if no frame could be decompressed.
+ *)
+function avcodec_decode_video2(avctx: PAVCodecContext; picture: PAVFrame;
+                       var got_picture_ptr: cint;
+                       avpkt: PAVPacket): cint;
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+(* Decode a subtitle message. Return -1 if error, otherwise return the
+ * number of bytes used. If no subtitle could be decompressed,
+ * got_sub_ptr is zero. Otherwise, the subtitle is stored in*sub.
+ *)
+function avcodec_decode_subtitle(avctx: PAVCodecContext; sub: PAVSubtitle;
+                          var got_sub_ptr: cint;
+                          buf: {const} PByteArray; buf_size: cint): cint;
+  cdecl; external av__codec;
+{$IFEND}
+  
+{$IF LIBAVCODEC_VERSION >= 52025000} // 52.25.0
+(* Decode a subtitle message.
+ * Return a negative value on error, otherwise return the number of bytes used.
+ * If no subtitle could be decompressed, got_sub_ptr is zero.
+ * Otherwise, the subtitle is stored in *sub.
+ * Note that CODEC_CAP_DR1 is not available for subtitle codecs. This is for
+ * simplicity, because the performance difference is expect to be negligible 
+ * and reusing a get_buffer written for video codecs would probably perform badly
+ * due to a potentially very different allocation pattern.
+ *
+ * @param avctx the codec context
+ * @param[out] sub The AVSubtitle in which the decoded subtitle will be stored, must be
+                   freed with avsubtitle_free if *got_sub_ptr is set.
+ * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero.
+ * @param[in] avpkt The input AVPacket containing the input buffer.
+ *)
+function avcodec_decode_subtitle2(avctx: PAVCodecContext; sub: PAVSubtitle;
+                          var got_sub_ptr: cint;
+                          avpkt: PAVPacket): cint;
+  cdecl; external av__codec;
+{$IFEND}
+  
+{$IF LIBAVCODEC_VERSION >= 52082000} // 52.82.0
+(**
+ * Frees all allocated data in the given subtitle struct.
+ *
+ * @param sub AVSubtitle to free.
+ *)
+procedure avsubtitle_free(sub: PAVSubtitle);
+  cdecl; external av__codec;
+{$IFEND}
+
+function avcodec_parse_frame(avctx: PAVCodecContext; pdata: PPointer;
+                      data_size_ptr: PCint;
+                      buf: PByteArray; buf_size: cint): cint;
+  cdecl; external av__codec;
+
+(**
+ * Encode an audio frame from samples into buf.
+ *
+ * @note The output buffer should be at least FF_MIN_BUFFER_SIZE bytes large.
+ * However, for PCM audio the user will know how much space is needed
+ * because it depends on the value passed in buf_size as described
+ * below. In that case a lower value can be used.
+ *
+ * @param avctx the codec context
+ * @param[out] buf the output buffer
+ * @param[in] buf_size the output buffer size
+ * @param[in] samples the input buffer containing the samples
+ * The number of samples read from this buffer is frame_size*channels,
+ * both of which are defined in avctx.
+ * For PCM audio the number of samples read from samples is equal to
+ * buf_size * input_sample_size / output_sample_size.
+ * @return On error a negative value is returned, on success zero or the number
+ * of bytes used to encode the data read from the input buffer.
+ *)
+function avcodec_encode_audio(avctx: PAVCodecContext; buf: PByte;
+                      buf_size: cint; samples: {const} PSmallint): cint;
+  cdecl; external av__codec;
+
+(**
+ * Encode a video frame from pict into buf.
+ * The input picture should be
+ * stored using a specific format, namely avctx.pix_fmt.
+ *
+ * @param avctx the codec context
+ * @param[out] buf the output buffer for the bitstream of encoded frame
+ * @param[in] buf_size the size of the output buffer in bytes
+ * @param[in] pict the input picture to encode
+ * @return On error a negative value is returned, on success zero or the number
+ * of bytes used from the output buffer.
+ *)
+function avcodec_encode_video(avctx: PAVCodecContext; buf: PByte;
+                      buf_size: cint; pict: PAVFrame): cint;
+  cdecl; external av__codec;
+function avcodec_encode_subtitle(avctx: PAVCodecContext; buf: PByteArray;
+                      buf_size: cint; sub: {const} PAVSubtitle): cint;
+  cdecl; external av__codec;
+
+function avcodec_close(avctx: PAVCodecContext): cint;
+  cdecl; external av__codec;
+
+(**
+ * Register all the codecs, parsers and bitstream filters which were enabled at
+ * configuration time. If you do not call this function you can select exactly
+ * which formats you want to support, by using the individual registration
+ * functions.
+ *
+ * @see register_avcodec
+ * @see avcodec_register
+ * @see av_register_codec_parser
+ * @see av_register_bitstream_filter
+ *)
+procedure avcodec_register_all();
+  cdecl; external av__codec;
+
+(**
+ * Flush buffers, should be called when seeking or when switching to a different stream.
+ *)
+procedure avcodec_flush_buffers(avctx: PAVCodecContext);
+  cdecl; external av__codec;
+  
+procedure avcodec_default_free_buffers(s: PAVCodecContext);
+  cdecl; external av__codec;
+
+(* misc useful functions *)
+
+(**
+ * Return a single letter to describe the given picture type pict_type.
+ *
+ * @param[in] pict_type the picture type
+ * @return A single character representing the picture type.
+ *)
+function av_get_pict_type_char(pict_type: cint): AnsiChar;
+  cdecl; external av__codec;
+
+(**
+ * Return codec bits per sample.
+ *
+ * @param[in] codec_id the codec
+ * @return Number of bits per sample or zero if unknown for the given codec.
+ *)
+function av_get_bits_per_sample(codec_id: TCodecID): cint;
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION >= 51041000} // 51.41.0
+(**
+ * Return sample format bits per sample.
+ *
+ * @param[in] sample_fmt the sample format
+ * @return Number of bits per sample or zero if unknown for the given sample format.
+ *)
+function av_get_bits_per_sample_format(sample_fmt: TSampleFormat): cint;
+  cdecl; external av__codec;
+{$IFEND}
+
+const
+  AV_PARSER_PTS_NB      = 4;
+  PARSER_FLAG_COMPLETE_FRAMES = $0001;
+{$IF LIBAVCODEC_VERSION >= 52070000} // 52.70.0
+  PARSER_FLAG_ONCE            = $0002;
+{$IFEND}
+
+type
+  {* frame parsing *}
+  PAVCodecParserContext = ^TAVCodecParserContext;
+  PAVCodecParser = ^TAVCodecParser;
+
+  TAVCodecParserContext = record
+    priv_data: pointer;
+    parser: PAVCodecParser;
+    frame_offset: cint64; (* offset of the current frame *)
+    cur_offset: cint64; (* current offset (incremented by each av_parser_parse()) *)
+    next_frame_offset: cint64; (* offset of the next frame *)
+    (* video info *)
+    pict_type: cint; (* XXX: put it back in AVCodecContext *)
+    (**
+     * This field is used for proper frame duration computation in lavf.
+     * It signals, how much longer the frame duration of the current frame
+     * is compared to normal frame duration.
+     *
+     * frame_duration = (1 + repeat_pict) * time_base
+     *
+     * It is used by codecs like H.264 to display telecined material.
+     *)
+    repeat_pict: cint; (* XXX: put it back in AVCodecContext *)
+    pts: cint64;     (* pts of the current frame *)
+    dts: cint64;     (* dts of the current frame *)
+
+    (* private data *)
+    last_pts: cint64;
+    last_dts: cint64;
+    fetch_timestamp: cint;
+
+    cur_frame_start_index: cint;
+    cur_frame_offset: array [0..AV_PARSER_PTS_NB - 1] of cint64;
+    cur_frame_pts: array [0..AV_PARSER_PTS_NB - 1] of cint64;
+    cur_frame_dts: array [0..AV_PARSER_PTS_NB - 1] of cint64;
+
+    flags: cint;
+
+    {$IF LIBAVCODEC_VERSION >= 51040003} // 51.40.3
+    offset: cint64;      ///< byte offset from starting packet start
+    {$IFEND}
+    {$IF LIBAVCODEC_VERSION >= 51057001} // 51.57.1
+    cur_frame_end: array [0..AV_PARSER_PTS_NB - 1] of cint64;
+    {$IFEND}
+    {$IF LIBAVCODEC_VERSION >= 52016000} // 52.16.0
+    (*!
+     * Set by parser to 1 for key frames and 0 for non-key frames.
+     * It is initialized to -1, so if the parser doesn't set this flag,
+     * old-style fallback using FF_I_TYPE picture type as key frames
+     * will be used.
+     *)
+    key_frame: cint;
+    {$IFEND}
+    {$IF LIBAVCODEC_VERSION >= 52018000} // 52.18.0
+    (**
+     * Time difference in stream time base units from the pts of this
+     * packet to the point at which the output from the decoder has converged
+     * independent from the availability of previous frames. That is, the
+     * frames are virtually identical no matter if decoding started from
+     * the very first frame or from this keyframe.
+     * Is AV_NOPTS_VALUE if unknown.
+     * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY
+     * set.
+     *
+     * The purpose of this field is to allow seeking in streams that have no
+     * keyframes in the conventional sense. It corresponds to the
+     * recovery point SEI in H.264 and match_time_delta in NUT. It is also
+     * essential for some types of subtitle streams to ensure that all
+     * subtitles are correctly displayed after seeking.
+     *)
+    convergence_duration: cint64;
+    {$IFEND}
+    {$IF LIBAVCODEC_VERSION >= 52019000} // 52.19.0
+    // Timestamp generation support:
+    (**
+     * Synchronization point for start of timestamp generation.
+     *
+     * Set to >0 for sync point, 0 for no sync point and <0 for undefined
+     * (default).
+     *
+     * For example, this corresponds to presence of H.264 buffering period
+     * SEI message.
+     *)
+    dts_sync_point: cint;
+
+    (**
+     * Offset of the current timestamp against last timestamp sync point in
+     * units of AVCodecContext.time_base.
+     *
+     * Set to INT_MIN when dts_sync_point unused. Otherwise, it must
+     * contain a valid timestamp offset.
+     *
+     * Note that the timestamp of sync point has usually a nonzero
+     * dts_ref_dts_delta, which refers to the previous sync point. Offset of
+     * the next frame after timestamp sync point will be usually 1.
+     *
+     * For example, this corresponds to H.264 cpb_removal_delay.
+     *)
+    dts_ref_dts_delta: cint;
+
+    (**
+     * Presentation delay of current frame in units of AVCodecContext.time_base.
+     *
+     * Set to INT_MIN when dts_sync_point unused. Otherwise, it must
+     * contain valid non-negative timestamp delta (presentation time of a frame
+     * must not lie in the past).
+     *
+     * This delay represents the difference between decoding and presentation
+     * time of the frame.
+     *
+     * For example, this corresponds to H.264 dpb_output_delay.
+     *)
+    pts_dts_delta: cint;
+    {$IFEND}
+
+    {$IF LIBAVCODEC_VERSION >= 52021000} // 52.21.0
+    (**
+     * Position of the packet in file.
+     *
+     * Analogous to cur_frame_pts/dts
+     *)
+    cur_frame_pos: array [0..AV_PARSER_PTS_NB - 1] of cint64;
+
+    (**
+     * Byte position of currently parsed frame in stream.
+     *)
+    pos: cint64;
+
+    (**
+     * Previous frame byte position.
+     *)
+    last_pos: cint64;
+    {$IFEND}
+  end;
+
+  TAVCodecParser = record
+    codec_ids: array [0..4] of cint; (* several codec IDs are permitted *)
+    priv_data_size: cint;
+    parser_init: function(s: PAVCodecParserContext): cint; cdecl;
+    parser_parse: function(s: PAVCodecParserContext;
+                           avctx: PAVCodecContext;
+                           poutbuf: {const} PPointer; poutbuf_size: PCint;
+                           buf: {const} PByteArray; buf_size: cint): cint; cdecl;
+    parser_close: procedure(s: PAVCodecParserContext); cdecl;
+    split: function(avctx: PAVCodecContext; buf: {const} PByteArray;
+                    buf_size: cint): cint; cdecl;
+    next: PAVCodecParser;
+  end;
+
+
+{$IF LIBAVCODEC_VERSION < 52000000} // 52.0.0
+{
+var
+  av_first_parser: PAVCodecParser; external av__codec;
+}
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 51049000} // 51.49.0
+function av_parser_next(c: PAVCodecParser): PAVCodecParser;
+  cdecl; external av__codec;
+{$IFEND}
+
+procedure av_register_codec_parser(parser: PAVCodecParser);
+  cdecl; external av__codec;
+
+function av_parser_init(codec_id: cint): PAVCodecParserContext;
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
+function av_parser_parse(s: PAVCodecParserContext;
+                  avctx: PAVCodecContext;
+                  poutbuf: PPointer;
+                  poutbuf_size: PCint;
+                  buf: {const} PByteArray;
+                  buf_size: cint;
+                  pts: cint64;
+                  dts: cint64): cint;
+  cdecl; external av__codec; deprecated;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52021000} // 52.21.0
+(**
+ * Parse a packet.
+ *
+ * @param s             parser context.
+ * @param avctx         codec context.
+ * @param poutbuf       set to pointer to parsed buffer or NULL if not yet finished.
+ * @param poutbuf_size  set to size of parsed buffer or zero if not yet finished.
+ * @param buf           input buffer.
+ * @param buf_size      input length, to signal EOF, this should be 0 (so that the last frame can be output).
+ * @param pts           input presentation timestamp.
+ * @param dts           input decoding timestamp.
+ * @param pos           input byte position in stream.
+ * @return the number of bytes of the input bitstream used.
+ *
+ * Example:
+ * @code
+ *   while (in_len) do
+ *   begin
+ *     len := av_parser_parse2(myparser, AVCodecContext, data, size,
+ *                                       in_data, in_len,
+ *                                       pts, dts, pos);
+ *      in_data := in_data + len;
+ *      in_len  := in_len  - len;
+ *
+ *      if (size) then
+ *        decode_frame(data, size);
+ *   end;
+ * @endcode
+ *)
+function av_parser_parse2(s:    PAVCodecParserContext;
+                  avctx:        PAVCodecContext;
+                  poutbuf:      PPointer;
+                  poutbuf_size: PCint;
+                  buf: {const}  PByteArray;
+                  buf_size:     cint;
+                  pts:          cint64;
+                  dts:          cint64;
+                  pos:          cint64): cint;
+   cdecl; external av__codec;
+{$IFEND}
+
+function av_parser_change(s: PAVCodecParserContext;
+                   avctx: PAVCodecContext;
+                   poutbuf: PPointer; poutbuf_size: PCint;
+                   buf: {const} PByteArray; buf_size: cint; keyframe: cint): cint;
+  cdecl; external av__codec;
+procedure av_parser_close(s: PAVCodecParserContext);
+  cdecl; external av__codec;
+
+type
+  PAVBitStreamFilterContext = ^TAVBitStreamFilterContext;
+  PAVBitStreamFilter = ^TAVBitStreamFilter;
+
+  TAVBitStreamFilterContext = record
+    priv_data: pointer;
+    filter: PAVBitStreamFilter;
+    parser: PAVCodecParserContext;
+    next: PAVBitStreamFilterContext;
+  end;
+
+  TAVBitStreamFilter = record
+    name: PAnsiChar;
+    priv_data_size: cint;
+    filter: function(bsfc: PAVBitStreamFilterContext;
+                  avctx: PAVCodecContext; args: PByteArray;
+                  poutbuf: PPointer; poutbuf_size: PCint;
+                  buf: PByte; buf_size: cint; keyframe: cint): cint; cdecl;
+    {$IF LIBAVCODEC_VERSION >= 51043000} // 51.43.0
+    close: procedure(bsfc: PAVBitStreamFilterContext);
+    {$IFEND}
+    next: PAVBitStreamFilter;
+  end;
+
+procedure av_register_bitstream_filter(bsf: PAVBitStreamFilter);
+  cdecl; external av__codec;
+
+function av_bitstream_filter_init(name: PAnsiChar): PAVBitStreamFilterContext;
+  cdecl; external av__codec;
+
+function av_bitstream_filter_filter(bsfc: PAVBitStreamFilterContext;
+                               avctx: PAVCodecContext; args: PByteArray;
+                               poutbuf: PPointer; poutbuf_size: PCint;
+                               buf: PByte; buf_size: cint; keyframe: cint): cint;
+  cdecl; external av__codec;
+
+procedure av_bitstream_filter_close(bsf: PAVBitStreamFilterContext);
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION >= 51049000} // 51.49.0
+function av_bitstream_filter_next(f: PAVBitStreamFilter): PAVBitStreamFilter;
+  cdecl; external av__codec;
+{$IFEND}
+
+(* memory *)
+
+(**
+ * Reallocate the given block if it is not large enough, otherwise do nothing.
+ *
+ * @see av_realloc
+ *)
+procedure av_fast_realloc(ptr: pointer; size: PCuint; min_size: cuint);
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION >= 52025000} // >= 52.25.0
+(**
+ * Allocate a buffer, reusing the given one if large enough.
+ *
+ * Contrary to av_fast_realloc the current buffer contents might not be
+ * preserved and on error the old buffer is freed, thus no special
+ * handling to avoid memleaks is necessary.
+ *
+ * @param ptr pointer to pointer to already allocated buffer, overwritten with pointer to new buffer
+ * @param size size of the buffer *ptr points to
+ * @param min_size minimum size of *ptr buffer after returning, *ptr will be NULL and
+ *                 *size 0 if an error occurred.
+ *)
+procedure av_fast_malloc(ptr: pointer; size: PCuint; min_size: cuint);
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION < 51057000} // 51.57.0
+(* for static data only *)
+
+(**
+ * Frees all static arrays and resets their pointers to 0.
+ * Call this function to release all statically allocated tables.
+ *
+ * @deprecated. Code which uses av_free_static is broken/misdesigned
+ * and should correctly use static arrays
+ *
+ *)
+procedure av_free_static();
+  cdecl; external av__codec; deprecated;
+
+(**
+ * Allocation of static arrays.
+ *
+ * @warning Do not use for normal allocation.
+ *
+ * @param[in] size The amount of memory you need in bytes.
+ * @return block of memory of the requested size
+ * @deprecated. Code which uses av_mallocz_static is broken/misdesigned
+ * and should correctly use static arrays
+ *)
+procedure av_mallocz_static(size: cuint);
+  cdecl; external av__codec; deprecated; {av_malloc_attrib av_alloc_size(1)}
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52085000} // 52.85.0
+(**
+ * Copy image data in src_data to dst_data.
+ *
+ * @param dst_linesize linesizes for the image in dst_data
+ * @param src_linesize linesizes for the image in src_data
+ *)
+type
+  PQuaduint8Array = ^TQuaduint8Array;
+  TQuaduint8Array = array [0..3] of cuint8;
+
+procedure av_picture_data_copy(dst_data: PQuaduint8Array; dst_linesize: TQuadIntArray;
+                               src_data: PQuaduint8Array; src_linesize: TQuadIntArray;
+                               pix_fmt:  TAVPixelFormat;  width: cint; height: cint);
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION < 51035000} // 51.35.0
+procedure av_realloc_static(ptr: pointer; size: cuint);
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 51039000} // 51.39.0
+(**
+ * Copy image src to dst. Wraps av_picture_data_copy() above.
+ *)
+procedure av_picture_copy(dst: PAVPicture; 
+              src: {const} PAVPicture;
+{$IF LIBAVCODEC_VERSION < 52022001} // 52.22.1
+              pix_fmt: cint;
+{$ELSE}
+              pix_fmt: TAVPixelFormat;
+{$IFEND}
+              width:  cint;
+              height: cint);
+  cdecl; external av__codec;
+
+(**
+ * Crop image top and left side.
+ *)
+function av_picture_crop(dst: PAVPicture;
+              src: {const} PAVPicture;
+{$IF LIBAVCODEC_VERSION < 52022001} // 52.22.1
+              pix_fmt: cint;
+{$ELSE}
+              pix_fmt: TAVPixelFormat;
+{$IFEND}
+              top_band:  cint;
+              left_band: cint): cint;
+  cdecl; external av__codec;
+
+(**
+ * Pad image.
+ *)
+function av_picture_pad(dst: PAVPicture;
+            src: {const} PAVPicture;
+            height: cint;
+            width: cint;
+{$IF LIBAVCODEC_VERSION < 52022001} // 52.22.1
+            pix_fmt: cint;
+{$ELSE}
+            pix_fmt: TAVPixelFormat;
+{$IFEND}
+            padtop: cint;
+            padbottom: cint;
+            padleft: cint;
+            padright:
+            cint;
+            color: PCint): cint;
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION < 52000000} // 52.0.0
+(**
+ * @deprecated Use the software scaler (swscale) instead.
+ *)
+procedure img_copy(dst: PAVPicture; src: {const} PAVPicture;
+                    pix_fmt: TAVPixelFormat; width: cint; height: cint);
+  cdecl; external av__codec; deprecated;
+
+(**
+ * @deprecated Use the software scaler (swscale) instead.
+ *)
+function img_crop(dst: PAVPicture; src: {const} PAVPicture;
+           pix_fmt: TAVPixelFormat; top_band, left_band: cint): cint;
+  cdecl; external av__codec; deprecated;
+
+(**
+ * @deprecated Use the software scaler (swscale) instead.
+ *)
+function img_pad(dst: PAVPicture; src: {const} PAVPicture; height, width: cint;
+                  pix_fmt: TAVPixelFormat; padtop, padbottom, padleft, padright: cint;
+                  color: PCint): cint;
+  cdecl; external av__codec; deprecated;
+{$IFEND}
+
+(**
+ * Encode extradata length to a buffer. Used by xiph codecs.
+ *
+ * @param s buffer to write to; must be at least (v/255+1) bytes long
+ * @param v size of extradata in bytes
+ * @return number of bytes written to the buffer.
+ *)
+function av_xiphlacing(s: PByte; v: cuint): cuint;
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION_MAJOR < 53}  // < 53
+{$IF LIBAVCODEC_VERSION >= 51041000} // >= 51.41.0
+(**
+ * Parse str and put in width_ptr and height_ptr the detected values.
+ *
+{$IF LIBAVCODEC_VERSION >= 52084001} // >= 52.84.1
+ * @deprecated Deprecated in favor of av_parse_video_size().
+{$ELSE}
+ * @return 0 in case of a successful parsing, a negative value otherwise
+ * @param[in] str the string to parse: it has to be a string in the format
+ * width x height or a valid video frame size abbreviation.
+ * @param[in,out] width_ptr pointer to the variable which will contain the detected
+ * frame width value
+ * @param[in,out] height_ptr pointer to the variable which will contain the detected
+ * frame height value
+{$IFEND}
+ *)
+function av_parse_video_frame_size(width_ptr: PCint; height_ptr: PCint; str: {const} PAnsiChar): cint;
+  cdecl; external av__codec;
+{$IF LIBAVCODEC_VERSION >= 52084001} // >= 52.84.1
+  deprecated;
+{$IFEND}
+
+(**
+ * Parse str and store the detected values in *frame_rate.
+ *
+{$IF LIBAVCODEC_VERSION >= 52084001} // >= 52.84.1
+ * @deprecated Deprecated in favor of av_parse_video_rate().
+{$ELSE}
+ * @return 0 in case of a successful parsing, a negative value otherwise
+ * @param[in] str the string to parse: it has to be a string in the format
+ * frame_rate_num / frame_rate_den, a float number or a valid video rate abbreviation
+ * @param[in,out] frame_rate pointer to the AVRational which will contain the detected
+ * frame rate
+{$IFEND}
+ *)
+function av_parse_video_frame_rate(frame_rate: PAVRational; str: {const} PAnsiChar): cint;
+  cdecl; external av__codec;
+{$IF LIBAVCODEC_VERSION >= 52084001} // >= 52.84.1
+  deprecated;
+{$IFEND}
+{$IFEND}
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION < 52059000} // <52.59.0
+
+{
+ The following error codes are moved to libavutil/error.h on 
+ revision 22501 Mar 13 2010
+}
+
+{* error handling *}
+
+const
+{$IFDEF UNIX}
+  ENOENT = ESysENOENT;
+  EIO    = ESysEIO;
+  ENOMEM = ESysENOMEM;
+  EINVAL = ESysEINVAL;
+  EDOM   = ESysEDOM;
+  ENOSYS = ESysENOSYS;
+  EILSEQ = ESysEILSEQ;
+  EPIPE  = ESysEPIPE;
+{$ELSE}
+  ENOENT = 2;
+  EIO    = 5;
+  ENOMEM = 12;
+  EINVAL = 22;
+  EPIPE  = 32;  // just an assumption. needs to be checked.
+  EDOM   = 33;
+  {$IFDEF MSWINDOWS}
+  // Note: we assume that ffmpeg was compiled with MinGW.
+  // This must be changed if DLLs were compiled with cygwin.
+  ENOSYS = 40;  // MSVC/MINGW: 40, CYGWIN: 88,  LINUX/FPC: 38
+  EILSEQ = 42;  // MSVC/MINGW: 42, CYGWIN: 138, LINUX/FPC: 84
+  {$ENDIF}
+{$ENDIF}
+
+(**
+ * We need the sign of the error, because some platforms have 
+ * E* and errno already negated. The previous version failed
+ * with Delphi, because it needed EINVAL defined.
+ * Warning: This code is platform dependent and assumes constants 
+ * to be 32 bit.
+ * This version does the following steps:
+ * 1) shr 30:        shifts the sign bit to bit position 2
+ * 2) and $00000002: sets all other bits to zero
+ *                   positive EINVAL gives 0, negative gives 2
+ * 3) - 1:           positive EINVAL gives -1, negative 1
+ *)
+const
+  AVERROR_SIGN = (EINVAL shr 30) and $00000002 - 1;
+
+(*
+#if EINVAL > 0
+#define AVERROR(e) (-(e)) {**< Returns a negative error code from a POSIX error code, to return from library functions. *}
+#define AVUNERROR(e) (-(e)) {**< Returns a POSIX error code from a library function error return value. *}
+#else
+{* Some platforms have E* and errno already negated. *}
+#define AVERROR(e) (e)
+#define AVUNERROR(e) (e)
+#endif
+*)
+
+const
+  AVERROR_UNKNOWN     = AVERROR_SIGN * EINVAL;  (**< unknown error *)
+  AVERROR_IO          = AVERROR_SIGN * EIO;     (**< I/O error *)
+  AVERROR_NUMEXPECTED = AVERROR_SIGN * EDOM;    (**< Number syntax expected in filename. *)
+  AVERROR_INVALIDDATA = AVERROR_SIGN * EINVAL;  (**< invalid data found *)
+  AVERROR_NOMEM       = AVERROR_SIGN * ENOMEM;  (**< not enough memory *)
+  AVERROR_NOFMT       = AVERROR_SIGN * EILSEQ;  (**< unknown format *)
+  AVERROR_NOTSUPP     = AVERROR_SIGN * ENOSYS;  (**< Operation not supported. *)
+  AVERROR_NOENT       = AVERROR_SIGN * ENOENT;  (**< No such file or directory. *)
+{$IF LIBAVCODEC_VERSION >= 52017000} // 52.17.0
+  AVERROR_EOF         = AVERROR_SIGN * EPIPE;   (**< End of file. *)
+{$IFEND}
+  // Note: function calls as constant-initializers are invalid
+  //AVERROR_PATCHWELCOME = -MKTAG('P','A','W','E'); {**< Not yet implemented in FFmpeg. Patches welcome. *}
+  AVERROR_PATCHWELCOME = -(ord('P') or (ord('A') shl 8) or (ord('W') shl 16) or (ord('E') shl 24));
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52032000} // >= 52.32.0
+(**
+ * Log a generic warning message about a missing feature. This function is
+ * intended to be used internally by FFmpeg (libavcodec, libavformat, etc.)
+ * only, and would normally not be used by applications.
+ * @param[in] avc a pointer to an arbitrary struct of which the first field is
+ * a pointer to an AVClass struct
+ * @param[in] feature string containing the name of the missing feature
+ * @param[in] want_sample indicates if samples are wanted which exhibit this feature.
+ * If want_sample is non-zero, additional verbage will be added to the log
+ * message which tells the user how to report samples to the development
+ * mailing list.
+ *)
+procedure av_log_missing_feature(avc: Pointer; feature: {const} Pchar; want_sample: cint);
+  cdecl; external av__codec;
+
+(**
+ * Log a generic warning message asking for a sample. This function is
+ * intended to be used internally by FFmpeg (libavcodec, libavformat, etc.)
+ * only, and would normally not be used by applications.
+ * @param[in] avc a pointer to an arbitrary struct of which the first field is
+ * a pointer to an AVClass struct
+ * @param[in] msg string containing an optional message, or NULL if no message
+ *)
+procedure av_log_ask_for_sample(avc: Pointer; msg: {const} Pchar);
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52018000} // 52.18.0
+(**
+ * Register the hardware accelerator hwaccel.
+ *)
+procedure av_register_hwaccel (hwaccel: PAVHWAccel)
+  cdecl; external av__codec;
+
+(**
+ * If hwaccel is NULL, returns the first registered hardware accelerator,
+ * if hwaccel is non-NULL, returns the next registered hardware accelerator
+ * after hwaccel, or NULL if hwaccel is the last one.
+ *)
+function av_hwaccel_next (hwaccel: PAVHWAccel): PAVHWAccel;
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52030000} // 52.30.0
+(**
+ * Lock operation used by lockmgr
+ *)
+type
+  TAVLockOp = (
+    AV_LOCK_CREATE,  ///< Create a mutex
+    AV_LOCK_OBTAIN,  ///< Lock the mutex
+    AV_LOCK_RELEASE, ///< Unlock the mutex
+    AV_LOCK_DESTROY  ///< Free mutex resources
+  );
+
+(**
+ * Register a user provided lock manager supporting the operations
+ * specified by AVLockOp. mutex points to a (void) where the
+ * lockmgr should store/get a pointer to a user allocated mutex. It's
+ * NULL upon AV_LOCK_CREATE and != NULL for all other ops.
+ *
+ * @param cb User defined callback. Note: FFmpeg may invoke calls to this
+ *           callback during the call to av_lockmgr_register().
+ *           Thus, the application must be prepared to handle that.
+ *           If cb is set to NULL the lockmgr will be unregistered.
+ *           Also note that during unregistration the previously registered
+ *           lockmgr callback may also be invoked.
+ *)
+// ToDo: Implement and test this
+//function av_lockmgr_register(cb: function (mutex: pointer; op: TAVLockOp)): cint;
+//  cdecl; external av__codec;
+{$IFEND}
+
+implementation
+
+{$IF (LIBAVCODEC_VERSION >= 52025000) and (LIBAVCODEC_VERSION <= 52027000)} // 52.25.0 - 52.27.0
+procedure av_free_packet(pkt: PAVPacket);{$IFDEF HASINLINE} inline; {$ENDIF} 
+begin
+  if assigned(pkt) then
+  begin
+    if assigned(pkt^.destruct) then
+      pkt^.destruct(pkt);
+    pkt^.data := NIL;
+    pkt^.size := 0;
+  end;
+end;
+{$IFEND}
+
+end.
diff --git a/songmanagement/src/lib/ffmpeg/avformat.pas b/songmanagement/src/lib/ffmpeg/avformat.pas
new file mode 100644
index 00000000..bd13c70e
--- /dev/null
+++ b/songmanagement/src/lib/ffmpeg/avformat.pas
@@ -0,0 +1,2100 @@
+(*
+ * copyright (c) 2001 Fabrice Bellard
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * This is a part of Pascal porting of ffmpeg.
+ * - Originally by Victor Zinetz for Delphi and Free Pascal on Windows.
+ * - For Mac OS X, some modifications were made by The Creative CAT, denoted as CAT
+ *   in the source codes.
+ * - Changes and updates by the UltraStar Deluxe Team
+ *
+ * Conversion of libavformat/avformat.h
+ * Min. version: 50.5.0 , revision  6577, Sat Oct  7 15:30:46 2006 UTC
+ * Max. version: 52.78.3, revision 24841, Thu Aug 26 02:00:00 2010 CET
+ *)
+
+unit avformat;
+
+{$IFDEF FPC}
+  {$MODE DELPHI }
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$I switches.inc}  (* for the HasInline define *)
+
+{$IFDEF DARWIN}
+  {$linklib libavformat}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  avcodec,
+  avutil,
+  avio,
+  rational,
+  SysUtils,
+  UConfig;
+
+const
+  (*
+   * IMPORTANT: The official FFmpeg C headers change very quickly. Often some
+   * of the data structures are changed so that they become incompatible with
+   * older header files. The Pascal headers have to be adjusted to those changes,
+   * otherwise the application might crash randomly or strange bugs (not
+   * necessarily related to video or audio due to buffer overflows etc.) might
+   * occur.
+   *
+   * In the past users reported problems with USDX that took hours to fix and
+   * the problem was an unsupported version of FFmpeg. So we decided to disable
+   * support for future versions of FFmpeg until the headers are revised by us
+   * for that version as they otherwise most probably will break USDX.
+   *
+   * If the headers do not yet support your FFmpeg version you may want to
+   * adjust the max. version numbers manually but please note: it may work but
+   * in many cases it does not. The USDX team does NOT PROVIDE ANY SUPPORT
+   * for the game if the MAX. VERSION WAS CHANGED.
+   *
+   * The only safe way to support new versions of FFmpeg is to add the changes
+   * of the FFmpeg git repository C headers to the Pascal headers.
+   * You can accelerate this process by posting a patch with the git changes
+   * translated to Pascal to our bug tracker (please join our IRC chat before
+   * you start working on it). Simply adjusting the max. versions is NOT a valid
+   * fix. 
+   *)
+  (* Max. supported version by this header *)
+  LIBAVFORMAT_MAX_VERSION_MAJOR   = 52;
+  LIBAVFORMAT_MAX_VERSION_MINOR   = 78;
+  LIBAVFORMAT_MAX_VERSION_RELEASE = 3;
+  LIBAVFORMAT_MAX_VERSION = (LIBAVFORMAT_MAX_VERSION_MAJOR * VERSION_MAJOR) +
+                            (LIBAVFORMAT_MAX_VERSION_MINOR * VERSION_MINOR) +
+                            (LIBAVFORMAT_MAX_VERSION_RELEASE * VERSION_RELEASE);
+
+  (* Min. supported version by this header *)
+  LIBAVFORMAT_MIN_VERSION_MAJOR   = 50;
+  LIBAVFORMAT_MIN_VERSION_MINOR   = 5;
+  LIBAVFORMAT_MIN_VERSION_RELEASE = 0;
+  LIBAVFORMAT_MIN_VERSION = (LIBAVFORMAT_MIN_VERSION_MAJOR * VERSION_MAJOR) +
+                            (LIBAVFORMAT_MIN_VERSION_MINOR * VERSION_MINOR) +
+                            (LIBAVFORMAT_MIN_VERSION_RELEASE * VERSION_RELEASE);
+
+(* Check if linked versions are supported *)
+{$IF (LIBAVFORMAT_VERSION < LIBAVFORMAT_MIN_VERSION)}
+  {$MESSAGE Error 'Linked version of libavformat is too old!'}
+{$IFEND}
+
+(* Check if linked versions are supported *)
+{$IF (LIBAVFORMAT_VERSION > LIBAVFORMAT_MAX_VERSION)}
+  {$MESSAGE Error 'Linked version of libavformat is not yet supported!'}
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52078003} // >= 52.78.3
+(**
+ * Those FF_API_* defines are not part of public API.
+ * They may change, break or disappear at any time.
+ *)
+const
+  {$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+  FF_API_MAX_STREAMS       = (LIBAVFORMAT_VERSION_MAJOR < 53);
+  FF_API_OLD_METADATA      = (LIBAVFORMAT_VERSION_MAJOR < 53);
+  FF_API_REGISTER_PROTOCOL = (LIBAVFORMAT_VERSION_MAJOR < 53);
+  FF_API_URL_RESETBUF      = (LIBAVFORMAT_VERSION_MAJOR < 53);
+  {$ELSE}
+  FF_API_URL_CLASS    = (LIBAVFORMAT_VERSION_MAJOR >= 53);
+  {$IFEND}
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52020000} // 52.20.0
+(**
+ * I return the LIBAVFORMAT_VERSION_INT constant.  You got
+ * a fucking problem with that, douchebag?
+ *)
+function avformat_version(): cuint;
+  cdecl; external av__format;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52039002} // 52.39.2
+(**
+ * Return the libavformat build-time configuration.
+ *)
+function avformat_configuration(): {const} PansiChar;
+  cdecl; external av__format;
+
+(**
+ * Return the libavformat license.
+ *)
+function avformat_license(): {const} PansiChar;
+  cdecl; external av__format;
+{$IFEND}
+
+type
+  PAVFile = Pointer;
+
+(*
+ * Public Metadata API.
+ * The metadata API allows libavformat to export metadata tags to a client
+ * application using a sequence of key/value pairs. Like all strings in FFmpeg,
+ * metadata must be stored as UTF-8 encoded Unicode. Note that metadata
+ * exported by demuxers isn't checked to be valid UTF-8 in most cases.
+ * Important concepts to keep in mind:
+ * 1. Keys are unique; there can never be 2 tags with the same key. This is
+ *    also meant semantically, i.e., a demuxer should not knowingly produce
+ *    several keys that are literally different but semantically identical.
+ *    E.g., key=Author5, key=Author6. In this example, all authors must be
+ *    placed in the same tag.
+ * 2. Metadata is flat, not hierarchical; there are no subtags. If you
+ *    want to store, e.g., the email address of the child of producer Alice
+ *    and actor Bob, that could have key=alice_and_bobs_childs_email_address.
+ * 3. A tag whose value is localized for a particular language is appended
+ *    with a dash character ('-') and the ISO 639-2/B 3-letter language code.
+ *    For example: Author-ger=Michael, Author-eng=Mike
+ *    The original/default language is in the unqualified "Author" tag.
+ *    A demuxer should set a default if it sets any translated tag.
+ *)
+const
+  AV_METADATA_MATCH_CASE    = 1;
+  AV_METADATA_IGNORE_SUFFIX = 2;
+{$IF LIBAVFORMAT_VERSION >= 52043000} // >= 52.43.0
+  AV_METADATA_DONT_STRDUP_KEY = 4;
+  AV_METADATA_DONT_STRDUP_VAL = 8;
+{$IFEND}
+{$IF LIBAVFORMAT_VERSION >= 52061000} // >= 52.61.0
+  AV_METADATA_DONT_OVERWRITE  = 16;
+{$IFEND}
+
+type
+  PAVMetadataTag = ^TAVMetadataTag;
+  TAVMetadataTag = record
+    key:   PAnsiChar;
+    value: PAnsiChar;
+  end;
+
+  PAVMetadata = Pointer;
+
+{$IF LIBAVFORMAT_VERSION > 52024001} // > 52.24.1
+(**
+ * Get a metadata element with matching key.
+ *
+ * @param prev Set to the previous matching element to find the next.
+ *             If set to NULL the first matching element is returned.
+ * @param flags Allows case as well as suffix-insensitive comparisons.
+ * @return Found tag or NULL, changing key or value leads to undefined behavior.
+ *)
+function av_metadata_get(m: PAVMetadata; key: {const} PAnsiChar;
+                         prev: {const} PAVMetadataTag ; flags: cint): PAVMetadataTag;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION < 52078003} // < 52.78.3
+(**
+ * Set the given tag in *pm, overwriting an existing tag.
+ *
+ * @param pm pointer to a pointer to a metadata struct. If *pm is NULL
+ * a metadata struct is allocated and put in *pm.
+ * @param key tag key to add to *pm (will be av_strduped)
+ * @param value tag value to add to *pm (will be av_strduped)
+ * @return >= 0 on success otherwise an error code <0
+ * @deprecated Use av_metadata_set2() instead.
+ *)
+function av_metadata_set(var pm: PAVMetadata; key: {const} PAnsiChar; value: {const} PAnsiChar): cint;
+  cdecl; external av__format;
+  {$IF LIBAVFORMAT_VERSION >= 52061000} // >= 52.61.0
+    deprecated;
+  {$IFEND}
+{$ELSE}
+  {$IFDEF FF_API_OLD_METADATA}
+(**
+ * Set the given tag in *pm, overwriting an existing tag.
+ *
+ * @param pm pointer to a pointer to a metadata struct. If *pm is NULL
+ * a metadata struct is allocated and put in *pm.
+ * @param key tag key to add to *pm (will be av_strduped)
+ * @param value tag value to add to *pm (will be av_strduped)
+ * @return >= 0 on success otherwise an error code <0
+ * @deprecated Use av_metadata_set2() instead.
+ *)
+function av_metadata_set(var pm: PAVMetadata; key: {const} PAnsiChar; value: {const} PAnsiChar): cint;
+  cdecl; external av__format; deprecated;
+  {$ENDIF}
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52043000} // >= 52.43.0
+(**
+ * Set the given tag in *pm, overwriting an existing tag.
+ *
+ * @param pm pointer to a pointer to a metadata struct. If *pm is NULL
+ * a metadata struct is allocated and put in *pm.
+ * @param key tag key to add to *pm (will be av_strduped depending on flags)
+ * @param value tag value to add to *pm (will be av_strduped depending on flags).
+ *        Passing a NULL value will cause an existing tag to be deleted.
+ * @return >= 0 on success otherwise an error code <0
+ *)
+function av_metadata_set2(var pm: PAVMetadata; key: {const} PAnsiChar; value: {const} PAnsiChar; flags: cint): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Free all the memory allocated for an AVMetadata struct.
+ *)
+procedure av_metadata_free(var m: PAVMetadata);
+  cdecl; external av__format;
+{$IFEND}
+
+(* packet functions *)
+
+{$IF LIBAVFORMAT_VERSION < 52032000} // < 52.32.0
+type
+  PAVPacket = ^TAVPacket;
+  TAVPacket = record
+    (**
+     * Presentation timestamp in time_base units; the time at which the
+     * decompressed packet will be presented to the user.
+     * Can be AV_NOPTS_VALUE if it is not stored in the file.
+     * pts MUST be larger or equal to dts as presentation can not happen before
+     * decompression, unless one wants to view hex dumps. Some formats misuse
+     * the terms dts and pts/cts to mean something different. Such timestamps
+     * must be converted to true pts/dts before they are stored in AVPacket.
+     *)
+    pts: cint64;
+    (**
+     * Decompression timestamp in time_base units; the time at which the
+     * packet is decompressed.
+     * Can be AV_NOPTS_VALUE if it is not stored in the file.
+     *)
+    dts: cint64;
+    data: PByteArray;
+    size: cint;
+    stream_index: cint;
+    flags: cint;
+    (**
+     * Duration of this packet in time_base units, 0 if unknown.
+     * Equals next_pts - this_pts in presentation order.
+     *)
+    duration: cint;
+    destruct: procedure (p: PAVPacket); cdecl;
+    priv: pointer;
+    pos: cint64;                            ///< byte position in stream, -1 if unknown
+
+    {$IF LIBAVFORMAT_VERSION >= 52022000} // 52.22.0
+    (**
+     * Time difference in stream time base units from the pts of this
+     * packet to the point at which the output from the decoder has converged
+     * independent from the availability of previous frames. That is, the
+     * frames are virtually identical no matter if decoding started from
+     * the very first frame or from this keyframe.
+     * Is AV_NOPTS_VALUE if unknown.
+     * This field is not the display duration of the current packet.
+     *
+     * The purpose of this field is to allow seeking in streams that have no
+     * keyframes in the conventional sense. It corresponds to the
+     * recovery point SEI in H.264 and match_time_delta in NUT. It is also
+     * essential for some types of subtitle streams to ensure that all
+     * subtitles are correctly displayed after seeking.
+     *)
+    convergence_duration: cint64;
+    {$IFEND}
+  end;
+  
+const
+  PKT_FLAG_KEY = $0001;
+
+procedure av_destruct_packet_nofree(var pkt: TAVPacket);
+  cdecl; external av__format;
+
+(**
+ * Default packet destructor.
+ *)
+procedure av_destruct_packet(var pkt: TAVPacket);
+  cdecl; external av__format;
+
+(**
+ * Initialize optional fields of a packet with default values.
+ *
+ * @param pkt packet
+ *)
+procedure av_init_packet(var pkt: TAVPacket);
+{$IF LIBAVFORMAT_VERSION >= 51012002} // 51.12.2
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Allocate the payload of a packet and initialize its fields with
+ * default values.
+ *
+ * @param pkt packet
+ * @param size wanted payload size
+ * @return 0 if OK, AVERROR_xxx otherwise
+ *)
+function av_new_packet(var pkt: TAVPacket; size: cint): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Allocate and read the payload of a packet and initialize its fields with
+ * default values.
+ *
+ * @param pkt packet
+ * @param size desired payload size
+ * @return >0 (read size) if OK, AVERROR_xxx otherwise
+ *)
+function av_get_packet(s: PByteIOContext; var pkt: TAVPacket; size: cint): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION < 52032000} // < 52.32.0
+(**
+ * @warning This is a hack - the packet memory allocation stuff is broken. The
+ * packet is allocated if it was not really allocated.
+ *)
+function av_dup_packet(pkt: PAVPacket): cint;
+  cdecl; external av__format;
+
+(**
+ * Free a packet.
+ *
+ * @param pkt packet to free
+ *)
+procedure av_free_packet(pkt: PAVPacket); {$IFDEF HasInline}inline;{$ENDIF}
+{$IFEND}
+
+(*************************************************)
+(* fractional numbers for exact pts handling *)
+
+type
+ (**
+  * The exact value of the fractional number is: 'val + num / den'.
+  * num is assumed to be 0 <= num < den.
+  *)
+  PAVFrac = ^TAVFrac;
+  TAVFrac = record
+    val, num, den: cint64;
+  end;
+
+(*************************************************)
+(* input/output formats *)
+
+type
+  (**
+   * This structure contains the data a format has to probe a file.
+   *)
+  TAVProbeData = record
+    filename: PAnsiChar;
+    buf: PByteArray;  (**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. *)
+    buf_size: cint;   (**< Size of buf except extra allocated bytes *)
+  end;
+
+const
+  AVPROBE_SCORE_MAX   = 100;   ///< Maximum score, half of that is used for file-extension-based detection
+  AVPROBE_PADDING_SIZE = 32;   ///< extra allocated bytes at the end of the probe buffer
+
+  //! Demuxer will use url_fopen, no opened file should be provided by the caller.
+  AVFMT_NOFILE        = $0001;
+  AVFMT_NEEDNUMBER    = $0002; (**< Needs '%d' in filename. *)
+  AVFMT_SHOW_IDS      = $0008; (**< Show format stream IDs numbers. *)
+  AVFMT_RAWPICTURE    = $0020; (**< Format wants AVPicture structure for
+                                      raw picture data. *)
+  AVFMT_GLOBALHEADER  = $0040; (**< Format wants global header. *)
+  AVFMT_NOTIMESTAMPS  = $0080; (**< Format does not need / have any timestamps. *)
+  AVFMT_GENERIC_INDEX = $0100; (**< Use generic index building code. *)
+  AVFMT_TS_DISCONT    = $0200; (**< Format allows timestamp discontinuities. *)
+  {$IF LIBAVFORMAT_VERSION >= 52029002} // 52.29.2
+  AVFMT_VARIABLE_FPS  = $0400; (**< Format allows variable fps. *)
+  {$IFEND}
+  {$IF LIBAVFORMAT_VERSION >= 52052000} // 52.52.0
+  AVFMT_NODIMENSIONS  = $0800; (**< Format does not need width/height *)
+  {$IFEND}
+
+  // used by AVIndexEntry
+  AVINDEX_KEYFRAME = $0001;
+
+  AVFMTCTX_NOHEADER = $0001; (**< signal that no header is present
+                                         (streams are added dynamically) *)
+
+{$IF LIBAVFORMAT_VERSION < 52078003}  // < 52.78.3
+  {$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+  MAX_STREAMS = 20;
+  {$ELSE}
+    {$IF LIBAVFORMAT_VERSION < 52068000}  // < 52.68.0
+  MAX_STREAMS = 100;
+    {$IFEND}
+  {$IFEND}
+{$ELSE}
+  {$IFDEF FF_API_MAX_STREAMS}
+  MAX_STREAMS = 20;
+  {$ENDIF}
+{$IFEND}
+
+
+  AVFMT_NOOUTPUTLOOP = -1;
+  AVFMT_INFINITEOUTPUTLOOP = 0;
+  AVFMT_FLAG_GENPTS = $0001;   ///< Generate missing pts even if it requires parsing future frames.
+  AVFMT_FLAG_IGNIDX = $0002;   ///< Ignore index.
+  AVFMT_FLAG_NONBLOCK = $0004; ///< Do not block when reading packets from input.
+{$IF LIBAVFORMAT_VERSION >= 52048000}  // >= 52.48.0
+  AVFMT_FLAG_IGNDTS   = $0008; ///< Ignore DTS on frames that contain both DTS & PTS
+{$IFEND}
+{$IF LIBAVFORMAT_VERSION >= 52060000}  // >= 52.60.0
+  AVFMT_FLAG_NOFILLIN = $0010; ///< Do not infer any values from other values, just return what is stored in the container
+  AVFMT_FLAG_NOPARSE  = $0020; ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled
+{$IFEND}
+{$IF LIBAVFORMAT_VERSION >= 52063000}  // >= 52.63.0
+  AVFMT_FLAG_RTP_HINT = $0040; ///< Add RTP hinting to the output file
+{$IFEND}
+
+  // used by AVStream
+  MAX_REORDER_DELAY = 16;
+
+  // used by TAVProgram
+  AV_PROGRAM_RUNNING = 1;
+
+
+  AV_DISPOSITION_DEFAULT   = $0001;
+  AV_DISPOSITION_DUB       = $0002;
+  AV_DISPOSITION_ORIGINAL  = $0004;
+  AV_DISPOSITION_COMMENT   = $0008;
+  AV_DISPOSITION_LYRICS    = $0010;
+  AV_DISPOSITION_KARAOKE   = $0020;
+
+  {$IF LIBAVFORMAT_VERSION >= 52073000}  // >= 52.73.0
+  (**
+   * Track should be used during playback by default.
+   * Useful for subtitle track that should be displayed
+   * even when user did not explicitly ask for subtitles.
+   *)
+  AV_DISPOSITION_FORCED    = $0040;
+  {$IFEND}
+
+  // used by TAVFormatContext.debug
+  FF_FDEBUG_TS = 0001;
+
+  {$IF LIBAVFORMAT_VERSION >= 52034000}  // >= 52.34.0
+    {$IF LIBAVFORMAT_VERSION < 52039000} // <  52.39.0
+  MAX_PROBE_PACKETS = 100;
+    {$ELSE}
+  MAX_PROBE_PACKETS = 2500;
+    {$IFEND}
+  {$IFEND}
+
+  {$IF LIBAVFORMAT_VERSION >= 52035000}  // >= 52.35.0
+    {$IF LIBAVFORMAT_VERSION < 52039000} // <  52.39.0
+  RAW_PACKET_BUFFER_SIZE = 32000;
+    {$ELSE}
+  RAW_PACKET_BUFFER_SIZE = 2500000;
+    {$IFEND}
+  {$IFEND}
+
+type
+  PPAVCodecTag = ^PAVCodecTag;
+  PAVCodecTag = Pointer;
+
+  PPAVFormatContext = ^PAVFormatContext;
+  PAVFormatContext = ^TAVFormatContext;
+
+  PAVFormatParameters = ^TAVFormatParameters;
+
+  PAVOutputFormat = ^TAVOutputFormat;
+  PAVProbeData = ^TAVProbeData;
+
+  PAVInputFormat = ^TAVInputFormat;
+  PAVIndexEntry = ^TAVIndexEntry;
+
+  PAVStream = ^TAVStream;
+  PAVPacketList = ^TAVPacketList;
+
+  PPAVProgram = ^PAVProgram;
+  PAVProgram = ^TAVProgram;
+
+  {$IF LIBAVFORMAT_VERSION < 51006000} // 51.6.0
+  PAVImageFormat = ^TAVImageFormat;
+  PAVImageInfo = ^TAVImageInfo;
+  {$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52030001} // >= 52.30.1
+(**
+ * Convert all the metadata sets from ctx according to the source and
+ * destination conversion tables.
+ *
+ * @param d_conv destination tags format conversion table
+ * @param s_conv source tags format conversion table
+ *)
+  PAVMetadataConv = ^TAVMetadataConv;
+  TAVMetadataConv = record
+    ctx:            PAVFormatContext;
+    d_conv: {const} PAVMetadataConv;
+    s_conv: {const} PAVMetadataConv;
+  end;
+{$IFEND}
+
+  PAVChapter = ^TAVChapter;
+  TAVChapter = record
+    id: cint;                 ///< unique ID to identify the chapter
+    time_base: TAVRational;   ///< time base in which the start/end timestamps are specified
+    start, end_: cint64;      ///< chapter start/end time in time_base units
+    {$IF LIBAVFORMAT_VERSION < 52078003} // < 52.78.3
+    title: PAnsiChar;         ///< chapter title
+    {$ELSE}
+      {$IFDEF FF_API_OLD_METADATA}
+    title: PAnsiChar;         ///< chapter title
+      {$ENDIF}
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52024001} // 52.24.1
+    metadata: PAVMetadata;
+    {$IFEND}
+  end;
+  TAVChapterArray = array[0..(MaxInt div SizeOf(TAVChapter))-1] of TAVChapter;
+  PAVChapterArray = ^TAVChapterArray;
+
+  TAVFormatParameters = record
+    time_base: TAVRational;
+    sample_rate: cint;
+    channels: cint;
+    width: cint;
+    height: cint;
+    pix_fmt: TAVPixelFormat;
+    {$IF LIBAVFORMAT_VERSION < 51006000} // 51.6.0
+    image_format: PAVImageFormat;
+    {$IFEND}
+    channel: cint; (**< Used to select DV channel. *)
+    {$IF LIBAVFORMAT_VERSION_MAJOR < 52}
+    device: PAnsiChar; (* video, audio or DV device, if LIBAVFORMAT_VERSION_INT < (52<<16) *)
+    {$IFEND}
+    standard: PAnsiChar; (**< TV standard, NTSC, PAL, SECAM *)
+    { Delphi does not support bit fields -> use bf_flags instead
+    unsigned int mpeg2ts_raw:1;  (**< Force raw MPEG-2 transport stream output, if possible. *)
+    unsigned int mpeg2ts_compute_pcr:1; (**< Compute exact PCR for each transport
+                                  stream packet (only meaningful if
+                                  mpeg2ts_raw is TRUE). *)
+    unsigned int initial_pause:1;       (**< Do not begin to play the stream
+                                        immediately (RTSP only). *)
+    unsigned int prealloced_context:1;
+    }
+    bf_flags: byte; // 0:mpeg2ts_raw/1:mpeg2ts_compute_pcr/2:initial_pause/3:prealloced_context
+    {$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+    video_codec_id: TCodecID;
+    audio_codec_id: TCodecID;
+    {$IFEND}
+  end;
+
+  TAVOutputFormat = record
+    name: PAnsiChar;
+    (**
+     * Descriptive name for the format, meant to be more human-readable
+     * than name. You should use the NULL_IF_CONFIG_SMALL() macro
+     * to define it.
+     *)
+    long_name: PAnsiChar;
+    mime_type: PAnsiChar;
+    extensions: PAnsiChar; (**< comma-separated filename extensions *)
+    (**
+     * size of private data so that it can be allocated in the wrapper
+     *)
+    priv_data_size: cint;
+    (* output support *)
+    audio_codec: TCodecID; (**< default audio codec *)
+    video_codec: TCodecID; (**< default video codec *)
+    write_header: function (c: PAVFormatContext): cint; cdecl;
+    write_packet: function (c: PAVFormatContext; pkt: PAVPacket): cint; cdecl;
+    write_trailer: function (c: PAVFormatContext): cint; cdecl;
+    (** 
+     * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER
+     *)
+    flags: cint;
+    (**
+     * Currently only used to set pixel format if not YUV420P.
+     *)
+    set_parameters: function (c: PAVFormatContext; f: PAVFormatParameters): cint; cdecl;
+    interleave_packet: function (s: PAVFormatContext; out_: PAVPacket;
+                                 in_: PAVPacket; flush: cint): cint; cdecl;
+
+    {$IF LIBAVFORMAT_VERSION >= 51008000} // 51.8.0
+    (**
+     * List of supported codec_id-codec_tag pairs, ordered by "better
+     * choice first". The arrays are all terminated by CODEC_ID_NONE.
+     *)
+    codec_tag: {const} PPAVCodecTag;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 51012002} // 51.12.2
+    subtitle_codec: TCodecID; (**< default subtitle codec *)
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52030001} // 52.30.1
+    {const} metadata_conv: PAVMetadataConv;
+    {$IFEND}
+
+    (* private fields *)
+    next: PAVOutputFormat;
+  end;
+
+  TAVInputFormat = record
+    (**
+     * A comma separated list of short names for the format. New names
+     * may be appended with a minor bump.
+     *)
+    name: PAnsiChar;
+
+    (**
+     * Descriptive name for the format, meant to be more human-readable
+     * than name. You should use the NULL_IF_CONFIG_SMALL() macro
+     * to define it.
+     *)
+    long_name: PAnsiChar;
+
+    (**
+     * Size of private data so that it can be allocated in the wrapper.
+     *)
+    priv_data_size: cint;
+
+    (**
+     * Tell if a given file has a chance of being parsed as this format.
+     * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes
+     * big so you do not have to check for that unless you need more.
+     *)
+    read_probe: function (p: PAVProbeData): cint; cdecl;
+
+    (**
+     * Read the format header and initialize the AVFormatContext
+     * structure. Return 0 if OK. 'ap' if non-NULL contains
+     * additional parameters. Only used in raw format right
+     * now. 'av_new_stream' should be called to create new streams.
+     *)
+    read_header: function (c: PAVFormatContext; ap: PAVFormatParameters): cint; cdecl;
+
+    (**
+     * Read one packet and put it in 'pkt'. pts and flags are also
+     * set. 'av_new_stream' can be called only if the flag
+     * AVFMTCTX_NOHEADER is used.
+     * @return 0 on success, < 0 on error.
+     *         When returning an error, pkt must not have been allocated
+     *         or must be freed before returning
+     *)
+    read_packet: function (c: PAVFormatContext; var pkt: TAVPacket): cint; cdecl;
+
+    (**
+     * Close the stream. The AVFormatContext and AVStreams are not
+     * freed by this function
+     *)
+    read_close: function (c: PAVFormatContext): cint; cdecl;
+
+{$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+    (**
+     * Seek to a given timestamp relative to the frames in
+     * stream component stream_index.
+     * @param stream_index Must not be -1.
+     * @param flags Selects which direction should be preferred if no exact
+     *              match is available.
+     * @return >= 0 on success (but not necessarily the new offset)
+     *)
+    read_seek: function (c: PAVFormatContext; stream_index: cint;
+                  timestamp: cint64; flags: cint): cint; cdecl;
+{$IFEND}
+
+    (**
+     * Gets the next timestamp in stream[stream_index].time_base units.
+     * @return the timestamp or AV_NOPTS_VALUE if an error occurred
+     *)
+    read_timestamp: function (s: PAVFormatContext; stream_index: cint;
+                              pos: pint64; pos_limit: cint64): cint64; cdecl;
+
+    (**
+     * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER.
+     *)
+    flags: cint;
+
+    (**
+     * If extensions are defined, then no probe is done. You should
+     * usually not use extension format guessing because it is not
+     * reliable enough
+     *)
+    extensions: PAnsiChar;
+
+    (**
+     * General purpose read-only value that the format can use.
+     *)
+    value: cint;
+
+    (**
+     * Start/resume playing - only meaningful if using a network-based format
+     * (RTSP).
+     *)
+    read_play: function (c: PAVFormatContext): cint; cdecl;
+
+    (**
+     * Pause playing - only meaningful if using a network-based format
+     * (RTSP).
+     *)  
+    read_pause: function (c: PAVFormatContext): cint; cdecl;
+
+    {$IF LIBAVFORMAT_VERSION >= 51008000} // 51.8.0
+    codec_tag: {const} PPAVCodecTag;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52030000} // 52.30.0
+    (**
+     * Seek to timestamp ts.
+     * Seeking will be done so that the point from which all active streams
+     * can be presented successfully will be closest to ts and within min/max_ts.
+     * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
+     *)
+    read_seek2: function (s:            PAVFormatContext;
+                          stream_index: cint;
+			  min_ts:       cint64;
+			  ts:           cint64; 
+			  max_ts:       cint64;
+			  flags:        cint): cint; cdecl;
+    {$IFEND}
+    
+    {$IF LIBAVFORMAT_VERSION >= 52030001} // 52.30.1
+    {const} metadata_conv: PAVMetadataConv;
+    {$IFEND}
+
+    (* private fields *)
+    next: PAVInputFormat;
+  end;
+
+  TAVStreamParseType = (
+    AVSTREAM_PARSE_NONE,
+    AVSTREAM_PARSE_FULL,       (**< full parsing and repack *)
+    AVSTREAM_PARSE_HEADERS,    (**< Only parse headers, do not repack. *)
+    AVSTREAM_PARSE_TIMESTAMPS  (**< full parsing and interpolation of timestamps for frames not starting on a packet boundary *)
+    {$IF LIBAVFORMAT_VERSION >= 52066000} // 52.66.0
+  , AVSTREAM_PARSE_FULL_ONCE   (**< full parsing and repack of the first frame only, only implemented for H.264 currently *)
+    {$IFEND}
+  );
+
+  TAVIndexEntry = record
+    pos: cint64;
+    timestamp: cint64;
+    { Delphi doesn't support bitfields -> use flags_size instead
+    int flags:2;
+    int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment).
+    }
+    flags_size: cint; // 0..1: flags, 2..31: size
+    min_distance: cint;         (**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. *)
+  end;
+
+ (**
+  * Stream structure.
+  * New fields can be added to the end with minor version bumps.
+  * Removal, reordering and changes to existing fields require a major
+  * version bump.
+  * sizeof(AVStream) must not be used outside libav*.
+  *)
+  TAVStream = record
+    index: cint;    (**< stream index in AVFormatContext *)
+    id: cint;       (**< format-specific stream ID *)
+    codec: PAVCodecContext; (**< codec context *)
+    (**
+     * Real base framerate of the stream.
+     * This is the lowest framerate with which all timestamps can be
+     * represented accurately (it is the least common multiple of all
+     * framerates in the stream). Note, this value is just a guess!
+     * For example, if the time base is 1/90000 and all frames have either
+     * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1.
+     *)
+    r_frame_rate: TAVRational;
+    priv_data: pointer;
+
+    (* internal data used in av_find_stream_info() *)
+    first_dts: cint64;
+    {$IF LIBAVFORMAT_VERSION_MAJOR < 52}
+    codec_info_nb_frames: cint;
+    {$IFEND}
+
+    (** 
+     * encoding: pts generation when outputting stream
+     *)
+    pts: TAVFrac;
+    (**
+     * This is the fundamental unit of time (in seconds) in terms
+     * of which frame timestamps are represented. For fixed-fps content,
+     * time base should be 1/framerate and timestamp increments should be 1.
+     *)
+    time_base: TAVRational;
+    pts_wrap_bits: cint; (* number of bits in pts (used for wrapping control) *)
+    (* ffmpeg.c private use *)
+    stream_copy: cint; (**< If set, just copy stream. *)
+    discard: TAVDiscard; ///< Selects which packets can be discarded at will and do not need to be demuxed.
+    //FIXME move stuff to a flags field?
+    (** 
+     * Quality, as it has been removed from AVCodecContext and put in AVVideoFrame.
+     * MN:dunno if thats the right place, for it
+     *)
+    quality: cfloat;
+
+    (**
+     * Decoding: pts of the first frame of the stream, in stream time base.
+     * Only set this if you are absolutely 100% sure that the value you set
+     * it to really is the pts of the first frame.
+     * This may be undefined (AV_NOPTS_VALUE).
+     * @note The ASF header does NOT contain a correct start_time the ASF
+     * demuxer must NOT set this.
+     *)
+    start_time: cint64;
+
+    (**
+     * Decoding: duration of the stream, in stream time base.
+     * If a source file does not specify a duration, but does specify
+     * a bitrate, this value will be estimated from bitrate and file size.
+     *)
+    duration: cint64;
+
+    {$IF LIBAVFORMAT_VERSION < 52078003} // < 52.78.3
+    language: array [0..3] of PAnsiChar; (**< ISO 639-2/B 3-letter language code (empty string if undefined) *)
+    {$ELSE}
+      {$IFDEF FF_API_OLD_METADATA}
+    language: array [0..3] of PAnsiChar; (**< ISO 639-2/B 3-letter language code (empty string if undefined) *)
+      {$ENDIF}
+    {$IFEND}
+
+    (* av_read_frame() support *)
+    need_parsing: TAVStreamParseType;
+    parser: PAVCodecParserContext;
+
+    cur_dts: cint64;
+    last_IP_duration: cint;
+    last_IP_pts: cint64;
+    (* av_seek_frame() support *)
+    index_entries: PAVIndexEntry; (**< Only used if the format does not
+                                       support seeking natively. *)
+    nb_index_entries: cint;
+    index_entries_allocated_size: cuint;
+
+    nb_frames: cint64;                 ///< number of frames in this stream if known or 0
+    
+    {$IF (LIBAVFORMAT_VERSION >= 50006000) and (LIBAVFORMAT_VERSION_MAJOR < 53)} // 50.6.0 - 53.0.0
+    unused: array [0..4] of cint64;
+    {$IFEND}
+
+    {$IF (LIBAVFORMAT_VERSION >= 52006000) and (LIBAVFORMAT_VERSION < 52078003)} // 52.6.0 - 52.78.2
+    filename: PAnsiChar; (**< source filename of the stream *)
+    {$ELSE}
+      {$IFDEF FF_API_OLD_METADATA}
+    filename: PAnsiChar; (**< source filename of the stream *)
+      {$ENDIF}    
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52008000} // 52.8.0
+    disposition: cint; (**< AV_DISPOSITION_* bitfield *)
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52019000} // 52.19.0
+    probe_data: TAVProbeData;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52021000} // 52.21.0
+    pts_buffer: array [0..MAX_REORDER_DELAY] of cint64;
+
+    (**
+     * sample aspect ratio (0 if unknown)
+     * - encoding: Set by user.
+     * - decoding: Set by libavformat.
+     *)
+    sample_aspect_ratio: TAVRational;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52024001} // 52.24.1
+    metadata: PAVMetadata;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION > 52024001} // > 52.24.1
+    {* Intended mostly for av_read_frame() support. Not supposed to be used by *}
+    {* external applications; try to use something else if at all possible.    *}
+    cur_ptr: {const} PCuint8;
+    cur_len: cint;
+    cur_pkt: TAVPacket;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52030000} // > 52.30.0
+    // Timestamp generation support:
+    (**
+     * Timestamp corresponding to the last dts sync point.
+     *
+     * Initialized when AVCodecParserContext.dts_sync_point >= 0 and
+     * a DTS is received from the underlying container. Otherwise set to
+     * AV_NOPTS_VALUE by default.
+     *)
+    reference_dts: cint64;
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52034000} // >= 52.34.0
+    (**
+     * Number of packets to buffer for codec probing
+     * NOT PART OF PUBLIC API
+     *)
+    probe_packets: cint;
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52038000} // >= 52.38.0
+    (**
+     * last packet in packet_buffer for this stream when muxing.
+     * used internally, NOT PART OF PUBLIC API, dont read or write from outside of libav*
+     *)
+    last_in_packet_buffer: PAVPacketList;
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52041000} // >= 52.41.0
+    (**
+     * Average framerate
+     *)
+    avg_frame_rate: TAVRational;
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52054000} // >= 52.54.0
+    (**
+     * Number of frames that have been demuxed during av_find_stream_info()
+     *)
+    codec_info_nb_frames: cint;
+    {$IFEND}
+  end;
+
+ (**
+  * Format I/O context.
+  * New fields can be added to the end with minor version bumps.
+  * Removal, reordering and changes to existing fields require a major
+  * version bump.
+  * sizeof(AVFormatContext) must not be used outside libav*.
+  *)
+  TAVFormatContext = record
+    av_class: PAVClass; (**< Set by avformat_alloc_context. *)
+    (* Can only be iformat or oformat, not both at the same time. *)
+    iformat: PAVInputFormat;
+    oformat: PAVOutputFormat;
+    priv_data: pointer;
+
+    {$IF LIBAVFORMAT_VERSION_MAJOR >= 52}
+    pb: PByteIOContext;
+    {$ELSE}
+    pb: TByteIOContext;
+    {$IFEND}
+
+    nb_streams: cuint;
+    streams: array [0..MAX_STREAMS - 1] of PAVStream;
+    filename: array [0..1023] of AnsiChar; (* input or output filename *)
+    (* stream info *)
+    timestamp: cint64;
+    {$IF LIBAVFORMAT_VERSION < 52078003} // < 52.78.3
+    title: array [0..511] of AnsiChar;
+    author: array [0..511] of AnsiChar;
+    copyright: array [0..511] of AnsiChar;
+    comment: array [0..511] of AnsiChar;
+    album: array [0..511] of AnsiChar;
+    year: cint;  (**< ID3 year, 0 if none *)
+    track: cint; (**< track number, 0 if none *)
+    genre: array [0..31] of AnsiChar; (**< ID3 genre *)
+    {$ELSE}
+      {$IFDEF FF_API_OLD_METADATA}
+    title: array [0..511] of AnsiChar;
+    author: array [0..511] of AnsiChar;
+    copyright: array [0..511] of AnsiChar;
+    comment: array [0..511] of AnsiChar;
+    album: array [0..511] of AnsiChar;
+    year: cint;  (**< ID3 year, 0 if none *)
+    track: cint; (**< track number, 0 if none *)
+    genre: array [0..31] of AnsiChar; (**< ID3 genre *)
+      {$ENDIF}
+    {$IFEND}
+
+    ctx_flags: cint; (**< Format-specific flags, see AVFMTCTX_xx *)
+    (* private data for pts handling (do not modify directly). *)
+    (**
+     * This buffer is only needed when packets were already buffered but
+     * not decoded, for example to get the codec parameters in MPEG
+     * streams.
+     *)
+    packet_buffer: PAVPacketList;
+
+    (**
+     * Decoding: position of the first frame of the component, in
+     * AV_TIME_BASE fractional seconds. NEVER set this value directly:
+     * It is deduced from the AVStream values.
+     *)
+    start_time: cint64;
+    (**
+     * Decoding: duration of the stream, in AV_TIME_BASE fractional
+     * seconds. Only set this value if you know none of the individual stream
+     * durations and also dont set any of them. This is deduced from the
+     * AVStream values if not set.
+     *)
+    duration: cint64;
+    (**
+     * decoding: total file size, 0 if unknown
+     *)
+    file_size: cint64;
+    (**
+     * Decoding: total stream bitrate in bit/s, 0 if not
+     * available. Never set it directly if the file_size and the
+     * duration are known as ffmpeg can compute it automatically.
+     *)
+    bit_rate: cint;
+
+    (* av_read_frame() support *)
+    cur_st: PAVStream;
+    {$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+    cur_ptr_deprecated: pbyte;
+    cur_len_deprecated: cint;
+    cur_pkt_deprecated: TAVPacket;
+    {$IFEND}
+
+    (* av_seek_frame() support *)
+    data_offset: cint64; (**< offset of the first packet *)
+    index_built: cint;
+
+    mux_rate: cint;
+    {$IF LIBAVFORMAT_VERSION < 52034001} // < 52.34.1
+    packet_size: cint;
+    {$ELSE}
+    packet_size: cuint;
+    {$IFEND}
+    preload: cint;
+    max_delay: cint;
+
+    (**
+     * number of times to loop output in formats that support it
+     *)
+    loop_output: cint;
+
+    flags: cint;
+    loop_input: cint;
+
+    {$IF LIBAVFORMAT_VERSION >= 50006000} // 50.6.0
+    (**
+     * decoding: size of data to probe; encoding: unused.
+     *)
+    probesize: cuint;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 51009000} // 51.9.0
+    (**
+     * Maximum time (in AV_TIME_BASE units) during which the input should
+     * be analyzed in av_find_stream_info().
+     *)
+    max_analyze_duration: cint;
+
+    key: pbyte;
+    keylen : cint;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 51014000} // 51.14.0
+    nb_programs: cuint;
+    programs: PPAVProgram;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52003000} // 52.3.0
+    (**
+     * Forced video codec_id.
+     * Demuxing: Set by user.
+     *)
+    video_codec_id: TCodecID;
+
+    (**
+     * Forced audio codec_id.
+     * Demuxing: Set by user.
+     *)
+    audio_codec_id: TCodecID;
+
+    (**
+     * Forced subtitle codec_id.
+     * Demuxing: Set by user.
+     *)
+    subtitle_codec_id: TCodecID;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52004000} // 52.4.0
+    (**
+     * Maximum amount of memory in bytes to use for the index of each stream.
+     * If the index exceeds this size, entries will be discarded as
+     * needed to maintain a smaller size. This can lead to slower or less
+     * accurate seeking (depends on demuxer).
+     * Demuxers for which a full in-memory index is mandatory will ignore
+     * this.
+     * muxing  : unused
+     * demuxing: set by user
+     *)
+    max_index_size: cuint;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52009000} // 52.9.0
+    (**
+     * Maximum amount of memory in bytes to use for buffering frames
+     * obtained from realtime capture devices.
+     *)
+    max_picture_buffer: cuint;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52014000} // 52.14.0
+    nb_chapters: cuint;
+    chapters: PAVChapterArray;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52016000} // 52.16.0
+    (**
+     * Flags to enable debugging.
+     *)
+    debug: cint;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52019000} // 52.19.0
+    (**
+     * Raw packets from the demuxer, prior to parsing and decoding.
+     * This buffer is used for buffering packets until the codec can
+     * be identified, as parsing cannot be done without knowing the
+     * codec.
+     *)
+    raw_packet_buffer: PAVPacketList;
+    raw_packet_buffer_end: PAVPacketList;
+
+    packet_buffer_end: PAVPacketList;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52024001} // 52.24.1
+    metadata: PAVMetadata;
+    {$IFEND}
+    
+    {$IF LIBAVFORMAT_VERSION >= 52035000} // 52.35.0
+    (**
+     * Remaining size available for raw_packet_buffer, in bytes.
+     * NOT PART OF PUBLIC API
+     *)
+    raw_packet_buffer_remaining_size: cint;
+    {$IFEND}
+
+    {$IF LIBAVFORMAT_VERSION >= 52056000} // 52.56.0
+    (**
+     * Start time of the stream in real world time, in microseconds
+     * since the unix epoch (00:00 1st January 1970). That is, pts=0
+     * in the stream was captured at this real world time.
+     * - encoding: Set by user.
+     * - decoding: Unused.
+     *)
+    start_time_realtime: cint64;
+    {$IFEND}
+
+  end;
+
+  (**
+   * New fields can be added to the end with minor version bumps.
+   * Removal, reordering and changes to existing fields require a major
+   * version bump.
+   * sizeof(AVProgram) must not be used outside libav*.
+   *)
+  TAVProgram = record
+      id                : cint;
+      {$IF LIBAVFORMAT_VERSION < 52078003} // < 52.78.3
+      provider_name     : PAnsiChar;  ///< network name for DVB streams
+      name              : PAnsiChar;  ///< service name for DVB streams
+      {$ELSE}
+        {$IFDEF FF_API_OLD_METADATA}
+      provider_name     : PAnsiChar;  ///< network name for DVB streams
+      name              : PAnsiChar;  ///< service name for DVB streams
+        {$ENDIF}
+      {$IFEND}
+      flags             : cint;
+      discard           : TAVDiscard; ///< selects which program to discard and which to feed to the caller
+      {$IF LIBAVFORMAT_VERSION >= 51016000} // 51.16.0
+      stream_index      : PCardinal;
+      nb_stream_indexes : PCardinal;
+      {$IFEND}
+      {$IF LIBAVFORMAT_VERSION >= 52024001} // 52.24.1
+      metadata: PAVMetadata;
+      {$IFEND}
+  end;
+
+  TAVPacketList = record
+    pkt: TAVPacket;
+    next: PAVPacketList;
+  end;
+
+{$IF LIBAVFORMAT_VERSION < 51006000} // 51.6.0
+  (* still image support *)
+  PAVInputImageContext = pointer; {deprecated}
+
+  (* still image support *)
+  TAVImageInfo = record
+    pix_fmt: TAVPixelFormat; (* requested pixel format *)
+    width: cint; (* requested width *)
+    height: cint; (* requested height *)
+    interleaved: cint; (* image is interleaved (e.g. interleaved GIF) *)
+    pict: TAVPicture; (* returned allocated image *)
+  end; {deprecated}
+
+  TAVImageFormat = record
+    name: PAnsiChar;
+    extensions: PAnsiChar;
+    (* tell if a given file has a chance of being parsing by this format *)
+    img_probe: function (d: PAVProbeData): cint; cdecl;
+    (* read a whole image. 'alloc_cb' is called when the image size is
+       known so that the caller can allocate the image. If 'allo_cb'
+       returns non zero, then the parsing is aborted. Return '0' if
+       OK. *)
+    img_read: function (b: PByteIOContext; alloc_cb: pointer; ptr: pointer): cint; cdecl;
+    (* write the image *)
+    supported_pixel_formats: cint; (* mask of supported formats for output *)
+    img_write: function (b: PByteIOContext; i: PAVImageInfo): cint; cdecl;
+    flags: cint;
+    next: PAVImageFormat;
+  end; {deprecated}
+
+procedure av_register_image_format(img_fmt: PAVImageFormat);
+    cdecl; external av__format; deprecated;
+
+function av_probe_image_format(pd: PAVProbeData): PAVImageFormat;
+    cdecl; external av__format; deprecated;
+
+function guess_image_format(filename: PAnsiChar): PAVImageFormat;
+    cdecl; external av__format; deprecated;
+
+function av_read_image(pb: PByteIOContext; filename: PAnsiChar;
+                  fmt: PAVImageFormat;
+                  alloc_cb: pointer; opaque: pointer): cint;
+    cdecl; external av__format; deprecated;
+
+function av_write_image(pb: PByteIOContext; fmt: PAVImageFormat; img: PAVImageInfo): cint;
+    cdecl; external av__format; deprecated;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52030001} // >= 52.30.1
+(**
+ * Convert all the metadata sets from ctx according to the source and
+ * destination conversion tables. If one of the tables is NULL, then
+ * tags are converted to/from ffmpeg generic tag names.
+ *
+ * @param d_conv destination tags format conversion table
+ * @param s_conv source tags format conversion table
+ *)
+procedure av_metadata_conv(ctx: PAVFormatContext; {const} d_conv: PAVMetadataConv;
+                                                  {const} s_conv: PAVMetadataConv);
+  cdecl; external av__format;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+{
+var
+  first_iformat: PAVInputFormat; external av__format;
+  first_oformat: PAVOutputFormat; external av__format;
+}
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52003000} // 52.3.0
+(**
+ * If f is NULL, returns the first registered input format,
+ * if f is non-NULL, returns the next registered input format after f
+ * or NULL if f is the last one.
+ *)
+function av_iformat_next(f: PAVInputFormat): PAVInputFormat;
+    cdecl; external av__format;
+(**
+ * If f is NULL, returns the first registered output format,
+ * if f is non-NULL, returns the next registered input format after f
+ * or NULL if f is the last one.
+ *)
+function av_oformat_next(f: PAVOutputFormat): PAVOutputFormat;
+    cdecl; external av__format;
+{$IFEND}
+
+function av_guess_image2_codec(filename: {const} PAnsiChar): TCodecID;
+    cdecl; external av__format;
+
+(* XXX: Use automatic init with either ELF sections or C file parser *)
+(* modules. *)
+
+(* utils.c *)
+procedure av_register_input_format(format: PAVInputFormat);
+  cdecl; external av__format;
+
+procedure av_register_output_format(format: PAVOutputFormat);
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION_MAJOR < 53} // < 53
+function guess_stream_format(short_name: PAnsiChar;
+                             filename: PAnsiChar;
+                             mime_type: PAnsiChar): PAVOutputFormat;
+  cdecl; external av__format; deprecated;
+{$IFEND}
+
+(**
+ * Return the output format in the list of registered output formats
+ * which best matches the provided parameters, or return NULL if
+ * there is no match.
+ *
+ * @param short_name if non-NULL checks if short_name matches with the
+ * names of the registered formats
+ * @param filename if non-NULL checks if filename terminates with the
+ * extensions of the registered formats
+ * @param mime_type if non-NULL checks if mime_type matches with the
+ * MIME type of the registered formats
+ *)
+(**
+ * @deprecated Use av_guess_format() instead.
+ *)
+function guess_format(short_name: PAnsiChar;
+                      filename: PAnsiChar;
+                      mime_type: PAnsiChar): PAVOutputFormat;
+  cdecl; external av__format;
+{$IF LIBAVFORMAT_VERSION >= 52045000} // >= 52.45.0
+                              deprecated;
+function av_guess_format(short_name: PAnsiChar;
+                         filename: PAnsiChar;
+                         mime_type: PAnsiChar): PAVOutputFormat;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Guess the codec ID based upon muxer and filename.
+ *)
+function av_guess_codec(fmt: PAVOutputFormat; short_name: PAnsiChar;
+                        filename: PAnsiChar; mime_type: PAnsiChar;
+                        type_: TCodecType): TCodecID;
+  cdecl; external av__format;
+
+(**
+ * Send a nice hexadecimal dump of a buffer to the specified file stream.
+ *
+ * @param f The file stream pointer where the dump should be sent to.
+ * @param buf buffer
+ * @param size buffer size
+ *
+ * @see av_hex_dump_log, av_pkt_dump, av_pkt_dump_log
+ *)
+procedure av_hex_dump(f: PAVFile; buf: PByteArray; size: cint);
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 51011000} // 51.11.0
+(**
+ * Send a nice hexadecimal dump of a buffer to the log.
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ * pointer to an AVClass struct.
+ * @param level The importance level of the message, lower values signifying
+ * higher importance.
+ * @param buf buffer
+ * @param size buffer size
+ *
+ * @see av_hex_dump, av_pkt_dump, av_pkt_dump_log
+ *)
+procedure av_hex_dump_log(avcl: Pointer; level: cint; buf: PByteArray; size: cint);
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Send a nice dump of a packet to the specified file stream.
+ *
+ * @param f The file stream pointer where the dump should be sent to.
+ * @param pkt packet to dump
+ * @param dump_payload True if the payload must be displayed, too.
+ *)
+procedure av_pkt_dump(f: PAVFile; pkt: PAVPacket; dump_payload: cint);
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 51011000} // 51.11.0
+(**
+ * Send a nice dump of a packet to the log.
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ * pointer to an AVClass struct.
+ * @param level The importance level of the message, lower values signifying
+ * higher importance.
+ * @param pkt packet to dump
+ * @param dump_payload True if the payload must be displayed, too.
+ *)
+procedure av_pkt_dump_log(avcl: Pointer; level: cint; pkt: PAVPacket; dump_payload: cint);
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Initialize libavformat and register all the muxers, demuxers and
+ * protocols. If you do not call this function, then you can select
+ * exactly which formats you want to support.
+ *
+ * @see av_register_input_format()
+ * @see av_register_output_format()
+ * @see av_register_protocol()
+ *)
+procedure av_register_all();
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 51008000} // 51.8.0
+(**
+ * Get the CodecID for the given codec tag tag.
+ * If no codec id is found returns CODEC_ID_NONE.
+ *
+ * @param tags list of supported codec_id-codec_tag pairs, as stored
+ * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
+ *)
+function av_codec_get_id(var tags: PAVCodecTag; tag: cuint): TCodecID;
+  cdecl; external av__format;
+
+(**
+ * Getsthe codec tag for the given codec id id.
+ * If no codec tag is found returns 0.
+ *
+ * @param tags list of supported codec_id-codec_tag pairs, as stored
+ * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag
+ *)
+function av_codec_get_tag(var tags: PAVCodecTag; id: TCodecID): cuint;
+  cdecl; external av__format;
+{$IFEND}
+
+(* media file input *)
+
+(**
+ * Find AVInputFormat based on the short name of the input format.
+ *)
+function av_find_input_format(short_name: PAnsiChar): PAVInputFormat;
+  cdecl; external av__format;
+
+(**
+ * Guess file format.
+ *
+ * @param is_opened Whether the file is already opened; determines whether
+ *                  demuxers with or without AVFMT_NOFILE are probed.
+ *)
+function av_probe_input_format(pd: PAVProbeData; is_opened: cint): PAVInputFormat;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52062000} // 52.62.0
+(**
+ * Guess the file format.
+ *
+ * @param is_opened Whether the file is already opened; determines whether
+ *                  demuxers with or without AVFMT_NOFILE are probed.
+ * @param score_max A probe score larger that this is required to accept a
+ *                  detection, the variable is set to the actual detection
+ *                  score afterwards.
+ *                  If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended
+ *                  to retry with a larger probe buffer.
+ *)
+function av_probe_input_format2(pd: PAVProbeData; is_opened: cint; score_max: PCint): PAVInputFormat;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Allocate all the structures needed to read an input stream.
+ *        This does not open the needed codecs for decoding the stream[s].
+ *)
+function av_open_input_stream(var ic_ptr: PAVFormatContext;
+                       pb: PByteIOContext; filename: PAnsiChar;
+                       fmt: PAVInputFormat; ap: PAVFormatParameters): cint;
+  cdecl; external av__format;
+
+(**
+ * Open a media file as input. The codecs are not opened. Only the file
+ * header (if present) is read.
+ *
+ * @param ic_ptr The opened media file handle is put here.
+ * @param filename filename to open
+ * @param fmt If non-NULL, force the file format to use.
+ * @param buf_size optional buffer size (zero if default is OK)
+ * @param ap Additional parameters needed when opening the file
+ *           (NULL if default).
+ * @return 0 if OK, AVERROR_xxx otherwise
+ *)
+function av_open_input_file(var ic_ptr: PAVFormatContext; filename: PAnsiChar;
+                     fmt: PAVInputFormat; buf_size: cint;
+                     ap: PAVFormatParameters): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52026000} // 52.26.0
+(**
+ * Allocate an AVFormatContext.
+ * Can be freed with av_free() but do not forget to free everything you
+ * explicitly allocated as well!
+ *)
+function avformat_alloc_context(): PAVFormatContext;
+  cdecl; external av__format;
+{$ELSE}
+  {$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+(**
+ * @deprecated Use avformat_alloc_context() instead.
+ *)
+function av_alloc_format_context(): PAVFormatContext;
+  cdecl; external av__format;
+  {$IFEND}
+{$IFEND}
+
+(**
+ * Read packets of a media file to get stream information. This
+ * is useful for file formats with no headers such as MPEG. This
+ * function also computes the real framerate in case of MPEG-2 repeat
+ * frame mode.
+ * The logical file position is not changed by this function;
+ * examined packets may be buffered for later processing.
+ *
+ * @param ic media file handle
+ * @return >=0 if OK, AVERROR_xxx on error
+ * @todo Let the user decide somehow what information is needed so that
+ *       we do not waste time getting stuff the user does not need.
+ *)
+function av_find_stream_info(ic: PAVFormatContext): cint;
+  cdecl; external av__format;
+
+(**
+ * Read a transport packet from a media file.
+ *
+ * This function is obsolete and should never be used.
+ * Use av_read_frame() instead.
+ *
+ * @param s media file handle
+ * @param pkt is filled
+ * @return 0 if OK, AVERROR_xxx on error
+ *)
+function av_read_packet(s: PAVFormatContext; var pkt: TAVPacket): cint;
+  cdecl; external av__format;
+
+(**
+ * Return the next frame of a stream.
+ *
+ * The returned packet is valid
+ * until the next av_read_frame() or until av_close_input_file() and
+ * must be freed with av_free_packet. For video, the packet contains
+ * exactly one frame. For audio, it contains an cint number of
+ * frames if each frame has a known fixed size (e.g. PCM or ADPCM
+ * data). If the audio frames have a variable size (e.g. MPEG audio),
+ * then it contains one frame.
+ *
+ * pkt->pts, pkt->dts and pkt->duration are always set to correct
+ * values in AVStream.time_base units (and guessed if the format cannot
+ * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format
+ * has B-frames, so it is better to rely on pkt->dts if you do not
+ * decompress the payload.
+ *
+ * @return 0 if OK, < 0 on error or end of file
+ *)
+function av_read_frame(s: PAVFormatContext; var pkt: TAVPacket): cint;
+  cdecl; external av__format;
+
+(**
+ * Seek to the keyframe at timestamp.
+ * 'timestamp' in 'stream_index'.
+ * @param stream_index If stream_index is (-1), a default
+ * stream is selected, and timestamp is automatically converted
+ * from AV_TIME_BASE units to the stream specific time_base.
+ * @param timestamp Timestamp in AVStream.time_base units
+ *        or, if no stream is specified, in AV_TIME_BASE units.
+ * @param flags flags which select direction and seeking mode
+ * @return >= 0 on success
+ *)
+function av_seek_frame(s: PAVFormatContext; stream_index: cint; timestamp: cint64;
+                       flags: cint): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52026000} // 52.26.0
+(**
+ * Seek to timestamp ts.
+ * Seeking will be done so that the point from which all active streams
+ * can be presented successfully will be closest to ts and within min/max_ts.
+ * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
+ *
+ * If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in byte and
+ * are the file position (this may not be supported by all demuxers).
+ * If flags contain AVSEEK_FLAG_FRAME then all timestamps are in frames
+ * in the stream with stream_index (this may not be supported by all demuxers).
+ * Otherwise all timestamps are in units of the stream selected by stream_index
+ * or if stream_index is -1, in AV_TIME_BASE units.
+ * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as
+ * keyframes (this may not be supported by all demuxers).
+ *
+ * @param stream_index index of the stream which is used as time base reference.
+ * @param min_ts smallest acceptable timestamp
+ * @param ts target timestamp
+ * @param max_ts largest acceptable timestamp
+ * @param flags flags
+ * @return >=0 on success, error code otherwise
+ *
+ * @note This is part of the new seek API which is still under construction.
+ *       Thus do not use this yet. It may change at any time, do not expect
+ *       ABI compatibility yet!
+ *)
+function avformat_seek_file(s:            PAVFormatContext;
+			    stream_index: cint;
+			    min_ts:       cint64;
+			    ts:           cint64;
+			    max_ts:       cint64;
+			    flags:        cint): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Start playing a network-based stream (e.g. RTSP stream) at the
+ * current position.
+ *)
+function av_read_play(s: PAVFormatContext): cint;
+  cdecl; external av__format;
+
+(**
+ * Pause a network-based stream (e.g. RTSP stream).
+ *
+ * Use av_read_play() to resume it.
+ *)
+function av_read_pause(s: PAVFormatContext): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52003000} // 52.3.0
+(**
+ * Free a AVFormatContext allocated by av_open_input_stream.
+ * @param s context to free
+ *)
+procedure av_close_input_stream(s: PAVFormatContext);
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Close a media file (but not its codecs).
+ *
+ * @param s media file handle
+ *)
+procedure av_close_input_file(s: PAVFormatContext);
+  cdecl; external av__format;
+
+(**
+ * Add a new stream to a media file.
+ *
+ * Can only be called in the read_header() function. If the flag
+ * AVFMTCTX_NOHEADER is in the format context, then new streams
+ * can be added in read_packet too.
+ *
+ * @param s media file handle
+ * @param id file-format-dependent stream ID
+ *)
+function av_new_stream(s: PAVFormatContext; id: cint): PAVStream;
+  cdecl; external av__format;
+{$IF LIBAVFORMAT_VERSION >= 51014000} // 51.14.0
+function av_new_program(s: PAVFormatContext; id: cint): PAVProgram;
+  cdecl; external av__format;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52014000} // 52.14.0
+(**
+ * Add a new chapter.
+ * This function is NOT part of the public API
+ * and should ONLY be used by demuxers.
+ *
+ * @param s media file handle
+ * @param id unique ID for this chapter
+ * @param start chapter start time in time_base units
+ * @param end chapter end time in time_base units
+ * @param title chapter title
+ *
+ * @return AVChapter or NULL on error
+ *)
+function ff_new_chapter(s: PAVFormatContext; id: cint; time_base: TAVRational;
+                        start, end_: cint64; title: {const} PAnsiChar): PAVChapter;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Set the pts for a given stream.
+ *
+ * @param s stream
+ * @param pts_wrap_bits number of bits effectively used by the pts
+ *        (used for wrap control, 33 is the value for MPEG)
+ * @param pts_num numerator to convert to seconds (MPEG: 1)
+ * @param pts_den denominator to convert to seconds (MPEG: 90000)
+ *)
+procedure av_set_pts_info(s: PAVStream; pts_wrap_bits: cint;
+{$IF LIBAVFORMAT_VERSION < 52036000} // < 52.36.0
+                   pts_num: cint; pts_den: cint);
+{$ELSE}
+                   pts_num: cuint; pts_den: cuint);
+{$IFEND}
+  cdecl; external av__format;
+
+const
+  AVSEEK_FLAG_BACKWARD = 1; ///< seek backward
+  AVSEEK_FLAG_BYTE     = 2; ///< seeking based on position in bytes
+  AVSEEK_FLAG_ANY      = 4; ///< seek to any frame, even non-keyframes
+{$IF LIBAVFORMAT_VERSION >= 52037000} // >= 52.37.0
+  AVSEEK_FLAG_FRAME    = 8;
+{$IFEND}
+
+function av_find_default_stream_index(s: PAVFormatContext): cint;
+  cdecl; external av__format;
+
+(**
+ * Get the index for a specific timestamp.
+ * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond
+ *                 to the timestamp which is <= the requested one, if backward
+ *                 is 0, then it will be >=
+ *              if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise
+ * @return < 0 if no such timestamp could be found
+ *)
+function av_index_search_timestamp(st: PAVStream; timestamp: cint64; flags: cint): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52004000} // 52.4.0
+(**
+ * Ensure the index uses less memory than the maximum specified in
+ * AVFormatContext.max_index_size by discarding entries if it grows
+ * too large.
+ * This function is not part of the public API and should only be called
+ * by demuxers.
+ *)
+procedure ff_reduce_index(s: PAVFormatContext; stream_index: cint);
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Add an index entry into a sorted list. Update the entry if the list
+ * already contains it.
+ *
+ * @param timestamp timestamp in the timebase of the given stream
+ *)
+function av_add_index_entry(st: PAVStream; pos: cint64; timestamp: cint64;
+                  size: cint; distance: cint; flags: cint): cint;
+  cdecl; external av__format;
+
+(**
+ * Perform a binary search using av_index_search_timestamp() and
+ * AVInputFormat.read_timestamp().
+ * This is not supposed to be called directly by a user application,
+ * but by demuxers.
+ * @param target_ts target timestamp in the time base of the given stream
+ * @param stream_index stream number
+ *)
+function av_seek_frame_binary(s: PAVFormatContext; stream_index: cint;
+                 target_ts: cint64; flags: cint): cint;
+  cdecl; external av__format;
+
+
+(**
+ * Update cur_dts of all streams based on the given timestamp and AVStream.
+ *
+ * Stream ref_st unchanged, others set cur_dts in their native time base.
+ * Only needed for timestamp wrapping or if (dts not set and pts!=dts).
+ * @param timestamp new dts expressed in time_base of param ref_st
+ * @param ref_st reference stream giving time_base of param timestamp
+ *)
+procedure av_update_cur_dts(s: PAVFormatContext; ref_st: PAVStream;
+                            timestamp: cint64);
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 51007000} // 51.7.0
+type
+  TReadTimestampFunc = function (pavfc: PAVFormatContext;
+    arg2: cint; arg3: Pint64; arg4: cint64): cint64; cdecl;
+
+(**
+ * Perform a binary search using read_timestamp().
+ * This is not supposed to be called directly by a user application,
+ * but by demuxers.
+ * @param target_ts target timestamp in the time base of the given stream
+ * @param stream_index stream number
+ *)
+function av_gen_search(s: PAVFormatContext; stream_index: cint;
+                       target_ts: cint64; pos_min: cint64;
+                       pos_max: cint64; pos_limit: cint64;
+                       ts_min: cint64; ts_max: cint64;
+                       flags: cint; ts_ret: Pint64;
+                       read_timestamp: TReadTimestampFunc): cint64;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * media file output
+ *)
+function av_set_parameters(s: PAVFormatContext; ap: PAVFormatParameters): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52072000} // 52.72.0
+(**
+ * Split a URL string into components.
+ *
+ * The pointers to buffers for storing individual components may be null,
+ * in order to ignore that component. Buffers for components not found are
+ * set to empty strings. If the port is not found, it is set to a negative
+ * value.
+ *
+ * @param proto the buffer for the protocol
+ * @param proto_size the size of the proto buffer
+ * @param authorization the buffer for the authorization
+ * @param authorization_size the size of the authorization buffer
+ * @param hostname the buffer for the host name
+ * @param hostname_size the size of the hostname buffer
+ * @param port_ptr a pointer to store the port number in
+ * @param path the buffer for the path
+ * @param path_size the size of the path buffer
+ * @param url the URL to split
+ *)
+procedure av_url_split(proto: PAnsiChar;         proto_size: cint;
+                       authorization: PAnsiChar; authorization_size: cint;
+                       hostname: PAnsiChar;      hostname_size: cint;
+                       port_ptr: Pcint;
+                       path: PAnsiChar;          path_size: cint;
+                       {const} url: PAnsiChar);
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Allocate the stream private data and write the stream header to an
+ * output media file.
+ *
+ * @param s media file handle
+ * @return 0 if OK, AVERROR_xxx on error
+ *)
+function av_write_header(s: PAVFormatContext): cint;
+  cdecl; external av__format;
+
+(**
+ * Write a packet to an output media file.
+ *
+ * The packet shall contain one audio or video frame.
+ * The packet must be correctly interleaved according to the container
+ * specification, if not then av_interleaved_write_frame must be used.
+ *
+ * @param s media file handle
+ * @param pkt The packet, which contains the stream_index, buf/buf_size,
+ *            dts/pts, ...
+ * @return < 0 on error, = 0 if OK, 1 if end of stream wanted
+ *)
+function av_write_frame(s: PAVFormatContext; var pkt: TAVPacket): cint;
+  cdecl; external av__format;
+
+(**
+ * Write a packet to an output media file ensuring correct interleaving.
+ *
+ * The packet must contain one audio or video frame.
+ * If the packets are already correctly interleaved, the application should
+ * call av_write_frame() instead as it is slightly faster. It is also important
+ * to keep in mind that completely non-interleaved input will need huge amounts
+ * of memory to interleave with this, so it is preferable to interleave at the
+ * demuxer level.
+ *
+ * @param s media file handle
+ * @param pkt The packet, which contains the stream_index, buf/buf_size,
+ *            dts/pts, ...
+ * @return < 0 on error, = 0 if OK, 1 if end of stream wanted
+ *)
+function av_interleaved_write_frame(s: PAVFormatContext; var pkt: TAVPacket): cint;
+  cdecl; external av__format;
+
+(**
+ * Interleave a packet per dts in an output media file.
+ *
+ * Packets with pkt->destruct == av_destruct_packet will be freed inside this
+ * function, so they cannot be used after it. Note that calling av_free_packet()
+ * on them is still safe.
+ *
+ * @param s media file handle
+ * @param out the interleaved packet will be output here
+ * @param pkt the input packet
+ * @param flush 1 if no further packets are available as input and all
+ *              remaining packets should be output
+ * @return 1 if a packet was output, 0 if no packet could be output,
+ *         < 0 if an error occurred
+ *)
+function av_interleave_packet_per_dts(s: PAVFormatContext; _out: PAVPacket;
+                                      pkt: PAVPacket; flush: cint): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52025000} // 52.25.0
+(**
+ * Add packet to AVFormatContext->packet_buffer list, determining its
+ * interleaved position using compare() function argument.
+ *
+ * This function is not part of the public API and should only be called
+ * by muxers using their own interleave function.
+ *)
+{
+procedure ff_interleave_add_packet(s:   PAVFormatContext;
+                                   pkt: PAVPacket;
+		   compare: function(para1: PAVFormatContext;
+				     para2: PAVPacket;
+				     para3: PAVPacket): cint);
+  cdecl; external av__format;
+}
+{$IFEND}
+
+(**
+ * Write the stream trailer to an output media file and free the
+ * file private data.
+ *
+ * May only be called after a successful call to av_write_header.
+ *
+ * @param s media file handle
+ * @return 0 if OK, AVERROR_xxx on error
+ *)
+function av_write_trailer(s: pAVFormatContext): cint;
+  cdecl; external av__format;
+
+procedure dump_format(ic: PAVFormatContext; index: cint; url: PAnsiChar;
+               is_output: cint);
+  cdecl; external av__format;
+
+(**
+ * Parse width and height out of string str.
+ * @deprecated Use av_parse_video_frame_size instead.
+ *)
+function parse_image_size(width_ptr: PCint; height_ptr: PCint;
+                          str: PAnsiChar): cint;
+  cdecl; external av__format; deprecated;
+
+{$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+(**
+ * Convert framerate from a string to a fraction.
+ * @deprecated Use av_parse_video_frame_rate instead.
+ *)
+function parse_frame_rate(frame_rate: PCint; frame_rate_base: PCint;
+                          arg: PByteArray): cint;
+  cdecl; external av__format; deprecated;
+{$IFEND}
+
+(**
+ * Parse datestr and return a corresponding number of microseconds.
+ * @param datestr String representing a date or a duration.
+ * - If a date the syntax is:
+ * @code
+ *  now|{[{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH[:MM[:SS[.m...]]]}|{HH[MM[SS[.m...]]]}}[Z|z]}
+ * @endcode
+ * If the value is "now" it takes the current time.
+ * Time is localtime unless Z is appended, in which case it is
+ * interpreted as UTC.
+ * If the year-month-day part is not specified it takes the current
+ * year-month-day.
+ * Returns the number of microseconds since 1st of January, 1970 up to
+ * the time of the parsed date or INT64_MIN if datestr cannot be
+ * successfully parsed.
+ * - If a duration the syntax is:
+ * @code
+ *  [-]HH[:MM[:SS[.m...]]]
+ *  [-]S+[.m...]
+ * @endcode
+ * @return the number of microseconds contained in a time interval
+ * with the specified duration or INT64_MIN if datestr cannot be
+ * successfully parsed.
+ * @param duration Flag which tells how to interpret datestr, if
+ * not zero datestr is interpreted as a duration, otherwise as a
+ * date.
+ *)
+function parse_date(datestr: PAnsiChar; duration: cint): cint64;
+  cdecl; external av__format;
+
+(**
+ * Get the current time in microseconds.
+ *)
+function av_gettime(): cint64;
+  cdecl; external av__format;
+
+(* ffm-specific for ffserver *)
+const
+  FFM_PACKET_SIZE = 4096;
+
+function ffm_read_write_index(fd: cint): cint64;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION < 52027000} // 52.27.0
+procedure ffm_write_write_index(fd: cint; pos: cint64);
+{$ELSE}
+function ffm_write_write_index(fd: cint; pos: cint64): cint;
+{$IFEND}
+  cdecl; external av__format;
+
+procedure ffm_set_write_index(s: PAVFormatContext; pos: cint64; file_size: cint64);
+  cdecl; external av__format;
+
+(**
+ * Attempt to find a specific tag in a URL.
+ *
+ * syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done.
+ * Return 1 if found.
+ *)
+function find_info_tag(arg: PAnsiChar; arg_size: cint; tag1: PAnsiChar; info: PAnsiChar): cint;
+  cdecl; external av__format;
+
+(**
+ * Return in 'buf' the path with '%d' replaced by a number.
+ *
+ * Also handles the '%0nd' format where 'n' is the total number
+ * of digits and '%%'.
+ *
+ * @param buf destination buffer
+ * @param buf_size destination buffer size
+ * @param path numbered sequence string
+ * @param number frame number
+ * @return 0 if OK, -1 on format error
+ *)
+function av_get_frame_filename(buf: PAnsiChar; buf_size: cint;
+                               path: PAnsiChar; number: cint): cint;
+  cdecl; external av__format
+  {$IF LIBAVFORMAT_VERSION <= 50006000} // 50.6.0
+  name 'get_frame_filename'
+  {$IFEND};
+
+(**
+ * Check whether filename actually is a numbered sequence generator.
+ *
+ * @param filename possible numbered sequence string
+ * @return 1 if a valid numbered sequence string, 0 otherwise
+ *)
+function av_filename_number_test(filename: PAnsiChar): cint;
+  cdecl; external av__format
+  {$IF LIBAVFORMAT_VERSION <= 50006000} // 50.6.0
+  name 'filename_number_test'
+  {$IFEND};
+
+{$IF LIBAVFORMAT_VERSION >= 51012002} // 51.12.2
+(**
+ * Generate an SDP for an RTP session.
+ *
+ * @param ac array of AVFormatContexts describing the RTP streams. If the
+ *           array is composed by only one context, such context can contain
+ *           multiple AVStreams (one AVStream per RTP stream). Otherwise,
+ *           all the contexts in the array (an AVCodecContext per RTP stream)
+ *           must contain only one AVStream.
+ * @param n_files number of AVCodecContexts contained in ac
+ * @param buff buffer where the SDP will be stored (must be allocated by
+ *             the caller)
+ * @param size the size of the buffer
+ * @return 0 if OK, AVERROR_xxx on error
+ *)
+function avf_sdp_create(ac: PPAVFormatContext; n_files: cint; buff: PByteArray; size: cint): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52060000} // 52.60.0
+(**
+ * Return a positive value if the given filename has one of the given
+ * extensions, 0 otherwise.
+ *
+ * @param extensions a comma-separated list of filename extensions
+ *)
+function av_match_ext(filename: {const} Pchar; extensions: {const} Pchar): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+implementation
+
+{$IF LIBAVFORMAT_VERSION < 51012002} // 51.12.2
+procedure av_init_packet(var pkt: TAVPacket);
+begin
+  with pkt do begin
+    pts   := AV_NOPTS_VALUE;
+    dts   := AV_NOPTS_VALUE;
+    pos   := -1;
+    duration := 0;
+    flags := 0;
+    stream_index := 0;
+    destruct := @av_destruct_packet_nofree
+  end
+end;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION < 52032000} // < 52.32.0
+procedure av_free_packet(pkt: PAVPacket);
+begin
+  if ((pkt <> nil) and (@pkt^.destruct <> nil)) then
+    pkt^.destruct(pkt);
+end;
+{$IFEND}
+
+end.
diff --git a/songmanagement/src/lib/ffmpeg/avio.pas b/songmanagement/src/lib/ffmpeg/avio.pas
new file mode 100644
index 00000000..adb59a44
--- /dev/null
+++ b/songmanagement/src/lib/ffmpeg/avio.pas
@@ -0,0 +1,796 @@
+(*
+ * unbuffered io for ffmpeg system
+ * copyright (c) 2001 Fabrice Bellard
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * This is a part of Pascal porting of ffmpeg.
+ * - Originally by Victor Zinetz for Delphi and Free Pascal on Windows.
+ * - For Mac OS X, some modifications were made by The Creative CAT, denoted as CAT
+ *   in the source codes.
+ * - Changes and updates by the UltraStar Deluxe Team
+ *
+ * Conversion of libavformat/avio.h
+ * unbuffered I/O operations
+ * @warning This file has to be considered an internal but installed
+ * header, so it should not be directly included in your projects.
+ *
+ * update to
+ * Max. avformat version: 52.78.3, revision 24841, Thu Aug 26 02:00:00 2010 CET
+ *)
+
+unit avio;
+
+{$IFDEF FPC}
+  {$MODE DELPHI }
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$I switches.inc}
+
+interface
+
+uses
+  ctypes,
+  avutil,
+  avcodec,
+  SysUtils,
+  UConfig;
+
+(* unbuffered I/O *)
+
+const
+  URL_RDONLY = 0;
+  URL_WRONLY = 1;
+  URL_RDWR   = 2;
+
+ (**
+  * Passing this as the "whence" parameter to a seek function causes it to
+  * return the filesize without seeking anywhere. Supporting this is optional.
+  * If it is not supported then the seek function will return <0.
+  *)
+  AVSEEK_SIZE = $10000;
+
+{$IF LIBAVFORMAT_VERSION >= 52056000} // 52.56.0
+ (**
+  * Oring this flag as into the "whence" parameter to a seek function causes it to
+  * seek by any means (like reopening and linear reading) or other normally unreasonble
+  * means that can be extreemly slow.
+  * This may be ignored by the seek code.
+  *)
+  AVSEEK_FORCE = $20000;
+{$IFEND}
+
+type
+  TURLInterruptCB = function (): cint; cdecl;
+
+type
+  PURLProtocol = ^TURLProtocol;
+
+ (**
+  * URL Context.
+  * New fields can be added to the end with minor version bumps.
+  * Removal, reordering and changes to existing fields require a major
+  * version bump.
+  * sizeof(URLContext) must not be used outside libav*.
+  *)
+  PURLContext = ^TURLContext;
+  TURLContext = record
+    {$IF LIBAVFORMAT_VERSION < 52078003} // < 52.78.3
+    av_class: {const} PAVClass; ///< information for av_log(). Set by url_open().
+    {$ELSE}
+      {$IFDEF FF_API_URL_CLASS}
+    av_class: {const} PAVClass; ///< information for av_log(). Set by url_open().
+      {$ENDIF}
+    {$IFEND}
+    prot: PURLProtocol;
+    flags: cint;
+    is_streamed: cint;  (**< true if streamed (no seek possible), default = false *)
+    max_packet_size: cint;  (**< if non zero, the stream is packetized with this max packet size *)
+    priv_data: pointer;
+    filename: PAnsiChar; (**< specified URL *)
+{$IF LIBAVFORMAT_VERSION >= 52070000} // 52.70.0
+     is_connected: cint;
+{$IFEND}
+  end;
+  PPURLContext = ^PURLContext;
+
+  PURLPollEntry = ^TURLPollEntry;
+  TURLPollEntry = record
+    handle: PURLContext;
+    events: cint;
+    revents: cint;
+  end;
+
+  TURLProtocol = record
+    name: PAnsiChar;
+{$IF LIBAVFORMAT_VERSION < 52047000} // 52.47.0
+    url_open: function (h: PURLContext; filename: {const} PAnsiChar; flags: cint): cint; cdecl;
+{$ELSE}
+    url_open: function (h: PURLContext; url: {const} PAnsiChar; flags: cint): cint; cdecl;
+{$IFEND}
+
+(**
+ * Read up to size bytes from the resource accessed by h, and store
+ * the read bytes in buf.
+ *
+ * @return The number of bytes actually read, or a negative value
+ * corresponding to an AVERROR code in case of error. A value of zero
+ * indicates that it is not possible to read more from the accessed
+ * resource (except if the value of the size argument is also zero).
+ *)
+    url_read: function (h: PURLContext; buf: PByteArray; size: cint): cint; cdecl;
+
+(**
+ * Read as many bytes as possible (up to size), calling the
+ * read function multiple times if necessary.
+ * Will also retry if the read function returns AVERROR(EAGAIN).
+ * This makes special short-read handling in applications
+ * unnecessary, if the return value is < size then it is
+ * certain there was either an error or the end of file was reached.
+ *)
+    url_write: function (h: PURLContext; {const} buf: PByteArray; size: cint): cint; cdecl;
+
+(**
+ * Change the position that will be used by the next read/write
+ * operation on the resource accessed by h.
+ *
+ * @param pos specifies the new position to set
+ * @param whence specifies how pos should be interpreted, it must be
+ * one of SEEK_SET (seek from the beginning), SEEK_CUR (seek from the
+ * current position), SEEK_END (seek from the end), or AVSEEK_SIZE
+ * (return the filesize of the requested resource, pos is ignored).
+ * @return a negative value corresponding to an AVERROR code in case
+ * of failure, or the resulting file position, measured in bytes from
+ * the beginning of the file. You can use this feature together with
+ * SEEK_CUR to read the current file position.
+ *)
+    url_seek: function (h: PURLContext; pos: cint64; whence: cint): cint64; cdecl;
+
+    url_close: function (h: PURLContext): cint; cdecl;
+    next: PURLProtocol;
+    {$IF (LIBAVFORMAT_VERSION >= 52001000) and (LIBAVFORMAT_VERSION < 52004000)} // 52.1.0 .. 52.4.0
+    url_read_play: function (h: PURLContext): cint; cdecl;
+    url_read_pause: function (h: PURLContext): cint; cdecl;
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52004000} // 52.4.0
+    url_read_pause: function (h: PURLContext; pause: cint): cint; cdecl;
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52001000} // 52.1.0
+    url_read_seek: function (h: PURLContext; stream_index: cint;
+                             timestamp: cint64; flags: cint): cint64; cdecl;
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52031000} // 52.31.0
+    url_get_file_handle: function (h: PURLContext): cint; cdecl;
+    {$IFEND}
+    
+    {$IF LIBAVFORMAT_VERSION >= 52071000} // 52.71.0
+    priv_data_size: cint;
+    {const} priv_data_class: PAVClass;
+    {$IFEND}
+  end;
+
+ (**
+  * Bytestream IO Context.
+  * New fields can be added to the end with minor version bumps.
+  * Removal, reordering and changes to existing fields require a major
+  * version bump.
+  * sizeof(ByteIOContext) must not be used outside libav*.
+  *)
+  PByteIOContext = ^TByteIOContext;
+  TByteIOContext = record
+    buffer: PByteArray;
+    buffer_size: cint;
+    buf_ptr: PByteArray;
+    buf_end: PByteArray;
+    opaque: pointer;
+    read_packet: function (opaque: pointer; buf: PByteArray; buf_size: cint): cint; cdecl;
+    write_packet: function (opaque: pointer; buf: PByteArray; buf_size: cint): cint; cdecl;
+    seek: function (opaque: pointer; offset: cint64; whence: cint): cint64; cdecl;
+    pos: cint64; (* position in the file of the current buffer *)
+    must_flush: cint; (* true if the next seek should flush *)
+    eof_reached: cint; (* true if eof reached *)
+    write_flag: cint;  (* true if open for writing *)
+    is_streamed: cint;
+    max_packet_size: cint;
+    checksum: culong;
+    checksum_ptr: PByteArray;
+    update_checksum: function (checksum: culong; buf: {const} PByteArray; size: cuint): culong; cdecl;
+    error: cint;         ///< contains the error code or 0 if no error happened
+    {$IF (LIBAVFORMAT_VERSION >= 52001000) and (LIBAVFORMAT_VERSION < 52004000)} // 52.1.0 .. 52.4.0
+    read_play: function(opaque: Pointer): cint; cdecl;
+    read_pause: function(opaque: Pointer): cint; cdecl;
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52004000} // 52.4.0
+    read_pause: function(opaque: Pointer; pause: cint): cint; cdecl;
+    {$IFEND}
+    {$IF LIBAVFORMAT_VERSION >= 52001000} // 52.1.0
+    read_seek: function(opaque: Pointer; stream_index: cint;
+                        timestamp: cint64; flags: cint): cint64; cdecl;
+    {$IFEND}
+  end;
+
+{$IF LIBAVFORMAT_VERSION >= 52070000} // 52.70.0
+(**
+ * Create a URLContext for accessing to the resource indicated by
+ * url, but do not initiate the connection yet.
+ *
+ * @param puc pointer to the location where, in case of success, the
+ * function puts the pointer to the created URLContext
+ * @param flags flags which control how the resource indicated by url
+ * is to be opened
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code in case of failure
+ *)
+function url_alloc(h: PPURLContext; {const} url: PAnsiChar; flags: cint): cint;
+  cdecl; external av__format;
+
+(**
+ * Connect an URLContext that has been allocated by url_alloc
+ *)
+function url_connect(h: PURLContext): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52021000} // 52.21.0
+(**
+ * Create a URLContext for accessing to the resource indicated by
+ * URL, and open it using the URLProtocol up.
+ *
+ * @param puc pointer to the location where, in case of success, the
+ * function puts the pointer to the created URLContext
+ * @param flags flags which control how the resource indicated by URL
+ * is to be opened
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code in case of failure
+ *)
+function url_open_protocol(puc: PPURLContext; up: PURLProtocol;
+{$IF LIBAVFORMAT_VERSION < 52047000} // 52.47.0
+                           filename: {const} PAnsiChar; flags: cint): cint;
+{$ELSE}
+                           url: {const} PAnsiChar; flags: cint): cint;
+{$IFEND}
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Create a URLContext for accessing to the resource indicated by
+ * url, and open it.
+ *
+ * @param puc pointer to the location where, in case of success, the
+ * function puts the pointer to the created URLContext
+ * @param flags flags which control how the resource indicated by url
+ * is to be opened
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code in case of failure
+ *)
+{$IF LIBAVFORMAT_VERSION < 52047000} // 52.47.0
+function url_open(h: PPointer; filename: {const} PAnsiChar; flags: cint): cint;
+{$ELSE}
+function url_open(h: PPointer; url: {const} PAnsiChar; flags: cint): cint;
+{$IFEND}
+  cdecl; external av__format;
+function url_read (h: PURLContext; buf: PByteArray; size: cint): cint;
+  cdecl; external av__format;
+{$IF LIBAVFORMAT_VERSION >= 52034000} // 52.34.0
+function url_read_complete (h: PURLContext; buf: PByteArray; size: cint): cint; cdecl;
+  cdecl; external av__format;
+{$IFEND}
+function url_write (h: PURLContext; {const} buf: PByteArray; size: cint): cint;
+  cdecl; external av__format;
+function url_seek (h: PURLContext; pos: cint64; whence: cint): cint64;
+  cdecl; external av__format;
+
+(**
+ * Close the resource accessed by the URLContext h, and free the
+ * memory used by it.
+ *
+ * @return a negative value if an error condition occurred, 0
+ * otherwise
+ *)
+function url_close (h: PURLContext): cint;
+  cdecl; external av__format;
+
+(**
+ * Return a non-zero value if the resource indicated by url
+ * exists, 0 otherwise.
+ *)
+{$IF LIBAVFORMAT_VERSION < 52047000} // 52.47.0
+function url_exist(filename: {const} PAnsiChar): cint;
+{$ELSE}
+function url_exist(url: {const} PAnsiChar): cint;
+{$IFEND}
+  cdecl; external av__format;
+
+function url_filesize (h: PURLContext): cint64;
+  cdecl; external av__format;
+
+(**
+ * Return the file descriptor associated with this URL. For RTP, this
+ * will return only the RTP file descriptor, not the RTCP file descriptor.
+ * To get both, use rtp_get_file_handles().
+ *
+ * @return the file descriptor associated with this URL, or <0 on error.
+ *)
+(* not implemented *)
+function url_get_file_handle(h: PURLContext): cint;
+  cdecl; external av__format;
+
+(**
+ * Return the maximum packet size associated to packetized file
+ * handle. If the file is not packetized (stream like HTTP or file on
+ * disk), then 0 is returned.
+ *
+ * @param h file handle
+ * @return maximum packet size in bytes
+ *)
+function url_get_max_packet_size(h: PURLContext): cint;
+  cdecl; external av__format;
+procedure url_get_filename(h: PURLContext; buf: PAnsiChar; buf_size: cint);
+  cdecl; external av__format;
+
+(**
+ * The callback is called in blocking functions to test regulary if
+ * asynchronous interruption is needed. AVERROR(EINTR) is returned
+ * in this case by the interrupted function. 'NULL' means no interrupt
+ * callback is given.
+ *)
+procedure url_set_interrupt_cb (interrupt_cb: TURLInterruptCB);
+  cdecl; external av__format;
+
+(* not implemented *)
+function url_poll(poll_table: PURLPollEntry; n: cint; timeout: cint): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52004000} // 52.4.0
+(**
+ * Pause and resume playing - only meaningful if using a network streaming
+ * protocol (e.g. MMS).
+ * @param pause 1 for pause, 0 for resume
+ *)
+function av_url_read_pause(h: PURLContext; pause: cint): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52001000} // 52.1.0
+(**
+ * Seek to a given timestamp relative to some component stream.
+ * Only meaningful if using a network streaming protocol (e.g. MMS.).
+ * @param stream_index The stream index that the timestamp is relative to.
+ *        If stream_index is (-1) the timestamp should be in AV_TIME_BASE
+ *        units from the beginning of the presentation.
+ *        If a stream_index >= 0 is used and the protocol does not support
+ *        seeking based on component streams, the call will fail with ENOTSUP.
+ * @param timestamp timestamp in AVStream.time_base units
+ *        or if there is no stream specified then in AV_TIME_BASE units.
+ * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE
+ *        and AVSEEK_FLAG_ANY. The protocol may silently ignore
+ *        AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will
+ *        fail with ENOTSUP if used and not supported.
+ * @return >= 0 on success
+ * @see AVInputFormat::read_seek
+ *)
+function av_url_read_seek(h: PURLContext; stream_index: cint;
+                          timestamp: cint64; flags: cint): cint64;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+var
+{$IF LIBAVFORMAT_VERSION < 52078003} // < 52.78.3
+  first_protocol: PURLProtocol; external av__format;
+{$ELSE}
+  {$IFDEF FF_API_REGISTER_PROTOCOL}
+  first_protocol: PURLProtocol; external av__format;
+  {$IFEND}
+{$IFEND}
+  url_interrupt_cb: PURLInterruptCB; external av__format;
+**)
+
+{$IF LIBAVFORMAT_VERSION >= 52002000} // 52.2.0
+(**
+ * If protocol is NULL, returns the first registered protocol,
+ * if protocol is non-NULL, returns the next registered protocol after protocol,
+ * or NULL if protocol is the last one.
+ *)
+function av_protocol_next(p: PURLProtocol): PURLProtocol;
+  cdecl; external av__format;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION <= 52028000} // 52.28.0
+(**
+ * Register the URLProtocol protocol.
+ *
+ *
+ * @deprecated Use av_register_protocol() instead.
+ *)
+function register_protocol(protocol: PURLProtocol): cint;
+  cdecl; external av__format;
+(** Alias for register_protocol()
+ *
+ * @deprecated Use av_register_protocol2() instead.
+ *)
+function av_register_protocol(protocol: PURLProtocol): cint;
+  cdecl; external av__format name 'register_protocol';
+{$ELSE}
+{$IF LIBAVFORMAT_VERSION < 52078003} // < 52.78.3
+function av_register_protocol(protocol: PURLProtocol): cint;
+  cdecl; external av__format;
+{$ELSE}
+  {$IFDEF FF_API_REGISTER_PROTOCOL}
+function av_register_protocol(protocol: PURLProtocol): cint;
+  cdecl; external av__format;
+  {$ENDIF}
+{$IFEND}
+{$IFEND}
+{$IF LIBAVFORMAT_VERSION >= 52069000} // 52.69.0
+function av_register_protocol2(protocol: PURLProtocol; size: cint): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+type
+  TReadWriteFunc = function(opaque: Pointer; buf: PByteArray; buf_size: cint): cint; cdecl;
+  TSeekFunc = function(opaque: Pointer; offset: cint64; whence: cint): cint64; cdecl;
+
+function init_put_byte(s: PByteIOContext;
+                buffer: PByteArray;
+                buffer_size: cint; write_flag: cint;
+                opaque: pointer;
+                read_packet: TReadWriteFunc;
+                write_packet: TReadWriteFunc;
+                seek: TSeekFunc): cint;
+  cdecl; external av__format;
+{$IF LIBAVFORMAT_VERSION >= 52004000} // 52.4.0
+function av_alloc_put_byte(
+                  buffer: PByteArray;
+                  buffer_size: cint;
+                  write_flag: cint;
+                  opaque: Pointer;
+                  read_packet: TReadWriteFunc;
+                  write_packet: TReadWriteFunc;
+                  seek: TSeekFunc): PByteIOContext;
+  cdecl; external av__format;
+{$IFEND}
+
+procedure put_byte(s: PByteIOContext; b: cint);
+  cdecl; external av__format;
+procedure put_buffer (s: PByteIOContext; buf: {const} PByteArray; size: cint);
+  cdecl; external av__format;
+procedure put_le64(s: PByteIOContext; val: cuint64);
+  cdecl; external av__format;
+procedure put_be64(s: PByteIOContext; val: cuint64);
+  cdecl; external av__format;
+procedure put_le32(s: PByteIOContext; val: cuint);
+  cdecl; external av__format;
+procedure put_be32(s: PByteIOContext; val: cuint);
+  cdecl; external av__format;
+procedure put_le24(s: PByteIOContext; val: cuint);
+  cdecl; external av__format;
+procedure put_be24(s: PByteIOContext; val: cuint);
+  cdecl; external av__format;
+procedure put_le16(s: PByteIOContext; val: cuint);
+  cdecl; external av__format;
+procedure put_be16(s: PByteIOContext; val: cuint);
+  cdecl; external av__format;
+procedure put_tag(s: PByteIOContext; tag: {const} PAnsiChar);
+  cdecl; external av__format;
+
+procedure put_strz(s: PByteIOContext; buf: {const} PAnsiChar);
+  cdecl; external av__format;
+
+(**
+ * fseek() equivalent for ByteIOContext.
+ * @return new position or AVERROR.
+ *)
+function url_fseek(s: PByteIOContext; offset: cint64; whence: cint): cint64;
+  cdecl; external av__format;
+
+(**
+ * Skip given number of bytes forward.
+ * @param offset number of bytes
+ * @return 0 on success, <0 on error
+ *)
+{$IF LIBAVFORMAT_VERSION < 52074000} // 52.74.0
+procedure url_fskip(s: PByteIOContext; offset: cint64);
+  cdecl; external av__format;
+{$ELSE}
+function url_fskip(s: PByteIOContext; offset: cint64): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * ftell() equivalent for ByteIOContext.
+ * @return position or AVERROR.
+ *)
+function url_ftell(s: PByteIOContext): cint64;
+  cdecl; external av__format;
+
+(**
+ * Get the filesize.
+ * @return filesize or AVERROR
+ *)
+function url_fsize(s: PByteIOContext): cint64;
+  cdecl; external av__format;
+
+(**
+ * feof() equivalent for ByteIOContext.
+ * @return non zero if and only if end of file
+ *)
+function url_feof(s: PByteIOContext): cint;
+  cdecl; external av__format;
+
+function url_ferror(s: PByteIOContext): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52004000} // 52.4.0
+function av_url_read_fpause(h: PByteIOContext; pause: cint): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52001000} // 52.1.0
+function av_url_read_fseek(h: PByteIOContext; stream_index: cint;
+                           timestamp: cint64; flags: cint): cint64;
+  cdecl; external av__format;
+{$IFEND}
+
+const
+  URL_EOF = -1;
+(** @note return URL_EOF (-1) if EOF *)
+function url_fgetc(s: PByteIOContext): cint;
+  cdecl; external av__format;
+
+(** @warning currently size is limited *)
+function url_fprintf(s: PByteIOContext; fmt: {const} PAnsiChar; args: array of const): cint;
+  cdecl; external av__format;
+
+(** @note unlike fgets, the EOL character is not returned and a whole
+   line is parsed. return NULL if first char read was EOF *)
+function url_fgets(s: PByteIOContext; buf: PAnsiChar; buf_size: cint): PAnsiChar;
+  cdecl; external av__format;
+
+procedure put_flush_packet (s: PByteIOContext);
+  cdecl; external av__format;
+
+(**
+ * Read size bytes from ByteIOContext into buf.
+ * @return number of bytes read or AVERROR
+ *)
+function get_buffer(s: PByteIOContext; buf: PByteArray; size: cint): cint;
+  cdecl; external av__format;
+
+(**
+ * Read size bytes from ByteIOContext into buf.
+ * This reads at most 1 packet. If that is not enough fewer bytes will be
+ * returned.
+ * @return number of bytes read or AVERROR
+ *)
+function get_partial_buffer(s: PByteIOContext; buf: PByteArray; size: cint): cint;
+  cdecl; external av__format;
+
+(** @note return 0 if EOF, so you cannot use it if EOF handling is
+   necessary *)
+function get_byte(s: PByteIOContext): cint;
+  cdecl; external av__format;
+function get_le24(s: PByteIOContext): cuint;
+  cdecl; external av__format;
+function get_le32(s: PByteIOContext): cuint;
+  cdecl; external av__format;
+function get_le64(s: PByteIOContext): cuint64;
+  cdecl; external av__format;
+function get_le16(s: PByteIOContext): cuint;
+  cdecl; external av__format;
+
+function get_strz(s: PByteIOContext; buf: PAnsiChar; maxlen: cint): PAnsiChar;
+  cdecl; external av__format;
+function get_be16(s: PByteIOContext): cuint;
+  cdecl; external av__format;
+function get_be24(s: PByteIOContext): cuint;
+  cdecl; external av__format;
+function get_be32(s: PByteIOContext): cuint;
+  cdecl; external av__format;
+function get_be64(s: PByteIOContext): cuint64;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 51017001} // 51.17.1
+  {$IF LIBAVFORMAT_VERSION < 52078003} // < 52.78.3
+function ff_get_v(bc: PByteIOContext): cuint64;
+  cdecl; external av__format;
+  {$ELSE}
+    {$IFDEF FF_API_URL_RESETBUF}
+function ff_get_v(bc: PByteIOContext): cuint64;
+  cdecl; external av__format;
+    {$ENDIF}
+  {$IFEND}
+{$IFEND}
+
+function url_is_streamed(s: PByteIOContext): cint; {$IFDEF HasInline}inline;{$ENDIF}
+
+(**
+ * Create and initialize a ByteIOContext for accessing the
+ * resource referenced by the URLContext h.
+ * @note When the URLContext h has been opened in read+write mode, the
+ * ByteIOContext can be used only for writing.
+ *
+ * @param s Used to return the pointer to the created ByteIOContext.
+ * In case of failure the pointed to value is set to NULL.
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code in case of failure
+ *)
+{$IF LIBAVFORMAT_VERSION >= 52000000} // 52.0.0
+function url_fdopen (var s: PByteIOContext; h: PURLContext): cint;
+{$ELSE}
+function url_fdopen (s: PByteIOContext; h: PURLContext): cint;
+{$IFEND}
+  cdecl; external av__format;
+
+(** @warning must be called before any I/O *)
+function url_setbufsize (s: PByteIOContext; buf_size: cint): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+{$IF LIBAVFORMAT_VERSION >= 51015000} // 51.15.0
+(** Reset the buffer for reading or writing.
+ * @note Will drop any data currently in the buffer without transmitting it.
+ * @param flags URL_RDONLY to set up the buffer for reading, or URL_WRONLY
+ *        to set up the buffer for writing. *)
+function url_resetbuf(s: PByteIOContext; flags: cint): cint;
+  cdecl; external av__format;
+{$IFEND}
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52061000} // 52.61.0
+(**
+ * Rewind the ByteIOContext using the specified buffer containing the first buf_size bytes of the file.
+ * Used after probing to avoid seeking.
+ * Joins buf and s->buffer, taking any overlap into consideration.
+ * @note s->buffer must overlap with buf or they can't be joined and the function fails
+ * @note This function is NOT part of the public API
+ *
+ * @param s The read-only ByteIOContext to rewind
+ * @param buf The probe buffer containing the first buf_size bytes of the file
+ * @param buf_size The size of buf
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code in case of failure
+ *)
+function ff_rewind_with_probe_data(s: PByteIOContext;  buf: PAnsiChar; buf_size: cint): cint;
+  cdecl; external av__format;
+{$IFEND}
+
+(**
+ * Create and initialize a ByteIOContext for accessing the
+ * resource indicated by url.
+ * @note When the resource indicated by url has been opened in
+ * read+write mode, the ByteIOContext can be used only for writing.
+ *
+ * @param s Used to return the pointer to the created ByteIOContext.
+ * In case of failure the pointed to value is set to NULL.
+ * @param flags flags which control how the resource indicated by url
+ * is to be opened
+ * @return 0 in case of success, a negative value corresponding to an
+ * AVERROR code in case of failure
+ *)
+{$IF LIBAVFORMAT_VERSION < 52047000} // 52.47.0
+{$IF LIBAVFORMAT_VERSION >= 52000000} // 52.0.0
+function url_fopen(var s: PByteIOContext; filename: {const} PAnsiChar; flags: cint): cint;
+{$ELSE}
+function url_fopen(s: PByteIOContext; filename: {const} PAnsiChar; flags: cint): cint;
+{$IFEND}
+{$ELSE}
+function url_fopen(var s: PByteIOContext; url: {const} PAnsiChar; flags: cint): cint;
+{$IFEND}
+  cdecl; external av__format;
+function url_fclose(s: PByteIOContext): cint;
+  cdecl; external av__format;
+function url_fileno(s: PByteIOContext): PURLContext;
+  cdecl; external av__format;
+
+(**
+ * Return the maximum packet size associated to packetized buffered file
+ * handle. If the file is not packetized (stream like http or file on
+ * disk), then 0 is returned.
+ *
+ * @param s buffered file handle
+ * @return maximum packet size in bytes
+ *)
+function url_fget_max_packet_size (s: PByteIOContext): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 52000000} // 52.0.0
+function url_open_buf(var s: PByteIOContext; buf: PAnsiChar; buf_size: cint; flags: cint): cint;
+{$ELSE}
+function url_open_buf(s: PByteIOContext; buf: PAnsiChar; buf_size: cint; flags: cint): cint;
+{$IFEND}
+  cdecl; external av__format;
+
+(** return the written or read size *)
+function url_close_buf(s: PByteIOContext): cint;
+  cdecl; external av__format;
+
+(**
+ * Open a write only memory stream.
+ *
+ * @param s new IO context
+ * @return zero if no error.
+ *)
+{$IF LIBAVFORMAT_VERSION >= 52000000} // 52.0.0
+function url_open_dyn_buf(var s: PByteIOContext): cint;
+{$ELSE}
+function url_open_dyn_buf(s: PByteIOContext): cint;
+{$IFEND}
+  cdecl; external av__format;
+
+(**
+ * Open a write only packetized memory stream with a maximum packet
+ * size of 'max_packet_size'.  The stream is stored in a memory buffer
+ * with a big endian 4 byte header giving the packet size in bytes.
+ *
+ * @param s new IO context
+ * @param max_packet_size maximum packet size (must be > 0)
+ * @return zero if no error.
+ *)
+{$IF LIBAVFORMAT_VERSION >= 52000000} // 52.0.0
+function url_open_dyn_packet_buf(var s: PByteIOContext; max_packet_size: cint): cint;
+{$ELSE}
+function url_open_dyn_packet_buf(s: PByteIOContext; max_packet_size: cint): cint;
+{$IFEND}
+  cdecl; external av__format;
+
+(**
+ * Return the written size and a pointer to the buffer. The buffer
+ * must be freed with av_free(). If the buffer is opened with
+ * url_open_dyn_buf, then padding of FF_INPUT_BUFFER_PADDING_SIZE is
+ * added; if opened with url_open_dyn_packet_buf, no padding is added.
+ * @param s IO context
+ * @param pbuffer pointer to a byte buffer
+ * @return the length of the byte buffer
+ *)
+function url_close_dyn_buf(s: PByteIOContext; pbuffer:PPointer): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION >= 51017001} // 51.17.1
+function ff_crc04C11DB7_update(checksum: culong; buf: {const} PByteArray;
+                               len: cuint): culong;
+  cdecl; external av__format;
+{$IFEND}
+
+function get_checksum(s: PByteIOContext): culong;
+  cdecl; external av__format;
+procedure init_gsum(s: PByteIOContext;
+                        update_checksum: pointer;
+                        checksum: culong);
+  cdecl; external av__format;
+
+(* udp.c *)
+function udp_set_remote_url(h: PURLContext; uri: {const} PAnsiChar): cint;
+  cdecl; external av__format;
+function udp_get_local_port(h: PURLContext): cint;
+  cdecl; external av__format;
+
+{$IF LIBAVFORMAT_VERSION_MAJOR <= 52}
+function udp_get_file_handle(h: PURLContext): cint;
+  cdecl; external av__format;
+{$IFEND}
+  
+implementation
+
+function url_is_streamed(s: PByteIOContext): cint;
+begin
+  Result := s^.is_streamed;
+end;
+
+end.
diff --git a/songmanagement/src/lib/ffmpeg/avutil.pas b/songmanagement/src/lib/ffmpeg/avutil.pas
new file mode 100644
index 00000000..2f8c79f7
--- /dev/null
+++ b/songmanagement/src/lib/ffmpeg/avutil.pas
@@ -0,0 +1,504 @@
+(*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * This is a part of Pascal porting of ffmpeg.
+ * - Originally by Victor Zinetz for Delphi and Free Pascal on Windows.
+ * - For Mac OS X, some modifications were made by The Creative CAT, denoted as CAT
+ *   in the source codes.
+ * - Changes and updates by the UltraStar Deluxe Team
+ *
+ * Conversions of
+ *
+ * libavutil/avutil.h:
+ *  Min. version: 49.0.1,  revision  6577, Sat Oct  7 15:30:46 2006 UTC
+ *  Max. version: 50.24.0, revision 24814, Wed Aug 25 05:00:00 2010 CET
+ *
+ * libavutil/mem.h:
+ *  revision 23904, Wed Jul 21 01:00:00 2010 CET
+ *
+ * libavutil/log.h:
+ *  revision 23972, Wed Jul 21 01:00:00 2010 CET
+ *
+ * include/keep pixfmt.h (change in revision 50.01.0)
+ * Maybe, the pixelformats are not needed, but it has not been checked.
+ * log.h is only partial.
+ *
+ *)
+
+unit avutil;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+  {$linklib libavutil}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  mathematics,
+  rational,
+  {$IFDEF UNIX}
+  BaseUnix,
+  {$ENDIF}
+  UConfig;
+
+const
+  (*
+   * IMPORTANT: The official FFmpeg C headers change very quickly. Often some
+   * of the data structures are changed so that they become incompatible with
+   * older header files. The Pascal headers have to be adjusted to those changes,
+   * otherwise the application might crash randomly or strange bugs (not
+   * necessarily related to video or audio due to buffer overflows etc.) might
+   * occur.
+   *
+   * In the past users reported problems with USDX that took hours to fix and
+   * the problem was an unsupported version of FFmpeg. So we decided to disable
+   * support for future versions of FFmpeg until the headers are revised by us
+   * for that version as they otherwise most probably will break USDX.
+   *
+   * If the headers do not yet support your FFmpeg version you may want to
+   * adjust the max. version numbers manually but please note: it may work but
+   * in many cases it does not. The USDX team does NOT PROVIDE ANY SUPPORT
+   * for the game if the MAX. VERSION WAS CHANGED.
+   *
+   * The only safe way to support new versions of FFmpeg is to add the changes
+   * of the FFmpeg git repository C headers to the Pascal headers.
+   * You can accelerate this process by posting a patch with the git changes
+   * translated to Pascal to our bug tracker (please join our IRC chat before
+   * you start working on it). Simply adjusting the max. versions is NOT a valid
+   * fix. 
+   *)
+  (* Max. supported version by this header *)
+  LIBAVUTIL_MAX_VERSION_MAJOR   = 50;
+  LIBAVUTIL_MAX_VERSION_MINOR   = 24;
+  LIBAVUTIL_MAX_VERSION_RELEASE = 0;
+  LIBAVUTIL_MAX_VERSION = (LIBAVUTIL_MAX_VERSION_MAJOR * VERSION_MAJOR) +
+                          (LIBAVUTIL_MAX_VERSION_MINOR * VERSION_MINOR) +
+                          (LIBAVUTIL_MAX_VERSION_RELEASE * VERSION_RELEASE);
+
+  (* Min. supported version by this header *)
+  LIBAVUTIL_MIN_VERSION_MAJOR   = 49;
+  LIBAVUTIL_MIN_VERSION_MINOR   = 0;
+  LIBAVUTIL_MIN_VERSION_RELEASE = 1;
+  LIBAVUTIL_MIN_VERSION = (LIBAVUTIL_MIN_VERSION_MAJOR * VERSION_MAJOR) +
+                          (LIBAVUTIL_MIN_VERSION_MINOR * VERSION_MINOR) +
+                          (LIBAVUTIL_MIN_VERSION_RELEASE * VERSION_RELEASE);
+
+(* Check if linked versions are supported *)
+{$IF (LIBAVUTIL_VERSION < LIBAVUTIL_MIN_VERSION)}
+  {$MESSAGE Error 'Linked version of libavutil is too old!'}
+{$IFEND}
+
+{$IF (LIBAVUTIL_VERSION > LIBAVUTIL_MAX_VERSION)}
+  {$MESSAGE Error 'Linked version of libavutil is not yet supported!'}
+{$IFEND}
+
+{$IF LIBAVUTIL_VERSION >= 49008000} // 49.8.0
+(**
+ * Return the LIBAVUTIL_VERSION_INT constant.
+ *)
+function avutil_version(): cuint;
+  cdecl; external av__util;
+{$IFEND}
+
+{$IF LIBAVUTIL_VERSION >= 50004000} // >= 50.4.0
+(**
+ * Return the libavutil build-time configuration.
+ *)
+function avutil_configuration(): PAnsiChar;
+  cdecl; external av__util;
+
+(**
+ * Return the libavutil license.
+ *)
+function avutil_license(): PAnsiChar;
+  cdecl; external av__util;
+{$IFEND}
+
+{
+  TAVMediaType moved to avutil in LIBAVUTIL_VERSION 50.14.0
+  but moving it in the pascal headers was not really necessary
+  but caused problems. So, I (KMS) left it there.
+
+type
+  TAVMediaType = (
+    AVMEDIA_TYPE_UNKNOWN = -1,
+    AVMEDIA_TYPE_VIDEO,
+    AVMEDIA_TYPE_AUDIO,
+    AVMEDIA_TYPE_DATA,
+    AVMEDIA_TYPE_SUBTITLE,
+    AVMEDIA_TYPE_ATTACHMENT,
+    AVMEDIA_TYPE_NB
+  );
+}
+
+{$INCLUDE error.pas}
+
+(* libavutil/pixfmt.h up to revision 23144, May 16 2010 *)
+
+type
+(**
+ * Pixel format. Notes:
+ *
+ * PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA
+ * color is put together as:
+ *  (A << 24) | (R << 16) | (G << 8) | B
+ * This is stored as BGRA on little-endian CPU architectures and ARGB on
+ * big-endian CPUs.
+ *
+ * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized
+ * image data is stored in AVFrame.data[0]. The palette is transported in
+ * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is
+ * formatted the same as in PIX_FMT_RGB32 described above (i.e., it is
+ * also endian-specific). Note also that the individual RGB palette
+ * components stored in AVFrame.data[1] should be in the range 0..255.
+ * This is important as many custom PAL8 video codecs that were designed
+ * to run on the IBM VGA graphics adapter use 6-bit palette components.
+ *
+ * For all the 8bit per pixel formats, an RGB32 palette is in data[1] like
+ * for pal8. This palette is filled in automatically by the function
+ * allocating the picture.
+ *
+ * Note, make sure that all newly added big endian formats have pix_fmt&1==1
+ * and that all newly added little endian formats have pix_fmt&1==0
+ * this allows simpler detection of big vs little endian.
+ *)
+
+  PAVPixelFormat = ^TAVPixelFormat;
+  TAVPixelFormat = (
+    PIX_FMT_NONE= -1,
+    PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
+    PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
+    PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...
+    PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...
+    PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+    PIX_FMT_YUV444P,   ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
+{$IF LIBAVUTIL_VERSION <= 50001000} // 50.01.0
+    PIX_FMT_RGB32,     ///< packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in CPU endianness
+{$IFEND}
+    PIX_FMT_YUV410P,   ///< planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
+    PIX_FMT_YUV411P,   ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
+{$IF LIBAVUTIL_VERSION <= 50000000} // 50.00.0
+    PIX_FMT_RGB565,    ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), in CPU endianness
+    PIX_FMT_RGB555,    ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in CPU endianness, most significant bit to 0
+{$IFEND}
+    PIX_FMT_GRAY8,     ///<        Y        ,  8bpp
+    PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
+    PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
+    PIX_FMT_PAL8,      ///< 8 bit with PIX_FMT_RGB32 palette
+    PIX_FMT_YUVJ420P,  ///< planar YUV 4:2:0, 12bpp, full scale (JPEG)
+    PIX_FMT_YUVJ422P,  ///< planar YUV 4:2:2, 16bpp, full scale (JPEG)
+    PIX_FMT_YUVJ444P,  ///< planar YUV 4:4:4, 24bpp, full scale (JPEG)
+    PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing
+    PIX_FMT_XVMC_MPEG2_IDCT,
+    PIX_FMT_UYVY422,   ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
+    PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
+{$IF LIBAVUTIL_VERSION <= 50001000} // 50.01.0
+    PIX_FMT_BGR32,     ///< packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in CPU endianness
+{$IFEND}
+{$IF LIBAVUTIL_VERSION <= 50000000} // 50.00.0
+    PIX_FMT_BGR565,    ///< packed RGB 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), in CPU endianness
+    PIX_FMT_BGR555,    ///< packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in CPU endianness, most significant bit to 1
+{$IFEND}
+    PIX_FMT_BGR8,      ///< packed RGB 3:3:2,  8bpp, (msb)2B 3G 3R(lsb)
+    PIX_FMT_BGR4,      ///< packed RGB 1:2:1, bitstream,  4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
+    PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1B 2G 1R(lsb)
+    PIX_FMT_RGB8,      ///< packed RGB 3:3:2,  8bpp, (msb)2R 3G 3B(lsb)
+    PIX_FMT_RGB4,      ///< packed RGB 1:2:1, bitstream,  4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
+    PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1R 2G 1B(lsb)
+    PIX_FMT_NV12,      ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
+    PIX_FMT_NV21,      ///< as above, but U and V bytes are swapped
+{$IF LIBAVUTIL_VERSION <= 50001000} // 50.01.0
+    PIX_FMT_RGB32_1,   ///< packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in CPU endianness
+    PIX_FMT_BGR32_1,   ///< packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in CPU endianness
+{$ELSE} // 50.02.0
+    PIX_FMT_ARGB,      ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
+    PIX_FMT_RGBA,      ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
+    PIX_FMT_ABGR,      ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
+    PIX_FMT_BGRA,      ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
+{$IFEND}
+    PIX_FMT_GRAY16BE,  ///<        Y        , 16bpp, big-endian
+    PIX_FMT_GRAY16LE,  ///<        Y        , 16bpp, little-endian
+    PIX_FMT_YUV440P,   ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
+    PIX_FMT_YUVJ440P,  ///< planar YUV 4:4:0 full scale (JPEG)
+    PIX_FMT_YUVA420P,  ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
+    PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+    PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+    PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+    PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+    PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+{$IF LIBAVUTIL_VERSION >= 49015000} // 49.15.0
+    PIX_FMT_RGB48BE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian
+    PIX_FMT_RGB48LE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian
+{$IFEND}
+{$IF LIBAVUTIL_VERSION >= 50001000} // 50.01.0
+    PIX_FMT_RGB565BE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), big-endian
+    PIX_FMT_RGB565LE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), little-endian
+    PIX_FMT_RGB555BE,  ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), big-endian, most significant bit to 0
+    PIX_FMT_RGB555LE,  ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), little-endian, most significant bit to 0
+
+    PIX_FMT_BGR565BE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), big-endian
+    PIX_FMT_BGR565LE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), little-endian
+    PIX_FMT_BGR555BE,  ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), big-endian, most significant bit to 1
+    PIX_FMT_BGR555LE,  ///< packed BGR 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), little-endian, most significant bit to 1
+
+    PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
+    PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
+    PIX_FMT_VAAPI_VLD,  ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+{$IFEND}
+    PIX_FMT_NB         ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
+  );
+
+const
+{$ifdef WORDS_BIGENDIAN}
+  {$IF LIBAVUTIL_VERSION <= 50001000} // 50.01.0
+    PIX_FMT_RGBA    = PIX_FMT_RGB32_1;
+    PIX_FMT_BGRA    = PIX_FMT_BGR32_1;
+    PIX_FMT_ARGB    = PIX_FMT_RGB32;
+    PIX_FMT_ABGR    = PIX_FMT_BGR32;
+  {$ELSE} // 50.02.0
+    PIX_FMT_RGB32   = PIX_FMT_ARGB;
+    PIX_FMT_RGB32_1 = PIX_FMT_RGBA;
+    PIX_FMT_BGR32   = PIX_FMT_ABGR;
+    PIX_FMT_BGR32_1 = PIX_FMT_BGRA;
+  {$IFEND}
+  PIX_FMT_GRAY16  = PIX_FMT_GRAY16BE;
+  {$IF LIBAVUTIL_VERSION >= 49015000} // 49.15.0
+    PIX_FMT_RGB48   = PIX_FMT_RGB48BE;
+  {$IFEND}
+  {$IF LIBAVUTIL_VERSION >= 50001000} // 50.01.0
+    PIX_FMT_RGB565  = PIX_FMT_RGB565BE;
+    PIX_FMT_RGB555  = PIX_FMT_RGB555BE;
+    PIX_FMT_BGR565  = PIX_FMT_BGR565BE;
+    PIX_FMT_BGR555  = PIX_FMT_BGR555BE
+  {$IFEND}
+{$else}
+  {$IF LIBAVUTIL_VERSION <= 50001000} // 50.01.0
+    PIX_FMT_RGBA    = PIX_FMT_BGR32;
+    PIX_FMT_BGRA    = PIX_FMT_RGB32;
+    PIX_FMT_ARGB    = PIX_FMT_BGR32_1;
+    PIX_FMT_ABGR    = PIX_FMT_RGB32_1;
+  {$ELSE} // 50.02.0
+    PIX_FMT_RGB32   = PIX_FMT_BGRA;
+    PIX_FMT_RGB32_1 = PIX_FMT_ABGR;
+    PIX_FMT_BGR32   = PIX_FMT_RGBA;
+    PIX_FMT_BGR32_1 = PIX_FMT_ARGB;
+  {$IFEND}
+  PIX_FMT_GRAY16  = PIX_FMT_GRAY16LE;
+  {$IF LIBAVUTIL_VERSION >= 49015000} // 49.15.0
+    PIX_FMT_RGB48   = PIX_FMT_RGB48LE;
+  {$IFEND}
+  {$IF LIBAVUTIL_VERSION >= 50001000} // 50.01.0
+    PIX_FMT_RGB565  = PIX_FMT_RGB565LE;
+    PIX_FMT_RGB555  = PIX_FMT_RGB555LE;
+    PIX_FMT_BGR565  = PIX_FMT_BGR565LE;
+    PIX_FMT_BGR555  = PIX_FMT_BGR555LE;
+  {$IFEND}
+{$ENDIF}
+
+{$IF LIBAVUTIL_VERSION_MAJOR < 50} // 50.0.0
+  PIX_FMT_UYVY411 = PIX_FMT_UYYVYY411;
+  PIX_FMT_RGBA32  = PIX_FMT_RGB32;
+  PIX_FMT_YUV422  = PIX_FMT_YUYV422;
+{$IFEND}
+
+(* libavutil/common.h *) // until now MKTAG and MKBETAG is all from common.h KMS 19/5/2010
+
+function MKTAG(a, b, c, d: AnsiChar): integer;
+function MKBETAG(a, b, c, d: AnsiChar): integer;
+
+(* libavutil/mem.h *)
+
+(* memory handling functions *)
+
+(**
+ * Allocate a block of size bytes with alignment suitable for all
+ * memory accesses (including vectors if available on the CPU).
+ * @param size Size in bytes for the memory block to be allocated.
+ * @return Pointer to the allocated block, NULL if the block cannot
+ * be allocated.
+ * @see av_mallocz()
+ *)
+function av_malloc(size: cuint): pointer;
+  cdecl; external av__util; {av_malloc_attrib av_alloc_size(1)}
+
+(**
+ * Allocate or reallocate a block of memory.
+ * If ptr is NULL and size > 0, allocate a new block. If 
+ * size is zero, free the memory block pointed to by ptr.
+ * @param size Size in bytes for the memory block to be allocated or
+ * reallocated.
+ * @param ptr Pointer to a memory block already allocated with
+ * av_malloc(z)() or av_realloc() or NULL.
+ * @return Pointer to a newly reallocated block or NULL if the block
+ * cannot be allocated or the function is used to free the memory block.
+ * @see av_fast_realloc()
+ *)
+function av_realloc(ptr: pointer; size: cuint): pointer;
+  cdecl; external av__util; {av_alloc_size(2)}
+
+(**
+ * Free a memory block which has been allocated with av_malloc(z)() or
+ * av_realloc().
+ * @param ptr Pointer to the memory block which should be freed.
+ * @note ptr = NULL is explicitly allowed.
+ * @note It is recommended that you use av_freep() instead.
+ * @see av_freep()
+ *)
+procedure av_free(ptr: pointer);
+  cdecl; external av__util;
+
+(**
+ * Allocate a block of size bytes with alignment suitable for all
+ * memory accesses (including vectors if available on the CPU) and
+ * zeroes all the bytes of the block.
+ * @param size Size in bytes for the memory block to be allocated.
+ * @return Pointer to the allocated block, NULL if it cannot be allocated.
+ * @see av_malloc()
+ *)
+function av_mallocz(size: cuint): pointer;
+  cdecl; external av__util; {av_malloc_attrib av_alloc_size(1)}
+
+(**
+ * Duplicate the string s.
+ * @param s string to be duplicated.
+ * @return Pointer to a newly allocated string containing a
+ * copy of s or NULL if the string cannot be allocated.
+ *)
+function av_strdup({const} s: PAnsiChar): PAnsiChar;
+  cdecl; external av__util; {av_malloc_attrib}
+
+(**
+ * Freesa memory block which has been allocated with av_malloc(z)() or
+ * av_realloc() and set the pointer pointing to it to NULL.
+ * @param ptr Pointer to the pointer to the memory block which should
+ * be freed.
+ * @see av_free()
+ *)
+procedure av_freep (ptr: pointer);
+  cdecl; external av__util;
+
+(* libavutil/log.h *)
+
+const
+{$IF LIBAVUTIL_VERSION_MAJOR < 50}
+  AV_LOG_QUIET   = -1;
+  AV_LOG_FATAL   =  0;
+  AV_LOG_ERROR   =  0;
+  AV_LOG_WARNING =  1;
+  AV_LOG_INFO    =  1;
+  AV_LOG_VERBOSE =  1;
+  AV_LOG_DEBUG   =  2;
+{$ELSE}
+  AV_LOG_QUIET   = -8;
+
+(**
+ * Something went really wrong and we will crash now.
+ *)
+  AV_LOG_PANIC   =  0;
+
+(**
+ * Something went wrong and recovery is not possible.
+ * For example, no header was found for a format which depends
+ * on headers or an illegal combination of parameters is used.
+ *)
+  AV_LOG_FATAL   =  8;
+
+(**
+ * Something went wrong and cannot losslessly be recovered.
+ * However, not all future data is affected.
+ *)
+  AV_LOG_ERROR   = 16;
+
+(**
+ * Something somehow does not look correct. This may or may not
+ * lead to problems. An example would be the use of '-vstrict -2'.
+ *)
+  AV_LOG_WARNING = 24;
+
+  AV_LOG_INFO    = 32;
+  AV_LOG_VERBOSE = 40;
+
+(**
+ * Stuff which is only useful for libav* developers.
+ *)
+  AV_LOG_DEBUG   = 48;
+{$IFEND}
+
+(**
+ * Send the specified message to the log if the level is less than or equal
+ * to the current av_log_level. By default, all logging messages are sent to
+ * stderr. This behavior can be altered by setting a different av_vlog callback
+ * function.
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ * pointer to an AVClass struct.
+ * @param level The importance level of the message, lower values signifying
+ * higher importance.
+ * @param fmt The format string (printf-compatible) that specifies how
+ * subsequent arguments are converted to output.
+ * @see av_vlog
+ *)
+
+{** to be translated if needed
+#ifdef __GNUC__
+void av_log(void*, int level, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4)));
+#else
+void av_log(void*, int level, const char *fmt, ...);
+#endif
+ 
+void av_vlog(void*, int level, const char *fmt, va_list);
+**}
+
+function av_log_get_level(): cint;
+  cdecl; external av__util;
+procedure av_log_set_level(level: cint);
+  cdecl; external av__util;
+
+{** to be translated if needed
+void av_log_set_callback(void (*)(void*, int, const char*, va_list));
+void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl);
+**}
+
+{$IF LIBAVUTIL_VERSION >= 50015003} // 50.15.3
+function av_default_item_name (ctx: pointer): Pchar;
+  cdecl; external av__util;
+{$IFEND}
+
+implementation
+
+(* libavutil/common.h *)
+
+function MKTAG(a, b, c, d: AnsiChar): integer;
+begin
+  Result := (ord(a) or (ord(b) shl 8) or (ord(c) shl 16) or (ord(d) shl 24));
+end;
+
+function MKBETAG(a, b, c, d: AnsiChar): integer;
+begin
+  Result := (ord(d) or (ord(c) shl 8) or (ord(b) shl 16) or (ord(a) shl 24));
+end;
+
+end.
diff --git a/songmanagement/src/lib/ffmpeg/error.pas b/songmanagement/src/lib/ffmpeg/error.pas
new file mode 100644
index 00000000..720005b6
--- /dev/null
+++ b/songmanagement/src/lib/ffmpeg/error.pas
@@ -0,0 +1,115 @@
+(*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * This is a part of the Pascal port of ffmpeg.
+ * - Changes and updates by the UltraStar Deluxe Team
+ *
+ * Conversion of libavutil/error.h
+ * Max. avutil version:  50.21.0, revision 24190, Wed Jul 21 01:00:00 2010 CET
+ *
+ *)
+
+{$IF LIBAVUTIL_VERSION >= 50012000} // >= 50.12.0
+
+{* error handling *}
+
+const
+{$IFDEF UNIX}
+  ENOENT = ESysENOENT;
+  EIO    = ESysEIO;
+  ENOMEM = ESysENOMEM;
+  EINVAL = ESysEINVAL;
+  EDOM   = ESysEDOM;
+  ENOSYS = ESysENOSYS;
+  EILSEQ = ESysEILSEQ;
+  EPIPE  = ESysEPIPE;
+{$ELSE}
+  ENOENT = 2;
+  EIO    = 5;
+  ENOMEM = 12;
+  EINVAL = 22;
+  EPIPE  = 32;  // just an assumption. needs to be checked.
+  EDOM   = 33;
+  {$IFDEF MSWINDOWS}
+  // Note: we assume that ffmpeg was compiled with MinGW.
+  // This must be changed if DLLs were compiled with cygwin.
+  ENOSYS = 40;  // MSVC/MINGW: 40, CYGWIN: 88,  LINUX/FPC: 38
+  EILSEQ = 42;  // MSVC/MINGW: 42, CYGWIN: 138, LINUX/FPC: 84
+  {$ENDIF}
+{$ENDIF}
+
+(**
+ * We need the sign of the error, because some platforms have 
+ * E* and errno already negated. The previous version failed
+ * with Delphi, because it needed EINVAL defined.
+ * Warning: This code is platform dependent and assumes constants 
+ * to be 32 bit.
+ * This version does the following steps:
+ * 1) shr 30:        shifts the sign bit to bit position 2
+ * 2) and $00000002: sets all other bits to zero
+ *                   positive EINVAL gives 0, negative gives 2
+ * 3) not:           inverts all bits. This gives -1 and -3
+ * 3) - 1:           positive EINVAL gives -1, negative 1
+ *)
+const
+  AVERROR_SIGN = (EINVAL shr 30) and $00000002 - 1;
+
+(*
+#if EINVAL > 0
+#define AVERROR(e) (-(e)) {**< Returns a negative error code from a POSIX error code, to return from library functions. *}
+#define AVUNERROR(e) (-(e)) {**< Returns a POSIX error code from a library function error return value. *}
+#else
+{* Some platforms have E* and errno already negated. *}
+#define AVERROR(e) (e)
+#define AVUNERROR(e) (e)
+#endif
+*)
+
+const
+  AVERROR_UNKNOWN     = AVERROR_SIGN * EINVAL;  (**< unknown error *)
+  AVERROR_IO          = AVERROR_SIGN * EIO;     (**< I/O error *)
+  AVERROR_NUMEXPECTED = AVERROR_SIGN * EDOM;    (**< Number syntax expected in filename. *)
+  AVERROR_INVALIDDATA = AVERROR_SIGN * EINVAL;  (**< invalid data found *)
+  AVERROR_NOMEM       = AVERROR_SIGN * ENOMEM;  (**< not enough memory *)
+  AVERROR_NOFMT       = AVERROR_SIGN * EILSEQ;  (**< unknown format *)
+  AVERROR_NOTSUPP     = AVERROR_SIGN * ENOSYS;  (**< Operation not supported. *)
+  AVERROR_NOENT       = AVERROR_SIGN * ENOENT;  (**< No such file or directory. *)
+{$IF LIBAVCODEC_VERSION >= 52017000} // 52.17.0
+  AVERROR_EOF         = AVERROR_SIGN * EPIPE;   (**< End of file. *)
+{$IFEND}
+  // Note: function calls as constant-initializers are invalid
+  //AVERROR_PATCHWELCOME = -MKTAG('P','A','W','E'); {**< Not yet implemented in FFmpeg. Patches welcome. *}
+  AVERROR_PATCHWELCOME = -(ord('P') or (ord('A') shl 8) or (ord('W') shl 16) or (ord('E') shl 24));
+{$IFEND}
+
+{$IF LIBAVUTIL_VERSION >= 50013000} // >= 50.13.0
+(*
+ * Put a description of the AVERROR code errnum in errbuf.
+ * In case of failure the global variable errno is set to indicate the
+ * error. Even in case of failure av_strerror() will print a generic
+ * error message indicating the errnum provided to errbuf.
+ *
+ * @param errnum      error code to describe
+ * @param errbuf      buffer to which description is written
+ * @param errbuf_size the size in bytes of errbuf
+ * @return 0 on success, a negative value if a description for errnum
+ * cannot be found
+ *)
+
+function av_strerror(errnum: cint; errbuf: Pchar; errbuf_size: cint): cint;
+  cdecl; external av__util;
+{$IFEND}
diff --git a/songmanagement/src/lib/ffmpeg/mathematics.pas b/songmanagement/src/lib/ffmpeg/mathematics.pas
new file mode 100644
index 00000000..98901c2a
--- /dev/null
+++ b/songmanagement/src/lib/ffmpeg/mathematics.pas
@@ -0,0 +1,133 @@
+(*
+ * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * This is a part of Pascal porting of ffmpeg.
+ * - Originally by Victor Zinetz for Delphi and Free Pascal on Windows.
+ * - For Mac OS X, some modifications were made by The Creative CAT, denoted as CAT
+ *   in the source codes.
+ * - Changes and updates by the UltraStar Deluxe Team
+ *
+ * Conversion of libavutil/mathematics.h
+ * avutil max. version 50.23.0, revision 24439, Wed Aug 25 05:00:00 2010 CET
+ *
+ *)
+
+unit mathematics;
+
+{$IFDEF FPC}
+  {$MODE DELPHI }
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  rational,
+  UConfig;
+
+const
+  M_E          = 2.7182818284590452354;   // e
+  M_LN2        = 0.69314718055994530942;  // log_e 2
+  M_LN10       = 2.30258509299404568402;  // log_e 10
+{$IF LIBAVUTIL_VERSION >= 50009000} // >= 50.9.0
+  M_LOG2_10    = 3.32192809488736234787;  // log_2 10
+{$IFEND}
+{$IF LIBAVUTIL_VERSION >= 50023000} // >= 50.23.0
+  M_PHI        = 1.61803398874989484820;  // phi / golden ratio
+{$IFEND}
+  M_PI         = 3.14159265358979323846;  // pi
+  M_SQRT1_2    = 0.70710678118654752440;  // 1/sqrt(2)
+{$IF LIBAVUTIL_VERSION >= 50014000} // >= 50.14.0
+  M_SQRT2      = 1.41421356237309504880;  // sqrt(2)
+{$IFEND}
+{$IF LIBAVUTIL_VERSION >= 50005001} // >= 50.5.1
+  NAN          = 0.0/0.0;     
+  INFINITY     = 1.0/0.0;     
+{$IFEND}
+
+type
+  TAVRounding = (
+    AV_ROUND_ZERO     = 0, ///< Round toward zero.
+    AV_ROUND_INF      = 1, ///< Round away from zero.
+    AV_ROUND_DOWN     = 2, ///< Round toward -infinity.
+    AV_ROUND_UP       = 3, ///< Round toward +infinity.
+    AV_ROUND_NEAR_INF = 5  ///< Round to nearest and halfway cases away from zero.
+  );
+
+{$IF LIBAVUTIL_VERSION >= 49013000} // 49.13.0
+(**
+ * Return the greatest common divisor of a and b.
+ * If both a or b are 0 or either or both are <0 then behavior is
+ * undefined.
+ *)
+function av_gcd(a: cint64; b: cint64): cint64;
+  cdecl; external av__util; {av_const}
+{$IFEND}
+
+(**
+ * Rescale a 64-bit integer with rounding to nearest.
+ * A simple a*b/c isn't possible as it can overflow.
+ *)
+function av_rescale (a, b, c: cint64): cint64;
+  cdecl; external av__util; {av_const}
+
+(**
+ * Rescale a 64-bit integer with specified rounding.
+ * A simple a*b/c isn't possible as it can overflow.
+ *)
+function av_rescale_rnd (a, b, c: cint64; enum: TAVRounding): cint64;
+  cdecl; external av__util; {av_const}
+
+(**
+ * Rescale a 64-bit integer by 2 rational numbers.
+ *)
+function av_rescale_q (a: cint64; bq, cq: TAVRational): cint64;
+  cdecl; external av__util; {av_const}
+
+{$IF LIBAVUTIL_VERSION >= 50008000} // 50.8.0
+(**
+ * Compare 2 timestamps each in its own timebases.
+ * The result of the function is undefined if one of the timestamps
+ * is outside the int64_t range when represented in the others timebase.
+ * @return -1 if ts_a is before ts_b, 1 if ts_a is after ts_b or 0 if they represent the same position
+ *)
+function av_compare_ts(ts_a: cint64; tb_a: TAVRational; ts_b: cint64; tb_b: TAVRational): cint;
+  cdecl; external av__util;
+{$IFEND}
+ 
+{$IF LIBAVUTIL_VERSION >= 50018000} // 50.18.0
+(**
+ * Compare 2 integers modulo mod.
+ * That is we compare integers a and b for which only the least
+ * significant log2(mod) bits are known.
+ *
+ * @param mod must be a power of 2
+ * @return a negative value if a is smaller than b
+ *         a positiv  value if a is greater than b
+ *         0                if a equals          b
+ *)
+function av_compare_mod(a: cuint64; b: cuint64; modVar: cuint64): cint64;
+  cdecl; external av__util;
+{$IFEND}
+
+implementation
+
+end.
diff --git a/songmanagement/src/lib/ffmpeg/opt.pas b/songmanagement/src/lib/ffmpeg/opt.pas
new file mode 100644
index 00000000..8669eaf6
--- /dev/null
+++ b/songmanagement/src/lib/ffmpeg/opt.pas
@@ -0,0 +1,261 @@
+(*
+ * AVOptions
+ * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * This is a part of Pascal porting of ffmpeg.
+ * - Originally by Victor Zinetz for Delphi and Free Pascal on Windows.
+ * - For Mac OS X, some modifications were made by The Creative CAT, denoted as CAT
+ *   in the source codes.
+ * - Changes and updates by the UltraStar Deluxe Team
+ *
+ * Conversion of libavcodec/opt.h
+ * Max. avcodec version: 52.86.1, 24882, Wed Aug 23 07:00:00 2010 CET
+ *
+ *)
+
+unit opt;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  rational,
+  UConfig;
+
+type
+  TAVOptionType = (
+    FF_OPT_TYPE_FLAGS,
+    FF_OPT_TYPE_INT,
+    FF_OPT_TYPE_INT64,
+    FF_OPT_TYPE_DOUBLE,
+    FF_OPT_TYPE_FLOAT,
+    FF_OPT_TYPE_STRING,
+    FF_OPT_TYPE_RATIONAL,
+    FF_OPT_TYPE_BINARY,  ///< offset must point to a pointer immediately followed by an int for the length
+    FF_OPT_TYPE_CONST = 128
+  );
+
+const
+  AV_OPT_FLAG_ENCODING_PARAM  = 1;   ///< a generic parameter which can be set by the user for muxing or encoding
+  AV_OPT_FLAG_DECODING_PARAM  = 2;   ///< a generic parameter which can be set by the user for demuxing or decoding
+  AV_OPT_FLAG_METADATA        = 4;   ///< some data extracted or inserted into the file like title, comment, ...
+  AV_OPT_FLAG_AUDIO_PARAM     = 8;
+  AV_OPT_FLAG_VIDEO_PARAM     = 16;
+  AV_OPT_FLAG_SUBTITLE_PARAM  = 32;
+
+type
+  (**
+   * AVOption
+   *)
+  PAVOption = ^TAVOption;
+  TAVOption = record
+    name: {const} PAnsiChar;
+    
+    (**
+     * short English help text
+     * @todo What about other languages?
+     *)
+    help: {const} PAnsiChar;
+
+    (**
+     * The offset relative to the context structure where the option
+     * value is stored. It should be 0 for named constants.
+     *)
+    offset: cint;
+    type_: TAVOptionType;
+
+    (**
+     * the default value for scalar options
+     *)
+    default_val: cdouble;
+    min: cdouble;                ///< minimum valid value for the option
+    max: cdouble;                ///< maximum valid value for the option
+
+    flags: cint;
+//FIXME think about enc-audio, ... style flags
+
+    (**
+     * The logical unit to which the option belongs. Non-constant
+     * options and corresponding named constants share the same
+     * unit. May be NULL.
+     *)
+    unit_: {const} PAnsiChar;
+  end;
+
+{$IF LIBAVCODEC_VERSION >= 52042000} // >= 52.42.0
+(**
+ * AVOption2.
+ * THIS IS NOT PART OF THE API/ABI YET!
+ * This is identical to AVOption except that default_val was replaced by
+ * an union, it should be compatible with AVOption on normal platforms.
+ *)
+type
+  PAVOption2 = ^TAVOption2;
+  TAVOption2 = record
+    name   : {const} PAnsiChar;
+
+    (**
+     * short English help text
+     * @todo What about other languages?
+     *)
+    help   : {const} PAnsiChar;
+
+    (**
+     * The offset relative to the context structure where the option
+     * value is stored. It should be 0 for named constants.
+     *)
+    offset : cint;
+    type_  : TAVOptionType;
+
+    (**
+     * the default value for scalar options
+     *)
+    default_val : record
+      case cint of
+        0 : (dbl: cdouble);
+        1 : (str: PAnsiChar);
+      end;
+    min   : cdouble;
+    max   : cdouble;
+    flags : cint;
+//FIXME think about enc-audio, ... style flags
+
+    (**
+     * The logical unit to which the option belongs. Non-constant
+     * options and corresponding named constants share the same
+     * unit. May be NULL.
+     *)
+    unit_: {const} PAnsiChar;
+  end;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 51039000} // 51.39.0
+(**
+ * Look for an option in obj. Look only for the options which
+ * have the flags set as specified in mask and flags (that is,
+ * for which it is the case that opt->flags & mask == flags).
+ *
+ * @param[in] obj a pointer to a struct whose first element is a
+ * pointer to an AVClass
+ * @param[in] name the name of the option to look for
+ * @param[in] unit the unit of the option to look for, or any if NULL
+ * @return a pointer to the option found, or NULL if no option
+ * has been found
+ *)
+function av_find_opt(obj: Pointer; {const} name: {const} PAnsiChar; {const} unit_: PAnsiChar; mask: cint; flags: cint): {const} PAVOption;
+  cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION_MAJOR < 53}
+
+(**
+ * @see av_set_string2()
+ *)
+function av_set_string(obj: pointer; name: {const} PAnsiChar; val: {const} PAnsiChar): {const} PAVOption;
+  cdecl; external av__codec; deprecated;
+
+{$IF LIBAVCODEC_VERSION >= 51059000} // 51.59.0
+(**
+ * @return a pointer to the AVOption corresponding to the field set or
+ * NULL if no matching AVOption exists, or if the value val is not
+ * valid
+ * @see av_set_string3()
+ *)
+function av_set_string2(obj: Pointer; name: {const} PAnsiChar; val: {const} PAnsiChar; alloc: cint): {const} PAVOption;
+  cdecl; external av__codec; deprecated;
+{$IFEND}
+
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52007000} // 52.7.0
+(**
+ * Set the field of obj with the given name to value.
+ *
+ * @param[in] obj A struct whose first element is a pointer to an
+ * AVClass.
+ * @param[in] name the name of the field to set
+ * @param[in] val The value to set. If the field is not of a string
+ * type, then the given string is parsed.
+ * SI postfixes and some named scalars are supported.
+ * If the field is of a numeric type, it has to be a numeric or named
+ * scalar. Behavior with more than one scalar and +- infix operators
+ * is undefined.
+ * If the field is of a flags type, it has to be a sequence of numeric
+ * scalars or named flags separated by '+' or '-'. Prefixing a flag
+ * with '+' causes it to be set without affecting the other flags;
+ * similarly, '-' unsets a flag.
+ * @param[out] o_out if non-NULL put here a pointer to the AVOption
+ * found
+ * @param alloc when 1 then the old value will be av_freed() and the
+ *                     new av_strduped()
+ *              when 0 then no av_free() nor av_strdup() will be used
+ * @return 0 if the value has been set, or an AVERROR code in case of
+ * error:
+ * AVERROR(ENOENT) if no matching option exists
+ * AVERROR(ERANGE) if the value is out of range
+ * AVERROR(EINVAL) if the value is not valid
+ *)
+function av_set_string3(obj: Pointer; name: {const} PAnsiChar; val: {const} PAnsiChar; alloc: cint; out o_out: {const} PAVOption): cint;
+  cdecl; external av__codec;
+{$IFEND}
+
+function av_set_double(obj: pointer; name: {const} PAnsiChar; n: cdouble): PAVOption;
+  cdecl; external av__codec;
+
+function av_set_q(obj: pointer; name: {const} PAnsiChar; n: TAVRational): PAVOption;
+  cdecl; external av__codec;
+
+function av_set_int(obj: pointer; name: {const} PAnsiChar; n: cint64): PAVOption;
+  cdecl; external av__codec;
+
+function av_get_double(obj: pointer; name: {const} PAnsiChar; var o_out: {const} PAVOption): cdouble;
+  cdecl; external av__codec;
+
+function av_get_q(obj: pointer; name: {const} PAnsiChar; var o_out: {const} PAVOption): TAVRational;
+  cdecl; external av__codec;
+
+function av_get_int(obj: pointer; name: {const} PAnsiChar; var o_out: {const} PAVOption): cint64;
+  cdecl; external av__codec;
+
+function av_get_string(obj: pointer; name: {const} PAnsiChar; var o_out: {const} PAVOption; buf: PAnsiChar; buf_len: cint): PAnsiChar;
+  cdecl; external av__codec;
+
+function av_next_option(obj: pointer; last: {const} PAVOption): PAVOption;
+  cdecl; external av__codec;
+
+function av_opt_show(obj: pointer; av_log_obj: pointer): cint;
+  cdecl; external av__codec;
+
+procedure av_opt_set_defaults(s: pointer);
+  cdecl; external av__codec;
+
+{$IF LIBAVCODEC_VERSION >= 51039000} // 51.39.0
+procedure av_opt_set_defaults2(s: Pointer; mask: cint; flags: cint);
+  cdecl; external av__codec;
+{$IFEND}
+
+implementation
+
+end.
diff --git a/songmanagement/src/lib/ffmpeg/rational.pas b/songmanagement/src/lib/ffmpeg/rational.pas
new file mode 100644
index 00000000..323d7937
--- /dev/null
+++ b/songmanagement/src/lib/ffmpeg/rational.pas
@@ -0,0 +1,170 @@
+(*
+ * rational numbers
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * This is a part of Pascal porting of ffmpeg.
+ * - Originally by Victor Zinetz for Delphi and Free Pascal on Windows.
+ * - For Mac OS X, some modifications were made by The Creative CAT, denoted as CAT
+ *   in the source codes.
+ * - Changes and updates by the UltraStar Deluxe Team
+ *
+ * Conversion of libavutil/rational.h
+ * avutil max. version 50.21.0, revision 24190, Wed Jul 21 01:00:00 2010 CET 
+ *
+ *)
+
+unit rational;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$I switches.inc}
+
+interface
+
+uses
+  ctypes,
+  UConfig;
+
+type
+  (*
+   * rational number numerator/denominator
+   *)
+  PAVRational = ^TAVRational;
+  TAVRational = record
+    num: cint; ///< numerator
+    den: cint; ///< denominator
+  end;
+
+  TAVRationalArray = array[0 .. (MaxInt div SizeOf(TAVRational))-1] of TAVRational;
+  PAVRationalArray = ^TAVRationalArray;
+
+(**
+ * Compare two rationals.
+ * @param a first rational
+ * @param b second rational
+ * @return 0 if a==b, 1 if a>b and -1 if a<b
+ *)
+function av_cmp_q(a: TAVRational; b: TAVRational): cint; {$IFDEF HasInline}inline;{$ENDIF}
+
+(**
+ * Convert rational to double.
+ * @param a rational to convert
+ * @return (double) a
+ *)
+function av_q2d(a: TAVRational): cdouble; {$IFDEF HasInline}inline;{$ENDIF}
+
+(**
+ * Reduce a fraction.
+ * This is useful for framerate calculations.
+ * @param dst_num destination numerator
+ * @param dst_den destination denominator
+ * @param num source numerator
+ * @param den source denominator
+ * @param max the maximum allowed for dst_num & dst_den
+ * @return 1 if exact, 0 otherwise
+ *)
+function av_reduce(dst_num: PCint; dst_den: PCint; num: cint64; den: cint64; max: cint64): cint;
+  cdecl; external av__util;
+
+(**
+ * Multiply two rationals.
+ * @param b first rational
+ * @param c second rational
+ * @return b*c
+ *)
+function av_mul_q(b: TAVRational; c: TAVRational): TAVRational;
+  cdecl; external av__util; {av_const}
+
+(**
+ * Divide one rational by another.
+ * @param b first rational
+ * @param c second rational
+ * @return b/c
+ *)
+function av_div_q(b: TAVRational; c: TAVRational): TAVRational;
+  cdecl; external av__util; {av_const}
+
+(**
+ * Add two rationals.
+ * @param b first rational
+ * @param c second rational
+ * @return b+c
+ *)
+function av_add_q(b: TAVRational; c: TAVRational): TAVRational;
+  cdecl; external av__util; {av_const}
+
+(**
+ * Subtract one rational from another.
+ * @param b first rational
+ * @param c second rational
+ * @return b-c
+ *)
+function av_sub_q(b: TAVRational; c: TAVRational): TAVRational;
+  cdecl; external av__util; {av_const}
+
+(**
+ * Convert a double precision floating point number to a rational.
+ * @param d double to convert
+ * @param max the maximum allowed numerator and denominator
+ * @return (AVRational) d
+ *)
+function av_d2q(d: cdouble; max: cint): TAVRational;
+  cdecl; external av__util; {av_const}
+
+{$IF LIBAVUTIL_VERSION >= 49011000} // 49.11.0
+(**
+ * @return 1 if q1 is nearer to q than q2, -1 if q2 is nearer
+ * than q1, 0 if they have the same distance.
+ *)
+function av_nearer_q(q, q1, q2: TAVRational): cint;
+  cdecl; external av__util;
+
+(**
+ * Find the nearest value in q_list to q.
+ * @param q_list an array of rationals terminated by {0, 0}
+ * @return the index of the nearest value found in the array
+ *)
+function av_find_nearest_q_idx(q: TAVRational; q_list: {const} PAVRationalArray): cint;
+  cdecl; external av__util;
+{$IFEND}
+
+implementation
+
+function av_cmp_q (a: TAVRational; b: TAVRational): cint;
+var
+  tmp: cint64;
+begin
+  tmp := a.num * cint64(b.den) - b.num * cint64(a.den);
+
+  if (tmp <> 0) then
+    Result := (tmp shr 63) or 1
+  else
+    Result := 0
+end;
+
+function av_q2d(a: TAVRational): cdouble;
+begin
+  Result := a.num / a.den;
+end;
+
+end.
diff --git a/songmanagement/src/lib/ffmpeg/swscale.pas b/songmanagement/src/lib/ffmpeg/swscale.pas
new file mode 100644
index 00000000..7289e902
--- /dev/null
+++ b/songmanagement/src/lib/ffmpeg/swscale.pas
@@ -0,0 +1,434 @@
+(*
+ * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * FFmpeg Pascal port
+ * - Ported by the UltraStar Deluxe Team
+ *
+ * Conversion of libswscale/swscale.h
+ * Max. version: 0.11.0, revision 31301, Mon Jul 12 8:00:00 2010 CET 
+ *)
+ 
+unit swscale;
+
+{$IFDEF FPC}
+  {$MODE DELPHI }
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+  {$linklib libswscale}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  avutil,
+  avcodec,
+  UConfig;
+
+const
+(*
+ * IMPORTANT: The official FFmpeg C headers change very quickly. Often some
+ * of the data structures are changed so that they become incompatible with
+ * older header files. The Pascal headers have to be adjusted to those changes,
+ * otherwise the application might crash randomly or strange bugs (not
+ * necessarily related to video or audio due to buffer overflows etc.) might
+ * occur.
+ *
+ * In the past users reported problems with USDX that took hours to fix and
+ * the problem was an unsupported version of FFmpeg. So we decided to disable
+ * support for future versions of FFmpeg until the headers are revised by us
+ * for that version as they otherwise most probably will break USDX.
+ *
+ * If the headers do not yet support your FFmpeg version you may want to
+ * adjust the max. version numbers manually but please note: it may work but
+ * in many cases it does not. The USDX team does NOT PROVIDE ANY SUPPORT
+ * for the game if the MAX. VERSION WAS CHANGED.
+ *
+ * The only safe way to support new versions of FFmpeg is to add the changes
+ * of the FFmpeg git repository C headers to the Pascal headers.
+ * You can accelerate this process by posting a patch with the git changes
+ * translated to Pascal to our bug tracker (please join our IRC chat before
+ * you start working on it). Simply adjusting the max. versions is NOT a valid
+ * fix. 
+ *)
+  (* Max. supported version by this header *)
+  LIBSWSCALE_MAX_VERSION_MAJOR   =  0;
+  LIBSWSCALE_MAX_VERSION_MINOR   = 11;
+  LIBSWSCALE_MAX_VERSION_RELEASE =  0;
+  LIBSWSCALE_MAX_VERSION = (LIBSWSCALE_MAX_VERSION_MAJOR * VERSION_MAJOR) +
+                           (LIBSWSCALE_MAX_VERSION_MINOR * VERSION_MINOR) +
+                           (LIBSWSCALE_MAX_VERSION_RELEASE * VERSION_RELEASE);
+
+(* Check if linked versions are supported *)
+{$IF (LIBSWSCALE_VERSION > LIBSWSCALE_MAX_VERSION)}
+  {$MESSAGE Error 'Linked version of libswscale is not yet supported!'}
+{$IFEND}
+
+type
+  TQuadCintArray = array[0..3] of cint;
+  PQuadCintArray = ^TQuadCintArray;
+  TCintArray = array[0..0] of cint;
+  PCintArray = ^TCintArray;
+  TPCuint8Array = array[0..0] of PCuint8;
+  PPCuint8Array = ^TPCuint8Array;
+
+{$IF LIBSWSCALE_VERSION >= 000006001} // 0.6.1
+(**
+ * Returns the LIBSWSCALE_VERSION_INT constant.
+ *)
+function swscale_version(): cuint;
+  cdecl; external sw__scale;
+{$IFEND}
+
+{$IF LIBSWSCALE_VERSION >= 000007002} // 0.7.2
+(**
+ * Returns the libswscale build-time configuration.
+ *)
+function swscale_configuration(): PAnsiChar;
+  cdecl; external sw__scale;
+
+(**
+ * Returns the libswscale license.
+ *)
+function swscale_license(): PAnsiChar;
+  cdecl; external sw__scale;
+{$IFEND}
+
+const
+  (* values for the flags, the stuff on the command line is different *)
+  SWS_FAST_BILINEAR =    1;
+  SWS_BILINEAR      =    2;
+  SWS_BICUBIC       =    4;
+  SWS_X             =    8;
+  SWS_POINT         =  $10;
+  SWS_AREA          =  $20;
+  SWS_BICUBLIN      =  $40;
+  SWS_GAUSS         =  $80;
+  SWS_SINC          = $100;
+  SWS_LANCZOS       = $200;
+  SWS_SPLINE        = $400;
+
+  SWS_SRC_V_CHR_DROP_MASK  = $30000;
+  SWS_SRC_V_CHR_DROP_SHIFT = 16;
+
+  SWS_PARAM_DEFAULT        = 123456;
+
+  SWS_PRINT_INFO           = $1000;
+
+  // the following 3 flags are not completely implemented
+  // internal chrominace subsampling info
+  SWS_FULL_CHR_H_INT    = $2000;
+  // input subsampling info
+  SWS_FULL_CHR_H_INP    = $4000;
+  SWS_DIRECT_BGR        = $8000;
+  SWS_ACCURATE_RND      = $40000;
+  SWS_BITEXACT          = $80000;
+
+  SWS_CPU_CAPS_MMX      = $80000000;
+  SWS_CPU_CAPS_MMX2     = $20000000;
+  SWS_CPU_CAPS_3DNOW    = $40000000;
+  SWS_CPU_CAPS_ALTIVEC  = $10000000;
+  SWS_CPU_CAPS_BFIN     = $01000000;
+
+  SWS_MAX_REDUCE_CUTOFF = 0.002;
+
+  SWS_CS_ITU709         = 1;
+  SWS_CS_FCC            = 4;
+  SWS_CS_ITU601         = 5;
+  SWS_CS_ITU624         = 5;
+  SWS_CS_SMPTE170M      = 5;
+  SWS_CS_SMPTE240M      = 7;
+  SWS_CS_DEFAULT        = 5;
+
+{$IF LIBSWSCALE_VERSION >= 000010000} // 0.10.0
+(**
+ * Returns a pointer to yuv<->rgb coefficients for the given colorspace
+ * suitable for sws_setColorspaceDetails().
+ *
+ * @param colorspace One of the SWS_CS_* macros. If invalid,
+ * SWS_CS_DEFAULT is used.
+ *)
+function sws_getCoefficients(colorspace: cint): Pcint;
+  cdecl; external sw__scale;
+{$IFEND}
+  
+type
+
+  // when used for filters they must have an odd number of elements
+  // coeffs cannot be shared between vectors
+  PSwsVector = ^TSwsVector;
+  TSwsVector = record
+    coeff: PCdouble;    // pointer to the list of coefficients
+    length: cint;       // number of coefficients in the vector
+  end;
+
+  // vectors can be shared
+  PSwsFilter = ^TSwsFilter;
+  TSwsFilter = record
+    lumH: PSwsVector;
+    lumV: PSwsVector;
+    chrH: PSwsVector;
+    chrV: PSwsVector;
+  end;
+
+  PSwsContext = ^TSwsContext;
+  TSwsContext = record
+    {internal structure}
+  end;
+
+{$IF LIBSWSCALE_VERSION >= 000008000} // 0.8.0
+(**
+ * Returns a positive value if pix_fmt is a supported input format, 0
+ * otherwise.
+ *)
+function sws_isSupportedInput(pix_fmt: TAVPixelFormat): cint;
+  cdecl; external sw__scale;
+
+(**
+ * Returns a positive value if pix_fmt is a supported output format, 0
+ * otherwise.
+ *)
+function sws_isSupportedOutput(pix_fmt: TAVPixelFormat): cint;
+  cdecl; external sw__scale;
+{$IFEND}
+
+(**
+ * Frees the swscaler context swsContext.
+ * If swsContext is NULL, then does nothing.
+ *)
+procedure sws_freeContext(swsContext: PSwsContext);
+  cdecl; external sw__scale;
+
+(**
+ * Allocates and returns a SwsContext. You need it to perform
+ * scaling/conversion operations using sws_scale().
+ *
+ * @param srcW the width of the source image
+ * @param srcH the height of the source image
+ * @param srcFormat the source image format
+ * @param dstW the width of the destination image
+ * @param dstH the height of the destination image
+ * @param dstFormat the destination image format
+ * @param flags specify which algorithm and options to use for rescaling
+ * @return a pointer to an allocated context, or NULL in case of error
+ *)
+function sws_getContext(srcW: cint; srcH: cint; srcFormat: TAVPixelFormat;
+                        dstW: cint; dstH: cint; dstFormat: TAVPixelFormat;
+	                flags: cint; srcFilter: PSwsFilter;
+	                dstFilter: PSwsFilter; param: PCdouble): PSwsContext;
+  cdecl; external sw__scale;
+
+(**
+ * Scales the image slice in srcSlice and puts the resulting scaled
+ * slice in the image in dst. A slice is a sequence of consecutive
+ * rows in an image.
+ *
+ * Slices have to be provided in sequential order, either in
+ * top-bottom or bottom-top order. If slices are provided in
+ * non-sequential order the behavior of the function is undefined.
+ *
+ * @param context   the scaling context previously created with
+ *                  sws_getContext()
+ * @param srcSlice  the array containing the pointers to the planes of
+ *                  the source slice
+ * @param srcStride the array containing the strides for each plane of
+ *                  the source image
+ * @param srcSliceY the position in the source image of the slice to
+ *                  process, that is the number (counted starting from
+ *                  zero) in the image of the first row of the slice
+ * @param srcSliceH the height of the source slice, that is the number
+ *                  of rows in the slice
+ * @param dst       the array containing the pointers to the planes of
+ *                  the destination image
+ * @param dstStride the array containing the strides for each plane of
+ *                  the destination image
+ * @return          the height of the output slice
+ *)
+function sws_scale(context: PSwsContext; {const} srcSlice: PPCuint8Array; {const} srcStride: PCintArray;
+              srcSliceY: cint; srcSliceH: cint; {const} dst: PPCuint8Array; {const} dstStride: PCintArray): cint;
+  cdecl; external sw__scale;
+
+{$IF LIBSWSCALE_VERSION_MAJOR < 1}
+// deprecated. Use sws_scale() instead.
+function sws_scale_ordered(context: PSwsContext; {const} src: PPCuint8Array;
+                           srcStride: PCintArray; srcSliceY: cint; srcSliceH: cint;
+	                   dst: PPCuint8Array; dstStride: PCintArray): cint;
+  cdecl; external sw__scale; deprecated;
+{$IFEND}
+
+(**
+ * @param inv_table the yuv2rgb coefficients, normally ff_yuv2rgb_coeffs[x]
+ * @param fullRange if 1 then the luma range is 0..255 if 0 it is 16..235
+ * @return -1 if not supported
+ *)
+function sws_setColorspaceDetails(c: PSwsContext; inv_table: PQuadCintArray; 
+              srcRange: cint; table: PQuadCintArray; dstRange: cint;
+              brightness: cint; contrast: cint; saturation: cint): cint;
+  cdecl; external sw__scale;
+
+(**
+ * @return -1 if not supported
+ *)
+function sws_getColorspaceDetails(c: PSwsContext; var inv_table: PQuadCintArray;
+              var srcRange: cint; var table: PQuadCintArray; var dstRange: cint;
+              var brightness: cint; var contrast: cint; var saturation: cint): cint;
+  cdecl; external sw__scale;
+
+(**
+ * Returns a normalized Gaussian curve used to filter stuff
+ * quality=3 is high quality, lower is lower quality.
+ *)
+function sws_getGaussianVec(variance: cdouble; quality: cdouble): PSwsVector;
+  cdecl; external sw__scale;
+
+(**
+ * Allocates and returns a vector with length coefficients, all
+ * with the same value c.
+ *)
+function sws_getConstVec(c: cdouble; length: cint): PSwsVector;
+  cdecl; external sw__scale;
+  
+(**
+ * Allocates and returns a vector with just one coefficient, with
+ * value 1.0.
+ *)
+function sws_getIdentityVec: PSwsVector;
+  cdecl; external sw__scale;
+
+(**
+ * Scales all the coefficients of a by the scalar value.
+ *)
+procedure sws_scaleVec(a: PSwsVector; scalar: cdouble);
+  cdecl; external sw__scale;
+
+(**
+ * Scales all the coefficients of a so that their sum equals height.
+ *)
+procedure sws_normalizeVec(a: PSwsVector; height: cdouble);
+  cdecl; external sw__scale;
+
+procedure sws_convVec(a: PSwsVector; b: PSwsVector);
+  cdecl; external sw__scale;
+
+procedure sws_addVec(a: PSwsVector; b: PSwsVector);
+  cdecl; external sw__scale;
+
+procedure sws_subVec(a: PSwsVector; b: PSwsVector);
+  cdecl; external sw__scale;
+
+procedure sws_shiftVec(a: PSwsVector; shift: cint);
+  cdecl; external sw__scale;
+
+(**
+ * Allocates and returns a clone of the vector a, that is a vector
+ * with the same coefficients as a.
+ *)
+function sws_cloneVec(a: PSwsVector): PSwsVector;
+  cdecl; external sw__scale;
+
+{$IF LIBSWSCALE_VERSION_MAJOR < 1}
+// deprecated Use sws_printVec2() instead.
+
+procedure sws_printVec(a: PSwsVector);
+  cdecl; external sw__scale; deprecated;
+{$IFEND}
+
+{$IF LIBSWSCALE_VERSION >= 000007000} // >= 0.7.0
+(**
+ * Prints with av_log() a textual representation of the vector a
+ * if log_level <= av_log_level.
+ *)
+procedure sws_printVec2(a:         PSwsVector;
+                        log_ctx:   PAVClass; // PAVClass is declared in avcodec.pas
+			log_level: cint);
+  cdecl; external sw__scale;
+{$IFEND}
+
+procedure sws_freeVec(a: PSwsVector);
+  cdecl; external sw__scale;
+
+function sws_getDefaultFilter(lumaGBlur: cfloat; chromaGBlur: cfloat; 
+                              lumaSharpen: cfloat; chromaSharpen: cfloat;
+			      chromaHShift: cfloat; chromaVShift: cfloat;
+			      verbose: cint): PSwsFilter;
+  cdecl; external sw__scale;
+
+procedure sws_freeFilter(filter: PSwsFilter);
+  cdecl; external sw__scale;
+
+(**
+ * Checks if context can be reused, otherwise reallocates a new
+ * one.
+ * 
+ * If context is NULL, just calls sws_getContext() to get a new
+ * context. Otherwise, checks if the parameters are the ones already
+ * saved in context. If that is the case, returns the current
+ * context. Otherwise, frees context and gets a new context with
+ * the new parameters.
+ * 
+ * Be warned that srcFilter and dstFilter are not checked, they
+ * are assumed to remain the same.
+ *)
+function sws_getCachedContext(context: PSwsContext;
+              srcW: cint; srcH: cint; srcFormat: TAVPixelFormat;
+              dstW: cint; dstH: cint; dstFormat: TAVPixelFormat;
+	      flags: cint; srcFilter: PSwsFilter; 
+	      dstFilter: PSwsFilter; param: PCdouble): PSwsContext;
+  cdecl; external sw__scale;
+
+{$IF LIBSWSCALE_VERSION >= 000011000} // >= 0.11.0
+(**
+ * Converts an 8bit paletted frame into a frame with a color depth of 32-bits.
+ *
+ * The output frame will have the same packed format as the palette.
+ *
+ * @param src        source frame buffer
+ * @param dst        destination frame buffer
+ * @param num_pixels number of pixels to convert
+ * @param palette    array with [256] entries, which must match color arrangement (RGB or BGR) of src
+ *)
+procedure sws_convertPalette8ToPacked32({const} src:      PPCuint8Array;
+                                         dst:             PPCuint8Array;
+					 num_pixels:      clong;
+					 {const} palette: PPCuint8Array);
+  cdecl; external sw__scale;
+
+(**
+ * Converts an 8bit paletted frame into a frame with a color depth of 24 bits.
+ *
+ * With the palette format "ABCD", the destination frame ends up with the format "ABC".
+ *
+ * @param src        source frame buffer
+ * @param dst        destination frame buffer
+ * @param num_pixels number of pixels to convert
+ * @param palette    array with [256] entries, which must match color arrangement (RGB or BGR) of src
+ *)
+procedure sws_convertPalette8ToPacked24({const} src:      PPCuint8Array;
+                                         dst:             PPCuint8Array;
+					 num_pixels:      clong;
+					 {const} palette: PPCuint8Array);
+  cdecl; external sw__scale;
+{$IFEND}
+
+implementation
+
+end.
diff --git a/songmanagement/src/lib/fft/UFFT.pas b/songmanagement/src/lib/fft/UFFT.pas
new file mode 100644
index 00000000..5a056a8c
--- /dev/null
+++ b/songmanagement/src/lib/fft/UFFT.pas
@@ -0,0 +1,602 @@
+{**********************************************************************
+
+  FFT.cpp
+
+  Dominic Mazzoni
+
+  September 2000
+
+***********************************************************************
+
+Fast Fourier Transform routines.
+
+  This file contains a few FFT routines, including a real-FFT
+  routine that is almost twice as fast as a normal complex FFT,
+  and a power spectrum routine when you know you don't care
+  about phase information.
+
+  Some of this code was based on a free implementation of an FFT
+  by Don Cross, available on the web at:
+
+    http://www.intersrv.com/~dcross/fft.html
+
+  The basic algorithm for his code was based on Numerican Recipes
+  in Fortran.  I optimized his code further by reducing array
+  accesses, caching the bit reversal table, and eliminating
+  float-to-double conversions, and I added the routines to
+  calculate a real FFT and a real power spectrum.
+
+***********************************************************************
+
+  Salvo Ventura - November 2006
+  Added more window functions:
+    * 4: Blackman
+    * 5: Blackman-Harris
+    * 6: Welch
+    * 7: Gaussian(a=2.5)
+    * 8: Gaussian(a=3.5)
+    * 9: Gaussian(a=4.5)
+
+***********************************************************************
+
+  This file is part of Audacity 1.3.4 beta (http://audacity.sourceforge.net/)
+  Ported to Pascal by the UltraStar Deluxe Team
+}
+
+unit UFFT;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // Use long strings
+{$ENDIF}
+
+interface
+type
+  TSingleArray = array[0 .. (MaxInt div SizeOf(Single))-1] of Single;
+  PSingleArray = ^TSingleArray;
+
+  TFFTWindowFunc = (
+    fwfRectangular,
+    fwfBartlett,
+    fwfHamming,
+    fwfHanning,
+    fwfBlackman,
+    fwfBlackman_Harris,
+    fwfWelch,
+    fwfGaussian2_5,
+    fwfGaussian3_5,
+    fwfGaussian4_5
+  );
+  
+const
+  FFTWindowName: array[TFFTWindowFunc] of string = (
+     'Rectangular',
+     'Bartlett',
+     'Hamming',
+     'Hanning',
+     'Blackman',
+     'Blackman-Harris',
+     'Welch',
+     'Gaussian(a=2.5)',
+     'Gaussian(a=3.5)',
+     'Gaussian(a=4.5)'
+  );
+
+(*
+ * This is the function you will use the most often.
+ * Given an array of floats, this will compute the power
+ * spectrum by doing a Real FFT and then computing the
+ * sum of the squares of the real and imaginary parts.
+ * Note that the output array is half the length of the
+ * input array, and that NumSamples must be a power of two.
+ *)
+procedure PowerSpectrum(NumSamples: Integer; In_, Out_: PSingleArray);
+
+(*
+ * Computes an FFT when the input data is real but you still
+ * want complex data as output.  The output arrays are half
+ * the length of the input, and NumSamples must be a power of
+ * two.
+ *)
+procedure RealFFT(NumSamples: integer;
+                  RealIn, RealOut, ImagOut: PSingleArray);
+
+(*
+ * Computes a FFT of complex input and returns complex output.
+ * Currently this is the only function here that supports the
+ * inverse transform as well.
+ *)
+procedure FFT(NumSamples: Integer;
+              InverseTransform: boolean;
+              RealIn, ImagIn, RealOut, ImagOut: PSingleArray);
+
+(*
+ * Applies a windowing function to the data in place
+ *
+ * 0: Rectangular (no window)
+ * 1: Bartlett    (triangular)
+ * 2: Hamming
+ * 3: Hanning
+ * 4: Blackman
+ * 5: Blackman-Harris
+ * 6: Welch
+ * 7: Gaussian(a=2.5)
+ * 8: Gaussian(a=3.5)
+ * 9: Gaussian(a=4.5)
+ *)
+procedure WindowFunc(whichFunction: TFFTWindowFunc; NumSamples: Integer; in_: PSingleArray);
+
+(*
+ * Returns the name of the windowing function (for UI display)
+ *)
+function WindowFuncName(whichFunction: TFFTWindowFunc): string;
+
+(*
+ * Returns the number of windowing functions supported
+ *)
+function NumWindowFuncs(): integer;
+
+
+implementation
+
+uses
+  SysUtils;
+
+type TIntArray = array[0 .. (MaxInt div SizeOf(Integer))-1] of Integer;
+type PIntArray = ^TIntArray;
+type TIntIntArray = array[0 .. (MaxInt div SizeOf(PIntArray))-1] of PIntArray;
+type PIntIntArray = ^TIntIntArray;
+var gFFTBitTable: PIntIntArray;
+const MaxFastBits: Integer = 16;
+
+function IsPowerOfTwo(x: Integer): Boolean;
+begin
+   if (x < 2) then
+      result := false
+   else if ((x and (x - 1)) <> 0) then  { Thanks to 'byang' for this cute trick! }
+      result := false
+   else
+    result := true;
+end;
+
+function NumberOfBitsNeeded(PowerOfTwo: Integer): Integer;
+var i: Integer;
+begin
+  if (PowerOfTwo < 2) then begin
+    Writeln(ErrOutput, Format('Error: FFT called with size %d\n', [PowerOfTwo]));
+    Abort;
+  end;
+
+  i := 0;
+  while(true) do begin
+    if (PowerOfTwo and (1 shl i) <> 0) then begin
+      result := i;
+      Exit;
+    end;
+    Inc(i);
+  end;
+end;
+
+function ReverseBits(index, NumBits: Integer): Integer;
+var
+  i, rev: Integer;
+begin
+  rev := 0;
+  for i := 0 to NumBits-1 do begin
+    rev := (rev shl 1) or (index and 1);
+    index := index shr 1;
+  end;
+
+  result := rev;
+end;
+
+procedure InitFFT();
+var
+  len: Integer;
+  b, i: Integer;
+begin
+  GetMem(gFFTBitTable, MaxFastBits * sizeof(PSingle));
+
+  len := 2;
+  for b := 1 to MaxFastBits do begin
+    GetMem(gFFTBitTable[b - 1], len * sizeof(Single));
+    for i := 0 to len-1 do
+      gFFTBitTable[b - 1][i] := ReverseBits(i, b);
+      len := len shl 1;
+   end;
+end;
+
+function FastReverseBits(i, NumBits: Integer): Integer; {$IFDEF HasInline}inline;{$ENDIF}
+begin
+  if (NumBits <= MaxFastBits) then
+    result := gFFTBitTable[NumBits - 1][i]
+  else
+    result := ReverseBits(i, NumBits);
+end;
+
+{*
+ * Complex Fast Fourier Transform
+ *}
+procedure FFT(NumSamples: Integer;
+         InverseTransform: boolean;
+         RealIn, ImagIn, RealOut, ImagOut: PSingleArray);
+var
+  NumBits: Integer;                 { Number of bits needed to store indices }
+  i, j, k, n: Integer;
+  BlockSize, BlockEnd: Integer;
+  delta_angle: Double;
+  angle_numerator: Double;
+  tr, ti: Double;                   { temp real, temp imaginary }
+  sm2, sm1, cm2, cm1: Double;
+  w: Double;
+  ar0, ar1, ar2, ai0, ai1, ai2: Double;
+  denom: Single;
+begin
+
+   angle_numerator := 2.0 * Pi;
+
+   if (not IsPowerOfTwo(NumSamples)) then begin
+      Writeln(ErrOutput, Format('%d is not a power of two', [NumSamples]));
+      Abort;
+   end;
+
+   if (gFFTBitTable = nil) then
+      InitFFT();
+
+   if (InverseTransform) then
+      angle_numerator := -angle_numerator;
+
+   NumBits := NumberOfBitsNeeded(NumSamples);
+
+   {
+    **   Do simultaneous data copy and bit-reversal ordering into outputs...
+   }
+
+   for i := 0 to NumSamples-1 do begin
+      j := FastReverseBits(i, NumBits);
+      RealOut[j] := RealIn[i];
+      if(ImagIn = nil) then
+        ImagOut[j] := 0.0
+      else
+        ImagOut[j] := ImagIn[i];
+   end;
+
+   {
+    **   Do the FFT itself...
+   }
+
+   BlockEnd := 1;
+   BlockSize := 2;
+   while(BlockSize <= NumSamples) do
+   begin
+
+      delta_angle := angle_numerator / BlockSize;
+
+      sm2 := sin(-2 * delta_angle);
+      sm1 := sin(-delta_angle);
+      cm2 := cos(-2 * delta_angle);
+      cm1 := cos(-delta_angle);
+      w := 2 * cm1;
+
+      i := 0;
+      while(i < NumSamples) do
+      begin
+         ar2 := cm2;
+         ar1 := cm1;
+
+         ai2 := sm2;
+         ai1 := sm1;
+
+         j := i;
+         for n := 0 to BlockEnd-1 do
+         begin
+            ar0 := w * ar1 - ar2;
+            ar2 := ar1;
+            ar1 := ar0;
+
+            ai0 := w * ai1 - ai2;
+            ai2 := ai1;
+            ai1 := ai0;
+
+            k := j + BlockEnd;
+            tr := ar0 * RealOut[k] - ai0 * ImagOut[k];
+            ti := ar0 * ImagOut[k] + ai0 * RealOut[k];
+
+            RealOut[k] := RealOut[j] - tr;
+            ImagOut[k] := ImagOut[j] - ti;
+
+            RealOut[j] := RealOut[j] + tr;
+            ImagOut[j] := ImagOut[j] + ti;
+
+            Inc(j);
+         end;
+
+         Inc(i, BlockSize);
+      end;
+
+      BlockEnd := BlockSize;
+      BlockSize := BlockSize shl 1;
+   end;
+
+   {
+      **   Need to normalize if inverse transform...
+   }
+
+   if (InverseTransform) then begin
+      denom := NumSamples;
+
+      for i := 0 to NumSamples-1 do begin
+         RealOut[i] := RealOut[i] / denom;
+         ImagOut[i] := ImagOut[i] / denom;
+      end;
+   end;
+end;
+
+(*
+ * Real Fast Fourier Transform
+ *
+ * This function was based on the code in Numerical Recipes in C.
+ * In Num. Rec., the inner loop is based on a single 1-based array
+ * of interleaved real and imaginary numbers.  Because we have two
+ * separate zero-based arrays, our indices are quite different.
+ * Here is the correspondence between Num. Rec. indices and our indices:
+ *
+ * i1  <->  real[i]
+ * i2  <->  imag[i]
+ * i3  <->  real[n/2-i]
+ * i4  <->  imag[n/2-i]
+ *)
+procedure RealFFT(NumSamples: integer; RealIn, RealOut, ImagOut: PSingleArray);
+var
+  Half: Integer;
+  i: Integer;
+  theta: Single;
+  tmpReal, tmpImag: PSingleArray;
+  wtemp: Single;
+  wpr, wpi, wr, wi: Single;
+  i3: Integer;
+  h1r, h1i, h2r, h2i: Single;
+begin
+   Half := NumSamples div 2;
+
+   theta := Pi / Half;
+
+   GetMem(tmpReal, Half * sizeof(Single));
+   GetMem(tmpImag, Half * sizeof(Single));
+
+   for i := 0 to Half-1 do
+   begin
+      tmpReal[i] := RealIn[2 * i];
+      tmpImag[i] := RealIn[2 * i + 1];
+   end;
+
+   FFT(Half, false, tmpReal, tmpImag, RealOut, ImagOut);
+
+   wtemp := sin(0.5 * theta);
+
+   wpr := -2.0 * wtemp * wtemp;
+   wpi := sin(theta);
+   wr := 1.0 + wpr;
+   wi := wpi;
+
+   for i := 1 to (Half div 2)-1 do
+   begin
+      i3 := Half - i;
+
+      h1r := 0.5 * (RealOut[i] + RealOut[i3]);
+      h1i := 0.5 * (ImagOut[i] - ImagOut[i3]);
+      h2r := 0.5 * (ImagOut[i] + ImagOut[i3]);
+      h2i := -0.5 * (RealOut[i] - RealOut[i3]);
+
+      RealOut[i] := h1r + wr * h2r - wi * h2i;
+      ImagOut[i] := h1i + wr * h2i + wi * h2r;
+      RealOut[i3] := h1r - wr * h2r + wi * h2i;
+      ImagOut[i3] := -h1i + wr * h2i + wi * h2r;
+
+      wtemp := wr;
+      wr := wtemp * wpr - wi * wpi + wr;
+      wi := wi * wpr + wtemp * wpi + wi;
+   end;
+
+   h1r := RealOut[0];
+   RealOut[0] := h1r + ImagOut[0];
+   ImagOut[0] := h1r - ImagOut[0];
+
+   FreeMem(tmpReal);
+   FreeMem(tmpImag);
+end;
+
+{*
+ * PowerSpectrum
+ *
+ * This function computes the same as RealFFT, above, but
+ * adds the squares of the real and imaginary part of each
+ * coefficient, extracting the power and throwing away the
+ * phase.
+ *
+ * For speed, it does not call RealFFT, but duplicates some
+ * of its code.
+ *}
+procedure PowerSpectrum(NumSamples: Integer; In_, Out_: PSingleArray);
+var
+  Half: Integer;
+  i: Integer;
+  theta: Single;
+  tmpReal, tmpImag, RealOut, ImagOut: PSingleArray;
+  wtemp: Single;
+  wpr, wpi, wr, wi: Single;
+  i3: Integer;
+  h1r, h1i, h2r, h2i, rt, it: Single;
+begin
+   Half := NumSamples div 2;
+
+   theta := Pi / Half;
+
+   GetMem(tmpReal, Half * sizeof(Single));
+   GetMem(tmpImag, Half * sizeof(Single));
+   GetMem(RealOut, Half * sizeof(Single));
+   GetMem(ImagOut, Half * sizeof(Single));
+
+   for i := 0 to Half-1 do begin
+      tmpReal[i] := In_[2 * i];
+      tmpImag[i] := In_[2 * i + 1];
+   end;
+
+   FFT(Half, false, tmpReal, tmpImag, RealOut, ImagOut);
+
+   wtemp := sin(0.5 * theta);
+
+   wpr := -2.0 * wtemp * wtemp;
+   wpi := sin(theta);
+   wr := 1.0 + wpr;
+   wi := wpi;
+
+   for i := 1 to (Half div 2)-1 do
+   begin
+      i3 := Half - i;
+
+      h1r := 0.5 * (RealOut[i] + RealOut[i3]);
+      h1i := 0.5 * (ImagOut[i] - ImagOut[i3]);
+      h2r := 0.5 * (ImagOut[i] + ImagOut[i3]);
+      h2i := -0.5 * (RealOut[i] - RealOut[i3]);
+
+      rt := h1r + wr * h2r - wi * h2i;
+      it := h1i + wr * h2i + wi * h2r;
+
+      Out_[i] := rt * rt + it * it;
+
+      rt := h1r - wr * h2r + wi * h2i;
+      it := -h1i + wr * h2i + wi * h2r;
+
+      Out_[i3] := rt * rt + it * it;
+
+      wtemp := wr;
+      wr := wtemp * wpr - wi * wpi + wr;
+      wi := wi * wpr + wtemp * wpi + wi;
+   end;
+
+   h1r := RealOut[0];
+   rt := h1r + ImagOut[0];
+   it := h1r - ImagOut[0];
+   Out_[0] := rt * rt + it * it;
+
+   rt := RealOut[Half div 2];
+   it := ImagOut[Half div 2];
+   Out_[Half div 2] := rt * rt + it * it;
+
+   FreeMem(tmpReal);
+   FreeMem(tmpImag);
+   FreeMem(RealOut);
+   FreeMem(ImagOut);
+end;
+
+(*
+ * Windowing Functions
+ *)
+function NumWindowFuncs(): integer;
+begin
+  Result := Length(FFTWindowName);
+end;
+
+function WindowFuncName(whichFunction: TFFTWindowFunc): string;
+begin
+  Result := FFTWindowName[whichFunction];
+end;
+
+procedure WindowFunc(whichFunction: TFFTWindowFunc; NumSamples: Integer; in_: PSingleArray);
+var
+  i: Integer;
+  A: Single;
+begin
+  case whichFunction of
+    fwfBartlett:
+    begin
+      // Bartlett (triangular) window
+      for i := 0 to (NumSamples div 2)-1 do
+      begin
+        in_[i] := in_[i] * (i / (NumSamples / 2));
+        in_[i + (NumSamples div 2)] :=
+            in_[i + (NumSamples div 2)] *
+            (1.0 - (i / (NumSamples / 2)));
+      end;
+    end;
+    fwfHamming:
+    begin
+      // Hamming
+      for i := 0 to NumSamples-1 do
+      begin
+        in_[i] := in_[i] * (0.54 - 0.46 * cos(2 * Pi * i / (NumSamples - 1)));
+      end;
+    end;
+    fwfHanning:
+    begin
+      // Hanning
+      for i := 0 to NumSamples-1 do
+      begin
+        in_[i] := in_[i] * (0.50 - 0.50 * cos(2 * Pi * i / (NumSamples - 1)));
+      end;
+    end;
+    fwfBlackman:
+    begin
+      // Blackman
+      for i := 0 to NumSamples-1 do
+      begin
+        in_[i] := in_[i] * (0.42 - 0.5 * cos (2 * Pi * i / (NumSamples - 1)) + 0.08 * cos (4 * Pi * i / (NumSamples - 1)));
+      end;
+    end;
+    fwfBlackman_Harris:
+    begin
+      // Blackman-Harris
+      for i := 0 to NumSamples-1 do
+      begin
+        in_[i] := in_[i] * (0.35875 - 0.48829 * cos(2 * Pi * i /(NumSamples-1)) + 0.14128 * cos(4 * Pi * i/(NumSamples-1)) - 0.01168 * cos(6 * Pi * i/(NumSamples-1)));
+      end;
+    end;
+    fwfWelch:
+    begin
+      // Welch
+      for i := 0 to NumSamples-1 do
+      begin
+        in_[i] := in_[i] * 4*i/NumSamples*(1-(i/NumSamples));
+      end;
+    end;
+    fwfGaussian2_5:
+    begin
+      // Gaussian (a=2.5)
+      // Precalculate some values, and simplify the fmla to try and reduce overhead
+      A := -2*2.5*2.5;
+
+      for i := 0 to NumSamples-1 do
+      begin
+        // full
+        // in_[i] := in_[i] * exp(-0.5*(A*((i-NumSamples/2)/NumSamples/2))*(A*((i-NumSamples/2)/NumSamples/2)));
+        // reduced
+        //in_[i] := in_[i] * exp(A*(0.25 + ((i/NumSamples)*(i/NumSamples)) - (i/NumSamples)));
+      end;
+    end;
+    fwfGaussian3_5:
+    begin
+      // Gaussian (a=3.5)
+      A := -2*3.5*3.5;
+
+      for i := 0 to NumSamples-1 do
+      begin
+        // reduced
+        in_[i] := in_[i] * exp(A*(0.25 + ((i/NumSamples)*(i/NumSamples)) - (i/NumSamples)));
+      end;
+    end;
+    fwfGaussian4_5:
+    begin
+      // Gaussian (a=4.5)
+      A := -2*4.5*4.5;
+
+      for i := 0 to NumSamples-1 do
+      begin
+        // reduced
+        in_[i] := in_[i] * exp(A*(0.25 + ((i/NumSamples)*(i/NumSamples)) - (i/NumSamples)));
+      end;
+    end;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/lib/freetype/demo/engine-test.bdsproj b/songmanagement/src/lib/freetype/demo/engine-test.bdsproj
new file mode 100644
index 00000000..e5b3e97d
--- /dev/null
+++ b/songmanagement/src/lib/freetype/demo/engine-test.bdsproj
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="utf-8"?>
+<BorlandProject>
+	<PersonalityInfo>
+		<Option>
+			<Option Name="Personality">Delphi.Personality</Option>
+			<Option Name="ProjectType">VCLApplication</Option>
+			<Option Name="Version">1.0</Option>
+			<Option Name="GUID">{41656F26-D552-4948-B9DB-E184B77C3993}</Option>
+		</Option>
+	</PersonalityInfo>
+	<Delphi.Personality>
+		<Source>
+			<Source Name="MainSource">engine-test.dpr</Source>
+		</Source>
+		<FileVersion>
+			<FileVersion Name="Version">7.0</FileVersion>
+		</FileVersion>
+		<Compiler>
+			<Compiler Name="A">8</Compiler>
+			<Compiler Name="B">0</Compiler>
+			<Compiler Name="C">1</Compiler>
+			<Compiler Name="D">1</Compiler>
+			<Compiler Name="E">0</Compiler>
+			<Compiler Name="F">0</Compiler>
+			<Compiler Name="G">1</Compiler>
+			<Compiler Name="H">1</Compiler>
+			<Compiler Name="I">1</Compiler>
+			<Compiler Name="J">0</Compiler>
+			<Compiler Name="K">0</Compiler>
+			<Compiler Name="L">1</Compiler>
+			<Compiler Name="M">0</Compiler>
+			<Compiler Name="N">1</Compiler>
+			<Compiler Name="O">1</Compiler>
+			<Compiler Name="P">1</Compiler>
+			<Compiler Name="Q">0</Compiler>
+			<Compiler Name="R">0</Compiler>
+			<Compiler Name="S">0</Compiler>
+			<Compiler Name="T">0</Compiler>
+			<Compiler Name="U">0</Compiler>
+			<Compiler Name="V">1</Compiler>
+			<Compiler Name="W">0</Compiler>
+			<Compiler Name="X">1</Compiler>
+			<Compiler Name="Y">1</Compiler>
+			<Compiler Name="Z">1</Compiler>
+			<Compiler Name="ShowHints">True</Compiler>
+			<Compiler Name="ShowWarnings">True</Compiler>
+			<Compiler Name="UnitAliases">WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;</Compiler>
+			<Compiler Name="NamespacePrefix"></Compiler>
+			<Compiler Name="GenerateDocumentation">False</Compiler>
+			<Compiler Name="DefaultNamespace"></Compiler>
+			<Compiler Name="SymbolDeprecated">True</Compiler>
+			<Compiler Name="SymbolLibrary">True</Compiler>
+			<Compiler Name="SymbolPlatform">True</Compiler>
+			<Compiler Name="SymbolExperimental">True</Compiler>
+			<Compiler Name="UnitLibrary">True</Compiler>
+			<Compiler Name="UnitPlatform">True</Compiler>
+			<Compiler Name="UnitDeprecated">True</Compiler>
+			<Compiler Name="UnitExperimental">True</Compiler>
+			<Compiler Name="HResultCompat">True</Compiler>
+			<Compiler Name="HidingMember">True</Compiler>
+			<Compiler Name="HiddenVirtual">True</Compiler>
+			<Compiler Name="Garbage">True</Compiler>
+			<Compiler Name="BoundsError">True</Compiler>
+			<Compiler Name="ZeroNilCompat">True</Compiler>
+			<Compiler Name="StringConstTruncated">True</Compiler>
+			<Compiler Name="ForLoopVarVarPar">True</Compiler>
+			<Compiler Name="TypedConstVarPar">True</Compiler>
+			<Compiler Name="AsgToTypedConst">True</Compiler>
+			<Compiler Name="CaseLabelRange">True</Compiler>
+			<Compiler Name="ForVariable">True</Compiler>
+			<Compiler Name="ConstructingAbstract">True</Compiler>
+			<Compiler Name="ComparisonFalse">True</Compiler>
+			<Compiler Name="ComparisonTrue">True</Compiler>
+			<Compiler Name="ComparingSignedUnsigned">True</Compiler>
+			<Compiler Name="CombiningSignedUnsigned">True</Compiler>
+			<Compiler Name="UnsupportedConstruct">True</Compiler>
+			<Compiler Name="FileOpen">True</Compiler>
+			<Compiler Name="FileOpenUnitSrc">True</Compiler>
+			<Compiler Name="BadGlobalSymbol">True</Compiler>
+			<Compiler Name="DuplicateConstructorDestructor">True</Compiler>
+			<Compiler Name="InvalidDirective">True</Compiler>
+			<Compiler Name="PackageNoLink">True</Compiler>
+			<Compiler Name="PackageThreadVar">True</Compiler>
+			<Compiler Name="ImplicitImport">True</Compiler>
+			<Compiler Name="HPPEMITIgnored">True</Compiler>
+			<Compiler Name="NoRetVal">True</Compiler>
+			<Compiler Name="UseBeforeDef">True</Compiler>
+			<Compiler Name="ForLoopVarUndef">True</Compiler>
+			<Compiler Name="UnitNameMismatch">True</Compiler>
+			<Compiler Name="NoCFGFileFound">True</Compiler>
+			<Compiler Name="ImplicitVariants">True</Compiler>
+			<Compiler Name="UnicodeToLocale">True</Compiler>
+			<Compiler Name="LocaleToUnicode">True</Compiler>
+			<Compiler Name="ImagebaseMultiple">True</Compiler>
+			<Compiler Name="SuspiciousTypecast">True</Compiler>
+			<Compiler Name="PrivatePropAccessor">True</Compiler>
+			<Compiler Name="UnsafeType">False</Compiler>
+			<Compiler Name="UnsafeCode">False</Compiler>
+			<Compiler Name="UnsafeCast">False</Compiler>
+			<Compiler Name="OptionTruncated">True</Compiler>
+			<Compiler Name="WideCharReduced">True</Compiler>
+			<Compiler Name="DuplicatesIgnored">True</Compiler>
+			<Compiler Name="UnitInitSeq">True</Compiler>
+			<Compiler Name="LocalPInvoke">True</Compiler>
+			<Compiler Name="MessageDirective">True</Compiler>
+			<Compiler Name="CodePage"></Compiler>
+		</Compiler>
+		<Linker>
+			<Linker Name="MapFile">0</Linker>
+			<Linker Name="OutputObjs">0</Linker>
+			<Linker Name="GenerateHpps">False</Linker>
+			<Linker Name="ConsoleApp">1</Linker>
+			<Linker Name="DebugInfo">False</Linker>
+			<Linker Name="RemoteSymbols">False</Linker>
+			<Linker Name="GenerateDRC">False</Linker>
+			<Linker Name="MinStackSize">16384</Linker>
+			<Linker Name="MaxStackSize">1048576</Linker>
+			<Linker Name="ImageBase">4194304</Linker>
+			<Linker Name="ExeDescription"></Linker>
+		</Linker>
+		<Directories>
+			<Directories Name="OutputDir"></Directories>
+			<Directories Name="UnitOutputDir"></Directories>
+			<Directories Name="PackageDLLOutputDir"></Directories>
+			<Directories Name="PackageDCPOutputDir"></Directories>
+			<Directories Name="SearchPath">..\..\JEDI-SDL\SDL\Pas</Directories>
+			<Directories Name="Packages">vclx;vcl;rtl;vclactnband</Directories>
+			<Directories Name="Conditionals"></Directories>
+			<Directories Name="DebugSourceDirs"></Directories>
+			<Directories Name="UsePackages">False</Directories>
+		</Directories>
+		<Parameters>
+			<Parameters Name="RunParams"></Parameters>
+			<Parameters Name="HostApplication"></Parameters>
+			<Parameters Name="Launcher"></Parameters>
+			<Parameters Name="UseLauncher">False</Parameters>
+			<Parameters Name="DebugCWD"></Parameters>
+			<Parameters Name="Debug Symbols Search Path"></Parameters>
+			<Parameters Name="LoadAllSymbols">True</Parameters>
+			<Parameters Name="LoadUnspecifiedSymbols">False</Parameters>
+		</Parameters>
+		<Language>
+			<Language Name="ActiveLang"></Language>
+			<Language Name="ProjectLang">$00000000</Language>
+			<Language Name="RootDir"></Language>
+		</Language>
+		<VersionInfo>
+			<VersionInfo Name="IncludeVerInfo">False</VersionInfo>
+			<VersionInfo Name="AutoIncBuild">False</VersionInfo>
+			<VersionInfo Name="MajorVer">1</VersionInfo>
+			<VersionInfo Name="MinorVer">0</VersionInfo>
+			<VersionInfo Name="Release">0</VersionInfo>
+			<VersionInfo Name="Build">0</VersionInfo>
+			<VersionInfo Name="Debug">False</VersionInfo>
+			<VersionInfo Name="PreRelease">False</VersionInfo>
+			<VersionInfo Name="Special">False</VersionInfo>
+			<VersionInfo Name="Private">False</VersionInfo>
+			<VersionInfo Name="DLL">False</VersionInfo>
+			<VersionInfo Name="Locale">1031</VersionInfo>
+			<VersionInfo Name="CodePage">1252</VersionInfo>
+		</VersionInfo>
+		<VersionInfoKeys>
+			<VersionInfoKeys Name="CompanyName"></VersionInfoKeys>
+			<VersionInfoKeys Name="FileDescription"></VersionInfoKeys>
+			<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
+			<VersionInfoKeys Name="InternalName"></VersionInfoKeys>
+			<VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys>
+			<VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys>
+			<VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys>
+			<VersionInfoKeys Name="ProductName"></VersionInfoKeys>
+			<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
+			<VersionInfoKeys Name="Comments"></VersionInfoKeys>
+		</VersionInfoKeys>
+	</Delphi.Personality>
+</BorlandProject>
diff --git a/songmanagement/src/lib/freetype/demo/engine-test.dpr b/songmanagement/src/lib/freetype/demo/engine-test.dpr
new file mode 100644
index 00000000..bbd7d890
--- /dev/null
+++ b/songmanagement/src/lib/freetype/demo/engine-test.dpr
@@ -0,0 +1,338 @@
+program engine_test;
+(*
+ * This code was created by Jeff Molofee '99
+ * (ported to Linux/SDL by Ti Leggett '01)
+ *
+ * If you've found this code useful, please let me know.
+ *
+ * Visit Jeff at http://nehe.gamedev.net/
+ *
+ * or for port-specific comments, questions, bugreports etc.
+ * email to leggett@eecs.tulane.edu
+ *)
+
+{$IFDEF FPC}
+  {$mode delphi}{$H+}
+{$ENDIF}
+
+{$APPTYPE Console}
+
+uses
+  moduleloader in '../../JEDI-SDL/SDL/Pas/moduleloader.pas',
+  SDL          in '../../JEDI-SDL/SDL/Pas/sdl.pas',
+  gl           in '../../JEDI-SDL/OpenGL/Pas/gl.pas',
+  glext        in '../../JEDI-SDL/OpenGL/Pas/glext.pas',
+  glu          in '../../JEDI-SDL/OpenGL/Pas/glu.pas',
+  {$IFNDEF FPC}
+  ctypes       in '../../ctypes/ctypes.pas',
+  {$ENDIF}
+  FreeType     in '../freetype.pas',
+  UFont        in 'UFont.pas',
+  //UFont        in '../../../base/UFont.pas',
+  UUnicodeUtils in '../../../base/UUnicodeUtils.pas',
+  math,
+  sysutils;
+
+const
+  // screen width, height, and bit depth
+  SCREEN_WIDTH  = 640;
+  SCREEN_HEIGHT = 480;
+  SCREEN_BPP    =  16;
+
+  //FONT_FILE = 'Test.ttf';
+  //FONT_FILE = 'C:/Windows/Fonts/Arial.ttf';
+  //FONT_FILE = 'C:/Windows/Fonts/SimSun.ttf';
+  //FONT_FILE = 'eurostarregularextended.ttf';
+  FONT_FILE = '../../../../game/fonts/FreeSans/FreeSans.ttf';
+  
+var
+  OurFont: TScalableFont;
+  // This is our SDL surface
+  surface: PSDL_Surface;
+  cnt1, cnt2: GLfloat;
+
+(* function to release/destroy our resources and restoring the old desktop *)
+procedure Quit(returnCode: integer);
+begin
+  OurFont.Free;
+
+  // clean up the window
+  SDL_Quit( );
+
+  // and exit appropriately
+  Halt( returnCode );
+end;
+
+(* function to reset our viewport after a window resize *)
+function resizeWindow(width: integer; height: integer): boolean;
+begin
+  // Protect against a divide by zero
+  if ( height = 0 ) then
+    height := 1;
+
+  // Setup our viewport.
+  glViewport( 0, 0, GLsizei(width), GLsizei(height) );
+
+  // change to the projection matrix and set our viewing volume.
+  glMatrixMode( GL_PROJECTION );
+  glLoadIdentity( );
+
+  // Set our perspective
+  //gluOrtho2D(0, width, 0, height);
+  gluOrtho2D(0, 800, 0, 600);
+
+  // Make sure we're chaning the model view and not the projection
+  glMatrixMode( GL_MODELVIEW );
+
+  // Reset The View
+  glLoadIdentity( );
+
+  Result := true;
+end;
+
+(* function to handle key press events *)
+procedure handleKeyPress(keysym: PSDL_keysym);
+begin
+  case ( keysym^.sym ) of
+    SDLK_ESCAPE:
+    begin
+      // ESC key was pressed
+      Quit( 0 );
+    end;
+    SDLK_F1:
+    begin
+      // F1 key was pressed
+      // this toggles fullscreen mode
+      SDL_WM_ToggleFullScreen( surface );
+    end;
+  end;
+end;
+
+(* general OpenGL initialization function *)
+function initGL(): boolean;
+begin
+  // Enable smooth shading
+  glShadeModel( GL_SMOOTH );
+
+  // Set the background black
+  //glClearColor( 1, 1, 1.0, 1.0 );
+  //glClearColor( 0.3, 0.7, 1.0, 1.0 );
+  glClearColor( 0.0, 0.0, 0.0, 1.0 );
+
+  // Depth buffer setup
+  glClearDepth( 1.0 );
+
+  // Enables Depth Testing
+  glEnable( GL_DEPTH_TEST );
+
+  // The Type Of Depth Test To Do
+  glDepthFunc( GL_LEQUAL );
+
+  // Really Nice Perspective Calculations
+  glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
+
+  OurFont := TFTScalableFont.Create(FONT_FILE, 64, 0.03);
+  //OurFont := TFTFont.Create(FONT_FILE, 128);
+  //OurFont := TFTScalableOutlineFont.Create(FONT_FILE, 64, 0.03);
+  //OurFont.UseKerning := false;
+  //TFTScalableOutlineFont(OurFont).SetOutlineColor(1, 0, 0, 1);
+  //OurFont := TOutlineFont.Create(FONT_FILE, 32, 2);
+  //OurFont.LineSpacing := OurFont.LineSpacing * 0.5;
+
+  Result := true;
+end;
+
+var
+  NextTime: cardinal;
+  Counter: integer;
+
+type
+  TVector4d = array[0..3] of GLdouble;
+
+function NewVector4d(a, b, c, d: GLdouble): TVector4d;
+begin
+  Result[0] := a;
+  Result[1] := b;
+  Result[2] := c;
+  Result[3] := d;
+end;
+
+(* Here goes our drawing code *)
+function drawGLScene(): boolean;
+var
+  msg: WideString;
+  bounds: TBoundsDbl;
+begin
+  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);  // Clear Screen And Depth Buffer
+
+  //msg := 'Here'#13'there'#13'be'#13#13'newlines'#13'.';
+  //msg := 'Here'#13'newlines';
+  msg := 'Active FreeType Text - ' + FloatToStr(cnt1);
+  //msg := 'Hören'#13'其自诞生至今'#13'спецификация';
+
+  // Red text
+  glLoadIdentity();
+  glTranslatef(cnt2, 240, 0);
+  if (cnt2 > 800) then
+    cnt2 := 0;
+  glTranslatef(30, 40, 0);
+  //glTranslatef(320, 240, 0);
+  //glRotatef(cnt1, 0, 0, 1);
+  //glScalef(1, 0.8 + 0.3*cos(cnt1/5), 1);
+
+  OurFont.Style := [Italic, {Underline,} Reflect];
+  //OurFont.GlyphSpacing := 10;
+  //OurFont.SetOutlineColor(0.5, 0.5, 0.5);
+  //OurFont.ReflectionSpacing := -4;
+  //OurFont.UseKerning := false;
+  OurFont.Height := 150;//cnt2;
+  //OurFont.Reset;
+  //OurFont.Aspect := 2;
+
+  glColor3f(1, 1, 0);
+  bounds := OurFont.BBox(msg);
+  //glRectf(bounds.Left, OurFont.Ascender, bounds.Right, OurFont.Ascender-OurFont.Height);
+
+  glColor4f(1, 1, 1, 1);
+  //OurFont.ReflectionSpacing := 0;
+  OurFont.Print(msg);
+
+  cnt1 := cnt1 + 0.051;  // Increase The First Counter
+  cnt2 := cnt2 + 0.005;  // Increase The First Counter
+
+  SDL_GL_SwapBuffers( );
+
+  Inc(Counter);
+
+  if (NextTime < SDL_GetTicks()) then
+  begin
+    NextTime := SDL_GetTicks() + 2000;
+    writeln('FPS: ' + floattostr(Counter / 2.0));
+    Counter := 0;
+  end;
+
+  Result := true;
+end;
+
+var
+  // Flags to pass to SDL_SetVideoMode
+  videoFlags: integer;
+  // main loop variable
+  done: boolean = false;
+  // used to collect events
+  event: TSDL_Event;
+  // this holds some info about our display
+  videoInfo: PSDL_VideoInfo;
+  // whether or not the window is active
+  isActive: boolean = true;
+
+begin
+  // initialize SDL
+  if ( SDL_Init( SDL_INIT_VIDEO or SDL_INIT_TIMER ) < 0 ) then
+  begin
+    writeln( ErrOutput, 'Video initialization failed: ' + SDL_GetError() );
+    Quit( 1 );
+  end;
+
+  // Fetch the video info
+  videoInfo := SDL_GetVideoInfo( );
+
+  if ( videoInfo = nil ) then
+  begin
+    writeln( ErrOutput, 'Video query failed: ' + SDL_GetError() );
+    Quit( 1 );
+  end;
+
+  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // Enable double buffering
+
+  // the flags to pass to SDL_SetVideoMode
+  videoFlags := SDL_OPENGL;                        // Enable OpenGL in SDL
+  videoFlags := videoFlags or SDL_HWPALETTE;       // Store the palette in hardware
+  videoFlags := videoFlags or SDL_RESIZABLE;       // Enable window resizing
+
+  // This checks to see if surfaces can be stored in memory
+  if ( videoInfo^.hw_available <> 0 ) then
+    videoFlags := videoFlags or SDL_HWSURFACE
+  else
+    videoFlags := videoFlags or SDL_SWSURFACE;
+
+  // This checks if hardware blits can be done
+  if ( videoInfo^.blit_hw <> 0 ) then
+    videoFlags := videoFlags or SDL_HWACCEL;
+
+  // Sets up OpenGL double buffering
+  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+
+  // get a SDL surface
+  surface := SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,
+                               videoFlags );
+
+  // Verify there is a surface
+  if ( surface = nil ) then
+  begin
+    writeln( ErrOutput, 'Video mode set failed: ' + SDL_GetError() );
+    Quit( 1 );
+  end;
+
+  // initialize OpenGL
+  initGL();
+
+  // resize the initial window
+  resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );
+
+  // wait for events
+  while ( not done ) do
+  begin
+    { handle the events in the queue }
+
+    while ( SDL_PollEvent( @event ) <> 0 ) do
+    begin
+      case( event.type_ ) of
+        SDL_ACTIVEEVENT:
+        begin
+          // Something's happend with our focus
+          // If we are iconified, we shouldn't draw the screen
+          if ( (event.active.state and SDL_APPACTIVE) <> 0 ) then
+          begin
+            if (  event.active.gain = 0 ) then
+              isActive := false
+            else
+              isActive := true;
+          end;
+        end;
+        SDL_VIDEORESIZE:
+        begin
+          // handle resize event
+          {$IFDEF UNIX}
+          surface := SDL_SetVideoMode( event.resize.w,
+              event.resize.h,
+              16, videoFlags );
+          if ( surface = nil ) then
+          begin
+            writeln( ErrOutput, 'Could not get a surface after resize: ' + SDL_GetError( ) );
+            Quit( 1 );
+          end;
+          {$ENDIF}
+          resizeWindow( event.resize.w, event.resize.h );
+        end;
+        SDL_KEYDOWN:
+        begin
+          // handle key presses
+          handleKeyPress( @event.key.keysym );
+        end;
+        SDL_QUITEV:
+        begin
+          // handle quit requests
+          done := true;
+        end;
+      end;
+    end;
+
+    // draw the scene
+    if ( isActive ) then
+      drawGLScene( );
+  end;
+
+  // clean ourselves up and exit
+  Quit( 0 );
+end.
diff --git a/songmanagement/src/lib/freetype/demo/engine-test.lpi b/songmanagement/src/lib/freetype/demo/engine-test.lpi
new file mode 100644
index 00000000..45483a56
--- /dev/null
+++ b/songmanagement/src/lib/freetype/demo/engine-test.lpi
@@ -0,0 +1,182 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="\"/>
+    <Version Value="6"/>
+    <General>
+      <MainUnit Value="0"/>
+      <IconPath Value=".\"/>
+      <TargetFileExt Value=""/>
+      <ActiveEditorIndexAtStart Value="0"/>
+    </General>
+    <VersionInfo>
+      <ProjectVersion Value=""/>
+      <Language Value=""/>
+      <CharSet Value=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <DestinationDirectory Value="$(TestDir)\publishedproject\"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <Units Count="16">
+      <Unit0>
+        <Filename Value="engine-test.dpr"/>
+        <IsPartOfProject Value="True"/>
+        <CursorPos X="18" Y="25"/>
+        <TopLine Value="1"/>
+        <EditorIndex Value="0"/>
+        <UsageCount Value="72"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="JEDI-SDL\OpenGL\Pas\opengl12.pas"/>
+        <UnitName Value="opengl12"/>
+        <CursorPos X="20" Y="9922"/>
+        <TopLine Value="9889"/>
+        <UsageCount Value="5"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="JEDI-SDL\SDL\Pas\sdl.pas"/>
+        <UnitName Value="sdl"/>
+        <CursorPos X="29" Y="3569"/>
+        <TopLine Value="3547"/>
+        <UsageCount Value="5"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="FreeType.pas"/>
+        <UnitName Value="FreeType"/>
+        <CursorPos X="6" Y="1"/>
+        <TopLine Value="1"/>
+        <UsageCount Value="5"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="UFreeType.pas"/>
+        <UnitName Value="UFreeType"/>
+        <CursorPos X="47" Y="111"/>
+        <TopLine Value="76"/>
+        <UsageCount Value="35"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="freetype"/>
+        <CursorPos X="1" Y="1"/>
+        <TopLine Value="1"/>
+        <UsageCount Value="8"/>
+        <SyntaxHighlighter Value="None"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="freetype\freetype.pas"/>
+        <UnitName Value="freetype"/>
+        <CursorPos X="31" Y="807"/>
+        <TopLine Value="14"/>
+        <UsageCount Value="15"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="..\..\daten\Projekte\UltraStarDX\trunk\Game\Code\lib\ffmpeg\avcodec.pas"/>
+        <UnitName Value="avcodec"/>
+        <CursorPos X="1" Y="38"/>
+        <TopLine Value="1"/>
+        <UsageCount Value="6"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="..\..\JEDI-SDL\OpenGL\Pas\gl.pas"/>
+        <UnitName Value="gl"/>
+        <CursorPos X="2" Y="89"/>
+        <TopLine Value="69"/>
+        <UsageCount Value="9"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="..\..\ctypes\ctypes.pas"/>
+        <UnitName Value="ctypes"/>
+        <CursorPos X="8" Y="25"/>
+        <TopLine Value="51"/>
+        <UsageCount Value="9"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="..\..\JEDI-SDL\OpenGL\Pas\glu.pas"/>
+        <UnitName Value="glu"/>
+        <CursorPos X="14" Y="155"/>
+        <TopLine Value="135"/>
+        <UsageCount Value="9"/>
+      </Unit10>
+      <Unit11>
+        <Filename Value="..\..\JEDI-SDL\SDL\Pas\sdl.pas"/>
+        <UnitName Value="sdl"/>
+        <CursorPos X="12" Y="1418"/>
+        <TopLine Value="1398"/>
+        <UsageCount Value="9"/>
+      </Unit11>
+      <Unit12>
+        <Filename Value="..\freetype.pas"/>
+        <UnitName Value="freetype"/>
+        <CursorPos X="3" Y="1985"/>
+        <TopLine Value="1965"/>
+        <UsageCount Value="10"/>
+      </Unit12>
+      <Unit13>
+        <Filename Value="C:\Programme\lazarus\fpc\2.2.0\source\rtl\objpas\classes\classesh.inc"/>
+        <CursorPos X="13" Y="26"/>
+        <TopLine Value="6"/>
+        <UsageCount Value="13"/>
+      </Unit13>
+      <Unit14>
+        <Filename Value="C:\Programme\lazarus\fpc\2.2.0\source\rtl\objpas\types.pp"/>
+        <UnitName Value="types"/>
+        <CursorPos X="7" Y="105"/>
+        <TopLine Value="73"/>
+        <UsageCount Value="12"/>
+      </Unit14>
+      <Unit15>
+        <Filename Value="UFont.pas"/>
+        <UnitName Value="UFont"/>
+        <CursorPos X="15" Y="1752"/>
+        <TopLine Value="1734"/>
+        <UsageCount Value="10"/>
+      </Unit15>
+    </Units>
+    <JumpHistory Count="2" HistoryIndex="1">
+      <Position1>
+        <Filename Value="engine-test.dpr"/>
+        <Caret Line="52" Column="10" TopLine="37"/>
+      </Position1>
+      <Position2>
+        <Filename Value="engine-test.dpr"/>
+        <Caret Line="1" Column="1" TopLine="1"/>
+      </Position2>
+    </JumpHistory>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="8"/>
+    <PathDelim Value="\"/>
+    <SearchPaths>
+      <IncludeFiles Value="..\..\JEDI-SDL\SDL\Pas\"/>
+    </SearchPaths>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <BreakPoints Count="1">
+      <Item1>
+        <Source Value="lesson43.dpr"/>
+        <Line Value="138"/>
+      </Item1>
+    </BreakPoints>
+    <Exceptions Count="2">
+      <Item1>
+        <Name Value="ECodetoolError"/>
+      </Item1>
+      <Item2>
+        <Name Value="EFOpenError"/>
+      </Item2>
+    </Exceptions>
+  </Debugging>
+</CONFIG>
diff --git a/songmanagement/src/lib/freetype/demo/nehe/UFreeType.pas b/songmanagement/src/lib/freetype/demo/nehe/UFreeType.pas
new file mode 100644
index 00000000..c1243aae
--- /dev/null
+++ b/songmanagement/src/lib/freetype/demo/nehe/UFreeType.pas
@@ -0,0 +1,326 @@
+unit UFreeType;
+
+{$IFDEF FPC}
+  {$mode delphi}{$H+}
+{$ENDIF}
+
+interface
+
+uses
+  FreeType,
+  gl,
+  glu,
+  classes,
+  sysutils;
+
+type
+  // This holds all of the information related to any
+  // freetype font that we want to create.
+  TFontData = class
+    h: single;                  ///< Holds the height of the font.
+    textures: array of GLuint;  ///< Holds the texture id's
+    list_base: GLuint;          ///< Holds the first display list id
+
+    // The init function will create a font of
+    // of the height h from the file fname.
+    constructor Create(const fname: string; h: cardinal);
+
+    // Free all the resources assosiated with the font.
+    destructor Destroy(); override;
+  end;
+
+  TFreeType = class
+    public
+      // The flagship function of the library - this thing will print
+      // out text at window coordinates x,y, using the font ft_font.
+      // The current modelview matrix will also be applied to the text.
+      class procedure print(ft_font: TFontData; x, y: single; const str: string);
+  end;
+
+
+implementation
+
+
+// This function gets the first power of 2 >= the
+// int that we pass it.
+function next_p2 ( a: integer ): integer; inline;
+begin
+  Result := 1;
+  while (Result < a) do
+    Result := Result shl 1;
+end;
+
+type
+  PAGLuint = ^AGLuint;
+  AGLuint = array[0..High(Word)] of GLuint;
+
+// Create a display list coresponding to the given character.
+procedure make_dlist ( face: FT_Face; ch: byte; list_base: GLuint; tex_base: PAGLuint );
+var
+  i, j: integer;
+  width, height: integer;
+  glyph: FT_Glyph;
+  bitmap_glyph: FT_BitmapGlyph;
+  bitmap: PFT_Bitmap;
+  expanded_data: array of GLubyte;
+  x, y: single;
+begin
+  // The first thing we do is get FreeType to render our character
+  // into a bitmap.  This actually requires a couple of FreeType commands:
+
+  // Load the Glyph for our character.
+  if (FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT ) <> 0) then
+    raise Exception.create('FT_Load_Glyph failed');
+
+  // Move the face's glyph into a Glyph object.
+  if (FT_Get_Glyph( face^.glyph, glyph ) <> 0) then
+    raise Exception.create('FT_Get_Glyph failed');
+
+  // Convert the glyph to a bitmap.
+  FT_Glyph_To_Bitmap( glyph, ft_render_mode_normal, nil, 1 );
+  bitmap_glyph := FT_BitmapGlyph(glyph);
+
+  // This reference will make accessing the bitmap easier
+  bitmap := @bitmap_glyph^.bitmap;
+
+  // Use our helper function to get the widths of
+  // the bitmap data that we will need in order to create
+  // our texture.
+  width := next_p2( bitmap.width );
+  height := next_p2( bitmap.rows );
+
+  // Allocate memory for the texture data.
+  SetLength(expanded_data, 2 * width * height);
+
+  // Here we fill in the data for the expanded bitmap.
+  // Notice that we are using two channel bitmap (one for
+  // luminocity and one for alpha), but we assign
+  // both luminocity and alpha to the value that we
+  // find in the FreeType bitmap.
+  // We use the ?: operator so that value which we use
+  // will be 0 if we are in the padding zone, and whatever
+  // is the the Freetype bitmap otherwise.
+  for j := 0 to height-1 do
+  begin
+    for i := 0 to width-1 do
+    begin
+      if ((i >= bitmap.width) or (j >= bitmap.rows)) then
+        expanded_data[2*(i+j*width)] := 0
+      else
+        expanded_data[2*(i+j*width)] := byte(bitmap.buffer[i + bitmap.width*j]);
+      expanded_data[2*(i+j*width)+1] := expanded_data[2*(i+j*width)];
+    end;
+  end;
+
+
+  // Now we just setup some texture paramaters.
+  glBindTexture( GL_TEXTURE_2D, tex_base[integer(ch)]);
+  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+  // Here we actually create the texture itself, notice
+  // that we are using GL_LUMINANCE_ALPHA to indicate that
+  // we are using 2 channel data.
+  glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height,
+      0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, @expanded_data[0] );
+
+  //With the texture created, we don't need to expanded data anymore
+  SetLength(expanded_data, 0);
+
+  //So now we can create the display list
+  glNewList(list_base+ch, GL_COMPILE);
+
+  glBindTexture(GL_TEXTURE_2D, tex_base[ch]);
+
+  glPushMatrix();
+
+  //first we need to move over a little so that
+  //the character has the right amount of space
+  //between it and the one before it.
+  glTranslatef(bitmap_glyph^.left, 0, 0);
+
+  //Now we move down a little in the case that the
+  //bitmap extends past the bottom of the line
+  //(this is only true for characters like 'g' or 'y'.
+  glTranslatef(0, bitmap_glyph^.top - bitmap.rows, 0);
+
+  //Now we need to account for the fact that many of
+  //our textures are filled with empty padding space.
+  //We figure what portion of the texture is used by 
+  //the actual character and store that information in
+  //the x and y variables, then when we draw the
+  //quad, we will only reference the parts of the texture
+  //that we contain the character itself.
+  x := bitmap.width / width;
+  y := bitmap.rows  / height;
+
+  //Here we draw the texturemaped quads.
+  //The bitmap that we got from FreeType was not
+  //oriented quite like we would like it to be,
+  //so we need to link the texture to the quad
+  //so that the result will be properly aligned.
+  glBegin(GL_QUADS);
+    glTexCoord2d(0, 0); glVertex2f(0, bitmap.rows);
+    glTexCoord2d(0, y); glVertex2f(0, 0);
+    glTexCoord2d(x, y); glVertex2f(bitmap.width, 0);
+    glTexCoord2d(x, 0); glVertex2f(bitmap.width, bitmap.rows);
+  glEnd();
+
+  glPopMatrix();
+  glTranslatef(face^.glyph^.advance.x shr 6, 0, 0);
+
+  //increment the raster position as if we were a bitmap font.
+  //(only needed if you want to calculate text length)
+  //glBitmap(0,0,0,0,face->glyph->advance.x >> 6,0,NULL);
+
+  //Finnish the display list
+  glEndList();
+end;
+
+
+constructor TFontData.Create(const fname: string; h: cardinal);
+var
+  library_: FT_Library;
+  //The object in which Freetype holds information on a given
+  //font is called a "face".
+  face: FT_Face;
+  i: byte;
+begin
+  //Allocate some memory to store the texture ids.
+  SetLength(textures, 128);
+
+  Self.h := h;
+
+  //Create and initilize a freetype font library.
+  if (FT_Init_FreeType( library_ ) <> 0) then
+    raise Exception.create('FT_Init_FreeType failed');
+
+  //This is where we load in the font information from the file.
+  //Of all the places where the code might die, this is the most likely,
+  //as FT_New_Face will die if the font file does not exist or is somehow broken.
+  if (FT_New_Face( library_, PChar(fname), 0, face ) <> 0) then
+    raise Exception.create('FT_New_Face failed (there is probably a problem with your font file)');
+
+  //For some twisted reason, Freetype measures font size
+  //in terms of 1/64ths of pixels.  Thus, to make a font
+  //h pixels high, we need to request a size of h*64.
+  //(h shl 6 is just a prettier way of writting h*64)
+  FT_Set_Char_Size( face, h shl 6, h shl 6, 96, 96);
+
+  //Here we ask opengl to allocate resources for
+  //all the textures and displays lists which we
+  //are about to create.  
+  list_base := glGenLists(128);
+  glGenTextures( 128, @textures[0] );
+
+  //This is where we actually create each of the fonts display lists.
+  for i := 0 to 127 do
+    make_dlist(face, i, list_base, @textures[0]);
+
+  //We don't need the face information now that the display
+  //lists have been created, so we free the assosiated resources.
+  FT_Done_Face(face);
+
+  //Ditto for the library.
+  FT_Done_FreeType(library_);
+end;
+
+destructor TFontData.Destroy();
+begin
+  glDeleteLists(list_base, 128);
+  glDeleteTextures(128, @textures[0]);
+  SetLength(textures, 0);
+end;
+
+/// A fairly straight forward function that pushes
+/// a projection matrix that will make object world
+/// coordinates identical to window coordinates.
+procedure pushScreenCoordinateMatrix(); inline;
+var
+  viewport: array [0..3] of GLint;
+begin
+  glPushAttrib(GL_TRANSFORM_BIT);
+  glGetIntegerv(GL_VIEWPORT, @viewport);
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  gluOrtho2D(viewport[0], viewport[2], viewport[1], viewport[3]);
+  glPopAttrib();
+end;
+
+/// Pops the projection matrix without changing the current
+/// MatrixMode.
+procedure pop_projection_matrix(); inline;
+begin
+  glPushAttrib(GL_TRANSFORM_BIT);
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glPopAttrib();
+end;
+
+///Much like Nehe's glPrint function, but modified to work
+///with freetype fonts.
+class procedure TFreeType.print(ft_font: TFontData; x, y: single; const str: string);
+var
+  font: GLuint;
+  h: single;
+  i: cardinal;
+  lines: TStringList;
+  modelview_matrix: array[0..15] of single;
+begin
+  // We want a coordinate system where things coresponding to window pixels.
+  pushScreenCoordinateMatrix();
+
+  font := ft_font.list_base;
+  h := ft_font.h / 0.63;      //We make the height about 1.5* that of
+
+  lines := TStringList.Create();
+  ExtractStrings([#13], [], PChar(str), lines);
+
+  glPushAttrib(GL_LIST_BIT or GL_CURRENT_BIT  or GL_ENABLE_BIT or GL_TRANSFORM_BIT);
+  glMatrixMode(GL_MODELVIEW);
+  glDisable(GL_LIGHTING);
+  glEnable(GL_TEXTURE_2D);
+  glDisable(GL_DEPTH_TEST);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  glListBase(font);
+
+  glGetFloatv(GL_MODELVIEW_MATRIX, @modelview_matrix);
+
+  //This is where the text display actually happens.
+  //For each line of text we reset the modelview matrix
+  //so that the line's text will start in the correct position.
+  //Notice that we need to reset the matrix, rather than just translating
+  //down by h. This is because when each character is
+  //draw it modifies the current matrix so that the next character
+  //will be drawn immediatly after it.
+  for i := 0 to lines.Count-1 do
+  begin
+    glPushMatrix();
+    glLoadIdentity();
+    glTranslatef(x, y - h*i, 0);
+    glMultMatrixf(@modelview_matrix);
+
+    //  The commented out raster position stuff can be useful if you need to
+    //  know the length of the text that you are creating.
+    //  If you decide to use it make sure to also uncomment the glBitmap command
+    //  in make_dlist().
+    //glRasterPos2f(0,0);
+    glCallLists(Length(lines[i]), GL_UNSIGNED_BYTE, PChar(lines[i]));
+    //float rpos[4];
+    //glGetFloatv(GL_CURRENT_RASTER_POSITION ,rpos);
+    //float len=x-rpos[0];
+
+    glPopMatrix();
+  end;
+
+  glPopAttrib();
+
+  pop_projection_matrix();
+ 
+  lines.Free();
+end;
+
+end.
diff --git a/songmanagement/src/lib/freetype/demo/nehe/lesson43.bdsproj b/songmanagement/src/lib/freetype/demo/nehe/lesson43.bdsproj
new file mode 100644
index 00000000..9d3851c4
--- /dev/null
+++ b/songmanagement/src/lib/freetype/demo/nehe/lesson43.bdsproj
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="utf-8"?>
+<BorlandProject>
+  <PersonalityInfo>
+    <Option>
+      <Option Name="Personality">Delphi.Personality</Option>
+      <Option Name="ProjectType">VCLApplication</Option>
+      <Option Name="Version">1.0</Option>
+      <Option Name="GUID">{3306FA70-362B-4647-A969-BCEA731F436C}</Option>
+    </Option>
+  </PersonalityInfo>
+  <Delphi.Personality>
+    <Source>
+      <Source Name="MainSource">lesson43.dpr</Source>
+    </Source>
+    <FileVersion>
+      <FileVersion Name="Version">7.0</FileVersion>
+    </FileVersion>
+    <Compiler>
+      <Compiler Name="A">8</Compiler>
+      <Compiler Name="B">0</Compiler>
+      <Compiler Name="C">1</Compiler>
+      <Compiler Name="D">1</Compiler>
+      <Compiler Name="E">0</Compiler>
+      <Compiler Name="F">0</Compiler>
+      <Compiler Name="G">1</Compiler>
+      <Compiler Name="H">1</Compiler>
+      <Compiler Name="I">1</Compiler>
+      <Compiler Name="J">0</Compiler>
+      <Compiler Name="K">0</Compiler>
+      <Compiler Name="L">1</Compiler>
+      <Compiler Name="M">0</Compiler>
+      <Compiler Name="N">1</Compiler>
+      <Compiler Name="O">1</Compiler>
+      <Compiler Name="P">1</Compiler>
+      <Compiler Name="Q">0</Compiler>
+      <Compiler Name="R">0</Compiler>
+      <Compiler Name="S">0</Compiler>
+      <Compiler Name="T">0</Compiler>
+      <Compiler Name="U">0</Compiler>
+      <Compiler Name="V">1</Compiler>
+      <Compiler Name="W">0</Compiler>
+      <Compiler Name="X">1</Compiler>
+      <Compiler Name="Y">1</Compiler>
+      <Compiler Name="Z">1</Compiler>
+      <Compiler Name="ShowHints">True</Compiler>
+      <Compiler Name="ShowWarnings">True</Compiler>
+      <Compiler Name="UnitAliases">WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;</Compiler>
+      <Compiler Name="NamespacePrefix"></Compiler>
+      <Compiler Name="GenerateDocumentation">False</Compiler>
+      <Compiler Name="DefaultNamespace"></Compiler>
+      <Compiler Name="SymbolDeprecated">True</Compiler>
+      <Compiler Name="SymbolLibrary">True</Compiler>
+      <Compiler Name="SymbolPlatform">True</Compiler>
+      <Compiler Name="SymbolExperimental">True</Compiler>
+      <Compiler Name="UnitLibrary">True</Compiler>
+      <Compiler Name="UnitPlatform">True</Compiler>
+      <Compiler Name="UnitDeprecated">True</Compiler>
+      <Compiler Name="UnitExperimental">True</Compiler>
+      <Compiler Name="HResultCompat">True</Compiler>
+      <Compiler Name="HidingMember">True</Compiler>
+      <Compiler Name="HiddenVirtual">True</Compiler>
+      <Compiler Name="Garbage">True</Compiler>
+      <Compiler Name="BoundsError">True</Compiler>
+      <Compiler Name="ZeroNilCompat">True</Compiler>
+      <Compiler Name="StringConstTruncated">True</Compiler>
+      <Compiler Name="ForLoopVarVarPar">True</Compiler>
+      <Compiler Name="TypedConstVarPar">True</Compiler>
+      <Compiler Name="AsgToTypedConst">True</Compiler>
+      <Compiler Name="CaseLabelRange">True</Compiler>
+      <Compiler Name="ForVariable">True</Compiler>
+      <Compiler Name="ConstructingAbstract">True</Compiler>
+      <Compiler Name="ComparisonFalse">True</Compiler>
+      <Compiler Name="ComparisonTrue">True</Compiler>
+      <Compiler Name="ComparingSignedUnsigned">True</Compiler>
+      <Compiler Name="CombiningSignedUnsigned">True</Compiler>
+      <Compiler Name="UnsupportedConstruct">True</Compiler>
+      <Compiler Name="FileOpen">True</Compiler>
+      <Compiler Name="FileOpenUnitSrc">True</Compiler>
+      <Compiler Name="BadGlobalSymbol">True</Compiler>
+      <Compiler Name="DuplicateConstructorDestructor">True</Compiler>
+      <Compiler Name="InvalidDirective">True</Compiler>
+      <Compiler Name="PackageNoLink">True</Compiler>
+      <Compiler Name="PackageThreadVar">True</Compiler>
+      <Compiler Name="ImplicitImport">True</Compiler>
+      <Compiler Name="HPPEMITIgnored">True</Compiler>
+      <Compiler Name="NoRetVal">True</Compiler>
+      <Compiler Name="UseBeforeDef">True</Compiler>
+      <Compiler Name="ForLoopVarUndef">True</Compiler>
+      <Compiler Name="UnitNameMismatch">True</Compiler>
+      <Compiler Name="NoCFGFileFound">True</Compiler>
+      <Compiler Name="ImplicitVariants">True</Compiler>
+      <Compiler Name="UnicodeToLocale">True</Compiler>
+      <Compiler Name="LocaleToUnicode">True</Compiler>
+      <Compiler Name="ImagebaseMultiple">True</Compiler>
+      <Compiler Name="SuspiciousTypecast">True</Compiler>
+      <Compiler Name="PrivatePropAccessor">True</Compiler>
+      <Compiler Name="UnsafeType">False</Compiler>
+      <Compiler Name="UnsafeCode">False</Compiler>
+      <Compiler Name="UnsafeCast">False</Compiler>
+      <Compiler Name="OptionTruncated">True</Compiler>
+      <Compiler Name="WideCharReduced">True</Compiler>
+      <Compiler Name="DuplicatesIgnored">True</Compiler>
+      <Compiler Name="UnitInitSeq">True</Compiler>
+      <Compiler Name="LocalPInvoke">True</Compiler>
+      <Compiler Name="MessageDirective">True</Compiler>
+      <Compiler Name="CodePage"></Compiler>
+    </Compiler>
+    <Linker>
+      <Linker Name="MapFile">0</Linker>
+      <Linker Name="OutputObjs">0</Linker>
+      <Linker Name="GenerateHpps">False</Linker>
+      <Linker Name="ConsoleApp">1</Linker>
+      <Linker Name="DebugInfo">False</Linker>
+      <Linker Name="RemoteSymbols">False</Linker>
+      <Linker Name="GenerateDRC">False</Linker>
+      <Linker Name="MinStackSize">16384</Linker>
+      <Linker Name="MaxStackSize">1048576</Linker>
+      <Linker Name="ImageBase">4194304</Linker>
+      <Linker Name="ExeDescription"></Linker>
+    </Linker>
+    <Directories>
+      <Directories Name="OutputDir"></Directories>
+      <Directories Name="UnitOutputDir"></Directories>
+      <Directories Name="PackageDLLOutputDir"></Directories>
+      <Directories Name="PackageDCPOutputDir"></Directories>
+      <Directories Name="SearchPath">../../../JEDI-SDL/SDL/Pas</Directories>
+      <Directories Name="Packages"></Directories>
+      <Directories Name="Conditionals"></Directories>
+      <Directories Name="DebugSourceDirs"></Directories>
+      <Directories Name="UsePackages">False</Directories>
+    </Directories>
+    <Parameters>
+      <Parameters Name="RunParams"></Parameters>
+      <Parameters Name="HostApplication"></Parameters>
+      <Parameters Name="Launcher"></Parameters>
+      <Parameters Name="UseLauncher">False</Parameters>
+      <Parameters Name="DebugCWD"></Parameters>
+      <Parameters Name="Debug Symbols Search Path"></Parameters>
+      <Parameters Name="LoadAllSymbols">True</Parameters>
+      <Parameters Name="LoadUnspecifiedSymbols">False</Parameters>
+    </Parameters>
+    <Language>
+      <Language Name="ActiveLang"></Language>
+      <Language Name="ProjectLang">$00000000</Language>
+      <Language Name="RootDir"></Language>
+    </Language>
+    <VersionInfo>
+      <VersionInfo Name="IncludeVerInfo">False</VersionInfo>
+      <VersionInfo Name="AutoIncBuild">False</VersionInfo>
+      <VersionInfo Name="MajorVer">1</VersionInfo>
+      <VersionInfo Name="MinorVer">0</VersionInfo>
+      <VersionInfo Name="Release">0</VersionInfo>
+      <VersionInfo Name="Build">0</VersionInfo>
+      <VersionInfo Name="Debug">False</VersionInfo>
+      <VersionInfo Name="PreRelease">False</VersionInfo>
+      <VersionInfo Name="Special">False</VersionInfo>
+      <VersionInfo Name="Private">False</VersionInfo>
+      <VersionInfo Name="DLL">False</VersionInfo>
+      <VersionInfo Name="Locale">1031</VersionInfo>
+      <VersionInfo Name="CodePage">1252</VersionInfo>
+    </VersionInfo>
+    <VersionInfoKeys>
+      <VersionInfoKeys Name="CompanyName"></VersionInfoKeys>
+      <VersionInfoKeys Name="FileDescription"></VersionInfoKeys>
+      <VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
+      <VersionInfoKeys Name="InternalName"></VersionInfoKeys>
+      <VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys>
+      <VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys>
+      <VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys>
+      <VersionInfoKeys Name="ProductName"></VersionInfoKeys>
+      <VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
+      <VersionInfoKeys Name="Comments"></VersionInfoKeys>
+    </VersionInfoKeys>
+  </Delphi.Personality>
+</BorlandProject>
diff --git a/songmanagement/src/lib/freetype/demo/nehe/lesson43.dpr b/songmanagement/src/lib/freetype/demo/nehe/lesson43.dpr
new file mode 100644
index 00000000..fe296fb5
--- /dev/null
+++ b/songmanagement/src/lib/freetype/demo/nehe/lesson43.dpr
@@ -0,0 +1,289 @@
+program lesson43;
+(*
+ * This code was created by Jeff Molofee '99
+ * (ported to Linux/SDL by Ti Leggett '01)
+ *
+ * If you've found this code useful, please let me know.
+ *
+ * Visit Jeff at http://nehe.gamedev.net/
+ *
+ * or for port-specific comments, questions, bugreports etc.
+ * email to leggett@eecs.tulane.edu
+ *)
+
+{$IFDEF FPC}
+  {$mode delphi}{$H+}
+{$ENDIF}
+
+{$APPTYPE Console}
+
+uses
+  moduleloader in '../../../JEDI-SDL/SDL/Pas/moduleloader.pas',
+  SDL          in '../../../JEDI-SDL/SDL/Pas/sdl.pas',
+  gl           in '../../../JEDI-SDL/OpenGL/Pas/gl.pas',
+  glu          in '../../../JEDI-SDL/OpenGL/Pas/glu.pas',
+  ctypes       in '../../../ctypes/ctypes.pas',
+  FreeType     in '../../freetype.pas',
+  UFreeType    in 'UFreeType.pas',
+  math,
+  sysutils;
+
+const
+  // screen width, height, and bit depth
+  SCREEN_WIDTH  = 640;
+  SCREEN_HEIGHT = 480;
+  SCREEN_BPP    =  16;
+
+var
+  our_font: TFontData;
+  // This is our SDL surface
+  surface: PSDL_Surface;
+  cnt1, cnt2: GLfloat;
+
+(* function to release/destroy our resources and restoring the old desktop *)
+procedure Quit(returnCode: integer);
+begin
+  // clean up the window
+  SDL_Quit( );
+
+  // and exit appropriately
+  Halt( returnCode );
+end;
+
+(* function to reset our viewport after a window resize *)
+function resizeWindow(width: integer; height: integer): boolean;
+var
+  // Height / width ration
+  ratio: GLfloat;
+begin
+  // Protect against a divide by zero
+  if ( height = 0 ) then
+    height := 1;
+
+  ratio := width / height;
+
+  // Setup our viewport.
+  glViewport( 0, 0, GLsizei(width), GLsizei(height) );
+
+  // change to the projection matrix and set our viewing volume.
+  glMatrixMode( GL_PROJECTION );
+  glLoadIdentity( );
+
+  // Set our perspective
+  gluPerspective( 45.0, ratio, 0.1, 100.0 );
+
+  // Make sure we're chaning the model view and not the projection
+  glMatrixMode( GL_MODELVIEW );
+
+  // Reset The View
+  glLoadIdentity( );
+
+  Result := true;
+end;
+
+(* function to handle key press events *)
+procedure handleKeyPress(keysym: PSDL_keysym);
+begin
+  case ( keysym^.sym ) of
+    SDLK_ESCAPE:
+    begin
+      // ESC key was pressed
+      Quit( 0 );
+    end;
+    SDLK_F1:
+    begin
+      // F1 key was pressed
+      // this toggles fullscreen mode
+      SDL_WM_ToggleFullScreen( surface );
+    end;
+  end;
+end;
+
+(* general OpenGL initialization function *)
+function initGL(): boolean;
+begin
+  // Enable smooth shading
+  glShadeModel( GL_SMOOTH );
+
+  // Set the background black
+  glClearColor( 0.0, 0.0, 0.0, 0.0 );
+
+  // Depth buffer setup
+  glClearDepth( 1.0 );
+
+  // Enables Depth Testing
+  glEnable( GL_DEPTH_TEST );
+
+  // The Type Of Depth Test To Do
+  glDepthFunc( GL_LEQUAL );
+
+  // Really Nice Perspective Calculations
+  glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
+
+  our_font := TFontData.Create('Test.ttf', 16);
+
+  Result := true;
+end;
+
+(* Here goes our drawing code *)
+function drawGLScene(): boolean;
+begin
+  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);  // Clear Screen And Depth Buffer
+  glLoadIdentity();              // Reset The Current Modelview Matrix
+  glTranslatef(0.0, 0.0, -1.0);  // Move One Unit Into The Screen
+
+  // Blue Text
+  glColor3ub(0, 0, $ff);
+
+  // Position The WGL Text On The Screen
+  glRasterPos2f(-0.40, 0.35);
+
+  // Here We Print Some Text Using Our FreeType Font
+  // The only really important command is the actual print() call,
+  // but for the sake of making the results a bit more interesting
+  // I have put in some code to rotate and scale the text.
+
+  // Red text
+  glColor3ub($ff, 0, 0);
+
+  glPushMatrix();
+  glLoadIdentity();
+  glRotatef(cnt1, 0, 0,1);
+  glScalef(1, 0.8 + 0.3*cos(cnt1/5) ,1);
+  glTranslatef(-180, 0, 0);
+  TFreeType.print(our_font, 320, 240, 'Active FreeType Text - ' + FloatToStr(cnt1));
+  glPopMatrix();
+
+  //Uncomment this to test out print's ability to handle newlines.
+  //TFreeType.print(our_font, 320, 200, 'Here'#13'there'#13'be'#13#13'newlines'#13'.');
+
+  cnt1 := cnt1 + 0.051;  // Increase The First Counter
+  cnt2 := cnt2 + 0.005;  // Increase The First Counter
+
+  SDL_GL_SwapBuffers( );
+
+  Result := true;
+end;
+
+var
+  // Flags to pass to SDL_SetVideoMode
+  videoFlags: integer;
+  // main loop variable
+  done: boolean = false;
+  // used to collect events
+  event: TSDL_Event;
+  // this holds some info about our display
+  videoInfo: PSDL_VideoInfo;
+  // whether or not the window is active
+  isActive: boolean = true;
+
+begin
+  // initialize SDL
+  if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) then
+  begin
+    writeln( ErrOutput, 'Video initialization failed: ' + SDL_GetError() );
+    Quit( 1 );
+  end;
+
+  // Fetch the video info
+  videoInfo := SDL_GetVideoInfo( );
+
+  if ( videoInfo = nil ) then
+  begin
+    writeln( ErrOutput, 'Video query failed: ' + SDL_GetError() );
+    Quit( 1 );
+  end;
+
+  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // Enable double buffering
+
+  // the flags to pass to SDL_SetVideoMode
+  videoFlags := SDL_OPENGL;                        // Enable OpenGL in SDL
+  videoFlags := videoFlags or SDL_HWPALETTE;       // Store the palette in hardware
+  videoFlags := videoFlags or SDL_RESIZABLE;       // Enable window resizing
+
+  // This checks to see if surfaces can be stored in memory
+  if ( videoInfo^.hw_available <> 0 ) then
+    videoFlags := videoFlags or SDL_HWSURFACE
+  else
+    videoFlags := videoFlags or SDL_SWSURFACE;
+
+  // This checks if hardware blits can be done
+  if ( videoInfo^.blit_hw <> 0 ) then
+    videoFlags := videoFlags or SDL_HWACCEL;
+
+  // Sets up OpenGL double buffering
+  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+
+  // get a SDL surface
+  surface := SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,
+                               videoFlags );
+
+  // Verify there is a surface
+  if ( surface = nil ) then
+  begin
+    writeln( ErrOutput, 'Video mode set failed: ' + SDL_GetError() );
+    Quit( 1 );
+  end;
+
+  // initialize OpenGL
+  initGL();
+
+  // resize the initial window
+  resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );
+
+  // wait for events
+  while ( not done ) do
+  begin
+    { handle the events in the queue }
+
+    while ( SDL_PollEvent( @event ) <> 0 ) do
+    begin
+      case( event.type_ ) of
+        SDL_ACTIVEEVENT:
+        begin
+          // Something's happend with our focus
+          // If we are iconified, we shouldn't draw the screen
+          if ( (event.active.state and SDL_APPACTIVE) <> 0 ) then
+          begin
+            if (  event.active.gain = 0 ) then
+              isActive := false
+            else
+              isActive := true;
+          end;
+        end;
+        SDL_VIDEORESIZE:
+        begin
+          // handle resize event
+          {$IFDEF UNIX}
+          surface := SDL_SetVideoMode( event.resize.w,
+              event.resize.h,
+              16, videoFlags );
+          if ( surface = nil ) then
+          begin
+            writeln( ErrOutput, 'Could not get a surface after resize: ' + SDL_GetError( ) );
+            Quit( 1 );
+          end;
+          {$ENDIF}
+          resizeWindow( event.resize.w, event.resize.h );
+        end;
+        SDL_KEYDOWN:
+        begin
+          // handle key presses
+          handleKeyPress( @event.key.keysym );
+        end;
+        SDL_QUITEV:
+        begin
+          // handle quit requests
+          done := true;
+        end;
+      end;
+    end;
+
+    // draw the scene
+    if ( isActive ) then
+      drawGLScene( );
+  end;
+
+  // clean ourselves up and exit
+  Quit( 0 );
+end.
diff --git a/songmanagement/src/lib/freetype/demo/nehe/readme.txt b/songmanagement/src/lib/freetype/demo/nehe/readme.txt
new file mode 100644
index 00000000..1186ef0e
--- /dev/null
+++ b/songmanagement/src/lib/freetype/demo/nehe/readme.txt
@@ -0,0 +1,9 @@
+Pascal conversion of the NeHe tutorial lesson 43  (Tutorial on using FreeType Fonts in OpenGL)
+http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=43
+
+Put the following DLLs into this directory:
+- libfreetype-6.dll
+- SDL.dll
+- zlib1.dll
+
+and copy a TrueType font to this directory and rename it into "Test.ttf".
diff --git a/songmanagement/src/lib/freetype/demo/switches.inc b/songmanagement/src/lib/freetype/demo/switches.inc
new file mode 100644
index 00000000..0a940004
--- /dev/null
+++ b/songmanagement/src/lib/freetype/demo/switches.inc
@@ -0,0 +1 @@
+{$DEFINE FREETYPE_DEMO}
diff --git a/songmanagement/src/lib/freetype/freetype.pas b/songmanagement/src/lib/freetype/freetype.pas
new file mode 100644
index 00000000..01f507bc
--- /dev/null
+++ b/songmanagement/src/lib/freetype/freetype.pas
@@ -0,0 +1,1903 @@
+(***************************************************************************)
+(*                                                                         *)
+(*  freetype.h                                                             *)
+(*                                                                         *)
+(*    FreeType high-level API and common types (specification only).       *)
+(*                                                                         *)
+(*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by             *)
+(*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *)
+(*                                                                         *)
+(*  This file is part of the FreeType project, and may only be used,       *)
+(*  modified, and distributed under the terms of the FreeType project      *)
+(*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *)
+(*  this file you indicate that you have read the license and              *)
+(*  understand and accept it fully.                                        *)
+(*                                                                         *)
+(***************************************************************************)
+
+(***************************************************************************)
+(* Initial Pascal port by                                                  *)
+(***************************************************************************)
+(* Anti-Grain Geometry - Version 2.4 (Public License)                      *)
+(* Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)     *)
+(*                                                                         *)
+(* Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)     *)
+(* Pascal Port By: Milan Marusinec alias Milano                            *)
+(*                 milan@marusinec.sk                                      *)
+(*                 http://www.aggpas.org                                   *)
+(* Copyright (c) 2005-2007                                                 *)
+(*                                                                         *)
+(* Permission to copy, use, modify, sell and distribute this software      *)
+(* is granted provided this copyright notice appears in all copies.        *)
+(* This software is provided "as is" without express or implied            *)
+(* warranty, and with no claim as to its suitability for any purpose.      *)
+(*                                                                         *)
+(***************************************************************************)
+
+(***************************************************************************)
+(* Extended by the UltraStar Deluxe Team                                   *)
+(***************************************************************************)
+
+unit freetype;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE DELPHI }
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+uses
+  ctypes;
+
+const
+{$IF Defined(MSWINDOWS)}
+  ft_lib = 'freetype6.dll';
+{$ELSEIF Defined(DARWIN)}
+  ft_lib = 'libfreetype.dylib';
+  {$LINKLIB libfreetype}
+{$ELSEIF Defined(UNIX)}
+  ft_lib = 'freetype.so';
+{$IFEND}
+
+type
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Library                                                         *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A handle to a FreeType library instance.  Each `library' is        *)
+  (*    completely independent from the others; it is the `root' of a set  *)
+  (*    of objects like fonts, faces, sizes, etc.                          *)
+  (*                                                                       *)
+  (*    It also embeds a memory manager (see @FT_Memory), as well as a     *)
+  (*    scan-line converter object (see @FT_Raster).                       *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Library objects are normally created by @FT_Init_FreeType, and     *)
+  (*    destroyed with @FT_Done_FreeType.                                  *)
+  (*                                                                       *)
+  FT_Library = Pointer;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Enum>                                                                *)
+  (*    FT_FACE_FLAG_XXX                                                   *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A list of bit flags used in the `face_flags' field of the          *)
+  (*    @FT_FaceRec structure.  They inform client applications of         *)
+  (*    properties of the corresponding face.                              *)
+  (*                                                                       *)
+  (* <Values>                                                              *)
+  (*    FT_FACE_FLAG_SCALABLE ::                                           *)
+  (*      Indicates that the face provides vectorial outlines.  This       *)
+  (*      doesn't prevent embedded bitmaps, i.e., a face can have both     *)
+  (*      this bit and @FT_FACE_FLAG_FIXED_SIZES set.                      *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_FIXED_SIZES ::                                        *)
+  (*      Indicates that the face contains `fixed sizes', i.e., bitmap     *)
+  (*      strikes for some given pixel sizes.  See the `num_fixed_sizes'   *)
+  (*      and `available_sizes' fields of @FT_FaceRec.                     *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_FIXED_WIDTH ::                                        *)
+  (*      Indicates that the face contains fixed-width characters (like    *)
+  (*      Courier, Lucido, MonoType, etc.).                                *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_SFNT ::                                               *)
+  (*      Indicates that the face uses the `sfnt' storage scheme.  For     *)
+  (*      now, this means TrueType and OpenType.                           *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_HORIZONTAL ::                                         *)
+  (*      Indicates that the face contains horizontal glyph metrics.  This *)
+  (*      should be set for all common formats.                            *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_VERTICAL ::                                           *)
+  (*      Indicates that the face contains vertical glyph metrics.  This   *)
+  (*      is only available in some formats, not all of them.              *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_KERNING ::                                            *)
+  (*      Indicates that the face contains kerning information.  If set,   *)
+  (*      the kerning distance can be retrieved through the function       *)
+  (*      @FT_Get_Kerning.  Note that if unset, this function will always  *)
+  (*      return the vector (0,0).                                         *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_FAST_GLYPHS ::                                        *)
+  (*      THIS FLAG IS DEPRECATED.  DO NOT USE OR TEST IT.                 *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_MULTIPLE_MASTERS ::                                   *)
+  (*      Indicates that the font contains multiple masters and is capable *)
+  (*      of interpolating between them.  See the multiple-masters         *)
+  (*      specific API for details.                                        *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_GLYPH_NAMES ::                                        *)
+  (*      Indicates that the font contains glyph names that can be         *)
+  (*      retrieved through @FT_Get_Glyph_Name.  Note that some TrueType   *)
+  (*      fonts contain broken glyph name tables.  Use the function        *)
+  (*      @FT_Has_PS_Glyph_Names when needed.                              *)
+  (*                                                                       *)
+  (*    FT_FACE_FLAG_EXTERNAL_STREAM ::                                    *)
+  (*      Used internally by FreeType to indicate that a face's stream was *)
+  (*      provided by the client application and should not be destroyed   *)
+  (*      when @FT_Done_Face is called.  Don't read or test this flag.     *)
+  (*                                                                       *)
+const
+  FT_FACE_FLAG_SCALABLE = 1 shl 0;
+  FT_FACE_FLAG_KERNING  = 1 shl 6;
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Macro>                                                               *)
+  (*    FT_ENC_TAG                                                         *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    This macro converts four-letter tags into an unsigned long.  It is *)
+  (*    used to define `encoding' identifiers (see @FT_Encoding).          *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Since many 16-bit compilers don't like 32-bit enumerations, you    *)
+  (*    should redefine this macro in case of problems to something like   *)
+  (*    this:                                                              *)
+  (*                                                                       *)
+  (*    {                                                                  *)
+  (*      #define FT_ENC_TAG( value, a, b, c, d )  value                   *)
+  (*    }                                                                  *)
+  (*                                                                       *)
+  (*    to get a simple enumeration without assigning special numbers.     *)
+  (*                                                                       *)
+  {
+  #define FT_ENC_TAG( value, a, b, c, d )         \
+          value = ( ( (FT_UInt32)(a) << 24 ) |  \
+                    ( (FT_UInt32)(b) << 16 ) |  \
+                    ( (FT_UInt32)(c) <<  8 ) |  \
+                      (FT_UInt32)(d)         )
+  }
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Enum>                                                                *)
+  (*    FT_Encoding                                                        *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    An enumeration used to specify encodings supported by charmaps.    *)
+  (*    Used in the @FT_Select_Charmap API function.                       *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Because of 32-bit charcodes defined in Unicode (i.e., surrogates), *)
+  (*    all character codes must be expressed as FT_Longs.                 *)
+  (*                                                                       *)
+  (*    The values of this type correspond to specific character           *)
+  (*    repertories (i.e. charsets), and not to text encoding methods      *)
+  (*    (like UTF-8, UTF-16, GB2312_EUC, etc.).                            *)
+  (*                                                                       *)
+  (*    Other encodings might be defined in the future.                    *)
+  (*                                                                       *)
+  (* <Values>                                                              *)
+  (*   FT_ENCODING_NONE ::                                                 *)
+  (*     The encoding value 0 is reserved.                                 *)
+  (*                                                                       *)
+  (*   FT_ENCODING_UNICODE ::                                              *)
+  (*     Corresponds to the Unicode character set.  This value covers      *)
+  (*     all versions of the Unicode repertoire, including ASCII and       *)
+  (*     Latin-1.  Most fonts include a Unicode charmap, but not all       *)
+  (*     of them.                                                          *)
+  (*                                                                       *)
+  (*   FT_ENCODING_MS_SYMBOL ::                                            *)
+  (*     Corresponds to the Microsoft Symbol encoding, used to encode      *)
+  (*     mathematical symbols in the 32..255 character code range.  For    *)
+  (*     more information, see `http://www.ceviz.net/symbol.htm'.          *)
+  (*                                                                       *)
+  (*   FT_ENCODING_SJIS ::                                                 *)
+  (*     Corresponds to Japanese SJIS encoding.  More info at              *)
+  (*     at `http://langsupport.japanreference.com/encoding.shtml'.        *)
+  (*     See note on multi-byte encodings below.                           *)
+  (*                                                                       *)
+  (*   FT_ENCODING_GB2312 ::                                               *)
+  (*     Corresponds to an encoding system for Simplified Chinese as used  *)
+  (*     used in mainland China.                                           *)
+  (*                                                                       *)
+  (*   FT_ENCODING_BIG5 ::                                                 *)
+  (*     Corresponds to an encoding system for Traditional Chinese as used *)
+  (*     in Taiwan and Hong Kong.                                          *)
+  (*                                                                       *)
+  (*   FT_ENCODING_WANSUNG ::                                              *)
+  (*     Corresponds to the Korean encoding system known as Wansung.       *)
+  (*     For more information see                                          *)
+  (*     `http://www.microsoft.com/typography/unicode/949.txt'.            *)
+  (*                                                                       *)
+  (*   FT_ENCODING_JOHAB ::                                                *)
+  (*     The Korean standard character set (KS C-5601-1992), which         *)
+  (*     corresponds to MS Windows code page 1361.  This character set     *)
+  (*     includes all possible Hangeul character combinations.             *)
+  (*                                                                       *)
+  (*   FT_ENCODING_ADOBE_LATIN_1 ::                                        *)
+  (*     Corresponds to a Latin-1 encoding as defined in a Type 1          *)
+  (*     Postscript font.  It is limited to 256 character codes.           *)
+  (*                                                                       *)
+  (*   FT_ENCODING_ADOBE_STANDARD ::                                       *)
+  (*     Corresponds to the Adobe Standard encoding, as found in Type 1,   *)
+  (*     CFF, and OpenType/CFF fonts.  It is limited to 256 character      *)
+  (*     codes.                                                            *)
+  (*                                                                       *)
+  (*   FT_ENCODING_ADOBE_EXPERT ::                                         *)
+  (*     Corresponds to the Adobe Expert encoding, as found in Type 1,     *)
+  (*     CFF, and OpenType/CFF fonts.  It is limited to 256 character      *)
+  (*     codes.                                                            *)
+  (*                                                                       *)
+  (*   FT_ENCODING_ADOBE_CUSTOM ::                                         *)
+  (*     Corresponds to a custom encoding, as found in Type 1, CFF, and    *)
+  (*     OpenType/CFF fonts.  It is limited to 256 character codes.        *)
+  (*                                                                       *)
+  (*   FT_ENCODING_APPLE_ROMAN ::                                          *)
+  (*     Corresponds to the 8-bit Apple roman encoding.  Many TrueType and *)
+  (*     OpenType fonts contain a charmap for this encoding, since older   *)
+  (*     versions of Mac OS are able to use it.                            *)
+  (*                                                                       *)
+  (*   FT_ENCODING_OLD_LATIN_2 ::                                          *)
+  (*     This value is deprecated and was never used nor reported by       *)
+  (*     FreeType.  Don't use or test for it.                              *)
+  (*                                                                       *)
+  (*   FT_ENCODING_MS_SJIS ::                                              *)
+  (*     Same as FT_ENCODING_SJIS.  Deprecated.                            *)
+  (*                                                                       *)
+  (*   FT_ENCODING_MS_GB2312 ::                                            *)
+  (*     Same as FT_ENCODING_GB2312.  Deprecated.                          *)
+  (*                                                                       *)
+  (*   FT_ENCODING_MS_BIG5 ::                                              *)
+  (*     Same as FT_ENCODING_BIG5.  Deprecated.                            *)
+  (*                                                                       *)
+  (*   FT_ENCODING_MS_WANSUNG ::                                           *)
+  (*     Same as FT_ENCODING_WANSUNG.  Deprecated.                         *)
+  (*                                                                       *)
+  (*   FT_ENCODING_MS_JOHAB ::                                             *)
+  (*     Same as FT_ENCODING_JOHAB.  Deprecated.                           *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*   By default, FreeType automatically synthetizes a Unicode charmap    *)
+  (*   for Postscript fonts, using their glyph names dictionaries.         *)
+  (*   However, it will also report the encodings defined explicitly in    *)
+  (*   the font file, for the cases when they are needed, with the Adobe   *)
+  (*   values as well.                                                     *)
+  (*                                                                       *)
+  (*   FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap   *)
+  (*   is neither Unicode nor ISO-8859-1 (otherwise it is set to           *)
+  (*   FT_ENCODING_UNICODE).  Use `FT_Get_BDF_Charset_ID' to find out      *)
+  (*   which encoding is really present.  If, for example, the             *)
+  (*   `cs_registry' field is `KOI8' and the `cs_encoding' field is `R',   *)
+  (*   the font is encoded in KOI8-R.                                      *)
+  (*                                                                       *)
+  (*   FT_ENCODING_NONE is always set (with a single exception) by the     *)
+  (*   winfonts driver.  Use `FT_Get_WinFNT_Header' and examine the        *)
+  (*   `charset' field of the `FT_WinFNT_HeaderRec' structure to find out  *)
+  (*   which encoding is really present.  For example, FT_WinFNT_ID_CP1251 *)
+  (*   (204) means Windows code page 1251 (for Russian).                   *)
+  (*                                                                       *)
+  (*   FT_ENCODING_NONE is set if `platform_id' is `TT_PLATFORM_MACINTOSH' *)
+  (*   and `encoding_id' is not `TT_MAC_ID_ROMAN' (otherwise it is set to  *)
+  (*   FT_ENCODING_APPLE_ROMAN).                                           *)
+  (*                                                                       *)
+  (*   If `platform_id' is `TT_PLATFORM_MACINTOSH', use the function       *)
+  (*   `FT_Get_CMap_Language_ID' to query the Mac language ID which may be *)
+  (*   needed to be able to distinguish Apple encoding variants.  See      *)
+  (*                                                                       *)
+  (*     http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/README.TXT   *)
+  (*                                                                       *)
+  (*   to get an idea how to do that.  Basically, if the language ID is 0, *)
+  (*   dont use it, otherwise subtract 1 from the language ID.  Then       *)
+  (*   examine `encoding_id'.  If, for example, `encoding_id' is           *)
+  (*   `TT_MAC_ID_ROMAN' and the language ID (minus 1) is                  *)
+  (*   `TT_MAC_LANGID_GREEK', it is the Greek encoding, not Roman.         *)
+  (*   `TT_MAC_ID_ARABIC' with `TT_MAC_LANGID_FARSI' means the Farsi       *)
+  (*   variant the Arabic encoding.                                        *)
+  (*                                                                       *)
+type
+  PFT_Encoding = ^FT_Encoding;
+  FT_Encoding = cint32; // 32 bit enum of FT_ENC_TAG
+const
+  FT_ENCODING_NONE      = (Ord(#0) shl 24) or
+                          (Ord(#0) shl 16) or
+                          (Ord(#0) shl  8) or
+                          (Ord(#0) shl  0);
+
+  FT_ENCODING_MS_SYMBOL = (Ord('s') shl 24) or
+                          (Ord('y') shl 16) or
+                          (Ord('m') shl  8) or
+                          (Ord('b') shl  0);
+
+  FT_ENCODING_UNICODE   = (Ord('u') shl 24) or
+                          (Ord('n') shl 16) or
+                          (Ord('i') shl  8) or
+                          (Ord('c') shl  0);
+
+  FT_ENCODING_SJIS      = (Ord('s') shl 24) or
+                          (Ord('j') shl 16) or
+                          (Ord('i') shl  8) or
+                          (Ord('s') shl  0);
+
+  FT_ENCODING_GB2312    = (Ord('g') shl 24) or
+                          (Ord('b') shl 16) or
+                          (Ord(' ') shl  8) or
+                          (Ord(' ') shl  0);
+
+  FT_ENCODING_BIG5      = (Ord('b') shl 24) or
+                          (Ord('i') shl 16) or
+                          (Ord('g') shl  8) or
+                          (Ord('5') shl  0);
+
+  FT_ENCODING_WANSUNG   = (Ord('w') shl 24) or
+                          (Ord('a') shl 16) or
+                          (Ord('n') shl  8) or
+                          (Ord('s') shl  0);
+
+  FT_ENCODING_JOHAB     = (Ord('j') shl 24) or
+                          (Ord('o') shl 16) or
+                          (Ord('h') shl  8) or
+                          (Ord('a') shl  0);
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Constant>                                                            *)
+  (*    FT_STYLE_FLAG_XXX                                                  *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A list of bit-flags used to indicate the style of a given face.    *)
+  (*    These are used in the `style_flags' field of @FT_FaceRec.          *)
+  (*                                                                       *)
+  (* <Values>                                                              *)
+  (*    FT_STYLE_FLAG_ITALIC ::                                            *)
+  (*      Indicates that a given face is italicized.                       *)
+  (*                                                                       *)
+  (*    FT_STYLE_FLAG_BOLD ::                                              *)
+  (*      Indicates that a given face is bold.                             *)
+  (*                                                                       *)
+const
+  FT_STYLE_FLAG_ITALIC = 1 shl 0;
+  FT_STYLE_FLAG_BOLD   = 1 shl 1;
+
+
+ (***************************************************************************
+  *
+  * @enum:
+  *   FT_LOAD_XXX
+  *
+  * @description:
+  *   A list of bit-field constants, used with @FT_Load_Glyph to indicate
+  *   what kind of operations to perform during glyph loading.
+  *
+  * @values:
+  *   FT_LOAD_DEFAULT ::
+  *     Corresponding to 0, this value is used a default glyph load.  In this
+  *     case, the following will happen:
+  *
+  *     1. FreeType looks for a bitmap for the glyph corresponding to the
+  *        face's current size.  If one is found, the function returns.  The
+  *        bitmap data can be accessed from the glyph slot (see note below).
+  *
+  *     2. If no embedded bitmap is searched or found, FreeType looks for a
+  *        scalable outline.  If one is found, it is loaded from the font
+  *        file, scaled to device pixels, then "hinted" to the pixel grid in
+  *        order to optimize it.  The outline data can be accessed from the
+  *        glyph slot (see note below).
+  *
+  *     Note that by default, the glyph loader doesn't render outlines into
+  *     bitmaps.  The following flags are used to modify this default
+  *     behaviour to more specific and useful cases.
+  *
+  *   FT_LOAD_NO_SCALE ::
+  *     Don't scale the vector outline being loaded to 26.6 fractional
+  *     pixels, but kept in font units.  Note that this also disables
+  *     hinting and the loading of embedded bitmaps.  You should only use it
+  *     when you want to retrieve the original glyph outlines in font units.
+  *
+  *   FT_LOAD_NO_HINTING ::
+  *     Don't hint glyph outlines after their scaling to device pixels.
+  *     This generally generates "blurrier" glyphs in anti-aliased modes.
+  *
+  *     This flag is ignored if @FT_LOAD_NO_SCALE is set.
+  *
+  *   FT_LOAD_RENDER ::
+  *     Render the glyph outline immediately into a bitmap before the glyph
+  *     loader returns.  By default, the glyph is rendered for the
+  *     @FT_RENDER_MODE_NORMAL mode, which corresponds to 8-bit anti-aliased
+  *     bitmaps using 256 opacity levels.  You can use either
+  *     @FT_LOAD_TARGET_MONO or @FT_LOAD_MONOCHROME to render 1-bit
+  *     monochrome bitmaps.
+  *
+  *     This flag is ignored if @FT_LOAD_NO_SCALE is set.
+  *
+  *   FT_LOAD_NO_BITMAP ::
+  *     Don't look for bitmaps when loading the glyph.  Only scalable
+  *     outlines will be loaded when available, and scaled, hinted, or
+  *     rendered depending on other bit flags.
+  *
+  *     This does not prevent you from rendering outlines to bitmaps
+  *     with @FT_LOAD_RENDER, however.
+  *
+  *   FT_LOAD_VERTICAL_LAYOUT ::
+  *     Prepare the glyph image for vertical text layout.  This basically
+  *     means that `face.glyph.advance' will correspond to the vertical
+  *     advance height (instead of the default horizontal advance width),
+  *     and that the glyph image will be translated to match the vertical
+  *     bearings positions.
+  *
+  *   FT_LOAD_FORCE_AUTOHINT ::
+  *     Force the use of the FreeType auto-hinter when a glyph outline is
+  *     loaded.  You shouldn't need this in a typical application, since it
+  *     is mostly used to experiment with its algorithm.
+  *
+  *   FT_LOAD_CROP_BITMAP ::
+  *     Indicates that the glyph loader should try to crop the bitmap (i.e.,
+  *     remove all space around its black bits) when loading it.  This is
+  *     only useful when loading embedded bitmaps in certain fonts, since
+  *     bitmaps rendered with @FT_LOAD_RENDER are always cropped by default.
+  *
+  *   FT_LOAD_PEDANTIC ::
+  *     Indicates that the glyph loader should perform pedantic
+  *     verifications during glyph loading, rejecting invalid fonts.  This
+  *     is mostly used to detect broken glyphs in fonts.  By default,
+  *     FreeType tries to handle broken fonts also.
+  *
+  *   FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
+  *     Indicates that the glyph loader should ignore the global advance
+  *     width defined in the font.  As far as we know, this is only used by
+  *     the X-TrueType font server, in order to deal correctly with the
+  *     incorrect metrics contained in DynaLab's TrueType CJK fonts.
+  *
+  *   FT_LOAD_NO_RECURSE ::
+  *     This flag is only used internally.  It merely indicates that the
+  *     glyph loader should not load composite glyphs recursively.  Instead,
+  *     it should set the `num_subglyph' and `subglyphs' values of the glyph
+  *     slot accordingly, and set "glyph->format" to
+  *     @FT_GLYPH_FORMAT_COMPOSITE.
+  *
+  *     The description of sub-glyphs is not available to client
+  *     applications for now.
+  *
+  *   FT_LOAD_IGNORE_TRANSFORM ::
+  *     Indicates that the glyph loader should not try to transform the
+  *     loaded glyph image.  This doesn't prevent scaling, hinting, or
+  *     rendering.
+  *
+  *   FT_LOAD_MONOCHROME ::
+  *     This flag is used with @FT_LOAD_RENDER to indicate that you want
+  *     to render a 1-bit monochrome glyph bitmap from a vectorial outline.
+  *
+  *     Note that this has no effect on the hinting algorithm used by the
+  *     glyph loader.  You should better use @FT_LOAD_TARGET_MONO if you
+  *     want to render monochrome-optimized glyph images instead.
+  *
+  *   FT_LOAD_LINEAR_DESIGN ::
+  *     Return the linearly scaled metrics expressed in original font units
+  *     instead of the default 16.16 pixel values.
+  *
+  *   FT_LOAD_NO_AUTOHINT ::
+  *     Indicates that the auto-hinter should never be used to hint glyph
+  *     outlines.  This doesn't prevent native format-specific hinters from
+  *     being used.  This can be important for certain fonts where unhinted
+  *     output is better than auto-hinted one.
+  *
+  *   FT_LOAD_TARGET_NORMAL ::
+  *     Use hinting for @FT_RENDER_MODE_NORMAL.
+  *
+  *   FT_LOAD_TARGET_LIGHT ::
+  *     Use hinting for @FT_RENDER_MODE_LIGHT.
+  *
+  *   FT_LOAD_TARGET_MONO ::
+  *     Use hinting for @FT_RENDER_MODE_MONO.
+  *
+  *   FT_LOAD_TARGET_LCD ::
+  *     Use hinting for @FT_RENDER_MODE_LCD.
+  *
+  *   FT_LOAD_TARGET_LCD_V ::
+  *     Use hinting for @FT_RENDER_MODE_LCD_V.
+  *)
+const
+  FT_LOAD_DEFAULT          = $0000;
+  FT_LOAD_NO_SCALE         = $0001;
+  FT_LOAD_NO_HINTING       = $0002;
+  FT_LOAD_RENDER           = $0004;
+  FT_LOAD_NO_BITMAP        = $0008;
+  FT_LOAD_VERTICAL_LAYOUT  = $0010;
+  FT_LOAD_FORCE_AUTOHINT   = $0020;
+  FT_LOAD_CROP_BITMAP      = $0040;
+  FT_LOAD_PEDANTIC         = $0080;
+  FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH = $0200;
+  FT_LOAD_NO_RECURSE       = $0400;
+  FT_LOAD_IGNORE_TRANSFORM = $0800;
+  FT_LOAD_MONOCHROME       = $1000;
+  FT_LOAD_LINEAR_DESIGN    = $2000;
+
+  (* temporary hack! *)
+  FT_LOAD_SBITS_ONLY       = $4000;
+  FT_LOAD_NO_AUTOHINT      = $8000;
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Enum>                                                                *)
+  (*    FT_Render_Mode                                                     *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    An enumeration type that lists the render modes supported by       *)
+  (*    FreeType 2.  Each mode corresponds to a specific type of scanline  *)
+  (*    conversion performed on the outline, as well as specific           *)
+  (*    hinting optimizations.                                             *)
+  (*                                                                       *)
+  (*    For bitmap fonts the `bitmap->pixel_mode' field in the             *)
+  (*    @FT_GlyphSlotRec structure gives the format of the returned        *)
+  (*    bitmap.                                                            *)
+  (*                                                                       *)
+  (* <Values>                                                              *)
+  (*    FT_RENDER_MODE_NORMAL ::                                           *)
+  (*      This is the default render mode; it corresponds to 8-bit         *)
+  (*      anti-aliased bitmaps, using 256 levels of opacity.               *)
+  (*                                                                       *)
+  (*    FT_RENDER_MODE_LIGHT ::                                            *)
+  (*      This is similar to @FT_RENDER_MODE_NORMAL -- you have to use     *)
+  (*      @FT_LOAD_TARGET_LIGHT in calls to @FT_Load_Glyph to get any      *)
+  (*      effect since the rendering process no longer influences the      *)
+  (*      positioning of glyph outlines.                                   *)
+  (*                                                                       *)
+  (*      The resulting glyph shapes are more similar to the original,     *)
+  (*      while being a bit more fuzzy (`better shapes' instead of `better *)
+  (*      contrast', so to say.                                            *)
+  (*                                                                       *)
+  (*    FT_RENDER_MODE_MONO ::                                             *)
+  (*      This mode corresponds to 1-bit bitmaps.                          *)
+  (*                                                                       *)
+  (*    FT_RENDER_MODE_LCD ::                                              *)
+  (*      This mode corresponds to horizontal RGB/BGR sub-pixel displays,  *)
+  (*      like LCD-screens.  It produces 8-bit bitmaps that are 3 times    *)
+  (*      the width of the original glyph outline in pixels, and which use *)
+  (*      the @FT_PIXEL_MODE_LCD mode.                                     *)
+  (*                                                                       *)
+  (*    FT_RENDER_MODE_LCD_V ::                                            *)
+  (*      This mode corresponds to vertical RGB/BGR sub-pixel displays     *)
+  (*      (like PDA screens, rotated LCD displays, etc.).  It produces     *)
+  (*      8-bit bitmaps that are 3 times the height of the original        *)
+  (*      glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode.   *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*   The LCD-optimized glyph bitmaps produced by FT_Render_Glyph are     *)
+  (*   _not filtered_ to reduce color-fringes.  It is up to the caller to  *)
+  (*   perform this pass.                                                  *)
+  (*                                                                       *)
+type
+  FT_Render_Mode = cint;
+const
+  FT_RENDER_MODE_NORMAL = 0;
+  FT_RENDER_MODE_LIGHT  = FT_RENDER_MODE_NORMAL + 1;
+  FT_RENDER_MODE_MONO   = FT_RENDER_MODE_LIGHT  + 1;
+  FT_RENDER_MODE_LCD    = FT_RENDER_MODE_MONO   + 1;
+  FT_RENDER_MODE_LCD_V  = FT_RENDER_MODE_LCD    + 1;
+  FT_RENDER_MODE_MAX    = FT_RENDER_MODE_LCD_V  + 1;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_GlyphSlot                                                       *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A handle to a given `glyph slot'.  A slot is a container where it  *)
+  (*    is possible to load any one of the glyphs contained in its parent  *)
+  (*    face.                                                              *)
+  (*                                                                       *)
+  (*    In other words, each time you call @FT_Load_Glyph or               *)
+  (*    @FT_Load_Char, the slot's content is erased by the new glyph data, *)
+  (*    i.e. the glyph's metrics, its image (bitmap or outline), and       *)
+  (*    other control information.                                         *)
+  (*                                                                       *)
+  (* <Also>                                                                *)
+  (*    @FT_GlyphSlotRec details the publicly accessible glyph fields.     *)
+  (*                                                                       *)
+type
+  FT_GlyphSlot = ^FT_GlyphSlotRec;
+
+
+{$DEFINE TYPE_DECL}
+{$I ftconfig.inc}
+{$I fttypes.inc}
+{$I ftimage.inc}
+{$I ftglyph.inc}
+{$I ftstroke.inc}
+{$I ftoutln.inc} 
+{$UNDEF TYPE_DECL}
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Glyph_Metrics                                                   *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A structure used to model the metrics of a single glyph.  The      *)
+  (*    values are expressed in 26.6 fractional pixel format; if the flag  *)
+  (*    FT_LOAD_NO_SCALE is used, values are returned in font units        *)
+  (*    instead.                                                           *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    width ::                                                           *)
+  (*      The glyph's width.                                               *)
+  (*                                                                       *)
+  (*    height ::                                                          *)
+  (*      The glyph's height.                                              *)
+  (*                                                                       *)
+  (*    horiBearingX ::                                                    *)
+  (*      Left side bearing for horizontal layout.                         *)
+  (*                                                                       *)
+  (*    horiBearingY ::                                                    *)
+  (*      Top side bearing for horizontal layout.                          *)
+  (*                                                                       *)
+  (*    horiAdvance ::                                                     *)
+  (*      Advance width for horizontal layout.                             *)
+  (*                                                                       *)
+  (*    vertBearingX ::                                                    *)
+  (*      Left side bearing for vertical layout.                           *)
+  (*                                                                       *)
+  (*    vertBearingY ::                                                    *)
+  (*      Top side bearing for vertical layout.                            *)
+  (*                                                                       *)
+  (*    vertAdvance ::                                                     *)
+  (*      Advance height for vertical layout.                              *)
+  (*                                                                       *)
+  FT_Glyph_Metrics = record
+    width  ,
+    height       : FT_Pos;
+
+    horiBearingX ,
+    horiBearingY ,
+    horiAdvance  : FT_Pos;
+
+    vertBearingX ,
+    vertBearingY ,
+    vertAdvance  : FT_Pos;
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Bitmap_Size                                                     *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    This structure models the size of a bitmap strike (i.e., a bitmap  *)
+  (*    instance of the font for a given resolution) in a fixed-size font  *)
+  (*    face.  It is used for the `available_sizes' field of the           *)
+  (*    @FT_FaceRec structure.                                             *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    height :: The (vertical) baseline-to-baseline distance in pixels.  *)
+  (*              It makes most sense to define the height of a bitmap     *)
+  (*              font in this way.                                        *)
+  (*                                                                       *)
+  (*    width  :: The average width of the font (in pixels).  Since the    *)
+  (*              algorithms to compute this value are different for the   *)
+  (*              various bitmap formats, it can only give an additional   *)
+  (*              hint if the `height' value isn't sufficient to select    *)
+  (*              the proper font.  For monospaced fonts the average width *)
+  (*              is the same as the maximum width.                        *)
+  (*                                                                       *)
+  (*    size   :: The point size in 26.6 fractional format this font shall *)
+  (*              represent (for a given vertical resolution).             *)
+  (*                                                                       *)
+  (*    x_ppem :: The horizontal ppem value (in 26.6 fractional format).   *)
+  (*                                                                       *)
+  (*    y_ppem :: The vertical ppem value (in 26.6 fractional format).     *)
+  (*              Usually, this is the `nominal' pixel height of the font. *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    The values in this structure are taken from the bitmap font.  If   *)
+  (*    the font doesn't provide a parameter it is set to zero to indicate *)
+  (*    that the information is not available.                             *)
+  (*                                                                       *)
+  (*    The following formula converts from dpi to ppem:                   *)
+  (*                                                                       *)
+  (*      ppem = size * dpi / 72                                           *)
+  (*                                                                       *)
+  (*    where `size' is in points.                                         *)
+  (*                                                                       *)
+  (*    Windows FNT:                                                       *)
+  (*      The `size' parameter is not reliable: There exist fonts (e.g.,   *)
+  (*      app850.fon) which have a wrong size for some subfonts; x_ppem    *)
+  (*      and y_ppem are thus set equal to pixel width and height given in *)
+  (*      in the Windows FNT header.                                       *)
+  (*                                                                       *)
+  (*    TrueType embedded bitmaps:                                         *)
+  (*      `size', `width', and `height' values are not contained in the    *)
+  (*      bitmap strike itself.  They are computed from the global font    *)
+  (*      parameters.                                                      *)
+  (*                                                                       *)
+  PFT_Bitmap_Size = ^FT_Bitmap_Size;
+  FT_Bitmap_Size = record
+    height,
+    width  : FT_Short;
+    
+    size:    FT_Pos;
+
+    x_ppem:  FT_Pos;
+    y_ppem:  FT_Pos;
+  end;
+
+  PAFT_Bitmap_Size = ^AFT_Bitmap_Size;
+  AFT_Bitmap_Size = array[0..High(Word)] of FT_Bitmap_Size;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Face                                                            *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A handle to a given typographic face object.  A face object models *)
+  (*    a given typeface, in a given style.                                *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Each face object also owns a single @FT_GlyphSlot object, as well  *)
+  (*    as one or more @FT_Size objects.                                   *)
+  (*                                                                       *)
+  (*    Use @FT_New_Face or @FT_Open_Face to create a new face object from *)
+  (*    a given filepathname or a custom input stream.                     *)
+  (*                                                                       *)
+  (*    Use @FT_Done_Face to destroy it (along with its slot and sizes).   *)
+  (*                                                                       *)
+  (* <Also>                                                                *)
+  (*    The @FT_FaceRec details the publicly accessible fields of a given  *)
+  (*    face object.                                                       *)
+  (*                                                                       *)
+  FT_Face = ^FT_FaceRec;
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_CharMap                                                         *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A handle to a given character map.  A charmap is used to translate *)
+  (*    character codes in a given encoding into glyph indexes for its     *)
+  (*    parent's face.  Some font formats may provide several charmaps per *)
+  (*    font.                                                              *)
+  (*                                                                       *)
+  (*    Each face object owns zero or more charmaps, but only one of them  *)
+  (*    can be "active" and used by @FT_Get_Char_Index or @FT_Load_Char.   *)
+  (*                                                                       *)
+  (*    The list of available charmaps in a face is available through the  *)
+  (*    "face->num_charmaps" and "face->charmaps" fields of @FT_FaceRec.   *)
+  (*                                                                       *)
+  (*    The currently active charmap is available as "face->charmap".      *)
+  (*    You should call @FT_Set_Charmap to change it.                      *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    When a new face is created (either through @FT_New_Face or         *)
+  (*    @FT_Open_Face), the library looks for a Unicode charmap within     *)
+  (*    the list and automatically activates it.                           *)
+  (*                                                                       *)
+  (* <Also>                                                                *)
+  (*    The @FT_CharMapRec details the publicly accessible fields of a     *)
+  (*    given character map.                                               *)
+  (*                                                                       *)
+  PFT_CharMap = ^FT_CharMap;
+  FT_CharMap = ^FT_CharMapRec;
+
+  PAFT_CharMap = ^FT_CharMap;
+  AFT_CharMap = array[0..High(Word)] of FT_CharMap;
+
+
+
+
+
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_SubGlyph                                                        *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    The subglyph structure is an internal object used to describe      *)
+  (*    subglyphs (for example, in the case of composites).                *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    The subglyph implementation is not part of the high-level API,     *)
+  (*    hence the forward structure declaration.                           *)
+  (*                                                                       *)
+  FT_SubGlyph = ^FT_SubGlyphRec;
+  FT_SubGlyphRec = record // internal
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_GlyphSlotRec                                                    *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    FreeType root glyph slot class structure.  A glyph slot is a       *)
+  (*    container where individual glyphs can be loaded, be they           *)
+  (*    vectorial or bitmap/graymaps.                                      *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    library           :: A handle to the FreeType library instance     *)
+  (*                         this slot belongs to.                         *)
+  (*                                                                       *)
+  (*    face              :: A handle to the parent face object.           *)
+  (*                                                                       *)
+  (*    next              :: In some cases (like some font tools), several *)
+  (*                         glyph slots per face object can be a good     *)
+  (*                         thing.  As this is rare, the glyph slots are  *)
+  (*                         listed through a direct, single-linked list   *)
+  (*                         using its `next' field.                       *)
+  (*                                                                       *)
+  (*    generic           :: A typeless pointer which is unused by the     *)
+  (*                         FreeType library or any of its drivers.  It   *)
+  (*                         can be used by client applications to link    *)
+  (*                         their own data to each glyph slot object.     *)
+  (*                                                                       *)
+  (*    metrics           :: The metrics of the last loaded glyph in the   *)
+  (*                         slot.  The returned values depend on the last *)
+  (*                         load flags (see the @FT_Load_Glyph API        *)
+  (*                         function) and can be expressed either in 26.6 *)
+  (*                         fractional pixels or font units.              *)
+  (*                                                                       *)
+  (*                         Note that even when the glyph image is        *)
+  (*                         transformed, the metrics are not.             *)
+  (*                                                                       *)
+  (*    linearHoriAdvance :: For scalable formats only, this field holds   *)
+  (*                         the linearly scaled horizontal advance width  *)
+  (*                         for the glyph (i.e. the scaled and unhinted   *)
+  (*                         value of the hori advance).  This can be      *)
+  (*                         important to perform correct WYSIWYG layout.  *)
+  (*                                                                       *)
+  (*                         Note that this value is expressed by default  *)
+  (*                         in 16.16 pixels. However, when the glyph is   *)
+  (*                         loaded with the FT_LOAD_LINEAR_DESIGN flag,   *)
+  (*                         this field contains simply the value of the   *)
+  (*                         advance in original font units.               *)
+  (*                                                                       *)
+  (*    linearVertAdvance :: For scalable formats only, this field holds   *)
+  (*                         the linearly scaled vertical advance height   *)
+  (*                         for the glyph.  See linearHoriAdvance for     *)
+  (*                         comments.                                     *)
+  (*                                                                       *)
+  (*    advance           :: This is the transformed advance width for the *)
+  (*                         glyph.                                        *)
+  (*                                                                       *)
+  (*    format            :: This field indicates the format of the image  *)
+  (*                         contained in the glyph slot.  Typically       *)
+  (*                         FT_GLYPH_FORMAT_BITMAP,                       *)
+  (*                         FT_GLYPH_FORMAT_OUTLINE, and                  *)
+  (*                         FT_GLYPH_FORMAT_COMPOSITE, but others are     *)
+  (*                         possible.                                     *)
+  (*                                                                       *)
+  (*    bitmap            :: This field is used as a bitmap descriptor     *)
+  (*                         when the slot format is                       *)
+  (*                         FT_GLYPH_FORMAT_BITMAP.  Note that the        *)
+  (*                         address and content of the bitmap buffer can  *)
+  (*                         change between calls of @FT_Load_Glyph and a  *)
+  (*                         few other functions.                          *)
+  (*                                                                       *)
+  (*    bitmap_left       :: This is the bitmap's left bearing expressed   *)
+  (*                         in integer pixels.  Of course, this is only   *)
+  (*                         valid if the format is                        *)
+  (*                         FT_GLYPH_FORMAT_BITMAP.                       *)
+  (*                                                                       *)
+  (*    bitmap_top        :: This is the bitmap's top bearing expressed in *)
+  (*                         integer pixels.  Remember that this is the    *)
+  (*                         distance from the baseline to the top-most    *)
+  (*                         glyph scanline, upwards y-coordinates being   *)
+  (*                         *positive*.                                   *)
+  (*                                                                       *)
+  (*    outline           :: The outline descriptor for the current glyph  *)
+  (*                         image if its format is                        *)
+  (*                         FT_GLYPH_FORMAT_OUTLINE.                      *)
+  (*                                                                       *)
+  (*    num_subglyphs     :: The number of subglyphs in a composite glyph. *)
+  (*                         This field is only valid for the composite    *)
+  (*                         glyph format that should normally only be     *)
+  (*                         loaded with the @FT_LOAD_NO_RECURSE flag.     *)
+  (*                         For now this is internal to FreeType.         *)
+  (*                                                                       *)
+  (*    subglyphs         :: An array of subglyph descriptors for          *)
+  (*                         composite glyphs.  There are `num_subglyphs'  *)
+  (*                         elements in there.  Currently internal to     *)
+  (*                         FreeType.                                     *)
+  (*                                                                       *)
+  (*    control_data      :: Certain font drivers can also return the      *)
+  (*                         control data for a given glyph image (e.g.    *)
+  (*                         TrueType bytecode, Type 1 charstrings, etc.). *)
+  (*                         This field is a pointer to such data.         *)
+  (*                                                                       *)
+  (*    control_len       :: This is the length in bytes of the control    *)
+  (*                         data.                                         *)
+  (*                                                                       *)
+  (*    other             :: Really wicked formats can use this pointer to *)
+  (*                         present their own glyph image to client apps. *)
+  (*                         Note that the app will need to know about the *)
+  (*                         image format.                                 *)
+  (*                                                                       *)
+  (*    lsb_delta         :: The difference between hinted and unhinted    *)
+  (*                         left side bearing while autohinting is        *)
+  (*                         active.  Zero otherwise.                      *)
+  (*                                                                       *)
+  (*    rsb_delta         :: The difference between hinted and unhinted    *)
+  (*                         right side bearing while autohinting is       *)
+  (*                         active.  Zero otherwise.                      *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    If @FT_Load_Glyph is called with default flags (see                *)
+  (*    @FT_LOAD_DEFAULT) the glyph image is loaded in the glyph slot in   *)
+  (*    its native format (e.g. a vectorial outline for TrueType and       *)
+  (*    Type 1 formats).                                                   *)
+  (*                                                                       *)
+  (*    This image can later be converted into a bitmap by calling         *)
+  (*    @FT_Render_Glyph.  This function finds the current renderer for    *)
+  (*    the native image's format then invokes it.                         *)
+  (*                                                                       *)
+  (*    The renderer is in charge of transforming the native image through *)
+  (*    the slot's face transformation fields, then convert it into a      *)
+  (*    bitmap that is returned in `slot->bitmap'.                         *)
+  (*                                                                       *)
+  (*    Note that `slot->bitmap_left' and `slot->bitmap_top' are also used *)
+  (*    to specify the position of the bitmap relative to the current pen  *)
+  (*    position (e.g. coordinates [0,0] on the baseline).  Of course,     *)
+  (*    `slot->format' is also changed to `FT_GLYPH_FORMAT_BITMAP' .       *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Here a small pseudo code fragment which shows how to use           *)
+  (*    `lsb_delta' and `rsb_delta':                                       *)
+  (*                                                                       *)
+  (*    {                                                                  *)
+  (*      FT_Pos  origin_x       = 0;                                      *)
+  (*      FT_Pos  prev_rsb_delta = 0;                                      *)
+  (*                                                                       *)
+  (*                                                                       *)
+  (*      for all glyphs do                                                *)
+  (*        <compute kern between current and previous glyph and add it to *)
+  (*         `origin_x'>                                                   *)
+  (*                                                                       *)
+  (*        <load glyph with `FT_Load_Glyph'>                              *)
+  (*                                                                       *)
+  (*        if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 )           *)
+  (*          origin_x -= 64;                                              *)
+  (*        else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 )      *)
+  (*          origin_x += 64;                                              *)
+  (*                                                                       *)
+  (*        prev_rsb_delta = face->glyph->rsb_delta;                       *)
+  (*                                                                       *)
+  (*        <save glyph image, or render glyph, or ...>                    *)
+  (*                                                                       *)
+  (*        origin_x += face->glyph->advance.x;                            *)
+  (*      endfor                                                           *)
+  (*    }                                                                  *)
+  (*                                                                       *)
+  FT_GlyphSlotRec = record
+    alibrary : FT_Library;
+
+    face  : FT_Face;
+    next  : FT_GlyphSlot;
+    flags : FT_UInt;
+
+    generic : FT_Generic;
+    metrics : FT_Glyph_Metrics;
+
+    linearHoriAdvance ,
+    linearVertAdvance : FT_Fixed;
+
+    advance : FT_Vector;
+    format  : FT_Glyph_Format;
+    bitmap  : FT_Bitmap;
+
+    bitmap_left ,
+    bitmap_top  : FT_Int;
+
+    outline : FT_Outline;
+
+    num_subglyphs : FT_UInt;
+    subglyphs     : FT_SubGlyph;
+    
+    control_data  : pointer;
+    control_len   : clong;
+
+    lsb_delta: FT_Pos;
+    rsb_delta: FT_Pos;
+
+    other : pointer;
+    
+    //internal: FT_Slot_Internal;
+  end;
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Size_Metrics                                                    *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    The size metrics structure returned scaled important distances for *)
+  (*    a given size object.                                               *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    x_ppem       :: The character width, expressed in integer pixels.  *)
+  (*                    This is the width of the EM square expressed in    *)
+  (*                    pixels, hence the term `ppem' (pixels per EM).     *)
+  (*                                                                       *)
+  (*    y_ppem       :: The character height, expressed in integer pixels. *)
+  (*                    This is the height of the EM square expressed in   *)
+  (*                    pixels, hence the term `ppem' (pixels per EM).     *)
+  (*                                                                       *)
+  (*    x_scale      :: A simple 16.16 fixed point format coefficient used *)
+  (*                    to scale horizontal distances expressed in font    *)
+  (*                    units to fractional (26.6) pixel coordinates.      *)
+  (*                                                                       *)
+  (*    y_scale      :: A simple 16.16 fixed point format coefficient used *)
+  (*                    to scale vertical distances expressed in font      *)
+  (*                    units to fractional (26.6) pixel coordinates.      *)
+  (*                                                                       *)
+  (*    ascender     :: The ascender, expressed in 26.6 fixed point        *)
+  (*                    pixels.  Positive for ascenders above the          *)
+  (*                    baseline.                                          *)
+  (*                                                                       *)
+  (*    descender    :: The descender, expressed in 26.6 fixed point       *)
+  (*                    pixels.  Negative for descenders below the         *)
+  (*                    baseline.                                          *)
+  (*                                                                       *)
+  (*    height       :: The text height, expressed in 26.6 fixed point     *)
+  (*                    pixels.  Always positive.                          *)
+  (*                                                                       *)
+  (*    max_advance  :: Maximum horizontal advance, expressed in 26.6      *)
+  (*                    fixed point pixels.  Always positive.              *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    For scalable fonts, the values of `ascender', `descender', and     *)
+  (*    `height' are scaled versions of `face->ascender',                  *)
+  (*    `face->descender', and `face->height', respectively.               *)
+  (*                                                                       *)
+  (*    Unfortunately, due to glyph hinting, these values might not be     *)
+  (*    exact for certain fonts.  They thus must be treated as unreliable  *)
+  (*    with an error margin of at least one pixel!                        *)
+  (*                                                                       *)
+  (*    Indeed, the only way to get the exact pixel ascender and descender *)
+  (*    is to render _all_ glyphs.  As this would be a definite            *)
+  (*    performance hit, it is up to client applications to perform such   *)
+  (*    computations.                                                      *)
+  (*                                                                       *)
+  FT_Size_Metrics = record
+    x_ppem,                   (* horizontal pixels per EM               *)
+    y_ppem:      FT_UShort;   (* vertical pixels per EM                 *)
+    x_scale,                  (* scaling values used to convert font    *)
+    y_scale:     FT_Fixed;    (* units to 26.6 fractional pixels        *)
+
+    ascender,                 (* ascender in 26.6 frac. pixels          *)
+    descender:   FT_Pos;      (* descender in 26.6 frac. pixels         *)
+    height:      FT_Pos;      (* text height in 26.6 frac. pixels       *)
+    max_advance: FT_Pos;      (* max horizontal advance, in 26.6 pixels *)
+  end;
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Size                                                            *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A handle to a given size object.  Such an object models the data   *)
+  (*    that depends on the current _resolution_ and _character size_ in a *)
+  (*    given @FT_Face.                                                    *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Each face object owns one or more sizes.  There is however a       *)
+  (*    single _active_ size for the face at any time that will be used by *)
+  (*    functions like @FT_Load_Glyph, @FT_Get_Kerning, etc.               *)
+  (*                                                                       *)
+  (*    You can use the @FT_Activate_Size API to change the current        *)
+  (*    active size of any given face.                                     *)
+  (*                                                                       *)
+  (* <Also>                                                                *)
+  (*    The @FT_SizeRec structure details the publicly accessible fields   *)
+  (*    of a given face object.                                            *)
+  (*                                                                       *)
+  FT_Size = ^FT_SizeRec;
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_SizeRec                                                         *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    FreeType root size class structure.  A size object models the      *)
+  (*    resolution and pointsize dependent data of a given face.           *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    face    :: Handle to the parent face object.                       *)
+  (*                                                                       *)
+  (*    generic :: A typeless pointer, which is unused by the FreeType     *)
+  (*               library or any of its drivers.  It can be used by       *)
+  (*               client applications to link their own data to each size *)
+  (*               object.                                                 *)
+  (*                                                                       *)
+  (*    metrics :: Metrics for this size object.  This field is read-only. *)
+  (*                                                                       *)
+  FT_SizeRec = record
+    face    : FT_Face;
+    generic : FT_Generic;
+    metrics : FT_Size_Metrics;
+    //internal : FT_Size_Internal;
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_FaceRec                                                         *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    FreeType root face class structure.  A face object models the      *)
+  (*    resolution and point-size independent data found in a font file.   *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    num_faces           :: In the case where the face is located in a  *)
+  (*                           collection (i.e., a file which embeds       *)
+  (*                           several faces), this is the total number of *)
+  (*                           faces found in the resource.  1 by default. *)
+  (*                           Accessing non-existent face indices causes  *)
+  (*                           an error.                                   *)
+  (*                                                                       *)
+  (*    face_index          :: The index of the face in its font file.     *)
+  (*                           Usually, this is 0 for all normal font      *)
+  (*                           formats.  It can be > 0 in the case of      *)
+  (*                           collections (which embed several fonts in a *)
+  (*                           single resource/file).                      *)
+  (*                                                                       *)
+  (*    face_flags          :: A set of bit flags that give important      *)
+  (*                           information about the face; see the         *)
+  (*                           @FT_FACE_FLAG_XXX constants for details.    *)
+  (*                                                                       *)
+  (*    style_flags         :: A set of bit flags indicating the style of  *)
+  (*                           the face (i.e., italic, bold, underline,    *)
+  (*                           etc).  See the @FT_STYLE_FLAG_XXX           *)
+  (*                           constants.                                  *)
+  (*                                                                       *)
+  (*    num_glyphs          :: The total number of glyphs in the face.     *)
+  (*                                                                       *)
+  (*    family_name         :: The face's family name.  This is an ASCII   *)
+  (*                           string, usually in English, which describes *)
+  (*                           the typeface's family (like `Times New      *)
+  (*                           Roman', `Bodoni', `Garamond', etc).  This   *)
+  (*                           is a least common denominator used to list  *)
+  (*                           fonts.  Some formats (TrueType & OpenType)  *)
+  (*                           provide localized and Unicode versions of   *)
+  (*                           this string.  Applications should use the   *)
+  (*                           format specific interface to access them.   *)
+  (*                                                                       *)
+  (*    style_name          :: The face's style name.  This is an ASCII    *)
+  (*                           string, usually in English, which describes *)
+  (*                           the typeface's style (like `Italic',        *)
+  (*                           `Bold', `Condensed', etc).  Not all font    *)
+  (*                           formats provide a style name, so this field *)
+  (*                           is optional, and can be set to NULL.  As    *)
+  (*                           for `family_name', some formats provide     *)
+  (*                           localized/Unicode versions of this string.  *)
+  (*                           Applications should use the format specific *)
+  (*                           interface to access them.                   *)
+  (*                                                                       *)
+  (*    num_fixed_sizes     :: The number of fixed sizes available in this *)
+  (*                           face.  This should be set to 0 for scalable *)
+  (*                           fonts, unless its face includes a set of    *)
+  (*                           glyphs (called a `strike') for the          *)
+  (*                           specified sizes.                            *)
+  (*                                                                       *)
+  (*    available_sizes     :: An array of sizes specifying the available  *)
+  (*                           bitmap/graymap sizes that are contained in  *)
+  (*                           in the font face.  Should be set to NULL if *)
+  (*                           the field `num_fixed_sizes' is set to 0.    *)
+  (*                                                                       *)
+  (*    num_charmaps        :: The total number of character maps in the   *)
+  (*                           face.                                       *)
+  (*                                                                       *)
+  (*    charmaps            :: A table of pointers to the face's charmaps. *)
+  (*                           Used to scan the list of available charmaps *)
+  (*                           -- this table might change after a call to  *)
+  (*                           @FT_Attach_File or @FT_Attach_Stream (e.g.  *)
+  (*                           if used to hook an additional encoding or   *)
+  (*                           CMap to the face object).                   *)
+  (*                                                                       *)
+  (*    generic             :: A field reserved for client uses.  See the  *)
+  (*                           @FT_Generic type description.               *)
+  (*                                                                       *)
+  (*    bbox                :: The font bounding box.  Coordinates are     *)
+  (*                           expressed in font units (see units_per_EM). *)
+  (*                           The box is large enough to contain any      *)
+  (*                           glyph from the font.  Thus, bbox.yMax can   *)
+  (*                           be seen as the `maximal ascender',          *)
+  (*                           bbox.yMin as the `minimal descender', and   *)
+  (*                           the maximal glyph width is given by         *)
+  (*                           `bbox.xMax-bbox.xMin' (not to be confused   *)
+  (*                           with the maximal _advance_width_).  Only    *)
+  (*                           relevant for scalable formats.              *)
+  (*                                                                       *)
+  (*    units_per_EM        :: The number of font units per EM square for  *)
+  (*                           this face.  This is typically 2048 for      *)
+  (*                           TrueType fonts, 1000 for Type1 fonts, and   *)
+  (*                           should be set to the (unrealistic) value 1  *)
+  (*                           for fixed-sizes fonts.  Only relevant for   *)
+  (*                           scalable formats.                           *)
+  (*                                                                       *)
+  (*    ascender            :: The face's ascender is the vertical         *)
+  (*                           distance from the baseline to the topmost   *)
+  (*                           point of any glyph in the face.  This       *)
+  (*                           field's value is positive, expressed in     *)
+  (*                           font units.  Some font designs use a value  *)
+  (*                           different from `bbox.yMax'.  Only relevant  *)
+  (*                           for scalable formats.                       *)
+  (*                                                                       *)
+  (*    descender           :: The face's descender is the vertical        *)
+  (*                           distance from the baseline to the           *)
+  (*                           bottommost point of any glyph in the face.  *)
+  (*                           This field's value is *negative* for values *)
+  (*                           below the baseline.  It is expressed in     *)
+  (*                           font units.  Some font designs use a value  *)
+  (*                           different from `bbox.yMin'.  Only relevant  *)
+  (*                           for scalable formats.                       *)
+  (*                                                                       *)
+  (*    height              :: The face's height is the vertical distance  *)
+  (*                           from one baseline to the next when writing  *)
+  (*                           several lines of text.  Its value is always *)
+  (*                           positive, expressed in font units.  The     *)
+  (*                           value can be computed as                    *)
+  (*                           `ascender+descender+line_gap' where the     *)
+  (*                           value of `line_gap' is also called          *)
+  (*                           `external leading'.  Only relevant for      *)
+  (*                           scalable formats.                           *)
+  (*                                                                       *)
+  (*    max_advance_width   :: The maximal advance width, in font units,   *)
+  (*                           for all glyphs in this face.  This can be   *)
+  (*                           used to make word wrapping computations     *)
+  (*                           faster.  Only relevant for scalable         *)
+  (*                           formats.                                    *)
+  (*                                                                       *)
+  (*    max_advance_height  :: The maximal advance height, in font units,  *)
+  (*                           for all glyphs in this face.  This is only  *)
+  (*                           relevant for vertical layouts, and should   *)
+  (*                           be set to the `height' for fonts that do    *)
+  (*                           not provide vertical metrics.  Only         *)
+  (*                           relevant for scalable formats.              *)
+  (*                                                                       *)
+  (*    underline_position  :: The position, in font units, of the         *)
+  (*                           underline line for this face.  It's the     *)
+  (*                           center of the underlining stem.  Only       *)
+  (*                           relevant for scalable formats.              *)
+  (*                                                                       *)
+  (*    underline_thickness :: The thickness, in font units, of the        *)
+  (*                           underline for this face.  Only relevant for *)
+  (*                           scalable formats.                           *)
+  (*                                                                       *)
+  (*    glyph               :: The face's associated glyph slot(s).  This  *)
+  (*                           object is created automatically with a new  *)
+  (*                           face object.  However, certain kinds of     *)
+  (*                           applications (mainly tools like converters) *)
+  (*                           can need more than one slot to ease their   *)
+  (*                           task.                                       *)
+  (*                                                                       *)
+  (*    size                :: The current active size for this face.      *)
+  (*                                                                       *)
+  (*    charmap             :: The current active charmap for this face.   *)
+  (*                                                                       *)
+  FT_FaceRec = record
+    num_faces       : FT_Long;
+    face_index      : FT_Long;
+
+    face_flags      : FT_Long;
+    style_flags     : FT_Long;
+
+    num_glyphs      : FT_Long;
+
+    family_name     : PFT_String;
+    style_name      : PFT_String;
+
+    num_fixed_sizes : FT_Int;
+    available_sizes : PAFT_Bitmap_Size; // is array
+
+    num_charmaps    : FT_Int;
+    charmaps        : PAFT_CharMap;    // is array
+
+    generic         : FT_Generic;
+
+    (*# the following are only relevant to scalable outlines *)
+    bbox            : FT_BBox;
+
+    units_per_EM    : FT_UShort;
+    ascender        : FT_Short;
+    descender       : FT_Short;
+    height          : FT_Short;
+
+    max_advance_width   : FT_Short;
+    max_advance_height  : FT_Short;
+    
+    underline_position  : FT_Short;
+    underline_thickness : FT_Short;
+
+    glyph           : FT_GlyphSlot;
+    size            : FT_Size;
+    charmap         : FT_CharMap;
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_CharMapRec                                                      *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    The base charmap structure.                                        *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    face        :: A handle to the parent face object.                 *)
+  (*                                                                       *)
+  (*    encoding    :: An @FT_Encoding tag identifying the charmap.  Use   *)
+  (*                   this with @FT_Select_Charmap.                       *)
+  (*                                                                       *)
+  (*    platform_id :: An ID number describing the platform for the        *)
+  (*                   following encoding ID.  This comes directly from    *)
+  (*                   the TrueType specification and should be emulated   *)
+  (*                   for other formats.                                  *)
+  (*                                                                       *)
+  (*    encoding_id :: A platform specific encoding number.  This also     *)
+  (*                   comes from the TrueType specification and should be *)
+  (*                   emulated similarly.                                 *)
+  (*                                                                       *)
+  FT_CharMapRec = record
+    face        : FT_Face;
+    encoding    : FT_Encoding;
+    platform_id : FT_UShort;
+    encoding_id : FT_UShort;
+  end;
+
+
+{$I ftconfig.inc}
+{$I fttypes.inc}
+{$I ftimage.inc}
+{$I ftglyph.inc}
+{$I ftstroke.inc}
+{$I ftoutln.inc} 
+
+
+{ GLOBAL PROCEDURES }
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* @macro:                                                               *)
+  (*    FT_HAS_KERNING( face )                                             *)
+  (*                                                                       *)
+  (* @description:                                                         *)
+  (*    A macro that returns true whenever a face object contains kerning  *)
+  (*    data that can be accessed with @FT_Get_Kerning.                    *)
+  (*                                                                       *)
+  function  FT_HAS_KERNING(face : FT_Face ) : cbool;
+
+  
+  (*************************************************************************)
+  (*                                                                       *)
+  (* @macro:                                                               *)
+  (*    FT_IS_SCALABLE( face )                                             *)
+  (*                                                                       *)
+  (* @description:                                                         *)
+  (*    A macro that returns true whenever a face object contains a        *)
+  (*    scalable font face (true for TrueType, Type 1, CID, and            *)
+  (*    OpenType/CFF font formats.                                         *)
+  (*                                                                       *)
+  function  FT_IS_SCALABLE(face : FT_Face ) : cbool;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Init_FreeType                                                   *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Initializes a new FreeType library object.  The set of modules     *)
+  (*    that are registered by this function is determined at build time.  *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    alibrary :: A handle to a new library object.                      *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  function  FT_Init_FreeType(out alibrary : FT_Library ) : FT_Error;
+    cdecl; external ft_lib name 'FT_Init_FreeType';
+
+ (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Done_FreeType                                                   *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Destroys a given FreeType library object and all of its childs,    *)
+  (*    including resources, drivers, faces, sizes, etc.                   *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    library :: A handle to the target library object.                  *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  function  FT_Done_FreeType(alibrary : FT_Library ) : FT_Error;
+    cdecl; external ft_lib name 'FT_Done_FreeType';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Attach_File                                                     *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    `Attaches' a given font file to an existing face.  This is usually *)
+  (*    to read additional information for a single face object.  For      *)
+  (*    example, it is used to read the AFM files that come with Type 1    *)
+  (*    fonts in order to add kerning data and other metrics.              *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    face         :: The target face object.                            *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    filepathname :: An 8-bit pathname naming the `metrics' file.       *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    If your font file is in memory, or if you want to provide your     *)
+  (*    own input stream object, use @FT_Attach_Stream.                    *)
+  (*                                                                       *)
+  (*    The meaning of the `attach' action (i.e., what really happens when *)
+  (*    the new file is read) is not fixed by FreeType itself.  It really  *)
+  (*    depends on the font format (and thus the font driver).             *)
+  (*                                                                       *)
+  (*    Client applications are expected to know what they are doing       *)
+  (*    when invoking this function.  Most drivers simply do not implement *)
+  (*    file attachments.                                                  *)
+  (*                                                                       *)
+  function  FT_Attach_File(face : FT_Face; filepathname : PChar ) : FT_Error;
+    cdecl; external ft_lib name 'FT_Attach_File';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_New_Memory_Face                                                 *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Creates a new face object from a given resource and typeface index *)
+  (*    using a font file already loaded into memory.                      *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    library    :: A handle to the library resource.                    *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    file_base  :: A pointer to the beginning of the font data.         *)
+  (*                                                                       *)
+  (*    file_size  :: The size of the memory chunk used by the font data.  *)
+  (*                                                                       *)
+  (*    face_index :: The index of the face within the resource.  The      *)
+  (*                  first face has index 0.                              *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    aface      :: A handle to a new face object.                       *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    The font data bytes are used _directly_ by the @FT_Face object.    *)
+  (*    This means that they are not copied, and that the client is        *)
+  (*    responsible for releasing/destroying them _after_ the              *)
+  (*    corresponding call to @FT_Done_Face .                              *)
+  (*                                                                       *)
+  (*    Unlike FreeType 1.x, this function automatically creates a glyph   *)
+  (*    slot for the face object which can be accessed directly through    *)
+  (*    `face->glyph'.                                                     *)
+  (*                                                                       *)
+  (*    @FT_New_Memory_Face can be used to determine and/or check the font *)
+  (*    format of a given font resource.  If the `face_index' field is     *)
+  (*    negative, the function will _not_ return any face handle in        *)
+  (*    `aface'; the return value is 0 if the font format is recognized,   *)
+  (*    or non-zero otherwise.                                             *)
+  (*                                                                       *)
+  function  FT_New_Memory_Face(
+            library_ : FT_Library;
+            file_base : PFT_Byte;
+            file_size ,
+            face_index : FT_Long;
+            out aface :  FT_Face ) : FT_Error;
+    cdecl; external ft_lib name 'FT_New_Memory_Face';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_New_Face                                                        *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Creates a new face object from a given resource and typeface index *)
+  (*    using a pathname to the font file.                                 *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    library    :: A handle to the library resource.                    *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    pathname   :: A path to the font file.                             *)
+  (*                                                                       *)
+  (*    face_index :: The index of the face within the resource.  The      *)
+  (*                  first face has index 0.                              *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    aface      :: A handle to a new face object.                       *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Unlike FreeType 1.x, this function automatically creates a glyph   *)
+  (*    slot for the face object which can be accessed directly through    *)
+  (*    `face->glyph'.                                                     *)
+  (*                                                                       *)
+  (*    @FT_New_Face can be used to determine and/or check the font format *)
+  (*    of a given font resource.  If the `face_index' field is negative,  *)
+  (*    the function will _not_ return any face handle in `aface';  the    *)
+  (*    return value is 0 if the font format is recognized, or non-zero    *)
+  (*    otherwise.                                                         *)
+  (*                                                                       *)
+  (*    Each new face object created with this function also owns a        *)
+  (*    default @FT_Size object, accessible as `face->size'.               *)
+  (*                                                                       *)
+  function  FT_New_Face(
+            library_ : FT_Library;
+            filepathname : PChar;
+            face_index : FT_Long;
+            out aface : FT_Face ) : FT_Error;
+    cdecl; external ft_lib name 'FT_New_Face';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Done_Face                                                       *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Discards a given face object, as well as all of its child slots    *)
+  (*    and sizes.                                                         *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    face :: A handle to a target face object.                          *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  function  FT_Done_Face(face : FT_Face ) : FT_Error;
+    cdecl; external ft_lib name 'FT_Done_Face';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Select_Charmap                                                  *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Selects a given charmap by its encoding tag (as listed in          *)
+  (*    `freetype.h').                                                     *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    face     :: A handle to the source face object.                    *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    encoding :: A handle to the selected charmap.                      *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    This function will return an error if no charmap in the face       *)
+  (*    corresponds to the encoding queried here.                          *)
+  (*                                                                       *)
+  function  FT_Select_Charmap(face : FT_Face; encoding : FT_Encoding ) : FT_Error;
+    cdecl; external ft_lib name 'FT_Select_Charmap';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Get_Char_Index                                                  *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Returns the glyph index of a given character code.  This function  *)
+  (*    uses a charmap object to do the translation.                       *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    face     :: A handle to the source face object.                    *)
+  (*                                                                       *)
+  (*    charcode :: The character code.                                    *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    The glyph index.  0 means `undefined character code'.              *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    FreeType computes its own glyph indices which are not necessarily  *)
+  (*    the same as used in the font in case the font is based on glyph    *)
+  (*    indices.  Reason for this behaviour is to assure that index 0 is   *)
+  (*    never used, representing the missing glyph.                        *)
+  (*                                                                       *)
+  function  FT_Get_Char_Index(face : FT_Face; charcode : FT_ULong ) : FT_UInt;
+    cdecl; external ft_lib name 'FT_Get_Char_Index';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Load_Glyph                                                      *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A function used to load a single glyph within a given glyph slot,  *)
+  (*    for a given size.                                                  *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    face        :: A handle to the target face object where the glyph  *)
+  (*                   will be loaded.                                     *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    glyph_index :: The index of the glyph in the font file.  For       *)
+  (*                   CID-keyed fonts (either in PS or in CFF format)     *)
+  (*                   this argument specifies the CID value.              *)
+  (*                                                                       *)
+  (*    load_flags  :: A flag indicating what to load for this glyph.  The *)
+  (*                   @FT_LOAD_XXX constants can be used to control the   *)
+  (*                   glyph loading process (e.g., whether the outline    *)
+  (*                   should be scaled, whether to load bitmaps or not,   *)
+  (*                   whether to hint the outline, etc).                  *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    If the glyph image is not a bitmap, and if the bit flag            *)
+  (*    FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be         *)
+  (*    transformed with the information passed to a previous call to      *)
+  (*    @FT_Set_Transform.                                                 *)
+  (*                                                                       *)
+  (*    Note that this also transforms the `face.glyph.advance' field, but *)
+  (*    *not* the values in `face.glyph.metrics'.                          *)
+  (*                                                                       *)
+  function  FT_Load_Glyph(
+            face : FT_Face;
+            glyph_index : FT_UInt ;
+            load_flags : FT_Int32 ) : FT_Error;
+    cdecl; external ft_lib name 'FT_Load_Glyph';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Render_Glyph                                                    *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Converts a given glyph image to a bitmap.  It does so by           *)
+  (*    inspecting the glyph image format, find the relevant renderer, and *)
+  (*    invoke it.                                                         *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    slot        :: A handle to the glyph slot containing the image to  *)
+  (*                   convert.                                            *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    render_mode :: This is the render mode used to render the glyph    *)
+  (*                   image into a bitmap.  See FT_Render_Mode for a list *)
+  (*                   of possible values.                                 *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  function  FT_Render_Glyph(slot : FT_GlyphSlot; render_mode : FT_Render_Mode ) : FT_Error;
+    cdecl; external ft_lib name 'FT_Render_Glyph';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Enum>                                                                *)
+  (*    FT_Kerning_Mode                                                    *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    An enumeration used to specify which kerning values to return in   *)
+  (*    @FT_Get_Kerning.                                                   *)
+  (*                                                                       *)
+  (* <Values>                                                              *)
+  (*    FT_KERNING_DEFAULT  :: Return scaled and grid-fitted kerning       *)
+  (*                           distances (value is 0).                     *)
+  (*                                                                       *)
+  (*    FT_KERNING_UNFITTED :: Return scaled but un-grid-fitted kerning    *)
+  (*                           distances.                                  *)
+  (*                                                                       *)
+  (*    FT_KERNING_UNSCALED :: Return the kerning vector in original font  *)
+  (*                           units.                                      *)
+  (*                                                                       *)
+const
+  FT_KERNING_DEFAULT  = 0;
+  FT_KERNING_UNFITTED = 1;
+  FT_KERNING_UNSCALED = 2;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Get_Kerning                                                     *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Returns the kerning vector between two glyphs of a same face.      *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    face        :: A handle to a source face object.                   *)
+  (*                                                                       *)
+  (*    left_glyph  :: The index of the left glyph in the kern pair.       *)
+  (*                                                                       *)
+  (*    right_glyph :: The index of the right glyph in the kern pair.      *)
+  (*                                                                       *)
+  (*    kern_mode   :: See @FT_Kerning_Mode for more information.          *)
+  (*                   Determines the scale/dimension of the returned      *)
+  (*                   kerning vector.                                     *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    akerning    :: The kerning vector.  This is in font units for      *)
+  (*                   scalable formats, and in pixels for fixed-sizes     *)
+  (*                   formats.                                            *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Only horizontal layouts (left-to-right & right-to-left) are        *)
+  (*    supported by this method.  Other layouts, or more sophisticated    *)
+  (*    kernings, are out of the scope of this API function -- they can be *)
+  (*    implemented through format-specific interfaces.                    *)
+  (*                                                                       *)
+  function  FT_Get_Kerning(
+            face : FT_Face;
+            left_glyph ,
+            right_glyph ,
+            kern_mode : FT_UInt;
+            out akerning : FT_Vector ) : FT_Error;
+    cdecl; external ft_lib name 'FT_Get_Kerning';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Set_Char_Size                                                   *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Sets the character dimensions of a given face object.  The         *)
+  (*    `char_width' and `char_height' values are used for the width and   *)
+  (*    height, respectively, expressed in 26.6 fractional points.         *)
+  (*                                                                       *)
+  (*    If the horizontal or vertical resolution values are zero, a        *)
+  (*    default value of 72dpi is used.  Similarly, if one of the          *)
+  (*    character dimensions is zero, its value is set equal to the other. *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    face            :: A handle to a target face object.               *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    char_width      :: The character width, in 26.6 fractional points. *)
+  (*                                                                       *)
+  (*    char_height     :: The character height, in 26.6 fractional        *)
+  (*                       points.                                         *)
+  (*                                                                       *)
+  (*    horz_resolution :: The horizontal resolution.                      *)
+  (*                                                                       *)
+  (*    vert_resolution :: The vertical resolution.                        *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    When dealing with fixed-size faces (i.e., non-scalable formats),   *)
+  (*    @FT_Set_Pixel_Sizes provides a more convenient interface.          *)
+  (*                                                                       *)
+  function  FT_Set_Char_Size(
+            face : FT_Face;
+            char_width ,
+            char_height : FT_F26dot6;
+            horz_res ,
+            vert_res : FT_UInt) : FT_Error;
+    cdecl; external ft_lib name 'FT_Set_Char_Size';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Set_Pixel_Sizes                                                 *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Sets the character dimensions of a given face object.  The width   *)
+  (*    and height are expressed in integer pixels.                        *)
+  (*                                                                       *)
+  (*    If one of the character dimensions is zero, its value is set equal *)
+  (*    to the other.                                                      *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    face         :: A handle to the target face object.                *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    pixel_width  :: The character width, in integer pixels.            *)
+  (*                                                                       *)
+  (*    pixel_height :: The character height, in integer pixels.           *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    The values of `pixel_width' and `pixel_height' correspond to the   *)
+  (*    pixel values of the _typographic_ character size, which are NOT    *)
+  (*    necessarily the same as the dimensions of the glyph `bitmap        *)
+  (*    cells'.                                                            *)
+  (*                                                                       *)
+  (*    The `character size' is really the size of an abstract square      *)
+  (*    called the `EM', used to design the font.  However, depending      *)
+  (*    on the font design, glyphs will be smaller or greater than the     *)
+  (*    EM.                                                                *)
+  (*                                                                       *)
+  (*    This means that setting the pixel size to, say, 8x8 doesn't        *)
+  (*    guarantee in any way that you will get glyph bitmaps that all fit  *)
+  (*    within an 8x8 cell (sometimes even far from it).                   *)
+  (*                                                                       *)
+  (*    For bitmap fonts, `pixel_height' usually is a reliable value for   *)
+  (*    the height of the bitmap cell.  Drivers for bitmap font formats    *)
+  (*    which contain a single bitmap strike only (BDF, PCF, FNT) ignore   *)
+  (*    `pixel_width'.                                                     *)
+  (*                                                                       *)
+  function  FT_Set_Pixel_Sizes(
+            face : FT_Face;
+            pixel_width ,
+            pixel_height : FT_UInt ) : FT_Error;
+    cdecl; external ft_lib name 'FT_Set_Pixel_Sizes';
+
+const
+  FT_ANGLE_PI  = 180 shl 16;
+  FT_ANGLE_2PI = FT_ANGLE_PI * 2;
+  FT_ANGLE_PI2 = FT_ANGLE_PI div 2;
+  FT_ANGLE_PI4 = FT_ANGLE_PI div 4;
+
+
+implementation
+
+
+{ FT_CURVE_TAG }
+function FT_CURVE_TAG(flag: byte): byte;
+begin
+  result := flag and 3;
+end;
+
+{ FT_HAS_KERNING }
+function FT_HAS_KERNING(face : FT_Face ) : cbool;
+begin
+  result := cbool(face.face_flags and FT_FACE_FLAG_KERNING );
+end;
+
+{ FT_IS_SCALABLE }
+function FT_IS_SCALABLE(face : FT_Face ) : cbool;
+begin
+  result := cbool(face.face_flags and FT_FACE_FLAG_SCALABLE );
+end;
+
+end.
+
diff --git a/songmanagement/src/lib/freetype/ftconfig.inc b/songmanagement/src/lib/freetype/ftconfig.inc
new file mode 100644
index 00000000..100fb2e0
--- /dev/null
+++ b/songmanagement/src/lib/freetype/ftconfig.inc
@@ -0,0 +1,35 @@
+(***************************************************************************)
+(*                                                                         *)
+(*  ftconfig.h                                                             *)
+(*                                                                         *)
+(*    ANSI-specific configuration file (specification only).               *)
+(*                                                                         *)
+(*  Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by                   *)
+(*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *)
+(*                                                                         *)
+(*  This file is part of the FreeType project, and may only be used,       *)
+(*  modified, and distributed under the terms of the FreeType project      *)
+(*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *)
+(*  this file you indicate that you have read the license and              *)
+(*  understand and accept it fully.                                        *)
+(*                                                                         *)
+(***************************************************************************)
+(***************************************************************************)
+(* Pascal port by the UltraStar Deluxe Team                                *)
+(***************************************************************************)
+
+{$IFDEF TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* IntN types                                                            *)
+  (*                                                                       *)
+  (*   Used to guarantee the size of some specific integers.               *)
+  (*                                                                       *)
+  FT_Int16   = cint16;
+  FT_UInt16  = cuint16;
+  FT_Int32   = cint32;
+  FT_UInt32  = cuint32;
+
+{$ENDIF TYPE_DECL}
+
diff --git a/songmanagement/src/lib/freetype/ftglyph.inc b/songmanagement/src/lib/freetype/ftglyph.inc
new file mode 100644
index 00000000..0d4acc99
--- /dev/null
+++ b/songmanagement/src/lib/freetype/ftglyph.inc
@@ -0,0 +1,435 @@
+(***************************************************************************)
+(*                                                                         *)
+(*  ftglyph.h                                                              *)
+(*                                                                         *)
+(*    FreeType convenience functions to handle glyphs (specification).     *)
+(*                                                                         *)
+(*  Copyright 1996-2001, 2002, 2003, 2006 by                               *)
+(*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *)
+(*                                                                         *)
+(*  This file is part of the FreeType project, and may only be used,       *)
+(*  modified, and distributed under the terms of the FreeType project      *)
+(*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *)
+(*  this file you indicate that you have read the license and              *)
+(*  understand and accept it fully.                                        *)
+(*                                                                         *)
+(***************************************************************************)
+(***************************************************************************)
+(* Pascal port by the UltraStar Deluxe Team                                *)
+(***************************************************************************)
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* This file contains the definition of several convenience functions    *)
+  (* that can be used by client applications to easily retrieve glyph      *)
+  (* bitmaps and outlines from a given face.                               *)
+  (*                                                                       *)
+  (* These functions should be optional if you are writing a font server   *)
+  (* or text layout engine on top of FreeType.  However, they are pretty   *)
+  (* handy for many other simple uses of the library.                      *)
+  (*                                                                       *)
+  (*************************************************************************)
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Section>                                                             *)
+  (*    glyph_management                                                   *)
+  (*                                                                       *)
+  (* <Title>                                                               *)
+  (*    Glyph Management                                                   *)
+  (*                                                                       *)
+  (* <Abstract>                                                            *)
+  (*    Generic interface to manage individual glyph data.                 *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    This section contains definitions used to manage glyph data        *)
+  (*    through generic FT_Glyph objects.  Each of them can contain a      *)
+  (*    bitmap, a vector outline, or even images in other formats.         *)
+  (*                                                                       *)
+  (*************************************************************************)
+
+{$IFDEF TYPE_DECL}
+  
+  (* forward declaration to a private type *)
+  PFT_Glyph_Class = Pointer;
+
+  
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Glyph                                                           *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Handle to an object used to model generic glyph images.  It is a   *)
+  (*    pointer to the @FT_GlyphRec structure and can contain a glyph      *)
+  (*    bitmap or pointer.                                                 *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Glyph objects are not owned by the library.  You must thus release *)
+  (*    them manually (through @FT_Done_Glyph) _before_ calling            *)
+  (*    @FT_Done_FreeType.                                                 *)
+  (*                                                                       *)
+  FT_Glyph = ^FT_GlyphRec;
+  
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_GlyphRec                                                        *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    The root glyph structure contains a given glyph image plus its     *)
+  (*    advance width in 16.16 fixed float format.                         *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    library :: A handle to the FreeType library object.                *)
+  (*                                                                       *)
+  (*    clazz   :: A pointer to the glyph's class.  Private.               *)
+  (*                                                                       *)
+  (*    format  :: The format of the glyph's image.                        *)
+  (*                                                                       *)
+  (*    advance :: A 16.16 vector that gives the glyph's advance width.    *)
+  (*                                                                       *)
+  FT_GlyphRec = record
+    library_: FT_Library;
+    clazz:    PFT_Glyph_Class;
+    format:   FT_Glyph_Format;
+    advance:  FT_Vector;
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_BitmapGlyph                                                     *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A handle to an object used to model a bitmap glyph image.  This is *)
+  (*    a sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec.     *)
+  (*                                                                       *)
+  FT_BitmapGlyph = ^FT_BitmapGlyphRec;
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_BitmapGlyphRec                                                  *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A structure used for bitmap glyph images.  This really is a        *)
+  (*    `sub-class' of `FT_GlyphRec'.                                      *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    root   :: The root FT_Glyph fields.                                *)
+  (*                                                                       *)
+  (*    left   :: The left-side bearing, i.e., the horizontal distance     *)
+  (*              from the current pen position to the left border of the  *)
+  (*              glyph bitmap.                                            *)
+  (*                                                                       *)
+  (*    top    :: The top-side bearing, i.e., the vertical distance from   *)
+  (*              the current pen position to the top border of the glyph  *)
+  (*              bitmap.  This distance is positive for upwards-y!        *)
+  (*                                                                       *)
+  (*    bitmap :: A descriptor for the bitmap.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    You can typecast FT_Glyph to FT_BitmapGlyph if you have            *)
+  (*    glyph->format == FT_GLYPH_FORMAT_BITMAP.  This lets you access     *)
+  (*    the bitmap's contents easily.                                      *)
+  (*                                                                       *)
+  (*    The corresponding pixel buffer is always owned by the BitmapGlyph  *)
+  (*    and is thus created and destroyed with it.                         *)
+  (*                                                                       *)
+  FT_BitmapGlyphRec = record
+    root:   FT_GlyphRec;
+    left:   FT_Int;
+    top:    FT_Int;
+    bitmap: FT_Bitmap;
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_OutlineGlyph                                                    *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A handle to an object used to model an outline glyph image.  This  *)
+  (*    is a sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. *)
+  (*                                                                       *)
+  FT_OutlineGlyph = ^FT_OutlineGlyphRec;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_OutlineGlyphRec                                                 *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A structure used for outline (vectorial) glyph images.  This       *)
+  (*    really is a `sub-class' of `FT_GlyphRec'.                          *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    root    :: The root FT_Glyph fields.                               *)
+  (*                                                                       *)
+  (*    outline :: A descriptor for the outline.                           *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    You can typecast FT_Glyph to FT_OutlineGlyph if you have           *)
+  (*    glyph->format == FT_GLYPH_FORMAT_OUTLINE.  This lets you access    *)
+  (*    the outline's content easily.                                      *)
+  (*                                                                       *)
+  (*    As the outline is extracted from a glyph slot, its coordinates are *)
+  (*    expressed normally in 26.6 pixels, unless the flag                 *)
+  (*    FT_LOAD_NO_SCALE was used in FT_Load_Glyph() or FT_Load_Char().    *)
+  (*                                                                       *)
+  (*    The outline's tables are always owned by the object and are        *)
+  (*    destroyed with it.                                                 *)
+  (*                                                                       *)
+  FT_OutlineGlyphRec = record
+    root:    FT_GlyphRec;
+    outline: FT_Outline;
+  end;
+
+{$ELSE TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Get_Glyph                                                       *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A function used to extract a glyph image from a slot.              *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    slot   :: A handle to the source glyph slot.                       *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    aglyph :: A handle to the glyph object.                            *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  function FT_Get_Glyph(
+             slot:   FT_GlyphSlot;
+             out aglyph: FT_Glyph ): FT_Error;
+    cdecl; external ft_lib name 'FT_Get_Glyph';
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Glyph_Copy                                                      *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A function used to copy a glyph image.  Note that the created      *)
+  (*    @FT_Glyph object must be released with @FT_Done_Glyph.             *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    source :: A handle to the source glyph object.                     *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    target :: A handle to the target glyph object.  0~in case of       *)
+  (*              error.                                                   *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0~means success.                             *)
+  (*                                                                       *)
+  function FT_Glyph_Copy(source: FT_Glyph;
+                 var target: FT_Glyph ): FT_Error;
+    cdecl; external ft_lib name 'FT_Glyph_Copy';
+
+{$ENDIF TYPE_DECL}
+{$IFDEF TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Enum>                                                                *)
+  (*    FT_Glyph_BBox_Mode                                                 *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    The mode how the values of @FT_Glyph_Get_CBox are returned.        *)
+  (*                                                                       *)
+  (* <Values>                                                              *)
+  (*    FT_GLYPH_BBOX_UNSCALED ::                                          *)
+  (*      Return unscaled font units.                                      *)
+  (*                                                                       *)
+  (*    FT_GLYPH_BBOX_SUBPIXELS ::                                         *)
+  (*      Return unfitted 26.6 coordinates.                                *)
+  (*                                                                       *)
+  (*    FT_GLYPH_BBOX_GRIDFIT ::                                           *)
+  (*      Return grid-fitted 26.6 coordinates.                             *)
+  (*                                                                       *)
+  (*    FT_GLYPH_BBOX_TRUNCATE ::                                          *)
+  (*      Return coordinates in integer pixels.                            *)
+  (*                                                                       *)
+  (*    FT_GLYPH_BBOX_PIXELS ::                                            *)
+  (*      Return grid-fitted pixel coordinates.                            *)
+  (*                                                                       *)
+  FT_Glyph_BBox_Mode = cint;
+{$ELSE TYPE_DECL}
+const
+  FT_GLYPH_BBOX_UNSCALED  = 0;
+  FT_GLYPH_BBOX_SUBPIXELS = 0;
+  FT_GLYPH_BBOX_GRIDFIT   = 1;
+  FT_GLYPH_BBOX_TRUNCATE  = 2;
+  FT_GLYPH_BBOX_PIXELS    = 3;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Glyph_Get_CBox                                                  *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Return a glyph's `control box'.  The control box encloses all the  *)
+  (*    outline's points, including B�zier control points.  Though it      *)
+  (*    coincides with the exact bounding box for most glyphs, it can be   *)
+  (*    slightly larger in some situations (like when rotating an outline  *)
+  (*    which contains B�zier outside arcs).                               *)
+  (*                                                                       *)
+  (*    Computing the control box is very fast, while getting the bounding *)
+  (*    box can take much more time as it needs to walk over all segments  *)
+  (*    and arcs in the outline.  To get the latter, you can use the       *)
+  (*    `ftbbox' component which is dedicated to this single task.         *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    glyph :: A handle to the source glyph object.                      *)
+  (*                                                                       *)
+  (*    mode  :: The mode which indicates how to interpret the returned    *)
+  (*             bounding box values.                                      *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    acbox :: The glyph coordinate bounding box.  Coordinates are       *)
+  (*             expressed in 1/64th of pixels if it is grid-fitted.       *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Coordinates are relative to the glyph origin, using the Y-upwards  *)
+  (*    convention.                                                        *)
+  (*                                                                       *)
+  (*    If the glyph has been loaded with @FT_LOAD_NO_SCALE, `bbox_mode'   *)
+  (*    must be set to @FT_GLYPH_BBOX_UNSCALED to get unscaled font        *)
+  (*    units in 26.6 pixel format.  The value @FT_GLYPH_BBOX_SUBPIXELS    *)
+  (*    is another name for this constant.                                 *)
+  (*                                                                       *)
+  (*    Note that the maximum coordinates are exclusive, which means that  *)
+  (*    one can compute the width and height of the glyph image (be it in  *)
+  (*    integer or 26.6 pixels) as:                                        *)
+  (*                                                                       *)
+  (*    {                                                                  *)
+  (*      width  = bbox.xMax - bbox.xMin;                                  *)
+  (*      height = bbox.yMax - bbox.yMin;                                  *)
+  (*    }                                                                  *)
+  (*                                                                       *)
+  (*    Note also that for 26.6 coordinates, if `bbox_mode' is set to      *)
+  (*    @FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted,  *)
+  (*    which corresponds to:                                              *)
+  (*                                                                       *)
+  (*    {                                                                  *)
+  (*      bbox.xMin = FLOOR(bbox.xMin);                                    *)
+  (*      bbox.yMin = FLOOR(bbox.yMin);                                    *)
+  (*      bbox.xMax = CEILING(bbox.xMax);                                  *)
+  (*      bbox.yMax = CEILING(bbox.yMax);                                  *)
+  (*    }                                                                  *)
+  (*                                                                       *)
+  (*    To get the bbox in pixel coordinates, set `bbox_mode' to           *)
+  (*    @FT_GLYPH_BBOX_TRUNCATE.                                           *)
+  (*                                                                       *)
+  (*    To get the bbox in grid-fitted pixel coordinates, set `bbox_mode'  *)
+  (*    to @FT_GLYPH_BBOX_PIXELS.                                          *)
+  (*                                                                       *)
+  procedure FT_Glyph_Get_CBox( glyph: FT_Glyph;
+                     bbox_mode: FT_UInt;
+                     out acbox: FT_BBox );
+    cdecl; external ft_lib name 'FT_Glyph_Get_CBox';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Glyph_To_Bitmap                                                 *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Converts a given glyph object to a bitmap glyph object.            *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    the_glyph   :: A pointer to a handle to the target glyph.          *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    render_mode :: An enumeration that describe how the data is        *)
+  (*                   rendered.                                           *)
+  (*                                                                       *)
+  (*    origin      :: A pointer to a vector used to translate the glyph   *)
+  (*                   image before rendering.  Can be 0 (if no            *)
+  (*                   translation).  The origin is expressed in           *)
+  (*                   26.6 pixels.                                        *)
+  (*                                                                       *)
+  (*    destroy     :: A boolean that indicates that the original glyph    *)
+  (*                   image should be destroyed by this function.  It is  *)
+  (*                   never destroyed in case of error.                   *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    The glyph image is translated with the `origin' vector before      *)
+  (*    rendering.                                                         *)
+  (*                                                                       *)
+  (*    The first parameter is a pointer to a FT_Glyph handle, that will   *)
+  (*    be replaced by this function.  Typically, you would use (omitting  *)
+  (*    error handling):                                                   *)
+  (*                                                                       *)
+  (*                                                                       *)
+  (*      {                                                                *)
+  (*        FT_Glyph        glyph;                                         *)
+  (*        FT_BitmapGlyph  glyph_bitmap;                                  *)
+  (*                                                                       *)
+  (*                                                                       *)
+  (*        // load glyph                                                  *)
+  (*        error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT );     *)
+  (*                                                                       *)
+  (*        // extract glyph image                                         *)
+  (*        error = FT_Get_Glyph( face->glyph, &glyph );                   *)
+  (*                                                                       *)
+  (*        // convert to a bitmap (default render mode + destroy old)     *)
+  (*        if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )                 *)
+  (*        {                                                              *)
+  (*          error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_DEFAULT,  *)
+  (*                                      0, 1 );                          *)
+  (*          if ( error ) // glyph unchanged                              *)
+  (*            ...                                                        *)
+  (*        }                                                              *)
+  (*                                                                       *)
+  (*        // access bitmap content by typecasting                        *)
+  (*        glyph_bitmap = (FT_BitmapGlyph)glyph;                          *)
+  (*                                                                       *)
+  (*        // do funny stuff with it, like blitting/drawing               *)
+  (*        ...                                                            *)
+  (*                                                                       *)
+  (*        // discard glyph image (bitmap or not)                         *)
+  (*        FT_Done_Glyph( glyph );                                        *)
+  (*      }                                                                *)
+  (*                                                                       *)
+  (*                                                                       *)
+  (*    This function does nothing if the glyph format isn't scalable.     *)
+  (*                                                                       *)
+  function FT_Glyph_To_Bitmap(var the_glyph: FT_Glyph;
+                      render_mode: FT_Render_Mode;
+                      origin:      PFT_Vector;
+                      destroy:     FT_Bool ): FT_Error;
+    cdecl; external ft_lib name 'FT_Glyph_To_Bitmap';
+
+    
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Done_Glyph                                                      *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Destroys a given glyph.                                            *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    glyph :: A handle to the target glyph object.                      *)
+  (*                                                                       *)
+  procedure FT_Done_Glyph( glyph: FT_Glyph );
+    cdecl; external ft_lib name 'FT_Done_Glyph';
+
+{$ENDIF TYPE_DECL}
diff --git a/songmanagement/src/lib/freetype/ftimage.inc b/songmanagement/src/lib/freetype/ftimage.inc
new file mode 100644
index 00000000..63eee534
--- /dev/null
+++ b/songmanagement/src/lib/freetype/ftimage.inc
@@ -0,0 +1,849 @@
+(***************************************************************************)
+(*                                                                         *)
+(*  ftimage.h                                                              *)
+(*                                                                         *)
+(*    FreeType glyph image formats and default raster interface            *)
+(*    (specification).                                                     *)
+(*                                                                         *)
+(*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by             *)
+(*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *)
+(*                                                                         *)
+(*  This file is part of the FreeType project, and may only be used,       *)
+(*  modified, and distributed under the terms of the FreeType project      *)
+(*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *)
+(*  this file you indicate that you have read the license and              *)
+(*  understand and accept it fully.                                        *)
+(*                                                                         *)
+(***************************************************************************)
+(***************************************************************************)
+(* Pascal port by the UltraStar Deluxe Team                                *)
+(***************************************************************************)
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* Note: A `raster' is simply a scan-line converter, used to render      *)
+  (*       FT_Outlines into FT_Bitmaps.                                    *)
+  (*                                                                       *)
+  (*************************************************************************)
+
+{$IFDEF TYPE_DECL}
+  
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Pos                                                             *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    The type FT_Pos is a 32-bit integer used to store vectorial        *)
+  (*    coordinates.  Depending on the context, these can represent        *)
+  (*    distances in integer font units, or 16,16, or 26.6 fixed float     *)
+  (*    pixel coordinates.                                                 *)
+  (*                                                                       *)
+  FT_Pos     = cslong;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Vector                                                          *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A simple structure used to store a 2D vector; coordinates are of   *)
+  (*    the FT_Pos type.                                                   *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    x :: The horizontal coordinate.                                    *)
+  (*    y :: The vertical coordinate.                                      *)
+  (*                                                                       *)
+  PFT_Vector = ^FT_Vector;
+  FT_Vector = record
+    x ,
+    y : FT_Pos;
+  end;
+
+  PFT_VectorArray = ^FT_VectorArray;
+  FT_VectorArray = array[0 .. (MaxInt div SizeOf(FT_Vector))-1] of FT_Vector;
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_BBox                                                            *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A structure used to hold an outline's bounding box, i.e., the      *)
+  (*    coordinates of its extrema in the horizontal and vertical          *)
+  (*    directions.                                                        *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    xMin :: The horizontal minimum (left-most).                        *)
+  (*                                                                       *)
+  (*    yMin :: The vertical minimum (bottom-most).                        *)
+  (*                                                                       *)
+  (*    xMax :: The horizontal maximum (right-most).                       *)
+  (*                                                                       *)
+  (*    yMax :: The vertical maximum (top-most).                           *)
+  (*                                                                       *)
+  PFT_BBox = ^FT_BBox;
+  FT_BBox = record
+    xMin, yMin : FT_Pos;
+    xMax, yMax : FT_Pos;
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Enum>                                                                *)
+  (*    FT_Pixel_Mode                                                      *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    An enumeration type used to describe the format of pixels in a     *)
+  (*    given bitmap.  Note that additional formats may be added in the    *)
+  (*    future.                                                            *)
+  (*                                                                       *)
+  (* <Values>                                                              *)
+  (*    FT_PIXEL_MODE_NONE ::                                              *)
+  (*      Value 0 is reserved.                                             *)
+  (*                                                                       *)
+  (*    FT_PIXEL_MODE_MONO ::                                              *)
+  (*      A monochrome bitmap, using 1 bit per pixel.  Note that pixels    *)
+  (*      are stored in most-significant order (MSB), which means that     *)
+  (*      the left-most pixel in a byte has value 128.                     *)
+  (*                                                                       *)
+  (*    FT_PIXEL_MODE_GRAY ::                                              *)
+  (*      An 8-bit bitmap, generally used to represent anti-aliased glyph  *)
+  (*      images.  Each pixel is stored in one byte.  Note that the number *)
+  (*      of value `gray' levels is stored in the `num_bytes' field of     *)
+  (*      the @FT_Bitmap structure (it generally is 256).                  *)
+  (*                                                                       *)
+  (*    FT_PIXEL_MODE_GRAY2 ::                                             *)
+  (*      A 2-bit/pixel bitmap, used to represent embedded anti-aliased    *)
+  (*      bitmaps in font files according to the OpenType specification.   *)
+  (*      We haven't found a single font using this format, however.       *)
+  (*                                                                       *)
+  (*    FT_PIXEL_MODE_GRAY4 ::                                             *)
+  (*      A 4-bit/pixel bitmap, used to represent embedded anti-aliased    *)
+  (*      bitmaps in font files according to the OpenType specification.   *)
+  (*      We haven't found a single font using this format, however.       *)
+  (*                                                                       *)
+  (*    FT_PIXEL_MODE_LCD ::                                               *)
+  (*      An 8-bit bitmap, used to represent RGB or BGR decimated glyph    *)
+  (*      images used for display on LCD displays; the bitmap is three     *)
+  (*      times wider than the original glyph image.  See also             *)
+  (*      @FT_RENDER_MODE_LCD.                                             *)
+  (*                                                                       *)
+  (*    FT_PIXEL_MODE_LCD_V ::                                             *)
+  (*      An 8-bit bitmap, used to represent RGB or BGR decimated glyph    *)
+  (*      images used for display on rotated LCD displays; the bitmap      *)
+  (*      is three times taller than the original glyph image.  See also   *)
+  (*      @FT_RENDER_MODE_LCD_V.                                           *)
+  (*                                                                       *)
+  FT_Pixel_Mode = cint;
+{$ELSE TYPE_DECL}
+const
+  FT_PIXEL_MODE_NONE    = 0;
+  FT_PIXEL_MODE_MONO    = FT_PIXEL_MODE_NONE  + 1;
+  FT_PIXEL_MODE_GRAY    = FT_PIXEL_MODE_MONO  + 1;
+  FT_PIXEL_MODE_GRAY2   = FT_PIXEL_MODE_GRAY  + 1;
+  FT_PIXEL_MODE_GRAY4   = FT_PIXEL_MODE_GRAY2 + 1;
+  FT_PIXEL_MODE_LCD     = FT_PIXEL_MODE_GRAY4 + 1;
+  FT_PIXEL_MODE_LCD_V   = FT_PIXEL_MODE_LCD   + 1;
+
+  FT_PIXEL_MODE_MAX     = FT_PIXEL_MODE_LCD_V + 1; (* do not remove *)
+{$ENDIF TYPE_DECL}
+{$IFDEF TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Bitmap                                                          *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A structure used to describe a bitmap or pixmap to the raster.     *)
+  (*    Note that we now manage pixmaps of various depths through the      *)
+  (*    `pixel_mode' field.                                                *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    rows         :: The number of bitmap rows.                         *)
+  (*                                                                       *)
+  (*    width        :: The number of pixels in bitmap row.                *)
+  (*                                                                       *)
+  (*    pitch        :: The pitch's absolute value is the number of bytes  *)
+  (*                    taken by one bitmap row, including padding.        *)
+  (*                    However, the pitch is positive when the bitmap has *)
+  (*                    a `down' flow, and negative when it has an `up'    *)
+  (*                    flow.  In all cases, the pitch is an offset to add *)
+  (*                    to a bitmap pointer in order to go down one row.   *)
+  (*                                                                       *)
+  (*    buffer       :: A typeless pointer to the bitmap buffer.  This     *)
+  (*                    value should be aligned on 32-bit boundaries in    *)
+  (*                    most cases.                                        *)
+  (*                                                                       *)
+  (*    num_grays    :: This field is only used with                       *)
+  (*                    `FT_PIXEL_MODE_GRAY'; it gives the number of gray  *)
+  (*                    levels used in the bitmap.                         *)
+  (*                                                                       *)
+  (*    pixel_mode   :: The pixel mode, i.e., how pixel bits are stored.   *)
+  (*                    See @FT_Pixel_Mode for possible values.            *)
+  (*                                                                       *)
+  (*    palette_mode :: This field is only used with paletted pixel modes; *)
+  (*                    it indicates how the palette is stored.            *)
+  (*                                                                       *)
+  (*    palette      :: A typeless pointer to the bitmap palette; only     *)
+  (*                    used for paletted pixel modes.                     *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*   For now, the only pixel mode supported by FreeType are mono and     *)
+  (*   grays.  However, drivers might be added in the future to support    *)
+  (*   more `colorful' options.                                            *)
+  (*                                                                       *)
+  (*   When using pixel modes pal2, pal4 and pal8 with a void `palette'    *)
+  (*   field, a gray pixmap with respectively 4, 16, and 256 levels of     *)
+  (*   gray is assumed.  This, in order to be compatible with some         *)
+  (*   embedded bitmap formats defined in the TrueType specification.      *)
+  (*                                                                       *)
+  (*   Note that no font was found presenting such embedded bitmaps, so    *)
+  (*   this is currently completely unhandled by the library.              *)
+  (*                                                                       *)
+  PFT_Bitmap = ^FT_Bitmap;
+  FT_Bitmap = record
+    rows:         FT_Int;
+    width:        FT_Int;
+    pitch:        FT_Int;
+    buffer:       PByteArray;
+    num_grays:    FT_Short;
+    pixel_mode:   byte;
+    palette_mode: byte;
+    palette:      pointer;
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Section>                                                             *)
+  (*    outline_processing                                                 *)
+  (*                                                                       *)
+  (*************************************************************************)
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Outline                                                         *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    This structure is used to describe an outline to the scan-line     *)
+  (*    converter.                                                         *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    n_contours :: The number of contours in the outline.               *)
+  (*                                                                       *)
+  (*    n_points   :: The number of points in the outline.                 *)
+  (*                                                                       *)
+  (*    points     :: A pointer to an array of `n_points' FT_Vector        *)
+  (*                  elements, giving the outline's point coordinates.    *)
+  (*                                                                       *)
+  (*    tags       :: A pointer to an array of `n_points' chars, giving    *)
+  (*                  each outline point's type.  If bit 0 is unset, the   *)
+  (*                  point is `off' the curve, i.e. a Bezier control      *)
+  (*                  point, while it is `on' when set.                    *)
+  (*                                                                       *)
+  (*                  Bit 1 is meaningful for `off' points only.  If set,  *)
+  (*                  it indicates a third-order Bezier arc control point; *)
+  (*                  and a second-order control point if unset.           *)
+  (*                                                                       *)
+  (*    contours   :: An array of `n_contours' shorts, giving the end      *)
+  (*                  point of each contour within the outline.  For       *)
+  (*                  example, the first contour is defined by the points  *)
+  (*                  `0' to `contours[0]', the second one is defined by   *)
+  (*                  the points `contours[0]+1' to `contours[1]', etc.    *)
+  (*                                                                       *)
+  (*    flags      :: A set of bit flags used to characterize the outline  *)
+  (*                  and give hints to the scan-converter and hinter on   *)
+  (*                  how to convert/grid-fit it.  See FT_Outline_Flags.   *)
+  (*                                                                       *)
+  PFT_Outline = ^FT_Outline;
+  FT_Outline = record
+    n_contours: FT_Short;        (* number of contours in glyph        *)
+    n_points:   FT_Short;        (* number of points in the glyph      *)
+
+    points:     PFT_VectorArray; (* the outline's points               *)
+    tags:       PByteArray;      (* the points flags                   *)
+    contours:   PFT_ShortArray;  (* the contour end points             *)
+
+    flags:      FT_Int;          (* outline masks                      *)
+  end;
+
+{$ELSE TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* @macro:                                                               *)
+  (*    FT_CURVE_TAG  ( flag )                                             *)
+  (*                                                                       *)
+  function  FT_CURVE_TAG(flag: byte): byte;
+
+const
+  FT_CURVE_TAG_ON    = 1;
+  FT_CURVE_TAG_CONIC = 0;
+  FT_CURVE_TAG_CUBIC = 2;
+
+  FT_CURVE_TAG_TOUCH_X   =   8;  // reserved for the TrueType hinter
+  FT_CURVE_TAG_TOUCH_Y   =  16;  // reserved for the TrueType hinter
+
+  FT_CURVE_TAG_TOUCH_BOTH  = ( FT_CURVE_TAG_TOUCH_X or
+                               FT_CURVE_TAG_TOUCH_Y );
+{$ENDIF TYPE_DECL}
+{$IFDEF TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <FuncType>                                                            *)
+  (*    FT_Outline_MoveToFunc                                              *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A function pointer type used to describe the signature of a `move  *)
+  (*    to' function during outline walking/decomposition.                 *)
+  (*                                                                       *)
+  (*    A `move to' is emitted to start a new contour in an outline.       *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    to   :: A pointer to the target point of the `move to'.            *)
+  (*                                                                       *)
+  (*    user :: A typeless pointer which is passed from the caller of the  *)
+  (*            decomposition function.                                    *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    Error code.  0 means success.                                      *)
+  (*                                                                       *)
+  FT_Outline_MoveToFunc = function(to_: {const} PFT_Vector;
+                                   user: Pointer): cint; cdecl;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <FuncType>                                                            *)
+  (*    FT_Outline_LineToFunc                                              *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A function pointer type used to describe the signature of a `line  *)
+  (*    to' function during outline walking/decomposition.                 *)
+  (*                                                                       *)
+  (*    A `line to' is emitted to indicate a segment in the outline.       *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    to   :: A pointer to the target point of the `line to'.            *)
+  (*                                                                       *)
+  (*    user :: A typeless pointer which is passed from the caller of the  *)
+  (*            decomposition function.                                    *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    Error code.  0 means success.                                      *)
+  (*                                                                       *)
+  FT_Outline_LineToFunc = function(to_: {const} PFT_Vector;
+                                   user: Pointer): cint; cdecl;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <FuncType>                                                            *)
+  (*    FT_Outline_ConicToFunc                                             *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A function pointer type use to describe the signature of a `conic  *)
+  (*    to' function during outline walking/decomposition.                 *)
+  (*                                                                       *)
+  (*    A `conic to' is emitted to indicate a second-order B�zier arc in   *)
+  (*    the outline.                                                       *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    control :: An intermediate control point between the last position *)
+  (*               and the new target in `to'.                             *)
+  (*                                                                       *)
+  (*    to      :: A pointer to the target end point of the conic arc.     *)
+  (*                                                                       *)
+  (*    user    :: A typeless pointer which is passed from the caller of   *)
+  (*               the decomposition function.                             *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    Error code.  0 means success.                                      *)
+  (*                                                                       *)
+  FT_Outline_ConicToFunc = function(control: {const} PFT_Vector;
+                             to_:  {const} PFT_Vector;
+                             user: Pointer): cint; cdecl;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <FuncType>                                                            *)
+  (*    FT_Outline_CubicToFunc                                             *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A function pointer type used to describe the signature of a `cubic *)
+  (*    to' function during outline walking/decomposition.                 *)
+  (*                                                                       *)
+  (*    A `cubic to' is emitted to indicate a third-order B�zier arc.      *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    control1 :: A pointer to the first B�zier control point.           *)
+  (*                                                                       *)
+  (*    control2 :: A pointer to the second B�zier control point.          *)
+  (*                                                                       *)
+  (*    to       :: A pointer to the target end point.                     *)
+  (*                                                                       *)
+  (*    user     :: A typeless pointer which is passed from the caller of  *)
+  (*                the decomposition function.                            *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    Error code.  0 means success.                                      *)
+  (*                                                                       *)
+  FT_Outline_CubicToFunc = function( control1: {const} PFT_Vector;
+                             control2: {const} PFT_Vector;
+                             to_:      {const} PFT_Vector;
+                             user:     Pointer ): cint; cdecl;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Outline_Funcs                                                   *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A structure to hold various function pointers used during outline  *)
+  (*    decomposition in order to emit segments, conic, and cubic B�ziers, *)
+  (*    as well as `move to' and `close to' operations.                    *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    move_to  :: The `move to' emitter.                                 *)
+  (*                                                                       *)
+  (*    line_to  :: The segment emitter.                                   *)
+  (*                                                                       *)
+  (*    conic_to :: The second-order B�zier arc emitter.                   *)
+  (*                                                                       *)
+  (*    cubic_to :: The third-order B�zier arc emitter.                    *)
+  (*                                                                       *)
+  (*    shift    :: The shift that is applied to coordinates before they   *)
+  (*                are sent to the emitter.                               *)
+  (*                                                                       *)
+  (*    delta    :: The delta that is applied to coordinates before they   *)
+  (*                are sent to the emitter, but after the shift.          *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    The point coordinates sent to the emitters are the transformed     *)
+  (*    version of the original coordinates (this is important for high    *)
+  (*    accuracy during scan-conversion).  The transformation is simple:   *)
+  (*                                                                       *)
+  (*    {                                                                  *)
+  (*      x' = (x << shift) - delta                                        *)
+  (*      y' = (x << shift) - delta                                        *)
+  (*    }                                                                  *)
+  (*                                                                       *)
+  (*    Set the value of `shift' and `delta' to 0 to get the original      *)
+  (*    point coordinates.                                                 *)
+  (*                                                                       *)
+  PFT_Outline_Funcs = ^FT_Outline_Funcs;
+  FT_Outline_Funcs = record
+    move_to:  FT_Outline_MoveToFunc;
+    line_to:  FT_Outline_LineToFunc;
+    conic_to: FT_Outline_ConicToFunc;
+    cubic_to: FT_Outline_CubicToFunc;
+
+    shift:    cint;
+    delta:    FT_Pos;
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Macro>                                                               *)
+  (*    FT_IMAGE_TAG                                                       *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    This macro converts four-letter tags to an unsigned long type.     *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    Since many 16-bit compilers don't like 32-bit enumerations, you    *)
+  (*    should redefine this macro in case of problems to something like   *)
+  (*    this:                                                              *)
+  (*                                                                       *)
+  (*    {                                                                  *)
+  (*      #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 )  value         *)
+  (*    }                                                                  *)
+  (*                                                                       *)
+  (*    to get a simple enumeration without assigning special numbers.     *)
+  (*                                                                       *)
+  {
+  #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 )  \
+          value = ( ( (unsigned long)_x1 << 24 ) | \
+                    ( (unsigned long)_x2 << 16 ) | \
+                    ( (unsigned long)_x3 << 8  ) | \
+                      (unsigned long)_x4         )
+  }
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Enum>                                                                *)
+  (*    FT_Glyph_Format                                                    *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    An enumeration type used to describe the format of a given glyph   *)
+  (*    image.  Note that this version of FreeType only supports two image *)
+  (*    formats, even though future font drivers will be able to register  *)
+  (*    their own format.                                                  *)
+  (*                                                                       *)
+  (* <Values>                                                              *)
+  (*    FT_GLYPH_FORMAT_NONE ::                                            *)
+  (*      The value 0 is reserved and does describe a glyph format.        *)
+  (*                                                                       *)
+  (*    FT_GLYPH_FORMAT_COMPOSITE ::                                       *)
+  (*      The glyph image is a composite of several other images.  This    *)
+  (*      format is _only_ used with @FT_LOAD_NO_RECURSE, and is used to   *)
+  (*      report compound glyphs (like accented characters).               *)
+  (*                                                                       *)
+  (*    FT_GLYPH_FORMAT_BITMAP ::                                          *)
+  (*      The glyph image is a bitmap, and can be described as an          *)
+  (*      @FT_Bitmap.  You generally need to access the `bitmap' field of  *)
+  (*      the @FT_GlyphSlotRec structure to read it.                       *)
+  (*                                                                       *)
+  (*    FT_GLYPH_FORMAT_OUTLINE ::                                         *)
+  (*      The glyph image is a vertorial outline made of line segments     *)
+  (*      and Bezier arcs; it can be described as an @FT_Outline; you      *)
+  (*      generally want to access the `outline' field of the              *)
+  (*      @FT_GlyphSlotRec structure to read it.                           *)
+  (*                                                                       *)
+  (*    FT_GLYPH_FORMAT_PLOTTER ::                                         *)
+  (*      The glyph image is a vectorial path with no inside/outside       *)
+  (*      contours.  Some Type 1 fonts, like those in the Hershey family,  *)
+  (*      contain glyphs in this format.  These are described as           *)
+  (*      @FT_Outline, but FreeType isn't currently capable of rendering   *)
+  (*      them correctly.                                                  *)
+  (*                                                                       *)
+  // Note: enums are 32 bit on x86 AND x86_64
+  FT_Glyph_Format = cuint32;  // 32 bit enum of FT_IMAGE_TAG
+{$ELSE TYPE_DECL}
+const
+  FT_GLYPH_FORMAT_NONE      = (Ord(#0) shl 24) or
+                              (Ord(#0) shl 16) or
+                              (Ord(#0) shl  8) or
+                              (Ord(#0) shl  0);
+
+  FT_GLYPH_FORMAT_COMPOSITE = (Ord('c') shl 24) or
+                              (Ord('o') shl 16) or
+                              (Ord('m') shl  8) or
+                              (Ord('p') shl  0);
+
+  FT_GLYPH_FORMAT_BITMAP    = (Ord('b') shl 24) or
+                              (Ord('i') shl 16) or
+                              (Ord('t') shl  8) or
+                              (Ord('s') shl  0);
+
+  FT_GLYPH_FORMAT_OUTLINE   = (Ord('o') shl 24) or
+                              (Ord('u') shl 16) or
+                              (Ord('t') shl  8) or
+                              (Ord('l') shl  0);
+
+  FT_GLYPH_FORMAT_PLOTTER   = (Ord('p') shl 24) or
+                              (Ord('l') shl 16) or
+                              (Ord('o') shl  8) or
+                              (Ord('t') shl  0);
+
+{$ENDIF TYPE_DECL}
+
+  (*************************************************************************)
+  (*************************************************************************)
+  (*************************************************************************)
+  (*****                                                               *****)
+  (*****            R A S T E R   D E F I N I T I O N S                *****)
+  (*****                                                               *****)
+  (*************************************************************************)
+  (*************************************************************************)
+  (*************************************************************************)
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* A raster is a scan converter, in charge of rendering an outline into  *)
+  (* a a bitmap.  This section contains the public API for rasters.        *)
+  (*                                                                       *)
+  (* Note that in FreeType 2, all rasters are now encapsulated within      *)
+  (* specific modules called `renderers'.  See `freetype/ftrender.h' for   *)
+  (* more details on renderers.                                            *)
+  (*                                                                       *)
+  (*************************************************************************)
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Section>                                                             *)
+  (*    raster                                                             *)
+  (*                                                                       *)
+  (* <Title>                                                               *)
+  (*    Scanline Converter                                                 *)
+  (*                                                                       *)
+  (* <Abstract>                                                            *)
+  (*    How vectorial outlines are converted into bitmaps and pixmaps.     *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    This section contains technical definitions.                       *)
+  (*                                                                       *)
+  (*************************************************************************)
+
+{$IFDEF TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Raster                                                          *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A handle (pointer) to a raster object.  Each object can be used    *)
+  (*    independently to convert an outline into a bitmap or pixmap.       *)
+  (*                                                                       *)
+  FT_Raster = Pointer;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Span                                                            *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A structure used to model a single span of gray (or black) pixels  *)
+  (*    when rendering a monochrome or anti-aliased bitmap.                *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    x        :: The span's horizontal start position.                  *)
+  (*                                                                       *)
+  (*    len      :: The span's length in pixels.                           *)
+  (*                                                                       *)
+  (*    coverage :: The span color/coverage, ranging from 0 (background)   *)
+  (*                to 255 (foreground).  Only used for anti-aliased       *)
+  (*                rendering.                                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    This structure is used by the span drawing callback type named     *)
+  (*    @FT_SpanFunc which takes the y-coordinate of the span as a         *)
+  (*    a parameter.                                                       *)
+  (*                                                                       *)
+  (*    The coverage value is always between 0 and 255.                    *)
+  (*                                                                       *)
+  PFT_Span = ^FT_Span;
+  FT_Span = record
+    x:         cshort;
+    len:       cushort;
+    coverage:  cuchar;
+  end;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <FuncType>                                                            *)
+  (*    FT_SpanFunc                                                        *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A function used as a call-back by the anti-aliased renderer in     *)
+  (*    order to let client applications draw themselves the gray pixel    *)
+  (*    spans on each scan line.                                           *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    y     :: The scanline's y-coordinate.                              *)
+  (*                                                                       *)
+  (*    count :: The number of spans to draw on this scanline.             *)
+  (*                                                                       *)
+  (*    spans :: A table of `count' spans to draw on the scanline.         *)
+  (*                                                                       *)
+  (*    user  :: User-supplied data that is passed to the callback.        *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    This callback allows client applications to directly render the    *)
+  (*    gray spans of the anti-aliased bitmap to any kind of surfaces.     *)
+  (*                                                                       *)
+  (*    This can be used to write anti-aliased outlines directly to a      *)
+  (*    given background bitmap, and even perform translucency.            *)
+  (*                                                                       *)
+  (*    Note that the `count' field cannot be greater than a fixed value   *)
+  (*    defined by the `FT_MAX_GRAY_SPANS' configuration macro in          *)
+  (*    `ftoption.h'.  By default, this value is set to 32, which means    *)
+  (*    that if there are more than 32 spans on a given scanline, the      *)
+  (*    callback is called several times with the same `y' parameter in    *)
+  (*    order to draw all callbacks.                                       *)
+  (*                                                                       *)
+  (*    Otherwise, the callback is only called once per scan-line, and     *)
+  (*    only for those scanlines that do have `gray' pixels on them.       *)
+  (*                                                                       *)
+  FT_SpanFunc = procedure(y:      cint;
+                  count:          cint;
+                  spans:          {const} PFT_Span;
+                  user:           Pointer ); cdecl;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <FuncType>                                                            *)
+  (*    FT_Raster_BitTest_Func                                             *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    THIS TYPE IS DEPRECATED.  DO NOT USE IT.                           *)
+  (*                                                                       *)
+  (*    A function used as a call-back by the monochrome scan-converter    *)
+  (*    to test whether a given target pixel is already set to the drawing *)
+  (*    `color'.  These tests are crucial to implement drop-out control    *)
+  (*    per-se the TrueType spec.                                          *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    y     :: The pixel's y-coordinate.                                 *)
+  (*                                                                       *)
+  (*    x     :: The pixel's x-coordinate.                                 *)
+  (*                                                                       *)
+  (*    user  :: User-supplied data that is passed to the callback.        *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*   1 if the pixel is `set', 0 otherwise.                               *)
+  (*                                                                       *)
+  FT_Raster_BitTest_Func = function(y: cint;
+                             x:    cint;
+                             user: Pointer): cint; cdecl;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <FuncType>                                                            *)
+  (*    FT_Raster_BitSet_Func                                              *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    THIS TYPE IS DEPRECATED.  DO NOT USE IT.                           *)
+  (*                                                                       *)
+  (*    A function used as a call-back by the monochrome scan-converter    *)
+  (*    to set an individual target pixel.  This is crucial to implement   *)
+  (*    drop-out control according to the TrueType specification.          *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    y     :: The pixel's y-coordinate.                                 *)
+  (*                                                                       *)
+  (*    x     :: The pixel's x-coordinate.                                 *)
+  (*                                                                       *)
+  (*    user  :: User-supplied data that is passed to the callback.        *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    1 if the pixel is `set', 0 otherwise.                              *)
+  (*                                                                       *)
+  FT_Raster_BitSet_Func = procedure(y: cint;
+                            x:    cint;
+                            user: Pointer ); cdecl;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Enum>                                                                *)
+  (*    FT_RASTER_FLAG_XXX                                                 *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A list of bit flag constants as used in the `flags' field of a     *)
+  (*    @FT_Raster_Params structure.                                       *)
+  (*                                                                       *)
+  (* <Values>                                                              *)
+  (*    FT_RASTER_FLAG_DEFAULT :: This value is 0.                         *)
+  (*                                                                       *)
+  (*    FT_RASTER_FLAG_AA      :: This flag is set to indicate that an     *)
+  (*                              anti-aliased glyph image should be       *)
+  (*                              generated.  Otherwise, it will be        *)
+  (*                              monochrome (1-bit).                      *)
+  (*                                                                       *)
+  (*    FT_RASTER_FLAG_DIRECT  :: This flag is set to indicate direct      *)
+  (*                              rendering.  In this mode, client         *)
+  (*                              applications must provide their own span *)
+  (*                              callback.  This lets them directly       *)
+  (*                              draw or compose over an existing bitmap. *)
+  (*                              If this bit is not set, the target       *)
+  (*                              pixmap's buffer _must_ be zeroed before  *)
+  (*                              rendering.                               *)
+  (*                                                                       *)
+  (*                              Note that for now, direct rendering is   *)
+  (*                              only possible with anti-aliased glyphs.  *)
+  (*                                                                       *)
+  (*    FT_RASTER_FLAG_CLIP    :: This flag is only used in direct         *)
+  (*                              rendering mode.  If set, the output will *)
+  (*                              be clipped to a box specified in the     *)
+  (*                              `clip_box' field of the                  *)
+  (*                              @FT_Raster_Params structure.             *)
+  (*                                                                       *)
+  (*                              Note that by default, the glyph bitmap   *)
+  (*                              is clipped to the target pixmap, except  *)
+  (*                              in direct rendering mode where all spans *)
+  (*                              are generated if no clipping box is set. *)
+  (*                                                                       *)
+{$ELSE TYPE_DECL}
+const
+  FT_RASTER_FLAG_DEFAULT  = $0;
+  FT_RASTER_FLAG_AA       = $1;
+  FT_RASTER_FLAG_DIRECT   = $2;
+  FT_RASTER_FLAG_CLIP     = $4;
+
+{$ENDIF TYPE_DECL}
+{$IFDEF TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Raster_Params                                                   *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A structure to hold the arguments used by a raster's render        *)
+  (*    function.                                                          *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    target      :: The target bitmap.                                  *)
+  (*                                                                       *)
+  (*    source      :: A pointer to the source glyph image (e.g., an       *)
+  (*                   @FT_Outline).                                       *)
+  (*                                                                       *)
+  (*    flags       :: The rendering flags.                                *)
+  (*                                                                       *)
+  (*    gray_spans  :: The gray span drawing callback.                     *)
+  (*                                                                       *)
+  (*    black_spans :: The black span drawing callback.                    *)
+  (*                                                                       *)
+  (*    bit_test    :: The bit test callback.  UNIMPLEMENTED!              *)
+  (*                                                                       *)
+  (*    bit_set     :: The bit set callback.  UNIMPLEMENTED!               *)
+  (*                                                                       *)
+  (*    user        :: User-supplied data that is passed to each drawing   *)
+  (*                   callback.                                           *)
+  (*                                                                       *)
+  (*    clip_box    :: An optional clipping box.  It is only used in       *)
+  (*                   direct rendering mode.  Note that coordinates here  *)
+  (*                   should be expressed in _integer_ pixels (and not in *)
+  (*                   26.6 fixed-point units).                            *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    An anti-aliased glyph bitmap is drawn if the @FT_RASTER_FLAG_AA    *)
+  (*    bit flag is set in the `flags' field, otherwise a monochrome       *)
+  (*    bitmap is generated.                                               *)
+  (*                                                                       *)
+  (*    If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the      *)
+  (*    raster will call the `gray_spans' callback to draw gray pixel      *)
+  (*    spans, in the case of an aa glyph bitmap, it will call             *)
+  (*    `black_spans', and `bit_test' and `bit_set' in the case of a       *)
+  (*    monochrome bitmap.  This allows direct composition over a          *)
+  (*    pre-existing bitmap through user-provided callbacks to perform the *)
+  (*    span drawing/composition.                                          *)
+  (*                                                                       *)
+  (*    Note that the `bit_test' and `bit_set' callbacks are required when *)
+  (*    rendering a monochrome bitmap, as they are crucial to implement    *)
+  (*    correct drop-out control as defined in the TrueType specification. *)
+  (*                                                                       *)
+  PFT_Raster_Params = ^FT_Raster_Params;
+  FT_Raster_Params = record
+    target:        {const} PFT_Bitmap;
+    source:        {const} Pointer;
+    flags:         cint;
+    gray_spans:    FT_SpanFunc;
+    black_spans:   FT_SpanFunc;
+    bit_test:      FT_Raster_BitTest_Func;     (* doesn't work! *)
+    bit_set:       FT_Raster_BitSet_Func;      (* doesn't work! *)
+    user:          Pointer;
+    clip_box:      FT_BBox;
+  end;
+
+{$ENDIF TYPE_DECL}
+
+
diff --git a/songmanagement/src/lib/freetype/ftoutln.inc b/songmanagement/src/lib/freetype/ftoutln.inc
new file mode 100644
index 00000000..997c6cb3
--- /dev/null
+++ b/songmanagement/src/lib/freetype/ftoutln.inc
@@ -0,0 +1,497 @@
+(***************************************************************************)
+(*                                                                         *)
+(*  ftoutln.h                                                              *)
+(*                                                                         *)
+(*    Support for the FT_Outline type used to store glyph shapes of        *)
+(*    most scalable font formats (specification).                          *)
+(*                                                                         *)
+(*  Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007 by                   *)
+(*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *)
+(*                                                                         *)
+(*  This file is part of the FreeType project, and may only be used,       *)
+(*  modified, and distributed under the terms of the FreeType project      *)
+(*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *)
+(*  this file you indicate that you have read the license and              *)
+(*  understand and accept it fully.                                        *)
+(*                                                                         *)
+(***************************************************************************)
+(***************************************************************************)
+(* Pascal port by the UltraStar Deluxe Team                                *)
+(***************************************************************************)
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Section>                                                             *)
+  (*    outline_processing                                                 *)
+  (*                                                                       *)
+  (* <Title>                                                               *)
+  (*    Outline Processing                                                 *)
+  (*                                                                       *)
+  (* <Abstract>                                                            *)
+  (*    Functions to create, transform, and render vectorial glyph images. *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    This section contains routines used to create and destroy scalable *)
+  (*    glyph images known as `outlines'.  These can also be measured,     *)
+  (*    transformed, and converted into bitmaps and pixmaps.               *)
+  (*                                                                       *)
+  (* <Order>                                                               *)
+  (*    FT_Outline                                                         *)
+  (*    FT_OUTLINE_FLAGS                                                   *)
+  (*    FT_Outline_New                                                     *)
+  (*    FT_Outline_Done                                                    *)
+  (*    FT_Outline_Copy                                                    *)
+  (*    FT_Outline_Translate                                               *)
+  (*    FT_Outline_Transform                                               *)
+  (*    FT_Outline_Embolden                                                *)
+  (*    FT_Outline_Reverse                                                 *)
+  (*    FT_Outline_Check                                                   *)
+  (*                                                                       *)
+  (*    FT_Outline_Get_CBox                                                *)
+  (*    FT_Outline_Get_BBox                                                *)
+  (*                                                                       *)
+  (*    FT_Outline_Get_Bitmap                                              *)
+  (*    FT_Outline_Render                                                  *)
+  (*                                                                       *)
+  (*    FT_Outline_Decompose                                               *)
+  (*    FT_Outline_Funcs                                                   *)
+  (*    FT_Outline_MoveTo_Func                                             *)
+  (*    FT_Outline_LineTo_Func                                             *)
+  (*    FT_Outline_ConicTo_Func                                            *)
+  (*    FT_Outline_CubicTo_Func                                            *)
+  (*                                                                       *)
+  (*************************************************************************)
+
+{$IFNDEF TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Decompose                                               *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Walks over an outline's structure to decompose it into individual  *)
+  (*    segments and Bézier arcs.  This function is also able to emit      *)
+  (*    `move to' and `close to' operations to indicate the start and end  *)
+  (*    of new contours in the outline.                                    *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    outline        :: A pointer to the source target.                  *)
+  (*                                                                       *)
+  (*    func_interface :: A table of `emitters', i.e,. function pointers   *)
+  (*                      called during decomposition to indicate path     *)
+  (*                      operations.                                      *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    user           :: A typeless pointer which is passed to each       *)
+  (*                      emitter during the decomposition.  It can be     *)
+  (*                      used to store the state during the               *)
+  (*                      decomposition.                                   *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  function FT_Outline_Decompose(
+                        outline:        PFT_Outline;
+                        func_interface: {const} PFT_Outline_Funcs;
+                        user:           Pointer): FT_Error;
+    cdecl; external ft_lib name 'FT_Outline_Decompose';
+
+    
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_New                                                     *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Creates a new outline of a given size.                             *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    library     :: A handle to the library object from where the       *)
+  (*                   outline is allocated.  Note however that the new    *)
+  (*                   outline will *not* necessarily be *freed*, when     *)
+  (*                   destroying the library, by @FT_Done_FreeType.       *)
+  (*                                                                       *)
+  (*    numPoints   :: The maximal number of points within the outline.    *)
+  (*                                                                       *)
+  (*    numContours :: The maximal number of contours within the outline.  *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    anoutline   :: A handle to the new outline.  NULL in case of       *)
+  (*                   error.                                              *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    The reason why this function takes a `library' parameter is simply *)
+  (*    to use the library's memory allocator.                             *)
+  (*                                                                       *)
+  function FT_Outline_New(
+                  library_:    FT_Library;
+                  numPoints:   FT_UInt;
+                  numContours: FT_Int;
+                  anoutline:   PFT_Outline): FT_Error;
+    cdecl; external ft_lib name 'FT_Outline_New';
+
+                  
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Done                                                    *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Destroys an outline created with @FT_Outline_New.                  *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    library :: A handle of the library object used to allocate the     *)
+  (*               outline.                                                *)
+  (*                                                                       *)
+  (*    outline :: A pointer to the outline object to be discarded.        *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    If the outline's `owner' field is not set, only the outline        *)
+  (*    descriptor will be released.                                       *)
+  (*                                                                       *)
+  (*    The reason why this function takes an `library' parameter is       *)
+  (*    simply to use ft_mem_free().                                       *)
+  (*                                                                       *)
+  function FT_Outline_Done(library_: FT_Library;
+                           outline:  PFT_Outline): FT_Error;
+    cdecl; external ft_lib name 'FT_Outline_Done';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Check                                                   *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Check the contents of an outline descriptor.                       *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    outline :: A handle to a source outline.                           *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  function FT_Outline_Check( outline: PFT_Outline ): FT_Error;
+    cdecl; external ft_lib name 'FT_Outline_Check';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Get_CBox                                                *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Returns an outline's `control box'.  The control box encloses all  *)
+  (*    the outline's points, including Bézier control points.  Though it  *)
+  (*    coincides with the exact bounding box for most glyphs, it can be   *)
+  (*    slightly larger in some situations (like when rotating an outline  *)
+  (*    which contains Bézier outside arcs).                               *)
+  (*                                                                       *)
+  (*    Computing the control box is very fast, while getting the bounding *)
+  (*    box can take much more time as it needs to walk over all segments  *)
+  (*    and arcs in the outline.  To get the latter, you can use the       *)
+  (*    `ftbbox' component which is dedicated to this single task.         *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    outline :: A pointer to the source outline descriptor.             *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    acbox   :: The outline's control box.                              *)
+  (*                                                                       *)
+  procedure FT_Outline_Get_CBox(
+                       outline: {const} PFT_Outline;
+                       acbox: PFT_BBox);
+    cdecl; external ft_lib name 'FT_Outline_Get_CBox';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Translate                                               *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Applies a simple translation to the points of an outline.          *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    outline :: A pointer to the target outline descriptor.             *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    xOffset :: The horizontal offset.                                  *)
+  (*                                                                       *)
+  (*    yOffset :: The vertical offset.                                    *)
+  (*                                                                       *)
+  procedure FT_Outline_Translate(
+                        outline: {const} PFT_Outline;
+                        xOffset: FT_Pos;
+                        yOffset: FT_Pos);
+    cdecl; external ft_lib name 'FT_Outline_Translate';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Copy                                                    *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Copies an outline into another one.  Both objects must have the    *)
+  (*    same sizes (number of points & number of contours) when this       *)
+  (*    function is called.                                                *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    source :: A handle to the source outline.                          *)
+  (*                                                                       *)
+  (* <Output>                                                              *)
+  (*    target :: A handle to the target outline.                          *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  function FT_Outline_Copy(
+                   source: {const} PFT_Outline;
+                   target: PFT_Outline): FT_Error;
+    cdecl; external ft_lib name 'FT_Outline_Copy';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Transform                                               *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Applies a simple 2x2 matrix to all of an outline's points.  Useful *)
+  (*    for applying rotations, slanting, flipping, etc.                   *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    outline :: A pointer to the target outline descriptor.             *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    matrix  :: A pointer to the transformation matrix.                 *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    You can use @FT_Outline_Translate if you need to translate the     *)
+  (*    outline's points.                                                  *)
+  (*                                                                       *)
+  procedure FT_Outline_Transform(
+                        outline: {const} PFT_Outline;
+                        matrix:  {const} PFT_Matrix);
+    cdecl; external ft_lib name 'FT_Outline_Transform';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Embolden                                                *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Emboldens an outline.  The new outline will be at most 4 times     *)
+  (*    `strength' pixels wider and higher.  You may think of the left and *)
+  (*    bottom borders as unchanged.                                       *)
+  (*                                                                       *)
+  (*    Negative `strength' values to reduce the outline thickness are     *)
+  (*    possible also.                                                     *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    outline  :: A handle to the target outline.                        *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    strength :: How strong the glyph is emboldened.  Expressed in      *)
+  (*                26.6 pixel format.                                     *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    The used algorithm to increase or decrease the thickness of the    *)
+  (*    glyph doesn't change the number of points; this means that certain *)
+  (*    situations like acute angles or intersections are sometimes        *)
+  (*    handled incorrectly.                                               *)
+  (*                                                                       *)
+  (*    Example call:                                                      *)
+  (*                                                                       *)
+  (*    {                                                                  *)
+  (*      FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );                   *)
+  (*      if ( face->slot->format == FT_GLYPH_FORMAT_OUTLINE )             *)
+  (*        FT_Outline_Embolden( &face->slot->outline, strength );         *)
+  (*    }                                                                  *)
+  (*                                                                       *)
+  function FT_Outline_Embolden(
+                       outline:  PFT_Outline;
+                       strength: FT_Pos): FT_Error;
+    cdecl; external ft_lib name 'FT_Outline_Embolden';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Reverse                                                 *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Reverses the drawing direction of an outline.  This is used to     *)
+  (*    ensure consistent fill conventions for mirrored glyphs.            *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    outline :: A pointer to the target outline descriptor.             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    This functions toggles the bit flag @FT_OUTLINE_REVERSE_FILL in    *)
+  (*    the outline's `flags' field.                                       *)
+  (*                                                                       *)
+  (*    It shouldn't be used by a normal client application, unless it     *)
+  (*    knows what it is doing.                                            *)
+  (*                                                                       *)
+  procedure FT_Outline_Reverse( outline: PFT_Outline );
+    cdecl; external ft_lib name 'FT_Outline_Reverse';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Get_Bitmap                                              *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Renders an outline within a bitmap.  The outline's image is simply *)
+  (*    OR-ed to the target bitmap.                                        *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    library :: A handle to a FreeType library object.                  *)
+  (*                                                                       *)
+  (*    outline :: A pointer to the source outline descriptor.             *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    abitmap :: A pointer to the target bitmap descriptor.              *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    This function does NOT CREATE the bitmap, it only renders an       *)
+  (*    outline image within the one you pass to it!                       *)
+  (*                                                                       *)
+  (*    It will use the raster corresponding to the default glyph format.  *)
+  (*                                                                       *)
+  function FT_Outline_Get_Bitmap(
+                         library_: FT_Library;
+                         outline:  PFT_Outline;
+                         abitmap:  {const} PFT_Bitmap): FT_Error;
+    cdecl; external ft_lib name 'FT_Outline_Get_Bitmap';
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Function>                                                            *)
+  (*    FT_Outline_Render                                                  *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Renders an outline within a bitmap using the current scan-convert. *)
+  (*    This functions uses an @FT_Raster_Params structure as an argument, *)
+  (*    allowing advanced features like direct composition, translucency,  *)
+  (*    etc.                                                               *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    library :: A handle to a FreeType library object.                  *)
+  (*                                                                       *)
+  (*    outline :: A pointer to the source outline descriptor.             *)
+  (*                                                                       *)
+  (* <InOut>                                                               *)
+  (*    params  :: A pointer to an @FT_Raster_Params structure used to     *)
+  (*               describe the rendering operation.                       *)
+  (*                                                                       *)
+  (* <Return>                                                              *)
+  (*    FreeType error code.  0 means success.                             *)
+  (*                                                                       *)
+  (* <Note>                                                                *)
+  (*    You should know what you are doing and how @FT_Raster_Params works *)
+  (*    to use this function.                                              *)
+  (*                                                                       *)
+  (*    The field `params.source' will be set to `outline' before the scan *)
+  (*    converter is called, which means that the value you give to it is  *)
+  (*    actually ignored.                                                  *)
+  (*                                                                       *)
+  function FT_Outline_Render(
+                     library_: FT_Library;
+                     outline: PFT_Outline;
+                     params:  PFT_Raster_Params): FT_Error;
+    cdecl; external ft_lib name 'FT_Outline_Render';
+
+{$ENDIF TYPE_DECL}
+
+ (**************************************************************************
+  *
+  * @enum:
+  *   FT_Orientation
+  *
+  * @description:
+  *   A list of values used to describe an outline's contour orientation.
+  *
+  *   The TrueType and Postscript specifications use different conventions
+  *   to determine whether outline contours should be filled or unfilled.
+  *
+  * @values:
+  *   FT_ORIENTATION_TRUETYPE ::
+  *     According to the TrueType specification, clockwise contours must
+  *     be filled, and counter-clockwise ones must be unfilled.
+  *
+  *   FT_ORIENTATION_POSTSCRIPT ::
+  *     According to the Postscript specification, counter-clockwise contours
+  *     must be filled, and clockwise ones must be unfilled.
+  *
+  *   FT_ORIENTATION_FILL_RIGHT ::
+  *     This is identical to @FT_ORIENTATION_TRUETYPE, but is used to
+  *     remember that in TrueType, everything that is to the right of
+  *     the drawing direction of a contour must be filled.
+  *
+  *   FT_ORIENTATION_FILL_LEFT ::
+  *     This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
+  *     remember that in Postscript, everything that is to the left of
+  *     the drawing direction of a contour must be filled.
+  *
+  *   FT_ORIENTATION_NONE ::
+  *     The orientation cannot be determined.  That is, different parts of
+  *     the glyph have different orientation.
+  *
+  *)
+{$IFDEF TYPE_DECL}
+  FT_Orientation = cint;
+{$ELSE TYPE_DECL}
+const
+  FT_ORIENTATION_TRUETYPE   = 0;
+  FT_ORIENTATION_POSTSCRIPT = 1;
+  FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE;
+  FT_ORIENTATION_FILL_LEFT  = FT_ORIENTATION_POSTSCRIPT;
+  FT_ORIENTATION_NONE       = FT_ORIENTATION_FILL_LEFT+1;
+
+ (**************************************************************************
+  *
+  * @function:
+  *   FT_Outline_Get_Orientation
+  *
+  * @description:
+  *   This function analyzes a glyph outline and tries to compute its
+  *   fill orientation (see @FT_Orientation).  This is done by computing
+  *   the direction of each global horizontal and/or vertical extrema
+  *   within the outline.
+  *
+  *   Note that this will return @FT_ORIENTATION_TRUETYPE for empty
+  *   outlines.
+  *
+  * @input:
+  *   outline ::
+  *     A handle to the source outline.
+  *
+  * @return:
+  *   The orientation.
+  *
+  *)
+  function FT_Outline_Get_Orientation( outline: PFT_Outline ): FT_Orientation;
+    cdecl; external ft_lib name 'FT_Outline_Get_Orientation';
+
+{$ENDIF TYPE_DECL}
+  
diff --git a/songmanagement/src/lib/freetype/ftstroke.inc b/songmanagement/src/lib/freetype/ftstroke.inc
new file mode 100644
index 00000000..bf8a00ae
--- /dev/null
+++ b/songmanagement/src/lib/freetype/ftstroke.inc
@@ -0,0 +1,711 @@
+{***************************************************************************}
+{*                                                                         *}
+{*  ftstroke.h                                                             *}
+{*                                                                         *}
+{*    FreeType path stroker (specification).                               *}
+{*                                                                         *}
+{*  Copyright 2002, 2003, 2004, 2005, 2006 by                              *}
+{*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *}
+{*                                                                         *}
+{*  This file is part of the FreeType project, and may only be used,       *}
+{*  modified, and distributed under the terms of the FreeType project      *}
+{*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *}
+{*  this file you indicate that you have read the license and              *}
+{*  understand and accept it fully.                                        *}
+{*                                                                         *}
+{***************************************************************************}
+(***************************************************************************)
+(* Pascal port by the UltraStar Deluxe Team                                *)
+(***************************************************************************)
+
+ {************************************************************************
+  *
+  * @section:
+  *    glyph_stroker
+  *
+  * @title:
+  *    Glyph Stroker
+  *
+  * @abstract:
+  *    Generating bordered and stroked glyphs.
+  *
+  * @description:
+  *    This component generates stroked outlines of a given vectorial
+  *    glyph.  It also allows you to retrieve the `outside' and/or the
+  *    `inside' borders of the stroke.
+  *
+  *    This can be useful to generate `bordered' glyph, i.e., glyphs
+  *    displayed with a coloured (and anti-aliased) border around their
+  *    shape.
+  *}
+
+{$IFDEF TYPE_DECL}
+
+ {**************************************************************
+  *
+  * @type:
+  *   FT_Stroker
+  *
+  * @description:
+  *   Opaque handler to a path stroker object.
+  *}
+   FT_Stroker = Pointer;
+
+
+  {**************************************************************
+   *
+   * @enum:
+   *   FT_Stroker_LineJoin
+   *
+   * @description:
+   *   These values determine how two joining lines are rendered
+   *   in a stroker.
+   *
+   * @values:
+   *   FT_STROKER_LINEJOIN_ROUND ::
+   *     Used to render rounded line joins.  Circular arcs are used
+   *     to join two lines smoothly.
+   *
+   *   FT_STROKER_LINEJOIN_BEVEL ::
+   *     Used to render beveled line joins; i.e., the two joining lines
+   *     are extended until they intersect.
+   *
+   *   FT_STROKER_LINEJOIN_MITER ::
+   *     Same as beveled rendering, except that an additional line
+   *     break is added if the angle between the two joining lines
+   *     is too closed (this is useful to avoid unpleasant spikes
+   *     in beveled rendering).
+   *}
+    FT_Stroker_LineJoin = cint;
+{$ELSE TYPE_DECL}
+const
+    FT_STROKER_LINEJOIN_ROUND = 0;
+    FT_STROKER_LINEJOIN_BEVEL = 1;
+    FT_STROKER_LINEJOIN_MITER = 2;
+
+{$ENDIF TYPE_DECL}
+{$IFDEF TYPE_DECL}
+
+  {**************************************************************
+   *
+   * @enum:
+   *   FT_Stroker_LineCap
+   *
+   * @description:
+   *   These values determine how the end of opened sub-paths are
+   *   rendered in a stroke.
+   *
+   * @values:
+   *   FT_STROKER_LINECAP_BUTT ::
+   *     The end of lines is rendered as a full stop on the last
+   *     point itself.
+   *
+   *   FT_STROKER_LINECAP_ROUND ::
+   *     The end of lines is rendered as a half-circle around the
+   *     last point.
+   *
+   *   FT_STROKER_LINECAP_SQUARE ::
+   *     The end of lines is rendered as a square around the
+   *     last point.
+   *}
+    FT_Stroker_LineCap = cint;
+{$ELSE TYPE_DECL}
+const
+    FT_STROKER_LINECAP_BUTT   = 0;
+    FT_STROKER_LINECAP_ROUND  = 1;
+    FT_STROKER_LINECAP_SQUARE = 2;
+
+{$ENDIF TYPE_DECL}
+{$IFDEF TYPE_DECL}
+
+  {**************************************************************
+   *
+   * @enum:
+   *   FT_StrokerBorder
+   *
+   * @description:
+   *   These values are used to select a given stroke border
+   *   in @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder.
+   *
+   * @values:
+   *   FT_STROKER_BORDER_LEFT ::
+   *     Select the left border, relative to the drawing direction.
+   *
+   *   FT_STROKER_BORDER_RIGHT ::
+   *     Select the right border, relative to the drawing direction.
+   *
+   * @note:
+   *   Applications are generally interested in the `inside' and `outside'
+   *   borders.  However, there is no direct mapping between these and the
+   *   `left' and `right' ones, since this really depends on the glyph's
+   *   drawing orientation, which varies between font formats.
+   *
+   *   You can however use @FT_Outline_GetInsideBorder and
+   *   @FT_Outline_GetOutsideBorder to get these.
+   *}
+    FT_StrokerBorder = cint;
+{$ELSE TYPE_DECL}
+const
+    FT_STROKER_BORDER_LEFT  = 0;
+    FT_STROKER_BORDER_RIGHT = 1;
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Outline_GetInsideBorder
+   *
+   * @description:
+   *   Retrieve the @FT_StrokerBorder value corresponding to the
+   *   `inside' borders of a given outline.
+   *
+   * @input:
+   *   outline ::
+   *     The source outline handle.
+   *
+   * @return:
+   *   The border index.  @FT_STROKER_BORDER_LEFT for empty or invalid
+   *   outlines.
+   *}
+  function FT_Outline_GetInsideBorder( outline: PFT_Outline ): FT_StrokerBorder;
+    cdecl; external ft_lib name 'FT_Outline_GetInsideBorder';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Outline_GetOutsideBorder
+   *
+   * @description:
+   *   Retrieve the @FT_StrokerBorder value corresponding to the
+   *   `outside' borders of a given outline.
+   *
+   * @input:
+   *   outline ::
+   *     The source outline handle.
+   *
+   * @return:
+   *   The border index.  @FT_STROKER_BORDER_LEFT for empty or invalid
+   *   outlines.
+   *}
+  function FT_Outline_GetOutsideBorder( outline: PFT_Outline ): FT_StrokerBorder;
+    cdecl; external ft_lib name 'FT_Outline_GetOutsideBorder';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_New
+   *
+   * @description:
+   *   Create a new stroker object.
+   *
+   * @input:
+   *   library ::
+   *     FreeType library handle.
+   *
+   * @output:
+   *   astroker ::
+   *     A new stroker object handle.  NULL in case of error.
+   *
+   * @return:
+   *    FreeType error code.  0 means success.
+   *}
+  function FT_Stroker_New(
+                  library_: FT_Library;
+                  out astroker: FT_Stroker ): FT_Error;
+    cdecl; external ft_lib name 'FT_Stroker_New';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_Set
+   *
+   * @description:
+   *   Reset a stroker object's attributes.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   *   radius ::
+   *     The border radius.
+   *
+   *   line_cap ::
+   *     The line cap style.
+   *
+   *   line_join ::
+   *     The line join style.
+   *
+   *   miter_limit ::
+   *     The miter limit for the FT_STROKER_LINEJOIN_MITER style,
+   *     expressed as 16.16 fixed point value.
+   *
+   * @note:
+   *   The radius is expressed in the same units that the outline
+   *   coordinates.
+   *}
+  procedure FT_Stroker_Set(
+                  stroker:     FT_Stroker;
+                  radius:      FT_Fixed;
+                  line_cap:    FT_Stroker_LineCap;
+                  line_join:   FT_Stroker_LineJoin;
+                  miter_limit: FT_Fixed );
+    cdecl; external ft_lib name 'FT_Stroker_Set';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_Rewind
+   *
+   * @description:
+   *   Reset a stroker object without changing its attributes.
+   *   You should call this function before beginning a new
+   *   series of calls to @FT_Stroker_BeginSubPath or
+   *   @FT_Stroker_EndSubPath.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *}
+  procedure FT_Stroker_Rewind( stroker: FT_Stroker );
+    cdecl; external ft_lib name 'FT_Stroker_Rewind';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_ParseOutline
+   *
+   * @description:
+   *   A convenience function used to parse a whole outline with
+   *   the stroker.  The resulting outline(s) can be retrieved
+   *   later by functions like @FT_Stroker_GetCounts and @FT_Stroker_Export.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   *   outline ::
+   *     The source outline.
+   *
+   *   opened ::
+   *     A boolean.  If 1, the outline is treated as an open path instead
+   *     of a closed one.
+   *
+   * @return:
+   *   FreeType error code.  0 means success.
+   *
+   * @note:
+   *   If `opened' is 0 (the default), the outline is treated as a closed
+   *   path, and the stroker will generate two distinct `border' outlines.
+   *
+   *   If `opened' is 1, the outline is processed as an open path, and the
+   *   stroker will generate a single `stroke' outline.
+   *
+   *   This function calls @FT_Stroker_Rewind automatically.
+   *}
+  function FT_Stroker_ParseOutline(
+                           stroker: FT_Stroker;
+                           outline: PFT_Outline;
+                           opened:  FT_Bool): FT_Error;
+    cdecl; external ft_lib name 'FT_Stroker_ParseOutline';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_BeginSubPath
+   *
+   * @description:
+   *   Start a new sub-path in the stroker.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   *   to ::
+   *     A pointer to the start vector.
+   *
+   *   open ::
+   *     A boolean.  If 1, the sub-path is treated as an open one.
+   *
+   * @return:
+   *   FreeType error code.  0 means success.
+   *
+   * @note:
+   *   This function is useful when you need to stroke a path that is
+   *   not stored as an @FT_Outline object.
+   *}
+  function FT_Stroker_BeginSubPath(
+                           stroker: FT_Stroker;
+                           to_:     PFT_Vector;
+                           open:    FT_Bool ): FT_Error;
+    cdecl; external ft_lib name 'FT_Stroker_BeginSubPath';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_EndSubPath
+   *
+   * @description:
+   *   Close the current sub-path in the stroker.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   * @return:
+   *   FreeType error code.  0 means success.
+   *
+   * @note:
+   *   You should call this function after @FT_Stroker_BeginSubPath.
+   *   If the subpath was not `opened', this function will `draw' a
+   *   single line segment to the start position when needed.
+   *}
+  function FT_Stroker_EndSubPath( stroker: FT_Stroker ): FT_Error;
+    cdecl; external ft_lib name 'FT_Stroker_EndSubPath';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_LineTo
+   *
+   * @description:
+   *   `Draw' a single line segment in the stroker's current sub-path,
+   *   from the last position.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   *   to ::
+   *     A pointer to the destination point.
+   *
+   * @return:
+   *   FreeType error code.  0 means success.
+   *
+   * @note:
+   *   You should call this function between @FT_Stroker_BeginSubPath and
+   *   @FT_Stroker_EndSubPath.
+   *}
+  function FT_Stroker_LineTo(
+                     stroker: FT_Stroker;
+                     to_:     PFT_Vector ): FT_Error;
+    cdecl; external ft_lib name 'FT_Stroker_LineTo';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_ConicTo
+   *
+   * @description:
+   *   `Draw' a single quadratic Bézier in the stroker's current sub-path,
+   *   from the last position.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   *   control ::
+   *     A pointer to a Bézier control point.
+   *
+   *   to ::
+   *     A pointer to the destination point.
+   *
+   * @return:
+   *   FreeType error code.  0 means success.
+   *
+   * @note:
+   *   You should call this function between @FT_Stroker_BeginSubPath and
+   *   @FT_Stroker_EndSubPath.
+   *}
+  function FT_Stroker_ConicTo(
+                      stroker: FT_Stroker;
+                      control: PFT_Vector;
+                      to_:     PFT_Vector ): FT_Error;
+    cdecl; external ft_lib name 'FT_Stroker_ConicTo';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_CubicTo
+   *
+   * @description:
+   *   `Draw' a single cubic Bézier in the stroker's current sub-path,
+   *   from the last position.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   *   control1 ::
+   *     A pointer to the first Bézier control point.
+   *
+   *   control2 ::
+   *     A pointer to second Bézier control point.
+   *
+   *   to ::
+   *     A pointer to the destination point.
+   *
+   * @return:
+   *   FreeType error code.  0 means success.
+   *
+   * @note:
+   *   You should call this function between @FT_Stroker_BeginSubPath and
+   *   @FT_Stroker_EndSubPath.
+   *}
+  function FT_Stroker_CubicTo(
+                      stroker:  FT_Stroker;
+                      control1: PFT_Vector;
+                      control2: PFT_Vector;
+                      to_:      PFT_Vector ): FT_Error;
+    cdecl; external ft_lib name 'FT_Stroker_CubicTo';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_GetBorderCounts
+   *
+   * @description:
+   *   Call this function once you have finished parsing your paths
+   *   with the stroker.  It will return the number of points and
+   *   contours necessary to export one of the `border' or `stroke'
+   *   outlines generated by the stroker.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   *   border ::
+   *     The border index.
+   *
+   * @output:
+   *   anum_points ::
+   *     The number of points.
+   *
+   *   anum_contours ::
+   *     The number of contours.
+   *
+   * @return:
+   *   FreeType error code.  0 means success.
+   *
+   * @note:
+   *   When an outline, or a sub-path, is `closed', the stroker generates
+   *   two independent `border' outlines, named `left' and `right'.
+   *
+   *   When the outline, or a sub-path, is `opened', the stroker merges
+   *   the `border' outlines with caps.  The `left' border receives all
+   *   points, while the `right' border becomes empty.
+   *
+   *   Use the function @FT_Stroker_GetCounts instead if you want to
+   *   retrieve the counts associated to both borders.
+   *}
+  function FT_Stroker_GetBorderCounts(
+                              stroker:           FT_Stroker;
+                              border:            FT_StrokerBorder;
+                              out anum_points:   FT_UInt;
+                              out anum_contours: FT_UInt ): FT_Error;
+    cdecl; external ft_lib name 'FT_Stroker_GetBorderCounts';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_ExportBorder
+   *
+   * @description:
+   *   Call this function after @FT_Stroker_GetBorderCounts to
+   *   export the corresponding border to your own @FT_Outline
+   *   structure.
+   *
+   *   Note that this function will append the border points and
+   *   contours to your outline, but will not try to resize its
+   *   arrays.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   *   border ::
+   *     The border index.
+   *
+   *   outline ::
+   *     The target outline handle.
+   *
+   * @note:
+   *   Always call this function after @FT_Stroker_GetBorderCounts to
+   *   get sure that there is enough room in your @FT_Outline object to
+   *   receive all new data.
+   *
+   *   When an outline, or a sub-path, is `closed', the stroker generates
+   *   two independent `border' outlines, named `left' and `right'
+   *
+   *   When the outline, or a sub-path, is `opened', the stroker merges
+   *   the `border' outlines with caps. The `left' border receives all
+   *   points, while the `right' border becomes empty.
+   *
+   *   Use the function @FT_Stroker_Export instead if you want to
+   *   retrieve all borders at once.
+   *}
+  procedure FT_Stroker_ExportBorder(
+                           stroker: FT_Stroker;
+                           border:  FT_StrokerBorder;
+                           outline: PFT_Outline );
+    cdecl; external ft_lib name 'FT_Stroker_ExportBorder';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_GetCounts
+   *
+   * @description:
+   *   Call this function once you have finished parsing your paths
+   *   with the stroker.  It returns the number of points and
+   *   contours necessary to export all points/borders from the stroked
+   *   outline/path.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   * @output:
+   *   anum_points ::
+   *     The number of points.
+   *
+   *   anum_contours ::
+   *     The number of contours.
+   *
+   * @return:
+   *   FreeType error code.  0 means success.
+   *}
+  function FT_Stroker_GetCounts(
+                        stroker:           FT_Stroker;
+                        out anum_points:   FT_UInt;
+                        out anum_contours: FT_UInt ): FT_Error;
+     cdecl; external ft_lib name 'FT_Stroker_GetCounts';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_Export
+   *
+   * @description:
+   *   Call this function after @FT_Stroker_GetBorderCounts to
+   *   export the all borders to your own @FT_Outline structure.
+   *
+   *   Note that this function will append the border points and
+   *   contours to your outline, but will not try to resize its
+   *   arrays.
+   *
+   * @input:
+   *   stroker ::
+   *     The target stroker handle.
+   *
+   *   outline ::
+   *     The target outline handle.
+   *}
+  procedure FT_Stroker_Export(
+                     stroker: FT_Stroker;
+                     outline: PFT_Outline );
+     cdecl; external ft_lib name 'FT_Stroker_Export';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Stroker_Done
+   *
+   * @description:
+   *   Destroy a stroker object.
+   *
+   * @input:
+   *   stroker ::
+   *     A stroker handle.  Can be NULL.
+   *}
+  procedure FT_Stroker_Done( stroker: FT_Stroker );
+     cdecl; external ft_lib name 'FT_Stroker_Done';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Glyph_Stroke
+   *
+   * @description:
+   *   Stroke a given outline glyph object with a given stroker.
+   *
+   * @inout:
+   *   pglyph ::
+   *     Source glyph handle on input, new glyph handle on output.
+   *
+   * @input:
+   *   stroker ::
+   *     A stroker handle.
+   *
+   *   destroy ::
+   *     A Boolean.  If 1, the source glyph object is destroyed
+   *     on success.
+   *
+   * @return:
+   *    FreeType error code.  0 means success.
+   *
+   * @note:
+   *   The source glyph is untouched in case of error.
+   *}
+  function FT_Glyph_Stroke(
+                   var glyph: FT_Glyph;
+                   stroker: FT_Stroker;
+                   destroy: FT_Bool ): FT_Error;
+     cdecl; external ft_lib name 'FT_Glyph_Stroke';
+
+
+  {**************************************************************
+   *
+   * @function:
+   *   FT_Glyph_StrokeBorder
+   *
+   * @description:
+   *   Stroke a given outline glyph object with a given stroker, but
+   *   only return either its inside or outside border.
+   *
+   * @inout:
+   *   pglyph ::
+   *     Source glyph handle on input, new glyph handle on output.
+   *
+   * @input:
+   *   stroker ::
+   *     A stroker handle.
+   *
+   *   inside ::
+   *     A Boolean.  If 1, return the inside border, otherwise
+   *     the outside border.
+   *
+   *   destroy ::
+   *     A Boolean.  If 1, the source glyph object is destroyed
+   *     on success.
+   *
+   * @return:
+   *    FreeType error code.  0 means success.
+   *
+   * @note:
+   *   The source glyph is untouched in case of error.
+   *}
+  function FT_Glyph_StrokeBorder(
+                         var glyph: FT_Glyph;
+                         stroker:   FT_Stroker;
+                         inside:    FT_Bool;
+                         destroy:   FT_Bool ): FT_Error;
+     cdecl; external ft_lib name 'FT_Glyph_StrokeBorder';
+
+{$ENDIF TYPE_DECL}
+
diff --git a/songmanagement/src/lib/freetype/fttypes.inc b/songmanagement/src/lib/freetype/fttypes.inc
new file mode 100644
index 00000000..a64432e6
--- /dev/null
+++ b/songmanagement/src/lib/freetype/fttypes.inc
@@ -0,0 +1,311 @@
+(***************************************************************************)
+(*                                                                         *)
+(*  fttypes.h                                                              *)
+(*                                                                         *)
+(*    FreeType simple types definitions (specification only).              *)
+(*                                                                         *)
+(*  Copyright 1996-2001, 2002, 2004, 2006, 2007 by                         *)
+(*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *)
+(*                                                                         *)
+(*  This file is part of the FreeType project, and may only be used,       *)
+(*  modified, and distributed under the terms of the FreeType project      *)
+(*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *)
+(*  this file you indicate that you have read the license and              *)
+(*  understand and accept it fully.                                        *)
+(*                                                                         *)
+(***************************************************************************)
+(***************************************************************************)
+(* Pascal port by the UltraStar Deluxe Team                                *)
+(***************************************************************************)
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Section>                                                             *)
+  (*    basic_types                                                        *)
+  (*                                                                       *)
+  (* <Title>                                                               *)
+  (*    Basic Data Types                                                   *)
+  (*                                                                       *)
+  (* <Abstract>                                                            *)
+  (*    The basic data types defined by the library.                       *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    This section contains the basic data types defined by FreeType 2,  *)
+  (*    ranging from simple scalar types to bitmap descriptors.  More      *)
+  (*    font-specific structures are defined in a different section.       *)
+  (*                                                                       *)
+  (* <Order>                                                               *)
+  (*    FT_Byte                                                            *)
+  (*    FT_Bytes                                                           *)
+  (*    FT_Char                                                            *)
+  (*    FT_Int                                                             *)
+  (*    FT_UInt                                                            *)
+  (*    FT_Short                                                           *)
+  (*    FT_UShort                                                          *)
+  (*    FT_Long                                                            *)
+  (*    FT_ULong                                                           *)
+  (*    FT_Bool                                                            *)
+  (*    FT_Offset                                                          *)
+  (*    FT_PtrDist                                                         *)
+  (*    FT_String                                                          *)
+  (*    FT_Tag                                                             *)
+  (*    FT_Error                                                           *)
+  (*    FT_Fixed                                                           *)
+  (*    FT_Pointer                                                         *)
+  (*    FT_Pos                                                             *)
+  (*    FT_Vector                                                          *)
+  (*    FT_BBox                                                            *)
+  (*    FT_Matrix                                                          *)
+  (*    FT_FWord                                                           *)
+  (*    FT_UFWord                                                          *)
+  (*    FT_F2Dot14                                                         *)
+  (*    FT_UnitVector                                                      *)
+  (*    FT_F26Dot6                                                         *)
+  (*                                                                       *)
+  (*                                                                       *)
+  (*    FT_Generic                                                         *)
+  (*    FT_Generic_Finalizer                                               *)
+  (*                                                                       *)
+  (*    FT_Bitmap                                                          *)
+  (*    FT_Pixel_Mode                                                      *)
+  (*    FT_Palette_Mode                                                    *)
+  (*    FT_Glyph_Format                                                    *)
+  (*    FT_IMAGE_TAG                                                       *)
+  (*                                                                       *)
+  (*************************************************************************)
+
+{$IFDEF TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Bool                                                            *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A typedef of unsigned char, used for simple booleans.  As usual,   *)
+  (*    values 1 and 0 represent true and false, respectively.             *)
+  (*                                                                       *)
+  FT_Bool    = cuchar;
+{$ENDIF TYPE_DECL}
+{$IFNDEF TYPE_DECL}
+const
+  FT_FALSE = 0;
+  FT_TRUE  = 1;
+{$ENDIF !TYPE_DECL}
+{$IFDEF TYPE_DECL}
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Byte                                                            *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A simple typedef for the _unsigned_ char type.                     *)
+  (*                                                                       *)
+  FT_Byte    = cuchar;
+  PFT_Byte   = ^FT_Byte;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_String                                                          *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A simple typedef for the char type, usually used for strings.      *)
+  (*                                                                       *)
+  FT_String  = cchar;
+  PFT_String = ^FT_String;
+
+  
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Short                                                           *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A typedef for signed short.                                        *)
+  (*                                                                       *)
+  FT_Short   = csshort;
+  PFT_Short  = ^FT_Short;
+
+  PFT_ShortArray = ^FT_ShortArray;
+  FT_ShortArray = array[0 .. (MaxInt div SizeOf(FT_Short))-1] of FT_Short;
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_UShort                                                          *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A typedef for unsigned short.                                      *)
+  (*                                                                       *)
+  FT_UShort  = cushort;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Int                                                             *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A typedef for the int type.                                        *)
+  (*                                                                       *)
+  FT_Int     = csint;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_UInt                                                            *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A typedef for the unsigned int type.                               *)
+  (*                                                                       *)
+  FT_UInt    = cuint;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Long                                                            *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A typedef for signed long.                                         *)
+  (*                                                                       *)
+  FT_Long    = cslong;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_ULong                                                           *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A typedef for unsigned long.                                       *)
+  (*                                                                       *)
+  FT_ULong   = culong;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_F26Dot6                                                         *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A signed 26.6 fixed float type used for vectorial pixel            *)
+  (*    coordinates.                                                       *)
+  (*                                                                       *)
+  FT_F26Dot6 = cslong;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Fixed                                                           *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    This type is used to store 16.16 fixed float values, like scaling  *)
+  (*    values or matrix coefficients.                                     *)
+  (*                                                                       *)
+  FT_Fixed   = cslong;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Type>                                                                *)
+  (*    FT_Error                                                           *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    The FreeType error code type.  A value of 0 is always interpreted  *)
+  (*    as a successful operation.                                         *)
+  (*                                                                       *)
+  FT_Error   = cint;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Matrix                                                          *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    A simple structure used to store a 2x2 matrix.  Coefficients are   *)
+  (*    in 16.16 fixed float format.  The computation performed is:        *)
+  (*                                                                       *)
+  (*       {                                                               *)
+  (*          x' = x*xx + y*xy                                             *)
+  (*          y' = x*yx + y*yy                                             *)
+  (*       }                                                               *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    xx :: Matrix coefficient.                                          *)
+  (*                                                                       *)
+  (*    xy :: Matrix coefficient.                                          *)
+  (*                                                                       *)
+  (*    yx :: Matrix coefficient.                                          *)
+  (*                                                                       *)
+  (*    yy :: Matrix coefficient.                                          *)
+  (*                                                                       *)
+  PFT_Matrix = ^FT_Matrix;
+  FT_Matrix = record
+    xx, xy: FT_Fixed;
+    yx, yy: FT_Fixed;
+  end;
+
+  
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <FuncType>                                                            *)
+  (*    FT_Generic_Finalizer                                               *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Describes a function used to destroy the `client' data of any      *)
+  (*    FreeType object.  See the description of the FT_Generic type for   *)
+  (*    details of usage.                                                  *)
+  (*                                                                       *)
+  (* <Input>                                                               *)
+  (*    The address of the FreeType object which is under finalization.    *)
+  (*    Its client data is accessed through its `generic' field.           *)
+  (*                                                                       *)
+  FT_Generic_Finalizer = procedure(AnObject : pointer ); cdecl;
+
+
+  (*************************************************************************)
+  (*                                                                       *)
+  (* <Struct>                                                              *)
+  (*    FT_Generic                                                         *)
+  (*                                                                       *)
+  (* <Description>                                                         *)
+  (*    Client applications often need to associate their own data to a    *)
+  (*    variety of FreeType core objects.  For example, a text layout API  *)
+  (*    might want to associate a glyph cache to a given size object.      *)
+  (*                                                                       *)
+  (*    Most FreeType object contains a `generic' field, of type           *)
+  (*    FT_Generic, which usage is left to client applications and font    *)
+  (*    servers.                                                           *)
+  (*                                                                       *)
+  (*    It can be used to store a pointer to client-specific data, as well *)
+  (*    as the address of a `finalizer' function, which will be called by  *)
+  (*    FreeType when the object is destroyed (for example, the previous   *)
+  (*    client example would put the address of the glyph cache destructor *)
+  (*    in the `finalizer' field).                                         *)
+  (*                                                                       *)
+  (* <Fields>                                                              *)
+  (*    data      :: A typeless pointer to any client-specified data. This *)
+  (*                 field is completely ignored by the FreeType library.  *)
+  (*                                                                       *)
+  (*    finalizer :: A pointer to a `generic finalizer' function, which    *)
+  (*                 will be called when the object is destroyed.  If this *)
+  (*                 field is set to NULL, no code will be called.         *)
+  (*                                                                       *)
+  FT_Generic = record
+    data:      pointer;
+    finalizer: FT_Generic_Finalizer;
+  end;
+
+
+  TByteArray = array [0 .. (MaxInt div SizeOf(byte))-1] of byte;
+  PByteArray = ^TByteArray;
+
+{$ENDIF TYPE_DECL}
+
diff --git a/songmanagement/src/lib/lib-info.txt b/songmanagement/src/lib/lib-info.txt
new file mode 100644
index 00000000..0a184568
--- /dev/null
+++ b/songmanagement/src/lib/lib-info.txt
@@ -0,0 +1,60 @@
+bass:
+http://www.un4seen.com/ (2.4.2.1)
+- FPC Mac OS X compatibility fixes
+
+fft:
+translation of audacity's FFT.cpp by hennymcc (maybe replace this with FFTW?)
+
+ffmpeg:
+- http://www.iversenit.dk/dev/ffmpeg-headers/: 2006-10
+- several bugs were fixed
+- many IFDEFS were added to the header to support multiple versions of ffmpeg (starting with end of 2006) and not only one specific version. This is necessary as we cannot control which version is used on linux. We could ship the ffmpeg lib with USDX and link statically but a stripped down ffmpeg is 15MB in size and takes 5 minutes to compile (so static linkage is not a good option).
+- the headers were updated to reflect the changes in the ffmpeg C-headers (http://svn.mplayerhq.hu/ffmpeg/trunk/ and http://svn.mplayerhq.hu/mplayer/trunk/libswscale/)
+
+freeimage:
+- inserted by eddie. Some compatibility fixes for platforms different than mac os x.
+- not used anymore
+
+freetype:
+- based on the AggPas (http://aggpas.org/) headers
+- just a minimal header that contains only some of the freetype functions and types. Some functions and structures/constants/types needed for USDX were added.
+- some comments added
+
+jedi-sdl:
+JEDI-SDL v1.0 Final RC 2 (http://jedi-sdl.pascalgamedevelopment.com/)
+- 64bit compatibility patch (http://sourceforge.net/tracker/index.php?func=detail&aid=1902924&group_id=43805&atid=437446)
+- some Mac OS X patches from freepascal trunk
+- some additional patched (see *.patch)
+
+midi:
+taken from http://www.torry.net/authorsmore.php?id=1615 (TMidiPlayer)
+- FPC (Win32) compatibility fixes
+- Win32 only. Maybe use some timidity stuff under linux.
+
+libpng:
+autocreated H2Pas file taken from freepascal trunk
+- bug fixes (especially H2Pas related stuff like wrong file types)
+- delphi compatibility
+- comments added
+
+portaudio:
+translation of the (patched) audacity C headers by hennymcc.
+See http://audacity.cvs.sourceforge.net/viewvc/audacity/lib-src/portaudio-v19/include/?sortdir=down
+
+portmixer:
+translation of the (patched) audacity C headers by hennymcc.
+- Unlike portaudio portmixer is part of audacity and there is no linux package for it. If we want to use it for linux, we have to link it statically. Unfortunately it requires a patched version of portaudio (which is part of audacity and statically linked to) so we have to statically link portaudio too :(.
+
+projectM:
+translation of the original C++ headers and C-wrapper by hennymcc
+
+samplerate:
+translation of the original C headers by profoX/hennymcc
+
+sqlite:
+taken from http://www.itwriting.com/blog/a-simple-delphi-wrapper-for-sqlite-3
+- slightly patched: see *.patch files for what has been patched (e.g. Binding)
+
+zlib:
+taken from freepascal (slightly patched)
+- delphi compatibility
\ No newline at end of file
diff --git a/songmanagement/src/lib/libpng/png.pas b/songmanagement/src/lib/libpng/png.pas
new file mode 100644
index 00000000..0092dde3
--- /dev/null
+++ b/songmanagement/src/lib/libpng/png.pas
@@ -0,0 +1,974 @@
+(*
+ * libpng pascal headers
+ * Version: 1.2.12
+ *)
+
+{$IFDEF FPC}
+  {$ifndef NO_SMART_LINK}
+  {$smartlink on}
+  {$endif}
+{$ENDIF}
+
+unit png;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKRECORDS C}
+{$ENDIF}
+
+uses
+  ctypes,
+  {$IFDEF MSWINDOWS}
+  Windows,
+  {$ENDIF}
+  {$IFDEF UNIX}
+  baseunix,
+  {$ENDIF}
+  zlib;
+
+const
+{$IFDEF MSWINDOWS}
+  // use libpng12-0 (Version 1.2.18), delivered wih SDL_Image
+  LibPng = 'libpng12-0'; // 'libpng13';
+  // matching lib version for libpng13.dll, needed for initialization
+  PNG_LIBPNG_VER_STRING='1.2.12';
+  // define the compiler that was used to built the DLL (necessary for jmp_buf)
+  // SDL_Image was compiled with GCC
+  //{$define MSVC_DLL} // MS Visual C++
+  {$DEFINE GCC_DLL}  // GCC
+{$ELSE}
+  LibPng = 'png';
+  // matching lib version for libpng, needed for initialization
+  PNG_LIBPNG_VER_STRING='1.2.12';
+  {$IFDEF DARWIN}
+    {$linklib libpng}
+  {$ENDIF}
+{$ENDIF}
+
+
+{$IFDEF MSWINDOWS}
+const
+   // JB_LEN (#elements in jmp_buf) depends on the compiler used to compile the DLL
+   //   MSVC++: 16 (x86/AMD64), GCC: 52
+   {$IF Defined(MSVC_DLL)}
+   JB_LEN = 16;
+   {$ELSEIF Defined(GCC_DLL)}
+   JB_LEN = 52;
+   {$ELSE}
+   JB_LEN = 0;
+   {$IFEND}
+{$ENDIF}
+
+type
+   {$IFNDEF FPC}
+   // defines for Delphi
+   size_t = culong;
+   {$ENDIF}
+
+   {$ifdef MSWINDOWS}
+     {$if JB_LEN > 0}
+     jmp_buf = array[0..JB_LEN-1] of cint;
+     // the png_struct cannot be accessed if the size of jmp_buf is unknown
+     {$define UsePngStruct}
+     {$ifend}
+     // Do NOT use time_t on windows! It might be 32 or 64bit, depending on the compiler and system.
+     // MSVS-2005 starts using 64bit for time_t on x86 by default, but GCC uses just 32bit.
+     //time_t = clong;
+   {$endif}
+
+   z_stream = TZStream;
+
+   png_uint_32 = cuint32;
+   png_int_32 = cint32;
+   png_uint_16 = cuint16;
+   png_int_16 = cint16;
+   png_byte = cuint8;
+   ppng_uint_32 = ^png_uint_32;
+   ppng_int_32 = ^png_int_32;
+   ppng_uint_16 = ^png_uint_16;
+   ppng_int_16 = ^png_int_16;
+   ppng_byte = ^png_byte;
+   pppng_uint_32 = ^ppng_uint_32;
+   pppng_int_32 = ^ppng_int_32;
+   pppng_uint_16 = ^ppng_uint_16;
+   pppng_int_16 = ^ppng_int_16;
+   pppng_byte = ^ppng_byte;
+   png_size_t = size_t;
+   png_fixed_point = png_int_32;
+   ppng_fixed_point = ^png_fixed_point;
+   pppng_fixed_point = ^ppng_fixed_point;
+   png_voidp = pointer;
+   png_bytep = Ppng_byte;
+   ppng_bytep = ^png_bytep;
+   png_uint_32p = Ppng_uint_32;
+   png_int_32p = Ppng_int_32;
+   png_uint_16p = Ppng_uint_16;
+   ppng_uint_16p = ^png_uint_16p;
+   png_int_16p = Ppng_int_16;
+   png_const_charp = {const} Pchar;
+   png_charp = Pchar;
+   ppng_charp = ^png_charp;
+   png_fixed_point_p = Ppng_fixed_point;
+   png_FILE_p = Pointer;
+   png_doublep = PCdouble;
+   png_bytepp = PPpng_byte;
+   png_uint_32pp = PPpng_uint_32;
+   png_int_32pp = PPpng_int_32;
+   png_uint_16pp = PPpng_uint_16;
+   png_int_16pp = PPpng_int_16;
+   png_const_charpp = {const} PPchar;
+   png_charpp = PPchar;
+   ppng_charpp = ^png_charpp;
+   png_fixed_point_pp = PPpng_fixed_point;
+   PPCdouble = ^PCdouble;
+   png_doublepp = PPCdouble;
+   PPPChar = ^PPChar;
+   png_charppp = PPPChar;
+   PCharf = PChar;
+   PPCharf = ^PCharf;
+   png_zcharp = PCharf;
+   png_zcharpp = PPCharf;
+   png_zstreamp = Pzstream;
+
+const
+  (* Maximum positive integer used in PNG is (2^31)-1 *)
+  PNG_UINT_31_MAX = (png_uint_32($7fffffff));
+  PNG_UINT_32_MAX = (png_uint_32(-1));
+  PNG_SIZE_MAX    = (png_size_t(-1));
+  {$if defined(PNG_1_0_X) or defined (PNG_1_2_X)}
+  (* PNG_MAX_UINT is deprecated; use PNG_UINT_31_MAX instead. *)
+  PNG_MAX_UINT = PNG_UINT_31_MAX;
+  {$ifend}
+
+  (* These describe the color_type field in png_info. *)
+  (* color type masks *)
+  PNG_COLOR_MASK_PALETTE  = 1;
+  PNG_COLOR_MASK_COLOR    = 2;
+  PNG_COLOR_MASK_ALPHA    = 4;
+
+  (* color types.  Note that not all combinations are legal *)
+  PNG_COLOR_TYPE_GRAY = 0;
+  PNG_COLOR_TYPE_PALETTE    = (PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_PALETTE);
+  PNG_COLOR_TYPE_RGB        = (PNG_COLOR_MASK_COLOR);
+  PNG_COLOR_TYPE_RGB_ALPHA  = (PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_ALPHA);
+  PNG_COLOR_TYPE_GRAY_ALPHA = (PNG_COLOR_MASK_ALPHA);
+  (* aliases *)
+  PNG_COLOR_TYPE_RGBA = PNG_COLOR_TYPE_RGB_ALPHA;
+  PNG_COLOR_TYPE_GA   = PNG_COLOR_TYPE_GRAY_ALPHA;
+
+  (* This is for compression type. PNG 1.0-1.2 only define the single type. *)
+  PNG_COMPRESSION_TYPE_BASE = 0; (* Deflate method 8, 32K window *)
+  PNG_COMPRESSION_TYPE_DEFAULT = PNG_COMPRESSION_TYPE_BASE;
+
+  (* This is for filter type. PNG 1.0-1.2 only define the single type. *)
+  PNG_FILTER_TYPE_BASE     = 0; (* Single row per-byte filtering *)
+  PNG_INTRAPIXEL_DIFFERENCING = 64; (* Used only in MNG datastreams *)
+  PNG_FILTER_TYPE_DEFAULT  = PNG_FILTER_TYPE_BASE;
+
+  (* These are for the interlacing type.  These values should NOT be changed. *)
+  PNG_INTERLACE_NONE      = 0; (* Non-interlaced image *)
+  PNG_INTERLACE_ADAM7     = 1; (* Adam7 interlacing *)
+  PNG_INTERLACE_LAST      = 2; (* Not a valid value *)
+
+  (* These are for the oFFs chunk.  These values should NOT be changed. *)
+  PNG_OFFSET_PIXEL        = 0; (* Offset in pixels *)
+  PNG_OFFSET_MICROMETER   = 1; (* Offset in micrometers (1/10^6 meter) *)
+  PNG_OFFSET_LAST         = 2; (* Not a valid value *)
+
+  (* These are for the pCAL chunk.  These values should NOT be changed. *)
+  PNG_EQUATION_LINEAR     = 0; (* Linear transformation *)
+  PNG_EQUATION_BASE_E     = 1; (* Exponential base e transform *)
+  PNG_EQUATION_ARBITRARY  = 2; (* Arbitrary base exponential transform *)
+  PNG_EQUATION_HYPERBOLIC = 3; (* Hyperbolic sine transformation *)
+  PNG_EQUATION_LAST       = 4; (* Not a valid value *)
+
+  (* These are for the sCAL chunk.  These values should NOT be changed. *)
+  PNG_SCALE_UNKNOWN       = 0; (* unknown unit (image scale) *)
+  PNG_SCALE_METER         = 1; (* meters per pixel *)
+  PNG_SCALE_RADIAN        = 2; (* radians per pixel *)
+  PNG_SCALE_LAST          = 3; (* Not a valid value *)
+
+  (* These are for the pHYs chunk.  These values should NOT be changed. *)
+  PNG_RESOLUTION_UNKNOWN  = 0; (* pixels/unknown unit (aspect ratio) *)
+  PNG_RESOLUTION_METER    = 1; (* pixels/meter *)
+  PNG_RESOLUTION_LAST     = 2; (* Not a valid value *)
+
+  (* These are for the sRGB chunk.  These values should NOT be changed. *)
+  PNG_sRGB_INTENT_PERCEPTUAL = 0;
+  PNG_sRGB_INTENT_RELATIVE   = 1;
+  PNG_sRGB_INTENT_SATURATION = 2;
+  PNG_sRGB_INTENT_ABSOLUTE   = 3;
+  PNG_sRGB_INTENT_LAST       = 4; (* Not a valid value *)
+
+  (* This is for text chunks *)
+  PNG_KEYWORD_MAX_LENGTH   = 79;
+
+  (* Maximum number of entries in PLTE/sPLT/tRNS arrays *)
+  PNG_MAX_PALETTE_LENGTH  = 256;
+
+  (* These determine if an ancillary chunk's data has been successfully read
+   * from the PNG header, or if the application has filled in the corresponding
+   * data in the info_struct to be written into the output file.  The values
+   * of the PNG_INFO_<chunk> defines should NOT be changed.
+   *)
+  PNG_INFO_gAMA = $0001;
+  PNG_INFO_sBIT = $0002;
+  PNG_INFO_cHRM = $0004;
+  PNG_INFO_PLTE = $0008;
+  PNG_INFO_tRNS = $0010;
+  PNG_INFO_bKGD = $0020;
+  PNG_INFO_hIST = $0040;
+  PNG_INFO_pHYs = $0080;
+  PNG_INFO_oFFs = $0100;
+  PNG_INFO_tIME = $0200;
+  PNG_INFO_pCAL = $0400;
+  PNG_INFO_sRGB = $0800;  (* GR-P, 0.96a *)
+  PNG_INFO_iCCP = $1000;  (* ESR, 1.0.6 *)
+  PNG_INFO_sPLT = $2000;  (* ESR, 1.0.6 *)
+  PNG_INFO_sCAL = $4000;  (* ESR, 1.0.6 *)
+  PNG_INFO_IDAT = $8000;  (* ESR, 1.0.6 *)
+
+
+(*
+var
+  png_libpng_ver    : array[0..11] of char; external LibPng name 'png_libpng_ver';
+  png_pass_start    : array[0..6] of cint; external LibPng name 'png_pass_start';
+  png_pass_inc      : array[0..6] of cint; external LibPng name 'png_pass_inc';
+  png_pass_ystart   : array[0..6] of cint; external LibPng name 'png_pass_ystart';
+  png_pass_yinc     : array[0..6] of cint; external LibPng name 'png_pass_yinc';
+  png_pass_mask     : array[0..6] of cint; external LibPng name 'png_pass_mask';
+  png_pass_dsp_mask : array[0..6] of cint; external LibPng name 'png_pass_dsp_mask';
+*)
+
+type
+  (* Three color definitions.  The order of the red, green, and blue, (and the
+   * exact size) is not important, although the size of the fields need to
+   * be png_byte or png_uint_16 (as defined below).
+   *)
+  png_color = record
+       red : png_byte;
+       green : png_byte;
+       blue : png_byte;
+    end;
+  ppng_color = ^png_color;
+  pppng_color = ^ppng_color;
+  png_color_struct = png_color;
+  png_colorp = Ppng_color;
+  ppng_colorp = ^png_colorp;
+  png_colorpp = PPpng_color;
+
+  png_color_16 = record
+       index : png_byte;    (* used for palette files *)
+       red : png_uint_16;   (* for use in red green blue files *)
+       green : png_uint_16;
+       blue : png_uint_16;
+       gray : png_uint_16;  (* for use in grayscale files *)
+    end;
+  ppng_color_16 = ^png_color_16 ;
+  pppng_color_16 = ^ppng_color_16 ;
+  png_color_16_struct = png_color_16;
+  png_color_16p = Ppng_color_16;
+  ppng_color_16p = ^png_color_16p;
+  png_color_16pp = PPpng_color_16;
+
+  png_color_8 = record
+       red : png_byte;    (* for use in red green blue files *)
+       green : png_byte;
+       blue : png_byte;
+       gray : png_byte;   (* for use in grayscale files *)
+       alpha : png_byte;  (* for alpha channel files *)
+    end;
+  ppng_color_8 = ^png_color_8;
+  pppng_color_8 = ^ppng_color_8;
+  png_color_8_struct = png_color_8;
+  png_color_8p = Ppng_color_8;
+  ppng_color_8p = ^png_color_8p;
+  png_color_8pp = PPpng_color_8;
+   
+  (*
+   * The following two structures are used for the in-core representation
+   * of sPLT chunks.
+   *)
+  png_sPLT_entry = record
+       red : png_uint_16;
+       green : png_uint_16;
+       blue : png_uint_16;
+       alpha : png_uint_16;
+       frequency : png_uint_16;
+    end;
+  ppng_sPLT_entry = ^png_sPLT_entry;
+  pppng_sPLT_entry = ^ppng_sPLT_entry;
+  png_sPLT_entry_struct = png_sPLT_entry;
+  png_sPLT_entryp = Ppng_sPLT_entry;
+  png_sPLT_entrypp = PPpng_sPLT_entry;
+
+  (*  When the depth of the sPLT palette is 8 bits, the color and alpha samples
+   *  occupy the LSB of their respective members, and the MSB of each member
+   *  is zero-filled.  The frequency member always occupies the full 16 bits.
+   *)
+
+  png_sPLT_t = record
+       name : png_charp;          (* palette name *)
+       depth : png_byte;          (* depth of palette samples *)
+       entries : png_sPLT_entryp; (* palette entries *)
+       nentries : png_int_32;     (* number of palette entries *)
+    end;
+  ppng_sPLT_t = ^png_sPLT_t;
+  pppng_sPLT_t = ^ppng_sPLT_t;
+  png_sPLT_struct = png_sPLT_t;
+  png_sPLT_tp = Ppng_sPLT_t;
+  png_sPLT_tpp = PPpng_sPLT_t;
+   
+  (* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
+   * and whether that contents is compressed or not.  The "key" field
+   * points to a regular zero-terminated C string.  The "text", "lang", and
+   * "lang_key" fields can be regular C strings, empty strings, or NULL pointers.
+   * However, the * structure returned by png_get_text() will always contain
+   * regular zero-terminated C strings (possibly empty), never NULL pointers,
+   * so they can be safely used in printf() and other string-handling functions.
+   *)
+  png_text = record
+       compression : cint;       (* compression value:
+                                   -1: tEXt, none
+                                    0: zTXt, deflate
+                                    1: iTXt, none
+                                    2: iTXt, deflate  *)
+       key : png_charp;          (* keyword, 1-79 character description of "text" *)
+       text : png_charp;         (* comment, may be an empty string (ie "")
+                                    or a NULL pointer *)
+       text_length : png_size_t; (* length of the text string *)
+    end;
+  ppng_text = ^png_text;
+  pppng_text = ^ppng_text;
+  png_text_struct = png_text;
+  png_textp = Ppng_text;
+  ppng_textp = ^png_textp;
+  png_textpp = PPpng_text;
+   
+  (* png_time is a way to hold the time in an machine independent way.
+   * Two conversions are provided, both from time_t and struct tm.  There
+   * is no portable way to convert to either of these structures, as far
+   * as I know.  If you know of a portable way, send it to me.  As a side
+   * note - PNG has always been Year 2000 compliant!
+   *)
+  png_time = record
+       year : png_uint_16; (* full year, as in, 1995 *)
+       month : png_byte;   (* month of year, 1 - 12 *)
+       day : png_byte;     (* day of month, 1 - 31 *)
+       hour : png_byte;    (* hour of day, 0 - 23 *)
+       minute : png_byte;  (* minute of hour, 0 - 59 *)
+       second : png_byte;  (* second of minute, 0 - 60 (for leap seconds) *)
+    end;
+  ppng_time = ^png_time;
+  pppng_time = ^ppng_time;
+  png_time_struct = png_time;
+  png_timep = Ppng_time;
+  PPNG_TIMEP = ^PNG_TIMEP;
+  png_timepp = PPpng_time;
+
+const
+  PNG_CHUNK_NAME_LENGTH = 5; 
+type
+  (* png_unknown_chunk is a structure to hold queued chunks for which there is
+   * no specific support.  The idea is that we can use this to queue
+   * up private chunks for output even though the library doesn't actually
+   * know about their semantics.
+   *)
+  png_unknown_chunk = record
+       name : array[0..PNG_CHUNK_NAME_LENGTH-1] of png_byte;
+       data : Ppng_byte;
+       size : png_size_t;
+       
+       (* libpng-using applications should NOT directly modify this byte. *)
+       location : png_byte; (* mode of operation at read time *)
+    end;
+  ppng_unknown_chunk = ^png_unknown_chunk;
+  pppng_unknown_chunk = ^ppng_unknown_chunk;
+  png_unknown_chunk_t = png_unknown_chunk;
+  png_unknown_chunkp = Ppng_unknown_chunk;
+  png_unknown_chunkpp = PPpng_unknown_chunk;
+   
+  (* png_info is a structure that holds the information in a PNG file so
+   * that the application can find out the characteristics of the image.
+   * If you are reading the file, this structure will tell you what is
+   * in the PNG file.  If you are writing the file, fill in the information
+   * you want to put into the PNG file, then call png_write_info().
+   * The names chosen should be very close to the PNG specification, so
+   * consult that document for information about the meaning of each field.
+   *
+   * With libpng < 0.95, it was only possible to directly set and read the
+   * the values in the png_info_struct, which meant that the contents and
+   * order of the values had to remain fixed.  With libpng 0.95 and later,
+   * however, there are now functions that abstract the contents of
+   * png_info_struct from the application, so this makes it easier to use
+   * libpng with dynamic libraries, and even makes it possible to use
+   * libraries that don't have all of the libpng ancillary chunk-handing
+   * functionality.
+   *
+   * In any case, the order of the parameters in png_info_struct should NOT
+   * be changed for as long as possible to keep compatibility with applications
+   * that use the old direct-access method with png_info_struct.
+   *
+   * The following members may have allocated storage attached that should be
+   * cleaned up before the structure is discarded: palette, trans, text,
+   * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
+   * splt_palettes, scal_unit, row_pointers, and unknowns.   By default, these
+   * are automatically freed when the info structure is deallocated, if they were
+   * allocated internally by libpng.  This behavior can be changed by means
+   * of the png_data_freer() function.
+   *
+   * More allocation details: all the chunk-reading functions that
+   * change these members go through the corresponding png_set_*
+   * functions.  A function to clear these members is available: see
+   * png_free_data().  The png_set_* functions do not depend on being
+   * able to point info structure members to any of the storage they are
+   * passed (they make their own copies), EXCEPT that the png_set_text
+   * functions use the same storage passed to them in the text_ptr or
+   * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
+   * functions do not make their own copies.
+   *)
+  png_info = record
+       width : png_uint_32;       (* width of image in pixels (from IHDR) *)
+       height : png_uint_32;      (* height of image in pixels (from IHDR) *)
+       valid : png_uint_32;       (* valid chunk data (see PNG_INFO_ below) *)
+       rowbytes : png_uint_32;    (* bytes needed to hold an untransformed row *)
+       palette : png_colorp;      (* array of color values (valid & PNG_INFO_PLTE) *)
+       num_palette : png_uint_16; (* number of color entries in "palette" (PLTE) *)
+       num_trans : png_uint_16;   (* number of transparent palette color (tRNS) *)
+       bit_depth : png_byte;      (* 1, 2, 4, 8, or 16 bits/channel (from IHDR) *)
+       color_type : png_byte;     (* see PNG_COLOR_TYPE_ below (from IHDR) *)
+       (* The following three should have been named *_method not *_type *)
+       compression_type : png_byte; (* must be PNG_COMPRESSION_TYPE_BASE (IHDR) *)
+       filter_type : png_byte;    (* must be PNG_FILTER_TYPE_BASE (from IHDR) *)
+       interlace_type : png_byte; (* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 *)
+
+       (* The following is informational only on read, and not used on writes. *)
+       channels : png_byte;       (* number of data channels per pixel (1, 2, 3, 4) *)
+       pixel_depth : png_byte;    (* number of bits per pixel *)
+       spare_byte : png_byte;     (* to align the data, and for future use *)
+       signature : array[0..7] of png_byte; (* magic bytes read by libpng from start of file *)
+
+       (* The rest of the data is optional.  If you are reading, check the
+        * valid field to see if the information in these are valid.  If you
+        * are writing, set the valid field to those chunks you want written,
+        * and initialize the appropriate fields below.
+        *)
+        
+       gamma : cfloat;
+       srgb_intent : png_byte;
+       num_text : cint;
+       max_text : cint;
+       text : png_textp;
+       mod_time : png_time;
+       sig_bit : png_color_8;
+       trans : png_bytep;
+       trans_values : png_color_16;
+       background : png_color_16;
+       x_offset : png_int_32;
+       y_offset : png_int_32;
+       offset_unit_type : png_byte;
+       x_pixels_per_unit : png_uint_32;
+       y_pixels_per_unit : png_uint_32;
+       phys_unit_type : png_byte;
+       hist : png_uint_16p;
+       x_white : cfloat;
+       y_white : cfloat;
+       x_red : cfloat;
+       y_red : cfloat;
+       x_green : cfloat;
+       y_green : cfloat;
+       x_blue : cfloat;
+       y_blue : cfloat;
+       pcal_purpose : png_charp;
+       pcal_X0 : png_int_32;
+       pcal_X1 : png_int_32;
+       pcal_units : png_charp;
+       pcal_params : png_charpp;
+       pcal_type : png_byte;
+       pcal_nparams : png_byte;
+       free_me : png_uint_32;
+       unknown_chunks : png_unknown_chunkp;
+       unknown_chunks_num : png_size_t;
+       iccp_name : png_charp;
+       iccp_profile : png_charp;
+       iccp_proflen : png_uint_32;
+       iccp_compression : png_byte;
+       splt_palettes : png_sPLT_tp;
+       splt_palettes_num : png_uint_32;
+       scal_unit : png_byte;
+       scal_pixel_width : cdouble;
+       scal_pixel_height : cdouble;
+       scal_s_width : png_charp;
+       scal_s_height : png_charp;
+       row_pointers : png_bytepp;
+       int_gamma : png_fixed_point;
+       int_x_white : png_fixed_point;
+       int_y_white : png_fixed_point;
+       int_x_red : png_fixed_point;
+       int_y_red : png_fixed_point;
+       int_x_green : png_fixed_point;
+       int_y_green : png_fixed_point;
+       int_x_blue : png_fixed_point;
+       int_y_blue : png_fixed_point;
+    end;
+  ppng_info = ^png_info;
+  pppng_info = ^ppng_info;
+  png_info_struct = png_info;
+  png_infop = Ppng_info;
+  png_infopp = PPpng_info;
+  
+  (* This is used for the transformation routines, as some of them
+   * change these values for the row.  It also should enable using
+   * the routines for other purposes.
+   *)
+  png_row_info = record
+       width : png_uint_32;    (* width of row *)
+       rowbytes : png_uint_32; (* number of bytes in row *)
+       color_type : png_byte;  (* color type of row *)
+       bit_depth : png_byte;   (* bit depth of row *)
+       channels : png_byte;    (* number of channels (1, 2, 3, or 4) *)
+       pixel_depth : png_byte; (* bits per pixel (depth * channels) *)
+    end;
+  ppng_row_info = ^png_row_info;
+  pppng_row_info = ^ppng_row_info;
+  png_row_info_struct = png_row_info;
+  png_row_infop = Ppng_row_info;
+  png_row_infopp = PPpng_row_info;
+  png_structp = ^png_struct;
+
+
+  (* These are the function types for the I/O functions and for the functions
+   * that allow the user to override the default I/O functions with his or her
+   * own.  The png_error_ptr type should match that of user-supplied warning
+   * and error functions, while the png_rw_ptr type should match that of the
+   * user read/write data functions.
+   *)
+  png_error_ptr = procedure(Arg1 : png_structp; Arg2 : png_const_charp); cdecl;
+  png_rw_ptr = procedure(Arg1 : png_structp; Arg2 : png_bytep; Arg3 : png_size_t); cdecl;
+  png_flush_ptr = procedure (Arg1 : png_structp); cdecl;
+  png_read_status_ptr = procedure (Arg1 : png_structp; Arg2 : png_uint_32; Arg3: cint); cdecl;
+  png_write_status_ptr = procedure (Arg1 : png_structp; Arg2:png_uint_32;Arg3 : cint); cdecl;
+  png_progressive_info_ptr = procedure (Arg1 : png_structp; Arg2 : png_infop); cdecl;
+  png_progressive_end_ptr = procedure (Arg1 : png_structp; Arg2 : png_infop); cdecl;
+  png_progressive_row_ptr = procedure (Arg1 : png_structp; Arg2 : png_bytep; Arg3 : png_uint_32; Arg4 : cint); cdecl;
+  png_user_transform_ptr = procedure (Arg1 : png_structp; Arg2 : png_row_infop; Arg3 : png_bytep); cdecl;
+  png_user_chunk_ptr = function (Arg1 : png_structp; Arg2 : png_unknown_chunkp): cint; cdecl;
+  png_unknown_chunk_ptr = procedure (Arg1 : png_structp); cdecl;
+  png_malloc_ptr = function (Arg1 : png_structp; Arg2 : png_size_t) : png_voidp; cdecl;
+  png_free_ptr = procedure (Arg1 : png_structp; Arg2 : png_voidp); cdecl;
+
+  png_struct_def = record
+        {$ifdef UsePngStruct}
+        jmpbuf : jmp_buf;            (* used in png_error *)
+        error_fn : png_error_ptr;    (* function for printing errors and aborting *)
+        warning_fn : png_error_ptr;  (* function for printing warnings *)
+        error_ptr : png_voidp;       (* user supplied struct for error functions *)
+        write_data_fn : png_rw_ptr;  (* function for writing output data *)
+        read_data_fn : png_rw_ptr;   (* function for reading input data *)
+        io_ptr : png_voidp;          (* ptr to application struct for I/O functions *)
+
+        read_user_transform_fn : png_user_transform_ptr;  (* user read transform *)
+
+        write_user_transform_fn : png_user_transform_ptr; (* user write transform *)
+
+        (* These were added in libpng-1.0.2 *)
+        user_transform_ptr : png_voidp; (* user supplied struct for user transform *)
+        user_transform_depth : png_byte;    (* bit depth of user transformed pixels *)
+        user_transform_channels : png_byte; (* channels in user transformed pixels *)
+
+        mode : png_uint_32;          (* tells us where we are in the PNG file *)
+        flags : png_uint_32;         (* flags indicating various things to libpng *)
+        transformations : png_uint_32; (* which transformations to perform *)
+
+        zstream : z_stream;          (* pointer to decompression structure (below) *)
+        zbuf : png_bytep;            (* buffer for zlib *)
+        zbuf_size : png_size_t;      (* size of zbuf *)
+        zlib_level : cint;        (* holds zlib compression level *)
+        zlib_method : cint;       (* holds zlib compression method *)
+        zlib_window_bits : cint;  (* holds zlib compression window bits *)
+        zlib_mem_level : cint;    (* holds zlib compression memory level *)
+        zlib_strategy : cint;     (* holds zlib compression strategy *)
+
+        width : png_uint_32;         (* width of image in pixels *)
+        height : png_uint_32;        (* height of image in pixels *)
+        num_rows : png_uint_32;      (* number of rows in current pass *)
+        usr_width : png_uint_32;     (* width of row at start of write *)
+        rowbytes : png_uint_32;      (* size of row in bytes *)
+        irowbytes : png_uint_32;     (* size of current interlaced row in bytes *)
+        iwidth : png_uint_32;        (* width of current interlaced row in pixels *)
+        row_number : png_uint_32;    (* current row in interlace pass *)
+        prev_row : png_bytep;        (* buffer to save previous (unfiltered) row *)
+        row_buf : png_bytep;         (* buffer to save current (unfiltered) row *)
+        sub_row : png_bytep;         (* buffer to save "sub" row when filtering *)
+        up_row : png_bytep;          (* buffer to save "up" row when filtering *)
+        avg_row : png_bytep;         (* buffer to save "avg" row when filtering *)
+        paeth_row : png_bytep;       (* buffer to save "Paeth" row when filtering *)
+        row_info : png_row_info;     (* used for transformation routines *)
+        
+        idat_size : png_uint_32;     (* current IDAT size for read *)
+        crc : png_uint_32;           (* current chunk CRC value *)
+        palette : png_colorp;        (* palette from the input file *)
+        num_palette : png_uint_16;   (* number of color entries in palette *)
+        num_trans : png_uint_16;     (* number of transparency values *)
+        chunk_name : array[0..4] of png_byte; (* null-terminated name of current chunk *)
+        compression : png_byte;      (* file compression type (always 0) *)
+        filter : png_byte;           (* file filter type (always 0) *)
+        interlaced : png_byte;       (* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 *)
+        pass : png_byte;             (* current interlace pass (0 - 6) *)
+        do_filter : png_byte;        (* row filter flags (see PNG_FILTER_ below ) *)
+        color_type : png_byte;       (* color type of file *)
+        bit_depth : png_byte;        (* bit depth of file *)
+        usr_bit_depth : png_byte;    (* bit depth of users row *)
+        pixel_depth : png_byte;      (* number of bits per pixel *)
+        channels : png_byte;         (* number of channels in file *)
+        usr_channels : png_byte;     (* channels at start of write *)
+        sig_bytes : png_byte;        (* magic bytes read/written from start of file *)
+
+        filler : png_uint_16;
+
+        background_gamma_type : png_byte;
+        background_gamma : cfloat;
+        background : png_color_16;
+        background_1 : png_color_16;
+        output_flush_fn : png_flush_ptr;
+        flush_dist : png_uint_32;
+        flush_rows : png_uint_32;
+        gamma_shift : cint;
+        gamma : cfloat;
+        screen_gamma : cfloat;
+        gamma_table : png_bytep;
+        gamma_from_1 : png_bytep;
+        gamma_to_1 : png_bytep;
+        gamma_16_table : png_uint_16pp;
+        gamma_16_from_1 : png_uint_16pp;
+        gamma_16_to_1 : png_uint_16pp;
+        sig_bit : png_color_8;
+        shift : png_color_8;
+        trans : png_bytep;
+        trans_values : png_color_16;
+        read_row_fn : png_read_status_ptr;
+        write_row_fn : png_write_status_ptr;
+        info_fn : png_progressive_info_ptr;
+        row_fn : png_progressive_row_ptr;
+        end_fn : png_progressive_end_ptr;
+        save_buffer_ptr : png_bytep;
+        save_buffer : png_bytep;
+        current_buffer_ptr : png_bytep;
+        current_buffer : png_bytep;
+        push_length : png_uint_32;
+        skip_length : png_uint_32;
+        save_buffer_size : png_size_t;
+        save_buffer_max : png_size_t;
+        buffer_size : png_size_t;
+        current_buffer_size : png_size_t;
+        process_mode : cint;
+        cur_palette : cint;
+        current_text_size : png_size_t;
+        current_text_left : png_size_t;
+        current_text : png_charp;
+        current_text_ptr : png_charp;
+        palette_lookup : png_bytep;
+        dither_index : png_bytep;
+        hist : png_uint_16p;
+        heuristic_method : png_byte;
+        num_prev_filters : png_byte;
+        prev_filters : png_bytep;
+        filter_weights : png_uint_16p;
+        inv_filter_weights : png_uint_16p;
+        filter_costs : png_uint_16p;
+        inv_filter_costs : png_uint_16p;
+        time_buffer : png_charp;
+        free_me : png_uint_32;
+        user_chunk_ptr : png_voidp;
+        read_user_chunk_fn : png_user_chunk_ptr;
+        num_chunk_list : cint;
+        chunk_list : png_bytep;
+        rgb_to_gray_status : png_byte;
+        rgb_to_gray_red_coeff : png_uint_16;
+        rgb_to_gray_green_coeff : png_uint_16;
+        rgb_to_gray_blue_coeff : png_uint_16;
+        empty_plte_permitted : png_byte;
+        int_gamma : png_fixed_point;
+        {$endif UsePngStruct}
+     end;
+   ppng_struct_def = ^png_struct_def;
+   pppng_struct_def = ^ppng_struct_def;
+   png_struct = png_struct_def;
+   ppng_struct = ^png_struct;
+   pppng_struct = ^ppng_struct;
+
+   version_1_0_8 = png_structp;
+   png_structpp = PPpng_struct;
+
+function png_access_version_number:png_uint_32; cdecl; external LibPng;
+
+procedure png_set_sig_bytes(png_ptr:png_structp; num_bytes:cint); cdecl; external LibPng;
+function png_sig_cmp(sig:png_bytep; start:png_size_t; num_to_check:png_size_t):cint; cdecl; external LibPng;
+function png_check_sig(sig:png_bytep; num:cint):cint; cdecl; external LibPng;
+
+(* Allocate and initialize png_ptr struct for reading, and any other memory. *)
+function png_create_read_struct(user_png_ver:png_const_charp; error_ptr:png_voidp; error_fn:png_error_ptr; warn_fn:png_error_ptr):png_structp; cdecl; external LibPng;
+
+(* Allocate and initialize png_ptr struct for writing, and any other memory *)
+function png_create_write_struct(user_png_ver:png_const_charp; error_ptr:png_voidp; error_fn:png_error_ptr; warn_fn:png_error_ptr):png_structp; cdecl; external LibPng;
+
+function png_get_compression_buffer_size(png_ptr:png_structp):png_uint_32; cdecl; external LibPng;
+procedure png_set_compression_buffer_size(png_ptr:png_structp; size:png_uint_32); cdecl; external LibPng;
+function png_reset_zstream(png_ptr:png_structp):cint; cdecl; external LibPng;
+
+procedure png_write_chunk(png_ptr:png_structp; chunk_name:png_bytep; data:png_bytep; length:png_size_t); cdecl; external LibPng;
+procedure png_write_chunk_start(png_ptr:png_structp; chunk_name:png_bytep; length:png_uint_32); cdecl; external LibPng;
+procedure png_write_chunk_data(png_ptr:png_structp; data:png_bytep; length:png_size_t); cdecl; external LibPng;
+procedure png_write_chunk_end(png_ptr:png_structp); cdecl; external LibPng;
+
+(* Allocate and initialize the info structure *)
+function png_create_info_struct(png_ptr:png_structp):png_infop; cdecl; external LibPng;
+
+(* Initialize the info structure (old interface - DEPRECATED) *)
+procedure png_info_init(info_ptr:png_infop); cdecl; external LibPng;
+
+(* Writes all the PNG information before the image. *)
+procedure png_write_info_before_PLTE(png_ptr:png_structp; info_ptr:png_infop); cdecl; external LibPng;
+procedure png_write_info(png_ptr:png_structp; info_ptr:png_infop); cdecl; external LibPng;
+
+(* read the information before the actual image data. *)
+procedure png_read_info(png_ptr:png_structp; info_ptr:png_infop); cdecl; external LibPng;
+
+function png_convert_to_rfc1123(png_ptr:png_structp; ptime:png_timep):png_charp; cdecl; external LibPng;
+procedure png_convert_from_struct_tm(ptime:png_timep; ttime:Pointer); cdecl; external LibPng;
+{$IFDEF UNIX}
+procedure png_convert_from_time_t(ptime:png_timep; ttime:time_t); cdecl; external LibPng;
+{$ENDIF}
+procedure png_set_expand(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_gray_1_2_4_to_8(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_palette_to_rgb(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_tRNS_to_alpha(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_bgr(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_gray_to_rgb(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_rgb_to_gray(png_ptr:png_structp; error_action:cint; red:cdouble; green:cdouble); cdecl; external LibPng;
+procedure png_set_rgb_to_gray_fixed(png_ptr:png_structp; error_action:cint; red:png_fixed_point; green:png_fixed_point); cdecl; external LibPng;
+function png_get_rgb_to_gray_status(png_ptr:png_structp):png_byte; cdecl; external LibPng;
+procedure png_build_grayscale_palette(bit_depth:cint; palette:png_colorp); cdecl; external LibPng;
+procedure png_set_strip_alpha(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_swap_alpha(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_invert_alpha(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_filler(png_ptr:png_structp; filler:png_uint_32; flags:cint); cdecl; external LibPng;
+procedure png_set_swap(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_packing(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_packswap(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_shift(png_ptr:png_structp; true_bits:png_color_8p); cdecl; external LibPng;
+function png_set_interlace_handling(png_ptr:png_structp):cint; cdecl; external LibPng;
+procedure png_set_invert_mono(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_background(png_ptr:png_structp; background_color:png_color_16p; background_gamma_code:cint; need_expand:cint; background_gamma:cdouble); cdecl; external LibPng;
+procedure png_set_strip_16(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_set_dither(png_ptr:png_structp; palette:png_colorp; num_palette:cint; maximum_colors:cint; histogram:png_uint_16p;
+            full_dither:cint); cdecl; external LibPng;
+procedure png_set_gamma(png_ptr:png_structp; screen_gamma:cdouble; default_file_gamma:cdouble); cdecl; external LibPng;
+procedure png_permit_empty_plte(png_ptr:png_structp; empty_plte_permitted:cint); cdecl; external LibPng;
+procedure png_set_flush(png_ptr:png_structp; nrows:cint); cdecl; external LibPng;
+procedure png_write_flush(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_start_read_image(png_ptr:png_structp); cdecl; external LibPng;
+procedure png_read_update_info(png_ptr:png_structp; info_ptr:png_infop); cdecl; external LibPng;
+
+(* read one or more rows of image data. *)
+procedure png_read_rows(png_ptr:png_structp; row:png_bytepp; display_row:png_bytepp; num_rows:png_uint_32); cdecl; external LibPng;
+
+(* read a row of data. *)
+procedure png_read_row(png_ptr:png_structp; row:png_bytep; display_row:png_bytep); cdecl; external LibPng;
+
+(* read the whole image into memory at once. *)
+procedure png_read_image(png_ptr:png_structp; image:png_bytepp); cdecl; external LibPng;
+
+(* write a row of image data *)
+procedure png_write_row(png_ptr:png_structp; row:png_bytep); cdecl; external LibPng;
+
+(* write a few rows of image data *)
+procedure png_write_rows(png_ptr:png_structp; row:png_bytepp; num_rows:png_uint_32); cdecl; external LibPng;
+
+(* write the image data *)
+procedure png_write_image(png_ptr:png_structp; image:png_bytepp); cdecl; external LibPng;
+
+(* writes the end of the PNG file. *)
+procedure png_write_end(png_ptr:png_structp; info_ptr:png_infop); cdecl; external LibPng;
+
+(* read the end of the PNG file. *)
+procedure png_read_end(png_ptr:png_structp; info_ptr:png_infop); cdecl; external LibPng;
+
+(* free any memory associated with the png_info_struct *)
+procedure png_destroy_info_struct(png_ptr:png_structp; info_ptr_ptr:png_infopp); cdecl; external LibPng;
+
+(* free any memory associated with the png_struct and the png_info_structs *)
+procedure png_destroy_read_struct(png_ptr_ptr:png_structpp; info_ptr_ptr:png_infopp; end_info_ptr_ptr:png_infopp); cdecl; external LibPng;
+
+(* free all memory used by the read (old method - NOT DLL EXPORTED) *)
+procedure png_read_destroy(png_ptr:png_structp; info_ptr:png_infop; end_info_ptr:png_infop); cdecl; external LibPng;
+
+(* free any memory associated with the png_struct and the png_info_structs *)
+procedure png_destroy_write_struct(png_ptr_ptr:png_structpp; info_ptr_ptr:png_infopp); cdecl; external LibPng;
+
+procedure png_write_destroy_info(info_ptr:png_infop); cdecl; external LibPng;
+procedure png_write_destroy(png_ptr:png_structp); cdecl; external LibPng;
+
+procedure png_set_crc_action(png_ptr:png_structp; crit_action:cint; ancil_action:cint); cdecl; external LibPng;
+
+procedure png_set_filter(png_ptr:png_structp; method:cint; filters:cint); cdecl; external LibPng;
+procedure png_set_filter_heuristics(png_ptr:png_structp; heuristic_method:cint; num_weights:cint; filter_weights:png_doublep; filter_costs:png_doublep); cdecl; external LibPng;
+
+procedure png_set_compression_level(png_ptr:png_structp; level:cint); cdecl; external LibPng;
+procedure png_set_compression_mem_level(png_ptr:png_structp; mem_level:cint); cdecl; external LibPng;
+procedure png_set_compression_strategy(png_ptr:png_structp; strategy:cint); cdecl; external LibPng;
+procedure png_set_compression_window_bits(png_ptr:png_structp; window_bits:cint); cdecl; external LibPng;
+procedure png_set_compression_method(png_ptr:png_structp; method:cint); cdecl; external LibPng;
+
+procedure png_init_io(png_ptr:png_structp; fp:png_FILE_p); cdecl; external LibPng;
+
+(* Replace the (error and abort), and warning functions with user
+ * supplied functions.  If no messages are to be printed you must still
+ * write and use replacement functions. The replacement error_fn should
+ * still do a longjmp to the last setjmp location if you are using this
+ * method of error handling.  If error_fn or warning_fn is NULL, the
+ * default function will be used.
+ *)
+procedure png_set_error_fn(png_ptr:png_structp; error_ptr:png_voidp; error_fn:png_error_ptr; warning_fn:png_error_ptr); cdecl; external LibPng;
+
+(* Return the user pointer associated with the error functions *)
+function png_get_error_ptr(png_ptr:png_structp):png_voidp; cdecl; external LibPng;
+
+(* Replace the default data output functions with a user supplied one(s).
+ * If buffered output is not used, then output_flush_fn can be set to NULL.
+ * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time
+ * output_flush_fn will be ignored (and thus can be NULL).
+ *)
+procedure png_set_write_fn(png_ptr:png_structp; io_ptr:png_voidp; write_data_fn:png_rw_ptr; output_flush_fn:png_flush_ptr); cdecl; external LibPng;
+
+(* Replace the default data input function with a user supplied one. *)
+procedure png_set_read_fn(png_ptr:png_structp; io_ptr:png_voidp; read_data_fn:png_rw_ptr); cdecl; external LibPng;
+
+(* Return the user pointer associated with the I/O functions *)
+function png_get_io_ptr(png_ptr:png_structp):png_voidp; cdecl; external LibPng;
+
+procedure png_set_read_status_fn(png_ptr:png_structp; read_row_fn:png_read_status_ptr); cdecl; external LibPng;
+procedure png_set_write_status_fn(png_ptr:png_structp; write_row_fn:png_write_status_ptr); cdecl; external LibPng;
+procedure png_set_read_user_transform_fn(png_ptr:png_structp; read_user_transform_fn:png_user_transform_ptr); cdecl; external LibPng;
+procedure png_set_write_user_transform_fn(png_ptr:png_structp; write_user_transform_fn:png_user_transform_ptr); cdecl; external LibPng;
+procedure png_set_user_transform_info(png_ptr:png_structp; user_transform_ptr:png_voidp; user_transform_depth:cint; user_transform_channels:cint); cdecl; external LibPng;
+function png_get_user_transform_ptr(png_ptr:png_structp):png_voidp; cdecl; external LibPng;
+procedure png_set_read_user_chunk_fn(png_ptr:png_structp; user_chunk_ptr:png_voidp; read_user_chunk_fn:png_user_chunk_ptr); cdecl; external LibPng;
+function png_get_user_chunk_ptr(png_ptr:png_structp):png_voidp; cdecl; external LibPng;
+procedure png_set_progressive_read_fn(png_ptr:png_structp; progressive_ptr:png_voidp; info_fn:png_progressive_info_ptr; row_fn:png_progressive_row_ptr; end_fn:png_progressive_end_ptr); cdecl; external LibPng;
+function png_get_progressive_ptr(png_ptr:png_structp):png_voidp; cdecl; external LibPng;
+procedure png_process_data(png_ptr:png_structp; info_ptr:png_infop; buffer:png_bytep; buffer_size:png_size_t); cdecl; external LibPng;
+procedure png_progressive_combine_row(png_ptr:png_structp; old_row:png_bytep; new_row:png_bytep); cdecl; external LibPng;
+function png_malloc(png_ptr:png_structp; size:png_uint_32):png_voidp; cdecl; external LibPng;
+procedure png_free(png_ptr:png_structp; ptr:png_voidp); cdecl; external LibPng;
+procedure png_free_data(png_ptr:png_structp; info_ptr:png_infop; free_me:png_uint_32; num:cint); cdecl; external LibPng;
+procedure png_data_freer(png_ptr:png_structp; info_ptr:png_infop; freer:cint; mask:png_uint_32); cdecl; external LibPng;
+function png_memcpy_check(png_ptr:png_structp; s1:png_voidp; s2:png_voidp; size:png_uint_32):png_voidp; cdecl; external LibPng;
+function png_memset_check(png_ptr:png_structp; s1:png_voidp; value:cint; size:png_uint_32):png_voidp; cdecl; external LibPng;
+procedure png_error(png_ptr:png_structp; error:png_const_charp); cdecl; external LibPng;
+procedure png_chunk_error(png_ptr:png_structp; error:png_const_charp); cdecl; external LibPng;
+procedure png_warning(png_ptr:png_structp; message:png_const_charp); cdecl; external LibPng;
+procedure png_chunk_warning(png_ptr:png_structp; message:png_const_charp); cdecl; external LibPng;
+function png_get_valid(png_ptr:png_structp; info_ptr:png_infop; flag:png_uint_32):png_uint_32; cdecl; external LibPng;
+function png_get_rowbytes(png_ptr:png_structp; info_ptr:png_infop):png_uint_32; cdecl; external LibPng;
+function png_get_rows(png_ptr:png_structp; info_ptr:png_infop):png_bytepp; cdecl; external LibPng;
+procedure png_set_rows(png_ptr:png_structp; info_ptr:png_infop; row_pointers:png_bytepp); cdecl; external LibPng;
+function png_get_channels(png_ptr:png_structp; info_ptr:png_infop):png_byte; cdecl; external LibPng;
+function png_get_image_width(png_ptr:png_structp; info_ptr:png_infop):png_uint_32; cdecl; external LibPng;
+function png_get_image_height(png_ptr:png_structp; info_ptr:png_infop):png_uint_32; cdecl; external LibPng;
+function png_get_bit_depth(png_ptr:png_structp; info_ptr:png_infop):png_byte; cdecl; external LibPng;
+function png_get_color_type(png_ptr:png_structp; info_ptr:png_infop):png_byte; cdecl; external LibPng;
+function png_get_filter_type(png_ptr:png_structp; info_ptr:png_infop):png_byte; cdecl; external LibPng;
+function png_get_interlace_type(png_ptr:png_structp; info_ptr:png_infop):png_byte; cdecl; external LibPng;
+function png_get_compression_type(png_ptr:png_structp; info_ptr:png_infop):png_byte; cdecl; external LibPng;
+function png_get_pixels_per_meter(png_ptr:png_structp; info_ptr:png_infop):png_uint_32; cdecl; external LibPng;
+function png_get_x_pixels_per_meter(png_ptr:png_structp; info_ptr:png_infop):png_uint_32; cdecl; external LibPng;
+function png_get_y_pixels_per_meter(png_ptr:png_structp; info_ptr:png_infop):png_uint_32; cdecl; external LibPng;
+function png_get_pixel_aspect_ratio(png_ptr:png_structp; info_ptr:png_infop):cfloat; cdecl; external LibPng;
+function png_get_x_offset_pixels(png_ptr:png_structp; info_ptr:png_infop):png_int_32; cdecl; external LibPng;
+function png_get_y_offset_pixels(png_ptr:png_structp; info_ptr:png_infop):png_int_32; cdecl; external LibPng;
+function png_get_x_offset_microns(png_ptr:png_structp; info_ptr:png_infop):png_int_32; cdecl; external LibPng;
+function png_get_y_offset_microns(png_ptr:png_structp; info_ptr:png_infop):png_int_32; cdecl; external LibPng;
+function png_get_signature(png_ptr:png_structp; info_ptr:png_infop):png_bytep; cdecl; external LibPng;
+
+function png_get_bKGD(png_ptr:png_structp; info_ptr:png_infop; background:Ppng_color_16p):png_uint_32; cdecl; external LibPng;
+procedure png_set_bKGD(png_ptr:png_structp; info_ptr:png_infop; background:png_color_16p); cdecl; external LibPng;
+function png_get_cHRM(png_ptr:png_structp; info_ptr:png_infop; white_x:PCdouble; white_y:PCdouble; red_x:PCdouble;
+           red_y:PCdouble; green_x:PCdouble; green_y:PCdouble; blue_x:PCdouble; blue_y:PCdouble):png_uint_32; cdecl; external LibPng;
+function png_get_cHRM_fixed(png_ptr:png_structp; info_ptr:png_infop; int_white_x:Ppng_fixed_point; int_white_y:Ppng_fixed_point; int_red_x:Ppng_fixed_point;
+           int_red_y:Ppng_fixed_point; int_green_x:Ppng_fixed_point; int_green_y:Ppng_fixed_point; int_blue_x:Ppng_fixed_point; int_blue_y:Ppng_fixed_point):png_uint_32; cdecl; external LibPng;
+procedure png_set_cHRM(png_ptr:png_structp; info_ptr:png_infop; white_x:cdouble; white_y:cdouble; red_x:cdouble;
+            red_y:cdouble; green_x:cdouble; green_y:cdouble; blue_x:cdouble; blue_y:cdouble); cdecl; external LibPng;
+procedure png_set_cHRM_fixed(png_ptr:png_structp; info_ptr:png_infop; int_white_x:png_fixed_point; int_white_y:png_fixed_point; int_red_x:png_fixed_point;
+            int_red_y:png_fixed_point; int_green_x:png_fixed_point; int_green_y:png_fixed_point; int_blue_x:png_fixed_point; int_blue_y:png_fixed_point); cdecl; external LibPng;
+function png_get_gAMA(png_ptr:png_structp; info_ptr:png_infop; file_gamma:PCdouble):png_uint_32; cdecl; external LibPng;
+function png_get_gAMA_fixed(png_ptr:png_structp; info_ptr:png_infop; int_file_gamma:Ppng_fixed_point):png_uint_32; cdecl; external LibPng;
+procedure png_set_gAMA(png_ptr:png_structp; info_ptr:png_infop; file_gamma:cdouble); cdecl; external LibPng;
+procedure png_set_gAMA_fixed(png_ptr:png_structp; info_ptr:png_infop; int_file_gamma:png_fixed_point); cdecl; external LibPng;
+function png_get_hIST(png_ptr:png_structp; info_ptr:png_infop; hist:Ppng_uint_16p):png_uint_32; cdecl; external LibPng;
+procedure png_set_hIST(png_ptr:png_structp; info_ptr:png_infop; hist:png_uint_16p); cdecl; external LibPng;
+function png_get_IHDR(png_ptr:png_structp; info_ptr:png_infop; width:Ppng_uint_32; height:Ppng_uint_32; bit_depth:PCint;
+           color_type:PCint; interlace_type:PCint; compression_type:PCint; filter_type:PCint):png_uint_32; cdecl; external LibPng;
+procedure png_set_IHDR(png_ptr:png_structp; info_ptr:png_infop; width:png_uint_32; height:png_uint_32; bit_depth:cint;
+            color_type:cint; interlace_type:cint; compression_type:cint; filter_type:cint); cdecl; external LibPng;
+function png_get_oFFs(png_ptr:png_structp; info_ptr:png_infop; offset_x:Ppng_int_32; offset_y:Ppng_int_32; unit_type:PCint):png_uint_32; cdecl; external LibPng;
+procedure png_set_oFFs(png_ptr:png_structp; info_ptr:png_infop; offset_x:png_int_32; offset_y:png_int_32; unit_type:cint); cdecl; external LibPng;
+function png_get_pCAL(png_ptr:png_structp; info_ptr:png_infop; purpose:Ppng_charp; X0:Ppng_int_32; X1:Ppng_int_32;
+           atype:PCint; nparams:PCint; units:Ppng_charp; params:Ppng_charpp):png_uint_32; cdecl; external LibPng;
+procedure png_set_pCAL(png_ptr:png_structp; info_ptr:png_infop; purpose:png_charp; X0:png_int_32; X1:png_int_32;
+            atype:cint; nparams:cint; units:png_charp; params:png_charpp); cdecl; external LibPng;
+function png_get_pHYs(png_ptr:png_structp; info_ptr:png_infop; res_x:Ppng_uint_32; res_y:Ppng_uint_32; unit_type:PCint):png_uint_32; cdecl; external LibPng;
+procedure png_set_pHYs(png_ptr:png_structp; info_ptr:png_infop; res_x:png_uint_32; res_y:png_uint_32; unit_type:cint); cdecl; external LibPng;
+function png_get_PLTE(png_ptr:png_structp; info_ptr:png_infop; palette:Ppng_colorp; num_palette:PCint):png_uint_32; cdecl; external LibPng;
+procedure png_set_PLTE(png_ptr:png_structp; info_ptr:png_infop; palette:png_colorp; num_palette:cint); cdecl; external LibPng;
+function png_get_sBIT(png_ptr:png_structp; info_ptr:png_infop; sig_bit:Ppng_color_8p):png_uint_32; cdecl; external LibPng;
+procedure png_set_sBIT(png_ptr:png_structp; info_ptr:png_infop; sig_bit:png_color_8p); cdecl; external LibPng;
+function png_get_sRGB(png_ptr:png_structp; info_ptr:png_infop; intent:PCint):png_uint_32; cdecl; external LibPng;
+procedure png_set_sRGB(png_ptr:png_structp; info_ptr:png_infop; intent:cint); cdecl; external LibPng;
+procedure png_set_sRGB_gAMA_and_cHRM(png_ptr:png_structp; info_ptr:png_infop; intent:cint); cdecl; external LibPng;
+function png_get_iCCP(png_ptr:png_structp; info_ptr:png_infop; name:png_charpp; compression_type:PCint; profile:png_charpp;
+           proflen:Ppng_uint_32):png_uint_32; cdecl; external LibPng;
+procedure png_set_iCCP(png_ptr:png_structp; info_ptr:png_infop; name:png_charp; compression_type:cint; profile:png_charp;
+            proflen:png_uint_32); cdecl; external LibPng;
+function png_get_sPLT(png_ptr:png_structp; info_ptr:png_infop; entries:png_sPLT_tpp):png_uint_32; cdecl; external LibPng;
+procedure png_set_sPLT(png_ptr:png_structp; info_ptr:png_infop; entries:png_sPLT_tp; nentries:cint); cdecl; external LibPng;
+
+(* png_get_text also returns the number of text chunks in *num_text *)
+function png_get_text(png_ptr:png_structp; info_ptr:png_infop; text_ptr:Ppng_textp; num_text:PCint):png_uint_32; cdecl; external LibPng;
+
+(*
+ *  Note while png_set_text() will accept a structure whose text,
+ *  language, and  translated keywords are NULL pointers, the structure
+ *  returned by png_get_text will always contain regular
+ *  zero-terminated C strings.  They might be empty strings but
+ *  they will never be NULL pointers.
+ *)
+procedure png_set_text(png_ptr:png_structp; info_ptr:png_infop; text_ptr:png_textp; num_text:cint); cdecl; external LibPng;
+
+function png_get_tIME(png_ptr:png_structp; info_ptr:png_infop; mod_time:Ppng_timep):png_uint_32; cdecl; external LibPng;
+procedure png_set_tIME(png_ptr:png_structp; info_ptr:png_infop; mod_time:png_timep); cdecl; external LibPng;
+function png_get_tRNS(png_ptr:png_structp; info_ptr:png_infop; trans:Ppng_bytep; num_trans:PCint; trans_values:Ppng_color_16p):png_uint_32; cdecl; external LibPng;
+procedure png_set_tRNS(png_ptr:png_structp; info_ptr:png_infop; trans:png_bytep; num_trans:cint; trans_values:png_color_16p); cdecl; external LibPng;
+function png_get_sCAL(png_ptr:png_structp; info_ptr:png_infop; aunit:PCint; width:PCdouble; height:PCdouble):png_uint_32; cdecl; external LibPng;
+procedure png_set_sCAL(png_ptr:png_structp; info_ptr:png_infop; aunit:cint; width:cdouble; height:cdouble); cdecl; external LibPng;
+procedure png_set_sCAL_s(png_ptr:png_structp; info_ptr:png_infop; aunit:cint; swidth:png_charp; sheight:png_charp); cdecl; external LibPng;
+
+procedure png_set_keep_unknown_chunks(png_ptr:png_structp; keep:cint; chunk_list:png_bytep; num_chunks:cint); cdecl; external LibPng;
+procedure png_set_unknown_chunks(png_ptr:png_structp; info_ptr:png_infop; unknowns:png_unknown_chunkp; num_unknowns:cint); cdecl; external LibPng;
+procedure png_set_unknown_chunk_location(png_ptr:png_structp; info_ptr:png_infop; chunk:cint; location:cint); cdecl; external LibPng;
+function png_get_unknown_chunks(png_ptr:png_structp; info_ptr:png_infop; entries:png_unknown_chunkpp):png_uint_32; cdecl; external LibPng;
+
+procedure png_set_invalid(png_ptr:png_structp; info_ptr:png_infop; mask:cint); cdecl; external LibPng;
+
+procedure png_read_png(png_ptr:png_structp; info_ptr:png_infop; transforms:cint; params:png_voidp); cdecl; external LibPng;
+procedure png_write_png(png_ptr:png_structp; info_ptr:png_infop; transforms:cint; params:png_voidp); cdecl; external LibPng;
+
+function png_get_header_ver(png_ptr:png_structp):png_charp; cdecl; external LibPng;
+function png_get_header_version(png_ptr:png_structp):png_charp; cdecl; external LibPng;
+function png_get_libpng_ver(png_ptr:png_structp):png_charp; cdecl; external LibPng;
+
+implementation
+
+end.
diff --git a/songmanagement/src/lib/midi/CIRCBUF.PAS b/songmanagement/src/lib/midi/CIRCBUF.PAS
new file mode 100644
index 00000000..3ceb4c6e
--- /dev/null
+++ b/songmanagement/src/lib/midi/CIRCBUF.PAS
@@ -0,0 +1,183 @@
+{ $Header: /MidiComp/CIRCBUF.PAS 2     10/06/97 7:33 Davec $ }
+
+{ Written by David Churcher <dchurcher@cix.compulink.co.uk>,
+  released to the public domain. }
+
+
+{ A First-In First-Out circular buffer.
+  Port of circbuf.c from Microsoft's Windows MIDI monitor example.
+  I did do a version of this as an object (see Rev 1.1) but it was getting too 
+  complicated and I couldn't see any real benefits to it so I dumped it 
+  for an ordinary memory buffer with pointers. 
+
+  This unit is a bit C-like, everything is done with pointers and extensive
+  use is made of the undocumented feature of the Inc() function that 
+  increments pointers by the size of the object pointed to.
+  All of this could probably be done using Pascal array notation with
+  range-checking turned off, but I'm not sure it's worth it.
+}
+
+Unit Circbuf;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+Uses
+  Windows,
+  MMSystem;
+
+type
+	{ MIDI input event }
+	TMidiBufferItem = record
+	  	timestamp: DWORD;	{ Timestamp in milliseconds after midiInStart }
+		data: DWORD;		{ MIDI message received }
+		sysex: PMidiHdr;	{ Pointer to sysex MIDIHDR, nil if not sysex }
+	end;
+	PMidiBufferItem = ^TMidiBufferItem;
+
+	{ MIDI input buffer }
+	TCircularBuffer = record
+		RecordHandle: HGLOBAL;		{ Windows memory handle for this record }
+		BufferHandle: HGLOBAL;		{ Windows memory handle for the buffer }
+		pStart: PMidiBufferItem;		{ ptr to start of buffer }
+		pEnd: PMidiBufferItem;			{ ptr to end of buffer }
+		pNextPut: PMidiBufferItem;		{ next location to fill }
+		pNextGet: PMidiBufferItem;		{ next location to empty }
+		Error: Word;		 		{ error code from MMSYSTEM functions }
+		Capacity: Word;				{ buffer size (in TMidiBufferItems) }
+		EventCount: Word;			{ Number of events in buffer }
+	end;
+
+   PCircularBuffer = ^TCircularBuffer;
+
+function GlobalSharedLockedAlloc( Capacity: Word; var hMem: HGLOBAL ): Pointer;
+procedure GlobalSharedLockedFree( hMem: HGLOBAL; ptr: Pointer );
+
+function CircbufAlloc( Capacity: Word ): PCircularBuffer;
+procedure CircbufFree( PBuffer: PCircularBuffer );
+function CircbufRemoveEvent( PBuffer: PCircularBuffer ): Boolean;
+function CircbufReadEvent( PBuffer: PCircularBuffer; PEvent: PMidiBufferItem ): Boolean;
+{ Note: The PutEvent function is in the DLL }
+
+implementation
+
+{ Allocates in global shared memory, returns pointer and handle }
+function GlobalSharedLockedAlloc( Capacity: Word; var hMem: HGLOBAL ): Pointer;
+var
+	ptr: Pointer;
+begin
+	{ Allocate the buffer memory }
+	hMem := GlobalAlloc(GMEM_SHARE Or GMEM_MOVEABLE Or GMEM_ZEROINIT, Capacity );
+
+	if (hMem = 0) then
+		ptr := Nil
+	else
+		begin
+		ptr := GlobalLock(hMem);
+		if (ptr = Nil) then
+			GlobalFree(hMem);
+		end;
+
+	GlobalSharedLockedAlloc := Ptr;
+end;
+
+procedure GlobalSharedLockedFree( hMem: HGLOBAL; ptr: Pointer );
+begin
+	if (hMem <> 0) then
+		begin
+		GlobalUnlock(hMem);
+		GlobalFree(hMem);
+		end;
+end;
+
+function CircbufAlloc( Capacity: Word ): PCircularBuffer;
+var
+	NewCircularBuffer: PCircularBuffer;
+	NewMIDIBuffer: PMidiBufferItem;
+	hMem: HGLOBAL;
+begin
+	{ TODO: Validate circbuf size, <64K }
+	NewCircularBuffer :=
+		GlobalSharedLockedAlloc( Sizeof(TCircularBuffer), hMem );
+	if (NewCircularBuffer <> Nil) then
+		begin
+		NewCircularBuffer^.RecordHandle := hMem;
+		NewMIDIBuffer :=
+			GlobalSharedLockedAlloc( Capacity * Sizeof(TMidiBufferItem), hMem );
+		if (NewMIDIBuffer = Nil) then
+			begin
+			{ TODO: Exception here? }
+			GlobalSharedLockedFree( NewCircularBuffer^.RecordHandle,
+											NewCircularBuffer );
+			NewCircularBuffer := Nil;
+			end
+		else
+			begin
+                	NewCircularBuffer^.pStart := NewMidiBuffer;
+			{ Point to item at end of buffer }
+			NewCircularBuffer^.pEnd := NewMidiBuffer;
+			Inc(NewCircularBuffer^.pEnd, Capacity);
+			{ Start off the get and put pointers in the same position. These
+			  will get out of sync as the interrupts start rolling in }
+			NewCircularBuffer^.pNextPut := NewMidiBuffer;
+			NewCircularBuffer^.pNextGet := NewMidiBuffer;
+			NewCircularBuffer^.Error := 0;
+			NewCircularBuffer^.Capacity := Capacity;
+			NewCircularBuffer^.EventCount := 0;
+			end;
+		end;
+	CircbufAlloc := NewCircularBuffer;
+end;
+
+procedure CircbufFree( pBuffer: PCircularBuffer );
+begin
+	if (pBuffer <> Nil) then
+		begin
+		GlobalSharedLockedFree(pBuffer^.BufferHandle, pBuffer^.pStart);
+		GlobalSharedLockedFree(pBuffer^.RecordHandle, pBuffer);
+		end;
+end;
+
+{ Reads first event in queue without removing it.
+  Returns true if successful, False if no events in queue }
+function CircbufReadEvent( PBuffer: PCircularBuffer; PEvent: PMidiBufferItem ): Boolean;
+var
+	PCurrentEvent: PMidiBufferItem;
+begin
+	if (PBuffer^.EventCount <= 0) then
+			CircbufReadEvent := False
+	else
+		begin
+		PCurrentEvent := PBuffer^.PNextget;
+
+		{ Copy the object from the "tail" of the buffer to the caller's object }
+		PEvent^.Timestamp := PCurrentEvent^.Timestamp;
+		PEvent^.Data := PCurrentEvent^.Data;
+        PEvent^.Sysex := PCurrentEvent^.Sysex;
+		CircbufReadEvent := True;
+		end;
+end;
+
+{ Remove current event from the queue }
+function CircbufRemoveEvent(PBuffer: PCircularBuffer): Boolean;
+begin
+	if (PBuffer^.EventCount > 0) then
+		begin
+		Dec( Pbuffer^.EventCount);
+
+		{ Advance the buffer pointer, with wrap }
+		Inc( Pbuffer^.PNextGet );
+		If (PBuffer^.PNextGet = PBuffer^.PEnd) then
+			PBuffer^.PNextGet := PBuffer^.PStart;
+
+		CircbufRemoveEvent := True;
+		end
+	else
+		CircbufRemoveEvent := False;
+end;
+
+end.
diff --git a/songmanagement/src/lib/midi/DELPHMCB.PAS b/songmanagement/src/lib/midi/DELPHMCB.PAS
new file mode 100644
index 00000000..ef0d5451
--- /dev/null
+++ b/songmanagement/src/lib/midi/DELPHMCB.PAS
@@ -0,0 +1,140 @@
+{ $Header: /MidiComp/DELPHMCB.PAS 2     10/06/97 7:33 Davec $ }
+
+{MIDI callback for Delphi, was DLL for Delphi 1}
+
+unit Delphmcb;
+
+{ These segment options required for the MIDI callback functions }
+{$IFNDEF FPC}
+{$C PRELOAD FIXED PERMANENT}
+{$ENDIF}
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+uses
+  Windows,
+  MMsystem,
+  Circbuf,
+  MidiDefs,
+  MidiCons;
+
+procedure midiHandler(
+		  hMidiIn: HMidiIn;
+		  wMsg: UINT;
+		  dwInstance: DWORD;
+		  dwParam1: DWORD;
+		  dwParam2: DWORD); stdcall; export;
+function CircbufPutEvent(PBuffer: PCircularBuffer; PTheEvent: PMidiBufferItem): Boolean; stdcall; export;
+
+implementation
+
+{ Add an event to the circular input buffer. }
+function CircbufPutEvent(PBuffer: PCircularBuffer; PTheEvent: PMidiBufferItem): Boolean; stdcall;
+begin
+	If (PBuffer^.EventCount < PBuffer^.Capacity) Then
+		begin
+		Inc(Pbuffer^.EventCount);
+
+		{ Todo: better way of copying this record }
+		with PBuffer^.PNextput^ do
+			begin
+			Timestamp := PTheEvent^.Timestamp;
+			Data := PTheEvent^.Data;
+			Sysex := PTheEvent^.Sysex;
+          end;
+
+		{ Move to next put location, with wrap }
+		Inc(Pbuffer^.PNextPut);
+		If (PBuffer^.PNextPut = PBuffer^.PEnd) then
+			PBuffer^.PNextPut := PBuffer^.PStart;
+
+		CircbufPutEvent := True;
+		end
+	else
+		CircbufPutEvent := False;
+end;
+
+{ This is the callback function specified when the MIDI device was opened
+  by midiInOpen. It's called at interrupt time when MIDI input is seen
+  by the MIDI device driver(s). See the docs for midiInOpen for restrictions
+  on the Windows functions that can be called in this interrupt. }
+procedure midiHandler(
+		  hMidiIn: HMidiIn;
+		  wMsg: UINT;
+		  dwInstance: DWORD;
+		  dwParam1: DWORD;
+		  dwParam2: DWORD); stdcall;
+var
+	thisEvent: TMidiBufferItem;
+	thisCtlInfo: PMidiCtlInfo;
+	thisBuffer: PCircularBuffer;
+Begin
+	case wMsg of
+
+		mim_Open: {nothing};
+
+		mim_Error: {TODO: handle (message to trigger exception?) };
+
+		mim_Data, mim_Longdata, mim_Longerror:
+			{ Note: mim_Longerror included because there's a bug in the Maui
+			input driver that sends MIM_LONGERROR for subsequent buffers when
+			the input buffer is smaller than the sysex block being received }
+
+			begin
+			{ TODO: Make filtered messages customisable, I'm sure someone wants to
+			do something with MTC! }
+			if (dwParam1 <> MIDI_ACTIVESENSING) and
+							(dwParam1 <> MIDI_TIMINGCLOCK) then
+				begin
+
+				{ The device driver passes us the instance data pointer we
+				specified for midiInOpen. Use this to get the buffer address
+				and window handle for the MIDI control }
+				thisCtlInfo := PMidiCtlInfo(dwInstance);
+				thisBuffer := thisCtlInfo^.PBuffer;
+
+				{ Screen out short messages if we've been asked to }
+				if ((wMsg <> mim_Data) or (thisCtlInfo^.SysexOnly = False))
+					and (thisCtlInfo <> Nil) and (thisBuffer <> Nil) then
+					begin
+					with thisEvent do
+						begin
+						timestamp := dwParam2;
+						if (wMsg = mim_Longdata) or
+							(wMsg = mim_Longerror) then
+							begin
+							data := 0;
+							sysex := PMidiHdr(dwParam1);
+							end
+						else
+							begin
+							data := dwParam1;
+							sysex := Nil;
+							end;
+						end;
+					if CircbufPutEvent( thisBuffer, @thisEvent ) then
+						{ Send a message to the control to say input's arrived }
+						PostMessage(thisCtlInfo^.hWindow, mim_Data, 0, 0)
+					else
+						{ Buffer overflow }
+						PostMessage(thisCtlInfo^.hWindow, mim_Overflow, 0, 0);
+					end;
+				end;
+			end;
+
+		mom_Done:	{ Sysex output complete, dwParam1 is pointer to MIDIHDR }
+			begin
+			{ Notify the control that its sysex output is finished.
+			  The control should call midiOutUnprepareHeader before freeing the buffer }
+			PostMessage(PMidiCtlInfo(dwInstance)^.hWindow, mom_Done, 0, dwParam1);
+			end;
+
+	end;	{ Case }
+end;
+
+end.
diff --git a/songmanagement/src/lib/midi/MIDIDEFS.PAS b/songmanagement/src/lib/midi/MIDIDEFS.PAS
new file mode 100644
index 00000000..4afe56ef
--- /dev/null
+++ b/songmanagement/src/lib/midi/MIDIDEFS.PAS
@@ -0,0 +1,55 @@
+{ $Header: /MidiComp/MIDIDEFS.PAS 2     10/06/97 7:33 Davec $ }
+
+{ Written by David Churcher <dchurcher@cix.compulink.co.uk>,
+  released to the public domain. }
+
+
+{ Common definitions used by DELPHMID.DPR and the MIDI components.
+  This must be a separate unit to prevent large chunks of the VCL being
+  linked into the DLL. }
+unit Mididefs;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+uses
+  Windows,
+  MMsystem,
+  Circbuf;
+
+type
+
+	{-------------------------------------------------------------------}
+	{ This is the information about the control that must be accessed by
+	  the MIDI input callback function in the DLL at interrupt time }
+	PMidiCtlInfo = ^TMidiCtlInfo;
+	TMidiCtlInfo = record
+		hMem: THandle; 				{ Memory handle for this record }
+		PBuffer: PCircularBuffer;	{ Pointer to the MIDI input data buffer }
+		hWindow: HWnd;					{ Control's window handle }
+		SysexOnly: Boolean;			{ Only process System Exclusive input }
+	end;
+
+	{ Information for the output timer callback function, also required at
+	  interrupt time. }
+	PMidiOutTimerInfo = ^TMidiOutTimerInfo;
+	TMidiOutTimerInfo = record
+		hMem: THandle;				{ Memory handle for this record }
+		PBuffer: PCircularBuffer;	{ Pointer to MIDI output data buffer }
+		hWindow: HWnd;				{ Control's window handle }
+		TimeToNextEvent: DWORD;	{ Delay to next event after timer set }
+		MIDIHandle: HMidiOut;		{ MIDI handle to send output to 
+									(copy of component's FMidiHandle property) }
+		PeriodMin: Word;			{ Multimedia timer minimum period supported }
+		PeriodMax: Word;			{ Multimedia timer maximum period supported }
+		TimerId: Word;				{ Multimedia timer ID of current event }
+	end;
+
+implementation
+
+
+end.
diff --git a/songmanagement/src/lib/midi/MIDITYPE.PAS b/songmanagement/src/lib/midi/MIDITYPE.PAS
new file mode 100644
index 00000000..45b50820
--- /dev/null
+++ b/songmanagement/src/lib/midi/MIDITYPE.PAS
@@ -0,0 +1,90 @@
+{ $Header: /MidiComp/MIDITYPE.PAS 2     10/06/97 7:33 Davec $ }
+
+{ Written by David Churcher <dchurcher@cix.compulink.co.uk>,
+  released to the public domain. }
+
+
+unit Miditype;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+uses
+  Classes,
+  Windows,
+  Messages,
+  MMSystem,
+  MidiDefs,
+  Circbuf;
+
+type
+	{-------------------------------------------------------------------}
+	{ A MIDI input/output event }
+	TMyMidiEvent = class(TPersistent)
+	public
+		MidiMessage: Byte;          { MIDI message status byte }
+		Data1: Byte;            { MIDI message data 1 byte }
+		Data2: Byte;            { MIDI message data 2 byte }
+		Time: DWORD;          { Time in ms since midiInOpen }
+		SysexLength: Word;  { Length of sysex data (0 if none) }
+		Sysex: PChar;           { Pointer to sysex data buffer }
+		destructor Destroy; override;   { Frees sysex data buffer if nec. }
+	end;
+	PMyMidiEvent = ^TMyMidiEvent;
+
+	{-------------------------------------------------------------------}
+	{ Encapsulates the MIDIHDR with its memory handle and sysex buffer }
+	PMyMidiHdr = ^TMyMidiHdr;
+	TMyMidiHdr = class(TObject)
+	public
+		hdrHandle: THandle;
+		hdrPointer: PMIDIHDR;
+		sysexHandle: THandle;
+		sysexPointer: Pointer;
+		constructor Create(BufferSize: Word);
+		destructor Destroy; override;
+	end;
+
+implementation
+
+{-------------------------------------------------------------------}
+{ Free any sysex buffer associated with the event }
+destructor TMyMidiEvent.Destroy;
+begin
+	if (Sysex <> Nil) then
+		Freemem(Sysex, SysexLength);
+
+	inherited Destroy;
+end;
+
+{-------------------------------------------------------------------}
+{ Allocate memory for the sysex header and buffer }
+constructor TMyMidiHdr.Create(BufferSize:Word);
+begin
+	inherited Create;
+
+	if BufferSize > 0 then
+		begin
+		hdrPointer := GlobalSharedLockedAlloc(sizeof(TMIDIHDR), hdrHandle);
+		sysexPointer := GlobalSharedLockedAlloc(BufferSize, sysexHandle);
+
+		hdrPointer^.lpData := sysexPointer;
+		hdrPointer^.dwBufferLength := BufferSize;
+		end;
+end;
+
+{-------------------------------------------------------------------}
+destructor TMyMidiHdr.Destroy;
+begin
+	GlobalSharedLockedFree( hdrHandle, hdrPointer );
+	GlobalSharedLockedFree( sysexHandle, sysexPointer );
+	inherited Destroy;
+end;
+
+
+
+end.
diff --git a/songmanagement/src/lib/midi/MidiFile.pas b/songmanagement/src/lib/midi/MidiFile.pas
new file mode 100644
index 00000000..acf44c04
--- /dev/null
+++ b/songmanagement/src/lib/midi/MidiFile.pas
@@ -0,0 +1,968 @@
+{
+  Load a midifile and get access to tracks and events
+  I did build this component to convert midifiles to wave files
+  or play the files on a software synthesizer which I'm currenly
+  building.
+
+  version 1.0 first release
+
+  version 1.1
+    added some function
+    function KeyToStr(key : integer) : string;
+    function MyTimeToStr(val : integer) : string;
+    Bpm can be set to change speed
+
+  version 1.2
+    added some functions
+    function  GetTrackLength:integer;
+    function  Ready: boolean;
+
+  version 1.3
+    update by Chulwoong,
+    He knows how to use the MM timer, the timing is much better now, thank you
+
+  for comments/bugs
+  F.Bouwmans
+  fbouwmans@spiditel.nl
+
+  if you think this component is nice and you use it, sent me a short email.
+  I've seen that other of my components have been downloaded a lot, but I've
+  got no clue wether they are actually used.
+  Don't worry because you are free to use these components
+
+  Timing has improved, however because the messages are handled by the normal
+  windows message loop (of the main window) it is still influenced by actions
+  done on the window (minimize/maximize ..).
+  Use of a second thread with higher priority which only handles the
+  timer message should increase performance. If somebody knows such a component
+  which is freeware please let me know.
+
+  interface description:
+
+  procedure ReadFile:
+    actually read the file which is set in Filename
+
+  function GetTrack(index: integer) : TMidiTrack;
+
+  property Filename
+    set/read filename of midifile
+
+  property NumberOfTracks
+    read number of tracks in current file
+
+  property TicksPerQuarter: integer
+    ticks per quarter, tells how to interpret the time value in midi events
+
+  property FileFormat: TFileFormat
+    tells the format of the current midifile
+
+  property Bpm:integer
+    tells Beats per minut
+
+  property OnMidiEvent:TOnMidiEvent
+    called while playing for each midi event
+
+  procedure StartPlaying;
+    start playing the current loaded midifile from the beginning
+
+  procedure StopPlaying;
+    stop playing the current midifile
+
+  procedure PlayToTime(time : integer);
+    if playing yourself then events from last time to this time are produced
+
+
+  function KeyToStr(key : integer) : string;
+      give note string on key value:  e.g. C4
+
+  function MyTimeToStr(val : integer) : string;
+      give time string from msec time
+
+  function  GetTrackLength:integer;
+      gives the track lenght in msec (assuming the bpm at the start oof the file)
+
+  function  Ready: boolean;
+      now you can check wether the playback is finished
+
+}
+
+unit MidiFile;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+uses
+  Windows,
+  Messages,
+  Classes,
+  {$IFDEF FPC}
+  WinAllocation,
+  {$ENDIF}
+  SysUtils,
+  UPath;
+
+type
+  TChunkType = (illegal, header, track);
+  TFileFormat = (single, multi_synch, multi_asynch);
+  PByte = ^byte;
+
+  TMidiEvent = record
+    event: byte;
+    data1: byte;
+    data2: byte;
+    str: string;
+    dticks: integer;
+    time: integer;
+    mtime: integer;
+    len: integer;
+  end;
+  PMidiEvent = ^TMidiEvent;
+
+  TOnMidiEvent = procedure(event: PMidiEvent) of object;
+  TEvent = procedure of object;
+
+  TMidiTrack = class(TObject)
+  protected
+    events: TList;
+      name: string;
+    instrument: string;
+    currentTime: integer;
+    currentPos: integer;
+    ready: boolean;
+    trackLenght: integer;
+    procedure checkReady;
+  public
+    OnMidiEvent: TOnMidiEvent;
+    OnTrackReady: TEvent;
+    constructor Create;
+    destructor Destroy; override;
+
+    procedure Rewind(pos: integer);
+    procedure PlayUntil(pos: integer);
+    procedure GoUntil(pos: integer);
+
+    procedure putEvent(event: PMidiEvent);
+    function getEvent(index: integer): PMidiEvent;
+    function getName: string;
+    function getInstrument: string;
+    function getEventCount: integer;
+    function getCurrentTime: integer;
+    function getTrackLength: integer;
+    function isReady:boolean;
+  end;
+
+  TMidiFile = class(TComponent)
+  private
+    { Private declarations }
+    procedure MidiTimer(sender : TObject);
+    procedure WndProc(var Msg : TMessage);
+  protected
+    { Protected declarations }
+    midiFile: TBinaryFileStream;
+    chunkType: TChunkType;
+    chunkLength: integer;
+    chunkData: PByte;
+    chunkIndex: PByte;
+    chunkEnd: PByte;
+    FPriority: DWORD;
+
+    // midi file attributes
+    FFileFormat: TFileFormat;
+    numberTracks: integer;
+    deltaTicks: integer;
+    FBpm: integer;
+    FBeatsPerMeasure: integer;
+    FusPerTick: double;
+    FFilename: IPath;
+
+    Tracks: TList;
+    currentTrack: TMidiTrack;
+    FOnMidiEvent: TOnMidiEvent;
+    FOnUpdateEvent: TNotifyEvent;
+
+    // playing attributes
+    playing: boolean;
+    PlayStartTime: integer;
+    currentTime: integer; // Current playtime in msec
+    currentPos: Double; // Current Position in ticks
+
+    procedure OnTrackReady;
+    procedure SetFilename(val: IPath);
+    procedure ReadChunkHeader;
+    procedure ReadChunkContent;
+    procedure ReadChunk;
+    procedure ProcessHeaderChunk;
+    procedure ProcessTrackChunk;
+    function ReadVarLength: integer;
+    function ReadString(l: integer): string;
+    procedure SetOnMidiEvent(handler: TOnMidiEvent);
+    procedure SetBpm(val: integer);
+  public
+    { Public declarations }
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+
+    procedure ReadFile;
+    function GetTrack(index: integer): TMidiTrack;
+
+    procedure StartPlaying;
+    procedure StopPlaying;
+    procedure ContinuePlaying;
+
+    procedure PlayToTime(time: integer);
+    procedure GoToTime(time: integer);
+    function GetCurrentTime: integer;
+    function GetFusPerTick : Double;
+    function  GetTrackLength:integer;
+    function  Ready: boolean;
+  published
+    { Published declarations }
+    property Filename: IPath read FFilename write SetFilename;
+    property NumberOfTracks: integer read numberTracks;
+    property TicksPerQuarter: integer read deltaTicks;
+    property FileFormat: TFileFormat read FFileFormat;
+    property Bpm: integer read FBpm write SetBpm;
+    property OnMidiEvent: TOnMidiEvent read FOnMidiEvent write SetOnMidiEvent;
+    property OnUpdateEvent: TNotifyEvent read FOnUpdateEvent write FOnUpdateEvent;
+  end;
+
+function KeyToStr(key: integer): string;
+function MyTimeToStr(val: integer): string;
+procedure Register;
+
+implementation
+
+uses mmsystem;
+
+type
+{$IFDEF FPC}
+  TTimerProc = TTIMECALLBACK;
+  TTimeCaps = TIMECAPS;
+{$ELSE}
+  TTimerProc = TFNTimeCallBack;
+{$ENDIF}
+
+const TIMER_RESOLUTION=10;
+const WM_MULTIMEDIA_TIMER=WM_USER+127;
+
+var MIDIFileHandle : HWND;
+    TimerProc      : TTimerProc;
+    MIDITimerID    : Integer;
+    TimerPeriod     : Integer;
+
+procedure TimerCallBackProc(uTimerID,uMsg: Cardinal; dwUser,dwParam1,dwParam2:DWORD);stdcall;
+begin
+     PostMessage(HWND(dwUser),WM_MULTIMEDIA_TIMER,0,0);
+end;
+
+procedure SetMIDITimer;
+  var TimeCaps    : TTimeCaps;
+begin
+  timeGetDevCaps(@TimeCaps,SizeOf(TimeCaps));
+  if TIMER_RESOLUTION < TimeCaps.wPeriodMin then
+    TimerPeriod:=TimeCaps.wPeriodMin
+  else if TIMER_RESOLUTION > TimeCaps.wPeriodMax then
+    TimerPeriod:=TimeCaps.wPeriodMax
+  else
+    TimerPeriod:=TIMER_RESOLUTION;
+
+  timeBeginPeriod(TimerPeriod);
+  MIDITimerID:=timeSetEvent(TimerPeriod,TimerPeriod,TimerProc,
+                            DWORD(MIDIFileHandle),TIME_PERIODIC);
+  if MIDITimerID=0 then
+    timeEndPeriod(TimerPeriod);
+end;
+
+procedure KillMIDITimer;
+begin
+  timeKillEvent(MIDITimerID);
+  timeEndPeriod(TimerPeriod);
+end;
+
+constructor TMidiTrack.Create;
+begin
+  inherited Create;
+  events := TList.Create;
+  currentTime := 0;
+  currentPos := 0;
+end;
+
+destructor TMidiTrack.Destroy;
+var
+  i: integer;
+begin
+  for i := 0 to events.count - 1 do
+    Dispose(PMidiEvent(events.items[i]));
+  events.Free;
+  inherited Destroy;
+end;
+
+procedure TMidiTRack.putEvent(event: PMidiEvent);
+var
+  command: integer;
+  i: integer;
+  pevent: PMidiEvent;
+begin
+  if (event.event = $FF) then
+  begin
+    if (event.data1 = 3) then
+      name := event.str;
+    if (event.data1 = 4) then
+      instrument := event.str;
+  end;
+  currentTime := currentTime + event.dticks;
+  event.time := currentTime; // for the moment just add dticks
+  event.len := 0;
+  events.add(TObject(event));
+  command := event.event and $F0;
+
+  if ((command = $80) // note off
+    or ((command = $90) and (event.data2 = 0))) //note on with speed 0
+  then
+  begin
+    // this is a note off, try to find the accompanion note on
+    command := event.event or $90;
+    i := events.count - 2;
+    while i >= 0 do
+    begin
+      pevent := PMidiEvent(events[i]);
+      if (pevent.event = command) and
+        (pevent.data1 = event.data1)
+        then
+      begin
+        pevent.len := currentTIme - pevent.time;
+        i := 0;
+        event.len := -1;
+      end;
+      dec(i);
+    end;
+  end;
+end;
+
+function TMidiTrack.getName: string;
+begin
+  result := name;
+end;
+
+function TMidiTrack.getInstrument: string;
+begin
+  result := instrument;
+end;
+
+function TMiditrack.getEventCount: integer;
+begin
+  result := events.count;
+end;
+
+function TMiditrack.getEvent(index: integer): PMidiEvent;
+begin
+  if ((index < events.count) and (index >= 0)) then
+    result := events[index]
+  else
+    result := nil;
+end;
+
+function TMiditrack.getCurrentTime: integer;
+begin
+  result := currentTime;
+end;
+
+procedure TMiditrack.Rewind(pos: integer);
+begin
+  if currentPos = events.count then
+    dec(currentPos);
+  while ((currentPos > 0) and
+    (PMidiEvent(events[currentPos]).time > pos))
+    do
+  begin
+    dec(currentPos);
+  end;
+  checkReady;
+end;
+
+procedure TMiditrack.PlayUntil(pos: integer);
+begin
+  if assigned(OnMidiEvent) then
+  begin
+    while ((currentPos < events.count) and
+      (PMidiEvent(events[currentPos]).time < pos)) do
+    begin
+      OnMidiEvent(PMidiEvent(events[currentPos]));
+      inc(currentPos);
+    end;
+  end;
+  checkReady;
+end;
+
+procedure TMidiTrack.GoUntil(pos: integer);
+begin
+  while ((currentPos < events.count) and
+    (PMidiEvent(events[currentPos]).time < pos)) do
+  begin
+    inc(currentPos);
+  end;
+  checkReady;
+end;
+
+procedure TMidiTrack.checkReady;
+begin
+  if currentPos >= events.count then
+  begin
+    ready := true;
+    if assigned(OnTrackReady) then
+      OnTrackReady;
+  end
+  else
+    ready := false;
+end;
+
+function TMidiTrack.getTrackLength: integer;
+begin
+  result := PMidiEvent(events[events.count-1]).time
+end;
+
+function TMidiTrack.isReady: boolean;
+begin
+  result := ready;
+end;
+
+constructor TMidifile.Create(AOwner: TComponent);
+begin
+  inherited Create(AOWner);
+  MIDIFileHandle:=AllocateHWnd(WndProc);
+  chunkData := nil;
+  chunkType := illegal;
+  Tracks := TList.Create;
+  TimerProc:=@TimerCallBackProc;
+  FPriority:=GetPriorityClass(MIDIFileHandle);
+end;
+
+destructor TMidifile.Destroy;
+var
+  i: integer;
+begin
+  if not (chunkData = nil) then FreeMem(chunkData);
+  for i := 0 to Tracks.Count - 1 do
+    TMidiTrack(Tracks.Items[i]).Free;
+  Tracks.Free;
+  SetPriorityClass(MIDIFileHandle,FPriority);
+
+  if MIDITimerID<>0 then KillMIDITimer;
+
+  DeallocateHWnd(MIDIFileHandle);
+
+  inherited Destroy;
+end;
+
+function TMidiFile.GetTrack(index: integer): TMidiTrack;
+begin
+  result := Tracks.Items[index];
+end;
+
+procedure TMidifile.SetFilename(val: IPath);
+begin
+  FFilename := val;
+//  ReadFile;
+end;
+
+procedure TMidifile.SetOnMidiEvent(handler: TOnMidiEvent);
+var
+  i: integer;
+begin
+//  if not (FOnMidiEvent = handler) then
+//  begin
+  FOnMidiEvent := handler;
+  for i := 0 to tracks.count - 1 do
+    TMidiTrack(tracks.items[i]).OnMidiEvent := handler;
+//  end;
+end;
+
+{$WARNINGS OFF}
+procedure TMidifile.MidiTimer(Sender: TObject);
+begin
+  if playing then
+  begin
+    PlayToTime(GetTickCount - PlayStartTime);
+    if assigned(FOnUpdateEvent) then FOnUpdateEvent(self);
+  end;
+end;
+{$WARNINGS ON}
+
+procedure TMidifile.StartPlaying;
+var
+  i: integer;
+begin
+  for i := 0 to tracks.count - 1 do
+    TMidiTrack(tracks[i]).Rewind(0);
+  playStartTime := getTickCount;
+  playing := true;
+
+  SetPriorityClass(MIDIFileHandle,REALTIME_PRIORITY_CLASS);
+
+  SetMIDITimer;
+  currentPos := 0.0;
+  currentTime := 0;
+end;
+
+{$WARNINGS OFF}
+procedure TMidifile.ContinuePlaying;
+begin
+  PlayStartTime := GetTickCount - currentTime;
+  playing := true;
+
+  SetPriorityClass(MIDIFileHandle,REALTIME_PRIORITY_CLASS);
+
+  SetMIDITimer;
+end;
+{$WARNINGS ON}
+
+procedure TMidifile.StopPlaying;
+begin
+  playing := false;
+  KillMIDITimer;
+  SetPriorityClass(MIDIFileHandle,FPriority);
+end;
+
+function TMidiFile.GetCurrentTime: integer;
+begin
+  Result := currentTime;
+end;
+
+procedure TMidifile.PlayToTime(time: integer);
+var
+  i: integer;
+  track: TMidiTrack;
+  pos: integer;
+  deltaTime: integer;
+begin
+  // calculate the pos in the file.
+  // pos is actually tick
+  // Current FusPerTick is uses to determine the actual pos
+
+  deltaTime := time - currentTime;
+  currentPos := currentPos + (deltaTime * 1000) / FusPerTick;
+  pos := round(currentPos);
+
+  for i := 0 to tracks.count - 1 do
+  begin
+    TMidiTrack(tracks.items[i]).PlayUntil(pos);
+  end;
+  currentTime := time;
+end;
+
+procedure TMidifile.GoToTime(time: integer);
+var
+  i: integer;
+  track: TMidiTrack;
+  pos: integer;
+begin
+  // this function should be changed because FusPerTick might not be constant
+  pos := round((time * 1000) / FusPerTick);
+  for i := 0 to tracks.count - 1 do
+  begin
+    TMidiTrack(tracks.items[i]).Rewind(0);
+    TMidiTrack(tracks.items[i]).GoUntil(pos);
+  end;
+end;
+
+procedure TMidifile.SetBpm(val: integer);
+var
+  us_per_quarter: integer;
+begin
+  if not (val = FBpm) then
+  begin
+    us_per_quarter := 60000000 div val;
+
+    FBpm := 60000000 div us_per_quarter;
+    FusPerTick := us_per_quarter / deltaTicks;
+  end;
+end;
+
+procedure TMidifile.ReadChunkHeader;
+var
+  theByte: array[0..7] of byte;
+begin
+  midiFile.Read(theByte[0], 8);
+  if (theByte[0] = $4D) and (theByte[1] = $54) then
+  begin
+    if (theByte[2] = $68) and (theByte[3] = $64) then
+      chunkType := header
+    else if (theByte[2] = $72) and (theByte[3] = $6B) then
+      chunkType := track
+    else
+      chunkType := illegal;
+  end
+  else
+  begin
+    chunkType := illegal;
+  end;
+  chunkLength := theByte[7] + theByte[6] * $100 + theByte[5] * $10000 + theByte[4] * $1000000;
+end;
+
+procedure TMidifile.ReadChunkContent;
+begin
+  if not (chunkData = nil) then
+    FreeMem(chunkData);
+  GetMem(chunkData, chunkLength + 10);
+  midiFile.Read(chunkData^, chunkLength);
+  chunkIndex := chunkData;
+  chunkEnd := PByte(integer(chunkIndex) + integer(chunkLength) - 1);
+end;
+
+procedure TMidifile.ReadChunk;
+begin
+  ReadChunkHeader;
+  ReadChunkContent;
+  case chunkType of
+    header:
+      ProcessHeaderChunk;
+    track:
+      ProcessTrackCHunk;
+  end;
+end;
+
+procedure TMidifile.ProcessHeaderChunk;
+begin
+  chunkIndex := chunkData;
+  inc(chunkIndex);
+  if chunkType = header then
+  begin
+    case chunkIndex^ of
+      0: FfileFormat := single;
+      1: FfileFormat := multi_synch;
+      2: FfileFormat := multi_asynch;
+    end;
+    inc(chunkIndex);
+    numberTracks := chunkIndex^ * $100;
+    inc(chunkIndex);
+    numberTracks := numberTracks + chunkIndex^;
+    inc(chunkIndex);
+    deltaTicks := chunkIndex^ * $100;
+    inc(chunkIndex);
+    deltaTicks := deltaTicks + chunkIndex^;
+  end;
+end;
+
+procedure TMidifile.ProcessTrackChunk;
+var
+  dTime: integer;
+  event: integer;
+  len: integer;
+  str: string;
+  midiEvent: PMidiEvent;
+  i: integer;
+  us_per_quarter: integer;
+begin
+  chunkIndex := chunkData;
+//  inc(chunkIndex);
+  event := 0;
+  if chunkType = track then
+  begin
+    currentTrack := TMidiTrack.Create;
+    currentTrack.OnMidiEvent := FOnMidiEvent;
+    Tracks.add(currentTrack);
+    while integer(chunkIndex) < integer(chunkEnd) do
+    begin
+      // each event starts with var length delta time
+      dTime := ReadVarLength;
+      if chunkIndex^ >= $80 then
+      begin
+        event := chunkIndex^;
+        inc(chunkIndex);
+      end;
+      // else it is a running status event (just the same event as before)
+
+      if event = $FF then
+      begin
+{        case chunkIndex^ of
+        $00: // sequence number, not implemented jet
+            begin
+              inc(chunkIndex); // $02
+              inc(chunkIndex);
+            end;
+        $01 .. $0f: // text events  FF ty len text
+            begin
+              New(midiEvent);
+              midiEvent.event := $FF;
+              midiEvent.data1 := chunkIndex^;     // type is stored in data1
+              midiEvent.dticks := dtime;
+
+              inc(chunkIndex);
+              len := ReadVarLength;
+              midiEvent.str    := ReadString(len);
+
+              currentTrack.putEvent(midiEvent);
+            end;
+        $20: // Midi channel prefix  FF 20 01 cc
+             begin
+               inc(chunkIndex); // $01
+               inc(chunkIndex); // channel
+               inc(chunkIndex);
+             end;
+        $2F: // End of track FF 2F 00
+             begin
+               inc(chunkIndex); // $00
+               inc(chunkIndex);
+             end;
+        $51: // Set Tempo  FF 51 03 tttttt
+             begin
+               inc(chunkIndex); // $03
+               inc(chunkIndex); // tt
+               inc(chunkIndex); // tt
+               inc(chunkIndex); // tt
+               inc(chunkIndex);
+             end;
+        $54: // SMPTE offset  FF 54 05 hr mn se fr ff
+             begin
+               inc(chunkIndex); // $05
+               inc(chunkIndex); // hr
+               inc(chunkIndex); // mn
+               inc(chunkIndex); // se
+               inc(chunkIndex); // fr
+               inc(chunkIndex); // ff
+               inc(chunkIndex);
+             end;
+        $58: // Time signature FF 58 04 nn dd cc bb
+             begin
+               inc(chunkIndex); // $04
+               inc(chunkIndex); // nn
+               inc(chunkIndex); // dd
+               inc(chunkIndex); // cc
+               inc(chunkIndex); // bb
+               inc(chunkIndex);
+             end;
+        $59: // Key signature FF 59 02 df mi
+             begin
+               inc(chunkIndex); // $02
+               inc(chunkIndex); // df
+               inc(chunkIndex); // mi
+               inc(chunkIndex);
+             end;
+        $7F: // Sequence specific Meta-event
+            begin
+              inc(chunkIndex);
+              len := ReadVarLength;
+              str := ReadString(len);
+            end;
+        else // unknown meta event
+        }
+        begin
+          New(midiEvent);
+          midiEvent.event := $FF;
+          midiEvent.data1 := chunkIndex^; // type is stored in data1
+          midiEvent.dticks := dtime;
+
+          inc(chunkIndex);
+          len := ReadVarLength;
+          midiEvent.str := ReadString(len);
+          currentTrack.putEvent(midiEvent);
+
+          case midiEvent.data1 of
+            $51:
+              begin
+                us_per_quarter :=
+                  (integer(byte(midiEvent.str[1])) shl 16 +
+                  integer(byte(midiEvent.str[2])) shl 8 +
+                  integer(byte(midiEvent.str[3])));
+                FBpm := 60000000 div us_per_quarter;
+                FusPerTick := us_per_quarter / deltaTicks;
+              end;
+          end;
+        end;
+//        end;
+      end
+      else
+      begin
+      // these are all midi events
+        New(midiEvent);
+        midiEvent.event := event;
+        midiEvent.dticks := dtime;
+//         inc(chunkIndex);
+        case event of
+          $80..$8F, // note off
+          $90..$9F, // note on
+          $A0..$AF, // key aftertouch
+          $B0..$BF, // control change
+          $E0..$EF: // pitch wheel change
+            begin
+              midiEvent.data1 := chunkIndex^; inc(chunkIndex);
+              midiEvent.data2 := chunkIndex^; inc(chunkIndex);
+            end;
+          $C0..$CF, // program change
+          $D0..$DF: // channel aftertouch
+            begin
+              midiEvent.data1 := chunkIndex^; inc(chunkIndex);
+            end;
+        else
+           // error
+        end;
+        currentTrack.putEvent(midiEvent);
+      end;
+    end;
+  end;
+end;
+
+
+function TMidifile.ReadVarLength: integer;
+var
+  i: integer;
+  b: byte;
+begin
+  b := 128;
+  i := 0;
+  while b > 127 do
+  begin
+    i := i shl 7;
+    b := chunkIndex^;
+    i := i + b and $7F;
+    inc(chunkIndex);
+  end;
+  result := i;
+end;
+
+function TMidifile.ReadString(l: integer): string;
+var
+  s: PChar;
+  i: integer;
+begin
+  GetMem(s, l + 1); ;
+  s[l] := chr(0);
+  for i := 0 to l - 1 do
+  begin
+    s[i] := Chr(chunkIndex^);
+    inc(chunkIndex);
+  end;
+  result := string(s);
+end;
+
+procedure TMidifile.ReadFile;
+var
+  i: integer;
+begin
+  for i := 0 to Tracks.Count - 1 do
+    TMidiTrack(Tracks.Items[i]).Free;
+  Tracks.Clear;
+  chunkType := illegal;
+
+  midiFile := TBinaryFileStream.Create(FFilename, fmOpenRead);
+  while (midiFile.Position < midiFile.Size) do
+    ReadChunk;
+  FreeAndNil(midiFile);
+  numberTracks := Tracks.Count;
+end;
+
+function KeyToStr(key: integer): string;
+var
+  n: integer;
+  str: string;
+begin
+  n := key mod 12;
+  case n of
+    0: str := 'C';
+    1: str := 'C#';
+    2: str := 'D';
+    3: str := 'D#';
+    4: str := 'E';
+    5: str := 'F';
+    6: str := 'F#';
+    7: str := 'G';
+    8: str := 'G#';
+    9: str := 'A';
+    10: str := 'A#';
+    11: str := 'B';
+  end;
+  Result := str + IntToStr(key div 12);
+end;
+
+function IntToLenStr(val: integer; len: integer): string;
+var
+  str: string;
+begin
+  str := IntToStr(val);
+  while Length(str) < len do
+    str := '0' + str;
+  Result := str;
+end;
+
+function MyTimeToStr(val: integer): string;
+ var
+  hour: integer;
+  min: integer;
+  sec: integer;
+  msec: integer;
+begin
+  msec := val mod 1000;
+  sec := val div 1000;
+  min := sec div 60;
+  sec := sec mod 60;
+  hour := min div 60;
+  min := min mod 60;
+  Result := IntToStr(hour) + ':' + IntToLenStr(min, 2) + ':' + IntToLenStr(sec, 2) + '.' + IntToLenStr(msec, 3);
+end;
+
+function TMidiFIle.GetFusPerTick : Double;
+begin
+  Result := FusPerTick;
+end;
+
+function  TMidiFIle.GetTrackLength:integer;
+var i,length : integer;
+    time : extended;
+begin
+  length := 0;
+  for i := 0 to Tracks.Count - 1 do
+    if TMidiTrack(Tracks.Items[i]).getTrackLength > length then
+      length := TMidiTrack(Tracks.Items[i]).getTrackLength;
+  time := length * FusPerTick;
+  time := time / 1000.0;
+  result := round(time);
+end;
+
+function  TMidiFIle.Ready: boolean;
+var i : integer;
+begin
+  result := true;
+  for i := 0 to Tracks.Count - 1 do
+    if not TMidiTrack(Tracks.Items[i]).isready then
+      result := false;
+end;
+
+procedure TMidiFile.OnTrackReady;
+begin
+  if ready then
+    if assigned(FOnUpdateEvent) then FOnUpdateEvent(self);
+end;
+
+procedure TMidiFile.WndProc(var Msg : TMessage);
+begin
+  with MSG do
+  begin
+    case Msg of
+      WM_MULTIMEDIA_TIMER:
+      begin
+        //try
+          MidiTimer(self);
+        //except
+        // Note: HandleException() is called by default if exception is not handled
+        //  Application.HandleException(Self);
+        //end;
+      end;
+    else
+      begin
+        Result := DefWindowProc(MIDIFileHandle, Msg, wParam, lParam);
+      end;
+    end;
+  end;
+end;
+
+procedure Register;
+begin
+  RegisterComponents('Synth', [TMidiFile]);
+end;
+
+end.
+
diff --git a/songmanagement/src/lib/midi/MidiScope.pas b/songmanagement/src/lib/midi/MidiScope.pas
new file mode 100644
index 00000000..afc20b0f
--- /dev/null
+++ b/songmanagement/src/lib/midi/MidiScope.pas
@@ -0,0 +1,198 @@
+{
+  Shows a large black area where midi note/controller events are shown
+  just to monitor midi activity (for the MidiPlayer)
+
+  version 1.0 first release
+
+  for comments/bugs
+  F.Bouwmans
+  fbouwmans@spiditel.nl
+
+  if you think this component is nice and you use it, sent me a short email.
+  I've seen that other of my components have been downloaded a lot, but I've
+  got no clue wether they are actually used.
+  Don't worry because you are free to use these components
+}
+
+unit MidiScope;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
+
+type
+  TMidiScope = class(TGraphicControl)
+  private
+    { Private declarations }
+  protected
+    { Protected declarations }
+    notes       : array[0..15,0..127] of integer;
+    controllers : array[0..15,0..17]  of integer;
+    aftertouch  : array[0..15,0..127] of integer;
+
+    selectedChannel : integer;
+
+    procedure PaintSlide(ch,pos,val: integer);
+
+    procedure NoteOn(channel, note, speed : integer);
+    procedure Controller(channel,number,value : integer);
+    procedure AfterTch(channel, note, value : integer);
+
+  public
+    { Public declarations }
+    constructor Create(AOwner: TComponent); override;
+    procedure MidiEvent(event,data1,data2 : integer);
+    procedure Paint; override;
+  published
+    { Published declarations }
+  end;
+
+
+procedure Register;
+
+const
+  BarHeight = 16;
+  BarHeightInc  = BarHeight+2;
+  BarWidth      = 3;
+  BarWidthInc   = BarWidth+1;
+  HeightDiv     = 128 div BarHeight;
+
+implementation
+
+uses Midicons;
+
+procedure Register;
+begin
+  RegisterComponents('Synth', [TMidiScope]);
+end;
+
+constructor TMidiScope.Create(AOwner: TComponent);
+var
+ i,j : integer;
+begin
+  inherited Create(AOwner);
+  Height := BarHeightinc * 16 + 4;
+  Width :=  147*BarWidthInc + 4 + 20;  // for channel number
+  for i := 0 to 15 do
+  begin
+    for j := 0 to 127 do
+    begin
+      notes[i,j] := 0;
+      aftertouch[i,j] := 0;
+    end;
+  end;
+  for i := 0 to 17 do
+  begin
+    for j := 0 to 15 do
+      controllers[i,j] := 0;
+  end;
+end;
+
+procedure TMidiScope.PaintSlide(ch,pos,val: integer);
+var x,y:integer;
+begin
+  Canvas.Brush.Color := clBlack;
+  Canvas.Pen.color := clBlack;
+  x := pos * BarWidthInc + 2;
+  y := 2 + ch * BarHeightInc;
+  Canvas.Rectangle(x, y, x+BarWidthInc, y+BarHeightInc);
+  Canvas.Brush.Color := clGreen;
+  Canvas.Pen.Color := clGreen;
+  Canvas.Rectangle(x, y + (BarHeight - (val div HeightDiv )), x + BarWidth, y + BarHeight)
+end;
+
+procedure TMidiScope.Paint;
+var i,j : integer;
+x : integer;
+begin
+  Canvas.Brush.color := clBlack;
+  Canvas.Rectangle(0,0,Width,Height);
+  Canvas.Pen.Color := clGreen;
+  x := 128*BarWidthInc+2;
+  Canvas.MoveTo(x,0);
+  Canvas.LineTo(x,Height);
+  x :=  148*BarWIdthInc+2;
+  canvas.Font.Color := clGreen;
+  for i := 0 to 15 do
+    Canvas.TextOut(x,((i+1)*BarHeightInc) - Canvas.font.size-3,IntToStr(i+1));
+  canvas.Pen.color := clBlack;
+  begin
+    for j := 0 to 127 do
+    begin
+      PaintSlide(i,j,notes[i,j]);
+    end;
+    for j := 0 to 17 do
+    begin
+      PaintSlide(i,j+129,controllers[i,j]);
+    end;
+  end;
+end;
+procedure TMidiScope.NoteOn(channel, note, speed : integer);
+begin
+  notes[channel,note] := speed;
+  PaintSlide(channel,note,notes[channel,note]);
+end;
+procedure TMidiScope.AfterTch(channel, note, value : integer);
+begin
+  aftertouch[channel,note] := value;
+end;
+
+procedure TMidiScope.Controller(channel,number,value : integer);
+var i : integer;
+begin
+  if number < 18 then
+  begin
+  controllers[channel,number] := value;
+  PaintSlide(channel,number+129,value);
+  end
+  else if number >= $7B then
+  begin
+    // all notes of for channel
+    for i := 0 to 127 do
+    begin
+      if notes[channel,i] > 0 then
+      begin
+        notes[channel,i] := 0;
+        PaintSlide(channel,i,0);
+      end;
+    end;
+  end;
+end;
+
+procedure TMidiScope.MidiEvent(event,data1,data2 : integer);
+begin
+  case (event AND $F0) of
+  MIDI_NOTEON :
+  begin
+    NoteOn((event AND $F),data1,data2);
+  end;
+  MIDI_NOTEOFF:
+  begin
+    NoteOn((event AND $F),data1,0);
+  end;
+  MIDI_CONTROLCHANGE :
+  begin
+    Controller((event AND $F),data1,data2);
+  end;
+  MIDI_CHANAFTERTOUCH:
+  begin
+    Controller((Event AND $F),16,Data1);
+  end;
+  MIDI_PITCHBEND:
+  begin
+  begin
+    Controller((Event AND $F),17,data2);
+  end;
+  end;
+  MIDI_KEYAFTERTOUCH:
+  begin
+  end;
+  end;
+end;
+end.
diff --git a/songmanagement/src/lib/midi/Midicons.pas b/songmanagement/src/lib/midi/Midicons.pas
new file mode 100644
index 00000000..72259beb
--- /dev/null
+++ b/songmanagement/src/lib/midi/Midicons.pas
@@ -0,0 +1,47 @@
+{ $Header: /MidiComp/MIDICONS.PAS 2     10/06/97 7:33 Davec $ }
+
+{ Written by David Churcher <dchurcher@cix.compulink.co.uk>,
+  released to the public domain. }
+
+
+{ MIDI Constants }
+unit Midicons;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+uses Messages;
+
+const
+	MIDI_ALLNOTESOFF     = $7B;
+	MIDI_NOTEON          = $90;
+	MIDI_NOTEOFF         = $80;
+	MIDI_KEYAFTERTOUCH   = $a0;
+	MIDI_CONTROLCHANGE   = $b0;
+	MIDI_PROGRAMCHANGE   = $c0;
+	MIDI_CHANAFTERTOUCH  = $d0;
+	MIDI_PITCHBEND       = $e0;
+	MIDI_SYSTEMMESSAGE   = $f0;
+	MIDI_BEGINSYSEX      = $f0;
+	MIDI_MTCQUARTERFRAME = $f1;
+	MIDI_SONGPOSPTR      = $f2;
+	MIDI_SONGSELECT      = $f3;
+	MIDI_ENDSYSEX        = $F7;
+	MIDI_TIMINGCLOCK     = $F8;
+	MIDI_START           = $FA;
+	MIDI_CONTINUE        = $FB;
+	MIDI_STOP            = $FC;
+	MIDI_ACTIVESENSING   = $FE;
+	MIDI_SYSTEMRESET     = $FF;
+
+	MIM_OVERFLOW         = WM_USER;	{ Input buffer overflow }
+	MOM_PLAYBACK_DONE    = WM_USER+1; { Timed playback complete }
+
+
+implementation
+
+end.
diff --git a/songmanagement/src/lib/midi/Midiin.pas b/songmanagement/src/lib/midi/Midiin.pas
new file mode 100644
index 00000000..a055669a
--- /dev/null
+++ b/songmanagement/src/lib/midi/Midiin.pas
@@ -0,0 +1,720 @@
+{ $Header: /MidiComp/Midiin.pas 2     10/06/97 7:33 Davec $ }
+
+{ Written by David Churcher <dchurcher@cix.compulink.co.uk>,
+  released to the public domain. }
+
+unit MidiIn;
+
+{
+  Properties:
+ DeviceID: 	Windows numeric device ID for the MIDI input device.
+ Between 0 and NumDevs-1.
+ Read-only while device is open, exception when changed while open
+
+ MIDIHandle:	The input handle to the MIDI device.
+ 0 when device is not open
+ Read-only, runtime-only
+
+ MessageCount:	Number of input messages waiting in input buffer
+
+ Capacity:	Number of messages input buffer can hold
+ Defaults to 1024
+ Limited to (64K/event size)
+ Read-only when device is open (exception when changed while open)
+
+ SysexBufferSize:	Size in bytes of each sysex buffer
+ Defaults to 10K
+ Minimum 0K (no buffers), Maximum 64K-1
+
+ SysexBufferCount:	Number of sysex buffers
+ Defaults to 16
+ Minimum 0 (no buffers), Maximum (avail mem/SysexBufferSize)
+ Check where these buffers are allocated?
+
+ SysexOnly: True to ignore all non-sysex input events. May be changed while
+ device is open. Handy for patch editors where you have lots of short MIDI
+ events on the wire which you are always going to ignore anyway.
+
+ DriverVersion: Version number of MIDI device driver. High-order byte is
+ major version, low-order byte is minor version.
+
+ ProductName: Name of product (e.g. 'MPU 401 In')
+
+ MID and PID: Manufacturer ID and Product ID, see
+ "Manufacturer and Product IDs" in MMSYSTEM.HLP for list of possible values.
+
+  Methods:
+ GetMidiEvent: Read Midi event at the head of the FIFO input buffer.
+ Returns a TMyMidiEvent object containing MIDI message data, timestamp,
+ and sysex data if applicable.
+ This method automatically removes the event from the input buffer.
+ It makes a copy of the received sysex buffer and puts the buffer back
+ on the input device.
+ The TMyMidiEvent object must be freed by calling MyMidiEvent.Free.
+
+ Open: Opens device. Note no input will appear until you call the Start
+ method.
+
+ Close: Closes device. Any pending system exclusive output will be cancelled.
+
+ Start: Starts receiving MIDI input.
+
+ Stop: Stops receiving MIDI input.
+
+  Events:
+ OnMidiInput: Called when MIDI input data arrives. Use the GetMidiEvent to
+ get the MIDI input data.
+
+ OnOverflow: Called if the MIDI input buffer overflows. The caller must
+ clear the buffer before any more MIDI input can be received.
+
+ Notes:
+ Buffering: Uses a circular buffer, separate pointers for next location
+ to fill and next location to empty because a MIDI input interrupt may
+ be adding data to the buffer while the buffer is being read. Buffer
+ pointers wrap around from end to start of buffer automatically. If
+ buffer overflows then the OnBufferOverflow event is triggered and no
+ further input will be received until the buffer is emptied by calls
+ to GetMidiEvent.
+
+ Sysex buffers: There are (SysexBufferCount) buffers on the input device.
+ When sysex events arrive these buffers are removed from the input device and
+ added to the circular buffer by the interrupt handler in the DLL.  When the sysex events
+ are removed from the circular buffer by the GetMidiEvent method the buffers are
+ put back on the input. If all the buffers are used up there will be no
+ more sysex input until at least one sysex event is removed from the input buffer.
+ In other	words if you're expecting lots of sysex input you need to set the
+ SysexBufferCount property high enough so that you won't run out of
+ input buffers before you get a chance to read them with GetMidiEvent.
+
+ If the synth sends a block of sysex that's longer than SysexBufferSize it
+ will be received as separate events.
+ TODO: Component derived from this one that handles >64K sysex blocks cleanly
+ and can stream them to disk.
+
+ Midi Time Code (MTC) and Active Sensing: The DLL is currently hardcoded
+ to filter these short events out, so that we don't spend all our time
+ processing them.
+ TODO: implement a filter property to select the events that will be filtered
+ out.
+}
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+uses
+  Classes,
+  SysUtils,
+  Messages,
+  Windows,
+  MMSystem,
+  {$IFDEF FPC}
+  WinAllocation,
+  {$ENDIF}
+  MidiDefs,
+  MidiType,
+  MidiCons,
+  Circbuf,
+  Delphmcb;
+
+type
+  MidiInputState = (misOpen, misClosed, misCreating, misDestroying);
+  EMidiInputError = class(Exception);
+
+ {-------------------------------------------------------------------}
+  TMidiInput = class(TComponent)
+  private
+    Handle: THandle; { Window handle used for callback notification }
+    FDeviceID: Word; { MIDI device ID }
+    FMIDIHandle: HMIDIIn; { Handle to input device }
+    FState: MidiInputState; { Current device state }
+
+    FError: Word;
+    FSysexOnly: Boolean;
+
+ { Stuff from MIDIINCAPS }
+    FDriverVersion: MMVERSION;
+    FProductName: string;
+    FMID: Word; { Manufacturer ID }
+    FPID: Word; { Product ID }
+
+ { Queue }
+    FCapacity: Word; { Buffer capacity }
+    PBuffer: PCircularBuffer; { Low-level MIDI input buffer created by Open method }
+    FNumdevs: Word; { Number of input devices on system }
+
+ { Events }
+    FOnMIDIInput: TNotifyEvent; { MIDI Input arrived }
+    FOnOverflow: TNotifyEvent; { Input buffer overflow }
+ { TODO: Some sort of error handling event for MIM_ERROR }
+
+ { Sysex }
+    FSysexBufferSize: Word;
+    FSysexBufferCount: Word;
+    MidiHdrs: Tlist;
+
+    PCtlInfo: PMidiCtlInfo; { Pointer to control info for DLL }
+
+  protected
+    procedure Prepareheaders;
+    procedure UnprepareHeaders;
+    procedure AddBuffers;
+    procedure SetDeviceID(DeviceID: Word);
+    procedure SetProductName(NewProductName: string);
+    function GetEventCount: Word;
+    procedure SetSysexBufferSize(BufferSize: Word);
+    procedure SetSysexBufferCount(BufferCount: Word);
+    procedure SetSysexOnly(bSysexOnly: Boolean);
+    function MidiInErrorString(WError: Word): string;
+
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+
+    property MIDIHandle: HMIDIIn read FMIDIHandle;
+
+    property DriverVersion: MMVERSION read FDriverVersion;
+    property MID: Word read FMID; { Manufacturer ID }
+    property PID: Word read FPID; { Product ID }
+
+    property Numdevs: Word read FNumdevs;
+
+    property MessageCount: Word read GetEventCount;
+ { TODO: property to select which incoming messages get filtered out }
+
+    procedure Open;
+    procedure Close;
+    procedure Start;
+    procedure Stop;
+ { Get first message in input queue }
+    function GetMidiEvent: TMyMidiEvent;
+    procedure MidiInput(var Message: TMessage);
+
+   { Some functions to decode and classify incoming messages would be good }
+
+  published
+
+ { TODO: Property editor with dropdown list of product names }
+    property ProductName: string read FProductName write SetProductName;
+
+    property DeviceID: Word read FDeviceID write SetDeviceID default 0;
+    property Capacity: Word read FCapacity write FCapacity default 1024;
+    property Error: Word read FError;
+    property SysexBufferSize: Word
+      read FSysexBufferSize
+      write SetSysexBufferSize
+      default 10000;
+    property SysexBufferCount: Word
+      read FSysexBufferCount
+      write SetSysexBufferCount
+      default 16;
+    property SysexOnly: Boolean
+      read FSysexOnly
+      write SetSysexOnly
+      default False;
+
+ { Events }
+    property OnMidiInput: TNotifyEvent read FOnMidiInput write FOnMidiInput;
+    property OnOverflow: TNotifyEvent read FOnOverflow write FOnOverflow;
+
+  end;
+
+procedure Register;
+
+{====================================================================}
+implementation
+
+uses Controls,
+     Graphics;
+
+(* Not used in Delphi 3
+{ This is the callback procedure in the external DLL.
+  It's used when midiInOpen is called by the Open method.
+  There are special requirements and restrictions for this callback
+  procedure (see midiInOpen in MMSYSTEM.HLP) so it's impractical to
+  make it an object method }
+{$IFDEF MSWINDOWS}
+function midiHandler(
+    hMidiIn: HMidiIn;
+    wMsg: UINT;
+    dwInstance: DWORD;
+    dwParam1: DWORD;
+    dwParam2: DWORD): Boolean; stdcall; external 'DELMID32.DLL';
+{$ENDIF}
+*)
+{-------------------------------------------------------------------}
+
+constructor TMidiInput.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FState := misCreating;
+
+  FSysexOnly := False;
+  FNumDevs := midiInGetNumDevs;
+  MidiHdrs := nil;
+
+ { Set defaults }
+  if  (FNumDevs > 0) then
+    SetDeviceID(0);
+  FCapacity := 1024;
+  FSysexBufferSize := 4096;
+  FSysexBufferCount := 16;
+
+ { Create the window for callback notification }
+  if not (csDesigning in ComponentState) then
+  begin
+    Handle := AllocateHwnd(MidiInput);
+  end;
+
+  FState := misClosed;
+
+end;
+
+{-------------------------------------------------------------------}
+{ Close the device if it's open }
+
+destructor TMidiInput.Destroy;
+begin
+  if (FMidiHandle <> 0) then
+  begin
+    Close;
+    FMidiHandle := 0;
+  end;
+
+  if (PCtlInfo <> nil) then
+    GlobalSharedLockedFree(PCtlinfo^.hMem, PCtlInfo);
+
+  DeallocateHwnd(Handle);
+  inherited Destroy;
+end;
+
+{-------------------------------------------------------------------}
+{ Convert the numeric return code from an MMSYSTEM function to a string
+  using midiInGetErrorText. TODO: These errors aren't very helpful
+  (e.g. "an invalid parameter was passed to a system function") so
+  sort out some proper error strings. }
+
+function TMidiInput.MidiInErrorString(WError: Word): string;
+var
+  errorDesc: PChar;
+begin
+  errorDesc := nil;
+  try
+    errorDesc := StrAlloc(MAXERRORLENGTH);
+    if midiInGetErrorText(WError, errorDesc, MAXERRORLENGTH) = 0 then
+      result := StrPas(errorDesc)
+    else
+      result := 'Specified error number is out of range';
+  finally
+    if errorDesc <> nil then StrDispose(errorDesc);
+  end;
+end;
+
+{-------------------------------------------------------------------}
+{ Set the sysex buffer size, fail if device is already open }
+
+procedure TMidiInput.SetSysexBufferSize(BufferSize: Word);
+begin
+  if FState = misOpen then
+    raise EMidiInputError.Create('Change to SysexBufferSize while device was open')
+  else
+  { TODO: Validate the sysex buffer size. Is this necessary for WIN32? }
+    FSysexBufferSize := BufferSize;
+end;
+
+{-------------------------------------------------------------------}
+{ Set the sysex buffer count, fail if device is already open }
+
+procedure TMidiInput.SetSysexBuffercount(Buffercount: Word);
+begin
+  if FState = misOpen then
+    raise EMidiInputError.Create('Change to SysexBuffercount while device was open')
+  else
+  { TODO: Validate the sysex buffer count }
+    FSysexBuffercount := Buffercount;
+end;
+
+{-------------------------------------------------------------------}
+{ Set the Sysex Only flag to eliminate unwanted short MIDI input messages }
+
+procedure TMidiInput.SetSysexOnly(bSysexOnly: Boolean);
+begin
+  FSysexOnly := bSysexOnly;
+ { Update the interrupt handler's copy of this property }
+  if PCtlInfo <> nil then
+    PCtlInfo^.SysexOnly := bSysexOnly;
+end;
+
+{-------------------------------------------------------------------}
+{ Set the Device ID to select a new MIDI input device
+  Note: If no MIDI devices are installed, throws an 'Invalid Device ID' exception }
+
+procedure TMidiInput.SetDeviceID(DeviceID: Word);
+var
+  MidiInCaps: TMidiInCaps;
+begin
+  if FState = misOpen then
+    raise EMidiInputError.Create('Change to DeviceID while device was open')
+  else
+    if (DeviceID >= midiInGetNumDevs) then
+      raise EMidiInputError.Create('Invalid device ID')
+    else
+    begin
+      FDeviceID := DeviceID;
+
+   { Set the name and other MIDIINCAPS properties to match the ID }
+      FError :=
+        midiInGetDevCaps(DeviceID, @MidiInCaps, sizeof(TMidiInCaps));
+      if Ferror <> MMSYSERR_NOERROR then
+        raise EMidiInputError.Create(MidiInErrorString(FError));
+
+      FProductName := StrPas(MidiInCaps.szPname);
+      FDriverVersion := MidiInCaps.vDriverVersion;
+      FMID := MidiInCaps.wMID;
+      FPID := MidiInCaps.wPID;
+
+    end;
+end;
+
+{-------------------------------------------------------------------}
+{ Set the product name and put the matching input device number in FDeviceID.
+  This is handy if you want to save a configured input/output device
+  by device name instead of device number, because device numbers may
+  change if users add or remove MIDI devices.
+  Exception if input device with matching name not found,
+  or if input device is open }
+
+procedure TMidiInput.SetProductName(NewProductName: string);
+var
+  MidiInCaps: TMidiInCaps;
+  testDeviceID: Word;
+  testProductName: string;
+begin
+  if FState = misOpen then
+    raise EMidiInputError.Create('Change to ProductName while device was open')
+  else
+  { Don't set the name if the component is reading properties because
+ the saved Productname will be from the machine the application was compiled
+ on, which may not be the same for the corresponding DeviceID on the user's
+ machine. The FProductname property will still be set by SetDeviceID }
+    if not (csLoading in ComponentState) then
+    begin
+      begin
+        for testDeviceID := 0 to (midiInGetNumDevs - 1) do
+        begin
+          FError :=
+            midiInGetDevCaps(testDeviceID, @MidiInCaps, sizeof(TMidiInCaps));
+          if Ferror <> MMSYSERR_NOERROR then
+            raise EMidiInputError.Create(MidiInErrorString(FError));
+          testProductName := StrPas(MidiInCaps.szPname);
+          if testProductName = NewProductName then
+          begin
+            FProductName := NewProductName;
+            Break;
+          end;
+        end;
+        if FProductName <> NewProductName then
+          raise EMidiInputError.Create('MIDI Input Device ' +
+            NewProductName + ' not installed ')
+        else
+          SetDeviceID(testDeviceID);
+      end;
+    end;
+end;
+
+
+{-------------------------------------------------------------------}
+{ Get the sysex buffers ready }
+
+procedure TMidiInput.PrepareHeaders;
+var
+  ctr: Word;
+  MyMidiHdr: TMyMidiHdr;
+begin
+  if (FSysexBufferCount > 0) and (FSysexBufferSize > 0)
+    and (FMidiHandle <> 0) then
+  begin
+    Midihdrs := TList.Create;
+    for ctr := 1 to FSysexBufferCount do
+    begin
+   { Initialize the header and allocate buffer memory }
+      MyMidiHdr := TMyMidiHdr.Create(FSysexBufferSize);
+
+   { Store the address of the MyMidiHdr object in the contained MIDIHDR
+              structure so we can get back to the object when a pointer to the
+              MIDIHDR is received.
+              E.g. see TMidiOutput.Output method }
+      MyMidiHdr.hdrPointer^.dwUser := DWORD(MyMidiHdr);
+
+   { Get MMSYSTEM's blessing for this header }
+      FError := midiInPrepareHeader(FMidiHandle, MyMidiHdr.hdrPointer,
+        sizeof(TMIDIHDR));
+      if Ferror <> MMSYSERR_NOERROR then
+        raise EMidiInputError.Create(MidiInErrorString(FError));
+
+   { Save it in our list }
+      MidiHdrs.Add(MyMidiHdr);
+    end;
+  end;
+
+end;
+
+{-------------------------------------------------------------------}
+{ Clean up from PrepareHeaders }
+
+procedure TMidiInput.UnprepareHeaders;
+var
+  ctr: Word;
+begin
+  if (MidiHdrs <> nil) then { will be Nil if 0 sysex buffers }
+  begin
+    for ctr := 0 to MidiHdrs.Count - 1 do
+    begin
+      FError := midiInUnprepareHeader(FMidiHandle,
+        TMyMidiHdr(MidiHdrs.Items[ctr]).hdrPointer,
+        sizeof(TMIDIHDR));
+      if Ferror <> MMSYSERR_NOERROR then
+        raise EMidiInputError.Create(MidiInErrorString(FError));
+      TMyMidiHdr(MidiHdrs.Items[ctr]).Free;
+    end;
+    MidiHdrs.Free;
+    MidiHdrs := nil;
+  end;
+end;
+
+{-------------------------------------------------------------------}
+{ Add sysex buffers, if required, to input device }
+
+procedure TMidiInput.AddBuffers;
+var
+  ctr: Word;
+begin
+  if MidiHdrs <> nil then { will be Nil if 0 sysex buffers }
+  begin
+    if MidiHdrs.Count > 0 then
+    begin
+      for ctr := 0 to MidiHdrs.Count - 1 do
+      begin
+        FError := midiInAddBuffer(FMidiHandle,
+          TMyMidiHdr(MidiHdrs.Items[ctr]).hdrPointer,
+          sizeof(TMIDIHDR));
+        if FError <> MMSYSERR_NOERROR then
+          raise EMidiInputError.Create(MidiInErrorString(FError));
+      end;
+    end;
+  end;
+end;
+
+{-------------------------------------------------------------------}
+
+procedure TMidiInput.Open;
+var
+  hMem: THandle;
+begin
+  try
+  { Create the buffer for the MIDI input messages }
+    if (PBuffer = nil) then
+      PBuffer := CircBufAlloc(FCapacity);
+
+  { Create the control info for the DLL }
+    if (PCtlInfo = nil) then
+    begin
+      PCtlInfo := GlobalSharedLockedAlloc(Sizeof(TMidiCtlInfo), hMem);
+      PctlInfo^.hMem := hMem;
+    end;
+    PctlInfo^.pBuffer := PBuffer;
+    Pctlinfo^.hWindow := Handle; { Control's window handle }
+    PCtlInfo^.SysexOnly := FSysexOnly;
+    FError := midiInOpen(@FMidiHandle, FDeviceId,
+      DWORD(@midiHandler),
+      DWORD(PCtlInfo),
+      CALLBACK_FUNCTION);
+
+    if (FError <> MMSYSERR_NOERROR) then
+   { TODO: use CreateFmtHelp to add MIDI device name/ID to message }
+      raise EMidiInputError.Create(MidiInErrorString(FError));
+
+  { Get sysex buffers ready }
+    PrepareHeaders;
+
+  { Add them to the input }
+    AddBuffers;
+
+    FState := misOpen;
+
+  except
+    if PBuffer <> nil then
+    begin
+      CircBufFree(PBuffer);
+      PBuffer := nil;
+    end;
+
+    if PCtlInfo <> nil then
+    begin
+      GlobalSharedLockedFree(PCtlInfo^.hMem, PCtlInfo);
+      PCtlInfo := nil;
+    end;
+
+  end;
+
+end;
+
+{-------------------------------------------------------------------}
+
+function TMidiInput.GetMidiEvent: TMyMidiEvent;
+var
+  thisItem: TMidiBufferItem;
+begin
+  if (FState = misOpen) and
+    CircBufReadEvent(PBuffer, @thisItem) then
+  begin
+    Result := TMyMidiEvent.Create;
+    with thisItem do
+    begin
+      Result.Time := Timestamp;
+      if (Sysex = nil) then
+      begin
+    { Short message }
+        Result.MidiMessage := LoByte(LoWord(Data));
+        Result.Data1 := HiByte(LoWord(Data));
+        Result.Data2 := LoByte(HiWord(Data));
+        Result.Sysex := nil;
+        Result.SysexLength := 0;
+      end
+      else
+             { Long Sysex message }
+      begin
+        Result.MidiMessage := MIDI_BEGINSYSEX;
+        Result.Data1 := 0;
+        Result.Data2 := 0;
+        Result.SysexLength := Sysex^.dwBytesRecorded;
+        if Sysex^.dwBytesRecorded <> 0 then
+        begin
+     { Put a copy of the sysex buffer in the object }
+          GetMem(Result.Sysex, Sysex^.dwBytesRecorded);
+          StrMove(Result.Sysex, Sysex^.lpData, Sysex^.dwBytesRecorded);
+        end;
+
+    { Put the header back on the input buffer }
+        FError := midiInPrepareHeader(FMidiHandle, Sysex,
+          sizeof(TMIDIHDR));
+        if Ferror = 0 then
+          FError := midiInAddBuffer(FMidiHandle,
+            Sysex, sizeof(TMIDIHDR));
+        if Ferror <> MMSYSERR_NOERROR then
+          raise EMidiInputError.Create(MidiInErrorString(FError));
+      end;
+    end;
+    CircbufRemoveEvent(PBuffer);
+  end
+  else
+  { Device isn't open, return a nil event }
+    Result := nil;
+end;
+
+{-------------------------------------------------------------------}
+
+function TMidiInput.GetEventCount: Word;
+begin
+  if FState = misOpen then
+    Result := PBuffer^.EventCount
+  else
+    Result := 0;
+end;
+
+{-------------------------------------------------------------------}
+
+procedure TMidiInput.Close;
+begin
+  if FState = misOpen then
+  begin
+    FState := misClosed;
+
+  { MidiInReset cancels any pending output.
+  Note that midiInReset causes an MIM_LONGDATA callback for each sysex
+  buffer on the input, so the callback function and Midi input buffer
+  should still be viable at this stage.
+  All the resulting MIM_LONGDATA callbacks will be completed by the time
+  MidiInReset returns, though. }
+    FError := MidiInReset(FMidiHandle);
+    if Ferror <> MMSYSERR_NOERROR then
+      raise EMidiInputError.Create(MidiInErrorString(FError));
+
+  { Remove sysex buffers from input device and free them }
+    UnPrepareHeaders;
+
+  { Close the device (finally!) }
+    FError := MidiInClose(FMidiHandle);
+    if Ferror <> MMSYSERR_NOERROR then
+      raise EMidiInputError.Create(MidiInErrorString(FError));
+
+    FMidiHandle := 0;
+
+    if (PBuffer <> nil) then
+    begin
+      CircBufFree(PBuffer);
+      PBuffer := nil;
+    end;
+  end;
+end;
+
+{-------------------------------------------------------------------}
+
+procedure TMidiInput.Start;
+begin
+  if FState = misOpen then
+  begin
+    FError := MidiInStart(FMidiHandle);
+    if Ferror <> MMSYSERR_NOERROR then
+      raise EMidiInputError.Create(MidiInErrorString(FError));
+  end;
+end;
+
+{-------------------------------------------------------------------}
+
+procedure TMidiInput.Stop;
+begin
+  if FState = misOpen then
+  begin
+    FError := MidiInStop(FMidiHandle);
+    if Ferror <> MMSYSERR_NOERROR then
+      raise EMidiInputError.Create(MidiInErrorString(FError));
+  end;
+end;
+
+{-------------------------------------------------------------------}
+
+procedure TMidiInput.MidiInput(var Message: TMessage);
+{ Triggered by incoming message from DLL.
+  Note DLL has already put the message in the queue }
+begin
+  case Message.Msg of
+    mim_data:
+  { Trigger the user's MIDI input event, if they've specified one and
+  we're not in the process of closing the device. The check for
+  GetEventCount > 0 prevents unnecessary event calls where the user has
+  already cleared all the events from the input buffer using a GetMidiEvent
+  loop in the OnMidiInput event handler }
+      if Assigned(FOnMIDIInput) and (FState = misOpen)
+        and (GetEventCount > 0) then
+        FOnMIDIInput(Self);
+
+    mim_Overflow: { input circular buffer overflow }
+      if Assigned(FOnOverflow) and (FState = misOpen) then
+        FOnOverflow(Self);
+  end;
+end;
+
+{-------------------------------------------------------------------}
+
+procedure Register;
+begin
+  RegisterComponents('Synth', [TMIDIInput]);
+end;
+
+end.
+
diff --git a/songmanagement/src/lib/midi/Midiout.pas b/songmanagement/src/lib/midi/Midiout.pas
new file mode 100644
index 00000000..7ce385eb
--- /dev/null
+++ b/songmanagement/src/lib/midi/Midiout.pas
@@ -0,0 +1,612 @@
+{ $Header: /MidiComp/MidiOut.pas 2     10/06/97 7:33 Davec $ }
+
+{ Written by David Churcher <dchurcher@cix.compulink.co.uk>,
+  released to the public domain. }
+
+{ Thanks very much to Fred Kohler for the Technology code. }
+
+unit MidiOut;
+
+{
+  MIDI Output component.
+
+  Properties:
+   DeviceID: 	Windows numeric device ID for the MIDI output device.
+ Between 0 and (midioutGetNumDevs-1), or MIDI_MAPPER (-1).
+    Special value MIDI_MAPPER specifies output to the Windows MIDI mapper
+ Read-only while device is open, exception if changed while open
+
+ MIDIHandle:	The output handle to the MIDI device.
+ 0 when device is not open
+ Read-only, runtime-only
+
+ ProductName: Name of the output device product that corresponds to the
+ DeviceID property (e.g. 'MPU 401 out').
+ You can write to this while the device is closed to select a particular
+ output device by name (the DeviceID property will change to match).
+ Exception if this property is changed while the device is open.
+
+ Numdevs: Number of MIDI output devices installed on the system. This
+ is the value returned by midiOutGetNumDevs. It's included for
+ completeness.
+
+    Technology: Type of technology used by the MIDI device. You can set this
+    property to one of the values listed for OutportTech (below) and the component
+    will find an appropriate MIDI device. For example:
+     MidiOutput.Technology := opt_FMSynth;
+    will set MidiInput.DeviceID to the MIDI device ID of the FM synth, if one
+    is installed. If no such device is available an exception is raised,
+    see MidiOutput.SetTechnology.
+
+ See the MIDIOUTCAPS entry in MMSYSTEM.HLP for descriptions of the
+ following properties:
+  DriverVersion
+  Voices
+  Notes
+  ChannelMask
+  Support
+
+ Error: The error code for the last MMSYSTEM error. See the MMSYSERR_
+ entries in MMSYSTEM.INT for possible values.
+
+  Methods:
+ Open: Open MIDI device specified by DeviceID property for output
+
+ Close: Close device
+
+ PutMidiEvent(Event:TMyMidiEvent): Output a note or sysex message to the
+ device. This method takes a TMyMidiEvent object and transmits it.
+ Notes:
+   1. If the object contains a sysex event the OnMidiOutput event will
+    be triggered when the sysex transmission is complete.
+   2. You can queue up multiple blocks of system exclusive data for
+    transmission by chucking them at this method; they will be
+   transmitted as quickly as the device can manage.
+   3. This method will not free the TMyMidiEvent object, the caller
+    must do that. Any sysex data in the TMyMidiEvent is copied before
+   transmission so you can free the TMyMidiEvent immediately after
+   calling PutMidiEvent, even if output has not yet finished.
+
+ PutShort(MidiMessage: Byte; Data1: Byte; Data2: Byte): Output a short
+ MIDI message. Handy when you can't be bothered to build a TMyMidiEvent.
+ If the message you're sending doesn't use Data1 or Data2, set them to 0.
+
+ PutLong(TheSysex: Pointer; msgLength: Word): Output sysex data.
+  SysexPointer: Pointer to sysex data to send
+  msgLength: Length of sysex data.
+ This is handy when you don't have a TMyMidiEvent.
+
+ SetVolume(Left: Word, Right: Word): Set the volume of the
+ left and right channels on the output device (only on internal devices?).
+ 0xFFFF is maximum volume. If the device doesn't support separate
+ left/right volume control, the value of the Left parameter will be used.
+ Check the Support property to see whether the device supports volume
+ control. See also other notes on volume control under midiOutSetVolume()
+ in MMSYSTEM.HLP.
+
+  Events:
+ OnMidiOutput: Procedure called when output of a system exclusive block
+ is completed.
+
+  Notes:
+   I haven't implemented any methods for midiOutCachePatches and
+  midiOutCacheDrumpatches, mainly 'cause I don't have any way of testing
+  them. Does anyone really use these?
+}
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+uses
+  SysUtils,
+  Windows,
+  Messages,
+  Classes,
+  MMSystem,
+  {$IFDEF FPC}
+  WinAllocation,
+  {$ENDIF}
+  Circbuf,
+  MidiType,
+  MidiDefs,
+  Delphmcb;
+
+{$IFDEF FPC}
+type TmidioutCaps = MIDIOUTCAPS;
+{$ENDIF}
+
+type
+  midioutputState = (mosOpen, mosClosed);
+  EmidioutputError = class(Exception);
+
+ { These are the equivalent of constants prefixed with mod_
+   as defined in MMSystem. See SetTechnology }
+  OutPortTech = (
+    opt_None, { none }
+    opt_MidiPort, { output port }
+    opt_Synth, { generic internal synth }
+    opt_SQSynth, { square wave internal synth }
+    opt_FMSynth, { FM internal synth }
+    opt_Mapper); { MIDI mapper }
+  TechNameMap = array[OutPortTech] of string[18];
+
+
+const
+  TechName: TechNameMap = (
+    'None', 'MIDI Port', 'Generic Synth', 'Square Wave Synth',
+    'FM Synth', 'MIDI Mapper');
+
+{-------------------------------------------------------------------}
+type
+  TMidiOutput = class(TComponent)
+  protected
+    Handle: THandle; { Window handle used for callback notification }
+    FDeviceID: Cardinal; { MIDI device ID }
+    FMIDIHandle: Hmidiout; { Handle to output device }
+    FState: midioutputState; { Current device state }
+    PCtlInfo: PMidiCtlInfo; { Pointer to control info for DLL }
+
+    PBuffer: PCircularBuffer; { Output queue for PutTimedEvent, set by Open }
+
+    FError: Word; { Last MMSYSTEM error }
+
+ { Stuff from midioutCAPS }
+    FDriverVersion: MMVERSION; { Driver version from midioutGetDevCaps }
+    FProductName: string; { product name }
+    FTechnology: OutPortTech; { Type of MIDI output device }
+    FVoices: Word; { Number of voices (internal synth) }
+    FNotes: Word; { Number of notes (internal synth) }
+    FChannelMask: Word; { Bit set for each MIDI channels that the
+          device responds to (internal synth) }
+    FSupport: DWORD; { Technology supported (volume control,
+          patch caching etc. }
+    FNumdevs: Word; { Number of MIDI output devices on system }
+
+
+    FOnMIDIOutput: TNotifyEvent; { Sysex output finished }
+
+    procedure MidiOutput(var Message: TMessage);
+    procedure SetDeviceID(DeviceID: Cardinal);
+    procedure SetProductName(NewProductName: string);
+    procedure SetTechnology(NewTechnology: OutPortTech);
+    function midioutErrorString(WError: Word): string;
+
+  public
+ { Properties }
+    property MIDIHandle: Hmidiout read FMIDIHandle;
+    property DriverVersion: MMVERSION { Driver version from midioutGetDevCaps }
+    read FDriverVersion;
+    property Technology: OutPortTech { Type of MIDI output device }
+    read FTechnology
+      write SetTechnology
+      default opt_Synth;
+    property Voices: Word { Number of voices (internal synth) }
+    read FVoices;
+    property Notes: Word { Number of notes (internal synth) }
+    read FNotes;
+    property ChannelMask: Word { Bit set for each MIDI channels that the }
+    read FChannelMask; { device responds to (internal synth) }
+    property Support: DWORD { Technology supported (volume control, }
+    read FSupport; { patch caching etc. }
+    property Error: Word read FError;
+    property Numdevs: Word read FNumdevs;
+
+ { Methods }
+    function Open: Boolean; virtual;
+    function Close: Boolean; virtual;
+    procedure PutMidiEvent(theEvent: TMyMidiEvent); virtual;
+    procedure PutShort(MidiMessage: Byte; Data1: Byte; Data2: Byte); virtual;
+    procedure PutLong(TheSysex: Pointer; msgLength: Word); virtual;
+    procedure SetVolume(Left: Word; Right: Word);
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+
+   { Some functions to decode and classify incoming messages would be nice }
+
+  published
+ { TODO: Property editor with dropdown list of product names }
+    property ProductName: string read FProductName write SetProductName;
+
+    property DeviceID: Cardinal read FDeviceID write SetDeviceID default 0;
+ { TODO: midiOutGetVolume? Or two properties for Left and Right volume?
+   Is it worth it??
+     midiOutMessage?? Does anyone use this? }
+
+ { Events }
+    property Onmidioutput: TNotifyEvent
+      read FOnmidioutput
+      write FOnmidioutput;
+  end;
+
+procedure Register;
+
+{-------------------------------------------------------------------}
+implementation
+
+(* Not used in Delphi 3
+
+{ This is the callback procedure in the external DLL.
+  It's used when midioutOpen is called by the Open method.
+  There are special requirements and restrictions for this callback
+  procedure (see midioutOpen in MMSYSTEM.HLP) so it's impractical to
+  make it an object method }
+{$IFDEF MSWINDOWS}
+function midiHandler(
+    hMidiIn: HMidiIn;
+    wMsg: UINT;
+    dwInstance: DWORD;
+    dwParam1: DWORD;
+    dwParam2: DWORD): Boolean; stdcall; external 'DELMID32.DLL';
+{$ENDIF}
+*)
+
+{-------------------------------------------------------------------}
+
+constructor Tmidioutput.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FState := mosClosed;
+  FNumdevs := midiOutGetNumDevs;
+
+ { Create the window for callback notification }
+  if not (csDesigning in ComponentState) then
+  begin
+    Handle := AllocateHwnd(MidiOutput);
+  end;
+
+end;
+
+{-------------------------------------------------------------------}
+
+destructor Tmidioutput.Destroy;
+begin
+  if FState = mosOpen then
+    Close;
+  if (PCtlInfo <> nil) then
+    GlobalSharedLockedFree(PCtlinfo^.hMem, PCtlInfo);
+  DeallocateHwnd(Handle);
+  inherited Destroy;
+end;
+
+{-------------------------------------------------------------------}
+{ Convert the numeric return code from an MMSYSTEM function to a string
+  using midioutGetErrorText. TODO: These errors aren't very helpful
+  (e.g. "an invalid parameter was passed to a system function") so
+  some proper error strings would be nice. }
+
+
+function Tmidioutput.midioutErrorString(WError: Word): string;
+var
+  errorDesc: PChar;
+begin
+  errorDesc := nil;
+  try
+    errorDesc := StrAlloc(MAXERRORLENGTH);
+    if midioutGetErrorText(WError, errorDesc, MAXERRORLENGTH) = 0 then
+      result := StrPas(errorDesc)
+    else
+      result := 'Specified error number is out of range';
+  finally
+    if errorDesc <> nil then StrDispose(errorDesc);
+  end;
+end;
+
+{-------------------------------------------------------------------}
+{ Set the output device ID and change the other properties to match }
+
+procedure Tmidioutput.SetDeviceID(DeviceID: Cardinal);
+var
+  midioutCaps: TmidioutCaps;
+begin
+  if FState = mosOpen then
+    raise EmidioutputError.Create('Change to DeviceID while device was open')
+  else
+    if (DeviceID >= midioutGetNumDevs) and (DeviceID <> MIDI_MAPPER) then
+      raise EmidioutputError.Create('Invalid device ID')
+    else
+    begin
+      FDeviceID := DeviceID;
+
+   { Set the name and other midioutCAPS properties to match the ID }
+      FError :=
+        midioutGetDevCaps(DeviceID, @midioutCaps, sizeof(TmidioutCaps));
+      if Ferror > 0 then
+        raise EmidioutputError.Create(midioutErrorString(FError));
+
+      with midiOutCaps do
+      begin
+        FProductName := StrPas(szPname);
+        FDriverVersion := vDriverVersion;
+        FTechnology := OutPortTech(wTechnology);
+        FVoices := wVoices;
+        FNotes := wNotes;
+        FChannelMask := wChannelMask;
+        FSupport := dwSupport;
+      end;
+
+    end;
+end;
+
+{-------------------------------------------------------------------}
+{ Set the product name property and put the matching output device number
+  in FDeviceID.
+  This is handy if you want to save a configured output/output device
+  by device name instead of device number, because device numbers may
+  change if users install or remove MIDI devices.
+  Exception if output device with matching name not found,
+  or if output device is open }
+
+procedure Tmidioutput.SetProductName(NewProductName: string);
+var
+  midioutCaps: TmidioutCaps;
+  testDeviceID: Integer;
+  testProductName: string;
+begin
+  if FState = mosOpen then
+    raise EmidioutputError.Create('Change to ProductName while device was open')
+  else
+  { Don't set the name if the component is reading properties because
+  the saved Productname will be from the machine the application was compiled
+  on, which may not be the same for the corresponding DeviceID on the user's
+  machine. The FProductname property will still be set by SetDeviceID }
+    if not (csLoading in ComponentState) then
+    begin
+    { Loop uses -1 to test for MIDI_MAPPER as well }
+      for testDeviceID := -1 to (midioutGetNumDevs - 1) do
+      begin
+        FError :=
+          midioutGetDevCaps(testDeviceID, @midioutCaps, sizeof(TmidioutCaps));
+        if Ferror > 0 then
+          raise EmidioutputError.Create(midioutErrorString(FError));
+        testProductName := StrPas(midioutCaps.szPname);
+        if testProductName = NewProductName then
+        begin
+          FProductName := NewProductName;
+          Break;
+        end;
+      end;
+      if FProductName <> NewProductName then
+        raise EmidioutputError.Create('MIDI output Device ' +
+          NewProductName + ' not installed')
+      else
+        SetDeviceID(testDeviceID);
+    end;
+end;
+
+{-------------------------------------------------------------------}
+{ Set the output technology property and put the matching output device
+ number in FDeviceID.
+  This is handy, for example, if you want to be able to switch between a
+  sound card and a MIDI port }
+
+procedure TMidiOutput.SetTechnology(NewTechnology: OutPortTech);
+var
+  midiOutCaps: TMidiOutCaps;
+  testDeviceID: Integer;
+  testTechnology: OutPortTech;
+begin
+  if FState = mosOpen then
+    raise EMidiOutputError.Create(
+      'Change to Product Technology while device was open')
+  else
+  begin
+       { Loop uses -1 to test for MIDI_MAPPER as well }
+    for testDeviceID := -1 to (midiOutGetNumDevs - 1) do
+    begin
+      FError :=
+        midiOutGetDevCaps(testDeviceID,
+        @midiOutCaps, sizeof(TMidiOutCaps));
+      if Ferror > 0 then
+        raise EMidiOutputError.Create(MidiOutErrorString(FError));
+      testTechnology := OutPortTech(midiOutCaps.wTechnology);
+      if testTechnology = NewTechnology then
+      begin
+        FTechnology := NewTechnology;
+        Break;
+      end;
+    end;
+    if FTechnology <> NewTechnology then
+      raise EMidiOutputError.Create('MIDI output technology ' +
+        TechName[NewTechnology] + ' not installed')
+    else
+      SetDeviceID(testDeviceID);
+  end;
+end;
+
+{-------------------------------------------------------------------}
+
+function Tmidioutput.Open: Boolean;
+var
+  hMem: THandle;
+begin
+  Result := False;
+  try
+  { Create the control info for the DLL }
+    if (PCtlInfo = nil) then
+    begin
+      PCtlInfo := GlobalSharedLockedAlloc(Sizeof(TMidiCtlInfo), hMem);
+      PctlInfo^.hMem := hMem;
+    end;
+
+    Pctlinfo^.hWindow := Handle; { Control's window handle }
+
+    FError := midioutOpen(@FMidiHandle, FDeviceId,
+      DWORD(@midiHandler),
+      DWORD(PCtlInfo),
+      CALLBACK_FUNCTION);
+{                FError := midioutOpen(@FMidiHandle, FDeviceId,
+      Handle,
+      DWORD(PCtlInfo),
+      CALLBACK_WINDOW); }
+    if (FError <> 0) then
+   { TODO: use CreateFmtHelp to add MIDI device name/ID to message }
+      raise EmidioutputError.Create(midioutErrorString(FError))
+    else
+    begin
+      Result := True;
+      FState := mosOpen;
+    end;
+
+  except
+    if PCtlInfo <> nil then
+    begin
+      GlobalSharedLockedFree(PCtlInfo^.hMem, PCtlInfo);
+      PCtlInfo := nil;
+    end;
+  end;
+
+end;
+
+{-------------------------------------------------------------------}
+
+procedure TMidiOutput.PutShort(MidiMessage: Byte; Data1: Byte; Data2: Byte);
+var
+  thisMsg: DWORD;
+begin
+  thisMsg := DWORD(MidiMessage) or
+    (DWORD(Data1) shl 8) or
+    (DWORD(Data2) shl 16);
+
+  FError := midiOutShortMsg(FMidiHandle, thisMsg);
+  if Ferror > 0 then
+    raise EmidioutputError.Create(midioutErrorString(FError));
+end;
+
+{-------------------------------------------------------------------}
+
+procedure TMidiOutput.PutLong(TheSysex: Pointer; msgLength: Word);
+{ Notes: This works asynchronously; you send your sysex output by
+calling this function, which returns immediately. When the MIDI device
+driver has finished sending the data the MidiOutPut function in this
+component is called, which will in turn call the OnMidiOutput method
+if the component user has defined one. }
+{ TODO: Combine common functions with PutTimedLong into subroutine }
+
+var
+  MyMidiHdr: TMyMidiHdr;
+begin
+ { Initialize the header and allocate buffer memory }
+  MyMidiHdr := TMyMidiHdr.Create(msgLength);
+
+ { Copy the data over to the MidiHdr buffer
+   We can't just use the caller's PChar because the buffer memory
+   has to be global, shareable, and locked. }
+  StrMove(MyMidiHdr.SysexPointer, TheSysex, msgLength);
+
+ { Store the MyMidiHdr address in the header so we can find it again quickly
+      (see the MidiOutput proc) }
+  MyMidiHdr.hdrPointer^.dwUser := DWORD(MyMidiHdr);
+
+ { Get MMSYSTEM's blessing for this header }
+  FError := midiOutPrepareHeader(FMidiHandle, MyMidiHdr.hdrPointer,
+    sizeof(TMIDIHDR));
+  if Ferror > 0 then
+    raise EMidiOutputError.Create(MidiOutErrorString(FError));
+
+ { Send it }
+  FError := midiOutLongMsg(FMidiHandle, MyMidiHdr.hdrPointer,
+    sizeof(TMIDIHDR));
+  if Ferror > 0 then
+    raise EMidiOutputError.Create(MidiOutErrorString(FError));
+
+end;
+
+{-------------------------------------------------------------------}
+
+procedure Tmidioutput.PutMidiEvent(theEvent: TMyMidiEvent);
+begin
+  if FState <> mosOpen then
+    raise EMidiOutputError.Create('MIDI Output device not open');
+
+  with theEvent do
+  begin
+    if Sysex = nil then
+    begin
+      PutShort(MidiMessage, Data1, Data2)
+    end
+    else
+      PutLong(Sysex, SysexLength);
+  end;
+end;
+
+{-------------------------------------------------------------------}
+
+function Tmidioutput.Close: Boolean;
+begin
+  Result := False;
+  if FState = mosOpen then
+  begin
+
+        { Note this sends a lot of fast control change messages which some synths can't handle.
+          TODO: Make this optional. }
+{		FError := midioutReset(FMidiHandle);
+  if Ferror <> 0 then
+   raise EMidiOutputError.Create(MidiOutErrorString(FError)); }
+
+    FError := midioutClose(FMidiHandle);
+    if Ferror <> 0 then
+      raise EMidiOutputError.Create(MidiOutErrorString(FError))
+    else
+      Result := True;
+  end;
+
+  FMidiHandle := 0;
+  FState := mosClosed;
+
+end;
+
+{-------------------------------------------------------------------}
+
+procedure TMidiOutput.SetVolume(Left: Word; Right: Word);
+var
+  dwVolume: DWORD;
+begin
+  dwVolume := (DWORD(Left) shl 16) or Right;
+  FError := midiOutSetVolume(DeviceID, dwVolume);
+  if Ferror <> 0 then
+    raise EMidiOutputError.Create(MidiOutErrorString(FError));
+end;
+
+{-------------------------------------------------------------------}
+
+procedure Tmidioutput.midioutput(var Message: TMessage);
+{ Triggered when sysex output from PutLong is complete }
+var
+  MyMidiHdr: TMyMidiHdr;
+  thisHdr: PMidiHdr;
+begin
+  if Message.Msg = Mom_Done then
+  begin
+  { Find the MIDIHDR we used for the output. Message.lParam is its address }
+    thisHdr := PMidiHdr(Message.lParam);
+
+  { Remove it from the output device }
+    midiOutUnprepareHeader(FMidiHandle, thisHdr, sizeof(TMIDIHDR));
+
+  { Get the address of the MyMidiHdr object containing this MIDIHDR structure.
+   We stored this address in the PutLong procedure }
+    MyMidiHdr := TMyMidiHdr(thisHdr^.dwUser);
+
+  { Header and copy of sysex data no longer required since output is complete }
+    MyMidiHdr.Free;
+
+  { Call the user's event handler if any }
+    if Assigned(FOnmidioutput) then
+      FOnmidioutput(Self);
+  end;
+ { TODO: Case for MOM_PLAYBACK_DONE }
+end;
+
+{-------------------------------------------------------------------}
+
+procedure Register;
+begin
+  RegisterComponents('Synth', [Tmidioutput]);
+end;
+
+end.
+
diff --git a/songmanagement/src/lib/midi/demo/MidiTest.dfm b/songmanagement/src/lib/midi/demo/MidiTest.dfm
new file mode 100644
index 00000000..0d0ae182
Binary files /dev/null and b/songmanagement/src/lib/midi/demo/MidiTest.dfm differ
diff --git a/songmanagement/src/lib/midi/demo/MidiTest.pas b/songmanagement/src/lib/midi/demo/MidiTest.pas
new file mode 100644
index 00000000..793db730
--- /dev/null
+++ b/songmanagement/src/lib/midi/demo/MidiTest.pas
@@ -0,0 +1,249 @@
+// Test application for TMidiFile
+
+unit MidiTest;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  StdCtrls, MidiFile,  ExtCtrls, MidiOut, MidiType, MidiScope, Grids;
+type
+  TMidiPlayer = class(TForm)
+    OpenDialog1: TOpenDialog;
+    Button1: TButton;
+    Button3: TButton;
+    Button4: TButton;
+    MidiOutput1: TMidiOutput;
+    cmbInput: TComboBox;
+    MidiFile1: TMidiFile;
+    MidiScope1: TMidiScope;
+    Label3: TLabel;
+    edtBpm: TEdit;
+    Memo2: TMemo;
+    edtTime: TEdit;
+    Button2: TButton;
+    TrackGrid: TStringGrid;
+    TracksGrid: TStringGrid;
+    edtLength: TEdit;
+    procedure Button1Click(Sender: TObject);
+    procedure MidiFile1MidiEvent(event: PMidiEvent);
+    procedure Button3Click(Sender: TObject);
+    procedure Button4Click(Sender: TObject);
+    procedure FormCreate(Sender: TObject);
+    procedure cmbInputChange(Sender: TObject);
+    procedure MidiFile1UpdateEvent(Sender: TObject);
+    procedure Button2Click(Sender: TObject);
+    procedure edtBpmKeyPress(Sender: TObject; var Key: Char);
+    procedure TracksGridSelectCell(Sender: TObject; Col, Row: Integer;
+      var CanSelect: Boolean);
+    procedure FormShow(Sender: TObject);
+  private
+    { Private declarations }
+    MidiOpened : boolean;
+    procedure SentAllNotesOff;
+
+    procedure MidiOpen;
+    procedure MidiClose;
+
+  public
+    { Public declarations }
+  end;
+
+var
+  MidiPlayer: TMidiPlayer;
+
+implementation
+
+{$R *.DFM}
+
+procedure TMidiPlayer.Button1Click(Sender: TObject);
+var
+  i,j: integer;
+  track : TMidiTrack;
+  event : PMidiEvent;
+begin
+  if opendialog1.execute then
+  begin
+    midifile1.filename := opendialog1.filename;
+    midifile1.readfile;
+//    label1.caption := IntToStr(midifile1.NumberOfTracks);
+    edtBpm.text := IntToStr(midifile1.Bpm);
+//    TracksGrid.cells.clear;
+    for i := 0 to midifile1.NumberOfTracks-1 do
+    begin
+      track := midifile1.getTrack(i);
+      TracksGrid.cells[0,i] := 'Tr: '+ track.getName + ' '+ track.getInstrument ;
+    end;
+    edtLength.Text := MyTimeToStr(MidiFile1.GetTrackLength);
+  end;
+end;
+
+procedure TMidiPlayer.MidiFile1MidiEvent(event: PMidiEvent);
+var mEvent : TMyMidiEvent;
+begin
+  mEvent := TMyMidiEvent.Create;
+  if not (event.event = $FF) then
+  begin
+    mEvent.MidiMessage := event.event;
+    mEvent.data1 := event.data1;
+    mEvent.data2 := event.data2;
+    midioutput1.PutMidiEvent(mEvent);
+  end
+  else
+  begin
+    if (event.data1 >= 1) and (event.data1 < 15) then
+    begin
+      memo2.Lines.add(IntToStr(event.data1) + ' '+ event.str);
+    end
+  end;
+  midiScope1.MidiEvent(event.event,event.data1,event.data2);
+  mEvent.Destroy;
+end;
+
+procedure TMidiPlayer.SentAllNotesOff;
+var mEvent : TMyMidiEvent;
+channel : integer;
+begin
+  mEvent := TMyMidiEvent.Create;
+  for channel:= 0 to 15 do
+  begin
+    mEvent.MidiMessage := $B0 + channel;
+    mEvent.data1 := $78;
+    mEvent.data2 := 0;
+    if MidiOpened then
+      midioutput1.PutMidiEvent(mEvent);
+    midiScope1.MidiEvent(mEvent.MidiMessage,mEvent.data1,mEvent.data2);
+  end;
+  mEvent.Destroy;
+end;
+
+procedure TMidiPlayer.Button3Click(Sender: TObject);
+begin
+  midifile1.StartPlaying;
+end;
+
+procedure TMidiPlayer.Button4Click(Sender: TObject);
+begin
+  midifile1.StopPlaying;
+  SentAllNotesOff;
+end;
+
+procedure TMidiPlayer.MidiOpen;
+begin
+  if not (cmbInput.Text = '') then
+  begin
+    MidiOutput1.ProductName := cmbInput.Text;
+    MidiOutput1.OPEN;
+    MidiOpened := true;
+  end;
+end;
+
+procedure TMidiPlayer.MidiClose;
+begin
+  if MidiOpened then
+  begin
+    MidiOutput1.Close;
+    MidiOpened := false;
+  end;
+end;
+
+
+procedure TMidiPlayer.FormCreate(Sender: TObject);
+var thisDevice : integer;
+begin
+  for thisDevice := 0 to MidiOutput1.NumDevs - 1 do
+  begin
+    MidiOutput1.DeviceID := thisDevice;
+    cmbInput.Items.Add(MidiOutput1.ProductName);
+  end;
+  cmbInput.ItemIndex := 0;
+  MidiOpened := false;
+  MidiOpen;
+end;
+
+procedure TMidiPlayer.cmbInputChange(Sender: TObject);
+begin
+  MidiClose;
+  MidiOPen;
+end;
+
+procedure TMidiPlayer.MidiFile1UpdateEvent(Sender: TObject);
+begin
+  edtTime.Text := MyTimeToStr(MidiFile1.GetCurrentTime);
+  edtTime.update;
+  if MidiFile1.ready then
+  begin
+    midifile1.StopPlaying;
+    SentAllNotesOff;
+  end;
+end;
+
+procedure TMidiPlayer.Button2Click(Sender: TObject);
+begin
+  MidiFile1.ContinuePlaying;
+end;
+
+procedure TMidiPlayer.edtBpmKeyPress(Sender: TObject; var Key: Char);
+begin
+ if Key = char(13) then
+ begin
+   MidiFile1.Bpm := StrToInt(edtBpm.Text);
+   edtBpm.text := IntToStr(midifile1.Bpm);
+   abort;
+ end;
+
+end;
+
+procedure TMidiPlayer.TracksGridSelectCell(Sender: TObject; Col,
+  Row: Integer; var CanSelect: Boolean);
+var
+  MidiTrack : TMidiTrack;
+  i         : integer;
+  j         : integer;
+  event     : PMidiEvent;
+begin
+  CanSelect := false;
+  if Row < MidiFile1.NumberOfTracks then
+  begin
+    CanSelect := true;
+    MidiTrack := MidiFile1.GetTrack(Row);
+    TrackGrid.RowCount := 2;
+    TrackGrid.RowCount := MidiTrack.getEventCount;
+    j := 1;
+    for i := 0 to MidiTrack.GetEventCount-1 do
+    begin
+      event := MidiTrack.getEvent(i);
+      if not (event.len = -1) then
+      begin // do not print when
+        TrackGrid.cells[0,j] := IntToStr(i);
+        TrackGrid.cells[1,j] := MyTimeToStr(event.time);
+        TrackGrid.cells[2,j] := IntToHex(event.event,2);
+        if not (event.event = $FF) then
+        begin
+          TrackGrid.cells[3,j] := IntToStr(event.len);
+          TrackGrid.cells[4,j] := KeyToStr(event.data1);
+          TrackGrid.cells[5,j] := IntToStr(event.data2);
+        end
+        else
+        begin
+          TrackGrid.cells[3,j] := IntToStr(event.data1);
+          TrackGrid.cells[4,j] := '';
+          TrackGrid.cells[5,j] := event.str;
+        end;
+        inc(j);
+      end;
+    end;
+    TrackGrid.RowCount := j;
+  end;
+end;
+
+procedure TMidiPlayer.FormShow(Sender: TObject);
+begin
+  TrackGrid.ColWidths[0] := 30;
+  TrackGrid.ColWidths[2] := 30;
+  TrackGrid.ColWidths[3] := 30;
+  TrackGrid.ColWidths[4] := 30;
+  TrackGrid.ColWidths[5] := 100;
+end;
+
+end.
diff --git a/songmanagement/src/lib/midi/demo/Project1.dpr b/songmanagement/src/lib/midi/demo/Project1.dpr
new file mode 100644
index 00000000..7aa4e512
--- /dev/null
+++ b/songmanagement/src/lib/midi/demo/Project1.dpr
@@ -0,0 +1,13 @@
+program Project1;
+
+uses
+  Forms,
+  MidiTest in 'MidiTest.pas' {MidiPlayer};
+
+{$R *.RES}
+
+begin
+  Application.Initialize;
+  Application.CreateForm(TMidiPlayer, MidiPlayer);
+  Application.Run;
+end.
diff --git a/songmanagement/src/lib/midi/demo/Project1.res b/songmanagement/src/lib/midi/demo/Project1.res
new file mode 100644
index 00000000..2b020d69
Binary files /dev/null and b/songmanagement/src/lib/midi/demo/Project1.res differ
diff --git a/songmanagement/src/lib/midi/midiComp.cfg b/songmanagement/src/lib/midi/midiComp.cfg
new file mode 100644
index 00000000..8b774c81
--- /dev/null
+++ b/songmanagement/src/lib/midi/midiComp.cfg
@@ -0,0 +1,35 @@
+-$A+
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J+
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$Y-
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-LE"d:\program files\borland\delphi5\Projects\Bpl"
+-LN"d:\program files\borland\delphi5\Projects\Bpl"
diff --git a/songmanagement/src/lib/midi/midiComp.dpk b/songmanagement/src/lib/midi/midiComp.dpk
new file mode 100644
index 00000000..7c403eae
--- /dev/null
+++ b/songmanagement/src/lib/midi/midiComp.dpk
@@ -0,0 +1,45 @@
+package midiComp;
+
+{$R *.RES}
+{$R 'MidiFile.dcr'}
+{$R 'Midiin.dcr'}
+{$R 'Midiout.dcr'}
+{$R 'MidiScope.dcr'}
+{$ALIGN ON}
+{$ASSERTIONS ON}
+{$BOOLEVAL OFF}
+{$DEBUGINFO ON}
+{$EXTENDEDSYNTAX ON}
+{$IMPORTEDDATA ON}
+{$IOCHECKS ON}
+{$LOCALSYMBOLS ON}
+{$LONGSTRINGS ON}
+{$OPENSTRINGS ON}
+{$OPTIMIZATION ON}
+{$OVERFLOWCHECKS OFF}
+{$RANGECHECKS OFF}
+{$REFERENCEINFO OFF}
+{$SAFEDIVIDE OFF}
+{$STACKFRAMES OFF}
+{$TYPEDADDRESS OFF}
+{$VARSTRINGCHECKS ON}
+{$WRITEABLECONST ON}
+{$MINENUMSIZE 1}
+{$IMAGEBASE $400000}
+{$DESCRIPTION 'Midi related components'}
+{$DESIGNONLY}
+{$IMPLICITBUILD ON}
+
+requires
+  vcl50;
+
+contains
+  Miditype in 'Miditype.pas',
+  Mididefs in 'Mididefs.pas',
+  MidiFile in 'MidiFile.pas',
+  Midiin in 'Midiin.pas',
+  Midiout in 'Midiout.pas',
+  MidiScope in 'MidiScope.pas',
+  Midicons in 'Midicons.pas';
+
+end.
diff --git a/songmanagement/src/lib/midi/midiComp.res b/songmanagement/src/lib/midi/midiComp.res
new file mode 100644
index 00000000..91fb756e
Binary files /dev/null and b/songmanagement/src/lib/midi/midiComp.res differ
diff --git a/songmanagement/src/lib/midi/readme.txt b/songmanagement/src/lib/midi/readme.txt
new file mode 100644
index 00000000..7112aecf
--- /dev/null
+++ b/songmanagement/src/lib/midi/readme.txt
@@ -0,0 +1,60 @@
+
+Midi components
+  TMidiFile, TMidiScope
+  TMidiIn and TMidiOut of david Churcher are included because they are used in 
+  the demo application
+
+Freeware.
+
+100% source code,  demo application.
+
+Included Components/Classes
+
+TMidiFile, read a midifile and have the contents available in memory 
+  list of Tracks, track is list of events
+
+
+TMidiScope, show all activity on a midi device
+
+TMidiIn and TMidiOut of David Churcher are included because they are used 
+in the demo application
+
+Midiplayer is a demo application which plays a midifile on a midi output
+ it is build fairly simple with the included components. The timer is used
+ to time the midievents. The timing is therefor as good as the windows timer.
+
+
+  The header of midifile,midiscope contains help information on the properties/functions
+  The example Midiplayer gives a good idea how to use the components
+
+Installation
+	open midiComp.dpk with file/open
+	compile and install the package
+	make sure that the directory where the files are located is in the library path 	
+        (tools/environment options/library)
+
+to run the demo
+	open project1.dpr in the demo directory and press run.
+
+
+
+history
+1.0  18-1-1999 first release
+
+1.1  5-3-1999 update
+  added some functions for display purposes
+  improved demo to include event viewer
+  bpm can be changed
+
+1.2  24-2-2000 update
+  added some functions to see the length of a song and ready function to know when playback is ready
+
+for comments/bugs in these components:
+
+Frans Bouwmans
+fbouwmans@spiditel.nl
+
+I'm busy building a software music synthesizer, which will be available in source 
+to the public. If you are interrested in helping me with certain soundmodules 
+(effects, filters, sound generators) just sent me an email.
+
diff --git a/songmanagement/src/lib/other/DirWatch.pas b/songmanagement/src/lib/other/DirWatch.pas
new file mode 100644
index 00000000..1e00ec5d
--- /dev/null
+++ b/songmanagement/src/lib/other/DirWatch.pas
@@ -0,0 +1,345 @@
+unit DirWatch;
+
+// -----------------------------------------------------------------------------
+// Component Name:  TDirectoryWatch                                            .
+// Module:          DirWatch                                                   .
+// Description:     Implements watching for file changes in a designated       .
+//                  directory (or directories).                                .
+// Version:         1.4                                                        .
+// Date:            10-MAR-2003                                                .
+// Target:          Win32, Delphi 3 - Delphi 7                                 .
+// Author:          Angus Johnson, angusj-AT-myrealbox-DOT-com                 .
+//                  A portion of code has been copied from the Drag & Drop     .
+//                  Component Suite which I co-authored with Anders Melander.  .
+// Copyright:       � 2003 Angus Johnson                                       .
+//                                                                             .
+// Usage:           1. Add a TDirectoryWatch component to your form.           .
+//                  2. Set its Directory property                              .
+//                  3. If you wish to watch its subdirectories too then set    .
+//                  the WatchSubDir property to true                           .
+//                  4. Assign the OnChange event                               .
+//                  5. Set Active to true                                      .
+// -----------------------------------------------------------------------------
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+  {$H+} // use long strings
+{$ENDIF}
+
+uses
+  Windows,
+  Messages,
+  Classes,
+  {$IFDEF FPC}
+  WinAllocation,
+  {$ENDIF}
+  SysUtils;
+
+type
+  TNotifyFilters = set of (nfFilename, nfDirname, nfAttrib,
+    nfSize, nfLastWrite, nfSecurity);
+
+  TWatchThread = class;             //forward declaration
+
+  TDirectoryWatch = class(TComponent)
+  private
+    fWindowHandle: THandle;
+    fWatchThread: TWatchThread;
+    fWatchSubDirs: boolean;
+    fDirectory: string;
+    fActive: boolean;
+    fNotifyFilters: TNotifyFilters; //see FindFirstChangeNotification in winAPI
+    fOnChangeEvent: TNotifyEvent;
+    procedure SetActive(aActive: boolean);
+    procedure SetDirectory(aDir: string);
+    procedure SetWatchSubDirs(aWatchSubDirs: boolean);
+    procedure SetNotifyFilters(aNotifyFilters: TNotifyFilters);
+    procedure WndProc(var aMsg: TMessage);
+  public
+    constructor Create(aOwner: TComponent); override;
+    destructor Destroy; override;
+  published
+    property Directory: string read fDirectory write SetDirectory;
+    property NotifyFilters: TNotifyFilters
+      read fNotifyFilters write SetNotifyFilters;
+    property WatchSubDirs: boolean read fWatchSubDirs write SetWatchSubDirs;
+    property Active: boolean read fActive write SetActive;
+    property OnChange: TNotifyEvent read fOnChangeEvent write fOnChangeEvent;
+  end;
+
+  TWatchThread = class(TThread)
+  private
+    fOwnerHdl: Thandle;
+    fChangeNotify : THandle; //Signals whenever Windows detects a change in    .
+                             //the watched directory                           .
+    fBreakEvent: THandle;    //Signals when either the Directory property      .
+                             //changes or when the thread terminates           .
+    fDirectory: string;
+    fWatchSubDirs: longbool;
+    fNotifyFilters: dword;
+    fFinished: boolean;    
+  protected
+    procedure SetDirectory(const Value: string);
+    procedure ProcessFilenameChanges;
+    procedure Execute; override;
+  public
+    constructor Create( OwnerHdl: THandle;
+      const InitialDir: string; WatchSubDirs: boolean; NotifyFilters: dword);
+    destructor Destroy; override;
+    procedure Terminate;
+    property Directory: string write SetDirectory;
+  end;
+
+procedure Register;
+
+implementation
+
+const
+  NOTIFYCHANGE_MESSAGE = WM_USER + 1;
+
+resourcestring
+  sInvalidDir = 'Invalid Directory: ';
+
+//----------------------------------------------------------------------------
+// Miscellaneous functions ...
+//----------------------------------------------------------------------------
+
+procedure Register;
+begin
+  RegisterComponents('Samples', [TDirectoryWatch]);
+end;
+//----------------------------------------------------------------------------
+
+function DirectoryExists(const Name: string): Boolean;
+var
+  Code: Integer;
+begin
+  Code := GetFileAttributes(PChar(Name));
+  Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
+end;
+
+//----------------------------------------------------------------------------
+// TDirectoryWatch methods ...
+//----------------------------------------------------------------------------
+
+constructor TDirectoryWatch.Create(aOwner: TComponent);
+begin
+  inherited Create(aOwner);
+  //default Notify values - notify if either a file name or a directory name
+  //changes or if a file is modified ...
+  fNotifyFilters := [nfFilename, nfDirname, nfLastWrite];
+  fDirectory := 'C:\';
+  //this non-visual control needs to handle messages, so ...
+  if not (csDesigning in ComponentState) then
+    fWindowHandle := AllocateHWnd(WndProc);
+end;
+//----------------------------------------------------------------------------
+
+destructor TDirectoryWatch.Destroy;
+begin
+  Active := false;
+  if not (csDesigning in ComponentState) then
+    DeallocateHWnd(fWindowHandle);
+  inherited Destroy;
+end;
+//----------------------------------------------------------------------------
+
+procedure TDirectoryWatch.WndProc(var aMsg: TMessage);
+begin
+  with aMsg do
+    if Msg = NOTIFYCHANGE_MESSAGE then
+    begin
+      if assigned(OnChange) then OnChange(self);
+    end else
+      Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
+end;
+//------------------------------------------------------------------------------
+
+procedure TDirectoryWatch.SetNotifyFilters(aNotifyFilters: TNotifyFilters);
+begin
+  if aNotifyFilters = fNotifyFilters then exit;
+  fNotifyFilters := aNotifyFilters;
+  if assigned(fWatchThread) then
+  begin
+    Active := false;
+    Active := true;
+  end;
+end;
+//------------------------------------------------------------------------------
+
+procedure TDirectoryWatch.SetWatchSubDirs(aWatchSubDirs: boolean);
+begin
+  if aWatchSubDirs = fWatchSubDirs then exit;
+  fWatchSubDirs := aWatchSubDirs;
+  if assigned(fWatchThread) then
+  begin
+    Active := false;
+    Active := true;
+  end;
+end;
+//------------------------------------------------------------------------------
+
+procedure TDirectoryWatch.SetDirectory(aDir: string);
+begin
+  if aDir = '' then
+  begin
+    Active := false;
+    fDirectory := '';
+    exit;
+  end;
+  if (aDir[length(aDir)] <> '\') then aDir := aDir + '\';
+  if aDir = fDirectory then exit;
+  if not (csDesigning in ComponentState) and not DirectoryExists(aDir) then
+    raise Exception.Create( sInvalidDir + aDir);
+  fDirectory := aDir;
+  if assigned(fWatchThread) then
+    fWatchThread.Directory := fDirectory;
+end;
+//------------------------------------------------------------------------------
+
+procedure TDirectoryWatch.SetActive(aActive: boolean);
+var
+  nf: dword;
+begin
+  if aActive = fActive then exit;
+  fActive := aActive;
+  if csDesigning in ComponentState then exit;
+  if fActive then
+  begin
+    if not DirectoryExists(fDirectory) then
+    begin
+      fActive := false;
+      raise Exception.Create(sInvalidDir + fDirectory);
+    end;
+    nf := 0;
+    if nfFilename in fNotifyFilters then
+      nf := nf or FILE_NOTIFY_CHANGE_FILE_NAME;
+    if nfDirname in fNotifyFilters then
+      nf := nf or FILE_NOTIFY_CHANGE_DIR_NAME;
+    if nfAttrib in fNotifyFilters then
+      nf := nf or FILE_NOTIFY_CHANGE_ATTRIBUTES;
+    if nfSize in fNotifyFilters then
+      nf := nf or FILE_NOTIFY_CHANGE_SIZE;
+    if nfLastWrite in fNotifyFilters then
+      nf := nf or FILE_NOTIFY_CHANGE_LAST_WRITE;
+    if nfSecurity in fNotifyFilters then
+      nf := nf or FILE_NOTIFY_CHANGE_SECURITY;
+    fWatchThread := TWatchThread.Create(
+      fWindowHandle, fDirectory, fWatchSubDirs, nf);
+  end else
+  begin
+    fWatchThread.Terminate;
+    fWatchThread := nil;
+  end;
+end;
+
+//----------------------------------------------------------------------------
+// TWatchThread methods ...
+//----------------------------------------------------------------------------
+
+constructor TWatchThread.Create(OwnerHdl: THandle;
+  const InitialDir: string; WatchSubDirs: boolean; NotifyFilters: dword);
+begin
+  inherited Create(True);       
+  fOwnerHdl := OwnerHdl;
+  if WatchSubDirs then
+    cardinal(fWatchSubDirs) := 1 //workaround a Win9x OS issue
+  else
+    fWatchSubDirs := false;
+  FreeOnTerminate := true;
+  Priority := tpLowest;
+  fDirectory := InitialDir;
+  fNotifyFilters := NotifyFilters;
+  fBreakEvent := windows.CreateEvent(nil, False, False, nil);
+  Resume;
+end;
+//------------------------------------------------------------------------------
+
+destructor TWatchThread.Destroy;
+begin
+  CloseHandle(fBreakEvent);
+  inherited Destroy;
+end;
+//------------------------------------------------------------------------------
+
+procedure TWatchThread.SetDirectory(const Value: string);
+begin
+  if (Value = FDirectory) then exit;
+  FDirectory := Value;
+  SetEvent(fBreakEvent);
+end;
+//------------------------------------------------------------------------------
+
+procedure TWatchThread.Terminate;
+begin
+  inherited Terminate;
+  SetEvent(fBreakEvent);
+  while not fFinished do sleep(10); //avoids a reported resource leak
+                                    //if called while closing the application.
+end;
+//------------------------------------------------------------------------------
+
+procedure TWatchThread.Execute;
+begin
+  //OUTER LOOP - manages Directory property reassignments
+  while (not Terminated) do
+  begin
+    fChangeNotify := FindFirstChangeNotification(pchar(fDirectory),
+      fWatchSubDirs, fNotifyFilters);
+    if (fChangeNotify = INVALID_HANDLE_VALUE) then
+      //Can't monitor the specified directory so we'll just wait for
+      //a new Directory assignment or the thread terminating ...
+      WaitForSingleObject(fBreakEvent, INFINITE)
+    else
+      try
+        //Now do the INNER loop...
+        ProcessFilenameChanges;
+      finally
+        FindCloseChangeNotification(fChangeNotify);
+      end;
+  end;
+  fFinished := true;
+end;
+//------------------------------------------------------------------------------
+
+procedure TWatchThread.ProcessFilenameChanges;
+var
+  WaitResult : DWORD;
+  HandleArray : array[0..1] of THandle;
+const
+  TEN_MSECS = 10;
+  HUNDRED_MSECS = 100;
+begin
+  HandleArray[0] := fBreakEvent;
+  HandleArray[1] := fChangeNotify;
+  //INNER LOOP - exits only when fBreakEvent signaled
+  while (not Terminated) do
+  begin
+    //waits for either fChangeNotify or fBreakEvent ...
+    WaitResult := WaitForMultipleObjects(2, @HandleArray, False, INFINITE);
+    if (WaitResult = WAIT_OBJECT_0 + 1) then //fChangeNotify
+    begin
+      repeat //ie: if a number of files are changing in a block
+             //just post the one notification message ...
+        FindNextChangeNotification(fChangeNotify);
+      until Terminated or
+        (WaitForSingleObject(fChangeNotify, TEN_MSECS) <> WAIT_OBJECT_0);
+      if Terminated then break;
+      //OK, now notify the main thread (before restarting inner loop)...
+      PostMessage(fOwnerHdl, NOTIFYCHANGE_MESSAGE, 0, 0);
+    end else //fBreakEvent ...
+    begin
+      //If the Directory property is undergoing multiple rapid reassignments
+      //wait 'til this stops before restarting monitoring of a new directory ...
+      while (not Terminated) and
+        (WaitForSingleObject(fBreakEvent, HUNDRED_MSECS) = WAIT_OBJECT_0) do;
+      break; //EXIT LOOP HERE
+    end;
+  end;
+end;
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/lib/other/WinAllocation.pas b/songmanagement/src/lib/other/WinAllocation.pas
new file mode 100644
index 00000000..ba1b0919
--- /dev/null
+++ b/songmanagement/src/lib/other/WinAllocation.pas
@@ -0,0 +1,101 @@
+unit WinAllocation;
+
+// FPC misses AllocateHWnd and DeallocateHWnd which is used by several
+// libraries such as Midi... or DirWatch.
+// Since FPC 2.2.2 there are dummies in Classes that just raise RunTime exceptions.
+// To avoid those exceptions, include this unit AFTER Classes.
+// Maybe the dummies will be replaced by functional routines in the future.WinAllocation
+//
+// THESE FUNCTIONS ARE ONLY FOR COMPATIBILITY WITH SOME EXTERNAL WIN32 LIBS.
+// DO NOT USE THEM IN USDX CODE.
+//
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+uses
+  Classes,
+  Windows;
+
+function  AllocateHWnd(Method: TWndMethod): HWND;
+procedure DeallocateHWnd(hWnd: HWND);
+
+implementation
+
+function AllocateHWndCallback(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
+var
+  Msg: TMessage;
+  MethodPtr: ^TWndMethod;
+begin
+  FillChar(Msg, SizeOf(Msg), 0);
+  Msg.msg := uMsg;
+  Msg.wParam := wParam;
+  Msg.lParam := lParam;
+
+  MethodPtr := Pointer(GetWindowLongPtr(hwnd, GWL_USERDATA));
+  if Assigned(MethodPtr) then
+    MethodPtr^(Msg);
+
+  Result := DefWindowProc(hwnd, uMsg, wParam, lParam);
+end;
+
+function AllocateHWnd(Method: TWndMethod): HWND;
+var
+  ClassExists: Boolean;
+  WndClass, OldClass: TWndClass;
+  MethodPtr: ^TMethod;
+begin
+  Result := 0;
+
+  // setup class-info
+  FillChar(WndClass, SizeOf(TWndClass), 0);
+  WndClass.hInstance := HInstance;
+  // Important: do not enable AllocateHWndCallback before the msg-handler method is assigned,
+  //   otherwise race-conditions might occur
+  WndClass.lpfnWndProc := @DefWindowProc;
+  WndClass.lpszClassName:= 'USDXUtilWindowClass';
+
+  // check if class is already registered
+  ClassExists := GetClassInfo(HInstance, WndClass.lpszClassName, OldClass);
+  // create window-class shared by all windows created by AllocateHWnd()
+  if (not ClassExists) or (@OldClass.lpfnWndProc <> @DefWindowProc) then
+  begin
+    if ClassExists then
+      UnregisterClass(WndClass.lpszClassName, HInstance);
+    if (RegisterClass(WndClass) = 0) then
+       Exit;
+  end;
+  // create window
+  Result := CreateWindowEx(WS_EX_TOOLWINDOW, WndClass.lpszClassName, '',
+    DWORD(WS_POPUP), 0, 0, 0, 0, 0, 0, HInstance, nil);
+  if (Result = 0) then
+    Exit;
+  // assign individual callback procedure to the window
+  if Assigned(Method) then
+  begin
+    // TMethod contains two pointers but we can pass just one as USERDATA
+    GetMem(MethodPtr, SizeOf(TMethod));
+    MethodPtr^ := TMethod(Method);
+    SetWindowLongPtr(Result, GWL_USERDATA, LONG_PTR(MethodPtr));
+  end;
+  // now enable AllocateHWndCallback for this window
+  SetWindowLongPtr(Result, GWL_WNDPROC, LONG_PTR(@AllocateHWndCallback));
+end;
+
+procedure DeallocateHWnd(hWnd: HWND);
+var
+  MethodPtr: ^TMethod;
+begin
+  if (hWnd <> 0) then
+  begin
+    MethodPtr := Pointer(GetWindowLongPtr(hWnd, GWL_USERDATA));
+    DestroyWindow(hWnd);
+    if Assigned(MethodPtr) then
+      FreeMem(MethodPtr);
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/lib/pcre/pcre.pas b/songmanagement/src/lib/pcre/pcre.pas
new file mode 100644
index 00000000..ab04a9d0
--- /dev/null
+++ b/songmanagement/src/lib/pcre/pcre.pas
@@ -0,0 +1,867 @@
+{**************************************************************************************************}
+{                                                                                                  }
+{ Project JEDI Code Library (JCL)                                                                  }
+{                                                                                                  }
+{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
+{ you may not use this file except in compliance with the License. You may obtain a copy of the    }
+{ License at http://www.mozilla.org/MPL/                                                           }
+{                                                                                                  }
+{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF   }
+{ ANY KIND, either express or implied. See the License for the specific language governing rights  }
+{ and limitations under the License.                                                               }
+{                                                                                                  }
+{ The Original Code is JclPRCE.pas.                                                                }
+{                                                                                                  }
+{ The Initial Developer of the Original Code is Peter Thornqvist.                                  }
+{ Portions created by Peter Thornqvist are Copyright (C) of Peter Thornqvist. All rights reserved. }
+{ Portions created by University of Cambridge are                                                  }
+{ Copyright (C) 1997-2001 by University of Cambridge.                                              }
+{                                                                                                  }
+{ Contributor(s):                                                                                  }
+{   Robert Rossmair (rrossmair)                                                                    }
+{   Mario R. Carro                                                                                 }
+{   Florent Ouchet (outchy)                                                                        }
+{                                                                                                  }
+{ The latest release of PCRE is always available from                                              }
+{ ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-xxx.tar.gz                            }
+{                                                                                                  }
+{**************************************************************************************************}
+{                                                                                                  }
+{ Header conversion of pcre.h                                                                      }
+{                                                                                                  }
+{                                                                                                  }
+{**************************************************************************************************}
+{                                                                                                  }
+{ Last modified: $Date::                                                                         $ }
+{ Revision:      $Rev::                                                                          $ }
+{ Author:        $Author::                                                                       $ }
+{                                                                                                  }
+{**************************************************************************************************}
+
+unit pcre;
+
+interface
+
+(*************************************************
+*       Perl-Compatible Regular Expressions      *
+*************************************************)
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$WEAKPACKAGEUNIT ON}
+
+(*$HPPEMIT '#include "pcre.h"'*)
+
+const
+  MAX_PATTERN_LENGTH = $10003;
+  {$EXTERNALSYM MAX_PATTERN_LENGTH}
+  MAX_QUANTIFY_REPEAT = $10000;
+  {$EXTERNALSYM MAX_QUANTIFY_REPEAT}
+  MAX_CAPTURE_COUNT = $FFFF;
+  {$EXTERNALSYM MAX_CAPTURE_COUNT}
+  MAX_NESTING_DEPTH = 200;
+  {$EXTERNALSYM MAX_NESTING_DEPTH}
+
+const
+  (* Options *)
+  PCRE_CASELESS = $00000001;
+  {$EXTERNALSYM PCRE_CASELESS}
+  PCRE_MULTILINE = $00000002;
+  {$EXTERNALSYM PCRE_MULTILINE}
+  PCRE_DOTALL = $00000004;
+  {$EXTERNALSYM PCRE_DOTALL}
+  PCRE_EXTENDED = $00000008;
+  {$EXTERNALSYM PCRE_EXTENDED}
+  PCRE_ANCHORED = $00000010;
+  {$EXTERNALSYM PCRE_ANCHORED}
+  PCRE_DOLLAR_ENDONLY = $00000020;
+  {$EXTERNALSYM PCRE_DOLLAR_ENDONLY}
+  PCRE_EXTRA = $00000040;
+  {$EXTERNALSYM PCRE_EXTRA}
+  PCRE_NOTBOL = $00000080;
+  {$EXTERNALSYM PCRE_NOTBOL}
+  PCRE_NOTEOL = $00000100;
+  {$EXTERNALSYM PCRE_NOTEOL}
+  PCRE_UNGREEDY = $00000200;
+  {$EXTERNALSYM PCRE_UNGREEDY}
+  PCRE_NOTEMPTY = $00000400;
+  {$EXTERNALSYM PCRE_NOTEMPTY}
+  PCRE_UTF8 = $00000800;
+  {$EXTERNALSYM PCRE_UTF8}
+  PCRE_NO_AUTO_CAPTURE = $00001000;
+  {$EXTERNALSYM PCRE_NO_AUTO_CAPTURE}
+  PCRE_NO_UTF8_CHECK = $00002000;
+  {$EXTERNALSYM PCRE_NO_UTF8_CHECK}
+  PCRE_AUTO_CALLOUT = $00004000;
+  {$EXTERNALSYM PCRE_AUTO_CALLOUT}
+  PCRE_PARTIAL_SOFT = $00008000;
+  {$EXTERNALSYM PCRE_PARTIAL_SOFT}
+  PCRE_PARTIAL = PCRE_PARTIAL_SOFT; // Backwards compatible synonym
+  {$EXTERNALSYM PCRE_PARTIAL}
+  PCRE_DFA_SHORTEST = $00010000;
+  {$EXTERNALSYM PCRE_DFA_SHORTEST}
+  PCRE_DFA_RESTART = $00020000;
+  {$EXTERNALSYM PCRE_DFA_RESTART}
+  PCRE_FIRSTLINE = $00040000;
+  {$EXTERNALSYM PCRE_FIRSTLINE}
+  PCRE_DUPNAMES = $00080000;
+  {$EXTERNALSYM PCRE_DUPNAMES}
+  PCRE_NEWLINE_CR = $00100000;
+  {$EXTERNALSYM PCRE_NEWLINE_CR}
+  PCRE_NEWLINE_LF = $00200000;
+  {$EXTERNALSYM PCRE_NEWLINE_LF}
+  PCRE_NEWLINE_CRLF = $00300000;
+  {$EXTERNALSYM PCRE_NEWLINE_CRLF}
+  PCRE_NEWLINE_ANY = $00400000;
+  {$EXTERNALSYM PCRE_NEWLINE_ANY}
+  PCRE_NEWLINE_ANYCRLF = $00500000;
+  {$EXTERNALSYM PCRE_NEWLINE_ANYCRLF}
+  PCRE_BSR_ANYCRLF = $00800000;
+  {$EXTERNALSYM PCRE_BSR_ANYCRLF}
+  PCRE_BSR_UNICODE = $01000000;
+  {$EXTERNALSYM PCRE_BSR_UNICODE}
+  PCRE_JAVASCRIPT_COMPAT = $02000000;
+  {$EXTERNALSYM PCRE_JAVASCRIPT_COMPAT}
+  PCRE_NO_START_OPTIMIZE = $04000000;
+  {$EXTERNALSYM PCRE_NO_START_OPTIMIZE}
+  PCRE_NO_START_OPTIMISE = $04000000;
+  {$EXTERNALSYM PCRE_NO_START_OPTIMISE}
+  PCRE_PARTIAL_HARD = $08000000;
+  {$EXTERNALSYM PCRE_PARTIAL_HARD}
+  PCRE_NOTEMPTY_ATSTART = $10000000;
+  {$EXTERNALSYM PCRE_NOTEMPTY_ATSTART}
+
+  (* Exec-time and get-time error codes *)
+
+  PCRE_ERROR_NOMATCH = -1;
+  {$EXTERNALSYM PCRE_ERROR_NOMATCH}
+  PCRE_ERROR_NULL = -2;
+  {$EXTERNALSYM PCRE_ERROR_NULL}
+  PCRE_ERROR_BADOPTION = -3;
+  {$EXTERNALSYM PCRE_ERROR_BADOPTION}
+  PCRE_ERROR_BADMAGIC = -4;
+  {$EXTERNALSYM PCRE_ERROR_BADMAGIC}
+  PCRE_ERROR_UNKNOWN_NODE = -5;
+  {$EXTERNALSYM PCRE_ERROR_UNKNOWN_NODE}
+  PCRE_ERROR_NOMEMORY = -6;
+  {$EXTERNALSYM PCRE_ERROR_NOMEMORY}
+  PCRE_ERROR_NOSUBSTRING = -7;
+  {$EXTERNALSYM PCRE_ERROR_NOSUBSTRING}
+  PCRE_ERROR_MATCHLIMIT = -8;
+  {$EXTERNALSYM PCRE_ERROR_MATCHLIMIT}
+  PCRE_ERROR_CALLOUT = -9;  (* Never used by PCRE itself *)
+  {$EXTERNALSYM PCRE_ERROR_CALLOUT}
+  PCRE_ERROR_BADUTF8 = -10;
+  {$EXTERNALSYM PCRE_ERROR_BADUTF8}
+  PCRE_ERROR_BADUTF8_OFFSET = -11;
+  {$EXTERNALSYM PCRE_ERROR_BADUTF8_OFFSET}
+  PCRE_ERROR_PARTIAL = -12;
+  {$EXTERNALSYM PCRE_ERROR_PARTIAL}
+  PCRE_ERROR_BADPARTIAL = -13;
+  {$EXTERNALSYM PCRE_ERROR_BADPARTIAL}
+  PCRE_ERROR_INTERNAL = -14;
+  {$EXTERNALSYM PCRE_ERROR_INTERNAL}
+  PCRE_ERROR_BADCOUNT = -15;
+  {$EXTERNALSYM PCRE_ERROR_BADCOUNT}
+  PCRE_ERROR_DFA_UITEM = -16;
+  {$EXTERNALSYM PCRE_ERROR_DFA_UITEM}
+  PCRE_ERROR_DFA_UCOND = -17;
+  {$EXTERNALSYM PCRE_ERROR_DFA_UCOND}
+  PCRE_ERROR_DFA_UMLIMIT = -18;
+  {$EXTERNALSYM PCRE_ERROR_DFA_UMLIMIT}
+  PCRE_ERROR_DFA_WSSIZE = -19;
+  {$EXTERNALSYM PCRE_ERROR_DFA_WSSIZE}
+  PCRE_ERROR_DFA_RECURSE = -20;
+  {$EXTERNALSYM PCRE_ERROR_DFA_RECURSE}
+  PCRE_ERROR_RECURSIONLIMIT = -21;
+  {$EXTERNALSYM PCRE_ERROR_RECURSIONLIMIT}
+  PCRE_ERROR_NULLWSLIMIT = -22;  (* No longer actually used *)
+  {$EXTERNALSYM PCRE_ERROR_NULLWSLIMIT}
+  PCRE_ERROR_BADNEWLINE = -23;
+  {$EXTERNALSYM PCRE_ERROR_BADNEWLINE}
+
+  (* Request types for pcre_fullinfo() *)
+
+  PCRE_INFO_OPTIONS = 0;
+  {$EXTERNALSYM PCRE_INFO_OPTIONS}
+  PCRE_INFO_SIZE = 1;
+  {$EXTERNALSYM PCRE_INFO_SIZE}
+  PCRE_INFO_CAPTURECOUNT = 2;
+  {$EXTERNALSYM PCRE_INFO_CAPTURECOUNT}
+  PCRE_INFO_BACKREFMAX = 3;
+  {$EXTERNALSYM PCRE_INFO_BACKREFMAX}
+  PCRE_INFO_FIRSTCHAR = 4;
+  {$EXTERNALSYM PCRE_INFO_FIRSTCHAR}
+  PCRE_INFO_FIRSTTABLE = 5;
+  {$EXTERNALSYM PCRE_INFO_FIRSTTABLE}
+  PCRE_INFO_LASTLITERAL = 6;
+  {$EXTERNALSYM PCRE_INFO_LASTLITERAL}
+  PCRE_INFO_NAMEENTRYSIZE = 7;
+  {$EXTERNALSYM PCRE_INFO_NAMEENTRYSIZE}
+  PCRE_INFO_NAMECOUNT = 8;
+  {$EXTERNALSYM PCRE_INFO_NAMECOUNT}
+  PCRE_INFO_NAMETABLE = 9;
+  {$EXTERNALSYM PCRE_INFO_NAMETABLE}
+  PCRE_INFO_STUDYSIZE = 10;
+  {$EXTERNALSYM PCRE_INFO_STUDYSIZE}
+  PCRE_INFO_DEFAULT_TABLES = 11;
+  {$EXTERNALSYM PCRE_INFO_DEFAULT_TABLES}
+  PCRE_INFO_OKPARTIAL = 12;
+  {$EXTERNALSYM PCRE_INFO_OKPARTIAL}
+  PCRE_INFO_JCHANGED = 13;
+  {$EXTERNALSYM PCRE_INFO_JCHANGED}
+  PCRE_INFO_HASCRORLF = 14;
+  {$EXTERNALSYM PCRE_INFO_HASCRORLF}
+  PCRE_INFO_MINLENGTH = 15;
+  {$EXTERNALSYM PCRE_INFO_MINLENGTH}
+
+  (* Request types for pcre_config() *)
+  PCRE_CONFIG_UTF8 = 0;
+  {$EXTERNALSYM PCRE_CONFIG_UTF8}
+  PCRE_CONFIG_NEWLINE = 1;
+  {$EXTERNALSYM PCRE_CONFIG_NEWLINE}
+  PCRE_CONFIG_LINK_SIZE = 2;
+  {$EXTERNALSYM PCRE_CONFIG_LINK_SIZE}
+  PCRE_CONFIG_POSIX_MALLOC_THRESHOLD = 3;
+  {$EXTERNALSYM PCRE_CONFIG_POSIX_MALLOC_THRESHOLD}
+  PCRE_CONFIG_MATCH_LIMIT = 4;
+  {$EXTERNALSYM PCRE_CONFIG_MATCH_LIMIT}
+  PCRE_CONFIG_STACKRECURSE = 5;
+  {$EXTERNALSYM PCRE_CONFIG_STACKRECURSE}
+  PCRE_CONFIG_UNICODE_PROPERTIES = 6;
+  {$EXTERNALSYM PCRE_CONFIG_UNICODE_PROPERTIES}
+  PCRE_CONFIG_MATCH_LIMIT_RECURSION = 7;
+  {$EXTERNALSYM PCRE_CONFIG_MATCH_LIMIT_RECURSION}
+  PCRE_CONFIG_BSR = 8;
+  {$EXTERNALSYM PCRE_CONFIG_BSR}
+
+  (* Bit flags for the pcre_extra structure *)
+
+  PCRE_EXTRA_STUDY_DATA = $0001;
+  {$EXTERNALSYM PCRE_EXTRA_STUDY_DATA}
+  PCRE_EXTRA_MATCH_LIMIT = $0002;
+  {$EXTERNALSYM PCRE_EXTRA_MATCH_LIMIT}
+  PCRE_EXTRA_CALLOUT_DATA = $0004;
+  {$EXTERNALSYM PCRE_EXTRA_CALLOUT_DATA}
+  PCRE_EXTRA_TABLES = $0008;
+  {$EXTERNALSYM PCRE_EXTRA_TABLES}
+  PCRE_EXTRA_MATCH_LIMIT_RECURSION = $0010;
+  {$EXTERNALSYM PCRE_EXTRA_MATCH_LIMIT_RECURSION}
+
+type
+  {$IFNDEF FPC}
+  {$IFDEF CPU64}
+  SizeInt = Int64;
+  {$ELSE ~CPU64}
+  SizeInt = Integer;
+  {$ENDIF ~CPU64}
+  PPAnsiChar = ^PAnsiChar;
+  {$ENDIF ~FPC}
+  PPPAnsiChar = ^PPAnsiChar;
+
+  real_pcre = packed record
+    {magic_number: Longword;
+    size: Integer;
+    tables: PAnsiChar;
+    options: Longword;
+    top_bracket: Word;
+    top_backref: word;
+    first_char: PAnsiChar;
+    req_char: PAnsiChar;
+    code: array [0..0] of AnsiChar;}
+  end;
+  TPCRE = real_pcre;
+  PPCRE = ^TPCRE;
+
+  real_pcre_extra = packed record
+    {options: PAnsiChar;
+    start_bits: array [0..31] of AnsiChar;}
+    flags: Cardinal;        (* Bits for which fields are set *)
+    study_data: Pointer;    (* Opaque data from pcre_study() *)
+    match_limit: Cardinal;  (* Maximum number of calls to match() *)
+    callout_data: Pointer;  (* Data passed back in callouts *)
+    tables: PAnsiChar;      (* Pointer to character tables *)
+    match_limit_recursion: Cardinal; (* Max recursive calls to match() *)
+  end;
+  TPCREExtra = real_pcre_extra;
+  PPCREExtra = ^TPCREExtra;
+
+  pcre_callout_block = packed record
+    version: Integer;           (* Identifies version of block *)
+  (* ------------------------ Version 0 ------------------------------- *)
+    callout_number: Integer;    (* Number compiled into pattern *)
+    offset_vector: PInteger;    (* The offset vector *)
+    subject: PAnsiChar;         (* The subject being matched *)
+    subject_length: Integer;    (* The length of the subject *)
+    start_match: Integer;       (* Offset to start of this match attempt *)
+    current_position: Integer;  (* Where we currently are in the subject *)
+    capture_top: Integer;       (* Max current capture *)
+    capture_last: Integer;      (* Most recently closed capture *)
+    callout_data: Pointer;      (* Data passed in with the call *)
+  (* ------------------- Added for Version 1 -------------------------- *)
+    pattern_position: Integer;  (* Offset to next item in the pattern *)
+    next_item_length: Integer;  (* Length of next item in the pattern *)
+  (* ------------------------------------------------------------------ *)
+  end;
+
+  pcre_malloc_callback = function(Size: SizeInt): Pointer; cdecl;
+  {$EXTERNALSYM pcre_malloc_callback}
+  pcre_free_callback = procedure(P: Pointer); cdecl;
+  {$EXTERNALSYM pcre_free_callback}
+  pcre_stack_malloc_callback = function(Size: SizeInt): Pointer; cdecl;
+  {$EXTERNALSYM pcre_stack_malloc_callback}
+  pcre_stack_free_callback = procedure(P: Pointer); cdecl;
+  {$EXTERNALSYM pcre_stack_free_callback}
+  pcre_callout_callback = function(var callout_block: pcre_callout_block): Integer; cdecl;
+  {$EXTERNALSYM pcre_callout_callback}
+
+var
+  // renamed from "pcre_X" to "pcre_X_func" to allow functions with name "pcre_X" to be
+  // declared in implementation when static linked
+  pcre_malloc_func: ^pcre_malloc_callback = nil;
+  {$EXTERNALSYM pcre_malloc_func}
+  pcre_free_func: ^pcre_free_callback = nil;
+  {$EXTERNALSYM pcre_free_func}
+  pcre_stack_malloc_func: ^pcre_stack_malloc_callback = nil;
+  {$EXTERNALSYM pcre_stack_malloc_func}
+  pcre_stack_free_func: ^pcre_stack_free_callback = nil;
+  {$EXTERNALSYM pcre_stack_free_func}
+  pcre_callout_func: ^pcre_callout_callback = nil;
+  {$EXTERNALSYM pcre_callout_func}
+
+procedure SetPCREMallocCallback(const Value: pcre_malloc_callback);
+{$EXTERNALSYM SetPCREMallocCallback}
+function GetPCREMallocCallback: pcre_malloc_callback;
+{$EXTERNALSYM GetPCREMallocCallback}
+function CallPCREMalloc(Size: SizeInt): Pointer;
+{$EXTERNALSYM CallPCREMalloc}
+
+procedure SetPCREFreeCallback(const Value: pcre_free_callback);
+{$EXTERNALSYM SetPCREFreeCallback}
+function GetPCREFreeCallback: pcre_free_callback;
+{$EXTERNALSYM GetPCREFreeCallback}
+procedure CallPCREFree(P: Pointer);
+{$EXTERNALSYM CallPCREFree}
+
+procedure SetPCREStackMallocCallback(const Value: pcre_stack_malloc_callback);
+{$EXTERNALSYM SetPCREStackMallocCallback}
+function GetPCREStackMallocCallback: pcre_stack_malloc_callback;
+{$EXTERNALSYM GetPCREStackMallocCallback}
+function CallPCREStackMalloc(Size: SizeInt): Pointer;
+{$EXTERNALSYM CallPCREStackMalloc}
+
+procedure SetPCREStackFreeCallback(const Value: pcre_stack_free_callback);
+{$EXTERNALSYM SetPCREStackFreeCallback}
+function GetPCREStackFreeCallback: pcre_stack_free_callback;
+{$EXTERNALSYM GetPCREStackFreeCallback}
+procedure CallPCREStackFree(P: Pointer);
+{$EXTERNALSYM CallPCREStackFree}
+
+procedure SetPCRECalloutCallback(const Value: pcre_callout_callback);
+{$EXTERNALSYM SetPCRECalloutCallback}
+function GetPCRECalloutCallback: pcre_callout_callback;
+{$EXTERNALSYM GetPCRECalloutCallback}
+function CallPCRECallout(var callout_block: pcre_callout_block): Integer;
+{$EXTERNALSYM CallPCRECallout}
+
+type
+  TPCRELibNotLoadedHandler = procedure; cdecl;
+
+var
+  // Value to initialize function pointers below with, in case LoadPCRE fails
+  // or UnloadPCRE is called.  Typically the handler will raise an exception.
+  LibNotLoadedHandler: TPCRELibNotLoadedHandler = nil;
+
+(* Functions *)
+
+// dynamic dll import
+type
+  pcre_compile_func = function(const pattern: PAnsiChar; options: Integer;
+    const errptr: PPAnsiChar; erroffset: PInteger; const tableptr: PAnsiChar): PPCRE;
+    cdecl;
+  {$EXTERNALSYM pcre_compile_func}
+  pcre_compile2_func = function(const pattern: PAnsiChar; options: Integer;
+    const errorcodeptr: PInteger; const errorptr: PPAnsiChar; erroroffset: PInteger;
+    const tables: PAnsiChar): PPCRE; cdecl;
+  {$EXTERNALSYM pcre_compile2_func}
+  pcre_config_func = function(what: Integer; where: Pointer): Integer;
+  cdecl;
+  {$EXTERNALSYM pcre_config_func}
+  pcre_copy_named_substring_func = function(const code: PPCRE; const subject: PAnsiChar;
+    ovector: PInteger; stringcount: Integer; const stringname: PAnsiChar;
+    buffer: PAnsiChar; size: Integer): Integer; cdecl;
+  {$EXTERNALSYM pcre_copy_named_substring_func}
+  pcre_copy_substring_func = function(const subject: PAnsiChar; ovector: PInteger;
+    stringcount, stringnumber: Integer; buffer: PAnsiChar; buffersize: Integer): Integer;
+    cdecl;
+  {$EXTERNALSYM pcre_copy_substring_func}
+  pcre_dfa_exec_func = function(const argument_re: PPCRE; const extra_data: PPCREExtra;
+    const subject: PAnsiChar; length: Integer; start_offset: Integer;
+    options: Integer; offsets: PInteger; offsetcount: Integer; workspace: PInteger;
+    wscount: Integer): Integer; cdecl;
+  {$EXTERNALSYM pcre_dfa_exec_func}
+  pcre_exec_func = function(const code: PPCRE; const extra: PPCREExtra; const subject: PAnsiChar;
+    length, startoffset, options: Integer; ovector: PInteger; ovecsize: Integer): Integer;
+    cdecl;
+  {$EXTERNALSYM pcre_exec_func}
+  pcre_free_substring_func = procedure(stringptr: PAnsiChar);
+    cdecl;
+  {$EXTERNALSYM pcre_free_substring_func}
+  pcre_free_substring_list_func = procedure(stringptr: PPAnsiChar);
+    cdecl;
+  {$EXTERNALSYM pcre_free_substring_list_func}
+  pcre_fullinfo_func = function(const code: PPCRE; const extra: PPCREExtra;
+    what: Integer; where: Pointer): Integer;
+    cdecl;
+  {$EXTERNALSYM pcre_fullinfo_func}
+  pcre_get_named_substring_func = function(const code: PPCRE; const subject: PAnsiChar;
+    ovector: PInteger; stringcount: Integer; const stringname: PAnsiChar;
+    const stringptr: PPAnsiChar): Integer; cdecl;
+  {$EXTERNALSYM pcre_get_named_substring_func}
+  pcre_get_stringnumber_func = function(const code: PPCRE;
+    const stringname: PAnsiChar): Integer; cdecl;
+  {$EXTERNALSYM pcre_get_stringnumber_func}
+  pcre_get_stringtable_entries_func = function(const code: PPCRE; const stringname: PAnsiChar;
+    firstptr: PPAnsiChar; lastptr: PPAnsiChar): Integer;
+    cdecl;
+  {$EXTERNALSYM pcre_get_stringtable_entries_func}
+  pcre_get_substring_func = function(const subject: PAnsiChar; ovector: PInteger;
+    stringcount, stringnumber: Integer; const stringptr: PPAnsiChar): Integer;
+    cdecl;
+  {$EXTERNALSYM pcre_get_substring_func}
+  pcre_get_substring_list_func = function(const subject: PAnsiChar; ovector: PInteger;
+    stringcount: Integer; listptr: PPPAnsiChar): Integer;
+    cdecl;
+  {$EXTERNALSYM pcre_get_substring_list_func}
+  pcre_info_func = function(const code: PPCRE; optptr, firstcharptr: PInteger): Integer;
+  cdecl;
+  {$EXTERNALSYM pcre_info_func}
+  pcre_maketables_func = function: PAnsiChar; cdecl;
+  {$EXTERNALSYM pcre_maketables_func}
+  pcre_refcount_func = function(argument_re: PPCRE; adjust: Integer): Integer;
+  cdecl;
+  {$EXTERNALSYM pcre_refcount_func}
+  pcre_study_func = function(const code: PPCRE; options: Integer; const errptr: PPAnsiChar): PPCREExtra;
+  cdecl;
+  {$EXTERNALSYM pcre_study_func}
+  pcre_version_func = function: PAnsiChar; cdecl;
+  {$EXTERNALSYM pcre_version_func}
+
+var
+  pcre_compile: pcre_compile_func = nil;
+  {$EXTERNALSYM pcre_compile}
+  pcre_compile2: pcre_compile2_func = nil;
+  {$EXTERNALSYM pcre_compile2}
+  pcre_config: pcre_config_func = nil;
+  {$EXTERNALSYM pcre_config}
+  pcre_copy_named_substring: pcre_copy_named_substring_func = nil;
+  {$EXTERNALSYM pcre_copy_named_substring}
+  pcre_copy_substring: pcre_copy_substring_func = nil;
+  {$EXTERNALSYM pcre_copy_substring}
+  pcre_dfa_exec: pcre_dfa_exec_func = nil;
+  {$EXTERNALSYM pcre_dfa_exec}
+  pcre_exec: pcre_exec_func = nil;
+  {$EXTERNALSYM pcre_exec}
+  pcre_free_substring: pcre_free_substring_func = nil;
+  {$EXTERNALSYM pcre_free_substring}
+  pcre_free_substring_list: pcre_free_substring_list_func = nil;
+  {$EXTERNALSYM pcre_free_substring_list}
+  pcre_fullinfo: pcre_fullinfo_func = nil;
+  {$EXTERNALSYM pcre_fullinfo}
+  pcre_get_named_substring: pcre_get_named_substring_func = nil;
+  {$EXTERNALSYM pcre_get_named_substring}
+  pcre_get_stringnumber: pcre_get_stringnumber_func = nil;
+  {$EXTERNALSYM pcre_get_stringnumber}
+  pcre_get_stringtable_entries: pcre_get_stringtable_entries_func = nil;
+  {$EXTERNALSYM pcre_get_stringtable_entries}
+  pcre_get_substring: pcre_get_substring_func = nil;
+  {$EXTERNALSYM pcre_get_substring}
+  pcre_get_substring_list: pcre_get_substring_list_func = nil;
+  {$EXTERNALSYM pcre_get_substring_list}
+  pcre_info: pcre_info_func = nil;
+  {$EXTERNALSYM pcre_info}
+  pcre_maketables: pcre_maketables_func = nil;
+  {$EXTERNALSYM pcre_maketables}
+  pcre_refcount: pcre_refcount_func = nil;
+  {$EXTERNALSYM pcre_refcount}
+  pcre_study: pcre_study_func = nil;
+  {$EXTERNALSYM pcre_study}
+  pcre_version: pcre_version_func = nil;
+  {$EXTERNALSYM pcre_version}
+
+function IsPCRELoaded: Boolean;
+function LoadPCRE: Boolean;
+procedure UnloadPCRE;
+
+implementation
+
+uses
+  SysUtils,
+  {$IFDEF DARWIN}
+  UConfig,
+  {$ENDIF DARWIN}  
+  {$IFDEF MSWINDOWS}
+  Windows;
+  {$ENDIF MSWINDOWS}
+  {$IFDEF UNIX}
+  {$IFDEF HAS_UNIT_TYPES}
+  Types,
+  {$ENDIF HAS_UNIT_TYPES}
+  {$IFDEF HAS_UNIT_LIBC}
+  Libc;
+  {$ELSE ~HAS_UNIT_LIBC}
+  dl;
+  {$ENDIF ~HAS_UNIT_LIBC}
+  {$ENDIF UNIX}
+
+type
+  {$IFDEF MSWINDOWS}
+  TModuleHandle = HINST;
+  {$ENDIF MSWINDOWS}
+  {$IFDEF LINUX}
+  TModuleHandle = Pointer;
+  {$ENDIF LINUX}
+  {$IFDEF DARWIN}
+  TModuleHandle = Pointer;
+  {$ENDIF DARWIN}
+
+const
+  {$IFDEF MSWINDOWS}
+  libpcremodulename = 'pcre3.dll';
+  {$ENDIF MSWINDOWS}
+  {$IFDEF LINUX}
+  libpcremodulename = 'libpcre.so.0';
+  {$ENDIF LINUX}
+  {$IFDEF DARWIN}
+  libpcremodulename = 'libpcre.dylib';  // this is a symlink for example to libpcre.0.0.1.dylib
+  // the system resolves the symlink
+  libpcremodulenamefromfink = LIBPCRE_LIBDIR + '/' + libpcremodulename;
+  // the install command in the Makefile resolves the symlink, when installing libpcre.dylib in the app bundle
+  libpcremodulenamefromexecutable = '@executable_path/' + libpcremodulename;
+  {$ENDIF DARWIN}
+  PCRECompileExportName = 'pcre_compile';
+  PCRECompile2ExportName = 'pcre_compile2';
+  PCREConfigExportName = 'pcre_config';
+  PCRECopyNamedSubstringExportName = 'pcre_copy_named_substring';
+  PCRECopySubStringExportName = 'pcre_copy_substring';
+  PCREDfaExecExportName = 'pcre_dfa_exec';
+  PCREExecExportName = 'pcre_exec';
+  PCREFreeSubStringExportName = 'pcre_free_substring';
+  PCREFreeSubStringListExportName = 'pcre_free_substring_list';
+  PCREFullInfoExportName = 'pcre_fullinfo';
+  PCREGetNamedSubstringExportName = 'pcre_get_named_substring';
+  PCREGetStringNumberExportName = 'pcre_get_stringnumber';
+  PCREGetStringTableEntriesExportName = 'pcre_get_stringtable_entries';
+  PCREGetSubStringExportName = 'pcre_get_substring';
+  PCREGetSubStringListExportName = 'pcre_get_substring_list';
+  PCREInfoExportName = 'pcre_info';
+  PCREMakeTablesExportName = 'pcre_maketables';
+  PCRERefCountExportName = 'pcre_refcount';
+  PCREStudyExportName = 'pcre_study';
+  PCREVersionExportName = 'pcre_version';
+  PCREMallocExportName = 'pcre_malloc';
+  PCREFreeExportName = 'pcre_free';
+  PCREStackMallocExportName = 'pcre_stack_malloc';
+  PCREStackFreeExportName = 'pcre_stack_free';
+  PCRECalloutExportName = 'pcre_callout';
+  INVALID_MODULEHANDLE_VALUE = TModuleHandle(0);
+
+var
+  PCRELib: TModuleHandle = INVALID_MODULEHANDLE_VALUE;
+
+procedure SetPCREMallocCallback(const Value: pcre_malloc_callback);
+begin
+  if not Assigned(pcre_malloc_func) then
+    LoadPCRE;
+
+  if Assigned(pcre_malloc_func) then
+    pcre_malloc_func^ := Value
+  else if Assigned(LibNotLoadedHandler) then
+    LibNotLoadedHandler;
+end;
+
+function GetPCREMallocCallback: pcre_malloc_callback;
+begin
+  if not Assigned(pcre_malloc_func) then
+    LoadPCRE;
+
+  if not Assigned(pcre_malloc_func) then
+  begin
+    Result := nil;
+    if Assigned(LibNotLoadedHandler) then
+      LibNotLoadedHandler;
+  end
+  else
+    Result := pcre_malloc_func^;
+end;
+
+function CallPCREMalloc(Size: SizeInt): Pointer;
+begin
+  Result := pcre_malloc_func^(Size);
+end;
+
+procedure SetPCREFreeCallback(const Value: pcre_free_callback);
+begin
+  if not Assigned(pcre_free_func) then
+    LoadPCRE;
+
+  if Assigned(pcre_free_func) then
+    pcre_free_func^ := Value
+  else if Assigned(LibNotLoadedHandler) then
+    LibNotLoadedHandler;
+end;
+
+function GetPCREFreeCallback: pcre_free_callback;
+begin
+  if not Assigned(pcre_free_func) then
+    LoadPCRE;
+
+  if not Assigned(pcre_free_func) then
+  begin
+    Result := nil;
+    if Assigned(LibNotLoadedHandler) then
+      LibNotLoadedHandler;
+  end
+  else
+    Result := pcre_free_func^
+end;
+
+procedure CallPCREFree(P: Pointer);
+begin
+  pcre_free_func^(P);
+end;
+
+procedure SetPCREStackMallocCallback(const Value: pcre_stack_malloc_callback);
+begin
+  if not Assigned(pcre_stack_malloc_func) then
+    LoadPCRE;
+
+  if Assigned(pcre_stack_malloc_func) then
+    pcre_stack_malloc_func^ := Value
+  else if Assigned(LibNotLoadedHandler) then
+    LibNotLoadedHandler;
+end;
+
+function GetPCREStackMallocCallback: pcre_stack_malloc_callback;
+begin
+  if not Assigned(pcre_stack_malloc_func) then
+    LoadPCRE;
+
+  if not Assigned(pcre_stack_malloc_func) then
+  begin
+    Result := nil;
+    if Assigned(LibNotLoadedHandler) then
+      LibNotLoadedHandler;
+  end
+  else
+    Result := pcre_stack_malloc_func^;
+end;
+
+function CallPCREStackMalloc(Size: SizeInt): Pointer;
+begin
+  Result := pcre_stack_malloc_func^(Size);
+end;
+
+procedure SetPCREStackFreeCallback(const Value: pcre_stack_free_callback);
+begin
+  if not Assigned(pcre_stack_free_func) then
+    LoadPCRE;
+
+  if Assigned(pcre_stack_free_func) then
+    pcre_stack_free_func^ := Value
+  else if Assigned(LibNotLoadedHandler) then
+    LibNotLoadedHandler;
+end;
+
+function GetPCREStackFreeCallback: pcre_stack_free_callback;
+begin
+  if not Assigned(pcre_stack_free_func) then
+    LoadPCRE;
+
+  if not Assigned(pcre_stack_free_func) then
+  begin
+    Result := nil;
+    if Assigned(LibNotLoadedHandler) then
+      LibNotLoadedHandler;
+  end
+  else
+    Result := pcre_stack_free_func^;
+end;
+
+procedure CallPCREStackFree(P: Pointer);
+begin
+  pcre_stack_free_func^(P);
+end;
+
+procedure SetPCRECalloutCallback(const Value: pcre_callout_callback);
+begin
+  if not Assigned(pcre_callout_func) then
+    LoadPCRE;
+
+  if Assigned(pcre_callout_func) then
+    pcre_callout_func^ := Value
+  else if Assigned(LibNotLoadedHandler) then
+    LibNotLoadedHandler;
+end;
+
+function GetPCRECalloutCallback: pcre_callout_callback;
+begin
+  if not Assigned(pcre_callout_func) then
+    LoadPCRE;
+
+  if not Assigned(pcre_callout_func) then
+  begin
+    Result := nil;
+    if Assigned(LibNotLoadedHandler) then
+      LibNotLoadedHandler;
+  end
+  else
+    Result := pcre_callout_func^;
+end;
+
+function CallPCRECallout(var callout_block: pcre_callout_block): Integer;
+begin
+  Result := pcre_callout_func^(callout_block);
+end;
+
+procedure InitPCREFuncPtrs(const Value: Pointer);
+begin
+  @pcre_compile := Value;
+  @pcre_compile2 := Value;
+  @pcre_config := Value;
+  @pcre_copy_named_substring := Value;
+  @pcre_copy_substring := Value;
+  @pcre_dfa_exec := Value;
+  @pcre_exec := Value;
+  @pcre_free_substring := Value;
+  @pcre_free_substring_list := Value;
+  @pcre_fullinfo := Value;
+  @pcre_get_named_substring := Value;
+  @pcre_get_stringnumber := Value;
+  @pcre_get_stringtable_entries := Value;
+  @pcre_get_substring := Value;
+  @pcre_get_substring_list := Value;
+  @pcre_info := Value;
+  @pcre_maketables := Value;
+  @pcre_refcount := Value;
+  @pcre_study := Value;
+  @pcre_version := Value;
+  pcre_malloc_func := nil;
+  pcre_free_func := nil;
+  pcre_stack_malloc_func := nil;
+  pcre_stack_free_func := nil;
+  pcre_callout_func := nil;
+end;
+
+function IsPCRELoaded: Boolean;
+begin
+  Result := PCRELib <> INVALID_MODULEHANDLE_VALUE;
+end;
+
+function LoadPCRE: Boolean;
+  function GetSymbol(SymbolName: PAnsiChar): Pointer;
+  begin
+    {$IFDEF MSWINDOWS}
+    Result := GetProcAddress(PCRELib, SymbolName);
+    {$ENDIF MSWINDOWS}
+    {$IFDEF UNIX}
+    Result := dlsym(PCRELib, SymbolName);
+    {$ENDIF UNIX}
+  end;
+
+begin
+  Result := PCRELib <> INVALID_MODULEHANDLE_VALUE;
+  if Result then
+    Exit;
+
+  if PCRELib = INVALID_MODULEHANDLE_VALUE then
+    {$IFDEF MSWINDOWS}
+    PCRELib := SafeLoadLibrary(libpcremodulename);
+    {$ENDIF MSWINDOWS}
+    {$IFDEF UNIX}
+    PCRELib := dlopen(PAnsiChar(libpcremodulename), RTLD_NOW);
+    {$ENDIF UNIX}
+    
+  {$IFDEF DARWIN}  // if libpcre.dylib is not found, first try from the executable path and finally from the fink path
+  if PCRELib = INVALID_MODULEHANDLE_VALUE then
+    PCRELib := dlopen(PAnsiChar(libpcremodulenamefromexecutable), RTLD_NOW);
+  if PCRELib = INVALID_MODULEHANDLE_VALUE then
+    PCRELib := dlopen(PAnsiChar(libpcremodulenamefromfink), RTLD_NOW);
+  {$ENDIF DARWIN}
+
+  Result := PCRELib <> INVALID_MODULEHANDLE_VALUE;
+  if Result then
+  begin
+    @pcre_compile := GetSymbol(PCRECompileExportName);
+    @pcre_compile2 := GetSymbol(PCRECompile2ExportName);
+    @pcre_config := GetSymbol(PCREConfigExportName);
+    @pcre_copy_named_substring := GetSymbol(PCRECopyNamedSubstringExportName);
+    @pcre_copy_substring := GetSymbol(PCRECopySubStringExportName);
+    @pcre_dfa_exec := GetSymbol(PCREDfaExecExportName);
+    @pcre_exec := GetSymbol(PCREExecExportName);
+    @pcre_free_substring := GetSymbol(PCREFreeSubStringExportName);
+    @pcre_free_substring_list := GetSymbol(PCREFreeSubStringListExportName);
+    @pcre_fullinfo := GetSymbol(PCREFullInfoExportName);
+    @pcre_get_named_substring := GetSymbol(PCREGetNamedSubstringExportName);
+    @pcre_get_stringnumber := GetSymbol(PCREGetStringNumberExportName);
+    @pcre_get_stringtable_entries := GetSymbol(PCREGetStringTableEntriesExportName);
+    @pcre_get_substring := GetSymbol(PCREGetSubStringExportName);
+    @pcre_get_substring_list := GetSymbol(PCREGetSubStringListExportName);
+    @pcre_info := GetSymbol(PCREInfoExportName);
+    @pcre_maketables := GetSymbol(PCREMakeTablesExportName);
+    @pcre_refcount := GetSymbol(PCRERefCountExportName);
+    @pcre_study := GetSymbol(PCREStudyExportName);
+    @pcre_version := GetSymbol(PCREVersionExportName);
+    pcre_malloc_func := GetSymbol(PCREMallocExportName);
+    pcre_free_func := GetSymbol(PCREFreeExportName);
+    pcre_stack_malloc_func := GetSymbol(PCREStackMallocExportName);
+    pcre_stack_free_func := GetSymbol(PCREStackFreeExportName);
+    pcre_callout_func := GetSymbol(PCRECalloutExportName);
+  end
+  else
+    InitPCREFuncPtrs(@LibNotLoadedHandler);
+end;
+
+procedure UnloadPCRE;
+begin
+  if PCRELib <> INVALID_MODULEHANDLE_VALUE then
+    {$IFDEF MSWINDOWS}
+    FreeLibrary(PCRELib);
+    {$ENDIF MSWINDOWS}
+    {$IFDEF UNIX}
+    dlclose(Pointer(PCRELib));
+    {$ENDIF UNIX}
+  PCRELib := INVALID_MODULEHANDLE_VALUE;
+  InitPCREFuncPtrs(@LibNotLoadedHandler);
+end;
+
+(*
+function pcre_compile; external libpcremodulename name PCRECompileExportName;
+function pcre_compile2; external libpcremodulename name PCRECompile2ExportName;
+function pcre_config; external libpcremodulename name PCREConfigExportName;
+function pcre_copy_named_substring; external libpcremodulename name PCRECopyNamedSubStringExportName;
+function pcre_copy_substring; external libpcremodulename name PCRECopySubStringExportName;
+function pcre_dfa_exec; external libpcremodulename name PCREDfaExecExportName;
+function pcre_exec; external libpcremodulename name PCREExecExportName;
+procedure pcre_free_substring; external libpcremodulename name PCREFreeSubStringExportName;
+procedure pcre_free_substring_list; external libpcremodulename name PCREFreeSubStringListExportName;
+function pcre_fullinfo; external libpcremodulename name PCREFullInfoExportName;
+function pcre_get_named_substring; external libpcremodulename name PCREGetNamedSubStringExportName;
+function pcre_get_stringnumber; external libpcremodulename name PCREGetStringNumberExportName;
+function pcre_get_stringtable_entries; external libpcremodulename name PCREGetStringTableEntriesExportName;
+function pcre_get_substring; external libpcremodulename name PCREGetSubStringExportName;
+function pcre_get_substring_list; external libpcremodulename name PCREGetSubStringListExportName;
+function pcre_info; external libpcremodulename name PCREInfoExportName;
+function pcre_maketables; external libpcremodulename name PCREMakeTablesExportName;
+function pcre_refcount; external libpcremodulename name PCRERefCountExportName;
+function pcre_study; external libpcremodulename name PCREStudyExportName;
+function pcre_version; external libpcremodulename name PCREVersionExportName;
+*)
+
+end.
diff --git a/songmanagement/src/lib/portaudio/portaudio.pas b/songmanagement/src/lib/portaudio/portaudio.pas
new file mode 100644
index 00000000..ea7d06b7
--- /dev/null
+++ b/songmanagement/src/lib/portaudio/portaudio.pas
@@ -0,0 +1,1160 @@
+{*
+ * $Id: portaudio.h,v 1.7 2007/08/16 20:45:34 richardash1981 Exp $
+ * PortAudio Portable Real-Time Audio Library
+ * PortAudio API Header File
+ * Latest version available at: http://www.portaudio.com/
+ *
+ * Copyright (c) 1999-2002 Ross Bencina and Phil Burk
+ *                                                 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *}
+
+{*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ *}
+
+{** @file
+ @brief The PortAudio API.
+*}
+
+unit portaudio;
+
+{$IFDEF FPC}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+  {$MODE DELPHI }
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+interface
+
+uses
+  ctypes;
+
+const
+{$IF Defined(MSWINDOWS)}
+  LibName = 'portaudio_x86.dll';
+{$ELSEIF Defined(DARWIN)}
+  // this is for portaudio version 19
+  LibName = 'libportaudio.2.dylib';
+  {$LINKLIB libportaudio.2}
+{$ELSEIF Defined(UNIX)}
+  LibName = 'libportaudio.so';
+{$IFEND}
+
+{** Retrieve the release number of the currently running PortAudio build,
+ eg 1900.
+*}
+function Pa_GetVersion(): cint; cdecl; external LibName;
+
+
+{** Retrieve a textual description of the current PortAudio build,
+ eg "PortAudio V19-devel 13 October 2002".
+*}
+function Pa_GetVersionText(): PChar; cdecl; external LibName;
+
+
+{** Error codes returned by PortAudio functions.
+ Note that with the exception of paNoError, all PaErrorCodes are negative.
+*}
+
+type TPaError = cint;
+type TPaErrorCode = {enum}cint; const
+{enum_begin PaErrorCode}
+    paNoError = 0;
+
+    paNotInitialized = -10000;
+    paUnanticipatedHostError                = (paNotInitialized+ 1);
+    paInvalidChannelCount                   = (paNotInitialized+ 2);
+    paInvalidSampleRate                     = (paNotInitialized+ 3);
+    paInvalidDevice                         = (paNotInitialized+ 4);
+    paInvalidFlag                           = (paNotInitialized+ 5);
+    paSampleFormatNotSupported              = (paNotInitialized+ 6);
+    paBadIODeviceCombination                = (paNotInitialized+ 7);
+    paInsufficientMemory                    = (paNotInitialized+ 8);
+    paBufferTooBig                          = (paNotInitialized+ 9);
+    paBufferTooSmall                        = (paNotInitialized+10);
+    paNullCallback                          = (paNotInitialized+11);
+    paBadStreamPtr                          = (paNotInitialized+12);
+    paTimedOut                              = (paNotInitialized+13);
+    paInternalError                         = (paNotInitialized+14);
+    paDeviceUnavailable                     = (paNotInitialized+15);
+    paIncompatibleHostApiSpecificStreamInfo = (paNotInitialized+16);
+    paStreamIsStopped                       = (paNotInitialized+17);
+    paStreamIsNotStopped                    = (paNotInitialized+18);
+    paInputOverflowed                       = (paNotInitialized+19);
+    paOutputUnderflowed                     = (paNotInitialized+20);
+    paHostApiNotFound                       = (paNotInitialized+21); // The notes below are from the 
+    paInvalidHostApi                        = (paNotInitialized+22); // original file portaudio.h
+    paCanNotReadFromACallbackStream         = (paNotInitialized+23); {**< @todo review error code name *}
+    paCanNotWriteToACallbackStream          = (paNotInitialized+24); {**< @todo review error code name *}
+    paCanNotReadFromAnOutputOnlyStream      = (paNotInitialized+25); {**< @todo review error code name *}
+    paCanNotWriteToAnInputOnlyStream        = (paNotInitialized+26); {**< @todo review error code name *}
+    paIncompatibleStreamHostApi             = (paNotInitialized+27);
+    paBadBufferPtr                          = (paNotInitialized+28);
+{enum_end PaErrorCode}
+
+
+{** Translate the supplied PortAudio error code into a human readable
+ message.
+*}
+function Pa_GetErrorText( errorCode: TPaError ): PChar; cdecl; external LibName;
+
+
+{** Library initialization function - call this before using PortAudio.
+ This function initialises internal data structures and prepares underlying
+ host APIs for use.  With the exception of Pa_GetVersion(), Pa_GetVersionText(),
+ and Pa_GetErrorText(), this function MUST be called before using any other
+ PortAudio API functions.
+
+ If Pa_Initialize() is called multiple times, each successful
+ call must be matched with a corresponding call to Pa_Terminate(). 
+ Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not 
+ required to be fully nested.
+
+ Note that if Pa_Initialize() returns an error code, Pa_Terminate() should
+ NOT be called.
+
+ @return paNoError if successful, otherwise an error code indicating the cause
+ of failure.
+
+ @see Pa_Terminate
+*}
+function Pa_Initialize(): TPaError; cdecl; external LibName;
+
+
+{** Library termination function - call this when finished using PortAudio.
+ This function deallocates all resources allocated by PortAudio since it was
+ initializied by a call to Pa_Initialize(). In cases where Pa_Initialise() has
+ been called multiple times, each call must be matched with a corresponding call
+ to Pa_Terminate(). The final matching call to Pa_Terminate() will automatically
+ close any PortAudio streams that are still open.
+
+ Pa_Terminate() MUST be called before exiting a program which uses PortAudio.
+ Failure to do so may result in serious resource leaks, such as audio devices
+ not being available until the next reboot.
+
+ @return paNoError if successful, otherwise an error code indicating the cause
+ of failure.
+ 
+ @see Pa_Initialize
+*}
+function Pa_Terminate(): TPaError; cdecl; external LibName;
+
+
+
+{** The type used to refer to audio devices. Values of this type usually
+ range from 0 to (Pa_GetDeviceCount()-1), and may also take on the PaNoDevice
+ and paUseHostApiSpecificDeviceSpecification values.
+
+ @see Pa_GetDeviceCount, paNoDevice, paUseHostApiSpecificDeviceSpecification
+*}
+type TPaDeviceIndex = cint;
+
+
+{** A special PaDeviceIndex value indicating that no device is available,
+ or should be used.
+
+ @see PaDeviceIndex
+*}
+const paNoDevice = TPaDeviceIndex(-1);
+
+
+{** A special PaDeviceIndex value indicating that the device(s) to be used
+ are specified in the host api specific stream info structure.
+
+ @see PaDeviceIndex
+*}
+const paUseHostApiSpecificDeviceSpecification = TPaDeviceIndex(-2);
+
+
+{* Host API enumeration mechanism *}
+
+{** The type used to enumerate to host APIs at runtime. Values of this type
+ range from 0 to (Pa_GetHostApiCount()-1).
+
+ @see Pa_GetHostApiCount
+*}
+type TPaHostApiIndex = cint;
+
+{** Retrieve the number of available host APIs. Even if a host API is
+ available it may have no devices available.
+
+ @return A non-negative value indicating the number of available host APIs
+ or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+
+ @see PaHostApiIndex
+*}
+function Pa_GetHostApiCount(): TPaHostApiIndex; cdecl; external LibName;
+
+
+{** Retrieve the index of the default host API. The default host API will be
+ the lowest common denominator host API on the current platform and is
+ unlikely to provide the best performance.
+
+ @return A non-negative value ranging from 0 to (Pa_GetHostApiCount()-1)
+ indicating the default host API index or, a PaErrorCode (which are always
+ negative) if PortAudio is not initialized or an error is encountered.
+*}
+function Pa_GetDefaultHostApi(): TPaHostApiIndex; cdecl; external LibName;
+
+
+{** Unchanging unique identifiers for each supported host API. This type
+ is used in the PaHostApiInfo structure. The values are guaranteed to be
+ unique and to never change, thus allowing code to be written that
+ conditionally uses host API specific extensions.
+
+ New type ids will be allocated when support for a host API reaches
+ "public alpha" status, prior to that developers should use the
+ paInDevelopment type id.
+
+ @see PaHostApiInfo
+*}
+type TPaHostApiTypeId = {enum}cint; const
+{enum_begin PaHostApiTypeId}
+    paInDevelopment=0; {* use while developing support for a new host API *}
+    paDirectSound=1;
+    paMME=2;
+    paASIO=3;
+    paSoundManager=4;
+    paCoreAudio=5;
+    paOSS=7;
+    paALSA=8;
+    paAL=9;
+    paBeOS=10;
+    paWDMKS=11;
+    paJACK=12;
+    paWASAPI=13;
+    paAudioScienceHPI=14;
+{enum_end PaHostApiTypeId}
+
+{** A structure containing information about a particular host API. *}
+
+type
+  PPaHostApiInfo = ^TPaHostApiInfo;
+  TPaHostApiInfo = record
+      {** this is struct version 1 *}
+      structVersion: cint;
+      {** The well known unique identifier of this host API @see PaHostApiTypeId *}
+      _type: TPaHostApiTypeId;
+      {** A textual description of the host API for display on user interfaces. *}
+      name: PChar;
+
+      {**  The number of devices belonging to this host API. This field may be
+       used in conjunction with Pa_HostApiDeviceIndexToDeviceIndex() to enumerate
+       all devices for this host API.
+       @see Pa_HostApiDeviceIndexToDeviceIndex
+      *}
+      deviceCount: cint;
+
+      {** The default input device for this host API. The value will be a
+       device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice
+       if no default input device is available.
+      *}
+      defaultInputDevice: TPaDeviceIndex;
+
+      {** The default output device for this host API. The value will be a
+       device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice
+       if no default output device is available.
+      *}
+      defaultOutputDevice: TPaDeviceIndex;
+  end;
+
+
+{** Retrieve a pointer to a structure containing information about a specific
+ host Api.
+
+ @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1)
+
+ @return A pointer to an immutable PaHostApiInfo structure describing
+ a specific host API. If the hostApi parameter is out of range or an error
+ is encountered, the function returns NULL.
+
+ The returned structure is owned by the PortAudio implementation and must not
+ be manipulated or freed. The pointer is only guaranteed to be valid between
+ calls to Pa_Initialize() and Pa_Terminate().
+*}
+function Pa_GetHostApiInfo( hostApi: TPaHostApiIndex ): PPaHostApiInfo; cdecl; external LibName;
+
+
+{** Convert a static host API unique identifier, into a runtime
+ host API index.
+
+ @param type A unique host API identifier belonging to the PaHostApiTypeId
+ enumeration.
+
+ @return A valid PaHostApiIndex ranging from 0 to (Pa_GetHostApiCount()-1) or,
+ a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+ 
+ The paHostApiNotFound error code indicates that the host API specified by the
+ type parameter is not available.
+
+ @see PaHostApiTypeId
+*}
+function Pa_HostApiTypeIdToHostApiIndex( _type: TPaHostApiTypeId ): TPaHostApiIndex; cdecl; external LibName;
+
+
+{** Convert a host-API-specific device index to standard PortAudio device index.
+ This function may be used in conjunction with the deviceCount field of
+ PaHostApiInfo to enumerate all devices for the specified host API.
+
+ @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1)
+
+ @param hostApiDeviceIndex A valid per-host device index in the range
+ 0 to (Pa_GetHostApiInfo(hostApi)->deviceCount-1)
+
+ @return A non-negative PaDeviceIndex ranging from 0 to (Pa_GetDeviceCount()-1)
+ or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+
+ A paInvalidHostApi error code indicates that the host API index specified by
+ the hostApi parameter is out of range.
+
+ A paInvalidDevice error code indicates that the hostApiDeviceIndex parameter
+ is out of range.
+ 
+ @see PaHostApiInfo
+*}
+function Pa_HostApiDeviceIndexToDeviceIndex( hostApi: TPaHostApiIndex;
+        hostApiDeviceIndex: cint ): TPaDeviceIndex; cdecl; external LibName;
+
+
+
+{** Structure used to return information about a host error condition.
+*}
+type
+  PPaHostErrorInfo = ^TPaHostErrorInfo;
+  TPaHostErrorInfo = record
+      hostApiType: TPaHostApiTypeId;    {**< the host API which returned the error code *}
+      errorCode: clong;                 {**< the error code returned *}
+      errorText: PChar;                 {**< a textual description of the error if available, otherwise a zero-length string *}
+  end;
+
+
+{** Return information about the last host error encountered. The error
+ information returned by Pa_GetLastHostErrorInfo() will never be modified
+ asyncronously by errors occurring in other PortAudio owned threads
+ (such as the thread that manages the stream callback.)
+
+ This function is provided as a last resort, primarily to enhance debugging
+ by providing clients with access to all available error information.
+
+ @return A pointer to an immutable structure constaining information about
+ the host error. The values in this structure will only be valid if a
+ PortAudio function has previously returned the paUnanticipatedHostError
+ error code.
+*}
+function Pa_GetLastHostErrorInfo(): PPaHostErrorInfo; cdecl; external LibName;
+
+
+
+{* Device enumeration and capabilities *}
+
+{** Retrieve the number of available devices. The number of available devices
+ may be zero.
+
+ @return A non-negative value indicating the number of available devices or,
+ a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+*}
+function Pa_GetDeviceCount(): TPaDeviceIndex; cdecl; external LibName;
+
+
+{** Retrieve the index of the default input device. The result can be
+ used in the inputDevice parameter to Pa_OpenStream().
+
+ @return The default input device index for the default host API, or paNoDevice
+ if no default input device is available or an error was encountered.
+*}
+function Pa_GetDefaultInputDevice(): TPaDeviceIndex; cdecl; external LibName;
+
+
+{** Retrieve the index of the default output device. The result can be
+ used in the outputDevice parameter to Pa_OpenStream().
+
+ @return The default output device index for the defualt host API, or paNoDevice
+ if no default output device is available or an error was encountered.
+
+ @note
+ On the PC, the user can specify a default device by
+ setting an environment variable. For example, to use device #1.
+<pre>
+ set PA_RECOMMENDED_OUTPUT_DEVICE=1
+</pre>
+ The user should first determine the available device ids by using
+ the supplied application "pa_devs".
+*}
+function Pa_GetDefaultOutputDevice(): TPaDeviceIndex; cdecl; external LibName;
+
+
+{** The type used to represent monotonic time in seconds that can be used
+ for syncronisation. The type is used for the outTime argument to the
+ PaStreamCallback and as the result of Pa_GetStreamTime().
+     
+ @see PaStreamCallback, Pa_GetStreamTime
+*}
+type TPaTime = cdouble;
+
+
+{** A type used to specify one or more sample formats. Each value indicates
+ a possible format for sound data passed to and from the stream callback,
+ Pa_ReadStream and Pa_WriteStream.
+
+ The standard formats paFloat32, paInt16, paInt32, paInt24, paInt8
+ and aUInt8 are usually implemented by all implementations.
+
+ The floating point representation (paFloat32) uses +1.0 and -1.0 as the
+ maximum and minimum respectively.
+
+ paUInt8 is an unsigned 8 bit format where 128 is considered "ground"
+
+ The paNonInterleaved flag indicates that a multichannel buffer is passed
+ as a set of non-interleaved pointers.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream, PaDeviceInfo
+ @see paFloat32, paInt16, paInt32, paInt24, paInt8
+ @see paUInt8, paCustomFormat, paNonInterleaved
+*}
+type TPaSampleFormat = culong;
+const
+  paFloat32        = TPaSampleFormat($00000001); {**< @see PaSampleFormat *}
+  paInt32          = TPaSampleFormat($00000002); {**< @see PaSampleFormat *}
+  paInt24          = TPaSampleFormat($00000004); {**< Packed 24 bit format. @see PaSampleFormat *}
+  paInt16          = TPaSampleFormat($00000008); {**< @see PaSampleFormat *}
+  paInt8           = TPaSampleFormat($00000010); {**< @see PaSampleFormat *}
+  paUInt8          = TPaSampleFormat($00000020); {**< @see PaSampleFormat *}
+  paCustomFormat   = TPaSampleFormat($00010000); {**< @see PaSampleFormat *}
+  paNonInterleaved = TPaSampleFormat($80000000);
+
+{** A structure providing information and capabilities of PortAudio devices.
+ Devices may support input, output or both input and output.
+*}
+type
+  PPaDeviceInfo = ^TPaDeviceInfo;
+  TPaDeviceInfo = record
+      structVersion: cint;  {* this is struct version 2 *}
+      name: PChar;
+      hostApi: TPaHostApiIndex; {* note this is a host API index, not a type id*}
+
+      maxInputChannels: cint;
+      maxOutputChannels: cint;
+
+      {* Default latency values for interactive performance. *}
+      defaultLowInputLatency: TPaTime;
+      defaultLowOutputLatency: TPaTime;
+      {* Default latency values for robust non-interactive applications (eg. playing sound files). *}
+      defaultHighInputLatency: TPaTime;
+      defaultHighOutputLatency: TPaTime;
+
+      defaultSampleRate: cdouble;
+  end;
+
+
+{** Retrieve a pointer to a PaDeviceInfo structure containing information
+ about the specified device.
+ @return A pointer to an immutable PaDeviceInfo structure. If the device
+ parameter is out of range the function returns NULL.
+
+ @param device A valid device index in the range 0 to (Pa_GetDeviceCount()-1)
+
+ @note PortAudio manages the memory referenced by the returned pointer,
+ the client must not manipulate or free the memory. The pointer is only
+ guaranteed to be valid between calls to Pa_Initialize() and Pa_Terminate().
+
+ @see PaDeviceInfo, PaDeviceIndex
+*}
+function Pa_GetDeviceInfo( device: TPaDeviceIndex ): PPaDeviceInfo; cdecl; external LibName;
+
+
+{** Parameters for one direction (input or output) of a stream.
+*}
+type
+  PPaStreamParameters = ^TPaStreamParameters;
+  TPaStreamParameters = record
+      {** A valid device index in the range 0 to (Pa_GetDeviceCount()-1)
+       specifying the device to be used or the special constant
+       paUseHostApiSpecificDeviceSpecification which indicates that the actual
+       device(s) to use are specified in hostApiSpecificStreamInfo.
+       This field must not be set to paNoDevice.
+      *}
+      device: TPaDeviceIndex;
+
+      {** The number of channels of sound to be delivered to the
+       stream callback or accessed by Pa_ReadStream() or Pa_WriteStream().
+       It can range from 1 to the value of maxInputChannels in the
+       PaDeviceInfo record for the device specified by the device parameter.
+      *}
+      channelCount: cint;
+
+      {** The sample format of the buffer provided to the stream callback,
+       a_ReadStream() or Pa_WriteStream(). It may be any of the formats described
+       by the PaSampleFormat enumeration.
+      *}
+      sampleFormat: TPaSampleFormat;
+
+      {** The desired latency in seconds. Where practical, implementations should
+       configure their latency based on these parameters, otherwise they may
+       choose the closest viable latency instead. Unless the suggested latency
+       is greater than the absolute upper limit for the device implementations
+       should round the suggestedLatency up to the next practial value - ie to
+       provide an equal or higher latency than suggestedLatency wherever possibe.
+       Actual latency values for an open stream may be retrieved using the
+       inputLatency and outputLatency fields of the PaStreamInfo structure
+       returned by Pa_GetStreamInfo().
+       @see default*Latency in PaDeviceInfo, *Latency in PaStreamInfo
+      *}
+      suggestedLatency: TPaTime;
+
+      {** An optional pointer to a host api specific data structure
+       containing additional information for device setup and/or stream processing.
+       hostApiSpecificStreamInfo is never required for correct operation,
+       if not used it should be set to NULL.
+      *}
+      hostApiSpecificStreamInfo: Pointer;
+  end;
+
+
+{** Return code for Pa_IsFormatSupported indicating success. *}
+const paFormatIsSupported = (0);
+
+{** Determine whether it would be possible to open a stream with the specified
+ parameters.
+
+ @param inputParameters A structure that describes the input parameters used to
+ open a stream. The suggestedLatency field is ignored. See PaStreamParameters
+ for a description of these parameters. inputParameters must be NULL for
+ output-only streams.
+
+ @param outputParameters A structure that describes the output parameters used
+ to open a stream. The suggestedLatency field is ignored. See PaStreamParameters
+ for a description of these parameters. outputParameters must be NULL for
+ input-only streams.
+
+ @param sampleRate The required sampleRate. For full-duplex streams it is the
+ sample rate for both input and output
+
+ @return Returns 0 if the format is supported, and an error code indicating why
+ the format is not supported otherwise. The constant paFormatIsSupported is
+ provided to compare with the return value for success.
+
+ @see paFormatIsSupported, PaStreamParameters
+*}
+function Pa_IsFormatSupported( inputParameters: PPaStreamParameters;
+                              outputParameters: PPaStreamParameters;
+                              sampleRate: cdouble ): TPaError; cdecl; external LibName;
+
+
+
+{* Streaming types and functions *}
+
+
+{**
+ A single PaStream can provide multiple channels of real-time
+ streaming audio input and output to a client application. A stream
+ provides access to audio hardware represented by one or more
+ PaDevices. Depending on the underlying Host API, it may be possible 
+ to open multiple streams using the same device, however this behavior 
+ is implementation defined. Portable applications should assume that 
+ a PaDevice may be simultaneously used by at most one PaStream.
+
+ Pointers to PaStream objects are passed between PortAudio functions that
+ operate on streams.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream, Pa_OpenDefaultStream, Pa_CloseStream,
+ Pa_StartStream, Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive,
+ Pa_GetStreamTime, Pa_GetStreamCpuLoad
+
+*}
+type
+  PPaStream = Pointer;
+
+{** Can be passed as the framesPerBuffer parameter to Pa_OpenStream()
+ or Pa_OpenDefaultStream() to indicate that the stream callback will
+ accept buffers of any size.
+*}
+const paFramesPerBufferUnspecified = (0);
+
+
+{** Flags used to control the behavior of a stream. They are passed as
+ parameters to Pa_OpenStream or Pa_OpenDefaultStream. Multiple flags may be
+ ORed together.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream
+ @see paNoFlag, paClipOff, paDitherOff, paNeverDropInput,
+  paPrimeOutputBuffersUsingStreamCallback, paPlatformSpecificFlags
+*}
+type TPaStreamFlags = culong;
+
+{** @see PaStreamFlags *}
+const   paNoFlag          = TPaStreamFlags(0);
+
+{** Disable default clipping of out of range samples.
+ @see PaStreamFlags
+*}
+const   paClipOff         = TPaStreamFlags($00000001);
+
+{** Disable default dithering.
+ @see PaStreamFlags
+*}
+const   paDitherOff       = TPaStreamFlags($00000002);
+
+{** Flag requests that where possible a full duplex stream will not discard
+ overflowed input samples without calling the stream callback. This flag is
+ only valid for full duplex callback streams and only when used in combination
+ with the paFramesPerBufferUnspecified (0) framesPerBuffer parameter. Using
+ this flag incorrectly results in a paInvalidFlag error being returned from
+ Pa_OpenStream and Pa_OpenDefaultStream.
+
+ @see PaStreamFlags, paFramesPerBufferUnspecified
+*}
+const   paNeverDropInput  = TPaStreamFlags($00000004);
+
+{** Call the stream callback to fill initial output buffers, rather than the
+ default behavior of priming the buffers with zeros (silence). This flag has
+ no effect for input-only and blocking read/write streams.
+ 
+ @see PaStreamFlags
+*}
+const   paPrimeOutputBuffersUsingStreamCallback = TPaStreamFlags($00000008);
+
+{** A mask specifying the platform specific bits.
+ @see PaStreamFlags
+*}
+const   paPlatformSpecificFlags = TPaStreamFlags($FFFF0000);
+
+{**
+ Timing information for the buffers passed to the stream callback.
+*}
+type
+  PPaStreamCallbackTimeInfo = ^TPaStreamCallbackTimeInfo;
+  TPaStreamCallbackTimeInfo = record
+      inputBufferAdcTime: TPaTime;
+      currentTime: TPaTime;
+      outputBufferDacTime: TPaTime;
+  end;
+
+
+{**
+ Flag bit constants for the statusFlags to PaStreamCallback.
+
+ @see paInputUnderflow, paInputOverflow, paOutputUnderflow, paOutputOverflow,
+ paPrimingOutput
+*}
+type TPaStreamCallbackFlags = culong;
+
+{** In a stream opened with paFramesPerBufferUnspecified, indicates that
+ input data is all silence (zeros) because no real data is available. In a
+ stream opened without paFramesPerBufferUnspecified, it indicates that one or
+ more zero samples have been inserted into the input buffer to compensate
+ for an input underflow.
+ @see PaStreamCallbackFlags
+*}
+const paInputUnderflow   = TPaStreamCallbackFlags($00000001);
+
+{** In a stream opened with paFramesPerBufferUnspecified, indicates that data
+ prior to the first sample of the input buffer was discarded due to an
+ overflow, possibly because the stream callback is using too much CPU time.
+ Otherwise indicates that data prior to one or more samples in the
+ input buffer was discarded.
+ @see PaStreamCallbackFlags
+*}
+const paInputOverflow    = TPaStreamCallbackFlags($00000002);
+
+{** Indicates that output data (or a gap) was inserted, possibly because the
+ stream callback is using too much CPU time.
+ @see PaStreamCallbackFlags
+*}
+const paOutputUnderflow  = TPaStreamCallbackFlags($00000004);
+
+{** Indicates that output data will be discarded because no room is available.
+ @see PaStreamCallbackFlags
+*}
+const paOutputOverflow   = TPaStreamCallbackFlags($00000008);
+
+{** Some of all of the output data will be used to prime the stream, input
+ data may be zero.
+ @see PaStreamCallbackFlags
+*}
+const paPrimingOutput    = TPaStreamCallbackFlags($00000010);
+
+{**
+ Allowable return values for the PaStreamCallback.
+ @see PaStreamCallback
+*}
+type TPaStreamCallbackResult = {enum}cint; const
+{enum_begin PaStreamCallbackResult}
+    paContinue=0;
+    paComplete=1;
+    paAbort=2;
+{enum_end PaStreamCallbackResult}
+
+{**
+ Functions of type PaStreamCallback are implemented by PortAudio clients.
+ They consume, process or generate audio in response to requests from an
+ active PortAudio stream.
+     
+ @param input and @param output are arrays of interleaved samples,
+ the format, packing and number of channels used by the buffers are
+ determined by parameters to Pa_OpenStream().
+     
+ @param frameCount The number of sample frames to be processed by
+ the stream callback.
+
+ @param timeInfo The time in seconds when the first sample of the input
+ buffer was received at the audio input, the time in seconds when the first
+ sample of the output buffer will begin being played at the audio output, and
+ the time in seconds when the stream callback was called.
+ See also Pa_GetStreamTime()
+
+ @param statusFlags Flags indicating whether input and/or output buffers
+ have been inserted or will be dropped to overcome underflow or overflow
+ conditions.
+
+ @param userData The value of a user supplied pointer passed to
+ Pa_OpenStream() intended for storing synthesis data etc.
+
+ @return
+ The stream callback should return one of the values in the
+ PaStreamCallbackResult enumeration. To ensure that the callback continues
+ to be called, it should return paContinue (0). Either paComplete or paAbort
+ can be returned to finish stream processing, after either of these values is
+ returned the callback will not be called again. If paAbort is returned the
+ stream will finish as soon as possible. If paComplete is returned, the stream
+ will continue until all buffers generated by the callback have been played.
+ This may be useful in applications such as soundfile players where a specific
+ duration of output is required. However, it is not necessary to utilise this
+ mechanism as Pa_StopStream(), Pa_AbortStream() or Pa_CloseStream() can also
+ be used to stop the stream. The callback must always fill the entire output
+ buffer irrespective of its return value.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream
+
+ @note With the exception of Pa_GetStreamCpuLoad() it is not permissable to call
+ PortAudio API functions from within the stream callback.
+*}
+type
+  PPaStreamCallback = ^TPaStreamCallback;
+  TPaStreamCallback = function(
+      input: Pointer; output: Pointer;
+      frameCount: culong;
+      timeInfo: PPaStreamCallbackTimeInfo;
+      statusFlags: TPaStreamCallbackFlags;
+      userData: Pointer ): cint; cdecl;
+
+
+{** Opens a stream for either input, output or both.
+     
+ @param stream The address of a PaStream pointer which will receive
+ a pointer to the newly opened stream.
+     
+ @param inputParameters A structure that describes the input parameters used by
+ the opened stream. See PaStreamParameters for a description of these parameters.
+ inputParameters must be NULL for output-only streams.
+
+ @param outputParameters A structure that describes the output parameters used by
+ the opened stream. See PaStreamParameters for a description of these parameters.
+ outputParameters must be NULL for input-only streams.
+ 
+ @param sampleRate The desired sampleRate. For full-duplex streams it is the
+ sample rate for both input and output
+
+ @param framesPerBuffer The number of frames passed to the stream callback
+ function, or the preferred block granularity for a blocking read/write stream.
+ The special value paFramesPerBufferUnspecified (0) may be used to request that
+ the stream callback will recieve an optimal (and possibly varying) number of
+ frames based on host requirements and the requested latency settings.
+ Note: With some host APIs, the use of non-zero framesPerBuffer for a callback
+ stream may introduce an additional layer of buffering which could introduce
+ additional latency. PortAudio guarantees that the additional latency
+ will be kept to the theoretical minimum however, it is strongly recommended
+ that a non-zero framesPerBuffer value only be used when your algorithm
+ requires a fixed number of frames per stream callback.
+ 
+ @param streamFlags Flags which modify the behaviour of the streaming process.
+ This parameter may contain a combination of flags ORed together. Some flags may
+ only be relevant to certain buffer formats.
+     
+ @param streamCallback A pointer to a client supplied function that is responsible
+ for processing and filling input and output buffers. If this parameter is NULL
+ the stream will be opened in 'blocking read/write' mode. In blocking mode,
+ the client can receive sample data using Pa_ReadStream and write sample data
+ using Pa_WriteStream, the number of samples that may be read or written
+ without blocking is returned by Pa_GetStreamReadAvailable and
+ Pa_GetStreamWriteAvailable respectively.
+
+ @param userData A client supplied pointer which is passed to the stream callback
+ function. It could for example, contain a pointer to instance data necessary
+ for processing the audio buffers. This parameter is ignored if streamCallback
+ is NULL.
+     
+ @return
+ Upon success Pa_OpenStream() returns paNoError and places a pointer to a
+ valid PaStream in the stream argument. The stream is inactive (stopped).
+ If a call to Pa_OpenStream() fails, a non-zero error code is returned (see
+ PaError for possible error codes) and the value of stream is invalid.
+
+ @see PaStreamParameters, PaStreamCallback, Pa_ReadStream, Pa_WriteStream,
+ Pa_GetStreamReadAvailable, Pa_GetStreamWriteAvailable
+*}
+function Pa_OpenStream( var stream: PPaStream;
+                       inputParameters: PPaStreamParameters;
+                       outputParameters: PPaStreamParameters;
+                       sampleRate: cdouble;
+                       framesPerBuffer: culong;
+                       streamFlags: TPaStreamFlags;
+                       streamCallback: PPaStreamCallback;
+                       userData: Pointer ): TPaError; cdecl; external LibName;
+
+
+{** A simplified version of Pa_OpenStream() that opens the default input
+ and/or output devices.
+
+ @param stream The address of a PaStream pointer which will receive
+ a pointer to the newly opened stream.
+ 
+ @param numInputChannels  The number of channels of sound that will be supplied
+ to the stream callback or returned by Pa_ReadStream. It can range from 1 to
+ the value of maxInputChannels in the PaDeviceInfo record for the default input
+ device. If 0 the stream is opened as an output-only stream.
+
+ @param numOutputChannels The number of channels of sound to be delivered to the
+ stream callback or passed to Pa_WriteStream. It can range from 1 to the value
+ of maxOutputChannels in the PaDeviceInfo record for the default output dvice.
+ If 0 the stream is opened as an output-only stream.
+
+ @param sampleFormat The sample format of both the input and output buffers
+ provided to the callback or passed to and from Pa_ReadStream and Pa_WriteStream.
+ sampleFormat may be any of the formats described by the PaSampleFormat
+ enumeration.
+ 
+ @param sampleRate Same as Pa_OpenStream parameter of the same name.
+ @param framesPerBuffer Same as Pa_OpenStream parameter of the same name.
+ @param streamCallback Same as Pa_OpenStream parameter of the same name.
+ @param userData Same as Pa_OpenStream parameter of the same name.
+
+ @return As for Pa_OpenStream
+
+ @see Pa_OpenStream, PaStreamCallback
+*}
+function Pa_OpenDefaultStream( var stream: PPaStream;
+                              numInputChannels: cint;
+                              numOutputChannels: cint;
+                              sampleFormat: TPaSampleFormat;
+                              sampleRate: cdouble;
+                              framesPerBuffer: culong;
+                              streamCallback: PPaStreamCallback;
+                              userData: Pointer ): TPaError; cdecl; external LibName;
+
+
+{** Closes an audio stream. If the audio stream is active it
+ discards any pending buffers as if Pa_AbortStream() had been called.
+*}
+function Pa_CloseStream( stream: PPaStream ): TPaError; cdecl; external LibName;
+
+
+{** Functions of type PaStreamFinishedCallback are implemented by PortAudio 
+ clients. They can be registered with a stream using the Pa_SetStreamFinishedCallback
+ function. Once registered they are called when the stream becomes inactive
+ (ie once a call to Pa_StopStream() will not block).
+ A stream will become inactive after the stream callback returns non-zero,
+ or when Pa_StopStream or Pa_AbortStream is called. For a stream providing audio
+ output, if the stream callback returns paComplete, or Pa_StopStream is called,
+ the stream finished callback will not be called until all generated sample data
+ has been played.
+ 
+ @param userData The userData parameter supplied to Pa_OpenStream()
+
+ @see Pa_SetStreamFinishedCallback
+*}
+type
+  PPaStreamFinishedCallback = ^TPaStreamFinishedCallback;
+  TPaStreamFinishedCallback = procedure( userData: Pointer ); cdecl;
+
+
+{** Register a stream finished callback function which will be called when the 
+ stream becomes inactive. See the description of PaStreamFinishedCallback for 
+ further details about when the callback will be called.
+
+ @param stream a pointer to a PaStream that is in the stopped state - if the
+ stream is not stopped, the stream's finished callback will remain unchanged 
+ and an error code will be returned.
+
+ @param streamFinishedCallback a pointer to a function with the same signature
+ as PaStreamFinishedCallback, that will be called when the stream becomes
+ inactive. Passing NULL for this parameter will un-register a previously
+ registered stream finished callback function.
+
+ @return on success returns paNoError, otherwise an error code indicating the cause
+ of the error.
+
+ @see PaStreamFinishedCallback
+*}
+function Pa_SetStreamFinishedCallback( stream: PPaStream;
+                streamFinishedCallback: PPaStreamFinishedCallback ): TPaError; cdecl; external LibName;
+
+
+{** Commences audio processing.
+*}
+function Pa_StartStream( stream: PPaStream ): TPaError; cdecl; external LibName;
+
+
+{** Terminates audio processing. It waits until all pending
+ audio buffers have been played before it returns.
+*}
+function Pa_StopStream( stream: PPaStream ): TPaError; cdecl; external LibName;
+
+
+{** Terminates audio processing immediately without waiting for pending
+ buffers to complete.
+*}
+function Pa_AbortStream( stream: PPaStream ): TPaError; cdecl; external LibName;
+
+
+{** Determine whether the stream is stopped.
+ A stream is considered to be stopped prior to a successful call to
+ Pa_StartStream and after a successful call to Pa_StopStream or Pa_AbortStream.
+ If a stream callback returns a value other than paContinue the stream is NOT
+ considered to be stopped.
+
+ @return Returns one (1) when the stream is stopped, zero (0) when
+ the stream is running or, a PaErrorCode (which are always negative) if
+ PortAudio is not initialized or an error is encountered.
+
+ @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive
+*}
+function Pa_IsStreamStopped( stream: PPaStream ): TPaError; cdecl; external LibName;
+
+
+{** Determine whether the stream is active.
+ A stream is active after a successful call to Pa_StartStream(), until it
+ becomes inactive either as a result of a call to Pa_StopStream() or
+ Pa_AbortStream(), or as a result of a return value other than paContinue from
+ the stream callback. In the latter case, the stream is considered inactive
+ after the last buffer has finished playing.
+
+ @return Returns one (1) when the stream is active (ie playing or recording
+ audio), zero (0) when not playing or, a PaErrorCode (which are always negative)
+ if PortAudio is not initialized or an error is encountered.
+
+ @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamStopped
+*}
+function Pa_IsStreamActive( stream: PPaStream ): TPaError; cdecl; external LibName;
+
+
+
+{** A structure containing unchanging information about an open stream.
+ @see Pa_GetStreamInfo
+*}
+type
+  PPaStreamInfo = ^TPaStreamInfo;
+  TPaStreamInfo = record
+      {** this is struct version 1 *}
+      structVersion: cint;
+
+      {** The input latency of the stream in seconds. This value provides the most
+       accurate estimate of input latency available to the implementation. It may
+       differ significantly from the suggestedLatency value passed to Pa_OpenStream().
+       The value of this field will be zero (0.) for output-only streams.
+       @see PaTime
+      *}
+      inputLatency: TPaTime;
+
+      {** The output latency of the stream in seconds. This value provides the most
+       accurate estimate of output latency available to the implementation. It may
+       differ significantly from the suggestedLatency value passed to Pa_OpenStream().
+       The value of this field will be zero (0.) for input-only streams.
+       @see PaTime
+      *}
+      outputLatency: TPaTime;
+
+      {** The sample rate of the stream in Hertz (samples per second). In cases
+       where the hardware sample rate is inaccurate and PortAudio is aware of it,
+       the value of this field may be different from the sampleRate parameter
+       passed to Pa_OpenStream(). If information about the actual hardware sample
+       rate is not available, this field will have the same value as the sampleRate
+       parameter passed to Pa_OpenStream().
+      *}
+      sampleRate: cdouble;
+  end;
+
+
+{** Retrieve a pointer to a PaStreamInfo structure containing information
+ about the specified stream.
+ @return A pointer to an immutable PaStreamInfo structure. If the stream
+ parameter invalid, or an error is encountered, the function returns NULL.
+
+ @param stream A pointer to an open stream previously created with Pa_OpenStream.
+
+ @note PortAudio manages the memory referenced by the returned pointer,
+ the client must not manipulate or free the memory. The pointer is only
+ guaranteed to be valid until the specified stream is closed.
+
+ @see PaStreamInfo
+*}
+function Pa_GetStreamInfo( stream: PPaStream ): PPaStreamInfo; cdecl; external LibName;
+
+
+{** Determine the current time for the stream according to the same clock used
+ to generate buffer timestamps. This time may be used for syncronising other
+ events to the audio stream, for example synchronizing audio to MIDI.
+                                        
+ @return The stream's current time in seconds, or 0 if an error occurred.
+
+ @see PaTime, PaStreamCallback
+*}
+function Pa_GetStreamTime( stream: PPaStream ): TPaTime; cdecl; external LibName;
+
+
+{** Retrieve CPU usage information for the specified stream.
+ The "CPU Load" is a fraction of total CPU time consumed by a callback stream's
+ audio processing routines including, but not limited to the client supplied
+ stream callback. This function does not work with blocking read/write streams.
+
+ This function may be called from the stream callback function or the
+ application.
+     
+ @return
+ A floating point value, typically between 0.0 and 1.0, where 1.0 indicates
+ that the stream callback is consuming the maximum number of CPU cycles possible
+ to maintain real-time operation. A value of 0.5 would imply that PortAudio and
+ the stream callback was consuming roughly 50% of the available CPU time. The
+ return value may exceed 1.0. A value of 0.0 will always be returned for a
+ blocking read/write stream, or if an error occurrs.
+*}
+function Pa_GetStreamCpuLoad( stream: PPaStream ): cdouble; cdecl; external LibName;
+
+
+{** Read samples from an input stream. The function doesn't return until
+ the entire buffer has been filled - this may involve waiting for the operating
+ system to supply the data.
+
+ @param stream A pointer to an open stream previously created with Pa_OpenStream.
+ 
+ @param buffer A pointer to a buffer of sample frames. The buffer contains
+ samples in the format specified by the inputParameters->sampleFormat field
+ used to open the stream, and the number of channels specified by
+ inputParameters->numChannels. If non-interleaved samples were requested,
+ buffer is a pointer to the first element of an array of non-interleaved
+ buffer pointers, one for each channel.
+
+ @param frames The number of frames to be read into buffer. This parameter
+ is not constrained to a specific range, however high performance applications
+ will want to match this parameter to the framesPerBuffer parameter used
+ when opening the stream.
+
+ @return On success PaNoError will be returned, or PaInputOverflowed if input
+ data was discarded by PortAudio after the previous call and before this call.
+*}
+function Pa_ReadStream( stream: PPaStream;
+                       buffer: Pointer;
+                       frames: culong ): TPaError; cdecl; external LibName;
+
+
+{** Write samples to an output stream. This function doesn't return until the
+ entire buffer has been consumed - this may involve waiting for the operating
+ system to consume the data.
+
+ @param stream A pointer to an open stream previously created with Pa_OpenStream.
+
+ @param buffer A pointer to a buffer of sample frames. The buffer contains
+ samples in the format specified by the outputParameters->sampleFormat field
+ used to open the stream, and the number of channels specified by
+ outputParameters->numChannels. If non-interleaved samples were requested,
+ buffer is a pointer to the first element of an array of non-interleaved
+ buffer pointers, one for each channel.
+
+ @param frames The number of frames to be written from buffer. This parameter
+ is not constrained to a specific range, however high performance applications
+ will want to match this parameter to the framesPerBuffer parameter used
+ when opening the stream.
+
+ @return On success PaNoError will be returned, or paOutputUnderflowed if
+ additional output data was inserted after the previous call and before this
+ call.
+*}
+function Pa_WriteStream( stream: PPaStream;
+                        buffer: Pointer;
+                        frames: culong ): TPaError; cdecl; external LibName;
+
+
+{** Retrieve the number of frames that can be read from the stream without
+ waiting.
+
+ @return Returns a non-negative value representing the maximum number of frames
+ that can be read from the stream without blocking or busy waiting or, a
+ PaErrorCode (which are always negative) if PortAudio is not initialized or an
+ error is encountered.
+*}
+function Pa_GetStreamReadAvailable( stream: PPaStream ): cslong; cdecl; external LibName;
+
+
+{** Retrieve the number of frames that can be written to the stream without
+ waiting.
+
+ @return Returns a non-negative value representing the maximum number of frames
+ that can be written to the stream without blocking or busy waiting or, a
+ PaErrorCode (which are always negative) if PortAudio is not initialized or an
+ error is encountered.
+*}
+function Pa_GetStreamWriteAvailable( stream: PPaStream ): cslong; cdecl; external LibName;
+
+
+{** Retrieve the host type handling an open stream.
+
+ @return Returns a non-negative value representing the host API type
+ handling an open stream or, a PaErrorCode (which are always negative)
+ if PortAudio is not initialized or an error is encountered.
+*}
+function Pa_GetStreamHostApiType( stream: PPaStream ): TPaHostApiTypeId; cdecl; external LibName;
+
+
+{* Miscellaneous utilities *}
+
+
+{** Retrieve the size of a given sample format in bytes.
+
+ @return The size in bytes of a single sample in the specified format,
+ or paSampleFormatNotSupported if the format is not supported.
+*}
+function Pa_GetSampleSize( format: TPaSampleFormat ): TPaError; cdecl; external LibName;
+
+
+{** Put the caller to sleep for at least 'msec' milliseconds. This function is
+ provided only as a convenience for authors of portable code (such as the tests
+ and examples in the PortAudio distribution.)
+
+ The function may sleep longer than requested so don't rely on this for accurate
+ musical timing.
+*}
+procedure Pa_Sleep( msec: clong ); cdecl; external LibName;
+
+implementation
+
+end.
diff --git a/songmanagement/src/lib/portmixer/portmixer.pas b/songmanagement/src/lib/portmixer/portmixer.pas
new file mode 100644
index 00000000..b84e0cd6
--- /dev/null
+++ b/songmanagement/src/lib/portmixer/portmixer.pas
@@ -0,0 +1,149 @@
+{*
+ * PortMixer
+ * PortMixer API Header File
+ *
+ * Copyright (c) 2002, 2006
+ *
+ * Written by Dominic Mazzoni
+ *        and Leland Lucius
+ *
+ * PortMixer is intended to work side-by-side with PortAudio,
+ * the Portable Real-Time Audio Library by Ross Bencina and
+ * Phil Burk.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *}
+unit portmixer;
+
+{$IFDEF FPC}
+  {$PACKRECORDS C}    (* GCC/Visual C/C++ compatible record packing *)
+  {$MODE DELPHI }
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  portaudio;
+
+const
+{$IF Defined(MSWINDOWS)}
+  LibName = 'portmixer.dll';
+{$ELSEIF Defined(DARWIN)}
+//  LibName = 'libportmixer.dylib';
+//  {$LINKLIB libportaudio}
+{$ELSEIF Defined(UNIX)}
+  LibName = 'libportmixer.so';
+{$IFEND}
+
+type
+  PPxMixer = Pointer;
+  TPxVolume = cfloat; {* 0.0 (min) --> 1.0 (max) *}
+  TPxBalance = cfloat; {* -1.0 (left) --> 1.0 (right) *}
+
+{*
+ Px_OpenMixer() returns a mixer which will work with the given PortAudio
+ audio device.  Pass 0 as the index for the first (default) mixer.
+*}
+
+function Px_OpenMixer( pa_stream: Pointer; i: cint ): PPxMixer; cdecl; external LibName;
+
+{*
+ Px_CloseMixer() closes a mixer opened using Px_OpenMixer and frees any
+ memory associated with it. 
+*}
+
+procedure Px_CloseMixer( mixer: PPxMixer ); cdecl; external LibName;
+
+{*
+ Px_GetNumMixers returns the number of mixers which could be
+ used with the given PortAudio device.  On most systems, there
+ will be only one mixer for each device; however there may be
+ multiple mixers for each device, or possibly multiple mixers
+ which are independent of any particular PortAudio device.
+*}
+
+function Px_GetNumMixers( mixer: PPxMixer ): cint; cdecl; external LibName;
+function Px_GetMixerName( mixer: PPxMixer; i: cint ): PChar; cdecl; external LibName;
+
+{*
+ Master (output) volume
+*}
+
+function Px_GetMasterVolume( mixer: PPxMixer ): TPxVolume; cdecl; external LibName;
+procedure Px_SetMasterVolume( mixer: PPxMixer; volume: TPxVolume ); cdecl; external LibName;
+
+{*
+ Main output volume
+*}
+
+function Px_GetPCMOutputVolume( mixer: PPxMixer ): TPxVolume; cdecl; external LibName;
+procedure Px_SetPCMOutputVolume( mixer: PPxMixer; volume: TPxVolume ); cdecl; external LibName;
+function Px_SupportsPCMOutputVolume( mixer: PPxMixer ): cint; cdecl; external LibName;
+
+{*
+ All output volumes
+*}
+
+function Px_GetNumOutputVolumes( mixer: PPxMixer ): cint; cdecl; external LibName;
+function Px_GetOutputVolumeName( mixer: PPxMixer; i: cint ): PChar; cdecl; external LibName;
+function Px_GetOutputVolume( mixer: PPxMixer; i: cint ): TPxVolume; cdecl; external LibName;
+procedure Px_SetOutputVolume( mixer: PPxMixer; i: cint; volume: TPxVolume ); cdecl; external LibName;
+
+{*
+ Input source
+*}
+
+function Px_GetNumInputSources( mixer: PPxMixer ): cint; cdecl; external LibName;
+function Px_GetInputSourceName( mixer: PPxMixer; i: cint): PChar; cdecl; external LibName;
+function Px_GetCurrentInputSource( mixer: PPxMixer ): cint; cdecl; external LibName; {* may return -1 == none *}
+procedure Px_SetCurrentInputSource( mixer: PPxMixer; i: cint ); cdecl; external LibName;
+
+{*
+ Input volume
+*}
+
+function Px_GetInputVolume( mixer: PPxMixer ): TPxVolume; cdecl; external LibName;
+procedure Px_SetInputVolume( mixer: PPxMixer; volume: TPxVolume ); cdecl; external LibName;
+
+{*
+  Balance
+*}
+
+function Px_SupportsOutputBalance( mixer: PPxMixer ): cint; cdecl; external LibName;
+function Px_GetOutputBalance( mixer: PPxMixer ): TPxBalance; cdecl; external LibName;
+procedure Px_SetOutputBalance( mixer: PPxMixer; balance: TPxBalance ); cdecl; external LibName;
+
+{*
+  Playthrough
+*}
+
+function Px_SupportsPlaythrough( mixer: PPxMixer ): cint; cdecl; external LibName;
+function Px_GetPlaythrough( mixer: PPxMixer ): TPxVolume; cdecl; external LibName;
+procedure Px_SetPlaythrough( mixer: PPxMixer; volume: TPxVolume ); cdecl; external LibName;
+
+implementation
+
+end.
diff --git a/songmanagement/src/lib/projectM/cwrapper/Makefile.in b/songmanagement/src/lib/projectM/cwrapper/Makefile.in
new file mode 100644
index 00000000..fef3b80b
--- /dev/null
+++ b/songmanagement/src/lib/projectM/cwrapper/Makefile.in
@@ -0,0 +1,41 @@
+#################################################
+# projectM C-wrapper
+# @configure_input@
+#################################################
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+OBJECTS	= projectM-cwrapper.o
+LIBRARY = libprojectM-cwrapper.a
+
+CXX      = @CXX@
+CXXFLAGS += @CXXFLAGS@
+INCLUDES = -I@libprojectM_INCLUDEDIR@/libprojectM
+DEFINES  = -DPROJECTM_VERSION_INT=@libprojectM_VERSION_INT@
+RANLIB   = @RANLIB@
+
+.PHONY: all clean distclean strip
+
+all : $(LIBRARY)
+
+$(LIBRARY): $(OBJECTS)
+	ar ruv $(LIBRARY) $(OBJECTS)
+	$(RANLIB) $(LIBRARY)
+
+%.o : %.cpp
+	$(CXX) $(CXXFLAGS) $(DEFINES) $(INCLUDES) -c $(<) -o $@
+
+clean : 
+	rm -f $(LIBRARY)
+	rm -f $(OBJECTS)
+
+distclean: clean
+	rm -rf Makefile
+
+strip : 
+	strip $(LIBRARY)
+	$(RANLIB) $(LIBRARY)
+
diff --git a/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.cpp b/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.cpp
new file mode 100644
index 00000000..ebf43554
--- /dev/null
+++ b/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.cpp
@@ -0,0 +1,104 @@
+#include "projectM-cwrapper.h"
+
+#define PM_CLASS(pm) ((projectM*)pm)
+
+#if (PROJECTM_VERSION_INT > 1000000)
+#define	PM_PCM(pm) (PM_CLASS(pm)->pcm())
+#else
+#define	PM_PCM(pm) (PM_CLASS(pm)->pcm)
+#endif
+
+projectM_ptr projectM_create1(char* config_file) 
+{
+    return projectM_ptr(new projectM(config_file));
+}
+
+#if (PROJECTM_VERSION_INT < 1000000)
+projectM_ptr projectM_create2(int gx, int gy, int fps, int texsize, 
+			      int width, int height, char* preset_url, 
+			      char* title_fonturl, char* title_menuurl)
+{
+    return projectM_ptr(new projectM(gx, gy, fps, texsize, width, height, 
+    				     preset_url, title_fonturl, title_menuurl));}
+#endif
+
+void projectM_resetGL(projectM_ptr pm, int width, int height)
+{
+    PM_CLASS(pm)->projectM_resetGL(width, height);
+}
+
+void projectM_setTitle(projectM_ptr pm, char* title)
+{
+    PM_CLASS(pm)->projectM_setTitle(title);
+}
+
+void projectM_renderFrame(projectM_ptr pm)
+{
+    PM_CLASS(pm)->renderFrame();
+}
+
+unsigned projectM_initRenderToTexture(projectM_ptr pm)
+{
+    return PM_CLASS(pm)->initRenderToTexture();
+}
+
+void projectM_key_handler(projectM_ptr pm, projectMEvent event, 
+		projectMKeycode keycode, projectMModifier modifier)
+{
+    PM_CLASS(pm)->key_handler(event, keycode, modifier);
+}
+	    
+void projectM_free(projectM_ptr pm)
+{
+    delete PM_CLASS(pm);
+}
+
+void PCM_addPCMfloat(projectM_ptr pm, float *PCMdata, int samples)
+{
+    PM_PCM(pm)->addPCMfloat(PCMdata, samples);
+}
+
+void PCM_addPCM16(projectM_ptr pm, short pcm_data[2][512])
+{
+    PM_PCM(pm)->addPCM16(pcm_data);
+}
+
+void PCM_addPCM16Data(projectM_ptr pm, const short* pcm_data, short samples)
+{
+    PM_PCM(pm)->addPCM16Data(pcm_data, samples);
+}
+
+void PCM_addPCM8(projectM_ptr pm, unsigned char pcm_data[2][1024])
+{
+    PM_PCM(pm)->addPCM8(pcm_data);
+}
+
+void PCM_addPCM8_512(projectM_ptr pm, const unsigned char pcm_data[2][512])
+{
+    PM_PCM(pm)->addPCM8_512(pcm_data);
+}
+
+#define COPY_FIELD(c_ptr, s, fld) (c_ptr->fld = s.fld)
+
+#if (PROJECTM_VERSION_INT > 1000000)
+void projectM_settings(projectM_ptr pm, Settings* settings)
+{
+    const projectM::Settings& pmSettings = PM_CLASS(pm)->settings();
+
+    COPY_FIELD(settings, pmSettings, meshX);
+    COPY_FIELD(settings, pmSettings, meshY);
+    COPY_FIELD(settings, pmSettings, fps);
+    COPY_FIELD(settings, pmSettings, textureSize);
+    COPY_FIELD(settings, pmSettings, windowWidth);
+    COPY_FIELD(settings, pmSettings, windowHeight);
+    settings->presetURL    = pmSettings.presetURL.c_str();
+    settings->titleFontURL = pmSettings.titleFontURL.c_str();
+    settings->menuFontURL  = pmSettings.menuFontURL.c_str();
+    COPY_FIELD(settings, pmSettings, smoothPresetDuration);
+    COPY_FIELD(settings, pmSettings, presetDuration);
+    COPY_FIELD(settings, pmSettings, beatSensitivity);
+    COPY_FIELD(settings, pmSettings, aspectCorrection);
+    COPY_FIELD(settings, pmSettings, easterEgg);
+    COPY_FIELD(settings, pmSettings, shuffleEnabled);
+}
+#endif
diff --git a/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.h b/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.h
new file mode 100644
index 00000000..125b1253
--- /dev/null
+++ b/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.h
@@ -0,0 +1,68 @@
+#ifndef __PROJECTM_CWRAPPER_H__
+#define __PROJECTM_CWRAPPER_H__
+
+#include "projectM.hpp"
+
+// PROJECTM_VERSION define is not very helpful, lets create our own
+#define PROJECTM_VERSION_1_00_00 1000000 // 1.00.00 = 1.0 or 1.01 (same version number for 1.0 and 1.01)
+#define PROJECTM_VERSION_1_10_00 1010000 // 1.10.00 = 1.1 (bigger than 1.2 due to strange versioning)
+#define PROJECTM_VERSION_1_02_00 1002000 // 1.02.00 = 1.2
+#define PROJECTM_VERSION_2_00_00 2000000 // 2.00.00 = 2.0
+
+// version of projectM to wrap (see PROJECTM_VERSION)
+#ifndef PROJECTM_VERSION_INT
+#define PROJECTM_VERSION_INT PROJECTM_VERSION_2_00_00
+#endif
+
+extern "C" {
+
+    #if (PROJECTM_VERSION_INT > 1000000)
+    struct Settings {
+	int meshX;
+	int meshY;
+	int fps;
+	int textureSize;
+	int windowWidth;
+	int windowHeight;
+	const char* presetURL;
+	const char* titleFontURL;
+	const char* menuFontURL;		
+	int smoothPresetDuration;
+	int presetDuration;
+	float beatSensitivity;
+	char aspectCorrection;
+	float easterEgg;
+	char shuffleEnabled;
+    };
+    #endif
+
+    typedef void* projectM_ptr;
+
+    DLLEXPORT projectM_ptr projectM_create1(char* config_file);
+    #if (PROJECTM_VERSION_INT < 1000000)
+    DLLEXPORT projectM_ptr projectM_create2(int gx, int gy, int fps, int texsize, 
+					    int width, int height, char* preset_url, 
+					    char* title_fonturl, char* title_menuurl);
+    #endif
+
+    DLLEXPORT void projectM_resetGL(projectM_ptr pm, int width, int height);
+    DLLEXPORT void projectM_setTitle(projectM_ptr pm, char* title);
+    DLLEXPORT void projectM_renderFrame(projectM_ptr pm);
+    DLLEXPORT unsigned projectM_initRenderToTexture(projectM_ptr pm); 
+    DLLEXPORT void projectM_key_handler(projectM_ptr pm, projectMEvent event, 
+					projectMKeycode keycode, projectMModifier modifier);
+    
+    DLLEXPORT void projectM_free(projectM_ptr pm);
+
+    DLLEXPORT void PCM_addPCMfloat(projectM_ptr pm, float *PCMdata, int samples);
+    DLLEXPORT void PCM_addPCM16(projectM_ptr pm, short [2][512]);
+    DLLEXPORT void PCM_addPCM16Data(projectM_ptr pm, const short* pcm_data, short samples);
+    DLLEXPORT void PCM_addPCM8(projectM_ptr pm, unsigned char [2][1024]);
+    DLLEXPORT void PCM_addPCM8_512(projectM_ptr pm, const unsigned char [2][512]);
+
+    #if (PROJECTM_VERSION_INT > 1000000)
+    DLLEXPORT void projectM_settings(projectM_ptr pm, Settings* settings);
+    #endif
+}
+
+#endif
diff --git a/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.sln b/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.sln
new file mode 100644
index 00000000..61fef817
--- /dev/null
+++ b/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "projectM-cwrapper", "projectM-cwrapper.vcproj", "{8E653284-12F3-4A90-9D0D-4195557051F7}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{8E653284-12F3-4A90-9D0D-4195557051F7}.Debug|Win32.ActiveCfg = Debug|Win32
+		{8E653284-12F3-4A90-9D0D-4195557051F7}.Debug|Win32.Build.0 = Debug|Win32
+		{8E653284-12F3-4A90-9D0D-4195557051F7}.Release|Win32.ActiveCfg = Release|Win32
+		{8E653284-12F3-4A90-9D0D-4195557051F7}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.vcproj b/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.vcproj
new file mode 100644
index 00000000..6f6ef4c1
--- /dev/null
+++ b/songmanagement/src/lib/projectM/cwrapper/projectM-cwrapper.vcproj
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9,00"
+	Name="projectM-cwrapper"
+	ProjectGUID="{8E653284-12F3-4A90-9D0D-4195557051F7}"
+	RootNamespace="projectMcwrapper"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="&quot;D:\daten\projectM-2.0.1-Source&quot;"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PROJECTMCWRAPPER_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="projectM.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="&quot;D:\daten\projectM-2.0.1-Source\build\Debug&quot;"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="&quot;D:\daten\projectM-2.0.1-Source&quot;"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PROJECTMCWRAPPER_EXPORTS"
+				ExceptionHandling="1"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="projectM.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="&quot;D:\daten\projectM-2.0.1-Source\build\Release&quot;"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Quelldateien"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\projectM-cwrapper.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Headerdateien"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\projectM-cwrapper.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Ressourcendateien"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/songmanagement/src/lib/projectM/projectM-0_9.inc b/songmanagement/src/lib/projectM/projectM-0_9.inc
new file mode 100644
index 00000000..6b525cf7
--- /dev/null
+++ b/songmanagement/src/lib/projectM/projectM-0_9.inc
@@ -0,0 +1,427 @@
+{$IFDEF Unix}
+uses
+  baseunix;
+{$ENDIF}
+
+const
+{$IF Defined(MSWINDOWS)}
+  libprojectM = 'libprojectM.dll';
+{$ELSEIF Defined(UNIX)}
+  libprojectM = 'libprojectM.so';
+{$IFEND}
+
+{**************** INTERNAL SECTION ****************}
+
+
+type
+  PPCfloat = ^PCfloat;
+
+type
+  _TContextType = cint;
+const
+  AGL_CONTEXT   = 0;
+  CGL_CONTEXT   = 1;
+  NSGL_CONTEXT  = 2;
+  GLX_CONTEXT   = 3;
+  WGL_CONTEXT   = 4;
+
+type
+  _PRenderTarget = ^_TRenderTarget;
+  _TRenderTarget = record
+    { Texture size }
+    texsize: cint;
+
+    { Application context }
+    origContextType: _TContextType;
+
+    usePbuffers: cint;
+
+    {$ifdef LINUX}
+      lock_func: procedure(); cdecl;
+      unlock_func: procedure(); cdecl;
+    {$endif}
+
+    { Opaque pbuffer context and pbuffer }
+    {$ifdef DARWIN}
+      origContext: Pointer;
+      pbufferContext: Pointer;
+      pbuffer: Pointer;
+    {$endif}
+
+  { Render target texture ID for non-pbuffer systems }
+    textureID: array[0..2] of GLuint;
+  end;
+
+  _PProjectM = ^_TProjectM;
+  _TProjectM = record
+    presetURL: PChar;
+    presetName: PChar;
+    fontURL: PChar;
+
+    hasInit: cint;
+
+    noSwitch: cint;
+    pcmframes: cint;
+    freqframes: cint;
+    totalframes: cint;
+
+    showfps: cint;
+    showtitle: cint;
+    showpreset: cint;
+    showhelp: cint;
+    showstats: cint;
+
+    studio: cint;
+
+    fbuffer: PGLubyte;
+
+    {$IFNDEF MSWINDOWS}
+    { The first ticks value of the application }
+    startTime: timeval;
+    {$ELSE}
+    startTime: clong;
+    {$ENDIF}
+    Time: cfloat;
+
+    { Render target texture ID }
+    renderTarget: _PRenderTarget;
+
+    disp: array[0..79] of Char;
+
+    wave_o: cfloat;
+
+    //int texsize=1024;   //size of texture to do actual graphics
+    fvw: cint;   //fullscreen dimensions
+    fvh: cint;
+    wvw: cint;   //windowed dimensions
+    wvh: cint;
+    vw: cint;    //runtime dimensions
+    vh: cint;
+    fullscreen: cint;
+
+    maxsamples: cint;  //size of PCM buffer
+    numsamples: cint;  //size of new PCM info
+    pcmdataL: PCfloat;     //holder for most recent pcm data
+    pcmdataR: PCfloat;     //holder for most recent pcm data
+
+    avgtime: cint;     //# frames per preset
+    
+    title: PChar;
+    drawtitle: cint;
+
+    correction: cint;
+
+    vol: cfloat;
+
+    //per pixel equation variables
+    gridx: PPCfloat;     //grid containing interpolated mesh
+    gridy: PPCfloat;
+    origtheta: PPCfloat; //grid containing interpolated mesh reference values
+    origrad: PPCfloat;
+    origx: PPCfloat;     //original mesh
+    origy: PPCfloat;
+    origx2: PPCfloat;    //original mesh
+    origy2: PPCfloat;
+
+    { Timing information }
+    mspf: cint;
+    timed: cint;
+    timestart: cint;
+    nohard: cint;
+    count: cint;
+    realfps,
+    fpsstart: cfloat;
+
+    { PCM data }
+    vdataL: array[0..511] of cfloat;  //holders for FFT data (spectrum)
+    vdataR: array[0..511] of cfloat;
+
+    { Various toggles }
+    doPerPixelEffects: cint;
+    doIterative: cint;
+
+    { ENGINE VARIABLES }
+    { From engine_vars.h }
+    preset_name: array[0..255] of Char;
+
+    { PER FRAME CONSTANTS BEGIN }
+    zoom: cfloat;
+    zoomexp: cfloat;
+    rot: cfloat;
+    warp: cfloat;
+
+    sx: cfloat;
+    sy: cfloat;
+    dx: cfloat;
+    dy: cfloat;
+    cx: cfloat;
+    cy: cfloat;
+
+    gy: cint;
+    gx: cint;
+
+    decay: cfloat;
+
+    wave_r: cfloat;
+    wave_g: cfloat;
+    wave_b: cfloat;
+    wave_x: cfloat;
+    wave_y: cfloat;
+    wave_mystery: cfloat;
+
+    ob_size: cfloat;
+    ob_r: cfloat;
+    ob_g: cfloat;
+    ob_b: cfloat;
+    ob_a: cfloat;
+
+    ib_size: cfloat;
+    ib_r: cfloat;
+    ib_g: cfloat;
+    ib_b: cfloat;
+    ib_a: cfloat;
+
+    meshx: cint;
+    meshy: cint;
+
+    mv_a: cfloat;
+    mv_r: cfloat;
+    mv_g: cfloat;
+    mv_b: cfloat;
+    mv_l: cfloat;
+    mv_x: cfloat;
+    mv_y: cfloat;
+    mv_dy: cfloat;
+    mv_dx: cfloat;
+
+    treb: cfloat;
+    mid: cfloat;
+    bass: cfloat;
+    bass_old: cfloat;
+    beat_sensitivity: cfloat;
+    treb_att: cfloat;
+    mid_att: cfloat;
+    bass_att: cfloat;
+    progress: cfloat;
+    frame: cint;
+
+    { PER_FRAME CONSTANTS END }
+
+    { PER_PIXEL CONSTANTS BEGIN }
+
+    x_per_pixel: cfloat;
+    y_per_pixel: cfloat;
+    rad_per_pixel: cfloat;
+    ang_per_pixel: cfloat;
+
+    { PER_PIXEL CONSTANT END }
+
+
+    fRating: cfloat;
+    fGammaAdj: cfloat;
+    fVideoEchoZoom: cfloat;
+    fVideoEchoAlpha: cfloat;
+
+    nVideoEchoOrientation: cint;
+    nWaveMode: cint;
+    bAdditiveWaves: cint;
+    bWaveDots: cint;
+    bWaveThick: cint;
+    bModWaveAlphaByVolume: cint;
+    bMaximizeWaveColor: cint;
+    bTexWrap: cint;
+    bDarkenCenter: cint;
+    bRedBlueStereo: cint;
+    bBrighten: cint;
+    bDarken: cint;
+    bSolarize: cint;
+    bInvert: cint;
+    bMotionVectorsOn: cint;
+    fps: cint;
+
+    fWaveAlpha: cfloat;
+    fWaveScale: cfloat;
+    fWaveSmoothing: cfloat;
+    fWaveParam: cfloat;
+    fModWaveAlphaStart: cfloat;
+    fModWaveAlphaEnd: cfloat;
+    fWarpAnimSpeed: cfloat;
+    fWarpScale: cfloat;
+    fShader: cfloat;
+
+    
+    { Q VARIABLES START }
+
+    q1: cfloat;
+    q2: cfloat;
+    q3: cfloat;
+    q4: cfloat;
+    q5: cfloat;
+    q6: cfloat;
+    q7: cfloat;
+    q8: cfloat;
+
+
+    { Q VARIABLES END }
+
+    zoom_mesh: PPCfloat;
+    zoomexp_mesh: PPCfloat;
+    rot_mesh: PPCfloat;
+
+    sx_mesh: PPCfloat;
+    sy_mesh: PPCfloat;
+    dx_mesh: PPCfloat;
+    dy_mesh: PPCfloat;
+    cx_mesh: PPCfloat;
+    cy_mesh: PPCfloat;
+
+    x_mesh: PPCfloat;
+    y_mesh: PPCfloat;
+    rad_mesh: PPCfloat;
+    theta_mesh: PPCfloat;
+  end;
+
+  PProjectMState = ^TProjectMState;
+  TProjectMState = record
+    fontURLStr: string;
+    presetURLStr: string;
+    titleStr: string;
+    pm: _TProjectM;
+  end;
+
+{ projectM.h declarations }
+procedure _projectM_init(pm: _PProjectM); cdecl; external libprojectM name 'projectM_init';
+procedure _projectM_reset(pm: _PProjectM); cdecl; external libprojectM name 'projectM_reset';
+procedure _projectM_resetGL(pm: _PProjectM; width: cint; height: cint); cdecl; external libprojectM name 'projectM_resetGL';
+procedure _projectM_setTitle(pm: _PProjectM; title: PChar); cdecl; external libprojectM name 'projectM_setTitle';
+procedure _renderFrame(pm: _PProjectM); cdecl; external libprojectM name 'renderFrame';
+
+{ PCM.h declarations }
+procedure _addPCMfloat(pcm_data: PCfloat; samples: cint); cdecl; external libprojectM name 'addPCMfloat';
+procedure _addPCM16(pcm_data: PPCM16); cdecl; external libprojectM name 'addPCM16';
+procedure _addPCM16Data(pcm_data: PCshort; samples: cshort); cdecl; external libprojectM name 'addPCM16Data';
+procedure _addPCM8_512(pcm_data: PPCM8_512); cdecl; external libprojectM name 'addPCM8';
+
+{ console_interface.h declarations }
+procedure _key_handler(pm: _PProjectM;
+                       event:    TProjectMEvent;
+                       keycode:  TProjectMKeycode;
+                       modifier: TProjectMModifier); cdecl; external libprojectM name 'key_handler';
+
+
+
+
+{**************** EXTERNAL SECTION ****************}
+
+
+constructor TProjectM.Create(gx, gy: cint; fps: integer;
+  texsize: integer; width, height: integer;
+  const presetsDir, fontsDir: string;
+  const titleFont, menuFont: string);
+var
+  state: PProjectMState;
+begin
+  inherited Create();
+
+  New(state);
+  data := state;
+
+  with state^ do
+  begin
+    // copy strings (Note: do not use e.g. PChar(presetsDir) directly, it might
+    // be a pointer to local stack data that is invalid after the calling function returns)
+    fontURLStr   := fontsDir;
+    presetURLStr := presetsDir;
+    
+    _projectM_reset(@pm);
+
+    pm.fullscreen := 0;
+    pm.renderTarget^.texsize := texsize;
+    pm.gx := gx;
+    pm.gy := gy;
+    pm.fps := fps;
+    pm.renderTarget^.usePbuffers := 0;
+    pm.fontURL   := PChar(fontURLStr);
+    pm.presetURL := PChar(presetURLStr);
+
+    _projectM_init(@pm);
+  end;
+end;
+
+procedure TProjectM.ResetGL(width, height: integer);
+begin
+  _projectM_resetGL(@PProjectMState(data).pm, width, height);
+end;
+
+procedure TProjectM.SetTitle(const title: string);
+var
+  state: PProjectMState;
+begin
+  state := PProjectMState(data);
+  with state^ do
+  begin
+    titleStr := title;
+    pm.title := PChar(titleStr);
+    pm.showtitle := 1;
+  end;
+end;
+
+procedure TProjectM.RenderFrame();
+begin
+  _renderFrame(@PProjectMState(data).pm);
+end;
+
+procedure TProjectM.AddPCMfloat(pcmData: PSingle; samples: integer);
+begin
+  _addPCMfloat(PCfloat(pcmData), samples);
+end;
+
+procedure TProjectM.AddPCM16(pcmData: PPCM16);
+begin
+  _addPCM16(pcmData);
+end;
+
+procedure TProjectM.AddPCM16Data(pcmData: PSmallint; samples: Smallint);
+begin
+  _addPCM16Data(PCshort(pcmData), samples);
+end;
+
+procedure TProjectM.AddPCM8_512(pcmData: PPCM8_512);
+begin
+  _addPCM8_512(pcmData);
+end;
+
+procedure TProjectM.KeyHandler(event:    TProjectMEvent;
+                               keycode:  TProjectMKeycode;
+                               modifier: TProjectMModifier);
+begin
+  _key_handler(@PProjectMState(data).pm, event, keycode, modifier);
+end;
+
+procedure TProjectM.RandomPreset();
+begin
+  KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_r_LOWERCASE, PROJECTM_KMOD_LSHIFT);
+end;
+
+procedure TProjectM.PreviousPreset();
+begin
+  KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_p_LOWERCASE, PROJECTM_KMOD_LSHIFT);
+end;
+
+procedure TProjectM.NextPreset();
+begin
+  KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_n_LOWERCASE, PROJECTM_KMOD_LSHIFT);
+end;
+
+procedure TProjectM.ToggleShowPresetNames();
+begin
+  KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_F3, PROJECTM_KMOD_LSHIFT);
+end;
+
+destructor TProjectM.Destroy();
+begin
+  Dispose(PProjectMState(data));
+  data := nil;
+  inherited;
+end;
+
diff --git a/songmanagement/src/lib/projectM/projectM-1_0.inc b/songmanagement/src/lib/projectM/projectM-1_0.inc
new file mode 100644
index 00000000..8e84894d
--- /dev/null
+++ b/songmanagement/src/lib/projectM/projectM-1_0.inc
@@ -0,0 +1,188 @@
+//uses
+
+(**
+ * Note: be careful with ProjectM's versioning scheme.
+ *
+ * Version  | Version in pkg-config .pc file
+ * ---------+--------------------------------------------
+ * 1.00     | 1.00
+ * 1.01     | 1.00
+ * 1.1      | 1.10
+ * 1.2      | 1.2 (= 1.02)
+ *
+ * So the version number of 1.1 is bigger than that of 1.2.
+ *)
+
+const
+{$IFDEF MSWINDOWS}
+  // Note: static linking is not possible with delphi because it does neither
+  // accept gcc nor MSVC object files (only Intel-style ones).
+  libprojectM_cwrapper = 'projectM-cwrapper.dll';
+{$ELSE}
+  // static libs are not supported in the "external"-clause
+  libprojectM_cwrapper = '';
+  // statically link the cwrapper and dynamically link projectM
+  {$L 'cwrapper/libprojectM-cwrapper.a'}
+  {$LINKLIB projectM}
+{$ENDIF}
+
+{**************** INTERNAL SECTION ****************}
+
+
+type
+  _PProjectM = Pointer;
+
+{ projectM.hpp declarations }
+function _projectM_create1(config_file: PChar): _PProjectM; cdecl; external libprojectM_cwrapper name 'projectM_create1';
+{$IF PROJECTM_VERSION < 1000000} // 0.9x
+function _projectM_create2(gx: cint; gy: cint; fps: cint;
+  texsize: cint; width: cint; height: cint;
+  preset_url: PChar; title_fonturl: PChar; title_menuurl: PChar): _PProjectM; cdecl; external libprojectM_cwrapper name 'projectM_create2';
+{$IFEND}
+
+procedure _projectM_resetGL(pm: _PProjectM; width: cint; height: cint); cdecl; external libprojectM_cwrapper name 'projectM_resetGL';
+procedure _projectM_setTitle(pm: _PProjectM; title: PChar); cdecl; external libprojectM_cwrapper name 'projectM_setTitle';
+procedure _projectM_renderFrame(pm: _PProjectM); cdecl; external libprojectM_cwrapper name 'projectM_renderFrame';
+function _projectM_initRenderToTexture(pm: _PProjectM): cuint; cdecl; external libprojectM_cwrapper name 'projectM_initRenderToTexture';
+
+procedure _projectM_free(pm: _PProjectM); cdecl; external libprojectM_cwrapper name 'projectM_free';
+
+procedure _projectM_key_handler(pm: _PProjectM; event: TProjectMEvent;
+  keycode: TProjectMKeycode; modifier: TProjectMModifier); cdecl; external libprojectM_cwrapper name 'projectM_key_handler';
+
+{$IF PROJECTM_VERSION > 1000000} // > 1.01
+procedure _projectM_settings(pm: _PProjectM; settings: PSettings); cdecl; external libprojectM_cwrapper name 'projectM_settings';
+{$IFEND}
+
+{ PCM.hpp declarations }
+procedure _PCM_addPCMfloat(pm: _PProjectM; pcm_data: PSingle; samples: cint); cdecl; external libprojectM_cwrapper name 'PCM_addPCMfloat';
+procedure _PCM_addPCM16(pm: _PProjectM; pcm_data: PPCM16); cdecl; external libprojectM_cwrapper name 'PCM_addPCM16';
+procedure _PCM_addPCM16Data(pm: _PProjectM; pcm_data: PCshort; samples: cshort); cdecl; external libprojectM_cwrapper name 'PCM_addPCM16Data';
+procedure _PCM_addPCM8_512(pm: _PProjectM; pcm_data: PPCM8_512); cdecl; external libprojectM_cwrapper name 'PCM_addPCM8_512';
+procedure _PCM_addPCM8_1024(pm: _PProjectM; pcm_data: PPCM8_1024); cdecl; external libprojectM_cwrapper name 'PCM_addPCM8';
+
+
+{**************** EXTERNAL SECTION ****************}
+
+// This constructor is present in projectM 1.0(1) but does not work with
+// linux because of a bug.
+(*
+constructor TProjectM.Create(gx, gy: integer; fps: integer;
+  texsize: integer; width, height: integer;
+  const presetsDir, fontsDir: string;
+  const titleFont, menuFont: string);
+begin
+  data := _projectM_create2(gx, gy, fps, texsize, width, height,
+            PChar(presetsDir),
+            PChar(fontsDir + PathDelim + titleFont),
+            PChar(fontsDir + PathDelim + menuFont));
+end;
+*)
+
+constructor TProjectM.Create(const configFile: string);
+begin
+  inherited Create();
+
+  // we cannot catch C++ exceptions in delphi, so we have to check
+  // if configFile is valid first
+  if (not FileExists(configFile)) then
+    raise Exception.Create('Invalid file: ' + configFile);
+
+  data := _projectM_create1(PChar(configFile));
+  if (data = nil) then
+    raise Exception.Create('Creation of projectM object failed');
+end;
+
+procedure TProjectM.ResetGL(width, height: Integer);
+begin
+  _projectM_resetGL(data, width, height);
+end;
+
+procedure TProjectM.SetTitle(const title: string);
+begin
+  _projectM_setTitle(data, PChar(title));
+end;
+
+procedure TProjectM.RenderFrame();
+begin
+  _projectM_renderFrame(data);
+end;
+
+procedure TProjectM.AddPCMfloat(pcmData: PSingle; samples: integer);
+begin
+  _PCM_addPCMfloat(data, pcmData, samples);
+end;
+
+procedure TProjectM.AddPCM16(pcmData: PPCM16);
+begin
+  _PCM_addPCM16(data, pcmData);
+end;
+
+{**
+ * Passes interleaved stereo PCM-samples to projectM.
+ *}
+procedure TProjectM.AddPCM16Data(pcmData: PSmallint; samples: Smallint);
+begin
+  _PCM_addPCM16Data(data, PCshort(pcmData), samples);
+end;
+
+procedure TProjectM.AddPCM8_512(pcmData: PPCM8_512);
+begin
+  _PCM_addPCM8_512(data, pcmData);
+end;
+
+procedure TProjectM.AddPCM8_1024(pcmData: PPCM8_1024);
+begin
+  _PCM_addPCM8_1024(data, pcmData);
+end;
+
+{**
+ * If the result is > -1 projectM will render to a texture.
+ * The texture-ID is the return-value.
+ *}
+function TProjectM.InitRenderToTexture(): GLuint;
+begin
+  result := _projectM_initRenderToTexture(data);
+end;
+
+procedure TProjectM.KeyHandler(event:    TProjectMEvent;
+                               keycode:  TProjectMKeycode;
+                               modifier: TProjectMModifier);
+begin
+  _projectM_key_handler(data, event, keycode, modifier);
+end;
+
+procedure TProjectM.RandomPreset();
+begin
+  KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_r_LOWERCASE, PROJECTM_KMOD_LSHIFT);
+end;
+
+procedure TProjectM.PreviousPreset();
+begin
+  KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_p_LOWERCASE, PROJECTM_KMOD_LSHIFT);
+end;
+
+procedure TProjectM.NextPreset();
+begin
+  KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_n_LOWERCASE, PROJECTM_KMOD_LSHIFT);
+end;
+
+procedure TProjectM.ToggleShowPresetNames();
+begin
+  KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_F3, PROJECTM_KMOD_LSHIFT);
+end;
+                       
+{$IF PROJECTM_VERSION > 1000000} // > 1.01
+procedure TProjectM.Settings(var settings: TSettings);
+begin
+  _projectM_settings(data, @settings);
+end;
+{$IFEND}
+
+destructor TProjectM.Destroy();
+begin
+  _projectM_free(data);
+  data := nil;
+  inherited;
+end;
+
diff --git a/songmanagement/src/lib/projectM/projectM.pas b/songmanagement/src/lib/projectM/projectM.pas
new file mode 100644
index 00000000..533cb19b
--- /dev/null
+++ b/songmanagement/src/lib/projectM/projectM.pas
@@ -0,0 +1,232 @@
+unit projectM;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$H+}            (* use long strings *)
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+interface
+
+uses
+  SysUtils,
+  ctypes,
+  gl,
+  UConfig;
+
+type
+  // 16bit non-interleaved data
+  TPCM16 = array[0..1, 0..511] of Smallint;
+  PPCM16 = ^TPCM16;
+  // 8bit non-interleaved data (512 samples)
+  TPCM8_512 = array[0..1, 0..511] of byte;
+  PPCM8_512 = ^TPCM8_512;
+  // 8bit non-interleaved data (1024 samples)
+  TPCM8_1024 = array[0..1, 0..1023] of byte;
+  PPCM8_1024 = ^TPCM8_512;
+
+{ Event types }
+type
+  TProjectMEvent = cint;
+const
+  PROJECTM_KEYUP       = 0;
+  PROJECTM_KEYDOWN     = 1;
+  PROJECTM_VIDEORESIZE = 2;
+  PROJECTM_VIDEOQUIT   = 3;
+  PROJECTM_NONE        = 4;
+
+{ Keycodes }
+type
+  TProjectMKeycode = cint;
+const
+  PROJECTM_K_RETURN    =  0;
+  PROJECTM_K_RIGHT     =  1;
+  PROJECTM_K_LEFT      =  2;
+  PROJECTM_K_UP        =  3;
+  PROJECTM_K_DOWN      =  4;
+  PROJECTM_K_PAGEUP    =  5;
+  PROJECTM_K_PAGEDOWN  =  6;
+  PROJECTM_K_INSERT    =  7;
+  PROJECTM_K_DELETE    =  8;
+  PROJECTM_K_ESCAPE    =  9;
+  PROJECTM_K_LSHIFT    = 10;
+  PROJECTM_K_RSHIFT    = 11;
+  PROJECTM_K_CAPSLOCK  = 12;
+  PROJECTM_K_LCTRL     = 13;
+  PROJECTM_K_HOME      = 14;
+  PROJECTM_K_END       = 15;
+  PROJECTM_K_BACKSPACE = 16;
+
+  PROJECTM_K_F1        = 17;
+  PROJECTM_K_F2        = (PROJECTM_K_F1 +  1);
+  PROJECTM_K_F3        = (PROJECTM_K_F1 +  2);
+  PROJECTM_K_F4        = (PROJECTM_K_F1 +  3);
+  PROJECTM_K_F5        = (PROJECTM_K_F1 +  4);
+  PROJECTM_K_F6        = (PROJECTM_K_F1 +  5);
+  PROJECTM_K_F7        = (PROJECTM_K_F1 +  6);
+  PROJECTM_K_F8        = (PROJECTM_K_F1 +  7);
+  PROJECTM_K_F9        = (PROJECTM_K_F1 +  8);
+  PROJECTM_K_F10       = (PROJECTM_K_F1 +  9);
+  PROJECTM_K_F11       = (PROJECTM_K_F1 + 10);
+  PROJECTM_K_F12       = (PROJECTM_K_F1 + 11);
+
+  PROJECTM_K_0         = 48;
+  PROJECTM_K_1         = (PROJECTM_K_0 + 1);
+  PROJECTM_K_2         = (PROJECTM_K_0 + 2);
+  PROJECTM_K_3         = (PROJECTM_K_0 + 3);
+  PROJECTM_K_4         = (PROJECTM_K_0 + 4);
+  PROJECTM_K_5         = (PROJECTM_K_0 + 5);
+  PROJECTM_K_6         = (PROJECTM_K_0 + 6);
+  PROJECTM_K_7         = (PROJECTM_K_0 + 7);
+  PROJECTM_K_8         = (PROJECTM_K_0 + 8);
+  PROJECTM_K_9         = (PROJECTM_K_0 + 9);
+
+  { Upper case }
+  PROJECTM_K_A_UPPERCASE = 65;
+  PROJECTM_K_B_UPPERCASE = (PROJECTM_K_A_UPPERCASE +  1);
+  PROJECTM_K_C_UPPERCASE = (PROJECTM_K_A_UPPERCASE +  2);
+  PROJECTM_K_D_UPPERCASE = (PROJECTM_K_A_UPPERCASE +  3);
+  PROJECTM_K_E_UPPERCASE = (PROJECTM_K_A_UPPERCASE +  4);
+  PROJECTM_K_F_UPPERCASE = (PROJECTM_K_A_UPPERCASE +  5);
+  PROJECTM_K_G_UPPERCASE = (PROJECTM_K_A_UPPERCASE +  6);
+  PROJECTM_K_H_UPPERCASE = (PROJECTM_K_A_UPPERCASE +  7);
+  PROJECTM_K_I_UPPERCASE = (PROJECTM_K_A_UPPERCASE +  8);
+  PROJECTM_K_J_UPPERCASE = (PROJECTM_K_A_UPPERCASE +  9);
+  PROJECTM_K_K_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 10);
+  PROJECTM_K_L_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 11);
+  PROJECTM_K_M_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 12);
+  PROJECTM_K_N_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 13);
+  PROJECTM_K_O_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 14);
+  PROJECTM_K_P_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 15);
+  PROJECTM_K_Q_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 16);
+  PROJECTM_K_R_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 17);
+  PROJECTM_K_S_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 18);
+  PROJECTM_K_T_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 19);
+  PROJECTM_K_U_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 20);
+  PROJECTM_K_V_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 21);
+  PROJECTM_K_W_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 22);
+  PROJECTM_K_X_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 23);
+  PROJECTM_K_Y_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 24);
+  PROJECTM_K_Z_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 25);
+
+  { Lower case }
+  PROJECTM_K_a_LOWERCASE = 97;
+  PROJECTM_K_b_LOWERCASE = (PROJECTM_K_a_LOWERCASE +  1);
+  PROJECTM_K_c_LOWERCASE = (PROJECTM_K_a_LOWERCASE +  2);
+  PROJECTM_K_d_LOWERCASE = (PROJECTM_K_a_LOWERCASE +  3);
+  PROJECTM_K_e_LOWERCASE = (PROJECTM_K_a_LOWERCASE +  4);
+  PROJECTM_K_f_LOWERCASE = (PROJECTM_K_a_LOWERCASE +  5);
+  PROJECTM_K_g_LOWERCASE = (PROJECTM_K_a_LOWERCASE +  6);
+  PROJECTM_K_h_LOWERCASE = (PROJECTM_K_a_LOWERCASE +  7);
+  PROJECTM_K_i_LOWERCASE = (PROJECTM_K_a_LOWERCASE +  8);
+  PROJECTM_K_j_LOWERCASE = (PROJECTM_K_a_LOWERCASE +  9);
+  PROJECTM_K_k_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 10);
+  PROJECTM_K_l_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 11);
+  PROJECTM_K_m_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 12);
+  PROJECTM_K_n_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 13);
+  PROJECTM_K_o_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 14);
+  PROJECTM_K_p_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 15);
+  PROJECTM_K_q_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 16);
+  PROJECTM_K_r_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 17);
+  PROJECTM_K_s_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 18);
+  PROJECTM_K_t_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 19);
+  PROJECTM_K_u_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 20);
+  PROJECTM_K_v_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 21);
+  PROJECTM_K_w_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 22);
+  PROJECTM_K_x_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 23);
+  PROJECTM_K_y_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 24);
+  PROJECTM_K_z_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 25);
+
+  PROJECTM_K_NONE        = (PROJECTM_K_z_LOWERCASE + 1);
+
+{ Modifiers }
+type
+  TProjectMModifier = cint;
+const
+  PROJECTM_KMOD_LSHIFT = 0;
+  PROJECTM_KMOD_RSHIFT = 1;
+  PROJECTM_KMOD_CAPS   = 2;
+  PROJECTM_KMOD_LCTRL  = 3;
+  PROJECTM_KMOD_RCTRL  = 4;
+
+type
+  PSettings = ^TSettings;
+  TSettings = record
+    meshX: cint;
+    meshY: cint;
+    fps: cint;
+    textureSize: cint;
+    windowWidth: cint;
+    windowHeight: cint;
+    presetURL: PChar;
+    titleFontURL: PChar;
+    menuFontURL: PChar;
+    smoothPresetDuration: cint;
+    presetDuration: cint;
+    beatSensitivity: cfloat;
+    aspectCorrection: byte;
+    easterEgg: cfloat;
+    shuffleEnabled: byte;
+  end;
+
+type
+  PProjectM = ^TProjectM;
+  TProjectM = class(TObject)
+    private
+      data: Pointer;
+    public
+      {$IF PROJECTM_VERSION < 1000000} // 0.9x
+      constructor Create(gx, gy: integer; fps: integer;
+        texsize: integer; width, height: integer;
+        const presetsDir, fontsDir: string;
+        const titleFont: string = 'Vera.ttf';
+        const menuFont: string = 'Vera.ttf'); overload;
+      {$IFEND}
+      {$IF PROJECTM_VERSION >= 1000000}
+      constructor Create(const configFile: string); overload;
+      {$IFEND}
+
+      procedure ResetGL(width, height: Integer);
+      procedure SetTitle(const title: string);
+      procedure RenderFrame();
+
+      procedure AddPCMfloat(pcmData: PSingle; samples: integer);
+      procedure AddPCM16(pcmData: PPCM16);
+      procedure AddPCM16Data(pcmData: PSmallint; samples: Smallint);
+      procedure AddPCM8_512(pcmData: PPCM8_512);
+      {$IF PROJECTM_VERSION >= 1000000}
+      procedure AddPCM8_1024(pcmData: PPCM8_1024);
+      {$IFEND}
+
+      procedure RandomPreset();
+      procedure PreviousPreset();
+      procedure NextPreset();
+      procedure ToggleShowPresetNames();
+
+      {$IF PROJECTM_VERSION >= 1000000}
+      function InitRenderToTexture(): GLuint;
+      {$IFEND}
+
+      procedure KeyHandler(event:    TProjectMEvent;
+                           keycode:  TProjectMKeycode;
+                           modifier: TProjectMModifier);
+
+      {$IF PROJECTM_VERSION > 1000000} // > 1.01
+      procedure Settings(var settings: TSettings);
+      {$IFEND}
+
+      destructor Destroy(); override;
+  end;
+
+implementation
+
+{$IF PROJECTM_VERSION >= 1000000}
+  {$I projectM-1_0.inc}
+{$ELSE}
+  {$I projectM-0_9.inc}
+{$IFEND}
+
+end.
diff --git a/songmanagement/src/lib/requirements.txt b/songmanagement/src/lib/requirements.txt
new file mode 100644
index 00000000..d3955585
--- /dev/null
+++ b/songmanagement/src/lib/requirements.txt
@@ -0,0 +1,48 @@
+Included in SVN ..
+---------------------------------------------------------------------------
+
+
+Jedi-sdl
+  http://sourceforge.net/projects/jedi-sdl
+
+pngImage
+  http://pngdelphi.sourceforge.net/
+
+BASS.pas
+  http://www.un4seen.com/download.php?bass23
+
+ffmpeg
+  http://www.iversenit.dk/dev/ffmpeg-headers/
+
+SQLLite Wrapper
+  http://www.itwriting.com/sqlitesimple.php
+
+======================================
+LINUX build
+======================================
+On top of the above pas files, you will need development libraries for them.
+
+here are the instructions needed to compile on ubunty ( 7.04 )
+
+		sudo apt-get install libavcodec-dev libavformat-dev libsqlite3-dev libsdl-ttf2.0-dev libsdl-image1.2-dev portaudio19-dev 
+
+in order to build the configure file ( with autogen.sh )
+
+		sudo apt-get install automake autoconf
+
+
+for Fedora 8 ( contributed by kdub )
+
+		yum install ffmpeg-devel portaudio-devel SDL_ttf-devel SDL_image-devel sqlite-devel
+
+======================================
+Mac OS X build
+======================================
+You need the Developer tools from Apple, Xcode and fink, the open source software package manager.
+
+Install the FreePascal compiler (version 2.2.2 or later) using fink or a package.
+
+Install these libs and their dependences using fink:
+
+		fink install pkgconfig libavcodec-dev libavformat-dev libavutil-dev libswscale-dev
+		fink install portaudio2 SDL SDL-image libpng3 sqlite3-dev
\ No newline at end of file
diff --git a/songmanagement/src/lib/samplerate/samplerate.pas b/songmanagement/src/lib/samplerate/samplerate.pas
new file mode 100644
index 00000000..784b87da
--- /dev/null
+++ b/songmanagement/src/lib/samplerate/samplerate.pas
@@ -0,0 +1,199 @@
+{*
+** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.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.
+*}
+
+{*
+** API documentation is available here:
+** http://www.mega-nerd.com/SRC/api.html
+*}
+
+unit samplerate;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* GCC/Visual C/C++ compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+
+interface
+
+uses
+  ctypes,
+  UConfig;
+
+const
+{$IFDEF MSWINDOWS}
+  LibName = 'libsamplerate-0.dll';
+{$ENDIF}
+{$IFDEF UNIX}
+  LibName = 'samplerate';
+  {$IFDEF DARWIN}
+    {$LINKLIB libsamplerate}
+  {$ENDIF}
+{$ENDIF}
+
+{ Opaque data type SRC_STATE. }
+type
+  PSRC_STATE = ^SRC_STATE;
+  SRC_STATE = record
+    // opaque
+  end;
+
+{ SRC_DATA is used to pass data to src_simple() and src_process().  }
+type
+  PSRC_DATA = ^SRC_DATA;
+  SRC_DATA = record
+    data_in, data_out: PCfloat;
+    input_frames, output_frames: clong;
+    input_frames_used, output_frames_gen: clong;
+    end_of_input: cint;
+    src_ratio: cdouble;
+  end;
+
+{ SRC_CB_DATA is used with callback based API.  }
+type
+  SRC_CB_DATA = record
+    frames: clong;
+    data_in: PCfloat;
+  end;
+
+{*
+** User supplied callback function type for use with src_callback_new()
+** and src_callback_read(). First parameter is the same pointer that was
+** passed into src_callback_new(). Second parameter is pointer to a
+** pointer. The user supplied callback function must modify *data to
+** point to the start of the user supplied float array. The user supplied
+** function must return the number of frames that **data points to.
+*}
+src_callback_t = function (cb_data: pointer; var data: PCfloat): clong; cdecl;
+
+{*
+** Standard initialisation function : return an anonymous pointer to the
+** internal state of the converter. Choose a converter from the enums below.
+** Error returned in *error.
+*}
+function src_new(converter_type: cint; channels: cint; error: PCint): PSRC_STATE; cdecl; external LibName;
+
+{*
+** Initilisation for callback based API : return an anonymous pointer to the
+** internal state of the converter. Choose a converter from the enums below.
+** The cb_data pointer can point to any data or be set to NULL. Whatever the
+** value, when processing, user supplied function "func" gets called with
+** cb_data as first parameter.
+*}
+function src_callback_new(func: src_callback_t; converter_type: cint; channels: cint;
+            error: Pinteger; cb_data: pointer): PSRC_STATE; cdecl; external LibName;
+
+{*
+** Cleanup all internal allocations.
+** Always returns NULL.
+*}
+function src_delete(state: PSRC_STATE): PSRC_STATE; cdecl; external LibName;
+
+{*
+** Standard processing function.
+** Returns non zero on error.
+*}
+function src_process(state: PSRC_STATE; data: PSRC_DATA): cint; cdecl; external LibName;
+
+{*
+** Callback based processing function. Read up to frames worth of data from
+** the converter int *data and return frames read or -1 on error.
+*}
+function src_callback_read(state: PSRC_STATE; src_ratio: cdouble;
+            frames: clong; data: PCfloat): clong; cdecl; external LibName;
+
+{*
+** Simple interface for performing a single conversion from input buffer to
+** output buffer at a fixed conversion ratio.
+** Simple interface does not require initialisation as it can only operate on
+** a single buffer worth of audio.
+*}
+function src_simple(data: PSRC_DATA; converter_type: cint; channels: cint): cint; cdecl; external LibName;
+
+{*
+** This library contains a number of different sample rate converters,
+** numbered 0 through N.
+**
+** Return a string giving either a name or a more full description of each
+** sample rate converter or NULL if no sample rate converter exists for
+** the given value. The converters are sequentially numbered from 0 to N.
+*}
+function src_get_name(converter_type: cint): {const} Pchar; cdecl; external LibName;
+function src_get_description(converter_type: cint): {const} Pchar; cdecl; external LibName;
+function src_get_version(): {const} Pchar; cdecl; external LibName;
+
+{*
+** Set a new SRC ratio. This allows step responses
+** in the conversion ratio.
+** Returns non zero on error.
+*}
+function src_set_ratio(state: PSRC_STATE; new_ratio: cdouble): cint; cdecl; external LibName;
+
+{*
+** Reset the internal SRC state.
+** Does not modify the quality settings.
+** Does not free any memory allocations.
+** Returns non zero on error.
+*}
+function src_reset(state: PSRC_STATE): cint; cdecl; external LibName;
+
+{*
+** Return TRUE if ratio is a valid conversion ratio, FALSE
+** otherwise.
+*}
+function src_is_valid_ratio(ratio: cdouble): cint; cdecl; external LibName;
+
+{*
+** Return an error number.
+*}
+function src_error(state: PSRC_STATE): cint; cdecl; external LibName;
+
+{*
+** Convert the error number into a string.
+*}
+function src_strerror(error: cint): {const} Pchar; cdecl; external LibName;
+
+{*
+** The following enums can be used to set the interpolator type
+** using the function src_set_converter().
+*}
+const
+  SRC_SINC_BEST_QUALITY   = 0;
+  SRC_SINC_MEDIUM_QUALITY = 1;
+  SRC_SINC_FASTEST        = 2;
+  SRC_ZERO_ORDER_HOLD     = 3;
+  SRC_LINEAR              = 4;
+
+{*
+** Extra helper functions for converting from short to float and
+** back again.
+*}
+procedure src_short_to_float_array(input: {const} PCshort; output: PCfloat; len: cint); cdecl; external LibName;
+procedure src_float_to_short_array(input: {const} PCfloat; output: PCshort; len: cint); cdecl; external LibName;
+
+{$IF LIBSAMPLERATE_VERSION >= 1003} // 0.1.3
+procedure src_int_to_float_array(input: {const} PCint; output: PCfloat; len: cint); cdecl; external LibName;
+procedure src_float_to_int_array(input: {const} PCfloat; output: PCint; len: cint); cdecl; external LibName;
+{$IFEND}
+
+implementation
+
+end.
diff --git a/songmanagement/src/lib/zlib/zlib.pas b/songmanagement/src/lib/zlib/zlib.pas
new file mode 100644
index 00000000..8d09313f
--- /dev/null
+++ b/songmanagement/src/lib/zlib/zlib.pas
@@ -0,0 +1,215 @@
+(*
+ * zlib pascal headers
+ * This file is part of Free Pascal, released under the LGPL.
+ *)
+
+{$ifdef FPC}
+  {$ifndef NO_SMART_LINK}
+  {$smartlink on}
+  {$endif}
+{$endif}
+unit zlib;
+
+interface
+
+{$ifdef FPC}
+  {$mode objfpc} // Needed for array of const
+  {$H+} // use long strings
+  {$PACKRECORDS C}
+{$endif}
+
+uses
+  ctypes;
+
+const
+  ZLIB_VERSION = '1.2.3';
+
+{$ifdef MSWINDOWS}
+  libz = 'zlib1';
+{$else}
+  libz = 'z';
+  {$IFDEF DARWIN}
+    {$linklib libz}
+  {$ENDIF}
+{$endif}
+
+type
+  { Compatible with paszlib }
+  uInt    = cuint;
+  uLong   = culong;
+  uLongf  = uLong; {FAR}
+  PuLongf = ^uLongf;
+  z_off_t = clong;
+  pbyte   = ^byte;
+  bytef   = byte; {FAR}
+  pbytef  = ^byte; 
+  voidpf  = pointer;
+
+  TAllocfunc = function (opaque: voidpf; items: uInt; size: uInt): voidpf; cdecl;
+  TFreeFunc = procedure (opaque: voidpf; address: voidpf); cdecl;
+
+  TInternalState = record
+  end;
+  PInternalState = ^TInternalstate;
+
+  TZStream = record
+    next_in:   pbytef;
+    avail_in:  uInt;
+    total_in:  uLong;
+    next_out:  pbytef;
+    avail_out: uInt;
+    total_out: uLong;
+    msg:       pchar;
+    state:     PInternalState;
+    zalloc:    TAllocFunc;
+    zfree:     TFreeFunc;
+    opaque:    voidpf;
+    data_type: cint;
+    adler:     uLong;
+    reserved:  uLong;
+  end;
+  TZStreamRec = TZStream;
+  PZstream = ^TZStream;
+  gzFile = pointer;
+
+
+const
+  Z_NO_FLUSH      = 0;
+  Z_PARTIAL_FLUSH = 1;
+  Z_SYNC_FLUSH    = 2;
+  Z_FULL_FLUSH    = 3;
+  Z_FINISH        = 4;
+  Z_BLOCK         = 5;
+
+  Z_OK            = 0;
+  Z_STREAM_END    = 1;
+  Z_NEED_DICT     = 2;
+  Z_ERRNO         = -(1);
+  Z_STREAM_ERROR  = -(2);
+  Z_DATA_ERROR    = -(3);
+  Z_MEM_ERROR     = -(4);
+  Z_BUF_ERROR     = -(5);
+  Z_VERSION_ERROR = -(6);
+
+  Z_NO_COMPRESSION      = 0;
+  Z_BEST_SPEED          = 1;
+  Z_BEST_COMPRESSION    = 9;
+  Z_DEFAULT_COMPRESSION = -(1);
+
+  Z_FILTERED         = 1;
+  Z_HUFFMAN_ONLY     = 2;
+  Z_RLE              = 3;
+  Z_FIXED            = 4;
+  Z_DEFAULT_STRATEGY = 0;
+
+  Z_BINARY  = 0;
+  Z_TEXT    = 1;
+  Z_ASCII   = Z_TEXT;
+  Z_UNKNOWN = 2;
+
+  Z_DEFLATED = 8;
+
+  Z_NULL = 0;
+
+function zlibVersionpchar(): pchar; cdecl; external libz name 'zlibVersion';
+function zlibVersion(): string;
+
+function deflate(var strm: TZStream; flush: integer): integer; cdecl; external libz name 'deflate';
+function deflateEnd(var strm: TZStream): integer; cdecl; external libz name 'deflateEnd';
+function inflate(var strm: TZStream; flush: integer): integer; cdecl; external libz name 'inflate';
+function inflateEnd(var strm: TZStream): integer; cdecl; external libz name 'inflateEnd';
+function deflateSetDictionary(var strm: TZStream; dictionary: pbytef; dictLength: uInt): integer; cdecl; external libz name 'deflateSetDictionary';
+function deflateCopy(var dest, source: TZstream): integer; cdecl; external libz name 'deflateCopy';
+function deflateReset(var strm: TZStream): integer; cdecl; external libz name 'deflateReset';
+function deflateParams(var strm: TZStream; level: integer; strategy: integer): integer; cdecl; external libz name 'deflateParams';
+//...
+function inflateSetDictionary(var strm: TZStream; dictionary: pbytef; dictLength: uInt): integer; cdecl; external libz name 'inflateSetDictionary';
+function inflateSync(var strm: TZStream): integer; cdecl; external libz name 'inflateSync';
+//...
+function inflateReset(var strm: TZStream): integer; cdecl; external libz name 'inflateReset';
+
+function compress(dest: pbytef; destLen: puLongf; source : pbytef; sourceLen: uLong): integer; cdecl; external libz name 'compress';
+function compress2(dest: pbytef; destLen: puLongf; source : pbytef; sourceLen: uLong; level: integer): integer; cdecl; external libz name 'compress2';
+function uncompress(dest: pbytef; destLen: puLongf; source : pbytef; sourceLen: uLong): integer; cdecl; external libz name 'uncompress';
+
+function gzopen(path: pchar; mode: pchar): gzFile; cdecl; external libz name 'gzopen';
+function gzdopen(fd: integer; mode: pchar): gzFile; cdecl; external libz name 'gzdopen';
+function gzsetparams(thefile: gzFile; level: integer; strategy: integer): integer; cdecl; external libz name 'gzsetparams';
+function gzread(thefile: gzFile; buf: pointer; len: cardinal): integer; cdecl; external libz name 'gzread';
+function gzwrite(thefile: gzFile; buf: pointer; len: cardinal): integer; cdecl; external libz name 'gzwrite';
+function gzprintf(thefile: gzFile; format: pbytef; args: array of const): integer; cdecl; external libz name 'gzprintf';
+function gzputs(thefile: gzFile; s: pbytef): integer; cdecl; external libz name 'gzputs';
+function gzgets(thefile: gzFile; buf: pbytef; len: integer): pchar; cdecl; external libz name 'gzgets';
+function gzputc(thefile: gzFile; c: integer): integer; cdecl; external libz name 'gzputc';
+function gzgetc(thefile: gzFile): integer; cdecl; external libz name 'gzgetc';
+function gzflush(thefile: gzFile; flush: integer): integer; cdecl; external libz name 'gzflush';
+function gzseek(thefile: gzFile; offset: z_off_t; whence: integer): z_off_t; cdecl; external libz name 'gzseek';
+function gzrewind(thefile: gzFile): integer; cdecl; external libz name 'gzrewind';
+function gztell(thefile: gzFile): z_off_t; cdecl; external libz name 'gztell';
+function gzeof(thefile: gzFile): integer; cdecl; external libz name 'gzeof';
+function gzclose(thefile: gzFile): integer; cdecl; external libz name 'gzclose';
+function gzerror(thefile: gzFile; var errnum: integer): pchar; cdecl; external libz name 'gzerror';
+
+function adler32(adler: uLong; buf: pbytef; len: uInt): uLong; cdecl; external libz name 'adler32';
+function crc32(crc: uLong; buf: pbytef; len: uInt): uLong; cdecl; external libz name 'crc32';
+
+function deflateInit_(var strm: TZStream; level: integer; version: pchar; stream_size: integer): integer; cdecl; external libz name 'deflateInit_';
+function deflateInit(var strm: TZStream; level : integer) : integer;
+function inflateInit_(var strm: TZStream; version: pchar; stream_size: integer): integer; cdecl; external libz name 'inflateInit_';
+function inflateInit(var strm:TZStream) : integer;
+function deflateInit2_(var strm: TZStream; level: integer; method: integer; windowBits: integer; memLevel: integer; strategy: integer; version: pchar; stream_size: integer): integer; cdecl; external libz name 'deflateInit2_';
+function deflateInit2(var strm: TZStream; level, method, windowBits, memLevel, strategy: integer): integer;
+function inflateInit2_(var strm: TZStream; windowBits: integer; version: pchar; stream_size: integer): integer; cdecl; external libz name 'inflateInit2_';
+function inflateInit2(var strm: TZStream; windowBits: integer): integer;
+
+function zErrorpchar(err: integer): pchar; cdecl; external libz name 'zError';
+function zError(err: integer): string;
+function inflateSyncPoint(z: PZstream): integer; cdecl; external libz name 'inflateSyncPoint';
+function get_crc_table(): pointer; cdecl; external libz name 'get_crc_table';
+
+function zlibAllocMem(AppData: Pointer; Items, Size: Integer):  Pointer; cdecl;
+procedure zlibFreeMem(AppData, Block: Pointer);  cdecl;
+
+implementation
+
+function zlibversion(): string;
+begin
+   zlibversion := string(zlibversionpchar);
+end;
+
+function deflateInit(var strm: TZStream; level: integer) : integer;
+begin
+   deflateInit := deflateInit_(strm, level, ZLIB_VERSION, sizeof(TZStream));
+end;
+
+function inflateInit(var strm: TZStream): integer;
+begin
+   inflateInit := inflateInit_(strm, ZLIB_VERSION, sizeof(TZStream));
+end;
+
+function deflateInit2(var strm: TZStream; level, method, windowBits, memLevel, strategy: integer) : integer;
+begin
+   deflateInit2 := deflateInit2_(strm, level, method, windowBits, memLevel, strategy, ZLIB_VERSION, sizeof(TZStream));
+end;
+
+function inflateInit2(var strm: TZStream; windowBits: integer): integer;
+begin
+   inflateInit2 := inflateInit2_(strm, windowBits, ZLIB_VERSION, sizeof(TZStream));
+end;
+
+function zError(err: integer): string;
+begin
+   zerror := string(zErrorpchar(err));
+end;
+
+function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
+begin
+  Result := GetMemory(Items * Size);
+end;
+
+procedure zlibFreeMem(AppData, Block: Pointer); cdecl;
+begin
+  FreeMem(Block);
+end;
+
+end.
diff --git a/songmanagement/src/lua/UHookableEvent.pas b/songmanagement/src/lua/UHookableEvent.pas
new file mode 100644
index 00000000..8ad7ea9c
--- /dev/null
+++ b/songmanagement/src/lua/UHookableEvent.pas
@@ -0,0 +1,380 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UHookableEvent;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses ULua;
+
+type
+  { Record holding information about a hook of an event }
+  PHook = ^THook;
+  THook = record
+    Handle: Integer; //< Handle to identify the hook, e.g. for unhooking by plugin
+    Parent: Integer; //< Lua Core Handle this hook belongs to
+
+    Func: String;   //< Name of the global that holds the function
+
+    Next: PHook; //< Next Hook in list (nil for the first)
+  end;
+
+  { procedure is called before each call to the hooking lua functions, to push values on stack
+    returns the number of pushed arguments}
+  PrepareStackProc = Function(L: PLua_State): Integer;
+
+  { class representing a hookable event }
+  THookableEvent = class
+    private
+      iHandle: Integer; //< used to unregister at lua core
+      LastHook: PHook;  //< last hook in hook list, first to be called
+      NextHookHandle: Integer;  //< handle to identify next hook
+
+      sName: String;    //< the events name
+
+      PrepareStack: PrepareStackProc; //< prepare stack procedure passed to constructor
+      CallinProcess: boolean; //< true if a chain call is in process, to prepare unhooking during calls
+      HooksToRemove: array of PHook; // hooks to delete after chaincall
+
+      procedure RemoveWaitingHooks;
+    public
+      constructor Create(Name: String; const Proc: PrepareStackProc = nil);
+
+      property Name: String read sName;             //< returns the events name
+      property Handle: Integer read iHandle;        //< returns the events name
+
+      procedure Hook(L: Plua_State; Parent: Integer; Func: String); //< pushes hook object/table to the lua stack
+      procedure UnHook(L: Plua_State; hHook: Integer);              //< unhook by plugin. push true or error string to lua stack
+
+      procedure UnHookByParent(Parent: Integer);     //< deletes all hooks by a specified parent (unhook by core)
+
+      function CallHookChain(Breakable: Boolean): PLua_State;   //< calls the events hookchain. if breakable, plugin can breake the chain by returning a value != 0 or false or nil
+
+      destructor Destroy; override;
+  end;
+
+{ the default function for THookableEvent.PrepareStack it don't pass any arguments }
+function PrepareStack_Dummy(L: PLua_State): Integer;
+
+{ function in resulting hook table. it calls the unhook command of the event on plugins demand }
+function LuaHook_UnHook(L: Plua_State): Integer; cdecl;
+
+implementation
+uses ULuaCore;
+
+constructor THookableEvent.Create(Name: String; const Proc: PrepareStackProc);
+begin
+  inherited Create;
+  
+  Self.sName := Name;
+
+  if (@Proc = nil) then
+    Self.PrepareStack := @PrepareStack_Dummy
+  else
+    Self.PrepareStack := Proc;
+
+  //init LastHook pointer w/ nil
+  LastHook := nil;
+  NextHookHandle := 1;
+
+  iHandle := LuaCore.RegisterEvent(Self);
+end;
+
+destructor THookableEvent.Destroy;
+var
+  Prev: PHook;
+  Cur:  PHook;
+begin
+  //delete all hooks
+  Cur := LastHook;
+  While (Cur <> nil) do
+  begin
+    Prev := Cur;
+    Cur := Prev.Next;
+
+    Dispose(Prev);
+  end;
+
+  //remove from luacores list
+  LuaCore.UnRegisterEvent(iHandle);
+
+  inherited;
+end;
+
+{ adds hook to events list and pushes hook object/table to the lua stack }
+procedure  THookableEvent.Hook(L: PLua_State; Parent: Integer; Func: String);
+  var
+    Item: PHook;
+    P: TLuaPlugin;
+begin
+  P := LuaCore.GetPluginById(Parent);
+  if (P <> nil) then
+  begin
+    // get mem and fill it w/ data
+    New(Item);
+    Item.Handle := NextHookHandle;
+    Inc(NextHookHandle);
+
+    Item.Parent := Parent;
+    Item.Func := Func;
+
+    // add at front of the hook chain
+    Item.Next := LastHook;
+    LastHook := Item;
+
+    //we need 2 free stack slots
+    lua_checkstack(L, 2);
+
+    //create the hook table, we need 2 elements (event name and unhook function)
+    lua_createtable(L, 0, 2);
+
+    //push events name
+    lua_pushstring(L, PAnsiChar(Name));
+
+    //add the name to the table
+    lua_setfield(L, -2, 'Event');
+
+    //push hook id to the stack
+    lua_pushinteger(L, Item.Handle);
+
+    //create a c closure, append one value from stack(the id)
+    //this will pop both, the function and the id
+    lua_pushcclosure(L, LuaHook_UnHook, 1);
+
+    //add the function to our table
+    lua_setfield(L, -2, 'Unhook');
+
+    //the table is left on the stack, it is our result
+  end;
+end;
+
+{ removes hooks in HookstoRemove array from chain }
+procedure THookableEvent.RemoveWaitingHooks;
+  function IsInArray(Cur: PHook): boolean;
+    var I: Integer;
+  begin
+    Result := false;
+    for I := 0 to high(HooksToRemove) do
+      if (HooksToRemove[I] = Cur) then
+      begin
+        Result := true;
+        Break;
+      end;
+  end;
+
+  var
+    Cur, Prev: PHook;
+begin
+  Prev := nil;
+  Cur := LastHook;
+
+  while (Cur <> nil) do
+  begin
+    if (IsInArray(Cur)) then
+    begin //we found the hook
+      if (prev <> nil) then
+        Prev.Next := Cur.Next
+      else //last hook found
+        LastHook := Cur.Next;
+
+      //free hooks memory
+      Dispose(Cur);
+
+      if (prev <> nil) then
+        Cur := Prev.Next
+      else
+        Cur := LastHook;
+    end
+    else
+    begin
+      Prev := Cur;
+      Cur := Prev.Next;
+    end;
+  end;
+
+  SetLength(HooksToRemove, 0);
+end;
+
+{ unhook by plugin. push true or error string to lua stack }
+procedure  THookableEvent.UnHook(L: Plua_State; hHook: Integer);
+  var
+    Cur, Prev: PHook;
+    Len: integer;
+begin
+  if (hHook < NextHookHandle) and (hHook > 0) then
+  begin
+    //Search for the Hook
+    Prev := nil;
+    Cur := LastHook;
+
+    while (Cur <> nil) do
+    begin
+      if (Cur.Handle = hHook) then
+      begin //we found the hook
+        if not CallinProcess then
+        begin // => remove it
+          if (prev <> nil) then
+            Prev.Next := Cur.Next
+          else //last hook found
+            LastHook := Cur.Next;
+
+          //free hooks memory
+          Dispose(Cur);
+        end
+        else
+        begin // add to list of hooks to remove
+          Len := Length(HooksToRemove);
+          SetLength(HooksToRemove, Len + 1);
+          HooksToRemove[Len] := Cur;
+        end;
+        
+        //indicate success
+        lua_pushboolean(L, True);
+        exit; //break the chain and exit the function
+      end;
+      Prev := Cur;
+      Cur := Prev.Next;
+    end;
+
+    lua_pushstring(L, PAnsiChar('handle already unhooked')); //the error description
+  end
+  else
+    lua_pushstring(L, PAnsiChar('undefined hook handle')); //the error description
+end;
+
+{ deletes all hooks by a specified parent (unhook by core) }
+procedure  THookableEvent.UnHookByParent(Parent: Integer);
+  var
+    Cur, Prev: PHook;
+begin
+  Prev := nil;
+  Cur := LastHook;
+
+  While (Cur <> nil) do
+  begin
+    if (Cur.Parent = Parent) then
+    begin //found a hook from parent => remove it
+      if (Prev <> nil) then
+        Prev.Next := Cur.Next
+      Else
+        LastHook := Cur.Next;
+
+      Dispose(Cur);
+
+      if (Prev <> nil) then
+        Cur := Prev.Next
+      else
+        Cur := LastHook;
+    end
+    else //move through the chain
+    begin
+      Prev := Cur;
+      Cur := Prev.Next;
+    end;
+  end;
+end;
+
+{ calls the events hookchain. if breakable, plugin can breake the chain
+  by returning a value
+  breakable is pushed as the first parameter to the hooking functions
+  if chain is broken the LuaStack is returned, with all results left
+  you may call lua_clearstack }
+function  THookableEvent.CallHookChain(Breakable: Boolean): Plua_State;
+  var
+    Cur: PHook;
+    P: TLuaPlugin;
+begin
+  Result := nil;
+
+  CallinProcess := true;
+  
+  Cur := LastHook;
+  While (Cur <> nil) do
+  begin
+    P := LuaCore.GetPluginById(Cur.Parent);
+    lua_pushboolean(P.LuaState, Breakable);
+
+    if  (P.CallFunctionByName(Cur.Func, 1 + PrepareStack(P.LuaState), LUA_MULTRET))
+    and Breakable
+    and (lua_gettop(P.LuaState) > 0) then
+    begin //Chain Broken
+      Result := P.LuaState;
+      Break;
+    end;
+
+    Cur := Cur.Next;
+  end;
+
+  RemoveWaitingHooks;
+  CallinProcess := false;
+end;
+
+{ the default function for THookableEvent.PrepareStack it don't pass any arguments }
+function PrepareStack_Dummy(L: PLua_State): Integer;
+begin
+  Result := 0;
+end;
+
+{ function in resulting hook table. it calls the unhook command of the event on plugins demand }
+function LuaHook_UnHook(L: Plua_State): Integer; cdecl;
+  var
+    Name: string;
+    Event: THookableEvent;
+    hHook: integer;
+begin
+  Result := 0;
+
+  if not lua_isTable(L, 1) then
+    LuaL_Error(L, 'Can''t find hook table in LuaHook_Unhook. Please call Unhook with method seperator (colon) instead of a point.');
+
+  // get event name
+  Lua_GetField(L, 1, 'Event');
+  if not lua_isString(L, -1) then
+    LuaL_Error(L, 'Can''t get event name in LuaHook_Unhook');
+
+  Name := Lua_ToString(L, -1);
+
+  // get event by name
+  Event := LuaCore.GetEventbyName(Name);
+
+  // free stack slots
+  Lua_pop(L, Lua_GetTop(L));
+
+  if (Event = nil) then
+    LuaL_Error(L, PAnsiChar('event ' + Name + ' does not exist (anymore?) in LuaHook_Unhook'));
+
+  // get the hookid
+  hHook := lua_ToInteger(L, lua_upvalueindex(1));
+
+  Event.UnHook(L, hHook);
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/lua/ULuaCore.pas b/songmanagement/src/lua/ULuaCore.pas
new file mode 100644
index 00000000..ea9fd991
--- /dev/null
+++ b/songmanagement/src/lua/ULuaCore.pas
@@ -0,0 +1,1021 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaCore;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses SysUtils, ULua, UHookableEvent, UPath;
+
+type
+  { this exception is raised when the lua panic function
+    is called. Only in case we use call instead of pcall.
+    it has the lua error string in its message attribute }
+  ELuaException = class(Exception);
+
+  { record represents item of Eventlist of TLuaCore }
+  PEventListItem = ^TEventListItem;
+  TEventListItem = record
+    Event: THookableEvent;
+    Next:  PEventListItem;
+  end;
+
+  { record represents a module }
+  TLuaModule = record
+    Name:      string;
+    Functions: array of luaL_reg; //modules functions, w/ trailing nils this time
+  end;
+
+  TLuaPlugin_Status = (psNone, psRunning, psClosed, psErrorOnLoad, psErrorOnCall, psErrorInInit, psErrorOnRun);
+  { class represents a loaded plugin }
+  TLuaPlugin = class
+    private
+      iId:        integer;
+      Filename:   IPath;
+      State:      Plua_State; //< all functions of this plugin are called with this Lua state
+      bPaused:    boolean;    //< If true no lua functions from this state are called
+      ErrorCount: integer;    //< counts the errors that occured during function calls of this plugin
+      ShutDown:   boolean;    //< for self shutdown by plugin. true if plugin wants to be unloaded after execution of current function
+
+      sName:    string;
+      sVersion: string;
+      sAuthor:  string;
+      sURL:     string;
+
+      sStatus:  TLuaPlugin_Status;
+    public
+      constructor Create(Filename: IPath; Id: integer);
+
+      property Id:      integer read iId;
+      property Name:    string read sName;
+      property Version: string read sVersion;
+      property Author:  string read sAuthor;
+      property Url:     string read sUrl;
+
+      property Status:      TLuaPlugin_Status read sStatus;
+      property CountErrors: integer read ErrorCount;
+
+      property LuaState:    Plua_State read State;
+
+      procedure Load;
+
+      procedure Register(Name, Version, Author, Url: string);
+      function HasRegistred: boolean;
+
+      procedure PausePlugin(doPause: boolean);
+      property Paused: boolean read bPaused write PausePlugin;
+
+      procedure ShutMeDown;
+
+      { calls the lua function in the global w/ the given name.
+        the arguments to the function have to be pushed to the stack
+        before calling this function.
+        the arguments and the function will be removed from stack
+        results will not be removed.
+        if result is false there was an error calling the function
+        if ReportErrors is true the errorstring is popped from stack
+        and written to error.log otherwise it is left on stack}
+      function CallFunctionByName(Name:               string; 
+                                  const nArgs:        integer = 0;
+				  const nResults:     integer = 0;
+				  const ReportErrors: boolean = true): boolean;
+      procedure ClearStack;
+
+      procedure Unload; //< Destroys the Luastate, and frees as much mem as possible, w/o destroying the class and important information 
+
+      destructor Destroy; override;
+  end;
+
+  { class managing the plugins w/ their LuaStates, the events and modules
+    it also offers the usdx table to the plugins w/ some basic functionality
+    like self unload or hook getting}
+  TLuaCore = class
+    private
+      EventList:         PEventListItem;  //< pointer to first registred Event, ordered by name
+      EventHandles:      array of string; //< Index is Events handle, value is events name. if length(value) is 0 handle is considered unregistred
+
+      Plugins:           array of TLuaPlugin;
+
+      eLoadingFinished: THookableEvent;
+    protected
+      Modules: array of TLuaModule; //< modules that has been registred, has to be proctected because fucntions of this unit need to get access
+
+      function GetModuleIdByName(Name: string): integer; //returns id of given module, or -1 if module is not found
+    public
+      constructor Create;
+      destructor Destroy; override;
+
+      procedure LoadPlugins;                         //< calls LoadPlugin w/ Plugindir and LoadingFinished Eventchain
+
+      procedure BrowseDir(Dir: IPath);               //< searches for files w/ extension .usdx in the specified dir and tries to load them w/ lua
+      procedure LoadPlugin(Filename: IPath);         //< tries to load filename w/ lua and creates the default usdx lua environment for the plugins state
+
+      function GetPluginByName(Name: string): TLuaPlugin;
+      function GetPluginById(Id: integer): TLuaPlugin;
+
+      { this function adds a module loader for your functions
+        name is the name the script needs to write in its require()
+        Functions is an array of lua calling compatible functions
+        w/o trailing nils! }
+      procedure RegisterModule(Name: string; const Functions: array of luaL_reg);
+
+      function RegisterEvent(Event: THookableEvent): integer; //< adds the event to eventlist and returns its handle
+      procedure UnRegisterEvent(hEvent: integer);             //< removes the event from eventlist by handle
+
+      function GetEventbyName(Name: string): THookableEvent;       //< tries to find the event w/ the given name in the list
+      function GetEventbyHandle(hEvent: integer): THookableEvent;  //< tries to find the event w/ the given handle
+
+      procedure UnHookByParent(Parent: integer); //< remove all hooks by given parent id from all events
+
+      procedure PrepareState(L: Plua_State);
+
+      procedure DumpPlugins; //< prints plugin runtime information w/ Log.LogStatus
+  end;
+
+//some luastyle functions to call from lua scripts
+{ register global, used by plugins to identify
+  register(plugin name, plugin version, [plugin author], [plugin homepage])
+  can only be called once since the global "register" is niled by the function
+  returns true on success. (name does not exist)}
+function TLuaPlugin_Register (L: Plua_State): integer; cdecl;
+
+{ moduleloader for usdx.* modules
+  stored in package.loaders[3]
+  package.loaders[3] (module name)
+  returns a function to load the requested module or a error
+  description(string) when the module is not found }
+function TLuaCore_ModuleLoader (L: Plua_State): integer; cdecl;
+
+{ loads module specified by a cfunction upvalue to
+  usdx.modulename and returns it.
+  loadmodule(module name) }
+function TLuaCore_LoadModule (L: Plua_State): integer; cdecl;
+
+{ custom lua panic function
+  it writes error string to error.log and raises an ELuaException
+  that may be caught }
+function TLua_CustomPanic (L: Plua_State): integer; cdecl;
+
+{ replacement for luas require function
+  can be called with more than one parameter to require
+  some modules at once. e.g.: require('math', 'Usdx.Log')
+  modules are loaded from right to left
+  unlike standard require the module tables are not returned
+  the standard require function in _require is called by
+  this function }
+function TLua_CustomRequire(L: PLua_State): integer; cdecl;
+
+
+var
+  LuaCore: TLuaCore;
+
+implementation
+uses
+  StrUtils,
+  ULog,
+  UFilesystem,
+  ULuaUsdx,
+  UPathUtils,
+  ULuaUtils;
+
+constructor TLuaCore.Create;
+begin
+  inherited;
+
+  //init EventList w/ nil
+  EventList := nil;
+
+  eLoadingFinished := nil;
+end;
+
+destructor TLuaCore.Destroy;
+var
+  Cur:  PEventListItem;
+  Prev: PEventListItem;
+begin
+  SetLength(EventHandles, 0);
+
+  //delete event list
+  Cur := EventList;
+
+  while(Cur <> nil) do
+  begin
+    Prev := Cur;
+    Cur := Prev.Next;
+
+    Dispose(Prev);
+  end;
+
+  inherited;
+end;
+
+{ calls BrowseDir w/ plugin dir and LoadingFinished eventchain }
+procedure TLuaCore.LoadPlugins;
+begin
+  // we have to create event here, because in create it can
+  // not be registred, because LuaCore is no assigned
+  if (not Assigned(eLoadingFinished)) then
+    eLoadingFinished := THookableEvent.Create('Usdx.LoadingFinished');
+
+  BrowseDir(PluginPath);
+  eLoadingFinished.CallHookChain(false);
+end;
+
+{ searches for files w/ extension .usdx in the specified
+  dir and tries to load them w/ lua }
+procedure TLuaCore.BrowseDir(Dir: IPath);
+  var
+    Iter:     IFileIterator;
+    FileInfo: TFileInfo;
+    FileName: IPath;
+    Ext:      IPath;
+begin
+  Ext := Path('.usdx');
+
+  // search for all files and directories
+  Iter := FileSystem.FileFind(Dir.Append('*'), faAnyFile);
+  while (Iter.HasNext) do
+  begin
+    FileInfo := Iter.Next;
+    FileName := FileInfo.Name;
+    if ((FileInfo.Attr and faDirectory) <> 0) then
+    begin
+      if (not FileName.Equals('.')) and (not FileName.Equals('..')) then
+        BrowseDir(Dir.Append(FileName));
+    end
+    else
+    begin
+      if (Ext.Equals(FileName.GetExtension(), true)) then
+      begin
+        LoadPlugin(Dir.Append(FileName));
+      end;
+    end;
+  end;
+end;
+
+{ tries to load filename w/ lua and creates the default
+  usdx lua environment for the plugins state }
+procedure TLuaCore.LoadPlugin(Filename: IPath);
+  var
+    Len: integer;  
+begin
+  Len := Length(Plugins);
+  SetLength(Plugins, Len + 1);
+  Plugins[Len] := TLuaPlugin.Create(Filename, Len);
+  Plugins[Len].Load;
+end;
+
+{ returns Plugin on success nil on failure }
+function TLuaCore.GetPluginByName(Name: string): TLuaPlugin;
+  var
+    I: integer;
+begin
+  Result := nil;
+  Name := lowercase(Name);
+
+  for I := 0 to High(Plugins) do
+    if (lowercase(Plugins[I].Name) = Name) then
+    begin
+      Result := GetPluginById(I);
+      Exit;
+    end;
+end;
+
+{ returns Plugin on success nil on failure }
+function TLuaCore.GetPluginById(Id: integer): TLuaPlugin;
+begin
+  if (Id >= 0) and (Id <= High(Plugins)) then
+    Result := Plugins[Id]
+  else
+    Result := nil;
+end;
+
+{ this function adds a module loader for your functions
+  name is the name the script needs to write in its require()
+  Functions is an array of lua calling compatible functions
+  w/o trailing nils! }
+procedure TLuaCore.RegisterModule(Name: string; const Functions: array of luaL_reg);
+  var
+    Len:     integer;
+    FuncLen: integer;
+    I:       integer;
+begin
+  Len := Length(Modules);
+  SetLength(Modules, Len + 1);
+  Modules[Len].Name := Name;
+
+  FuncLen := Length(Functions);
+  SetLength(Modules[Len].Functions, FuncLen + 1);
+  
+  for I := 0 to FuncLen-1 do
+    Modules[Len].Functions[I] := Functions[I];
+
+  Modules[Len].Functions[FuncLen].name := nil;
+  Modules[Len].Functions[FuncLen].func := nil;
+end;
+
+{ adds the event to eventlist and returns its handle
+  called by THookableEvent on creation }
+function TLuaCore.RegisterEvent(Event: THookableEvent): integer;
+var
+  Cur, Prev, Item: PEventListItem;
+begin
+  if (Event <> nil) and (Length(Event.Name) > 0) then
+  begin
+    Result := Length(EventHandles);
+    SetLength(EventHandles, Result + 1); //get Handle and copy it to result
+
+    EventHandles[Result] := Event.Name;
+
+    //create eventlist item
+    New(Item);
+    Item.Event := Event;
+
+    //search for a place for this event in alphabetical order
+    Prev := nil;
+    Cur := EventList;
+
+    while (Cur <> nil) and (CompareStr(Cur.Event.Name, EventHandles[Result]) < 0) do
+    begin
+      Prev := Cur;
+      Cur := Prev.Next;
+    end;
+
+    //found the place => add new item
+    if (Prev <> nil) then
+      Prev.Next := Item
+    else //first item
+      EventList := Item;
+
+    Item.Next := Cur;
+  end
+  else
+    Result := -1;
+end;
+
+{ removes the event from eventlist by handle }
+procedure TLuaCore.UnRegisterEvent(hEvent: integer);
+  var
+    Cur, Prev: PEventListItem;
+begin
+  if (hEvent >= 0) and (hEvent <= High(EventHandles)) and (Length(EventHandles[hEvent]) > 0) then
+  begin //hEvent in bounds and not already deleted
+    //delete from eventlist
+    Prev := nil;
+    Cur  := EventList;
+
+    while (Cur <> nil) and (CompareStr(Cur.Event.Name, EventHandles[hEvent]) < 0) do
+    begin
+      Prev := Cur;
+      Cur  := Prev.Next;
+    end;
+
+    if (Cur <> nil) and (Cur.Event.Name = EventHandles[hEvent]) then
+    begin //delete if found
+      Prev.Next := Cur.Next; // remove from list
+      Dispose(Cur); // free memory
+    end;
+
+    //delete from handle array
+    EventHandles[hEvent] := '';
+  end;
+end;
+
+{ tries to find the event w/ the given name in the list
+  to-do : use binary search algorithm instead of linear search here
+          check whether this is possible (events are saved in a pointer list) }
+function TLuaCore.GetEventbyName(Name: string): THookableEvent;
+  var
+    Cur: PEventListItem;
+begin
+  Result := nil;
+
+  if (Length(Name) > 0) then
+  begin
+    //search in eventlist
+    Cur := EventList;
+
+    while (Cur <> nil) and (CompareStr(Cur.Event.Name, Name) < 0) do
+    begin
+      Cur := Cur.Next;
+    end;
+
+    if (Cur <> nil) and (Cur.Event.Name = Name) then
+    begin //we found what we want to find
+      Result := Cur.Event;
+    end;
+  end;
+end;
+
+{ tries to find the event w/ the given handle }
+function TLuaCore.GetEventbyHandle(hEvent: integer): THookableEvent;
+begin
+  if (hEvent >= 0) and (hEvent <= High(EventHandles)) and (Length(EventHandles[hEvent]) > 0) then
+  begin //hEvent in bounds and not already deleted
+    Result := GetEventByName(EventHandles[hEvent]);
+  end
+  else
+    Result := nil;
+end;
+
+{ remove all hooks by given parent id from all events }
+procedure TLuaCore.UnHookByParent(Parent: integer);
+  var
+    Cur: PEventListItem;
+begin
+  if (Parent >= 0) and (Parent <= High(Plugins)) then
+  begin
+    // go through event list
+    Cur := EventList;
+
+    while (Cur <> nil) do
+    begin
+      Cur.Event.UnHookByParent(Parent);
+      Cur := Cur.Next;
+    end;
+  end;
+end;
+
+{ prepares the given already opened Lua state with the
+  basic usdx environment, e.g.: base and package Modules,
+  usdx moduleloader and usdx table }
+procedure TLuaCore.PrepareState(L: Plua_State);
+begin
+  //load basic lib functionality
+  lua_pushcfunction(L, luaopen_base);
+  lua_call(L, 0, 0);
+  lua_pop(L, lua_gettop(L)); //pop the results
+
+  //load module functionality
+  lua_pushcfunction(L, luaopen_package);
+  lua_call(L, 0, 0);
+  lua_pop(L, lua_gettop(L)); //pop the results
+
+  { adds the loader for the other standard lib to package.preload table
+    plugins can call e.g. require('math') if they need math functionality }
+
+  // we need 3 free stack slots
+  lua_checkstack(L, 3);
+
+  // get package table
+  lua_getglobal (L, PChar('package'));
+
+  // get package.preload table
+  lua_getfield (L, -1, PChar('preload'));
+
+  {**** add string lib }
+
+  // push loader function
+  lua_pushcfunction(L, luaopen_string);
+
+  // set package.preload.x loader
+  lua_setfield (L, -2, PChar('string'));
+
+  {**** add table lib }
+
+  // push loader function
+  lua_pushcfunction(L, luaopen_table);
+
+  // set package.preload.x loader
+  lua_setfield (L, -2, PChar('table'));
+
+  {**** add math lib }
+
+  // push loader function
+  lua_pushcfunction(L, luaopen_math);
+
+  // set package.preload.x loader
+  lua_setfield (L, -2, PChar('math'));
+
+  {**** add os lib }
+
+  // push loader function
+  lua_pushcfunction(L, luaopen_os);
+
+  // set package.preload.x loader
+  lua_setfield (L, -2, PChar('os'));
+
+  //pop package.preload table from stack
+  lua_pop(L, 1);
+
+  // get package.loaders table
+  lua_getfield (L, -1, PChar('loaders'));
+
+  {**** Move C-Library and all-in-one module loader backwards,
+        slot 3 is free now }
+  // get package.loaders[4] function
+  lua_pushinteger(L, 5); //push new index
+  lua_pushinteger(L, 4); //push old index
+  lua_gettable (L, -3);
+
+  // and move it to package.loaders[5]
+  lua_settable (L, -3);
+
+  // get package.loaders[3] function
+  lua_pushinteger(L, 4); //push new index
+  lua_pushinteger(L, 3); //push old index
+  lua_gettable (L, -3);
+
+  // and move it to package.loaders[4]
+  lua_settable (L, -3);
+
+  {**** now we add the core module to package.loaders[3] }
+  lua_pushinteger(L, 3); //push new loaders index
+  lua_pushcfunction(L, TLuaCore_ModuleLoader);
+
+  // and move it to package.loaders[3]
+  lua_settable (L, -3);
+
+  //pop both package and package.loaders tables from stack
+  lua_pop(L, 2);
+
+  {**** replace the standard require w/ our custom require function }
+  // first move standard require function to _require
+  lua_getfield(L, LUA_GLOBALSINDEX, PChar('require'));
+  lua_setfield(L, LUA_GLOBALSINDEX, PChar('_require'));
+
+  // then save custom require function to require
+  lua_pushcfunction(L, TLua_CustomRequire);
+  lua_setfield(L, LUA_GLOBALSINDEX, PChar('require'));
+
+  {**** now we create the usdx table }
+  //at first functions from ULuaUsdx
+  luaL_register(L, 'Usdx', @ULuaUsdx_Lib_f[0]);
+end;
+
+{ returns id of given module, or -1 if module is not found }
+function TLuaCore.GetModuleIdByName(Name: string): integer;
+  var
+    I: integer;
+begin
+  Result := -1;
+  
+  for I := 0 to High(Modules) do
+    if (Modules[I].Name = Name) then
+    begin
+      Result := I;
+      Exit;
+    end;
+end;
+
+{ moduleloader for usdx.* modules
+  stored in package.loaders[3]
+  package.loaders[3] (module name)
+  returns a function to load the requested module or an error
+  description(string) when the module is not found }
+function TLuaCore_ModuleLoader (L: Plua_State): integer; cdecl;
+  var
+    Name: string;
+    ID:   integer;
+begin
+  Result := 1; //we will return one value in any case (or never return in case of an error)
+
+  if (lua_gettop(L) >= 1) then
+  begin
+    // pop all arguments but the first
+    if (lua_gettop(L) > 1) then
+      lua_pop(L, lua_gettop(L)-1);
+
+
+    if (lua_IsString(L, 1)) then
+    begin //we got the name => go get it
+      Name := lua_toString(L, 1);
+
+      //we need at least 6 letters
+      //and first 5 letters have to be usdx.
+      if (Length(Name) > 5) and (lowercase(copy(Name, 1, 5))='usdx.') then
+      begin
+        ID := LuaCore.GetModuleIdByName(copy(Name, 6, Length(Name) - 5));
+        if (ID >= 0) then
+        begin //found the module -> return loader function
+          lua_pushinteger(L, Id);
+          lua_pushcclosure(L, TLuaCore_LoadModule, 1);
+          //the function is the result, so we leave it on stack
+        end
+        else
+          lua_pushString(L, PChar('usdx module "' + Name + '" couldn''t be found'));
+      end
+      else
+        lua_pushString(L, PChar('module doesn''t have "Usdx." prefix'));
+
+    end
+    else
+      luaL_argerror(L, 1, PChar('string expected'));
+  end
+  else
+    luaL_error(L, PChar('no modulename specified in usdx moduleloader')); 
+end;
+
+{ loads module specified by a cfunction upvalue to
+  usdx.modulename and returns it.
+  loadmodule(module name) }
+function TLuaCore_LoadModule (L: Plua_State): integer; cdecl;
+  var
+    Id: integer;
+begin
+  if (not lua_isnoneornil(L, lua_upvalueindex(1))) then
+  begin
+    Id := lua_ToInteger(L, lua_upvalueindex(1));
+
+    luaL_register(L, PChar('Usdx.' + LuaCore.Modules[Id].Name), @LuaCore.Modules[Id].Functions[0]);
+
+    // set the modules table as global "modulename"
+    // so it can be accessed either by Usdx.modulename.x() or
+    // by modulename.x()
+    lua_setglobal(L, PChar(LuaCore.Modules[Id].Name));
+
+    // no we net to push the table again to return it
+    lua_getglobal(L, PChar(LuaCore.Modules[Id].Name));
+
+    Result := 1; //return table
+  end
+  else
+    luaL_error(L, PChar('no upvalue found in LuaCore_LoadModule'));
+end;
+
+{ prints plugin runtime information w/ Log.LogStatus }
+procedure TLuaCore.DumpPlugins;
+  function PluginStatusToString(Status: TLuaPlugin_Status): string;
+  begin
+    case Status of
+      psNone:        Result := 'not loaded';
+      psRunning:     Result := 'running';
+      psClosed:      Result := 'closed';
+      psErrorOnLoad: Result := 'error during load';
+      psErrorOnCall: Result := 'error during call';
+      psErrorInInit: Result := 'error in plugin_init()';
+      psErrorOnRun:  Result := 'error on function call';
+      else           Result := 'unknown';
+    end;
+  end;
+
+var
+  I: integer;
+begin
+  // print table header
+  Log.LogStatus(Format('%3s %-30s %-8s %-10s %-7s %-6s', [
+      '#', 'Name', 'Version', 'Status', 'Paused', '#Errors'
+  ]), 'LuaCore Plugins');
+
+  for I := 0 to High(Plugins) do
+    Log.LogStatus(Format('%3d %-30s %-8s %-10s %-7s %-6d', [
+        Plugins[I].Id, Plugins[I].Name, Plugins[I].Version,
+        PluginStatusToString(Plugins[I].Status),
+        BoolToStr(Plugins[I].Paused, true),
+        Plugins[I].CountErrors
+    ]), 'LuaCore Plugins');
+  if (High(Plugins) < 0) then
+    Log.LogError(' no plugins loaded ', 'LuaCore Plugins');
+end;
+
+// Implementation of TLuaPlugin
+//--------
+constructor TLuaPlugin.Create(Filename: IPath; Id: integer);
+begin
+  inherited Create;
+  Self.iId := Id;
+  Self.Filename := Filename;
+
+  // set some default attributes
+  Self.bPaused    := false;
+  Self.ErrorCount := 0;
+  Self.sName      := 'not registred';
+  Self.sStatus    := psNone;
+  Self.ShutDown   := false;
+
+  State := nil; //< to prevent calls to unopened state
+end;
+
+destructor TLuaPlugin.Destroy;
+begin
+  Unload;
+  inherited;
+end;
+
+{ does the main loading part
+  can not be called by create, because Plugins[Id] isn't defined there }
+procedure TLuaPlugin.Load;
+begin
+  // create Lua state for this plugin
+  State := luaL_newstate;
+
+  //set our custom panic function if s/t went wrong along the init
+  //we don't expect
+  lua_atPanic(State, TLua_CustomPanic);
+
+  if (LuaL_LoadFile(State, PChar(Filename.ToNative)) = 0) then
+  begin // file loaded successful
+    { note: we run the file here, but the environment isn't
+            set up now. it just causes the functions to
+            register in globals and runs the code in the file
+            body. At least there should be no code, it could
+            neither use functions from baselibs nor load libs
+            with require, this code would be useless. }
+    if (lua_pcall(State, 0, 0, 0) = 0) then
+    begin // file called successful
+
+      //let the core prepare our state
+      LuaCore.PrepareState(State);
+
+      // set register function
+      lua_checkstack(State, 2);
+      lua_pushinteger(State, Id);
+      lua_pushcclosure(State, TLuaPlugin_Register, 1); 
+      lua_setglobal(State, PChar('register'));
+
+      // write plugin id to registry
+      lua_pushinteger(State, iId);
+      lua_setfield (State, LUA_REGISTRYINDEX, '_USDX_STATE_ID');
+      lua_pop(State, Lua_GetTop(State));
+
+      // now run the plugin_init function
+      // plugin_init() if false or nothing is returned plugin init is aborted
+      if (CallFunctionByName('plugin_init', 0, 1)) then
+      begin
+        if (HasRegistred) and (sStatus = psNone) and (lua_toBoolean(State, 1)) then
+        begin
+          sStatus := psRunning;
+          ClearStack;
+        end
+        else
+          Unload;
+      end
+      else
+      begin
+        sStatus := psErrorInInit;
+        Log.LogError('error in plugin_init: ' + Self.Filename.ToNative, 'lua');
+        Unload;
+      end;
+    end
+    else
+    begin
+      sStatus := psErrorOnLoad;
+      Log.LogError(String(lua_toString(State, 1)), 'lua');
+      Log.LogError('unable to call file: ' + Self.Filename.ToNative, 'lua');
+      Unload;
+    end;
+
+  end
+  else
+  begin
+    sStatus := psErrorOnLoad;
+    Log.LogError(String(lua_toString(State, 1)), 'lua');
+    Log.LogError('unable to load file: ' + Self.Filename.ToNative, 'lua');
+    Unload;
+  end;
+end;
+
+procedure TLuaPlugin.Register(Name, Version, Author, Url: string);
+begin
+  sName    := Name;
+  sVersion := Version;
+  sAuthor  := Author;
+  sURL     := Url;
+end;
+
+{ returns true if plugin has called register }
+function TLuaPlugin.HasRegistred: boolean;
+begin
+  Result := (Self.sName <> 'not registred');
+end;
+
+procedure TLuaPlugin.PausePlugin(doPause: boolean);
+begin
+  bPaused := doPause;
+end;
+
+{ unload plugin after execution of the current function }
+procedure TLuaPlugin.ShutMeDown;
+begin
+  ShutDown := true;
+end;
+
+{ calls the lua function in the global w/ the given name.
+  the arguments to the function have to be pushed to the stack
+  before calling this function.
+  the arguments and the function will be removed from stack
+  results will not be removed.
+  if result is false there was an error calling the function,
+  if ReportErrors is true the errorstring is popped from stack
+  and written to error.log otherwise it is left on stack}
+function TLuaPlugin.CallFunctionByName(Name:               string; 
+                                       const nArgs:        integer;
+				       const nResults:     integer;
+				       const ReportErrors: boolean): boolean;
+begin
+  Result := false;
+  if (State <> nil) then
+  begin
+    if (not bPaused) then
+    begin
+      // we need at least one stack slot free
+      lua_checkstack(State, 1);
+
+      // lua_getglobal(State, PChar(Name)); //this is just a macro:
+      lua_getfield(State, LUA_GLOBALSINDEX, PChar(Name));
+
+      if (lua_isfunction(State, -1)) then
+      begin //we got a function
+        // move function in front of the arguments (if any)
+        if (nArgs > 0) then
+          lua_insert(State, -(nArgs + 1));
+
+        // call it!
+        if (lua_pcall(State, nArgs, nResults, 0) = 0) then
+          Result := true //called w/o errors
+        else //increase error counter
+          Inc (ErrorCount);
+      end
+      else
+      begin //we have to pop the args and the field we pushed from stack
+        lua_pop(State, nArgs + 1);
+        //leave an errormessage on stack
+        lua_pushstring(State, Pchar('could not find function named ' + Name));
+      end;
+    end
+    else
+    begin //we have to pop the args from stack
+      lua_pop(State, nArgs);
+      //leave an errormessage on stack
+      lua_pushstring(State, PChar('plugin paused'));
+    end;
+
+    if (not Result) and (ReportErrors) then
+      Log.LogError(lua_toString(State, -1), 'lua/' + sName);
+
+    if ShutDown then
+    begin // plugin indicates self shutdown
+      ShutDown := false;
+      Unload;
+      Result := false;
+    end
+  end
+  else
+  begin
+    Log.LogError('trying to call function of closed or not opened lua state', IfThen(HasRegistred, Name, Filename.ToUTF8));
+  end;
+end;
+
+{ removes all values from stack }
+procedure TLuaPlugin.ClearStack;
+begin
+  if (State <> nil) and (lua_gettop(State) > 0) then
+    lua_pop(State, lua_gettop(State));
+end;
+
+{ destroys the lua state, and frees as much mem as possible,
+  w/o destroying the class and important information }
+procedure TLuaPlugin.Unload;
+begin
+  if (State <> nil) then
+  begin
+    if (Status in [psRunning, psErrorOnRun]) then
+      CallFunctionByName('plugin_unload');
+
+    ClearStack;
+    lua_close(State);
+    State := nil; //don't forget to nil it ;)
+
+    LuaCore.UnHookByParent(iId);
+
+    if (sStatus = psRunning) then
+      sStatus := psClosed;
+  end;
+end;
+
+function TLuaPlugin_Register (L: Plua_State): integer; cdecl;
+  var
+    Id: integer;
+    P:  TLuaPlugin;
+    Name, Version, Author, Url: string;
+begin
+  if (lua_gettop(L) >= 2) then
+  begin // we got at least name and version
+    if (not lua_isNumber(L, lua_upvalueindex(1))) then
+      luaL_Error(L, PChar('upvalue missing'));
+
+    if (not lua_isString(L, 1)) then
+      luaL_ArgError(L, 1, 'string expected');
+
+    if (not lua_isString(L, 2)) then
+      luaL_ArgError(L, 1, 'string expected');
+
+    Id := lua_ToInteger(L, lua_upvalueindex(1));
+
+    //get version and name
+    Name    := lua_tostring(L, 1);
+    Version := lua_tostring(L, 2);
+
+    //get optional parameters
+    if (lua_isString(L, 3)) then //author
+      Author := lua_toString(L, 3)
+    else
+    begin
+      Author := 'unknown';
+    end;
+
+    // homepage
+    if (lua_isString(L, 4)) then
+      Url := lua_toString(L, 4)
+    else
+    begin
+      Url := '';
+    end;
+
+    //clear stack
+    if (lua_gettop(L) > 0) then
+      lua_pop(L, lua_gettop(L));
+
+    //call register
+    P := LuaCore.GetPluginById(Id);
+    if (P <> nil) then
+      P.Register(Name, Version, Author, Url)
+    else
+      luaL_error(L, PChar('wrong id in upstream'));
+
+    // remove function from global register
+    lua_pushnil(L);
+    lua_setglobal(L, PChar('register'));
+
+    // return true
+    Result := 1;
+    lua_pushboolean(L, true);  
+  end
+  else
+    luaL_error(L, PChar('not enough arguments, at least 2 expected. in TLuaPlugin_Register'));
+end;
+
+{ custom lua panic function
+  it writes error string to error.log and raises an ELuaException
+  that may be caught }
+function TLua_CustomPanic (L: Plua_State): integer; cdecl;
+  var
+    Msg: string;
+begin
+  if (lua_isString(L, -1)) then
+    Msg := lua_toString(L, -1)
+  else
+    Msg := 'undefined lua panic';
+
+  Log.LogError(Msg, 'lua');
+
+  raise ELuaException.Create(Msg);;
+
+  Result := 0;
+end;
+
+{ replacement for luas require function
+  can be called with more than one parameter to require
+  some modules at once. e.g.: require('math', 'Usdx.Log')
+  modules are loaded from right to left
+  unlike standard require the module tables are not returned
+  the standard require function in _require is called by
+  this function }
+function TLua_CustomRequire(L: PLua_State): integer; cdecl;
+begin
+  // no results
+  Result := 0;
+
+  // move through parameters
+  while (lua_getTop(L) >= 1) do
+  begin
+    // get luas require function
+    lua_getfield(L, LUA_GLOBALSINDEX, PChar('_require'));
+
+    // move it under the top param
+    lua_insert(L, -2);
+
+    // call it w/ next param (function + param are poped from stack)
+    lua_call(L, 1, 0);
+  end;
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/lua/ULuaGl.pas b/songmanagement/src/lua/ULuaGl.pas
new file mode 100644
index 00000000..178853b6
--- /dev/null
+++ b/songmanagement/src/lua/ULuaGl.pas
@@ -0,0 +1,1513 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaGl;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  gl,
+  ULua;
+
+function luaopen_gl (L: Plua_State): Integer; cdecl;
+function ULuaGl_StringToEnum(Str: String): GLenum;
+
+{ lua lib functions }
+function ULuaGl_Begin(L: Plua_State): Integer; cdecl;
+function ULuaGl_BindTexture(L: Plua_State): Integer; cdecl;
+function ULuaGl_BlendFunc(L: Plua_State): Integer; cdecl;
+function ULuaGl_Clear(L: Plua_State): Integer; cdecl;
+function ULuaGl_ClearAccum(L: Plua_State): Integer; cdecl;
+function ULuaGl_ClearColor(L: Plua_State): Integer; cdecl;
+function ULuaGl_Color(L: Plua_State): Integer; cdecl;
+function ULuaGl_CullFace(L: Plua_State): Integer; cdecl;
+function ULuaGl_DepthFunc(L: Plua_State): Integer; cdecl;
+function ULuaGl_DepthRange(L: Plua_State): Integer; cdecl;
+function ULuaGl_Disable(L: Plua_State): Integer; cdecl;
+function ULuaGl_DisableClientState(L: Plua_State): Integer; cdecl;
+function ULuaGl_DrawBuffer(L: Plua_State): Integer; cdecl;
+function ULuaGl_Enable(L: Plua_State): Integer; cdecl;
+function ULuaGl_EnableClientState(L: Plua_State): Integer; cdecl;
+function ULuaGl_End(L: Plua_State): Integer; cdecl;
+function ULuaGl_EndList(L: Plua_State): Integer; cdecl;
+function ULuaGl_Finish(L: Plua_State): Integer; cdecl;
+function ULuaGl_Flush(L: Plua_State): Integer; cdecl;
+function ULuaGl_FrontFace(L: Plua_State): Integer; cdecl;
+function ULuaGl_InitNames(L: Plua_State): Integer; cdecl;
+function ULuaGl_LoadIdentity(L: Plua_State): Integer; cdecl;
+function ULuaGl_LogicOp(L: Plua_State): Integer; cdecl;
+function ULuaGl_MatrixMode(L: Plua_State): Integer; cdecl;
+function ULuaGl_Ortho(L: Plua_State): Integer; cdecl;
+function ULuaGl_PopAttrib(L: Plua_State): Integer; cdecl;
+function ULuaGl_PopClientAttrib(L: Plua_State): Integer; cdecl;
+function ULuaGl_PopMatrix(L: Plua_State): Integer; cdecl;
+function ULuaGl_PopName(L: Plua_State): Integer; cdecl;
+function ULuaGl_PushMatrix(L: Plua_State): Integer; cdecl;
+function ULuaGl_RasterPos(L: Plua_State): Integer; cdecl;
+function ULuaGl_ReadBuffer(L: Plua_State): Integer; cdecl;
+function ULuaGl_Rect(L: Plua_State): Integer; cdecl;
+function ULuaGl_Rotate(L: Plua_State): Integer; cdecl;
+function ULuaGl_Scale(L: Plua_State): Integer; cdecl;
+function ULuaGl_ShadeModel(L: Plua_State): Integer; cdecl;
+function ULuaGl_TexCoord(L: Plua_State): Integer; cdecl;
+function ULuaGl_Translate(L: Plua_State): Integer; cdecl;
+function ULuaGl_Vertex(L: Plua_State): Integer; cdecl;
+function ULuaGl_Viewport(L: Plua_State): Integer; cdecl;
+function ULuaGl_Dummy(L: Plua_State): Integer; cdecl;
+
+const
+  ULuaGl_Lib_f: array [0..40] of lual_reg = (
+   (name:'Begin';func:ULuaGl_Begin),
+   (name:'BindTexture';func:ULuaGl_BindTexture),
+   (name:'BlendFunc';func:ULuaGl_BlendFunc),
+   (name:'Clear';func:ULuaGl_Clear),
+   (name:'ClearAccum';func:ULuaGl_ClearAccum),
+   (name:'ClearColor';func:ULuaGl_ClearColor),
+   (name:'Color';func:ULuaGl_Color),
+   (name:'CullFace';func:ULuaGl_CullFace),
+   (name:'DepthFunc';func:ULuaGl_DepthFunc),
+   (name:'DepthRange';func:ULuaGl_DepthRange),
+   (name:'Disable';func:ULuaGl_Disable),
+   (name:'DisableClientState';func:ULuaGl_DisableClientState),
+   (name:'DrawBuffer';func:ULuaGl_DrawBuffer),
+   (name:'Enable';func:ULuaGl_Enable),
+   (name:'EnableClientState';func:ULuaGl_EnableClientState),
+   (name:'End';func:ULuaGl_End),
+   (name:'EndList';func:ULuaGl_EndList),
+   (name:'Finish';func:ULuaGl_Finish),
+   (name:'Flush';func:ULuaGl_Flush),
+   (name:'FrontFace';func:ULuaGl_FrontFace),
+   (name:'InitNames';func:ULuaGl_InitNames),
+   (name:'LoadIdentity';func:ULuaGl_LoadIdentity),
+   (name:'LogicOp';func:ULuaGl_LogicOp),
+   (name:'MatrixMode';func:ULuaGl_MatrixMode),
+   (name:'Ortho';func:ULuaGl_Ortho),
+   (name:'PopAttrib';func:ULuaGl_PopAttrib),
+   (name:'PopClientAttrib';func:ULuaGl_PopClientAttrib),
+   (name:'PopMatrix';func:ULuaGl_PopMatrix),
+   (name:'PopName';func:ULuaGl_PopName),
+   (name:'PushMatrix';func:ULuaGl_PushMatrix),
+   (name:'RasterPos';func:ULuaGl_RasterPos),
+   (name:'ReadBuffer';func:ULuaGl_ReadBuffer),
+   (name:'Rotate';func:ULuaGl_Rotate),
+   (name:'Rect';func:ULuaGl_Rect),
+   (name:'Scale';func:ULuaGl_Scale),
+   (name:'ShadeModel';func:ULuaGl_ShadeModel),
+   (name:'TexCoord';func:ULuaGl_TexCoord),
+   (name:'Translate';func:ULuaGl_Translate),
+   (name:'Vertex';func:ULuaGl_Vertex),
+   (name:'Viewport';func:ULuaGl_Viewport),
+   (name:nil;func:nil)
+   );
+
+implementation
+
+uses
+   ULog;
+
+type
+  TULuaGl_Enums = record
+    Text:       string;
+    Value:      GLenum;
+  end;
+const
+  ULuaGl_EnumERROR = $fffffffe;
+
+function ULuaGl_Begin(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.Begin''');
+
+  glBegin(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_BindTexture(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.BindTexture''');
+
+  glBindTexture(e,lual_checkinteger(L,2));
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_BlendFunc(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+  f : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+  f := ULuaGl_StringToEnum(lual_checkstring(L,2));
+
+  if (e = ULuaGl_EnumERROR) or (f = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.BlendFunc''');
+
+  glBlendFunc(e,f);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_Clear(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.Clear''');
+
+  glClear(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_ClearAccum(L: Plua_State): Integer; cdecl;
+var
+  i: Integer;
+begin
+  if lua_istable(L, 1) then
+    for i := 1 to lua_objlen(L,1) do
+      lua_rawgeti(L,1,i);
+
+  if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+    glClearAccum(lual_checknumber(L,-4),
+                 lual_checknumber(L,-3),
+                 lual_checknumber(L,-2),
+                 lual_checknumber(L,-1))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.ClearAccum''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_ClearColor(L: Plua_State): Integer; cdecl;
+var
+  i: Integer;
+begin
+  if lua_istable(L, 1) then
+    for i := 1 to lua_objlen(L,1) do
+      lua_rawgeti(L,1,i);
+
+  if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+    glClearColor(lual_checknumber(L,-4),
+                 lual_checknumber(L,-3),
+                 lual_checknumber(L,-2),
+                 lual_checknumber(L,-1))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.ClearColor''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_Color(L: Plua_State): Integer; cdecl;
+var
+  i: Integer;
+begin
+  if lua_istable(L, 1) then
+    for i := 1 to lua_objlen(L,1) do
+      lua_rawgeti(L,1,i);
+
+  if (lua_istable(L, 1) and (lua_objlen(L,1) = 3)) or (lua_gettop(L) = 3) then
+    glColor3d(GLdouble(lual_checknumber(L,-3)),
+              GLdouble(lual_checknumber(L,-2)),
+              GLdouble(lual_checknumber(L,-1)))
+  else if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+    glColor4d(GLdouble(lual_checknumber(L,-4)),
+              GLdouble(lual_checknumber(L,-3)),
+              GLdouble(lual_checknumber(L,-2)),
+              GLdouble(lual_checknumber(L,-1)))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.Color''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_CullFace(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.CullFace''');
+
+  glCullFace(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_DepthFunc(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.DepthFunc''');
+
+  glDepthFunc(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_DepthRange(L: Plua_State): Integer; cdecl;
+var
+  i: Integer;
+begin
+  if lua_istable(L, 1) then
+    for i := 1 to lua_objlen(L,1) do
+      lua_rawgeti(L,1,i);
+
+  if  (lua_istable(L, 1) and (lua_objlen(L,1) = 2))
+  or  (lua_gettop(L) = 2) then
+    glDepthRange(lual_checkinteger(L,-2),
+                 lual_checkinteger(L,-1))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.DepthRange''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_Disable(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.Disable''');
+
+  glDisable(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_DisableClientState(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.DisableClientState''');
+
+  glDisableClientState(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_DrawBuffer(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.DrawBuffer''');
+
+  glDrawBuffer(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_Enable(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.Enable''');
+
+  glEnable(e);
+  result:=0; // number of results
+end;
+
+function ULuaGl_EnableClientState(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.EnableClientState''');
+
+  glEnableClientState(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_End(L: Plua_State): Integer; cdecl;
+begin
+  glEnd();
+  result:=0; // number of results
+end;
+
+function ULuaGl_EndList(L: Plua_State): Integer; cdecl;
+begin
+  glEndList();
+  result:=0; // number of results
+end;
+
+function ULuaGl_Finish(L: Plua_State): Integer; cdecl;
+begin
+  glFinish();
+  result:=0; // number of results
+end;
+
+function ULuaGl_Flush(L: Plua_State): Integer; cdecl;
+begin
+  glFlush();
+  result:=0; // number of results
+end;
+
+function ULuaGl_FrontFace(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.FrontFace''');
+
+  glFrontFace(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_InitNames(L: Plua_State): Integer; cdecl;
+begin
+  glInitNames();
+  result:=0; // number of results
+end;
+
+function ULuaGl_LoadIdentity(L: Plua_State): Integer; cdecl;
+begin
+  glLoadIdentity();
+  result:=0; // number of results
+end;
+
+function ULuaGl_LogicOp(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.LogicOp''');
+
+  glLogicOp(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_MatrixMode(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.MatrixMode''');
+
+  glMatrixMode(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_Ortho(L: Plua_State): Integer; cdecl;
+begin
+  if  (lua_gettop(L) = 6) then
+    glOrtho(lual_checkinteger(L,-6),
+            lual_checkinteger(L,-5),
+            lual_checkinteger(L,-4),
+            lual_checkinteger(L,-3),
+            lual_checkinteger(L,-2),
+            lual_checkinteger(L,-1))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.Ortho''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_PopAttrib(L: Plua_State): Integer; cdecl;
+begin
+  glPopAttrib();
+  result:=0; // number of results
+end;
+
+function ULuaGl_PopClientAttrib(L: Plua_State): Integer; cdecl;
+begin
+  glPopClientAttrib();
+  result:=0; // number of results
+end;
+
+function ULuaGl_PopMatrix(L: Plua_State): Integer; cdecl;
+begin
+  glPopMatrix();
+  result:=0; // number of results
+end;
+
+function ULuaGl_PopName(L: Plua_State): Integer; cdecl;
+begin
+  glPopName();
+  result:=0; // number of results
+end;
+
+function ULuaGl_PushMatrix(L: Plua_State): Integer; cdecl;
+begin
+  glPopName();
+  result:=0; // number of results
+end;
+
+function ULuaGl_RasterPos(L: Plua_State): Integer; cdecl;
+var
+  i: Integer;
+begin
+  if lua_istable(L, 1) then
+    for i := 1 to lua_objlen(L,1) do
+      lua_rawgeti(L,1,i);
+
+  if (lua_istable(L, 1) and (lua_objlen(L,1) = 2)) or (lua_gettop(L) = 2) then
+    glRasterPos2d(GLdouble(lual_checknumber(L,-2)),
+                  GLdouble(lual_checknumber(L,-1)))
+  else if (lua_istable(L, 1) and (lua_objlen(L,1) = 3)) or (lua_gettop(L) = 3) then
+    glRasterPos3d(GLdouble(lual_checknumber(L,-3)),
+                  GLdouble(lual_checknumber(L,-2)),
+                  GLdouble(lual_checknumber(L,-1)))
+  else if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+    glRasterPos4d(GLdouble(lual_checknumber(L,-4)),
+                  GLdouble(lual_checknumber(L,-3)),
+                  GLdouble(lual_checknumber(L,-2)),
+                  GLdouble(lual_checknumber(L,-1)))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.RasterPos''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_ReadBuffer(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.ReadBuffer''');
+
+  glReadBuffer(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_Rect(L: Plua_State): Integer; cdecl;
+var
+  i: Integer;
+begin
+  if lua_istable(L, 1) and lua_istable(L, 2) then
+  begin
+    for i := 1 to lua_objlen(L,1) do
+      lua_rawgeti(L,1,i);
+    for i := 1 to lua_objlen(L,2) do
+      lua_rawgeti(L,2,i);
+  end;
+
+  if  (lua_istable(L, 1) and (lua_objlen(L,1) = 2))
+  and (lua_istable(L, 2) and (lua_objlen(L,2) = 2))
+  or  (lua_gettop(L) = 4) then
+    glRectD(lual_checknumber(L,-4),
+            lual_checknumber(L,-3),
+            lual_checknumber(L,-2),
+            lual_checknumber(L,-1))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.Rect''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_Rotate(L: Plua_State): Integer; cdecl;
+begin
+  if  (lua_gettop(L) = 3) then
+    glRotated(lual_checkinteger(L,-4),
+              lual_checkinteger(L,-3),
+              lual_checkinteger(L,-2),
+              lual_checkinteger(L,-1))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.Rotate''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_Scale(L: Plua_State): Integer; cdecl;
+begin
+  if  (lua_gettop(L) = 3) then
+    glScaled(lual_checkinteger(L,-3),
+             lual_checkinteger(L,-2),
+             lual_checkinteger(L,-1))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.Scale''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_ShadeModel(L: Plua_State): Integer; cdecl;
+var
+  e : GLenum;
+begin
+  e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+  if (e = ULuaGl_EnumERROR) then
+    luaL_error(L, 'incorrect string argument to function ''gl.ShadeModel''');
+
+  glShadeModel(e);
+
+  result:=0; // number of results
+end;
+
+function ULuaGl_TexCoord(L: Plua_State): Integer; cdecl;
+var
+  i: Integer;
+begin
+  if lua_istable(L, 1) then
+    for i := 1 to lua_objlen(L,1) do
+      lua_rawgeti(L,1,i);
+
+  if (lua_istable(L, 1) and (lua_objlen(L,1) = 1)) or (lua_gettop(L) = 1) then
+    glTexCoord1d(GLdouble(lual_checknumber(L,-1)))
+  else if (lua_istable(L, 1) and (lua_objlen(L,1) = 2)) or (lua_gettop(L) = 2) then
+    glTexCoord2d(GLdouble(lual_checknumber(L,-2)),
+                 GLdouble(lual_checknumber(L,-1)))
+  else if (lua_istable(L, 1) and (lua_objlen(L,1) = 3)) or (lua_gettop(L) = 3) then
+    glTexCoord3d(GLdouble(lual_checknumber(L,-3)),
+                 GLdouble(lual_checknumber(L,-2)),
+                 GLdouble(lual_checknumber(L,-1)))
+  else if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+    glTexCoord4d(GLdouble(lual_checknumber(L,-4)),
+                 GLdouble(lual_checknumber(L,-3)),
+                 GLdouble(lual_checknumber(L,-2)),
+                 GLdouble(lual_checknumber(L,-1)))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.TexCoord''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_Translate(L: Plua_State): Integer; cdecl;
+begin
+  if  (lua_gettop(L) = 3) then
+    glTranslated(lual_checkinteger(L,-3),
+                 lual_checkinteger(L,-2),
+                 lual_checkinteger(L,-1))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.Translate''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_Vertex(L: Plua_State): Integer; cdecl;
+var
+  i: Integer;
+begin
+  if lua_istable(L, 1) then
+    for i := 1 to lua_objlen(L,1) do
+      lua_rawgeti(L,1,i);
+
+  if (lua_istable(L, 1) and (lua_objlen(L,1) = 2)) or (lua_gettop(L) = 2) then
+    glVertex2d(GLdouble(lual_checknumber(L,-2)),
+               GLdouble(lual_checknumber(L,-1)))
+  else if (lua_istable(L, 1) and (lua_objlen(L,1) = 3)) or (lua_gettop(L) = 3) then
+    glVertex3d(GLdouble(lual_checknumber(L,-3)),
+               GLdouble(lual_checknumber(L,-2)),
+               GLdouble(lual_checknumber(L,-1)))
+  else if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+    glVertex4d(GLdouble(lual_checknumber(L,-4)),
+               GLdouble(lual_checknumber(L,-3)),
+               GLdouble(lual_checknumber(L,-2)),
+               GLdouble(lual_checknumber(L,-1)))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.Vertex''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_Viewport(L: Plua_State): Integer; cdecl;
+var
+  i: Integer;
+begin
+  if lua_istable(L, 1) and lua_istable(L, 2) then
+  begin
+    for i := 1 to lua_objlen(L,1) do
+      lua_rawgeti(L,1,i);
+    for i := 1 to lua_objlen(L,2) do
+      lua_rawgeti(L,2,i);
+  end;
+
+  if  (lua_istable(L, 1) and (lua_objlen(L,1) = 2))
+  and (lua_istable(L, 2) and (lua_objlen(L,2) = 2))
+  or  (lua_gettop(L) = 4) then
+    glViewport(lual_checkinteger(L,-4),
+               lual_checkinteger(L,-3),
+               lual_checkinteger(L,-2),
+               lual_checkinteger(L,-1))
+  else
+    luaL_error(L, 'incorrect argument to function ''gl.Viewport''');
+  result:=0; // number of results
+end;
+
+function ULuaGl_Dummy(L: Plua_State): Integer; cdecl;
+begin
+  result:=0; // number of results
+end;
+
+function luaopen_gl (L: Plua_State): Integer; cdecl;
+begin
+    luaL_register(L,'gl',@ULuaGl_Lib_f[0]);
+    result:=1;
+end;
+
+(*
+  glAccum: procedure(op: GLenum; value: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAlphaFunc: procedure(func: GLenum; ref: GLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glAreTexturesResident: function (n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glArrayElement: procedure(i: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glBitmap: procedure (width, height: GLsizei; xorig, yorig: GLfloat; xmove, ymove: GLfloat; const bitmap: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCallList: procedure(list: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCallLists: procedure(n: GLsizei; atype: GLenum; const lists: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClearDepth: procedure(depth: GLclampd); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClearIndex: procedure(c: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClearStencil: procedure(s: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glClipPlane: procedure(plane: GLenum; const equation: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+  glColorMask: procedure(red, green, blue, alpha: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorMaterial: procedure(face, mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glColorPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyPixels: procedure(x, y: GLint; width, height: GLsizei; atype: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyTexImage1D: procedure (target: GLenum; level: GLint; internalFormat: GLenum; x, y: GLint; width: GLsizei; border: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyTexImage2D: procedure(target: GLenum; level: GLint; internalFormat: GLenum; x, y: GLint; width, height: GLsizei; border: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyTexSubImage1D: procedure(target: GLenum; level, xoffset, x, y: GLint; width: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glCopyTexSubImage2D: procedure(target: GLenum; level, xoffset, yoffset, x, y: GLint; width, height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteLists: procedure(list: GLuint; range: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDeleteTextures: procedure(n: GLsizei; const textures: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDepthMask: procedure(flag: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawArrays: procedure(mode: GLenum; first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawElements: procedure(mode: GLenum; count: GLsizei; atype: GLenum; const indices: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glDrawPixels: procedure(width, height: GLsizei; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEdgeFlag: procedure(flag: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEdgeFlagPointer: procedure(stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEdgeFlagv: procedure(const flag: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+  glEvalCoord1d: procedure(u: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord1dv: procedure(const u: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord1f: procedure(u: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord1fv: procedure(const u: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord2d: procedure(u, v: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord2dv: procedure(const u: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord2f: procedure(u, v: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalCoord2fv: procedure(const u: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+  glEvalMesh1: procedure(mode: GLenum; i1, i2: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalMesh2: procedure(mode: GLenum; i1, i2, j1, j2: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalPoint1: procedure(i: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glEvalPoint2: procedure(i, j: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFeedbackBuffer: procedure(size: GLsizei; atype: GLenum; buffer: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogfv: procedure(pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogi: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFogiv: procedure(pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glFrustum: procedure(left, right, bottom, top, zNear, zFar: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenLists: function(range: GLsizei): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGenTextures: procedure(n: GLsizei; textures: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetBooleanv: procedure(pname: GLenum; params: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetClipPlane: procedure(plane: GLenum; equation: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetDoublev: procedure(pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+//  glGetError: function: GLenum; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetFloatv: procedure(pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetIntegerv: procedure(pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetLightfv: procedure(light, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetLightiv: procedure(light, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapdv: procedure(target, query: GLenum; v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapfv: procedure(target, query: GLenum; v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMapiv: procedure(target, query: GLenum; v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMaterialfv: procedure(face, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetMaterialiv: procedure(face, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPixelMapfv: procedure(map: GLenum; values: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPixelMapuiv: procedure(map: GLenum; values: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPixelMapusv: procedure(map: GLenum; values: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPointerv: procedure(pname: GLenum; params: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetPolygonStipple: procedure(mask: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+/  glGetString: function(name: GLenum): PChar; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexEnvfv: procedure(target, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexEnviv: procedure(target, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexGendv: procedure(coord, pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexGenfv: procedure(coord, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexGeniv: procedure(coord, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexImage: procedure(target: GLenum; level: GLint; format: GLenum; atype: GLenum; pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexLevelParameterfv: procedure(target: GLenum; level: GLint; pname: GLenum; params: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexLevelParameteriv: procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexParameterfv: procedure(target, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glGetTexParameteriv: procedure(target, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glHint: procedure(target, mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexMask: procedure(mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+  glIndexPointer: procedure(atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexd: procedure(c: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexdv: procedure(const c: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexf: procedure(c: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexfv: procedure(const c: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexi: procedure(c: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexiv: procedure(const c: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexs: procedure(c: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexsv: procedure(const c: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexub: procedure(c: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIndexubv: procedure(const c: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+  glInterleavedArrays: procedure(format: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+/  glIsEnabled: function(cap: GLenum): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsList: function(list: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glIsTexture: function(texture: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightModelf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightModelfv: procedure(pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightModeli: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightModeliv: procedure(pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightf: procedure(light, pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightfv: procedure(light, pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLighti: procedure(light, pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLightiv: procedure(light, pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLineStipple: procedure(factor: GLint; pattern: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLineWidth: procedure(width: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glListBase: procedure(base: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadMatrixd: procedure(const m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadMatrixf: procedure(const m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glLoadName: procedure(name: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMap1d: procedure(target: GLenum; u1, u2: GLdouble; stride, order: GLint; const points: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMap1f: procedure(target: GLenum; u1, u2: GLfloat; stride, order: GLint; const points: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMap2d: procedure(target: GLenum; u1, u2: GLdouble; ustride, uorder: GLint; v1, v2: GLdouble; vstride, vorder: GLint; const points: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMap2f: procedure(target: GLenum; u1, u2: GLfloat; ustride, uorder: GLint; v1, v2: GLfloat; vstride, vorder: GLint; const points: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapGrid1d: procedure(un: GLint; u1, u2: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapGrid1f: procedure(un: GLint; u1, u2: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapGrid2d: procedure(un: GLint; u1, u2: GLdouble; vn: GLint; v1, v2: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMapGrid2f: procedure(un: GLint; u1, u2: GLfloat; vn: GLint; v1, v2: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMaterialf: procedure(face, pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMaterialfv: procedure(face, pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMateriali: procedure(face, pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMaterialiv: procedure(face, pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultMatrixd: procedure(const m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glMultMatrixf: procedure(const m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNewList: procedure(list: GLuint; mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3b: procedure(nx, ny, nz: GLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3bv: procedure(const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3d: procedure(nx, ny, nz: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3f: procedure(nx, ny, nz: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3i: procedure(nx, ny, nz: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3s: procedure(nx, ny, nz: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormal3sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glNormalPointer: procedure(atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPassThrough: procedure(token: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelMapfv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelMapuiv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelMapusv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelStoref: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelStorei: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelTransferf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelTransferi: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPixelZoom: procedure(xfactor, yfactor: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPointSize: procedure(size: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPolygonMode: procedure(face, mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPolygonOffset: procedure(factor, units: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPolygonStipple: procedure(const mask: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPrioritizeTextures: procedure(n: GLsizei; const textures: PGLuint; const priorities: PGLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPushAttrib: procedure(mask: GLbitfield); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPushClientAttrib: procedure(mask: GLbitfield); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glPushName: procedure(name: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glReadPixels: procedure(x, y: GLint; width, height: GLsizei; format, atype: GLenum; pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+  glRenderMode: function(mode: GLint): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glScissor: procedure(x, y: GLint; width, height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glSelectBuffer: procedure(size: GLsizei; buffer: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilFunc: procedure(func: GLenum; ref: GLint; mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilMask: procedure(mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glStencilOp: procedure(fail, zfail, zpass: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+  glTexCoordPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexEnvf: procedure(target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexEnvfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexEnvi: procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexEnviv: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGend: procedure(coord: GLenum; pname: GLenum; param: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGendv: procedure(coord: GLenum; pname: GLenum; const params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGenf: procedure(coord: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGenfv: procedure(coord: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGeni: procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexGeniv: procedure(coord: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexImage1D: procedure(target: GLenum; level, internalformat: GLint; width: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexImage2D: procedure(target: GLenum; level, internalformat: GLint; width, height: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexParameterf: procedure(target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexParameterfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexParameteri: procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexParameteriv: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexSubImage1D: procedure(target: GLenum; level, xoffset: GLint; width: GLsizei; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glTexSubImage2D: procedure(target: GLenum; level, xoffset, yoffset: GLint; width, height: GLsizei; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  glVertexPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  {$IFDEF WINDOWS}
+  ChoosePixelFormat: function(DC: HDC; p2: PPixelFormatDescriptor): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+  {$ENDIF}
+  *)
+
+  const
+  ULuaGl_Enum: array [0..579] of TULuaGl_Enums = (
+    (Text:'GL_VERSION_1_1';Value:GL_VERSION_1_1),
+    (Text:'GL_ACCUM';Value:GL_ACCUM),
+    (Text:'GL_LOAD';Value:GL_LOAD),
+    (Text:'GL_RETURN';Value:GL_RETURN),
+    (Text:'GL_MULT';Value:GL_MULT),
+    (Text:'GL_ADD';Value:GL_ADD),
+    (Text:'GL_NEVER';Value:GL_NEVER),
+    (Text:'GL_LESS';Value:GL_LESS),
+    (Text:'GL_EQUAL';Value:GL_EQUAL),
+    (Text:'GL_LEQUAL';Value:GL_LEQUAL),
+    (Text:'GL_GREATER';Value:GL_GREATER),
+    (Text:'GL_NOTEQUAL';Value:GL_NOTEQUAL),
+    (Text:'GL_GEQUAL';Value:GL_GEQUAL),
+    (Text:'GL_ALWAYS';Value:GL_ALWAYS),
+    (Text:'GL_CURRENT_BIT';Value:GL_CURRENT_BIT),
+    (Text:'GL_POINT_BIT';Value:GL_POINT_BIT),
+    (Text:'GL_LINE_BIT';Value:GL_LINE_BIT),
+    (Text:'GL_POLYGON_BIT';Value:GL_POLYGON_BIT),
+    (Text:'GL_POLYGON_STIPPLE_BIT';Value:GL_POLYGON_STIPPLE_BIT),
+    (Text:'GL_PIXEL_MODE_BIT';Value:GL_PIXEL_MODE_BIT),
+    (Text:'GL_LIGHTING_BIT';Value:GL_LIGHTING_BIT),
+    (Text:'GL_FOG_BIT';Value:GL_FOG_BIT),
+    (Text:'GL_DEPTH_BUFFER_BIT';Value:GL_DEPTH_BUFFER_BIT),
+    (Text:'GL_ACCUM_BUFFER_BIT';Value:GL_ACCUM_BUFFER_BIT),
+    (Text:'GL_STENCIL_BUFFER_BIT';Value:GL_STENCIL_BUFFER_BIT),
+    (Text:'GL_VIEWPORT_BIT';Value:GL_VIEWPORT_BIT),
+    (Text:'GL_TRANSFORM_BIT';Value:GL_TRANSFORM_BIT),
+    (Text:'GL_ENABLE_BIT';Value:GL_ENABLE_BIT),
+    (Text:'GL_COLOR_BUFFER_BIT';Value:GL_COLOR_BUFFER_BIT),
+    (Text:'GL_HINT_BIT';Value:GL_HINT_BIT),
+    (Text:'GL_EVAL_BIT';Value:GL_EVAL_BIT),
+    (Text:'GL_LIST_BIT';Value:GL_LIST_BIT),
+    (Text:'GL_TEXTURE_BIT';Value:GL_TEXTURE_BIT),
+    (Text:'GL_SCISSOR_BIT';Value:GL_SCISSOR_BIT),
+    (Text:'GL_ALL_ATTRIB_BITS';Value:GL_ALL_ATTRIB_BITS),
+    (Text:'GL_POINTS';Value:GL_POINTS),
+    (Text:'GL_LINES';Value:GL_LINES),
+    (Text:'GL_LINE_LOOP';Value:GL_LINE_LOOP),
+    (Text:'GL_LINE_STRIP';Value:GL_LINE_STRIP),
+    (Text:'GL_TRIANGLES';Value:GL_TRIANGLES),
+    (Text:'GL_TRIANGLE_STRIP';Value:GL_TRIANGLE_STRIP),
+    (Text:'GL_TRIANGLE_FAN';Value:GL_TRIANGLE_FAN),
+    (Text:'GL_QUADS';Value:GL_QUADS),
+    (Text:'GL_QUAD_STRIP';Value:GL_QUAD_STRIP),
+    (Text:'GL_POLYGON';Value:GL_POLYGON),
+    (Text:'GL_ZERO';Value:GL_ZERO),
+    (Text:'GL_ONE';Value:GL_ONE),
+    (Text:'GL_SRC_COLOR';Value:GL_SRC_COLOR),
+    (Text:'GL_ONE_MINUS_SRC_COLOR';Value:GL_ONE_MINUS_SRC_COLOR),
+    (Text:'GL_SRC_ALPHA';Value:GL_SRC_ALPHA),
+    (Text:'GL_ONE_MINUS_SRC_ALPHA';Value:GL_ONE_MINUS_SRC_ALPHA),
+    (Text:'GL_DST_ALPHA';Value:GL_DST_ALPHA),
+    (Text:'GL_ONE_MINUS_DST_ALPHA';Value:GL_ONE_MINUS_DST_ALPHA),
+    (Text:'GL_DST_COLOR';Value:GL_DST_COLOR),
+    (Text:'GL_ONE_MINUS_DST_COLOR';Value:GL_ONE_MINUS_DST_COLOR),
+    (Text:'GL_SRC_ALPHA_SATURATE';Value:GL_SRC_ALPHA_SATURATE),
+    (Text:'GL_TRUE';Value:GL_TRUE),
+    (Text:'GL_FALSE';Value:GL_FALSE),
+    (Text:'GL_CLIP_PLANE0';Value:GL_CLIP_PLANE0),
+    (Text:'GL_CLIP_PLANE1';Value:GL_CLIP_PLANE1),
+    (Text:'GL_CLIP_PLANE2';Value:GL_CLIP_PLANE2),
+    (Text:'GL_CLIP_PLANE3';Value:GL_CLIP_PLANE3),
+    (Text:'GL_CLIP_PLANE4';Value:GL_CLIP_PLANE4),
+    (Text:'GL_CLIP_PLANE5';Value:GL_CLIP_PLANE5),
+    (Text:'GL_BYTE';Value:GL_BYTE),
+    (Text:'GL_UNSIGNED_BYTE';Value:GL_UNSIGNED_BYTE),
+    (Text:'GL_SHORT';Value:GL_SHORT),
+    (Text:'GL_UNSIGNED_SHORT';Value:GL_UNSIGNED_SHORT),
+    (Text:'GL_INT';Value:GL_INT),
+    (Text:'GL_UNSIGNED_INT';Value:GL_UNSIGNED_INT),
+    (Text:'GL_FLOAT';Value:GL_FLOAT),
+    (Text:'GL_2_BYTES';Value:GL_2_BYTES),
+    (Text:'GL_3_BYTES';Value:GL_3_BYTES),
+    (Text:'GL_4_BYTES';Value:GL_4_BYTES),
+    (Text:'GL_DOUBLE';Value:GL_DOUBLE),
+    (Text:'GL_NONE';Value:GL_NONE),
+    (Text:'GL_FRONT_LEFT';Value:GL_FRONT_LEFT),
+    (Text:'GL_FRONT_RIGHT';Value:GL_FRONT_RIGHT),
+    (Text:'GL_BACK_LEFT';Value:GL_BACK_LEFT),
+    (Text:'GL_BACK_RIGHT';Value:GL_BACK_RIGHT),
+    (Text:'GL_FRONT';Value:GL_FRONT),
+    (Text:'GL_BACK';Value:GL_BACK),
+    (Text:'GL_LEFT';Value:GL_LEFT),
+    (Text:'GL_RIGHT';Value:GL_RIGHT),
+    (Text:'GL_FRONT_AND_BACK';Value:GL_FRONT_AND_BACK),
+    (Text:'GL_AUX0';Value:GL_AUX0),
+    (Text:'GL_AUX1';Value:GL_AUX1),
+    (Text:'GL_AUX2';Value:GL_AUX2),
+    (Text:'GL_AUX3';Value:GL_AUX3),
+    (Text:'GL_NO_ERROR';Value:GL_NO_ERROR),
+    (Text:'GL_INVALID_ENUM';Value:GL_INVALID_ENUM),
+    (Text:'GL_INVALID_VALUE';Value:GL_INVALID_VALUE),
+    (Text:'GL_INVALID_OPERATION';Value:GL_INVALID_OPERATION),
+    (Text:'GL_STACK_OVERFLOW';Value:GL_STACK_OVERFLOW),
+    (Text:'GL_STACK_UNDERFLOW';Value:GL_STACK_UNDERFLOW),
+    (Text:'GL_OUT_OF_MEMORY';Value:GL_OUT_OF_MEMORY),
+    (Text:'GL_2D';Value:GL_2D),
+    (Text:'GL_3D';Value:GL_3D),
+    (Text:'GL_3D_COLOR';Value:GL_3D_COLOR),
+    (Text:'GL_3D_COLOR_TEXTURE';Value:GL_3D_COLOR_TEXTURE),
+    (Text:'GL_4D_COLOR_TEXTURE';Value:GL_4D_COLOR_TEXTURE),
+    (Text:'GL_PASS_THROUGH_TOKEN';Value:GL_PASS_THROUGH_TOKEN),
+    (Text:'GL_POINT_TOKEN';Value:GL_POINT_TOKEN),
+    (Text:'GL_LINE_TOKEN';Value:GL_LINE_TOKEN),
+    (Text:'GL_POLYGON_TOKEN';Value:GL_POLYGON_TOKEN),
+    (Text:'GL_BITMAP_TOKEN';Value:GL_BITMAP_TOKEN),
+    (Text:'GL_DRAW_PIXEL_TOKEN';Value:GL_DRAW_PIXEL_TOKEN),
+    (Text:'GL_COPY_PIXEL_TOKEN';Value:GL_COPY_PIXEL_TOKEN),
+    (Text:'GL_LINE_RESET_TOKEN';Value:GL_LINE_RESET_TOKEN),
+    (Text:'GL_EXP';Value:GL_EXP),
+    (Text:'GL_EXP2';Value:GL_EXP2),
+    (Text:'GL_CW';Value:GL_CW),
+    (Text:'GL_CCW';Value:GL_CCW),
+    (Text:'GL_COEFF';Value:GL_COEFF),
+    (Text:'GL_ORDER';Value:GL_ORDER),
+    (Text:'GL_DOMAIN';Value:GL_DOMAIN),
+    (Text:'GL_CURRENT_COLOR';Value:GL_CURRENT_COLOR),
+    (Text:'GL_CURRENT_INDEX';Value:GL_CURRENT_INDEX),
+    (Text:'GL_CURRENT_NORMAL';Value:GL_CURRENT_NORMAL),
+    (Text:'GL_CURRENT_TEXTURE_COORDS';Value:GL_CURRENT_TEXTURE_COORDS),
+    (Text:'GL_CURRENT_RASTER_COLOR';Value:GL_CURRENT_RASTER_COLOR),
+    (Text:'GL_CURRENT_RASTER_INDEX';Value:GL_CURRENT_RASTER_INDEX),
+    (Text:'GL_CURRENT_RASTER_TEXTURE_COORDS';Value:GL_CURRENT_RASTER_TEXTURE_COORDS),
+    (Text:'GL_CURRENT_RASTER_POSITION';Value:GL_CURRENT_RASTER_POSITION),
+    (Text:'GL_CURRENT_RASTER_POSITION_VALID';Value:GL_CURRENT_RASTER_POSITION_VALID),
+    (Text:'GL_CURRENT_RASTER_DISTANCE';Value:GL_CURRENT_RASTER_DISTANCE),
+    (Text:'GL_POINT_SMOOTH';Value:GL_POINT_SMOOTH),
+    (Text:'GL_POINT_SIZE';Value:GL_POINT_SIZE),
+    (Text:'GL_POINT_SIZE_RANGE';Value:GL_POINT_SIZE_RANGE),
+    (Text:'GL_POINT_SIZE_GRANULARITY';Value:GL_POINT_SIZE_GRANULARITY),
+    (Text:'GL_LINE_SMOOTH';Value:GL_LINE_SMOOTH),
+    (Text:'GL_LINE_WIDTH';Value:GL_LINE_WIDTH),
+    (Text:'GL_LINE_WIDTH_RANGE';Value:GL_LINE_WIDTH_RANGE),
+    (Text:'GL_LINE_WIDTH_GRANULARITY';Value:GL_LINE_WIDTH_GRANULARITY),
+    (Text:'GL_LINE_STIPPLE';Value:GL_LINE_STIPPLE),
+    (Text:'GL_LINE_STIPPLE_PATTERN';Value:GL_LINE_STIPPLE_PATTERN),
+    (Text:'GL_LINE_STIPPLE_REPEAT';Value:GL_LINE_STIPPLE_REPEAT),
+    (Text:'GL_LIST_MODE';Value:GL_LIST_MODE),
+    (Text:'GL_MAX_LIST_NESTING';Value:GL_MAX_LIST_NESTING),
+    (Text:'GL_LIST_BASE';Value:GL_LIST_BASE),
+    (Text:'GL_LIST_INDEX';Value:GL_LIST_INDEX),
+    (Text:'GL_POLYGON_MODE';Value:GL_POLYGON_MODE),
+    (Text:'GL_POLYGON_SMOOTH';Value:GL_POLYGON_SMOOTH),
+    (Text:'GL_POLYGON_STIPPLE';Value:GL_POLYGON_STIPPLE),
+    (Text:'GL_EDGE_FLAG';Value:GL_EDGE_FLAG),
+    (Text:'GL_CULL_FACE';Value:GL_CULL_FACE),
+    (Text:'GL_CULL_FACE_MODE';Value:GL_CULL_FACE_MODE),
+    (Text:'GL_FRONT_FACE';Value:GL_FRONT_FACE),
+    (Text:'GL_LIGHTING';Value:GL_LIGHTING),
+    (Text:'GL_LIGHT_MODEL_LOCAL_VIEWER';Value:GL_LIGHT_MODEL_LOCAL_VIEWER),
+    (Text:'GL_LIGHT_MODEL_TWO_SIDE';Value:GL_LIGHT_MODEL_TWO_SIDE),
+    (Text:'GL_LIGHT_MODEL_AMBIENT';Value:GL_LIGHT_MODEL_AMBIENT),
+    (Text:'GL_SHADE_MODEL';Value:GL_SHADE_MODEL),
+    (Text:'GL_COLOR_MATERIAL_FACE';Value:GL_COLOR_MATERIAL_FACE),
+    (Text:'GL_COLOR_MATERIAL_PARAMETER';Value:GL_COLOR_MATERIAL_PARAMETER),
+    (Text:'GL_COLOR_MATERIAL';Value:GL_COLOR_MATERIAL),
+    (Text:'GL_FOG';Value:GL_FOG),
+    (Text:'GL_FOG_INDEX';Value:GL_FOG_INDEX),
+    (Text:'GL_FOG_DENSITY';Value:GL_FOG_DENSITY),
+    (Text:'GL_FOG_START';Value:GL_FOG_START),
+    (Text:'GL_FOG_END';Value:GL_FOG_END),
+    (Text:'GL_FOG_MODE';Value:GL_FOG_MODE),
+    (Text:'GL_FOG_COLOR';Value:GL_FOG_COLOR),
+    (Text:'GL_DEPTH_RANGE';Value:GL_DEPTH_RANGE),
+    (Text:'GL_DEPTH_TEST';Value:GL_DEPTH_TEST),
+    (Text:'GL_DEPTH_WRITEMASK';Value:GL_DEPTH_WRITEMASK),
+    (Text:'GL_DEPTH_CLEAR_VALUE';Value:GL_DEPTH_CLEAR_VALUE),
+    (Text:'GL_DEPTH_FUNC';Value:GL_DEPTH_FUNC),
+    (Text:'GL_ACCUM_CLEAR_VALUE';Value:GL_ACCUM_CLEAR_VALUE),
+    (Text:'GL_STENCIL_TEST';Value:GL_STENCIL_TEST),
+    (Text:'GL_STENCIL_CLEAR_VALUE';Value:GL_STENCIL_CLEAR_VALUE),
+    (Text:'GL_STENCIL_FUNC';Value:GL_STENCIL_FUNC),
+    (Text:'GL_STENCIL_VALUE_MASK';Value:GL_STENCIL_VALUE_MASK),
+    (Text:'GL_STENCIL_FAIL';Value:GL_STENCIL_FAIL),
+    (Text:'GL_STENCIL_PASS_DEPTH_FAIL';Value:GL_STENCIL_PASS_DEPTH_FAIL),
+    (Text:'GL_STENCIL_PASS_DEPTH_PASS';Value:GL_STENCIL_PASS_DEPTH_PASS),
+    (Text:'GL_STENCIL_REF';Value:GL_STENCIL_REF),
+    (Text:'GL_STENCIL_WRITEMASK';Value:GL_STENCIL_WRITEMASK),
+    (Text:'GL_MATRIX_MODE';Value:GL_MATRIX_MODE),
+    (Text:'GL_NORMALIZE';Value:GL_NORMALIZE),
+    (Text:'GL_VIEWPORT';Value:GL_VIEWPORT),
+    (Text:'GL_MODELVIEW_STACK_DEPTH';Value:GL_MODELVIEW_STACK_DEPTH),
+    (Text:'GL_PROJECTION_STACK_DEPTH';Value:GL_PROJECTION_STACK_DEPTH),
+    (Text:'GL_TEXTURE_STACK_DEPTH';Value:GL_TEXTURE_STACK_DEPTH),
+    (Text:'GL_MODELVIEW_MATRIX';Value:GL_MODELVIEW_MATRIX),
+    (Text:'GL_PROJECTION_MATRIX';Value:GL_PROJECTION_MATRIX),
+    (Text:'GL_TEXTURE_MATRIX';Value:GL_TEXTURE_MATRIX),
+    (Text:'GL_ATTRIB_STACK_DEPTH';Value:GL_ATTRIB_STACK_DEPTH),
+    (Text:'GL_CLIENT_ATTRIB_STACK_DEPTH';Value:GL_CLIENT_ATTRIB_STACK_DEPTH),
+    (Text:'GL_ALPHA_TEST';Value:GL_ALPHA_TEST),
+    (Text:'GL_ALPHA_TEST_FUNC';Value:GL_ALPHA_TEST_FUNC),
+    (Text:'GL_ALPHA_TEST_REF';Value:GL_ALPHA_TEST_REF),
+    (Text:'GL_DITHER';Value:GL_DITHER),
+    (Text:'GL_BLEND_DST';Value:GL_BLEND_DST),
+    (Text:'GL_BLEND_SRC';Value:GL_BLEND_SRC),
+    (Text:'GL_BLEND';Value:GL_BLEND),
+    (Text:'GL_LOGIC_OP_MODE';Value:GL_LOGIC_OP_MODE),
+    (Text:'GL_INDEX_LOGIC_OP';Value:GL_INDEX_LOGIC_OP),
+    (Text:'GL_COLOR_LOGIC_OP';Value:GL_COLOR_LOGIC_OP),
+    (Text:'GL_AUX_BUFFERS';Value:GL_AUX_BUFFERS),
+    (Text:'GL_DRAW_BUFFER';Value:GL_DRAW_BUFFER),
+    (Text:'GL_READ_BUFFER';Value:GL_READ_BUFFER),
+    (Text:'GL_SCISSOR_BOX';Value:GL_SCISSOR_BOX),
+    (Text:'GL_SCISSOR_TEST';Value:GL_SCISSOR_TEST),
+    (Text:'GL_INDEX_CLEAR_VALUE';Value:GL_INDEX_CLEAR_VALUE),
+    (Text:'GL_INDEX_WRITEMASK';Value:GL_INDEX_WRITEMASK),
+    (Text:'GL_COLOR_CLEAR_VALUE';Value:GL_COLOR_CLEAR_VALUE),
+    (Text:'GL_COLOR_WRITEMASK';Value:GL_COLOR_WRITEMASK),
+    (Text:'GL_INDEX_MODE';Value:GL_INDEX_MODE),
+    (Text:'GL_RGBA_MODE';Value:GL_RGBA_MODE),
+    (Text:'GL_DOUBLEBUFFER';Value:GL_DOUBLEBUFFER),
+    (Text:'GL_STEREO';Value:GL_STEREO),
+    (Text:'GL_RENDER_MODE';Value:GL_RENDER_MODE),
+    (Text:'GL_PERSPECTIVE_CORRECTION_HINT';Value:GL_PERSPECTIVE_CORRECTION_HINT),
+    (Text:'GL_POINT_SMOOTH_HINT';Value:GL_POINT_SMOOTH_HINT),
+    (Text:'GL_LINE_SMOOTH_HINT';Value:GL_LINE_SMOOTH_HINT),
+    (Text:'GL_POLYGON_SMOOTH_HINT';Value:GL_POLYGON_SMOOTH_HINT),
+    (Text:'GL_FOG_HINT';Value:GL_FOG_HINT),
+    (Text:'GL_TEXTURE_GEN_S';Value:GL_TEXTURE_GEN_S),
+    (Text:'GL_TEXTURE_GEN_T';Value:GL_TEXTURE_GEN_T),
+    (Text:'GL_TEXTURE_GEN_R';Value:GL_TEXTURE_GEN_R),
+    (Text:'GL_TEXTURE_GEN_Q';Value:GL_TEXTURE_GEN_Q),
+    (Text:'GL_PIXEL_MAP_I_TO_I';Value:GL_PIXEL_MAP_I_TO_I),
+    (Text:'GL_PIXEL_MAP_S_TO_S';Value:GL_PIXEL_MAP_S_TO_S),
+    (Text:'GL_PIXEL_MAP_I_TO_R';Value:GL_PIXEL_MAP_I_TO_R),
+    (Text:'GL_PIXEL_MAP_I_TO_G';Value:GL_PIXEL_MAP_I_TO_G),
+    (Text:'GL_PIXEL_MAP_I_TO_B';Value:GL_PIXEL_MAP_I_TO_B),
+    (Text:'GL_PIXEL_MAP_I_TO_A';Value:GL_PIXEL_MAP_I_TO_A),
+    (Text:'GL_PIXEL_MAP_R_TO_R';Value:GL_PIXEL_MAP_R_TO_R),
+    (Text:'GL_PIXEL_MAP_G_TO_G';Value:GL_PIXEL_MAP_G_TO_G),
+    (Text:'GL_PIXEL_MAP_B_TO_B';Value:GL_PIXEL_MAP_B_TO_B),
+    (Text:'GL_PIXEL_MAP_A_TO_A';Value:GL_PIXEL_MAP_A_TO_A),
+    (Text:'GL_PIXEL_MAP_I_TO_I_SIZE';Value:GL_PIXEL_MAP_I_TO_I_SIZE),
+    (Text:'GL_PIXEL_MAP_S_TO_S_SIZE';Value:GL_PIXEL_MAP_S_TO_S_SIZE),
+    (Text:'GL_PIXEL_MAP_I_TO_R_SIZE';Value:GL_PIXEL_MAP_I_TO_R_SIZE),
+    (Text:'GL_PIXEL_MAP_I_TO_G_SIZE';Value:GL_PIXEL_MAP_I_TO_G_SIZE),
+    (Text:'GL_PIXEL_MAP_I_TO_B_SIZE';Value:GL_PIXEL_MAP_I_TO_B_SIZE),
+    (Text:'GL_PIXEL_MAP_I_TO_A_SIZE';Value:GL_PIXEL_MAP_I_TO_A_SIZE),
+    (Text:'GL_PIXEL_MAP_R_TO_R_SIZE';Value:GL_PIXEL_MAP_R_TO_R_SIZE),
+    (Text:'GL_PIXEL_MAP_G_TO_G_SIZE';Value:GL_PIXEL_MAP_G_TO_G_SIZE),
+    (Text:'GL_PIXEL_MAP_B_TO_B_SIZE';Value:GL_PIXEL_MAP_B_TO_B_SIZE),
+    (Text:'GL_PIXEL_MAP_A_TO_A_SIZE';Value:GL_PIXEL_MAP_A_TO_A_SIZE),
+    (Text:'GL_UNPACK_SWAP_BYTES';Value:GL_UNPACK_SWAP_BYTES),
+    (Text:'GL_UNPACK_LSB_FIRST';Value:GL_UNPACK_LSB_FIRST),
+    (Text:'GL_UNPACK_ROW_LENGTH';Value:GL_UNPACK_ROW_LENGTH),
+    (Text:'GL_UNPACK_SKIP_ROWS';Value:GL_UNPACK_SKIP_ROWS),
+    (Text:'GL_UNPACK_SKIP_PIXELS';Value:GL_UNPACK_SKIP_PIXELS),
+    (Text:'GL_UNPACK_ALIGNMENT';Value:GL_UNPACK_ALIGNMENT),
+    (Text:'GL_PACK_SWAP_BYTES';Value:GL_PACK_SWAP_BYTES),
+    (Text:'GL_PACK_LSB_FIRST';Value:GL_PACK_LSB_FIRST),
+    (Text:'GL_PACK_ROW_LENGTH';Value:GL_PACK_ROW_LENGTH),
+    (Text:'GL_PACK_SKIP_ROWS';Value:GL_PACK_SKIP_ROWS),
+    (Text:'GL_PACK_SKIP_PIXELS';Value:GL_PACK_SKIP_PIXELS),
+    (Text:'GL_PACK_ALIGNMENT';Value:GL_PACK_ALIGNMENT),
+    (Text:'GL_MAP_COLOR';Value:GL_MAP_COLOR),
+    (Text:'GL_MAP_STENCIL';Value:GL_MAP_STENCIL),
+    (Text:'GL_INDEX_SHIFT';Value:GL_INDEX_SHIFT),
+    (Text:'GL_INDEX_OFFSET';Value:GL_INDEX_OFFSET),
+    (Text:'GL_RED_SCALE';Value:GL_RED_SCALE),
+    (Text:'GL_RED_BIAS';Value:GL_RED_BIAS),
+    (Text:'GL_ZOOM_X';Value:GL_ZOOM_X),
+    (Text:'GL_ZOOM_Y';Value:GL_ZOOM_Y),
+    (Text:'GL_GREEN_SCALE';Value:GL_GREEN_SCALE),
+    (Text:'GL_GREEN_BIAS';Value:GL_GREEN_BIAS),
+    (Text:'GL_BLUE_SCALE';Value:GL_BLUE_SCALE),
+    (Text:'GL_BLUE_BIAS';Value:GL_BLUE_BIAS),
+    (Text:'GL_ALPHA_SCALE';Value:GL_ALPHA_SCALE),
+    (Text:'GL_ALPHA_BIAS';Value:GL_ALPHA_BIAS),
+    (Text:'GL_DEPTH_SCALE';Value:GL_DEPTH_SCALE),
+    (Text:'GL_DEPTH_BIAS';Value:GL_DEPTH_BIAS),
+    (Text:'GL_MAX_EVAL_ORDER';Value:GL_MAX_EVAL_ORDER),
+    (Text:'GL_MAX_LIGHTS';Value:GL_MAX_LIGHTS),
+    (Text:'GL_MAX_CLIP_PLANES';Value:GL_MAX_CLIP_PLANES),
+    (Text:'GL_MAX_TEXTURE_SIZE';Value:GL_MAX_TEXTURE_SIZE),
+    (Text:'GL_MAX_PIXEL_MAP_TABLE';Value:GL_MAX_PIXEL_MAP_TABLE),
+    (Text:'GL_MAX_ATTRIB_STACK_DEPTH';Value:GL_MAX_ATTRIB_STACK_DEPTH),
+    (Text:'GL_MAX_MODELVIEW_STACK_DEPTH';Value:GL_MAX_MODELVIEW_STACK_DEPTH),
+    (Text:'GL_MAX_NAME_STACK_DEPTH';Value:GL_MAX_NAME_STACK_DEPTH),
+    (Text:'GL_MAX_PROJECTION_STACK_DEPTH';Value:GL_MAX_PROJECTION_STACK_DEPTH),
+    (Text:'GL_MAX_TEXTURE_STACK_DEPTH';Value:GL_MAX_TEXTURE_STACK_DEPTH),
+    (Text:'GL_MAX_VIEWPORT_DIMS';Value:GL_MAX_VIEWPORT_DIMS),
+    (Text:'GL_MAX_CLIENT_ATTRIB_STACK_DEPTH';Value:GL_MAX_CLIENT_ATTRIB_STACK_DEPTH),
+    (Text:'GL_SUBPIXEL_BITS';Value:GL_SUBPIXEL_BITS),
+    (Text:'GL_INDEX_BITS';Value:GL_INDEX_BITS),
+    (Text:'GL_RED_BITS';Value:GL_RED_BITS),
+    (Text:'GL_GREEN_BITS';Value:GL_GREEN_BITS),
+    (Text:'GL_BLUE_BITS';Value:GL_BLUE_BITS),
+    (Text:'GL_ALPHA_BITS';Value:GL_ALPHA_BITS),
+    (Text:'GL_DEPTH_BITS';Value:GL_DEPTH_BITS),
+    (Text:'GL_STENCIL_BITS';Value:GL_STENCIL_BITS),
+    (Text:'GL_ACCUM_RED_BITS';Value:GL_ACCUM_RED_BITS),
+    (Text:'GL_ACCUM_GREEN_BITS';Value:GL_ACCUM_GREEN_BITS),
+    (Text:'GL_ACCUM_BLUE_BITS';Value:GL_ACCUM_BLUE_BITS),
+    (Text:'GL_ACCUM_ALPHA_BITS';Value:GL_ACCUM_ALPHA_BITS),
+    (Text:'GL_NAME_STACK_DEPTH';Value:GL_NAME_STACK_DEPTH),
+    (Text:'GL_AUTO_NORMAL';Value:GL_AUTO_NORMAL),
+    (Text:'GL_MAP1_COLOR_4';Value:GL_MAP1_COLOR_4),
+    (Text:'GL_MAP1_INDEX';Value:GL_MAP1_INDEX),
+    (Text:'GL_MAP1_NORMAL';Value:GL_MAP1_NORMAL),
+    (Text:'GL_MAP1_TEXTURE_COORD_1';Value:GL_MAP1_TEXTURE_COORD_1),
+    (Text:'GL_MAP1_TEXTURE_COORD_2';Value:GL_MAP1_TEXTURE_COORD_2),
+    (Text:'GL_MAP1_TEXTURE_COORD_3';Value:GL_MAP1_TEXTURE_COORD_3),
+    (Text:'GL_MAP1_TEXTURE_COORD_4';Value:GL_MAP1_TEXTURE_COORD_4),
+    (Text:'GL_MAP1_VERTEX_3';Value:GL_MAP1_VERTEX_3),
+    (Text:'GL_MAP1_VERTEX_4';Value:GL_MAP1_VERTEX_4),
+    (Text:'GL_MAP2_COLOR_4';Value:GL_MAP2_COLOR_4),
+    (Text:'GL_MAP2_INDEX';Value:GL_MAP2_INDEX),
+    (Text:'GL_MAP2_NORMAL';Value:GL_MAP2_NORMAL),
+    (Text:'GL_MAP2_TEXTURE_COORD_1';Value:GL_MAP2_TEXTURE_COORD_1),
+    (Text:'GL_MAP2_TEXTURE_COORD_2';Value:GL_MAP2_TEXTURE_COORD_2),
+    (Text:'GL_MAP2_TEXTURE_COORD_3';Value:GL_MAP2_TEXTURE_COORD_3),
+    (Text:'GL_MAP2_TEXTURE_COORD_4';Value:GL_MAP2_TEXTURE_COORD_4),
+    (Text:'GL_MAP2_VERTEX_3';Value:GL_MAP2_VERTEX_3),
+    (Text:'GL_MAP2_VERTEX_4';Value:GL_MAP2_VERTEX_4),
+    (Text:'GL_MAP1_GRID_DOMAIN';Value:GL_MAP1_GRID_DOMAIN),
+    (Text:'GL_MAP1_GRID_SEGMENTS';Value:GL_MAP1_GRID_SEGMENTS),
+    (Text:'GL_MAP2_GRID_DOMAIN';Value:GL_MAP2_GRID_DOMAIN),
+    (Text:'GL_MAP2_GRID_SEGMENTS';Value:GL_MAP2_GRID_SEGMENTS),
+    (Text:'GL_TEXTURE_1D';Value:GL_TEXTURE_1D),
+    (Text:'GL_TEXTURE_2D';Value:GL_TEXTURE_2D),
+    (Text:'GL_FEEDBACK_BUFFER_POINTER';Value:GL_FEEDBACK_BUFFER_POINTER),
+    (Text:'GL_FEEDBACK_BUFFER_SIZE';Value:GL_FEEDBACK_BUFFER_SIZE),
+    (Text:'GL_FEEDBACK_BUFFER_TYPE';Value:GL_FEEDBACK_BUFFER_TYPE),
+    (Text:'GL_SELECTION_BUFFER_POINTER';Value:GL_SELECTION_BUFFER_POINTER),
+    (Text:'GL_SELECTION_BUFFER_SIZE';Value:GL_SELECTION_BUFFER_SIZE),
+    (Text:'GL_TEXTURE_WIDTH';Value:GL_TEXTURE_WIDTH),
+    (Text:'GL_TEXTURE_HEIGHT';Value:GL_TEXTURE_HEIGHT),
+    (Text:'GL_TEXTURE_INTERNAL_FORMAT';Value:GL_TEXTURE_INTERNAL_FORMAT),
+    (Text:'GL_TEXTURE_BORDER_COLOR';Value:GL_TEXTURE_BORDER_COLOR),
+    (Text:'GL_TEXTURE_BORDER';Value:GL_TEXTURE_BORDER),
+    (Text:'GL_DONT_CARE';Value:GL_DONT_CARE),
+    (Text:'GL_FASTEST';Value:GL_FASTEST),
+    (Text:'GL_NICEST';Value:GL_NICEST),
+    (Text:'GL_LIGHT0';Value:GL_LIGHT0),
+    (Text:'GL_LIGHT1';Value:GL_LIGHT1),
+    (Text:'GL_LIGHT2';Value:GL_LIGHT2),
+    (Text:'GL_LIGHT3';Value:GL_LIGHT3),
+    (Text:'GL_LIGHT4';Value:GL_LIGHT4),
+    (Text:'GL_LIGHT5';Value:GL_LIGHT5),
+    (Text:'GL_LIGHT6';Value:GL_LIGHT6),
+    (Text:'GL_LIGHT7';Value:GL_LIGHT7),
+    (Text:'GL_AMBIENT';Value:GL_AMBIENT),
+    (Text:'GL_DIFFUSE';Value:GL_DIFFUSE),
+    (Text:'GL_SPECULAR';Value:GL_SPECULAR),
+    (Text:'GL_POSITION';Value:GL_POSITION),
+    (Text:'GL_SPOT_DIRECTION';Value:GL_SPOT_DIRECTION),
+    (Text:'GL_SPOT_EXPONENT';Value:GL_SPOT_EXPONENT),
+    (Text:'GL_SPOT_CUTOFF';Value:GL_SPOT_CUTOFF),
+    (Text:'GL_CONSTANT_ATTENUATION';Value:GL_CONSTANT_ATTENUATION),
+    (Text:'GL_LINEAR_ATTENUATION';Value:GL_LINEAR_ATTENUATION),
+    (Text:'GL_QUADRATIC_ATTENUATION';Value:GL_QUADRATIC_ATTENUATION),
+    (Text:'GL_COMPILE';Value:GL_COMPILE),
+    (Text:'GL_COMPILE_AND_EXECUTE';Value:GL_COMPILE_AND_EXECUTE),
+    (Text:'GL_CLEAR';Value:GL_CLEAR),
+    (Text:'GL_AND';Value:GL_AND),
+    (Text:'GL_AND_REVERSE';Value:GL_AND_REVERSE),
+    (Text:'GL_COPY';Value:GL_COPY),
+    (Text:'GL_AND_INVERTED';Value:GL_AND_INVERTED),
+    (Text:'GL_NOOP';Value:GL_NOOP),
+    (Text:'GL_XOR';Value:GL_XOR),
+    (Text:'GL_OR';Value:GL_OR),
+    (Text:'GL_NOR';Value:GL_NOR),
+    (Text:'GL_EQUIV';Value:GL_EQUIV),
+    (Text:'GL_INVERT';Value:GL_INVERT),
+    (Text:'GL_OR_REVERSE';Value:GL_OR_REVERSE),
+    (Text:'GL_COPY_INVERTED';Value:GL_COPY_INVERTED),
+    (Text:'GL_OR_INVERTED';Value:GL_OR_INVERTED),
+    (Text:'GL_NAND';Value:GL_NAND),
+    (Text:'GL_SET';Value:GL_SET),
+    (Text:'GL_EMISSION';Value:GL_EMISSION),
+    (Text:'GL_SHININESS';Value:GL_SHININESS),
+    (Text:'GL_AMBIENT_AND_DIFFUSE';Value:GL_AMBIENT_AND_DIFFUSE),
+    (Text:'GL_COLOR_INDEXES';Value:GL_COLOR_INDEXES),
+    (Text:'GL_MODELVIEW';Value:GL_MODELVIEW),
+    (Text:'GL_PROJECTION';Value:GL_PROJECTION),
+    (Text:'GL_TEXTURE';Value:GL_TEXTURE),
+    (Text:'GL_COLOR';Value:GL_COLOR),
+    (Text:'GL_DEPTH';Value:GL_DEPTH),
+    (Text:'GL_STENCIL';Value:GL_STENCIL),
+    (Text:'GL_COLOR_INDEX';Value:GL_COLOR_INDEX),
+    (Text:'GL_STENCIL_INDEX';Value:GL_STENCIL_INDEX),
+    (Text:'GL_DEPTH_COMPONENT';Value:GL_DEPTH_COMPONENT),
+    (Text:'GL_RED';Value:GL_RED),
+    (Text:'GL_GREEN';Value:GL_GREEN),
+    (Text:'GL_BLUE';Value:GL_BLUE),
+    (Text:'GL_ALPHA';Value:GL_ALPHA),
+    (Text:'GL_RGB';Value:GL_RGB),
+    (Text:'GL_RGBA';Value:GL_RGBA),
+    (Text:'GL_LUMINANCE';Value:GL_LUMINANCE),
+    (Text:'GL_LUMINANCE_ALPHA';Value:GL_LUMINANCE_ALPHA),
+    (Text:'GL_BITMAP';Value:GL_BITMAP),
+    (Text:'GL_POINT';Value:GL_POINT),
+    (Text:'GL_LINE';Value:GL_LINE),
+    (Text:'GL_FILL';Value:GL_FILL),
+    (Text:'GL_RENDER';Value:GL_RENDER),
+    (Text:'GL_FEEDBACK';Value:GL_FEEDBACK),
+    (Text:'GL_SELECT';Value:GL_SELECT),
+    (Text:'GL_FLAT';Value:GL_FLAT),
+    (Text:'GL_SMOOTH';Value:GL_SMOOTH),
+    (Text:'GL_KEEP';Value:GL_KEEP),
+    (Text:'GL_REPLACE';Value:GL_REPLACE),
+    (Text:'GL_INCR';Value:GL_INCR),
+    (Text:'GL_DECR';Value:GL_DECR),
+    (Text:'GL_VENDOR';Value:GL_VENDOR),
+    (Text:'GL_RENDERER';Value:GL_RENDERER),
+    (Text:'GL_VERSION';Value:GL_VERSION),
+    (Text:'GL_EXTENSIONS';Value:GL_EXTENSIONS),
+    (Text:'GL_S';Value:GL_S),
+    (Text:'GL_T';Value:GL_T),
+    (Text:'GL_R';Value:GL_R),
+    (Text:'GL_Q';Value:GL_Q),
+    (Text:'GL_MODULATE';Value:GL_MODULATE),
+    (Text:'GL_DECAL';Value:GL_DECAL),
+    (Text:'GL_TEXTURE_ENV_MODE';Value:GL_TEXTURE_ENV_MODE),
+    (Text:'GL_TEXTURE_ENV_COLOR';Value:GL_TEXTURE_ENV_COLOR),
+    (Text:'GL_TEXTURE_ENV';Value:GL_TEXTURE_ENV),
+    (Text:'GL_EYE_LINEAR';Value:GL_EYE_LINEAR),
+    (Text:'GL_OBJECT_LINEAR';Value:GL_OBJECT_LINEAR),
+    (Text:'GL_SPHERE_MAP';Value:GL_SPHERE_MAP),
+    (Text:'GL_TEXTURE_GEN_MODE';Value:GL_TEXTURE_GEN_MODE),
+    (Text:'GL_OBJECT_PLANE';Value:GL_OBJECT_PLANE),
+    (Text:'GL_EYE_PLANE';Value:GL_EYE_PLANE),
+    (Text:'GL_NEAREST';Value:GL_NEAREST),
+    (Text:'GL_LINEAR';Value:GL_LINEAR),
+    (Text:'GL_NEAREST_MIPMAP_NEAREST';Value:GL_NEAREST_MIPMAP_NEAREST),
+    (Text:'GL_LINEAR_MIPMAP_NEAREST';Value:GL_LINEAR_MIPMAP_NEAREST),
+    (Text:'GL_NEAREST_MIPMAP_LINEAR';Value:GL_NEAREST_MIPMAP_LINEAR),
+    (Text:'GL_LINEAR_MIPMAP_LINEAR';Value:GL_LINEAR_MIPMAP_LINEAR),
+    (Text:'GL_TEXTURE_MAG_FILTER';Value:GL_TEXTURE_MAG_FILTER),
+    (Text:'GL_TEXTURE_MIN_FILTER';Value:GL_TEXTURE_MIN_FILTER),
+    (Text:'GL_TEXTURE_WRAP_S';Value:GL_TEXTURE_WRAP_S),
+    (Text:'GL_TEXTURE_WRAP_T';Value:GL_TEXTURE_WRAP_T),
+    (Text:'GL_CLAMP';Value:GL_CLAMP),
+    (Text:'GL_REPEAT';Value:GL_REPEAT),
+    (Text:'GL_CLIENT_PIXEL_STORE_BIT';Value:GL_CLIENT_PIXEL_STORE_BIT),
+    (Text:'GL_CLIENT_VERTEX_ARRAY_BIT';Value:GL_CLIENT_VERTEX_ARRAY_BIT),
+    (Text:'GL_CLIENT_ALL_ATTRIB_BITS';Value:GL_CLIENT_ALL_ATTRIB_BITS),
+    (Text:'GL_POLYGON_OFFSET_FACTOR';Value:GL_POLYGON_OFFSET_FACTOR),
+    (Text:'GL_POLYGON_OFFSET_UNITS';Value:GL_POLYGON_OFFSET_UNITS),
+    (Text:'GL_POLYGON_OFFSET_POINT';Value:GL_POLYGON_OFFSET_POINT),
+    (Text:'GL_POLYGON_OFFSET_LINE';Value:GL_POLYGON_OFFSET_LINE),
+    (Text:'GL_POLYGON_OFFSET_FILL';Value:GL_POLYGON_OFFSET_FILL),
+    (Text:'GL_ALPHA4';Value:GL_ALPHA4),
+    (Text:'GL_ALPHA8';Value:GL_ALPHA8),
+    (Text:'GL_ALPHA12';Value:GL_ALPHA12),
+    (Text:'GL_ALPHA16';Value:GL_ALPHA16),
+    (Text:'GL_LUMINANCE4';Value:GL_LUMINANCE4),
+    (Text:'GL_LUMINANCE8';Value:GL_LUMINANCE8),
+    (Text:'GL_LUMINANCE12';Value:GL_LUMINANCE12),
+    (Text:'GL_LUMINANCE16';Value:GL_LUMINANCE16),
+    (Text:'GL_LUMINANCE4_ALPHA4';Value:GL_LUMINANCE4_ALPHA4),
+    (Text:'GL_LUMINANCE6_ALPHA2';Value:GL_LUMINANCE6_ALPHA2),
+    (Text:'GL_LUMINANCE8_ALPHA8';Value:GL_LUMINANCE8_ALPHA8),
+    (Text:'GL_LUMINANCE12_ALPHA4';Value:GL_LUMINANCE12_ALPHA4),
+    (Text:'GL_LUMINANCE12_ALPHA12';Value:GL_LUMINANCE12_ALPHA12),
+    (Text:'GL_LUMINANCE16_ALPHA16';Value:GL_LUMINANCE16_ALPHA16),
+    (Text:'GL_INTENSITY';Value:GL_INTENSITY),
+    (Text:'GL_INTENSITY4';Value:GL_INTENSITY4),
+    (Text:'GL_INTENSITY8';Value:GL_INTENSITY8),
+    (Text:'GL_INTENSITY12';Value:GL_INTENSITY12),
+    (Text:'GL_INTENSITY16';Value:GL_INTENSITY16),
+    (Text:'GL_R3_G3_B2';Value:GL_R3_G3_B2),
+    (Text:'GL_RGB4';Value:GL_RGB4),
+    (Text:'GL_RGB5';Value:GL_RGB5),
+    (Text:'GL_RGB8';Value:GL_RGB8),
+    (Text:'GL_RGB10';Value:GL_RGB10),
+    (Text:'GL_RGB12';Value:GL_RGB12),
+    (Text:'GL_RGB16';Value:GL_RGB16),
+    (Text:'GL_RGBA2';Value:GL_RGBA2),
+    (Text:'GL_RGBA4';Value:GL_RGBA4),
+    (Text:'GL_RGB5_A1';Value:GL_RGB5_A1),
+    (Text:'GL_RGBA8';Value:GL_RGBA8),
+    (Text:'GL_RGB10_A2';Value:GL_RGB10_A2),
+    (Text:'GL_RGBA12';Value:GL_RGBA12),
+    (Text:'GL_RGBA16';Value:GL_RGBA16),
+    (Text:'GL_TEXTURE_RED_SIZE';Value:GL_TEXTURE_RED_SIZE),
+    (Text:'GL_TEXTURE_GREEN_SIZE';Value:GL_TEXTURE_GREEN_SIZE),
+    (Text:'GL_TEXTURE_BLUE_SIZE';Value:GL_TEXTURE_BLUE_SIZE),
+    (Text:'GL_TEXTURE_ALPHA_SIZE';Value:GL_TEXTURE_ALPHA_SIZE),
+    (Text:'GL_TEXTURE_LUMINANCE_SIZE';Value:GL_TEXTURE_LUMINANCE_SIZE),
+    (Text:'GL_TEXTURE_INTENSITY_SIZE';Value:GL_TEXTURE_INTENSITY_SIZE),
+    (Text:'GL_PROXY_TEXTURE_1D';Value:GL_PROXY_TEXTURE_1D),
+    (Text:'GL_PROXY_TEXTURE_2D';Value:GL_PROXY_TEXTURE_2D),
+    (Text:'GL_TEXTURE_PRIORITY';Value:GL_TEXTURE_PRIORITY),
+    (Text:'GL_TEXTURE_RESIDENT';Value:GL_TEXTURE_RESIDENT),
+    (Text:'GL_TEXTURE_BINDING_1D';Value:GL_TEXTURE_BINDING_1D),
+    (Text:'GL_TEXTURE_BINDING_2D';Value:GL_TEXTURE_BINDING_2D),
+    (Text:'GL_VERTEX_ARRAY';Value:GL_VERTEX_ARRAY),
+    (Text:'GL_NORMAL_ARRAY';Value:GL_NORMAL_ARRAY),
+    (Text:'GL_COLOR_ARRAY';Value:GL_COLOR_ARRAY),
+    (Text:'GL_INDEX_ARRAY';Value:GL_INDEX_ARRAY),
+    (Text:'GL_TEXTURE_COORD_ARRAY';Value:GL_TEXTURE_COORD_ARRAY),
+    (Text:'GL_EDGE_FLAG_ARRAY';Value:GL_EDGE_FLAG_ARRAY),
+    (Text:'GL_VERTEX_ARRAY_SIZE';Value:GL_VERTEX_ARRAY_SIZE),
+    (Text:'GL_VERTEX_ARRAY_TYPE';Value:GL_VERTEX_ARRAY_TYPE),
+    (Text:'GL_VERTEX_ARRAY_STRIDE';Value:GL_VERTEX_ARRAY_STRIDE),
+    (Text:'GL_NORMAL_ARRAY_TYPE';Value:GL_NORMAL_ARRAY_TYPE),
+    (Text:'GL_NORMAL_ARRAY_STRIDE';Value:GL_NORMAL_ARRAY_STRIDE),
+    (Text:'GL_COLOR_ARRAY_SIZE';Value:GL_COLOR_ARRAY_SIZE),
+    (Text:'GL_COLOR_ARRAY_TYPE';Value:GL_COLOR_ARRAY_TYPE),
+    (Text:'GL_COLOR_ARRAY_STRIDE';Value:GL_COLOR_ARRAY_STRIDE),
+    (Text:'GL_INDEX_ARRAY_TYPE';Value:GL_INDEX_ARRAY_TYPE),
+    (Text:'GL_INDEX_ARRAY_STRIDE';Value:GL_INDEX_ARRAY_STRIDE),
+    (Text:'GL_TEXTURE_COORD_ARRAY_SIZE';Value:GL_TEXTURE_COORD_ARRAY_SIZE),
+    (Text:'GL_TEXTURE_COORD_ARRAY_TYPE';Value:GL_TEXTURE_COORD_ARRAY_TYPE),
+    (Text:'GL_TEXTURE_COORD_ARRAY_STRIDE';Value:GL_TEXTURE_COORD_ARRAY_STRIDE),
+    (Text:'GL_EDGE_FLAG_ARRAY_STRIDE';Value:GL_EDGE_FLAG_ARRAY_STRIDE),
+    (Text:'GL_VERTEX_ARRAY_POINTER';Value:GL_VERTEX_ARRAY_POINTER),
+    (Text:'GL_NORMAL_ARRAY_POINTER';Value:GL_NORMAL_ARRAY_POINTER),
+    (Text:'GL_COLOR_ARRAY_POINTER';Value:GL_COLOR_ARRAY_POINTER),
+    (Text:'GL_INDEX_ARRAY_POINTER';Value:GL_INDEX_ARRAY_POINTER),
+    (Text:'GL_TEXTURE_COORD_ARRAY_POINTER';Value:GL_TEXTURE_COORD_ARRAY_POINTER),
+    (Text:'GL_EDGE_FLAG_ARRAY_POINTER';Value:GL_EDGE_FLAG_ARRAY_POINTER),
+    (Text:'GL_V2F';Value:GL_V2F),
+    (Text:'GL_V3F';Value:GL_V3F),
+    (Text:'GL_C4UB_V2F';Value:GL_C4UB_V2F),
+    (Text:'GL_C4UB_V3F';Value:GL_C4UB_V3F),
+    (Text:'GL_C3F_V3F';Value:GL_C3F_V3F),
+    (Text:'GL_N3F_V3F';Value:GL_N3F_V3F),
+    (Text:'GL_C4F_N3F_V3F';Value:GL_C4F_N3F_V3F),
+    (Text:'GL_T2F_V3F';Value:GL_T2F_V3F),
+    (Text:'GL_T4F_V4F';Value:GL_T4F_V4F),
+    (Text:'GL_T2F_C4UB_V3F';Value:GL_T2F_C4UB_V3F),
+    (Text:'GL_T2F_C3F_V3F';Value:GL_T2F_C3F_V3F),
+    (Text:'GL_T2F_N3F_V3F';Value:GL_T2F_N3F_V3F),
+    (Text:'GL_T2F_C4F_N3F_V3F';Value:GL_T2F_C4F_N3F_V3F),
+    (Text:'GL_T4F_C4F_N3F_V4F';Value:GL_T4F_C4F_N3F_V4F),
+    (Text:'GL_EXT_vertex_array';Value:GL_EXT_vertex_array),
+    (Text:'GL_WIN_swap_hint';Value:GL_WIN_swap_hint),
+    (Text:'GL_EXT_bgra';Value:GL_EXT_bgra),
+    (Text:'GL_EXT_paletted_texture';Value:GL_EXT_paletted_texture),
+    (Text:'GL_VERTEX_ARRAY_EXT';Value:GL_VERTEX_ARRAY_EXT),
+    (Text:'GL_NORMAL_ARRAY_EXT';Value:GL_NORMAL_ARRAY_EXT),
+    (Text:'GL_COLOR_ARRAY_EXT';Value:GL_COLOR_ARRAY_EXT),
+    (Text:'GL_INDEX_ARRAY_EXT';Value:GL_INDEX_ARRAY_EXT),
+    (Text:'GL_TEXTURE_COORD_ARRAY_EXT';Value:GL_TEXTURE_COORD_ARRAY_EXT),
+    (Text:'GL_EDGE_FLAG_ARRAY_EXT';Value:GL_EDGE_FLAG_ARRAY_EXT),
+    (Text:'GL_VERTEX_ARRAY_SIZE_EXT';Value:GL_VERTEX_ARRAY_SIZE_EXT),
+    (Text:'GL_VERTEX_ARRAY_TYPE_EXT';Value:GL_VERTEX_ARRAY_TYPE_EXT),
+    (Text:'GL_VERTEX_ARRAY_STRIDE_EXT';Value:GL_VERTEX_ARRAY_STRIDE_EXT),
+    (Text:'GL_VERTEX_ARRAY_COUNT_EXT';Value:GL_VERTEX_ARRAY_COUNT_EXT),
+    (Text:'GL_NORMAL_ARRAY_TYPE_EXT';Value:GL_NORMAL_ARRAY_TYPE_EXT),
+    (Text:'GL_NORMAL_ARRAY_STRIDE_EXT';Value:GL_NORMAL_ARRAY_STRIDE_EXT),
+    (Text:'GL_NORMAL_ARRAY_COUNT_EXT';Value:GL_NORMAL_ARRAY_COUNT_EXT),
+    (Text:'GL_COLOR_ARRAY_SIZE_EXT';Value:GL_COLOR_ARRAY_SIZE_EXT),
+    (Text:'GL_COLOR_ARRAY_TYPE_EXT';Value:GL_COLOR_ARRAY_TYPE_EXT),
+    (Text:'GL_COLOR_ARRAY_STRIDE_EXT';Value:GL_COLOR_ARRAY_STRIDE_EXT),
+    (Text:'GL_COLOR_ARRAY_COUNT_EXT';Value:GL_COLOR_ARRAY_COUNT_EXT),
+    (Text:'GL_INDEX_ARRAY_TYPE_EXT';Value:GL_INDEX_ARRAY_TYPE_EXT),
+    (Text:'GL_INDEX_ARRAY_STRIDE_EXT';Value:GL_INDEX_ARRAY_STRIDE_EXT),
+    (Text:'GL_INDEX_ARRAY_COUNT_EXT';Value:GL_INDEX_ARRAY_COUNT_EXT),
+    (Text:'GL_TEXTURE_COORD_ARRAY_SIZE_EXT';Value:GL_TEXTURE_COORD_ARRAY_SIZE_EXT),
+    (Text:'GL_TEXTURE_COORD_ARRAY_TYPE_EXT';Value:GL_TEXTURE_COORD_ARRAY_TYPE_EXT),
+    (Text:'GL_TEXTURE_COORD_ARRAY_STRIDE_EXT';Value:GL_TEXTURE_COORD_ARRAY_STRIDE_EXT),
+    (Text:'GL_TEXTURE_COORD_ARRAY_COUNT_EXT';Value:GL_TEXTURE_COORD_ARRAY_COUNT_EXT),
+    (Text:'GL_EDGE_FLAG_ARRAY_STRIDE_EXT';Value:GL_EDGE_FLAG_ARRAY_STRIDE_EXT),
+    (Text:'GL_EDGE_FLAG_ARRAY_COUNT_EXT';Value:GL_EDGE_FLAG_ARRAY_COUNT_EXT),
+    (Text:'GL_VERTEX_ARRAY_POINTER_EXT';Value:GL_VERTEX_ARRAY_POINTER_EXT),
+    (Text:'GL_NORMAL_ARRAY_POINTER_EXT';Value:GL_NORMAL_ARRAY_POINTER_EXT),
+    (Text:'GL_COLOR_ARRAY_POINTER_EXT';Value:GL_COLOR_ARRAY_POINTER_EXT),
+    (Text:'GL_INDEX_ARRAY_POINTER_EXT';Value:GL_INDEX_ARRAY_POINTER_EXT),
+    (Text:'GL_TEXTURE_COORD_ARRAY_POINTER_EXT';Value:GL_TEXTURE_COORD_ARRAY_POINTER_EXT),
+    (Text:'GL_EDGE_FLAG_ARRAY_POINTER_EXT';Value:GL_EDGE_FLAG_ARRAY_POINTER_EXT),
+    (Text:'GL_DOUBLE_EXT';Value:GL_DOUBLE_EXT),
+    (Text:'GL_BGR_EXT';Value:GL_BGR_EXT),
+    (Text:'GL_BGRA_EXT';Value:GL_BGRA_EXT),
+    (Text:'GL_COLOR_TABLE_FORMAT_EXT';Value:GL_COLOR_TABLE_FORMAT_EXT),
+    (Text:'GL_COLOR_TABLE_WIDTH_EXT';Value:GL_COLOR_TABLE_WIDTH_EXT),
+    (Text:'GL_COLOR_TABLE_RED_SIZE_EXT';Value:GL_COLOR_TABLE_RED_SIZE_EXT),
+    (Text:'GL_COLOR_TABLE_GREEN_SIZE_EXT';Value:GL_COLOR_TABLE_GREEN_SIZE_EXT),
+    (Text:'GL_COLOR_TABLE_BLUE_SIZE_EXT';Value:GL_COLOR_TABLE_BLUE_SIZE_EXT),
+    (Text:'GL_COLOR_TABLE_ALPHA_SIZE_EXT';Value:GL_COLOR_TABLE_ALPHA_SIZE_EXT),
+    (Text:'GL_COLOR_TABLE_LUMINANCE_SIZE_EXT';Value:GL_COLOR_TABLE_LUMINANCE_SIZE_EXT),
+    (Text:'GL_COLOR_TABLE_INTENSITY_SIZE_EXT';Value:GL_COLOR_TABLE_INTENSITY_SIZE_EXT),
+    (Text:'GL_COLOR_INDEX1_EXT';Value:GL_COLOR_INDEX1_EXT),
+    (Text:'GL_COLOR_INDEX2_EXT';Value:GL_COLOR_INDEX2_EXT),
+    (Text:'GL_COLOR_INDEX4_EXT';Value:GL_COLOR_INDEX4_EXT),
+    (Text:'GL_COLOR_INDEX8_EXT';Value:GL_COLOR_INDEX8_EXT),
+    (Text:'GL_COLOR_INDEX12_EXT';Value:GL_COLOR_INDEX12_EXT),
+    (Text:'GL_COLOR_INDEX16_EXT';Value:GL_COLOR_INDEX16_EXT)
+   );
+
+function ULuaGl_StringToEnum(Str: String): GLenum;
+  function GetEnum(const Str: String): GLenum;
+  var
+    i : Integer;
+  begin
+    for i := 0 to high(ULuaGl_Enum) do
+    begin
+      if 0 = AnsiCompareText(Str, ULuaGl_Enum[i].Text) then
+      begin
+        Result := ULuaGl_Enum[i].Value;
+        Exit;
+      end;
+    end;
+    Result := ULuaGl_EnumERROR;
+  end;
+  var
+    i : Integer;
+    j : Integer;
+    temp : GLenum;
+begin
+  Result := 0;
+  j := 1;
+  for i := 1 to Length(Str) do
+  begin
+    if Str[i] = ',' then
+    begin
+      temp := GetEnum(Copy(Str,j,i-j));
+      if temp <> ULuaGl_EnumERROR then
+        Result := Result or temp;
+      j := i + 1;
+    end;
+  end;
+
+  temp := GetEnum(Copy(Str,j,MaxInt));
+  if (temp = ULuaGl_EnumERROR) then
+  begin
+    if Result = 0 then
+      Result := ULuaGl_EnumERROR;
+    exit;
+  end;
+  Result := Result or temp;
+end;
+end.
+
diff --git a/songmanagement/src/lua/ULuaLog.pas b/songmanagement/src/lua/ULuaLog.pas
new file mode 100644
index 00000000..95efaa19
--- /dev/null
+++ b/songmanagement/src/lua/ULuaLog.pas
@@ -0,0 +1,167 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaLog;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  ULog,
+  ULua;
+
+function luaopen_Log (L: Plua_State): Integer; cdecl;
+
+function ULuaLog_LogError(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogMsg(L: Plua_State): Integer; cdecl;
+function ULuaLog_BenchmarkStart(L: Plua_State): Integer; cdecl;
+function ULuaLog_BenchmarkEnd(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogBenchmark(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogDebug(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogInfo(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogStatus(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogWarn(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogCritical(L: Plua_State): Integer; cdecl;
+function ULuaLog_CriticalError(L: Plua_State): Integer; cdecl;
+function ULuaLog_GetLogLevel(L: Plua_State): Integer; cdecl;
+function ULuaLog_SetLogLevel(L: Plua_State): Integer; cdecl;
+
+
+const
+  ULuaLog_Lib_f: array [0..13] of lual_reg = (
+   (name:'LogError';func:ULuaLog_LogError),
+   (name:'LogMsg';func:ULuaLog_LogMsg),
+   (name:'BenchmarkStart';func:ULuaLog_BenchmarkStart),
+   (name:'BenchmarkEnd';func:ULuaLog_BenchmarkEnd),
+   (name:'LogBenchmark';func:ULuaLog_LogBenchmark),
+   (name:'LogDebug';func:ULuaLog_LogDebug),
+   (name:'LogInfo';func:ULuaLog_LogInfo),
+   (name:'LogStatus';func:ULuaLog_LogStatus),
+   (name:'LogWarn';func:ULuaLog_LogWarn),
+   (name:'LogCritical';func:ULuaLog_LogCritical),
+   (name:'CriticalError';func:ULuaLog_CriticalError),
+   (name:'SetLogLevel';func:ULuaLog_GetLogLevel),
+   (name:'GetLogLevel';func:ULuaLog_SetLogLevel),
+   (name:nil;func:nil)
+   );
+
+implementation
+
+function ULuaLog_LogError(L: Plua_State): Integer; cdecl;
+begin
+  if (lua_gettop(L) > 1) then
+    Log.LogError(luaL_checkstring(L,-2),luaL_checkstring(L,-1))
+  else
+    Log.LogError(luaL_checkstring(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_LogMsg(L: Plua_State): Integer; cdecl;
+begin
+  if (lua_gettop(L) > 2) then
+    Log.LogMsg(luaL_checkstring(L,-3),luaL_checkstring(L,-1),luaL_checkinteger(L,-2))
+  else
+    Log.LogMsg(luaL_checkstring(L,-2),luaL_checkinteger(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_BenchmarkStart(L: Plua_State): Integer; cdecl;
+begin
+  Log.BenchmarkStart(luaL_checkinteger(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_BenchmarkEnd(L: Plua_State): Integer; cdecl;
+begin
+  Log.BenchmarkEnd(luaL_checkinteger(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_LogBenchmark(L: Plua_State): Integer; cdecl;
+begin
+  Log.LogBenchmark(luaL_checkstring(L,-2),luaL_checkinteger(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_LogDebug(L: Plua_State): Integer; cdecl;
+begin
+  Log.LogDebug(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_LogInfo(L: Plua_State): Integer; cdecl;
+begin
+  Log.LogInfo(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_LogStatus(L: Plua_State): Integer; cdecl;
+begin
+  Log.LogStatus(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_LogWarn(L: Plua_State): Integer; cdecl;
+begin
+  Log.LogWarn(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_LogCritical(L: Plua_State): Integer; cdecl;
+begin
+  Log.LogCritical(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_CriticalError(L: Plua_State): Integer; cdecl;
+begin
+  Log.CriticalError(luaL_checkstring(L,-1));
+  result:=0; // number of results
+end;
+
+function ULuaLog_GetLogLevel(L: Plua_State): Integer; cdecl;
+begin
+  lua_pushinteger(L,Log.GetLogLevel());
+  result:=1; // number of results
+end;
+
+function ULuaLog_SetLogLevel(L: Plua_State): Integer; cdecl;
+begin
+  Log.SetLogLevel(luaL_checkinteger(L,-1));
+  result:=0; // number of results
+end;
+
+function luaopen_Log (L: Plua_State): Integer; cdecl;
+begin
+    luaL_register(L,'Log',@ULuaLog_Lib_f[0]);
+    result:=1;
+end;
+end.
diff --git a/songmanagement/src/lua/ULuaParty.pas b/songmanagement/src/lua/ULuaParty.pas
new file mode 100644
index 00000000..69096e97
--- /dev/null
+++ b/songmanagement/src/lua/ULuaParty.pas
@@ -0,0 +1,391 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaParty;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses ULua;
+
+{ lua c functions from Party table. Enables creating of party modes w/ lua scripts }
+
+{ Party.Register - register party mode at party manager
+  arguments: info: table
+                   Name: String;          //< Name used as identifier (language strings, etc.). Has to be set.
+                   CanNonParty: Boolean   //< mode is playable when not in party mode. defaulted to false if not set
+                   CanParty: Boolean      //< mode is playable in party mode. defaulted to false if not set
+                   PlayerCount: Table     //< playable with one, two, three etc. players per team. defaulted to no restrictions if not set. (use table constructor e.g. {1, 2, 3) means playable w/ 1, 2 or three players)
+                   TeamCount: Table       //< playable with one, two, three etc. different teams. defaulted to no restrictions if not set. (use table constructor e.g. {1, 2, 3) means playable w/ 1, 2 or three players)
+
+                   BeforeSongSelect: String   //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+                   AfterSongSelect: String    //< name of global that will be called after song is selected (if nil, not callable or returns true, default action will be executed)
+
+                   BeforeSing: String         //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+                   OnSing: String             //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+                   AfterSing: String          //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)}
+function ULuaParty_Register(L: Plua_State): Integer; cdecl;
+
+{ Party.GameFinished - returns true if no party game is running or all rounds
+  of current game were played }
+function ULuaParty_GameFinished(L: Plua_State): Integer; cdecl;
+
+(* Party.SetRoundRanking - sets ranking of current party round,
+  arguments: Ranking: table
+  ranking of team i is the value (integer from 1 to number of teams) of the
+  table with index [i: number].
+  you may call this function in the following way:
+    Party.SetRoundRanking({3, 1, 2});
+    this means: team 1 is ranked third, team 2 is ranked first and team 3 is
+    ranked second.
+  if no party game is started or party game is finished
+  it will raise an error *)
+function ULuaParty_SetRoundRanking(L: Plua_State): Integer; cdecl;
+
+{ Party.GetTeams - returns a table with all information and structure as
+  in the TPartyGame.Teams array }
+function ULuaParty_GetTeams(L: Plua_State): Integer; cdecl;
+
+{ Party.SetTeams - changes all fields from TPartyGame.Teams that have been
+  set in the table given as first argument}
+function ULuaParty_SetTeams(L: Plua_State): Integer; cdecl;
+
+const
+  ULuaParty_Lib_f: array [0..4] of lual_reg = (
+    (name:'Register'; func:ULuaParty_Register),
+    (name:'GameFinished'; func:ULuaParty_GameFinished),
+    (name:'SetRoundRanking'; func:ULuaParty_SetRoundRanking),
+    (name:'GetTeams'; func:ULuaParty_GetTeams),
+    (name:'SetTeams'; func:ULuaParty_SetTeams)
+  );
+
+implementation
+uses ULuaCore, ULuaUtils, UParty, SysUtils;
+
+
+{ Party.Register - register party mode at party manager
+  arguments: info: table
+                   Name: String;          //< Name used as identifier (language strings, etc.). Has to be set.
+                   CanNonParty: Boolean   //< mode is playable when not in party mode. defaulted to false if not set
+                   CanParty: Boolean      //< mode is playable in party mode. defaulted to false if not set
+                   PlayerCount: Table     //< playable with one, two, three etc. players per team. defaulted to no restrictions if not set. (use table constructor e.g. {1, 2, 3) means playable w/ 1, 2 or three players)
+                   TeamCount: Table       //< playable with one, two, three etc. different teams. defaulted to no restrictions if not set. (use table constructor e.g. {1, 2, 3) means playable w/ 1, 2 or three players)
+
+                   BeforeSongSelect: String   //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+                   AfterSongSelect: String    //< name of global that will be called after song is selected (if nil, not callable or returns true, default action will be executed)
+
+                   BeforeSing: String         //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+                   OnSing: String             //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+                   AfterSing: String          //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)}
+function ULuaParty_Register(L: Plua_State): Integer; cdecl;
+  var
+    Info: TParty_ModeInfo;
+    Key: String;
+    P: TLuaPlugin;
+begin
+  Result := 0;
+  
+  // check for table on stack
+  luaL_checkType(L, 1, LUA_TTABLE);
+
+  // get parent id
+  P := Lua_GetOwner(L);
+
+
+  // set mode info to default
+  Party.DefaultModeInfo(Info);
+
+
+  // set parent in info rec and pop it from stack
+  Info.Parent := P.Id;
+
+  // go through table elements
+  lua_pushNil(L);
+  while (lua_Next(L, 1) <> 0) do
+  begin
+    Key := lowercase(lua_ToString(L, -2));
+
+    if (Key = 'name') and lua_isString(L, -1) then
+      Info.Name := lua_toString(L, -1)
+    else if (Key = 'cannonparty') and lua_isBoolean(L, -1) then
+      Info.CanNonParty := lua_toBoolean(L, -1)
+    else if (Key = 'canparty') and lua_isBoolean(L, -1) then
+      Info.CanParty := lua_toBoolean(L, -1)
+    else if (Key = 'playercount') and lua_isTable(L, -1) then
+      Info.PlayerCount := lua_toBinInt(L, -1)
+    else if (Key = 'teamcount') and lua_isTable(L, -1) then
+      Info.TeamCount := lua_toBinInt(L, -1)
+    else if (Key = 'beforesongselect') and lua_isString(L, -1) then
+      Info.Functions.BeforeSongSelect := lua_toString(L, -1)
+    else if (Key = 'aftersongselect') and lua_isString(L, -1) then
+      Info.Functions.AfterSongSelect := lua_toString(L, -1)
+    else if (Key = 'beforesing') and lua_isString(L, -1) then
+      Info.Functions.BeforeSing := lua_toString(L, -1)
+    else if (Key = 'onsing') and lua_isString(L, -1) then
+      Info.Functions.OnSing := lua_toString(L, -1)
+    else if (Key = 'aftersing') and lua_isString(L, -1) then
+      Info.Functions.AfterSing := lua_toString(L, -1);
+
+    // pop value from stack so key is on top
+    lua_pop(L, 1);
+  end;
+
+  // clear stack from table
+  lua_pop(L, lua_gettop(L));
+
+  if not Party.RegisterMode(Info) then
+    luaL_error(L, PChar('can''t register party mode at party manager in Party.Register. Is Info.Name defined or is there another mode with this name?'));
+end;
+
+{ Party.GameFinished - returns true if no party game is running or all rounds
+  of current game were played }
+function ULuaParty_GameFinished(L: Plua_State): Integer; cdecl;
+begin
+  // clear stack
+  lua_pop(L, lua_gettop(L));
+
+  // push result
+  lua_pushBoolean(L, Party.GameFinished);
+
+  //we return one value
+  Result := 1;
+end;
+
+{ Party.SetRoundRanking - sets ranking of current party round,
+  if no party game is started or party game is finished
+  it will raise an error }
+function ULuaParty_SetRoundRanking(L: Plua_State): Integer; cdecl;
+var
+  R: AParty_TeamRanking;
+  I: Integer;
+  Rank: Integer;
+begin
+  Result := 0;
+
+  luaL_checktype(L, 1, LUA_TTABLE);
+
+  lua_checkstack(L, 1);
+
+  SetLength(R, Length(Party.Teams));
+
+  for I := 0 to High(R) do
+  begin
+    lua_pushInteger(L, (I+1));
+    lua_gettable(L, 1);
+
+    R[I].Rank := Length(R);
+    R[I].Team := I;
+    if (lua_isnumber(L, -1)) then
+    begin
+      Rank := lua_toInteger(L, -1);
+      if (Rank >= 1) and (Rank <= Length(R)) then
+        R[I].Rank := Rank
+    end;
+
+    lua_pop(L, 1);
+    
+  end;
+
+  // pop table
+  lua_pop(L, 1);
+
+  if (not Party.SetRanking(R)) then
+    luaL_error(L, PChar('cann''t set party round ranking. Is party started and not finished yet?'));
+end;
+
+{ Party.GetTeams - returns a table with all information and structure as
+  in the TPartyGame.Teams array }
+function ULuaParty_GetTeams(L: Plua_State): Integer; cdecl;
+  var
+    Team: Integer;
+    Player: Integer;
+begin
+  // clear stack
+  lua_pop(L, lua_gettop(L));
+
+  // ensure we have enough stack slots left
+  lua_checkstack(L, 7);
+
+  // create the table we want to return
+  lua_createtable(L, Length(Party.Teams), 0);
+
+  // add the teams
+  for Team := 0 to High(Party.Teams) do
+  begin
+    // push key for current teams value. lua array beggins at 1
+    lua_pushInteger(L, Team + 1);
+
+    // push table containing team info and players table
+    lua_createtable(L, 0, 5);
+
+    // team name
+    lua_pushString(L, PChar(Party.Teams[Team].Name));
+    lua_setField(L, -2, 'Name');
+
+    // team score
+    lua_pushInteger(L, Party.Teams[Team].Score);
+    lua_setField(L, -2, 'Score');
+
+    // team jokers left
+    lua_pushInteger(L, Party.Teams[Team].JokersLeft);
+    lua_setField(L, -2, 'JokersLeft');
+
+    // team nextPlayer
+    lua_pushInteger(L, Party.Teams[Team].NextPlayer);
+    lua_setField(L, -2, 'NextPlayer');
+
+    // team players table
+    lua_createtable(L, Length(Party.Teams[Team].Players), 0);
+
+    //add players
+    for Player := 0 to High(Party.Teams[Team].Players) do
+    begin
+      // push key for current players value. lua array beggins at 1
+      lua_pushInteger(L, Player + 1);
+
+      // push table containing player info
+      lua_createTable(L, 0, 2);
+
+      // player name
+      lua_PushString(L, PChar(Party.Teams[Team].Players[Player].Name));
+      lua_SetField(L, -2, 'Name');
+
+      // players times played
+      lua_PushInteger(L, Party.Teams[Team].Players[Player].TimesPlayed);
+      lua_SetField(L, -2, 'TimesPlayed');
+
+      // add value - key - pair to teams player table
+      lua_setTable(L, -3);
+    end;
+
+    lua_setField(L, -2, 'Players');
+
+    // add value - key - pair to returned table
+    lua_setTable(L, -3);
+  end;
+
+  // we return 1 value (the first table)
+  Result := 1;
+end;
+
+{ Party.SetTeams - changes all fields from TPartyGame.Teams that have been
+  set in the table given as first argument}
+function ULuaParty_SetTeams(L: Plua_State): Integer; cdecl;
+
+  procedure Do_Player(Team, Player: Integer);
+    var
+      Key: String;
+  begin
+    if (Player >= 0) and (Player <= High(Party.Teams[Team].Players)) then
+    begin
+      // go through table elements
+      lua_pushNil(L);
+      while (lua_Next(L, -2) <> 0) do
+      begin
+        Key := lowercase(lua_ToString(L, -2));
+
+        if (Key = 'name') and lua_isString(L, -1) then
+          Party.Teams[Team].Players[Player].Name := lua_toString(L, -1)
+        else if (Key = 'timesplayed') and lua_isNumber(L, -1) then
+          Party.Teams[Team].Players[Player].TimesPlayed := lua_toInteger(L, -1);
+
+        // pop value from stack so key is on top
+        lua_pop(L, 1);
+      end;
+    end;
+  end;
+
+  procedure Do_Players(Team: Integer);
+  begin
+    // go through table elements
+    lua_pushNil(L);
+    while (lua_Next(L, -2) <> 0) do
+    begin
+      // check if key is a number and value is a table
+      if (lua_isNumber(L, -2)) and (lua_isTable(L, -1)) then
+        Do_Player(Team, lua_toInteger(L, -2));
+
+      // pop value from stack so key is on top
+      lua_pop(L, 1);
+    end;
+  end;
+
+  procedure Do_Team(Team: Integer);
+    var
+      Key: String;
+  begin
+    if (Team >= 0) and (Team <= High(Party.Teams)) then
+    begin
+      // go through table elements
+      lua_pushNil(L);
+      while (lua_Next(L, -2) <> 0) do
+      begin
+        Key := lowercase(lua_ToString(L, -2));
+
+        if (Key = 'name') and lua_isString(L, -1) then
+          Party.Teams[Team].Name := lua_toString(L, -1)
+        else if (Key = 'score') and lua_isNumber(L, -1) then
+          Party.Teams[Team].Score := lua_toInteger(L, -1)
+        else if (Key = 'jokersleft') and lua_isNumber(L, -1) then
+          Party.Teams[Team].JokersLeft := lua_toInteger(L, -1)
+        else if (Key = 'currentplayer') and lua_isNumber(L, -1) then
+          Party.Teams[Team].NextPlayer := lua_toInteger(L, -1)
+        else if (Key = 'players') and lua_isTable(L, -1) then
+          Do_Players(Team);
+
+        // pop value from stack so key is on top
+        lua_pop(L, 1);
+      end;
+    end;
+  end;
+begin
+  Result := 0;
+  
+  // check for table on stack
+  luaL_checkType(L, 1, LUA_TTABLE);
+
+
+  // go through table elements
+  lua_pushNil(L);
+  while (lua_Next(L, 1) <> 0) do
+  begin
+    // check if key is a number and value is a table
+    if (lua_isNumber(L, -2)) and (lua_isTable(L, -1)) then
+      Do_Team(lua_toInteger(L, -2));
+
+    // pop value from stack so key is on top
+    lua_pop(L, 1);
+  end;
+
+  // clear stack from table
+  lua_pop(L, lua_gettop(L));
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/lua/ULuaScreenSing.pas b/songmanagement/src/lua/ULuaScreenSing.pas
new file mode 100644
index 00000000..7e17224c
--- /dev/null
+++ b/songmanagement/src/lua/ULuaScreenSing.pas
@@ -0,0 +1,489 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/branches/experimental/Lua/src/lua/ULuaTexture.pas $
+ * $Id: ULuaTexture.pas 1551 2009-01-04 14:08:33Z Hawkear $
+ *}
+
+unit ULuaScreenSing;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  ULua;
+
+{ returns a table with following structure:
+    t[1..playercount] = score of player i }
+function ULuaScreenSing_GetScores(L: Plua_State): Integer; cdecl;
+
+{ returns a table with following structure:
+    t[1..playercount] = rating of player i range: [0..1] }
+function ULuaScreenSing_GetRating(L: Plua_State): Integer; cdecl;
+
+{ returns a table with following structure:
+    t[1..playercount] = rect of players score background: table(x, y, w, h) }
+function ULuaScreenSing_GetScoreBGRect(L: Plua_State): Integer; cdecl;
+
+{ returns a table with following structure:
+    t[1..playercount] = rect of players rating bar: table(x, y, w, h) }
+function ULuaScreenSing_GetRBRect(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.GetBPM - no arguments
+  returns the beats per minutes of the current song in quarts }
+function ULuaScreenSing_GetBPM(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.BeatsToSeconds(Beats: float)
+  returns the time in seconds that the given number of beats (in quarts) last }
+function ULuaScreenSing_BeatsToSeconds(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.SecondsToBeats(Seconds: float)
+  returns the Beats in quarts that the given seconds last }
+function ULuaScreenSing_SecondsToBeats(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.GetBeat() - returns current beat of lyricstate (in quarts) }
+function ULuaScreenSing_GetBeat(L: Plua_State): Integer; cdecl;
+
+{ finishes current song, if sing screen is not shown it will raise
+  an error }
+function ULuaScreenSing_Finish(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.GetSettings - no arguments
+  returns a table filled with the data of TScreenSing.Settings }
+function ULuaScreenSing_GetSettings(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.SetSettings - arguments: Table
+  sets all attributes of TScreenSing.Settings that are
+  unequal to nil in Table }
+function ULuaScreenSing_SetSettings(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.GetSongLines - no arguments
+  returns a table filled with lines of the loaded song or
+  nil if no song is loaded (singscreen is not displayed)
+  structure of returned table:
+    array [1.."count of lines"]
+     \
+     | Start: integer - beat the line is displayed at (on top of lyrics display)
+     | Lyric: string  - full lyric of the line
+     | Notes: array [1.."count notes of this line"]
+     \
+      | Start: integer    - beat the note starts at
+      | Length: integer   - length in beats
+      | Tone: integer     - pitch that has to be sung, full range
+      | NoteType: integer - 0 for freestyle, 1 for normal, 2 for golden
+      | Text: string      - text of this fragment }
+function ULuaScreenSing_GetSongLines(L: Plua_State): Integer; cdecl;
+
+const
+  ULuaScreenSing_Lib_f: array [0..11] of lual_reg = (
+    (name:'GetScores';func:ULuaScreenSing_GetScores),
+    (name:'GetRating';func:ULuaScreenSing_GetRating),
+    (name:'GetBPM';func:ULuaScreenSing_GetBPM),
+    (name:'BeatsToSeconds';func:ULuaScreenSing_BeatsToSeconds),
+    (name:'SecondsToBeats';func:ULuaScreenSing_SecondsToBeats),
+    (name:'GetBeat';func:ULuaScreenSing_GetBeat),
+    (name:'GetScoreBGRect';func:ULuaScreenSing_GetScoreBGRect),
+    (name:'GetRBRect';func:ULuaScreenSing_GetRBRect),
+    (name:'Finish';func:ULuaScreenSing_Finish),
+    (name:'GetSettings';func:ULuaScreenSing_GetSettings),
+    (name:'SetSettings';func:ULuaScreenSing_SetSettings),
+    (name:'GetSongLines';func:ULuaScreenSing_GetSongLines)
+  );
+
+implementation
+uses UScreenSing, UNote, UDisplay, UGraphic, UMusic, ULuaUtils, SysUtils;
+
+{ returns a table with following structure:
+    t[1..playercount] = score of player i }
+function ULuaScreenSing_GetScores(L: Plua_State): Integer; cdecl;
+  var
+    Top: Integer;
+    I: Integer;
+begin
+  Result := 1;
+
+  // pop arguments
+  Top := lua_getTop(L);
+  if (Top > 0) then
+    lua_pop(L, Top);
+
+  // create table
+  lua_createtable(L, Length(Player), 0);
+
+  // fill w/ values
+  for I := 0 to High(Player) do
+  begin
+    lua_pushInteger(L, I + 1);
+    lua_pushInteger(L, Player[I].ScoreTotalInt);
+
+    lua_settable(L, -3);
+  end;
+
+  // leave table on stack, it is our result
+end;
+
+{ returns a table with following structure:
+    t[1..playercount] = rating of player i range: [0..1] }
+function ULuaScreenSing_GetRating(L: Plua_State): Integer; cdecl;
+  var
+    Top: Integer;
+    I: Integer;
+begin
+  Result := 1;
+
+  // pop arguments
+  Top := lua_getTop(L);
+  if (Top > 0) then
+    lua_pop(L, Top);
+
+  // create table
+  lua_createtable(L, Length(Player), 0);
+
+  // fill w/ values
+  for I := 0 to High(ScreenSing.Scores.Players) do
+  begin
+    lua_pushInteger(L, I + 1);
+    lua_pushNumber(L, ScreenSing.Scores.Players[I].RBPos);
+
+    lua_settable(L, -3);
+  end;
+
+  // leave table on stack, it is our result
+end;
+
+{ ScreenSing.GetBPM - no arguments
+  returns the beats per minutes of the current song in quarts }
+function ULuaScreenSing_GetBPM(L: Plua_State): Integer; cdecl;
+begin
+  lua_ClearStack(L);
+  Result := 1;
+
+  if (CurrentSong = nil) or (Length(CurrentSong.BPM) = 0) or (Display.CurrentScreen <> @ScreenSing) then
+    lua_PushNumber(L, 0) // in case of error
+  else if (Length(CurrentSong.BPM) = 1) then
+    lua_PushNumber(L, CurrentSong.BPM[0].BPM)
+  else
+  begin
+    // to-do: do this for songs w/ BPM changes
+    //        or drop support for BPM changes?!
+  end;
+end;
+
+{ ScreenSing.BeatsToSeconds(Beats: float)
+  returns the time in seconds that the given number of beats (in quarts) last }
+function ULuaScreenSing_BeatsToSeconds(L: Plua_State): Integer; cdecl;
+begin
+  Result := 1;
+
+  if (CurrentSong = nil) or (Length(CurrentSong.BPM) = 0) or (Display.CurrentScreen <> @ScreenSing) then
+    lua_PushNumber(L, 0) // in case of error
+  else if (Length(CurrentSong.BPM) = 1) then
+    lua_PushNumber(L, luaL_CheckNumber(L, 1) * 60 / CurrentSong.BPM[0].BPM)
+  else
+  begin
+    // to-do: do this for songs w/ BPM changes
+    //        or drop support for BPM changes?!
+  end;
+end;
+
+{ ScreenSing.BeatsToSeconds(Seconds: float)
+  returns the Beats in quarts that the given seconds last }
+function ULuaScreenSing_SecondsToBeats(L: Plua_State): Integer; cdecl;
+begin
+  Result := 1;
+
+  if (CurrentSong = nil) or (Length(CurrentSong.BPM) = 0) or (Display.CurrentScreen <> @ScreenSing) then
+    lua_PushNumber(L, 0)
+  else if (Length(CurrentSong.BPM) = 1) then
+    lua_PushNumber(L, luaL_CheckNumber(L, 1) * CurrentSong.BPM[0].BPM / 60)
+  else
+  begin
+    // to-do: do this for songs w/ BPM changes
+    //        or drop support for BPM changes?!
+  end;
+end;
+
+{ ScreenSing.GetBeat() - returns current beat of lyricstate (in quarts) }
+function ULuaScreenSing_GetBeat(L: Plua_State): Integer; cdecl;
+var top: Integer;
+begin
+  //remove arguments (if any)
+  top := lua_gettop(L);
+
+  if (top > 0) then
+    lua_pop(L, top);
+
+  //push result
+  lua_pushnumber(L, LyricsState.MidBeat);
+  Result := 1; //one result
+end;
+
+{ returns a table with following structure:
+    t[1..playercount] = rect of players ScoreBG: table(x, y, w, h) }
+function ULuaScreenSing_GetScoreBGRect(L: Plua_State): Integer; cdecl;
+  var
+    Top: Integer;
+    I: Integer;
+begin
+  Result := 1;
+
+  // pop arguments
+  Top := lua_getTop(L);
+  if (Top > 0) then
+    lua_pop(L, Top);
+
+  // create table
+  lua_createtable(L, Length(ScreenSing.Scores.Players), 0);
+
+  // fill w/ values
+  for I := 0 to High(ScreenSing.Scores.Players) do
+  begin
+    lua_pushInteger(L, I + 1);
+
+    if (ScreenSing.Scores.Players[I].Position = High(Byte)) then
+      // player has no position, prevent crash by pushing nil
+      lua_pushNil(L)
+    else
+      with ScreenSing.Scores.Positions[ScreenSing.Scores.Players[I].Position] do
+        lua_PushRect(L, BGX, BGY, BGW, BGH);
+
+
+    lua_settable(L, -3);
+  end;
+
+  // leave table on stack, it is our result
+end;
+
+{ returns a table with following structure:
+    t[1..playercount] = rect of players rating bar: table(x, y, w, h) }
+function ULuaScreenSing_GetRBRect(L: Plua_State): Integer; cdecl;
+  var
+    Top: Integer;
+    I: Integer;
+begin
+  Result := 1;
+
+  // pop arguments
+  Top := lua_getTop(L);
+  if (Top > 0) then
+    lua_pop(L, Top);
+
+  // create table
+  lua_createtable(L, Length(ScreenSing.Scores.Players), 0);
+
+  // fill w/ values
+  for I := 0 to High(ScreenSing.Scores.Players) do
+  begin
+    lua_pushInteger(L, I + 1);
+
+    if (ScreenSing.Scores.Players[I].Position = High(Byte)) then
+      // player has no position, prevent crash by pushing nil
+      lua_pushNil(L)
+    else
+      with ScreenSing.Scores.Positions[ScreenSing.Scores.Players[I].Position] do
+        lua_PushRect(L, RBX, RBY, RBW, RBH);
+
+
+    lua_settable(L, -3);
+  end;
+
+  // leave table on stack, it is our result
+end;
+
+{ finishes current song, if sing screen is not shown it will raise
+  an error }
+function ULuaScreenSing_Finish(L: Plua_State): Integer; cdecl;
+  var Top: Integer;
+begin
+  Result := 0;
+
+  // pop arguments
+  Top := lua_getTop(L);
+  if (Top > 0) then
+    lua_pop(L, Top);
+
+  if (Display.CurrentScreen^ = ScreenSing) then
+  begin
+    ScreenSing.EndSong;
+  end
+  else
+    LuaL_error(L, 'Usdx.ScreenSing.Finish is called, but sing screen is not shown.'); 
+end;
+
+{ ScreenSing.GetSettings - no arguments
+  returns a table filled with the data of TScreenSing }
+function ULuaScreenSing_GetSettings(L: Plua_State): Integer; cdecl;
+  var Top: Integer;
+begin
+  // pop arguments
+  Top := lua_getTop(L);
+  if (Top > 0) then
+    lua_pop(L, Top);
+
+  lua_createtable(L, 0, 3);
+
+  //fill table w/ info
+  lua_pushBoolean(L, ScreenSing.Settings.LyricsVisible);
+  lua_setField(L, -2, 'LyricsVisible');
+
+  lua_pushBinInt(L, ScreenSing.Settings.NotesVisible);
+  lua_setField(L, -2, 'NotesVisible');
+
+  lua_pushBinInt(L, ScreenSing.Settings.PlayerEnabled);
+  lua_setField(L, -2, 'PlayerEnabled');
+
+
+  Result := 1;
+end;
+
+{ ScreenSing.SetSettings - arguments: Table
+  sets all attributes of TScreenSing.Settings that are
+  unequal to nil in Table }
+function ULuaScreenSing_SetSettings(L: Plua_State): Integer; cdecl;
+  var
+    Key: String;
+begin
+  Result := 0;
+
+  // check for table on stack
+  luaL_checkType(L, 1, LUA_TTABLE);
+
+  // go through table elements
+  lua_pushNil(L);
+  while (lua_Next(L, 1) <> 0) do
+  begin
+    Key := lowercase(lua_ToString(L, -2));
+
+    if (Key = 'lyricsvisible') and (lua_isBoolean(L, -1)) then
+      ScreenSing.settings.LyricsVisible := lua_toBoolean(L, -1)
+    else if (Key = 'notesvisible') and (lua_isTable(L, -1)) then
+      ScreenSing.settings.NotesVisible := lua_toBinInt(L, -1)
+    else if (Key = 'playerenabled') and (lua_isTable(L, -1)) then
+      ScreenSing.settings.PlayerEnabled := lua_toBinInt(L, -1);
+
+    // pop value from stack so key is on top
+    lua_pop(L, 1);
+  end;
+
+  // clear stack from table
+  lua_pop(L, lua_gettop(L));
+
+  ScreenSing.ApplySettings;
+end;
+
+{ ScreenSing.GetSongLines - no arguments
+  returns a table filled with lines of the loaded song or
+  nil if no song is loaded (singscreen is not displayed)
+  structure of returned table:
+    array [1.."count of lines"]
+     \
+     | Start: integer - beat the line is displayed at (on top of lyrics display)
+     | Lyric: string  - full lyric of the line
+     | Notes: array [1.."count notes of this line"]
+     \
+      | Start: integer    - beat the note starts at
+      | Length: integer   - length in beats
+      | Tone: integer     - pitch that has to be sung, full range
+      | NoteType: integer - 0 for freestyle, 1 for normal, 2 for golden
+      | Text: string      - text of this fragment }
+function ULuaScreenSing_GetSongLines(L: Plua_State): Integer; cdecl;
+  var
+    I, J: Integer;
+begin
+  Result := 1;
+  if  (Length(Lines) >= 1) then
+  begin
+    lua_ClearStack(L);
+
+    if not lua_CheckStack(L, 7) then
+      luaL_Error(L, PChar('can''t allocate enough stack space in ULuaScreenSing_GetSongLines'));
+
+    // lines array table
+    lua_CreateTable(L, Length(Lines[0].Line), 0);
+
+    for I := 0 to High(Lines[0].Line) do
+    with Lines[0].Line[I] do
+    begin
+      lua_pushInteger(L, I+1);
+
+      // line struct table
+      lua_CreateTable(L, 0, 3);
+
+      // line start
+      lua_PushInteger(L, Start);
+      lua_SetField(L, -2, PChar('Start'));
+
+      // line lyric
+      lua_PushString(L, PChar(Lyric));
+      lua_SetField(L, -2, PChar('Lyric'));
+
+      //line notes array table
+      lua_CreateTable(L, Length(Note), 0);
+
+      for J := 0 to High(Note) do
+      begin
+        lua_PushInteger(L, J + 1);
+
+        // note struct table
+        lua_CreateTable(L, 0, 5);
+
+        // Notes[J+1].Start
+        lua_PushInteger(L, Note[J].Start);
+        lua_SetField(L, -2, PChar('Start'));
+
+        // Notes[J+1].Length
+        lua_PushInteger(L, Note[J].Length);
+        lua_SetField(L, -2, PChar('Length'));
+
+        // Notes[J+1].Tone
+        lua_PushInteger(L, Note[J].Tone);
+        lua_SetField(L, -2, PChar('Tone'));
+
+        // Notes[J+1].NoteType
+        lua_PushInteger(L, Integer(Note[J].NoteType));
+        lua_SetField(L, -2, PChar('NoteType'));
+
+        // Notes[J+1].Text
+        lua_PushString(L, PChar(Note[J].Text));
+        lua_SetField(L, -2, PChar('Text'));
+
+        lua_SetTable(L, -3);
+      end;
+
+      lua_SetField(L, -2, PChar('Notes'));
+
+      // save line to array table
+      lua_setTable(L, -3);
+    end;
+  end
+  else
+  begin
+    lua_ClearStack(L);
+    lua_pushNil(L);
+  end;
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/lua/ULuaTextGL.pas b/songmanagement/src/lua/ULuaTextGL.pas
new file mode 100644
index 00000000..2e70a2c1
--- /dev/null
+++ b/songmanagement/src/lua/ULuaTextGL.pas
@@ -0,0 +1,148 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaTextGL;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  TextGL,
+  SysUtils,
+  ULua;
+
+{ TextGl.Pos(X, Y: Float) : sets font position }
+function ULuaTextGL_Pos(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Size(Size: Float) : sets font size }
+function ULuaTextGL_Size(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Style(Style: int) : sets font style (from 0 to 3) }
+function ULuaTextGL_Style(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Italic(isItalic: boolean) : sets if font is italic }
+function ULuaTextGL_Italic(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Width(Text: String) : returns width of Text if printed
+  w/ current settings in pixels }
+function ULuaTextGL_Width(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Print(Text: String) : prints text to screen w/ current
+  settings}
+function ULuaTextGL_Print(L: Plua_State): Integer; cdecl;
+
+const
+  ULuaTextGl_Lib_f: array [0..5] of lual_reg = (
+    (name:'Pos'; func:ULuaTextGl_Pos),
+    (name:'Size'; func:ULuaTextGl_Size),
+    (name:'Style'; func:ULuaTextGl_Style),
+    (name:'Italic'; func:ULuaTextGl_Italic),
+    (name:'Width'; func:ULuaTextGl_Width),
+    (name:'Print'; func:ULuaTextGl_Print)
+  );
+
+
+implementation
+
+{ TextGl.Pos(X, Y: Float) : sets font position }
+function ULuaTextGL_Pos(L: Plua_State): Integer; cdecl;
+  var X, Y: Double;
+begin
+  X := luaL_checknumber(L, 1);
+  Y := luaL_checknumber(L, 2);
+
+  SetFontPos(X, Y);
+
+  Result := 0;
+end;
+
+{ TextGl.Size(Size: Float) : sets font size }
+function ULuaTextGL_Size(L: Plua_State): Integer; cdecl;
+  var Size: Double;
+begin
+  Size := luaL_checknumber(L, 1);
+
+  SetFontSize(Size);
+  
+  Result := 0;
+end;
+
+{ TextGl.Style(Style: int) : sets font style (from 0 to 3) }
+function ULuaTextGL_Style(L: Plua_State): Integer; cdecl;
+  var Style: Integer;
+begin
+  Style := luaL_checkinteger(L, 1);
+
+  if (Style >= 0) and (Style < Length(Fonts)) then
+    SetFontStyle(Style)
+  else
+    luaL_ArgError(L, 1, PChar('number from 0 to ' + IntToStr(High(Fonts)) + ' expected'));
+
+  Result := 0;
+end;
+
+{ TextGl.Italic(isItalic: boolean) : sets if font is italic }
+function ULuaTextGL_Italic(L: Plua_State): Integer; cdecl;
+  var isItalic: Boolean;
+begin
+  luaL_checkany(L, 1);
+  isItalic := lua_toBoolean(L, 1);
+
+  SetFontItalic(isItalic);
+  
+  Result := 0;
+end;
+
+{ TextGl.Width(Text: String) : returns width of Text if printed
+  w/ current settings in pixels }
+function ULuaTextGL_Width(L: Plua_State): Integer; cdecl;
+  var Text: String;
+begin
+  Text := luaL_checkstring(L, 1);
+  lua_pop(L, lua_gettop(L));
+
+  lua_PushNumber(L, glTextWidth(Text));
+
+  Result := 1;
+end;
+
+{ TextGl.Print(Text: String) : prints text to screen w/ current
+  settings}
+function ULuaTextGL_Print(L: Plua_State): Integer; cdecl;
+  var Text: String;
+begin
+  Text := luaL_checkstring(L, 1);
+
+  glPrint(Text);
+
+  Result := 0;
+end;
+
+end.
diff --git a/songmanagement/src/lua/ULuaTexture.pas b/songmanagement/src/lua/ULuaTexture.pas
new file mode 100644
index 00000000..931c0405
--- /dev/null
+++ b/songmanagement/src/lua/ULuaTexture.pas
@@ -0,0 +1,63 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaTexture;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  ULua,
+  UTexture;
+
+function luaopen_Texture (L: Plua_State): Integer; cdecl;
+
+function ULuaTexture_Dummy(L: Plua_State): Integer; cdecl;
+
+implementation
+
+function ULuaTexture_Dummy(L: Plua_State): Integer; cdecl;
+begin
+  result:=0; // number of results
+end;
+
+const
+  ULuaTexture_Lib_f: array [0..1] of lual_reg = (
+   (name:'Add';func:ULuaTexture_Dummy),
+   (name:nil;func:nil)
+   );
+
+function luaopen_Texture (L: Plua_State): Integer; cdecl;
+begin
+    luaL_register(L,'Texture',@ULuaTexture_Lib_f[0]);
+    result:=1;
+end;
+end.
diff --git a/songmanagement/src/lua/ULuaUsdx.pas b/songmanagement/src/lua/ULuaUsdx.pas
new file mode 100644
index 00000000..d92289b1
--- /dev/null
+++ b/songmanagement/src/lua/ULuaUsdx.pas
@@ -0,0 +1,145 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaUsdx;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses ULua;
+
+{ some basic lua c functions from usdx table }
+
+{ Usdx.Time - returns sdl_time to have time numbers comparable with
+              ultrastar deluxe ones. no arguments }
+function ULuaUsdx_Time(L: Plua_State): Integer; cdecl;
+
+{ Usdx.Version - returns Usdx version string (the same that US_Version
+  language-constant does). no arguments }
+function ULuaUsdx_Version(L: Plua_State): Integer; cdecl;
+
+{ Usdx.Hook - returns an hook table with name and Unhook function
+              arguments: event_name: string }
+function ULuaUsdx_Hook(L: Plua_State): Integer; cdecl;
+
+{ Usdx.ShutMeDown - no results, no arguments
+  unloads the calling plugin }
+function ULuaUsdx_ShutMeDown(L: Plua_State): Integer; cdecl;
+
+const
+  ULuaUsdx_Lib_f: array [0..4] of lual_reg = (
+    (name:'Version'; func:ULuaUsdx_Version),
+    (name:'Time'; func:ULuaUsdx_Time),
+    (name:'Hook'; func:ULuaUsdx_Hook),
+    (name:'ShutMeDown'; func:ULuaUsdx_ShutMeDown),
+    (name:nil;func:nil)
+  );
+
+implementation
+uses SDL, ULuaCore, ULuaUtils, UHookableEvent, UConfig;
+
+{ Usdx.Time - returns sdl_time to have time numbers comparable with
+              ultrastar deluxe ones. no arguments }
+function ULuaUsdx_Time(L: Plua_State): Integer; cdecl;
+  var top: Integer;
+begin
+  //remove arguments (if any)
+  top := lua_gettop(L);
+
+  if (top > 0) then
+    lua_pop(L, top);
+
+  //push result
+  lua_pushinteger(L, SDL_GetTicks);
+  Result := 1; //one result
+end;
+
+{ Usdx.Version - returns Usdx version string (the same that US_Version
+  language-constant does). no arguments }
+function ULuaUsdx_Version(L: Plua_State): Integer; cdecl;
+  var top: Integer;
+begin
+  //remove arguments (if any)
+  top := lua_gettop(L);
+
+  if (top > 0) then
+    lua_pop(L, top);
+
+  //push result
+  lua_pushstring(L, PChar(USDXVersionStr()));
+  Result := 1; //one result
+end;
+
+{ Usdx.Hook - returns an hook table with name and Unhook function
+              arguments: event_name: string; function_name: string }
+function ULuaUsdx_Hook(L: Plua_State): Integer; cdecl;
+var
+  EventName: String;
+  FunctionName: String;
+  P: TLuaPlugin;
+  Event: THookableEvent;
+begin
+  EventName := luaL_checkstring(L, 1);
+  FunctionName := luaL_checkstring(L, 2);
+
+  P := Lua_GetOwner(L);
+
+  lua_pop(L, lua_gettop(L)); //clear stack
+
+  Result := 1;
+
+  Event := LuaCore.GetEventByName(EventName);
+  if (Event <> nil) then
+  begin
+    Event.Hook(L, P.Id, FunctionName);
+  end
+  else
+    luaL_error(L, PChar('event does not exist: ' + EventName));
+end;
+
+function ULuaUsdx_ShutMeDown(L: Plua_State): Integer; cdecl;
+  var
+    top: Integer;
+    P: TLuaPlugin;
+begin
+  Result := 0;
+  
+  //remove arguments (if any)
+  top := lua_gettop(L);
+
+  if (top > 0) then
+    lua_pop(L, top);
+
+  P := Lua_GetOwner(L);
+
+  P.ShutMeDown;
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/lua/ULuaUtils.pas b/songmanagement/src/lua/ULuaUtils.pas
new file mode 100644
index 00000000..143b34d4
--- /dev/null
+++ b/songmanagement/src/lua/ULuaUtils.pas
@@ -0,0 +1,186 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaUtils;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses ULua, ULuaCore;
+
+{ converts a lua table with a structure like:
+    * = 1 , * = 4 , * = 5
+  to an integer with the value:
+    0b11001
+  does not pop anything }
+function Lua_ToBinInt(L: PLua_State; idx: Integer): Integer;
+
+{ converts an integer with the value:
+    0b11001
+  to a lua table with a structure like:
+    * = 1 , * = 4 , * = 5
+  and pushed the table onto the stack }
+procedure Lua_PushBinInt(L: PLua_State; BinInt: Integer);
+
+{ pushes a table with position and size of a rectangle
+  t.x => position of the rectangle in pixels at x-axis
+  t.y => position of the rectangle in pixels at y-axis
+  t.w => width of the rectangle
+  t.h => height of the rectangle }
+procedure Lua_PushRect(L: PLua_State; X, Y, W, H: Double);
+
+{ returns plugin that is the owner of the given state
+  may raise a lua error if the parent id is not found
+  in states registry, if state owner does not exists
+  or is not loaded. So a check for a nil value is not
+  necessary }
+function Lua_GetOwner(L: PLua_State): TLuaPlugin;
+
+{ this is a helper in case an evenet owner don't has no use for the results
+  returns number of popped elements }
+function Lua_ClearStack(L: Plua_State): Integer;
+
+
+implementation
+
+{ converts a lua table with a structure like:
+    * = 1 , * = 4 , * = 5
+  to an integer with the value:
+    0b11001
+  does not pop anything }
+function Lua_ToBinInt(L: PLua_State; idx: Integer): Integer;
+  var
+    I: Integer;
+begin
+  // default: no bits set
+  Result := 0;
+
+  lua_checkstack(L, 2);
+
+  if (idx < 0) then
+    dec(idx); // we will push one value before using this
+
+  lua_PushNil(L);
+  while (lua_next(L, idx) <> 0) do
+  begin
+    if (lua_isNumber(L, -1)) then
+    begin //check if we got an integer value from 1 to 32
+      I := lua_toInteger(L, -1);
+      if (I >= 1) and (I <= 32) then
+        Result := Result or 1 shl (I - 1);
+    end;
+
+    // pop value, so key is on top
+    lua_pop(L, 1);
+  end;
+end;
+
+{ converts an integer with the value:
+    0b11001
+  to a lua table with a structure like:
+    * = 1 , * = 4 , * = 5
+  and pushed the table onto the stack }
+procedure Lua_PushBinInt(L: PLua_State; BinInt: Integer);
+var
+  I, Index: Integer;
+begin
+  lua_newTable(L);
+
+
+  Index := 1; //< lua starts w/ index 1
+  for I := 0 to 31 do
+    if (BinInt and (1 shl I) <> 0) then
+    begin
+      lua_pushInteger(L, Index);
+      lua_pushInteger(L, I);
+      lua_settable(L, -3);
+
+      Inc(Index);
+    end;
+end;
+
+{ pushes a table with position and size of a rectangle
+  t.x => position of the rectangle in pixels at x-axis
+  t.y => position of the rectangle in pixels at y-axis
+  t.w => width of the rectangle
+  t.h => height of the rectangle }
+procedure Lua_PushRect(L: PLua_State; X, Y, W, H: Double);
+begin
+  lua_createtable(L, 0, 4); // table w/ 4 record fields
+
+  // x pos
+  lua_pushNumber(L, X);
+  lua_setField(L, -2, 'x');
+
+  // y pos
+  lua_pushNumber(L, Y);
+  lua_setField(L, -2, 'y');
+
+  // width
+  lua_pushNumber(L, W);
+  lua_setField(L, -2, 'w');
+
+  // height
+  lua_pushNumber(L, H);
+  lua_setField(L, -2, 'h');
+end;
+
+{ returns plugin that is the owner of the given state
+  may raise a lua error if the parent id is not found
+  in states registry, if state owner does not exists
+  or is not loaded. So a check for a nil value is not
+  necessary }
+function Lua_GetOwner(L: PLua_State): TLuaPlugin;
+begin
+  lua_checkstack(L, 1);
+
+  lua_getfield (L, LUA_REGISTRYINDEX, '_USDX_STATE_ID');
+  if (not lua_isNumber(L, -1)) then
+    luaL_error(L, 'unable to get _USDX_STATE_ID');
+
+  Result := LuaCore.GetPluginById(lua_toInteger(L, -1));
+
+  lua_pop(L, 1); //< remove state id from stack
+
+  if (Result = nil) then
+    luaL_error(L, '_USDX_STATE_ID has invalid value')
+  else if (Result.Status > psRunning) then
+    luaL_error(L, 'owning plugin is not loaded or already unloaded in Lua_GetOwner');
+end;
+
+{ this is a helper in case an evenet owner don't has no use for the results
+  returns number of popped elements }
+function Lua_ClearStack(L: Plua_State): Integer;
+begin
+  Result := lua_gettop(L);
+  lua_pop(L, Result);
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/macosx/Info.plist b/songmanagement/src/macosx/Info.plist
new file mode 100644
index 00000000..0456dd9d
--- /dev/null
+++ b/songmanagement/src/macosx/Info.plist
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleDisplayName</key>
+	<string>UltraStarDeluxe</string>
+	<key>CFBundleExecutable</key>
+	<string>ultrastardx</string>
+	<key>CFBundleGetInfoString</key>
+	<string>UltraStarDeluxe, a SingStar clone</string>
+	<key>CFBundleIconFile</key>
+	<string>ultrastardx.icns</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.ultrastardeluxe.ultrastardeluxe</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>UltraStarDeluxe</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.1</string>
+	<key>CFBundleSignature</key>
+	<string>USDX</string>
+	<key>CFBundleVersion</key>
+	<string>1.1</string>
+	<key>NSAppleScriptEnabled</key>
+	<false/>
+	<key>NSHumanReadableCopyright</key>
+	<string>LGPL</string>
+	<key>NSMainNibFile</key>
+	<string>SDLMain</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
diff --git a/songmanagement/src/macosx/PseudoThread.pas b/songmanagement/src/macosx/PseudoThread.pas
new file mode 100644
index 00000000..d74285f7
--- /dev/null
+++ b/songmanagement/src/macosx/PseudoThread.pas
@@ -0,0 +1,75 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit PseudoThread;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+interface
+
+type
+
+// Debugging threads with XCode doesn't seem to work.
+// We use PseudoThread in Debug mode to get proper debugging.
+
+TPseudoThread = class(TObject)
+  private
+  protected
+    Terminated,
+    FreeOnTerminate: boolean;
+    procedure Execute; virtual; abstract;
+    procedure Resume;
+    procedure Suspend;
+  public
+   constructor Create(const suspended : boolean);
+end;
+
+implementation
+
+{ TPseudoThread }
+
+constructor TPseudoThread.Create(const suspended: boolean);
+begin
+  if not suspended then
+  begin
+    Execute;
+  end;
+end;
+
+procedure TPseudoThread.Resume;
+begin
+  Execute;
+end;
+
+procedure TPseudoThread.Suspend;
+begin
+end;
+
+end.
+ 
diff --git a/songmanagement/src/media/UAudioConverter.pas b/songmanagement/src/media/UAudioConverter.pas
new file mode 100644
index 00000000..657b80dd
--- /dev/null
+++ b/songmanagement/src/media/UAudioConverter.pas
@@ -0,0 +1,483 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioConverter;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMusic,
+  ULog,
+  ctypes,
+  {$IFDEF UseSRCResample}
+  samplerate,
+  {$ENDIF}
+  {$IFDEF UseFFmpegResample}
+  avcodec,
+  {$ENDIF}
+  UMediaCore_SDL,
+  sdl,
+  SysUtils,
+  Math;
+
+type
+  {*
+   * Notes:
+   *  - 44.1kHz to 48kHz conversion or vice versa is not supported
+   *    by SDL 1.2 (will be introduced in 1.3).
+   *    No conversion takes place in this cases.
+   *    This is because SDL just converts differences in powers of 2.
+   *    So the result might not be that accurate.
+   *    This IS audible (voice to high/low) and it needs good synchronization
+   *    with the video or the lyrics timer.
+   *  - float<->int16 conversion is not supported (will be part of 1.3) and
+   *    SDL (<1.3) is not capable of handling floats at all.
+   *  -> Using FFmpeg or libsamplerate for resampling is preferred.
+   *     Use SDL for channel and format conversion only.
+   *}
+  TAudioConverter_SDL = class(TAudioConverter)
+    private
+      cvt: TSDL_AudioCVT;
+    public
+      function Init(SrcFormatInfo: TAudioFormatInfo; DstFormatInfo: TAudioFormatInfo): boolean; override;
+      destructor Destroy(); override;
+
+      function Convert(InputBuffer: PByteArray; OutputBuffer: PByteArray; var InputSize: integer): integer; override;
+      function GetOutputBufferSize(InputSize: integer): integer; override;
+      function GetRatio(): double; override;
+  end;
+
+  {$IFDEF UseFFmpegResample}
+  // Note: FFmpeg seems to be using "kaiser windowed sinc" for resampling, so
+  // the quality should be good.
+  TAudioConverter_FFmpeg = class(TAudioConverter)
+    private
+      // TODO: use SDL for multi-channel->stereo and format conversion
+      ResampleContext: PReSampleContext;
+      Ratio: double;
+    public
+      function Init(SrcFormatInfo: TAudioFormatInfo; DstFormatInfo: TAudioFormatInfo): boolean; override;
+      destructor Destroy(); override;
+
+      function Convert(InputBuffer: PByteArray; OutputBuffer: PByteArray; var InputSize: integer): integer; override;
+      function GetOutputBufferSize(InputSize: integer): integer; override;
+      function GetRatio(): double; override;
+  end;
+  {$ENDIF}
+
+  {$IFDEF UseSRCResample}
+  TAudioConverter_SRC = class(TAudioConverter)
+    private
+      ConverterState: PSRC_STATE;
+      ConversionData: SRC_DATA;
+      FormatConverter: TAudioConverter;
+    public
+      function Init(SrcFormatInfo: TAudioFormatInfo; DstFormatInfo: TAudioFormatInfo): boolean; override;
+      destructor Destroy(); override;
+
+      function Convert(InputBuffer: PByteArray; OutputBuffer: PByteArray; var InputSize: integer): integer; override;
+      function GetOutputBufferSize(InputSize: integer): integer; override;
+      function GetRatio(): double; override;
+  end;
+
+  // Note: SRC (=libsamplerate) provides several converters with different quality
+  // speed trade-offs. The SINC-types are slow but offer best quality.
+  // The SRC_SINC_* converters are too slow for realtime conversion,
+  // (SRC_SINC_FASTEST is approx. ten times slower than SRC_LINEAR) resulting
+  // in audible clicks and pops.
+  // SRC_LINEAR is very fast and should have a better quality than SRC_ZERO_ORDER_HOLD
+  // because it interpolates the samples. Normal "non-audiophile" users should not
+  // be able to hear a difference between the SINC_* ones and LINEAR. Especially
+  // if people sing along with the song.
+  // But FFmpeg might offer a better quality/speed ratio than SRC_LINEAR.
+  const
+    SRC_CONVERTER_TYPE = SRC_LINEAR; 
+  {$ENDIF}
+
+implementation
+
+function TAudioConverter_SDL.Init(srcFormatInfo: TAudioFormatInfo; dstFormatInfo: TAudioFormatInfo): boolean;
+var
+  srcFormat: UInt16;
+  dstFormat: UInt16;
+begin
+  inherited Init(SrcFormatInfo, DstFormatInfo);
+
+  Result := false;
+
+  if (not ConvertAudioFormatToSDL(srcFormatInfo.Format, srcFormat) or
+      not ConvertAudioFormatToSDL(dstFormatInfo.Format, dstFormat)) then
+  begin
+    Log.LogError('Audio-format not supported by SDL', 'TSoftMixerPlaybackStream.InitFormatConversion');
+    Exit;
+  end;
+
+  if (SDL_BuildAudioCVT(@cvt,
+    srcFormat, srcFormatInfo.Channels, Round(srcFormatInfo.SampleRate),
+    dstFormat, dstFormatInfo.Channels, Round(dstFormatInfo.SampleRate)) = -1) then
+  begin
+    Log.LogError(SDL_GetError(), 'TSoftMixerPlaybackStream.InitFormatConversion');
+    Exit;
+  end;
+
+  Result := true;
+end;
+
+destructor TAudioConverter_SDL.Destroy();
+begin
+  // nothing to be done here
+  inherited;
+end;
+
+(*
+ * Returns the size of the output buffer. This might be bigger than the actual
+ * size of resampled audio data.
+ *)
+function TAudioConverter_SDL.GetOutputBufferSize(InputSize: integer): integer;
+begin
+  // Note: len_ratio must not be used here. Even if the len_ratio is 1.0, len_mult might be 2.
+  // Example: 44.1kHz/mono to 22.05kHz/stereo -> len_ratio=1, len_mult=2
+  Result := InputSize * cvt.len_mult;
+end;
+
+function TAudioConverter_SDL.GetRatio(): double;
+begin
+  Result := cvt.len_ratio;
+end;
+
+function TAudioConverter_SDL.Convert(InputBuffer: PByteArray; OutputBuffer: PByteArray; var InputSize: integer): integer;
+begin
+  Result := -1;
+
+  if (InputSize <= 0) then
+  begin
+    // avoid div-by-zero problems
+    if (InputSize = 0) then
+      Result := 0;
+    Exit;
+  end;
+
+  // OutputBuffer is always bigger than or equal to InputBuffer
+  Move(InputBuffer[0], OutputBuffer[0], InputSize);
+  cvt.buf := PUint8(OutputBuffer);
+  cvt.len := InputSize;
+  if (SDL_ConvertAudio(@cvt) = -1) then
+    Exit;
+
+  Result := cvt.len_cvt;
+end;
+
+
+{$IFDEF UseFFmpegResample}
+
+function TAudioConverter_FFmpeg.Init(SrcFormatInfo: TAudioFormatInfo; DstFormatInfo: TAudioFormatInfo): boolean;
+begin
+  inherited Init(SrcFormatInfo, DstFormatInfo);
+
+  Result := false;
+
+  // Note: ffmpeg does not support resampling for more than 2 input channels
+
+  if (srcFormatInfo.Format <> asfS16) then
+  begin
+    Log.LogError('Unsupported format', 'TAudioConverter_FFmpeg.Init');
+    Exit;
+  end;
+
+  // TODO: use SDL here
+  if (srcFormatInfo.Format <> dstFormatInfo.Format) then
+  begin
+    Log.LogError('Incompatible formats', 'TAudioConverter_FFmpeg.Init');
+    Exit;
+  end;
+
+  ResampleContext := audio_resample_init(
+      dstFormatInfo.Channels, srcFormatInfo.Channels,
+      Round(dstFormatInfo.SampleRate), Round(srcFormatInfo.SampleRate));
+  if (ResampleContext = nil) then
+  begin
+    Log.LogError('audio_resample_init() failed', 'TAudioConverter_FFmpeg.Init');
+    Exit;
+  end;
+
+  // calculate ratio
+  Ratio := (dstFormatInfo.Channels / srcFormatInfo.Channels) *
+           (dstFormatInfo.SampleRate / srcFormatInfo.SampleRate);
+
+  Result := true;
+end;
+
+destructor TAudioConverter_FFmpeg.Destroy();
+begin
+  if (ResampleContext <> nil) then
+    audio_resample_close(ResampleContext);
+  inherited;
+end;
+
+function TAudioConverter_FFmpeg.Convert(InputBuffer: PByteArray; OutputBuffer: PByteArray; var InputSize: integer): integer;
+var
+  InputSampleCount: integer;
+  OutputSampleCount: integer;
+begin
+  Result := -1;
+
+  if (InputSize <= 0) then
+  begin
+    // avoid div-by-zero in audio_resample()
+    if (InputSize = 0) then
+      Result := 0;
+    Exit;
+  end;
+
+  InputSampleCount := InputSize div SrcFormatInfo.FrameSize;
+  OutputSampleCount := audio_resample(
+      ResampleContext, PSmallInt(OutputBuffer), PSmallInt(InputBuffer),
+      InputSampleCount);
+  if (OutputSampleCount = -1) then
+  begin
+    Log.LogError('audio_resample() failed', 'TAudioConverter_FFmpeg.Convert');
+    Exit;
+  end;
+  Result := OutputSampleCount * DstFormatInfo.FrameSize;
+end;
+
+function TAudioConverter_FFmpeg.GetOutputBufferSize(InputSize: integer): integer;
+begin
+  Result := Ceil(InputSize * GetRatio());
+end;
+
+function TAudioConverter_FFmpeg.GetRatio(): double;
+begin
+  Result := Ratio;
+end;
+
+{$ENDIF}
+
+
+{$IFDEF UseSRCResample}
+
+function TAudioConverter_SRC.Init(SrcFormatInfo: TAudioFormatInfo; DstFormatInfo: TAudioFormatInfo): boolean;
+var
+  error: integer;
+  TempSrcFormatInfo: TAudioFormatInfo;
+  TempDstFormatInfo: TAudioFormatInfo;
+begin
+  inherited Init(SrcFormatInfo, DstFormatInfo);
+
+  Result := false;
+
+  FormatConverter := nil;
+
+  // SRC does not handle channel or format conversion
+  if ((SrcFormatInfo.Channels <> DstFormatInfo.Channels) or
+      not (SrcFormatInfo.Format in [asfS16, asfFloat])) then
+  begin
+    // SDL can not convert to float, so we have to convert to SInt16 first
+    TempSrcFormatInfo := TAudioFormatInfo.Create(
+        SrcFormatInfo.Channels, SrcFormatInfo.SampleRate, SrcFormatInfo.Format);
+    TempDstFormatInfo := TAudioFormatInfo.Create(
+        DstFormatInfo.Channels, SrcFormatInfo.SampleRate, asfS16);
+
+    // init format/channel conversion
+    FormatConverter := TAudioConverter_SDL.Create();
+    if (not FormatConverter.Init(TempSrcFormatInfo, TempDstFormatInfo)) then
+    begin
+      Log.LogError('Unsupported input format', 'TAudioConverter_SRC.Init');
+      FormatConverter.Free;
+      // exit after the format-info is freed
+    end;
+
+    // this info was copied so we do not need it anymore 
+    TempSrcFormatInfo.Free;
+    TempDstFormatInfo.Free;
+
+    // leave if the format is not supported
+    if (not assigned(FormatConverter)) then
+      Exit;
+
+    // adjust our copy of the input audio-format for SRC conversion
+    Self.SrcFormatInfo.Channels := DstFormatInfo.Channels;
+    Self.SrcFormatInfo.Format := asfS16;
+  end;
+
+  if ((DstFormatInfo.Format <> asfS16) and
+      (DstFormatInfo.Format <> asfFloat)) then
+  begin
+    Log.LogError('Unsupported output format', 'TAudioConverter_SRC.Init');
+    Exit;
+  end;
+
+  ConversionData.src_ratio := DstFormatInfo.SampleRate / SrcFormatInfo.SampleRate;
+  if (src_is_valid_ratio(ConversionData.src_ratio) = 0) then
+  begin
+    Log.LogError('Invalid samplerate ratio', 'TAudioConverter_SRC.Init');
+    Exit;
+  end;
+
+  ConverterState := src_new(SRC_CONVERTER_TYPE, DstFormatInfo.Channels, @error);
+  if (ConverterState = nil) then
+  begin
+    Log.LogError('src_new() failed: ' + src_strerror(error), 'TAudioConverter_SRC.Init');
+    Exit;
+  end;
+
+  Result := true;
+end;
+
+destructor TAudioConverter_SRC.Destroy();
+begin
+  if (ConverterState <> nil) then
+    src_delete(ConverterState);
+  FormatConverter.Free;
+  inherited;
+end;
+
+function TAudioConverter_SRC.Convert(InputBuffer: PByteArray; OutputBuffer: PByteArray; var InputSize: integer): integer;
+var
+  FloatInputBuffer: PSingle;
+  FloatOutputBuffer: PSingle;
+  TempBuffer: PByteArray;
+  TempSize: integer;
+  NumSamples: integer;
+  OutputSize: integer;
+  error: integer;
+begin
+  Result := -1;
+
+  TempBuffer := nil;
+
+  // format conversion with external converter (to correct number of channels and format)
+  if (assigned(FormatConverter)) then
+  begin
+    TempSize := FormatConverter.GetOutputBufferSize(InputSize);
+    GetMem(TempBuffer, TempSize);
+    InputSize := FormatConverter.Convert(InputBuffer, TempBuffer, InputSize);
+    InputBuffer := TempBuffer;
+  end;
+
+  if (InputSize <= 0) then
+  begin
+    // avoid div-by-zero problems
+    if (InputSize = 0) then
+      Result := 0;
+    if (TempBuffer <> nil) then
+      FreeMem(TempBuffer);
+    Exit;
+  end;
+
+  if (SrcFormatInfo.Format = asfFloat) then
+  begin
+    FloatInputBuffer := PSingle(InputBuffer);
+  end else begin
+    NumSamples := InputSize div AudioSampleSize[SrcFormatInfo.Format];
+    GetMem(FloatInputBuffer, NumSamples * SizeOf(Single));
+    src_short_to_float_array(PCshort(InputBuffer), PCfloat(FloatInputBuffer), NumSamples);
+  end;
+
+  // calculate approx. output size
+  OutputSize := Ceil(InputSize * ConversionData.src_ratio);
+
+  if (DstFormatInfo.Format = asfFloat) then
+  begin
+    FloatOutputBuffer := PSingle(OutputBuffer);
+  end else begin
+    NumSamples := OutputSize div AudioSampleSize[DstFormatInfo.Format];
+    GetMem(FloatOutputBuffer, NumSamples * SizeOf(Single));
+  end;
+
+  with ConversionData do
+  begin
+    data_in := PCFloat(FloatInputBuffer);
+    input_frames := InputSize div SrcFormatInfo.FrameSize;
+    data_out := PCFloat(FloatOutputBuffer);
+    output_frames := OutputSize div DstFormatInfo.FrameSize;
+    // TODO: set this to 1 at end of file-playback
+    end_of_input := 0;
+  end;
+
+  error := src_process(ConverterState, @ConversionData);
+  if (error <> 0) then
+  begin
+    Log.LogError(src_strerror(error), 'TAudioConverter_SRC.Convert');
+    if (SrcFormatInfo.Format <> asfFloat) then
+      FreeMem(FloatInputBuffer);
+    if (DstFormatInfo.Format <> asfFloat) then
+      FreeMem(FloatOutputBuffer);
+    if (TempBuffer <> nil) then
+      FreeMem(TempBuffer);
+    Exit;
+  end;
+
+  if (SrcFormatInfo.Format <> asfFloat) then
+    FreeMem(FloatInputBuffer);
+
+  if (DstFormatInfo.Format <> asfFloat) then
+  begin
+    NumSamples := ConversionData.output_frames_gen * DstFormatInfo.Channels;
+    src_float_to_short_array(PCfloat(FloatOutputBuffer), PCshort(OutputBuffer), NumSamples);
+    FreeMem(FloatOutputBuffer);
+  end;
+
+  // free format conversion buffer if used
+  if (TempBuffer <> nil) then
+    FreeMem(TempBuffer);
+
+  if (assigned(FormatConverter)) then
+    InputSize := ConversionData.input_frames_used * FormatConverter.SrcFormatInfo.FrameSize
+  else
+    InputSize := ConversionData.input_frames_used * SrcFormatInfo.FrameSize;
+
+  // set result to output size according to SRC
+  Result := ConversionData.output_frames_gen * DstFormatInfo.FrameSize;
+end;
+
+function TAudioConverter_SRC.GetOutputBufferSize(InputSize: integer): integer;
+begin
+  Result := Ceil(InputSize * GetRatio());
+end;
+
+function TAudioConverter_SRC.GetRatio(): double;
+begin
+  // if we need additional channel/format conversion, use this ratio
+  if (assigned(FormatConverter)) then
+    Result := FormatConverter.GetRatio()
+  else
+    Result := 1.0;
+
+  // now the SRC ratio (Note: the format might change from SInt16 to float)
+  Result := Result *
+            ConversionData.src_ratio *
+            (DstFormatInfo.FrameSize / SrcFormatInfo.FrameSize);
+end;
+
+{$ENDIF}
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/media/UAudioCore_Bass.pas b/songmanagement/src/media/UAudioCore_Bass.pas
new file mode 100644
index 00000000..3a84dcd7
--- /dev/null
+++ b/songmanagement/src/media/UAudioCore_Bass.pas
@@ -0,0 +1,177 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioCore_Bass;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  SysUtils,
+  UMusic,
+  bass;     // (Note: DWORD is defined here)
+
+type
+  TAudioCore_Bass = class
+    public
+      constructor Create();
+      class function GetInstance(): TAudioCore_Bass;
+      function CheckVersion(): boolean;
+      function ErrorGetString(): string; overload;
+      function ErrorGetString(errCode: integer): string; overload;
+      function ConvertAudioFormatToBASSFlags(Format: TAudioSampleFormat; out Flags: DWORD): boolean;
+      function ConvertBASSFlagsToAudioFormat(Flags: DWORD; out Format: TAudioSampleFormat): boolean;
+    private
+      function DecodeVersion(VersionHex: integer): string;
+  end;
+
+implementation
+
+uses
+  UMain,
+  ULog;
+
+const
+  // BASS 2.4.2 is not ABI compatible with older versions
+  // as (BASS_RECORDINFO.driver was removed)
+  BASS_MIN_REQUIRED_VERSION = $02040201;
+
+var
+  Instance: TAudioCore_Bass;
+
+constructor TAudioCore_Bass.Create();
+begin
+  inherited;
+end;
+
+class function TAudioCore_Bass.GetInstance(): TAudioCore_Bass;
+begin
+  if (not Assigned(Instance)) then
+    Instance := TAudioCore_Bass.Create();
+  Result := Instance;
+end;
+
+function TAudioCore_Bass.DecodeVersion(VersionHex: integer): string;
+var
+  Version: array [0..3] of integer;
+begin
+  Version[0] := (VersionHex shr 24) and $FF;
+  Version[1] := (VersionHex shr 16) and $FF;
+  Version[2] := (VersionHex shr 8) and $FF;
+  Version[3] := (VersionHex shr 0) and $FF;
+  Result := Format('%x.%x.%x.%x', [Version[0], Version[1], Version[2], Version[3]]);
+end;
+
+function TAudioCore_Bass.CheckVersion(): boolean;
+begin
+  Result := BASS_GetVersion() >= BASS_MIN_REQUIRED_VERSION;
+  if (not Result) then
+  begin
+    Log.LogWarn('Could not init BASS audio library. ''bass.dll'' version is ' + DecodeVersion(BASS_GetVersion()) + ' but ' + DecodeVersion(BASS_MIN_REQUIRED_VERSION) + ' or higher is required.',
+        'TAudioCore_Bass.CheckVersion');
+  end;
+end;
+
+function TAudioCore_Bass.ErrorGetString(): string;
+begin
+  Result := ErrorGetString(BASS_ErrorGetCode());
+end;
+
+function TAudioCore_Bass.ErrorGetString(errCode: integer): string;
+begin
+  case errCode of
+    BASS_OK:             result := 'No error';
+    BASS_ERROR_MEM:      result := 'Insufficient memory';
+    BASS_ERROR_FILEOPEN: result := 'File could not be opened';
+    BASS_ERROR_DRIVER:   result := 'Device driver not available';
+    BASS_ERROR_BUFLOST:  result := 'Buffer lost';
+    BASS_ERROR_HANDLE:   result := 'Invalid Handle';
+    BASS_ERROR_FORMAT:   result := 'Sample-Format not supported';
+    BASS_ERROR_POSITION: result := 'Illegal position';
+    BASS_ERROR_INIT:     result := 'BASS_Init has not been successfully called';
+    BASS_ERROR_START:    result := 'Paused/stopped';
+    BASS_ERROR_ALREADY:  result := 'Already created/used';
+    BASS_ERROR_NOCHAN:   result := 'No free channels';
+    BASS_ERROR_ILLTYPE:  result := 'Type is invalid';
+    BASS_ERROR_ILLPARAM: result := 'Illegal parameter';
+    BASS_ERROR_NO3D:     result := 'No 3D support';
+    BASS_ERROR_NOEAX:    result := 'No EAX support';
+    BASS_ERROR_DEVICE:   result := 'Invalid device number';
+    BASS_ERROR_NOPLAY:   result := 'Channel not playing';
+    BASS_ERROR_FREQ:     result := 'Freq out of range';
+    BASS_ERROR_NOTFILE:  result := 'Not a file stream';
+    BASS_ERROR_NOHW:     result := 'No hardware support';
+    BASS_ERROR_EMPTY:    result := 'Is empty';
+    BASS_ERROR_NONET:    result := 'Network unavailable';
+    BASS_ERROR_CREATE:   result := 'Creation error';
+    BASS_ERROR_NOFX:     result := 'DX8 effects unavailable';
+    BASS_ERROR_NOTAVAIL: result := 'Not available';
+    BASS_ERROR_DECODE:   result := 'Is a decoding channel';
+    BASS_ERROR_DX:       result := 'Insufficient version of DirectX';
+    BASS_ERROR_TIMEOUT:  result := 'Timeout';
+    BASS_ERROR_FILEFORM: result := 'File-Format not recognised/supported';
+    BASS_ERROR_SPEAKER:  result := 'Requested speaker(s) not support';
+    BASS_ERROR_VERSION:  result := 'Version error';
+    BASS_ERROR_CODEC:    result := 'Codec not available/supported';
+    BASS_ERROR_ENDED:    result := 'The channel/file has ended';
+    BASS_ERROR_UNKNOWN:  result := 'Unknown error';
+    else                 result := 'Unknown error';
+  end;
+end;
+
+function TAudioCore_Bass.ConvertAudioFormatToBASSFlags(Format: TAudioSampleFormat; out Flags: DWORD): boolean;
+begin
+  case Format of
+    asfS16:   Flags := 0;
+    asfFloat: Flags := BASS_SAMPLE_FLOAT;
+    asfU8:    Flags := BASS_SAMPLE_8BITS;
+    else begin
+      Result := false;
+      Exit;
+    end;
+  end;
+
+  Result := true;
+end;
+
+function TAudioCore_Bass.ConvertBASSFlagsToAudioFormat(Flags: DWORD; out Format: TAudioSampleFormat): boolean;
+begin
+  if ((Flags and BASS_SAMPLE_FLOAT) <> 0) then
+    Format := asfFloat
+  else if ((Flags and BASS_SAMPLE_8BITS) <> 0) then
+    Format := asfU8
+  else
+    Format := asfS16;
+
+  Result := true;
+end;
+
+end.
diff --git a/songmanagement/src/media/UAudioCore_Portaudio.pas b/songmanagement/src/media/UAudioCore_Portaudio.pas
new file mode 100644
index 00000000..c97b5d10
--- /dev/null
+++ b/songmanagement/src/media/UAudioCore_Portaudio.pas
@@ -0,0 +1,337 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioCore_Portaudio;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I ../switches.inc}
+
+uses
+  Classes,
+  SysUtils,
+  portaudio;
+
+type
+  TAudioCore_Portaudio = class
+    private
+      InitCount: integer; ///< keeps track of the number of Initialize/Terminate calls
+    public
+      constructor Create();
+      class function GetInstance(): TAudioCore_Portaudio;
+      function Initialize(): boolean;
+      function Terminate(): boolean;
+      function GetPreferredApiIndex(): TPaHostApiIndex;
+      function TestDevice(inParams, outParams: PPaStreamParameters; var sampleRate: double): boolean;
+  end;
+
+implementation
+
+uses
+  ULog;
+
+{*
+ * The default API used by Portaudio is the least common denominator
+ * and might lack efficiency. In addition it might not even work.
+ * We use an array named ApiPreferenceOrder with which we define the order of
+ * preferred APIs to use. The first API-type in the list is tried first.
+ * If it is not available the next one is tried and so on ...
+ * If none of the preferred APIs was found the default API (detected by
+ * portaudio) is used.
+ *
+ * Pascal does not permit zero-length static arrays, so you must use paDefaultApi
+ * as an array's only member if you do not have any preferences.
+ * You can also append paDefaultApi to a non-zero length preferences array but
+ * this is optional because the default API is always used as a fallback.
+ *}
+const
+  paDefaultApi = -1;
+const
+  ApiPreferenceOrder:
+{$IF Defined(MSWINDOWS)}
+    // Note1: Portmixer has no mixer support for paASIO and paWASAPI at the moment
+    // Note2: Windows Default-API is MME, but DirectSound is faster
+    array[0..0] of TPaHostApiTypeId = ( paDirectSound );
+{$ELSEIF Defined(DARWIN)}
+    array[0..0] of TPaHostApiTypeId = ( paDefaultApi ); // paCoreAudio
+{$ELSEIF Defined(UNIX)}
+    // Note: Portmixer has no mixer support for JACK at the moment
+    array[0..2] of TPaHostApiTypeId = ( paALSA, paJACK, paOSS );
+{$ELSE}
+    array[0..0] of TPaHostApiTypeId = ( paDefaultApi );
+{$IFEND}
+
+
+{ TAudioInput_Portaudio }
+
+var
+  Instance: TAudioCore_Portaudio;
+
+constructor TAudioCore_Portaudio.Create();
+begin
+  inherited;
+  InitCount := 0;
+end;
+
+class function TAudioCore_Portaudio.GetInstance(): TAudioCore_Portaudio;
+begin
+  if not assigned(Instance) then
+    Instance := TAudioCore_Portaudio.Create();
+  Result := Instance;
+end;
+
+function TAudioCore_Portaudio.Initialize(): boolean;
+var
+  Err: TPaError;
+begin
+  // initialize only once
+  if (InitCount > 0) then
+  begin
+    Inc(InitCount);
+    Result := true;
+    Exit;
+  end;
+
+  // init Portaudio
+  Err := Pa_Initialize();
+  if (Err <> paNoError) then
+  begin
+    Log.LogError(Pa_GetErrorText(Err), 'TAudioCore_Portaudio.Initialize');
+    Result := false;
+    Exit;
+  end;
+
+  // only increment on success
+  Inc(InitCount);
+  Result := true;
+end;
+
+function TAudioCore_Portaudio.Terminate(): boolean;
+var
+  Err: TPaError;
+begin
+  // decrement usage count
+  Dec(InitCount);
+  if (InitCount > 0) then
+  begin
+    // do not terminate yet
+    Result := true;
+    Exit;
+  end;
+
+  // terminate if usage count is 0
+  Err := Pa_Terminate();
+  if (Err <> paNoError) then
+  begin
+    Log.LogError(Pa_GetErrorText(Err), 'TAudioCore_Portaudio.Terminate');
+    Result := false;
+    Exit;
+  end;
+
+  Result := true;
+end;
+
+function TAudioCore_Portaudio.GetPreferredApiIndex(): TPaHostApiIndex;
+var
+  i:        integer;
+  apiIndex: TPaHostApiIndex;
+  apiInfo:  PPaHostApiInfo;
+begin
+  result := -1;
+
+  // select preferred sound-API
+  for i:= 0 to High(ApiPreferenceOrder) do
+  begin
+    if (ApiPreferenceOrder[i] <> paDefaultApi) then
+    begin
+      // check if API is available
+      apiIndex := Pa_HostApiTypeIdToHostApiIndex(ApiPreferenceOrder[i]);
+      if (apiIndex >= 0) then
+      begin
+        // we found an API but we must check if it works
+        // (on linux portaudio might detect OSS but does not provide
+        // any devices if ALSA is enabled)
+        apiInfo := Pa_GetHostApiInfo(apiIndex);
+        if (apiInfo^.deviceCount > 0) then
+        begin
+          Result := apiIndex;
+          break;
+        end;
+      end;
+    end;
+  end;
+
+  // None of the preferred APIs is available -> use default
+  if (result < 0) then
+  begin
+    result := Pa_GetDefaultHostApi();
+  end;
+end;
+
+{*
+ * Portaudio test callback used by TestDevice().
+ *}
+function TestCallback(input: pointer; output: pointer; frameCount: longword;
+      timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
+      inputDevice: pointer): integer; cdecl;
+begin
+  // this callback is called only once
+  result := paAbort;
+end;
+
+(*
+ * Tests if the callback works. Some devices can be opened without
+ * an error but the callback is never called. Calling Pa_StopStream() on such
+ * a stream freezes USDX then. Probably because the callback-thread is deadlocked
+ * due to some bug in portaudio. The blocking Pa_ReadStream() and Pa_WriteStream()
+ * block forever too and though can't be used for testing.
+ *
+ * To avoid freezing Pa_AbortStream (or Pa_CloseStream which calls Pa_AbortStream)
+ * can be used to force the stream to stop. But for some reason this stops debugging
+ * in gdb with a "no process found" message.
+ *
+ * Because freezing devices are non-working devices we test the devices here to
+ * be able to exclude them from the device-selection list.
+ *
+ * Portaudio does not provide any test to check this error case (probably because
+ * it should not even occur). So we have to open the device, start the stream and
+ * check if the callback is called (the stream is stopped if the callback is called
+ * for the first time, so we can poll until the stream is stopped).
+ *
+ * Another error that occurs is that some devices (even the default device) might
+ * work at the beginning but stop after a few calls (maybe 50) of the callback.
+ * For me this problem occurs with the default output-device. The "dmix" or "front"
+ * device must be selected instead. Another problem is that (due to a bug in
+ * portaudio or ALSA) the "front" device is not detected every time portaudio
+ * is started. Sometimes it needs two or more restarts.
+ *
+ * There is no reasonable way to test for these errors. For the first error-case
+ * we could test if the callback is called 50 times but this can take a second
+ * for each device and it can fail in the 51st or even 100th callback call then.
+ *
+ * The second error-case cannot be tested at all. How should we now that one
+ * device is missing if portaudio is not even able to detect it.
+ * We could start and terminate Portaudio for several times and see if the device
+ * count changes but this is ugly.
+ *
+ * Conclusion: We are not able to autodetect a working device with
+ *   portaudio (at least not with the newest v19_20071207) at the moment.
+ *   So we have to provide the possibility to manually select an output device
+ *   in the UltraStar options if we want to use portaudio instead of SDL.
+ *)
+function TAudioCore_Portaudio.TestDevice(inParams, outParams: PPaStreamParameters; var sampleRate: double): boolean;
+const
+  altSampleRates: array[0..1] of double = (44100, 48000); // alternative sample-rates
+var
+  stream:  PPaStream;
+  err:     TPaError;
+  cbWorks: boolean;
+  cbPolls: integer;
+  i:       integer;
+begin
+  Result := false;
+
+  if (sampleRate <= 0) then
+    sampleRate := 44100;
+
+  // check if device supports our input-format
+  err := Pa_IsFormatSupported(inParams, outParams, sampleRate);
+  if (err <> paNoError) then
+  begin
+    // we cannot fix the error -> exit
+    if (err <> paInvalidSampleRate) then
+      Exit;
+
+    // try alternative sample-rates to the detected one
+    sampleRate := 0;
+    for i := 0 to High(altSampleRates) do
+    begin
+      // do not check the detected sample-rate twice
+      if (altSampleRates[i] = sampleRate) then
+        continue;
+      // check alternative
+      err := Pa_IsFormatSupported(inParams, outParams, altSampleRates[i]);
+      if (err = paNoError) then
+      begin
+        // sample-rate works
+        sampleRate := altSampleRates[i];
+        break;
+      end;
+    end;
+    // no working sample-rate found
+    if (sampleRate = 0) then
+      Exit;
+  end;
+
+  // FIXME: for some reason gdb stops after a call of Pa_AbortStream()
+  // which is implicitely called by Pa_CloseStream().
+  // gdb's stops with the message: "ptrace: no process found".
+  // Probably because the callback-thread is killed what confuses gdb.
+  {$IF Defined(Debug) and Defined(Linux)}
+  cbWorks := true;
+  {$ELSE}
+  // open device for testing
+  err := Pa_OpenStream(stream, inParams, outParams, sampleRate,
+          paFramesPerBufferUnspecified,
+          paNoFlag, @TestCallback, nil);
+  if (err <> paNoError) then
+  begin
+    exit;
+  end;
+
+  // start the callback
+  err := Pa_StartStream(stream);
+  if (err <> paNoError) then
+  begin
+    Pa_CloseStream(stream);
+    exit;
+  end;
+
+  cbWorks := false;
+  // check if the callback was called (poll for max. 200ms)
+  for cbPolls := 1 to 20 do
+  begin
+    // if the test-callback was called it should be aborted now
+    if (Pa_IsStreamActive(stream) = 0) then
+    begin
+      cbWorks := true;
+      break;
+    end;
+    // not yet aborted, wait and try (poll) again
+    Pa_Sleep(10);
+  end;
+
+  // finally abort the stream
+  Pa_CloseStream(stream);
+  {$IFEND}
+  
+  Result := cbWorks;
+end;
+
+end.
diff --git a/songmanagement/src/media/UAudioDecoder_Bass.pas b/songmanagement/src/media/UAudioDecoder_Bass.pas
new file mode 100644
index 00000000..d6d2425a
--- /dev/null
+++ b/songmanagement/src/media/UAudioDecoder_Bass.pas
@@ -0,0 +1,278 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioDecoder_Bass;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+implementation
+
+uses
+  Classes,
+  SysUtils,
+  bass,
+  UMain,
+  UMusic,
+  UAudioCore_Bass,
+  ULog,
+  UPath;
+
+type
+  TBassDecodeStream = class(TAudioDecodeStream)
+    private
+      Handle: HSTREAM;
+      FormatInfo : TAudioFormatInfo;
+      Error: boolean;
+    public
+      constructor Create(Handle: HSTREAM);
+      destructor Destroy(); override;
+
+      procedure Close();                     override;
+
+      function GetLength(): real;            override;
+      function GetAudioFormatInfo(): TAudioFormatInfo; override;
+      function GetPosition: real;            override;
+      procedure SetPosition(Time: real);     override;
+      function GetLoop(): boolean;           override;
+      procedure SetLoop(Enabled: boolean);   override;
+      function IsEOF(): boolean;             override;
+      function IsError(): boolean;           override;
+
+      function ReadData(Buffer: PByteArray; BufSize: integer): integer; override;
+  end;
+
+type
+  TAudioDecoder_Bass = class( TInterfacedObject, IAudioDecoder )
+    public
+      function GetName: string;
+
+      function InitializeDecoder(): boolean;
+      function FinalizeDecoder(): boolean;
+      function Open(const Filename: IPath): TAudioDecodeStream;
+  end;
+
+var
+  BassCore: TAudioCore_Bass;
+
+
+{ TBassDecodeStream }
+
+constructor TBassDecodeStream.Create(Handle: HSTREAM);
+var
+  ChannelInfo: BASS_CHANNELINFO;
+  Format: TAudioSampleFormat;
+begin
+  inherited Create();
+  Self.Handle := Handle;
+
+  // setup format info
+  if (not BASS_ChannelGetInfo(Handle, ChannelInfo)) then
+  begin
+    raise Exception.Create('Failed to open decode-stream');
+  end;
+  BassCore.ConvertBASSFlagsToAudioFormat(ChannelInfo.flags, Format);
+  FormatInfo := TAudioFormatInfo.Create(ChannelInfo.chans, ChannelInfo.freq, format);
+
+  Error := false;
+end;
+
+destructor TBassDecodeStream.Destroy();
+begin
+  Close();
+  inherited;
+end;
+
+procedure TBassDecodeStream.Close();
+begin
+  if (Handle <> 0) then
+  begin
+    BASS_StreamFree(Handle);
+    Handle := 0;
+  end;
+  PerformOnClose();
+  FreeAndNil(FormatInfo);
+  Error := false;
+end;
+
+function TBassDecodeStream.GetAudioFormatInfo(): TAudioFormatInfo;
+begin
+  Result := FormatInfo;
+end;
+
+function TBassDecodeStream.GetLength(): real;
+var
+  bytes: QWORD;
+begin
+  bytes  := BASS_ChannelGetLength(Handle, BASS_POS_BYTE);
+  Result := BASS_ChannelBytes2Seconds(Handle, bytes);
+end;
+
+function TBassDecodeStream.GetPosition: real;
+var
+  bytes: QWORD;
+begin
+  bytes  := BASS_ChannelGetPosition(Handle, BASS_POS_BYTE);
+  Result := BASS_ChannelBytes2Seconds(Handle, bytes);
+end;
+
+procedure TBassDecodeStream.SetPosition(Time: real);
+var
+  bytes: QWORD;
+begin
+  bytes := BASS_ChannelSeconds2Bytes(Handle, Time);
+  BASS_ChannelSetPosition(Handle, bytes, BASS_POS_BYTE);
+end;
+
+function TBassDecodeStream.GetLoop(): boolean;
+var
+  flags: DWORD;
+begin
+  // retrieve channel flags
+  flags := BASS_ChannelFlags(Handle, 0, 0);
+  if (flags = DWORD(-1)) then
+  begin
+    Log.LogError('BASS_ChannelFlags: ' + BassCore.ErrorGetString(), 'TBassDecodeStream.GetLoop');
+    Result := false;
+    Exit;
+  end;
+  Result := (flags and BASS_SAMPLE_LOOP) <> 0;
+end;
+
+procedure TBassDecodeStream.SetLoop(Enabled: boolean);
+var
+  flags: DWORD;
+begin
+  // set/unset loop-flag
+  if (Enabled) then
+    flags := BASS_SAMPLE_LOOP
+  else
+    flags := 0;
+
+  // set new flag-bits
+  if (BASS_ChannelFlags(Handle, flags, BASS_SAMPLE_LOOP) = DWORD(-1)) then
+  begin
+    Log.LogError('BASS_ChannelFlags: ' + BassCore.ErrorGetString(), 'TBassDecodeStream.SetLoop');
+    Exit;
+  end;
+end;
+
+function TBassDecodeStream.IsEOF(): boolean;
+begin
+  Result := (BASS_ChannelIsActive(Handle) = BASS_ACTIVE_STOPPED);
+end;
+
+function TBassDecodeStream.IsError(): boolean;
+begin
+  Result := Error;
+end;
+
+function TBassDecodeStream.ReadData(Buffer: PByteArray; BufSize: integer): integer;
+begin
+  Result := BASS_ChannelGetData(Handle, Buffer, BufSize);
+  // check error state (do not handle EOF as error)
+  if ((Result = -1) and (BASS_ErrorGetCode() <> BASS_ERROR_ENDED)) then
+    Error := true
+  else
+    Error := false;
+end;
+
+
+{ TAudioDecoder_Bass }
+
+function TAudioDecoder_Bass.GetName: String;
+begin
+  result := 'BASS_Decoder';
+end;
+
+function TAudioDecoder_Bass.InitializeDecoder(): boolean;
+begin
+  Result := false;
+  BassCore := TAudioCore_Bass.GetInstance();
+  if not BassCore.CheckVersion then
+    Exit;
+  Result := true;
+end;
+
+function TAudioDecoder_Bass.FinalizeDecoder(): boolean;
+begin
+  Result := true;
+end;
+
+function TAudioDecoder_Bass.Open(const Filename: IPath): TAudioDecodeStream;
+var
+  Stream: HSTREAM;
+  ChannelInfo: BASS_CHANNELINFO;
+  FileExt: string;
+begin
+  Result := nil;
+
+  // check if BASS was initialized
+  // in case the decoder is not used with BASS playback, init the NO_SOUND device
+  if ((integer(BASS_GetDevice) = -1) and (BASS_ErrorGetCode() = BASS_ERROR_INIT)) then
+    BASS_Init(0, 44100, 0, 0, nil);
+
+  // TODO: use BASS_STREAM_PRESCAN for accurate seeking in VBR-files?
+  //       disadvantage: seeking will slow down.
+  
+  {$IFDEF MSWINDOWS}
+  // Windows: Use UTF-16 version
+  Stream := BASS_StreamCreateFile(False, PWideChar(Filename.ToWide), 0, 0, BASS_STREAM_DECODE or BASS_UNICODE);
+  {$ELSE}
+  // Mac OS X: Use UTF8/ANSI version
+  Stream := BASS_StreamCreateFile(False, PAnsiChar(Filename.ToNative), 0, 0, BASS_STREAM_DECODE);
+  {$ENDIF}
+  if (Stream = 0) then
+  begin
+    //Log.LogError(BassCore.ErrorGetString(), 'TAudioDecoder_Bass.Open');
+    Exit;
+  end;
+
+  // check if BASS opened some erroneously recognized file-formats
+  if BASS_ChannelGetInfo(Stream, channelInfo) then
+  begin
+    fileExt := Filename.GetExtension.ToUTF8;
+    // BASS opens FLV-files (maybe others too) although it cannot handle them.
+    // Setting BASS_CONFIG_VERIFY to the max. value (100000) does not help.
+    if ((fileExt = '.flv') and (channelInfo.ctype = BASS_CTYPE_STREAM_MP1)) then
+    begin
+      BASS_StreamFree(Stream);
+      Exit;
+    end;
+  end;
+
+  Result := TBassDecodeStream.Create(Stream);
+end;
+
+
+initialization
+  MediaManager.Add(TAudioDecoder_Bass.Create);
+
+end.
diff --git a/songmanagement/src/media/UAudioDecoder_FFmpeg.pas b/songmanagement/src/media/UAudioDecoder_FFmpeg.pas
new file mode 100644
index 00000000..b44c7b11
--- /dev/null
+++ b/songmanagement/src/media/UAudioDecoder_FFmpeg.pas
@@ -0,0 +1,1159 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioDecoder_FFmpeg;
+
+(*******************************************************************************
+ *
+ * This unit is primarily based upon -
+ *   http://www.dranger.com/ffmpeg/ffmpegtutorial_all.html
+ *
+ *   and tutorial03.c
+ *
+ *   http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
+ *
+ *******************************************************************************)
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+// show FFmpeg specific debug output
+{.$DEFINE DebugFFmpegDecode}
+
+// FFmpeg is very verbose and shows a bunch of errors.
+// Those errors (they can be considered as warnings by us) can be ignored
+// as they do not give any useful information.
+// There is no solution to fix this except for turning them off.
+{.$DEFINE EnableFFmpegErrorOutput}
+
+implementation
+
+uses
+  SDL, // SDL redefines some base types -> include before SysUtils to ignore them
+  Classes,
+  Math,
+  SysUtils,
+  avcodec,
+  avformat,
+  avutil,
+  avio,
+  mathematics, // used for av_rescale_q
+  rational,
+  UMusic,
+  UIni,
+  UMain,
+  UMediaCore_FFmpeg,
+  ULog,
+  UCommon,
+  UConfig,
+  UPath;
+
+const
+  MAX_AUDIOQ_SIZE = (5 * 16 * 1024);
+
+const
+  // TODO: The factor 3/2 might not be necessary as we do not need extra
+  // space for synchronizing as in the tutorial.
+  AUDIO_BUFFER_SIZE = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) div 2;
+
+type
+  TFFmpegDecodeStream = class(TAudioDecodeStream)
+    private
+      fStateLock:   PSDL_Mutex;
+
+      fEOFState:   boolean; // end-of-stream flag (locked by StateLock)
+      fErrorState: boolean; // error flag (locked by StateLock)
+
+      fQuitRequest: boolean; // (locked by StateLock)
+      fParserIdleCond: PSDL_Cond;
+
+      // parser pause/resume data
+      fParserLocked:            boolean;
+      fParserPauseRequestCount: integer;
+      fParserUnlockedCond:      PSDL_Cond;
+      fParserResumeCond:        PSDL_Cond;
+
+      fSeekRequest: boolean; // (locked by StateLock)
+      fSeekFlags:   integer; // (locked by StateLock)
+      fSeekPos:     double;    // stream position to seek for (in secs) (locked by StateLock)
+      fSeekFlush:   boolean;   // true if the buffers should be flushed after seeking (locked by StateLock)
+      SeekFinishedCond: PSDL_Cond;
+
+      fLoop: boolean; // (locked by StateLock)
+
+      fParseThread: PSDL_Thread;
+      fPacketQueue: TPacketQueue;
+
+      fFormatInfo: TAudioFormatInfo;
+
+      // FFmpeg specific data
+      fFormatCtx: PAVFormatContext;
+      fCodecCtx:  PAVCodecContext;
+      fCodec:     PAVCodec;
+
+      fAudioStreamIndex: integer;
+      fAudioStream: PAVStream;
+      fAudioStreamPos: double; // stream position in seconds (locked by DecoderLock)
+
+      // decoder pause/resume data
+      fDecoderLocked:            boolean;
+      fDecoderPauseRequestCount: integer;
+      fDecoderUnlockedCond:      PSDL_Cond;
+      fDecoderResumeCond:        PSDL_Cond;
+
+      // state-vars for DecodeFrame (locked by DecoderLock)
+      fAudioPaket:        TAVPacket;
+      fAudioPaketData:    PByteArray;
+      fAudioPaketSize:    integer;
+      fAudioPaketSilence: integer; // number of bytes of silence to return
+
+      // state-vars for AudioCallback (locked by DecoderLock)
+      fAudioBufferPos:  integer;
+      fAudioBufferSize: integer;
+      fAudioBuffer:     PByteArray;
+
+      fFilename: IPath;
+
+      procedure SetPositionIntern(Time: real; Flush: boolean; Blocking: boolean);
+      procedure SetEOF(State: boolean);   {$IFDEF HasInline}inline;{$ENDIF}
+      procedure SetError(State: boolean); {$IFDEF HasInline}inline;{$ENDIF}
+      function IsSeeking(): boolean;
+      function IsQuit(): boolean;
+
+      procedure Reset();
+
+      procedure Parse();
+      function ParseLoop(): boolean;
+      procedure PauseParser();
+      procedure ResumeParser();
+
+      function DecodeFrame(Buffer: PByteArray; BufferSize: integer): integer;
+      procedure FlushCodecBuffers();
+      procedure PauseDecoder();
+      procedure ResumeDecoder();
+    public
+      constructor Create();
+      destructor Destroy(); override;
+
+      function Open(const Filename: IPath): boolean;
+      procedure Close();                     override;
+
+      function GetLength(): real;            override;
+      function GetAudioFormatInfo(): TAudioFormatInfo; override;
+      function GetPosition: real;            override;
+      procedure SetPosition(Time: real);     override;
+      function GetLoop(): boolean;           override;
+      procedure SetLoop(Enabled: boolean);   override;
+      function IsEOF(): boolean;             override;
+      function IsError(): boolean;           override;
+
+      function ReadData(Buffer: PByteArray; BufferSize: integer): integer; override;
+  end;
+
+type
+  TAudioDecoder_FFmpeg = class(TInterfacedObject, IAudioDecoder)
+    public
+      function GetName: string;
+
+      function InitializeDecoder(): boolean;
+      function FinalizeDecoder(): boolean;
+      function Open(const Filename: IPath): TAudioDecodeStream;
+  end;
+
+var
+  FFmpegCore: TMediaCore_FFmpeg;
+
+function ParseThreadMain(Data: Pointer): integer; cdecl; forward;
+
+
+{ TFFmpegDecodeStream }
+
+constructor TFFmpegDecodeStream.Create();
+begin
+  inherited Create();
+
+  fStateLock := SDL_CreateMutex();
+  fParserUnlockedCond := SDL_CreateCond();
+  fParserResumeCond := SDL_CreateCond();
+  fParserIdleCond := SDL_CreateCond();
+  SeekFinishedCond := SDL_CreateCond();
+  fDecoderUnlockedCond := SDL_CreateCond();
+  fDecoderResumeCond := SDL_CreateCond();
+
+  // according to the documentation of avcodec_decode_audio(2), sample-data
+  // should be aligned on a 16 byte boundary. Otherwise internal calls
+  // (e.g. to SSE or Altivec operations) might fail or lack performance on some
+  // CPUs. Although GetMem() in Delphi and FPC seems to use a 16 byte or higher
+  // alignment for buffers of this size (alignment depends on the size of the
+  // requested buffer), we will set the alignment explicitly as the minimum
+  // alignment used by Delphi and FPC is on an 8 byte boundary.
+  // 
+  // Note: AudioBuffer was previously defined as a field of type TAudioBuffer
+  // (array[0..AUDIO_BUFFER_SIZE-1] of byte) and hence statically allocated.
+  // Fields of records are aligned different to memory allocated with GetMem(),
+  // aligning depending on the type but will be at least 2 bytes.
+  // AudioBuffer was not aligned to a 16 byte boundary. The {$ALIGN x} directive
+  // was not applicable as Delphi in contrast to FPC provides at most 8 byte
+  // alignment ({$ALIGN 16} is not supported) by this directive.
+  fAudioBuffer := GetAlignedMem(AUDIO_BUFFER_SIZE, 16);
+
+  Reset();
+end;
+
+procedure TFFmpegDecodeStream.Reset();
+begin
+  fParseThread := nil;
+
+  fEOFState := false;
+  fErrorState := false;
+  fLoop := false;
+  fQuitRequest := false;
+
+  fAudioPaketData := nil;
+  fAudioPaketSize := 0;
+  fAudioPaketSilence := 0;
+
+  fAudioBufferPos := 0;
+  fAudioBufferSize := 0;
+
+  fParserLocked := false;
+  fParserPauseRequestCount := 0;
+  fDecoderLocked := false;
+  fDecoderPauseRequestCount := 0;
+
+  FillChar(fAudioPaket, SizeOf(TAVPacket), 0);
+end;
+
+{*
+ * Frees the decode-stream data.
+ *}
+destructor TFFmpegDecodeStream.Destroy();
+begin
+  Close();
+
+  SDL_DestroyMutex(fStateLock);
+  SDL_DestroyCond(fParserUnlockedCond);
+  SDL_DestroyCond(fParserResumeCond);
+  SDL_DestroyCond(fParserIdleCond);
+  SDL_DestroyCond(SeekFinishedCond);
+  SDL_DestroyCond(fDecoderUnlockedCond);
+  SDL_DestroyCond(fDecoderResumeCond);
+
+  FreeAlignedMem(fAudioBuffer);
+
+  inherited;
+end;
+
+function TFFmpegDecodeStream.Open(const Filename: IPath): boolean;
+var
+  SampleFormat: TAudioSampleFormat;
+  AVResult: integer;
+begin
+  Result := false;
+
+  Close();
+  Reset();
+
+  if (not Filename.IsFile) then
+  begin
+    Log.LogError('Audio-file does not exist: "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
+    Exit;
+  end;
+
+  Self.fFilename := Filename;
+
+  // use custom 'ufile' protocol for UTF-8 support
+  if (av_open_input_file(fFormatCtx, PAnsiChar('ufile:'+FileName.ToUTF8), nil, 0, nil) <> 0) then
+  begin
+    Log.LogError('av_open_input_file failed: "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
+    Exit;
+  end;
+
+  // generate PTS values if they do not exist
+  fFormatCtx^.flags := fFormatCtx^.flags or AVFMT_FLAG_GENPTS;
+
+  // retrieve stream information
+  if (av_find_stream_info(fFormatCtx) < 0) then
+  begin
+    Log.LogError('av_find_stream_info failed: "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
+    Close();
+    Exit;
+  end;
+
+  // FIXME: hack used by ffplay. Maybe should not use url_feof() to test for the end
+  fFormatCtx^.pb.eof_reached := 0;
+
+  {$IFDEF DebugFFmpegDecode}
+  dump_format(fFormatCtx, 0, PAnsiChar(Filename.ToNative), 0);
+  {$ENDIF}
+
+  fAudioStreamIndex := FFmpegCore.FindAudioStreamIndex(fFormatCtx);
+  if (fAudioStreamIndex < 0) then
+  begin
+    Log.LogError('FindAudioStreamIndex: No Audio-stream found "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
+    Close();
+    Exit;
+  end;
+
+  //Log.LogStatus('AudioStreamIndex is: '+ inttostr(ffmpegStreamID), 'UAudio_FFmpeg');
+
+  fAudioStream := fFormatCtx.streams[fAudioStreamIndex];
+  fAudioStreamPos := 0;
+  fCodecCtx := fAudioStream^.codec;
+
+  // TODO: should we use this or not? Should we allow 5.1 channel audio?
+  (*
+  {$IF LIBAVCODEC_VERSION >= 51042000}
+  if (CodecCtx^.channels > 0) then
+    CodecCtx^.request_channels := Min(2, CodecCtx^.channels)
+  else
+    CodecCtx^.request_channels := 2;
+  {$IFEND}
+  *)
+
+  fCodec := avcodec_find_decoder(fCodecCtx^.codec_id);
+  if (fCodec = nil) then
+  begin
+    Log.LogError('Unsupported codec!', 'UAudio_FFmpeg');
+    fCodecCtx := nil;
+    Close();
+    Exit;
+  end;
+
+  // set debug options
+  fCodecCtx^.debug_mv := 0;
+  fCodecCtx^.debug := 0;
+
+  // detect bug-workarounds automatically
+  fCodecCtx^.workaround_bugs := FF_BUG_AUTODETECT;
+  // error resilience strategy (careful/compliant/agressive/very_aggressive)
+  //CodecCtx^.error_resilience := FF_ER_CAREFUL; //FF_ER_COMPLIANT;
+  // allow non spec compliant speedup tricks.
+  //CodecCtx^.flags2 := CodecCtx^.flags2 or CODEC_FLAG2_FAST;
+
+  // Note: avcodec_open() and avcodec_close() are not thread-safe and will
+  // fail if called concurrently by different threads.
+  FFmpegCore.LockAVCodec();
+  try
+    AVResult := avcodec_open(fCodecCtx, fCodec);
+  finally
+    FFmpegCore.UnlockAVCodec();
+  end;
+  if (AVResult < 0) then
+  begin
+    Log.LogError('avcodec_open failed!', 'UAudio_FFmpeg');
+    Close();
+    Exit;
+  end;
+
+  // now initialize the audio-format
+
+  if (not FFmpegCore.ConvertFFmpegToAudioFormat(fCodecCtx^.sample_fmt, SampleFormat)) then
+  begin
+    // try standard format
+    SampleFormat := asfS16;
+  end;
+  if fCodecCtx^.channels > 255 then
+    Log.LogStatus('Error: CodecCtx^.channels > 255', 'TFFmpegDecodeStream.Open');
+  fFormatInfo := TAudioFormatInfo.Create(
+    byte(fCodecCtx^.channels),
+    fCodecCtx^.sample_rate,
+    SampleFormat
+  );
+
+  fPacketQueue := TPacketQueue.Create();
+
+  // finally start the decode thread
+  fParseThread := SDL_CreateThread(@ParseThreadMain, Self);
+
+  Result := true;
+end;
+
+procedure TFFmpegDecodeStream.Close();
+var
+  ThreadResult: integer;
+begin
+  // wake threads waiting for packet-queue data
+  // Note: normally, there are no waiting threads. If there were waiting
+  // ones, they would block the audio-callback thread.
+  if (assigned(fPacketQueue)) then
+    fPacketQueue.Abort();
+
+  // send quit request (to parse-thread etc)
+  SDL_mutexP(fStateLock);
+  fQuitRequest := true;
+  SDL_CondBroadcast(fParserIdleCond);
+  SDL_mutexV(fStateLock);
+
+  // abort parse-thread
+  if (fParseThread <> nil) then
+  begin
+    // and wait until it terminates
+    SDL_WaitThread(fParseThread, ThreadResult);
+    fParseThread := nil;
+  end;
+
+  // Close the codec
+  if (fCodecCtx <> nil) then
+  begin
+    // avcodec_close() is not thread-safe
+    FFmpegCore.LockAVCodec();
+    try
+      avcodec_close(fCodecCtx);
+    finally
+      FFmpegCore.UnlockAVCodec();
+    end;
+    fCodecCtx := nil;
+  end;
+
+  // Close the video file
+  if (fFormatCtx <> nil) then
+  begin
+    av_close_input_file(fFormatCtx);
+    fFormatCtx := nil;
+  end;
+
+  PerformOnClose();
+  
+  FreeAndNil(fPacketQueue);
+  FreeAndNil(fFormatInfo);
+end;
+
+function TFFmpegDecodeStream.GetLength(): real;
+begin
+  // do not forget to consider the start_time value here
+  // there is a type size mismatch warnign because start_time and duration are cint64.
+  // So, in principle there could be an overflow when doing the sum.
+  Result := (fFormatCtx^.start_time + fFormatCtx^.duration) / AV_TIME_BASE;
+end;
+
+function TFFmpegDecodeStream.GetAudioFormatInfo(): TAudioFormatInfo;
+begin
+  Result := fFormatInfo;
+end;
+
+function TFFmpegDecodeStream.IsEOF(): boolean;
+begin
+  SDL_mutexP(fStateLock);
+  Result := fEOFState;
+  SDL_mutexV(fStateLock);
+end;
+
+procedure TFFmpegDecodeStream.SetEOF(State: boolean);
+begin
+  SDL_mutexP(fStateLock);
+  fEOFState := State;
+  SDL_mutexV(fStateLock);
+end;
+
+function TFFmpegDecodeStream.IsError(): boolean;
+begin
+  SDL_mutexP(fStateLock);
+  Result := fErrorState;
+  SDL_mutexV(fStateLock);
+end;
+
+procedure TFFmpegDecodeStream.SetError(State: boolean);
+begin
+  SDL_mutexP(fStateLock);
+  fErrorState := State;
+  SDL_mutexV(fStateLock);
+end;
+
+function TFFmpegDecodeStream.IsSeeking(): boolean;
+begin
+  SDL_mutexP(fStateLock);
+  Result := fSeekRequest;
+  SDL_mutexV(fStateLock);
+end;
+
+function TFFmpegDecodeStream.IsQuit(): boolean;
+begin
+  SDL_mutexP(fStateLock);
+  Result := fQuitRequest;
+  SDL_mutexV(fStateLock);
+end;
+
+function TFFmpegDecodeStream.GetPosition(): real;
+var
+  BufferSizeSec: double;
+begin
+  PauseDecoder();
+
+  // ReadData() does not return all of the buffer retrieved by DecodeFrame().
+  // Determine the size of the unused part of the decode-buffer.
+  BufferSizeSec := (fAudioBufferSize - fAudioBufferPos) /
+                   fFormatInfo.BytesPerSec;
+
+  // subtract the size of unused buffer-data from the audio clock.
+  Result := fAudioStreamPos - BufferSizeSec;
+
+  ResumeDecoder();
+end;
+
+procedure TFFmpegDecodeStream.SetPosition(Time: real);
+begin
+  SetPositionIntern(Time, true, true);
+end;
+
+function TFFmpegDecodeStream.GetLoop(): boolean;
+begin
+  SDL_mutexP(fStateLock);
+  Result := fLoop;
+  SDL_mutexV(fStateLock);
+end;
+
+procedure TFFmpegDecodeStream.SetLoop(Enabled: boolean);
+begin
+  SDL_mutexP(fStateLock);
+  fLoop := Enabled;
+  SDL_mutexV(fStateLock);
+end;
+
+
+(********************************************
+ * Parser section
+ ********************************************)
+
+procedure TFFmpegDecodeStream.PauseParser();
+begin
+  if (SDL_ThreadID() = fParseThread.threadid) then
+    Exit;
+    
+  SDL_mutexP(fStateLock);
+  Inc(fParserPauseRequestCount);
+  while (fParserLocked) do
+    SDL_CondWait(fParserUnlockedCond, fStateLock);
+  SDL_mutexV(fStateLock);
+end;
+
+procedure TFFmpegDecodeStream.ResumeParser();
+begin
+  if (SDL_ThreadID() = fParseThread.threadid) then
+    Exit;
+
+  SDL_mutexP(fStateLock);
+  Dec(fParserPauseRequestCount);
+  SDL_CondSignal(fParserResumeCond);
+  SDL_mutexV(fStateLock);
+end;
+
+procedure TFFmpegDecodeStream.SetPositionIntern(Time: real; Flush: boolean; Blocking: boolean);
+begin
+  // - Pause the parser first to prevent it from putting obsolete packages
+  //   into the queue after the queue was flushed and before seeking is done.
+  //   Otherwise we will hear fragments of old data, if the stream was seeked
+  //   in stopped mode and resumed afterwards (applies to non-blocking mode only).
+  // - Pause the decoder to avoid race-condition that might occur otherwise.
+  // - Last lock the state lock because we are manipulating some shared state-vars.
+  PauseParser();
+  PauseDecoder();
+  SDL_mutexP(fStateLock);
+  try
+    fEOFState := false;
+    fErrorState := false;
+
+    // do not seek if we are already at the correct position.
+    // This is important especially for seeking to position 0 if we already are
+    // at the beginning. Although seeking with AVSEEK_FLAG_BACKWARD for pos 0 works,
+    // it is still a bit choppy (although much better than w/o AVSEEK_FLAG_BACKWARD).
+    if (Time = fAudioStreamPos) then
+      Exit;    
+
+    // configure seek parameters
+    fSeekPos := Time;
+    fSeekFlush := Flush;
+    fSeekFlags := AVSEEK_FLAG_ANY;
+    fSeekRequest := true;
+
+    // Note: the BACKWARD-flag seeks to the first position <= the position
+    // searched for. Otherwise e.g. position 0 might not be seeked correct.
+    // For some reason ffmpeg sometimes doesn't use position 0 but the key-frame
+    // following. In streams with few key-frames (like many flv-files) the next
+    // key-frame after 0 might be 5secs ahead.
+    if (Time <= fAudioStreamPos) then
+      fSeekFlags := fSeekFlags or AVSEEK_FLAG_BACKWARD;
+
+    // send a reuse signal in case the parser was stopped (e.g. because of an EOF)
+    SDL_CondSignal(fParserIdleCond);
+  finally
+    SDL_mutexV(fStateLock);
+    ResumeDecoder();
+    ResumeParser();
+  end;
+
+  // in blocking mode, wait until seeking is done
+  if (Blocking) then
+  begin
+    SDL_mutexP(fStateLock);
+    while (fSeekRequest) do
+      SDL_CondWait(SeekFinishedCond, fStateLock);
+    SDL_mutexV(fStateLock);
+  end;
+end;
+
+function ParseThreadMain(Data: Pointer): integer; cdecl;
+var
+  Stream: TFFmpegDecodeStream;
+begin
+  Stream := TFFmpegDecodeStream(Data);
+  if (Stream <> nil) then
+    Stream.Parse();
+  Result := 0;
+end;
+
+procedure TFFmpegDecodeStream.Parse();
+begin
+  // reuse thread as long as the stream is not terminated
+  while (ParseLoop()) do
+  begin
+    // wait for reuse or destruction of stream
+    SDL_mutexP(fStateLock);
+    while (not (fSeekRequest or fQuitRequest)) do
+      SDL_CondWait(fParserIdleCond, fStateLock);
+    SDL_mutexV(fStateLock);
+  end;
+end;
+
+(**
+ * Parser main loop.
+ * Will not return until parsing of the stream is finished.
+ * Reasons for the parser to return are:
+ * - the end-of-file is reached
+ * - an error occured
+ * - the stream was quited (received a quit-request)
+ * Returns true if the stream can be resumed or false if the stream has to
+ * be terminated.
+ *)
+function TFFmpegDecodeStream.ParseLoop(): boolean;
+var
+  Packet: TAVPacket;
+  SeekTarget: int64;
+  ByteIOCtx: PByteIOContext;
+  ErrorCode: integer;
+  StartSilence: double;       // duration of silence at start of stream
+  StartSilencePtr: PDouble;  // pointer for the EMPTY status packet 
+
+  // Note: pthreads wakes threads waiting on a mutex in the order of their
+  // priority and not in FIFO order. SDL does not provide any option to
+  // control priorities. This might (and already did) starve threads waiting
+  // on the mutex (e.g. SetPosition) making usdx look like it was froozen.
+  // Instead of simply locking the critical section we set a ParserLocked flag
+  // instead and give priority to the threads requesting the parser to pause.
+  procedure LockParser();
+  begin
+    SDL_mutexP(fStateLock);
+    while (fParserPauseRequestCount > 0) do
+      SDL_CondWait(fParserResumeCond, fStateLock);
+    fParserLocked := true;
+    SDL_mutexV(fStateLock);
+  end;
+
+  procedure UnlockParser();
+  begin
+    SDL_mutexP(fStateLock);
+    fParserLocked := false;
+    SDL_CondBroadcast(fParserUnlockedCond);
+    SDL_mutexV(fStateLock);
+  end;
+
+begin
+  Result := true;
+
+  while (true) do
+  begin
+    LockParser();
+    try
+
+      if (IsQuit()) then
+      begin
+        Result := false;
+        Exit;
+      end;
+
+      // handle seek-request (Note: no need to lock SeekRequest here)
+      if (fSeekRequest) then
+      begin
+        // first try: seek on the audio stream
+        SeekTarget := Round(fSeekPos / av_q2d(fAudioStream^.time_base));
+        StartSilence := 0;
+        if (SeekTarget < fAudioStream^.start_time) then
+          StartSilence := (fAudioStream^.start_time - SeekTarget) * av_q2d(fAudioStream^.time_base);
+        ErrorCode := av_seek_frame(fFormatCtx, fAudioStreamIndex, SeekTarget, fSeekFlags);
+
+        if (ErrorCode < 0) then
+        begin
+          // second try: seek on the default stream (necessary for flv-videos and some ogg-files)
+          SeekTarget := Round(fSeekPos * AV_TIME_BASE);
+          StartSilence := 0;
+          if (SeekTarget < fFormatCtx^.start_time) then
+            StartSilence := (fFormatCtx^.start_time - SeekTarget) / AV_TIME_BASE;
+          ErrorCode := av_seek_frame(fFormatCtx, -1, SeekTarget, fSeekFlags);
+        end;
+
+        // pause decoder and lock state (keep the lock-order to avoid deadlocks).
+        // Note that the decoder does not block in the packet-queue in seeking state,
+        // so locking the decoder here does not cause a dead-lock.
+        PauseDecoder();
+        SDL_mutexP(fStateLock);
+        try
+          if (ErrorCode < 0) then
+          begin
+            // seeking failed
+            fErrorState := true;
+            Log.LogError('Seek Error in "'+fFormatCtx^.filename+'"', 'UAudioDecoder_FFmpeg');
+          end
+          else
+          begin
+            if (fSeekFlush) then
+            begin
+              // flush queue (we will send a Flush-Packet when seeking is finished)
+              fPacketQueue.Flush();
+
+              // flush the decode buffers
+              fAudioBufferSize := 0;
+              fAudioBufferPos := 0;
+              fAudioPaketSize := 0;
+              fAudioPaketSilence := 0;
+              FlushCodecBuffers();
+              
+              // Set preliminary stream position. The position will be set to
+              // the correct value as soon as the first packet is decoded.
+              fAudioStreamPos := fSeekPos;
+            end
+            else
+            begin
+              // request avcodec buffer flush
+              fPacketQueue.PutStatus(PKT_STATUS_FLAG_FLUSH, nil);
+            end;
+
+            // fill the gap between position 0 and start_time with silence
+            // but not if we are in loop mode
+            if ((StartSilence > 0) and (not fLoop)) then
+            begin
+              GetMem(StartSilencePtr, SizeOf(StartSilence));
+              StartSilencePtr^ := StartSilence;
+              fPacketQueue.PutStatus(PKT_STATUS_FLAG_EMPTY, StartSilencePtr);
+            end;
+          end;
+
+          fSeekRequest := false;
+          SDL_CondBroadcast(SeekFinishedCond);
+        finally
+          SDL_mutexV(fStateLock);
+          ResumeDecoder();
+        end;
+      end;
+
+      if (fPacketQueue.GetSize() > MAX_AUDIOQ_SIZE) then
+      begin
+        SDL_Delay(10);
+        Continue;
+      end;
+
+      if (av_read_frame(fFormatCtx, Packet) < 0) then
+      begin
+        // failed to read a frame, check reason
+        {$IF (LIBAVFORMAT_VERSION_MAJOR >= 52)}
+        ByteIOCtx := fFormatCtx^.pb;
+        {$ELSE}
+        ByteIOCtx := @fFormatCtx^.pb;
+        {$IFEND}
+
+        // check for end-of-file (eof is not an error)
+        if (url_feof(ByteIOCtx) <> 0) then
+        begin
+          if (GetLoop()) then
+          begin
+            // rewind stream (but do not flush)
+            SetPositionIntern(0, false, false);
+            Continue;
+          end
+          else
+          begin
+            // signal end-of-file
+            fPacketQueue.PutStatus(PKT_STATUS_FLAG_EOF, nil);
+            Exit;
+          end;
+        end;
+
+        // check for errors
+        if (url_ferror(ByteIOCtx) <> 0) then
+        begin
+          // an error occured -> abort and wait for repositioning or termination
+          fPacketQueue.PutStatus(PKT_STATUS_FLAG_ERROR, nil);
+          Exit;
+        end;
+
+        // url_feof() does not detect an EOF for some files
+        // so we have to do it this way.
+        if ((fFormatCtx^.file_size <> 0) and
+            (ByteIOCtx^.pos >= fFormatCtx^.file_size)) then
+        begin
+          fPacketQueue.PutStatus(PKT_STATUS_FLAG_EOF, nil);
+          Exit;
+        end;
+
+        // unknown error occured, exit
+        fPacketQueue.PutStatus(PKT_STATUS_FLAG_ERROR, nil);
+        Exit;
+      end;
+
+      if (Packet.stream_index = fAudioStreamIndex) then
+        fPacketQueue.Put(@Packet)
+      else
+        av_free_packet(@Packet);
+
+    finally
+      UnlockParser();
+    end;
+  end;
+end;
+
+
+(********************************************
+ * Decoder section
+ ********************************************)
+
+procedure TFFmpegDecodeStream.PauseDecoder();
+begin
+  SDL_mutexP(fStateLock);
+  Inc(fDecoderPauseRequestCount);
+  while (fDecoderLocked) do
+    SDL_CondWait(fDecoderUnlockedCond, fStateLock);
+  SDL_mutexV(fStateLock);
+end;
+
+procedure TFFmpegDecodeStream.ResumeDecoder();
+begin
+  SDL_mutexP(fStateLock);
+  Dec(fDecoderPauseRequestCount);
+  SDL_CondSignal(fDecoderResumeCond);
+  SDL_mutexV(fStateLock);
+end;
+
+procedure TFFmpegDecodeStream.FlushCodecBuffers();
+begin
+  // if no flush operation is specified, avcodec_flush_buffers will not do anything.
+  if (@fCodecCtx.codec.flush <> nil) then
+  begin
+    // flush buffers used by avcodec_decode_audio, etc.
+    avcodec_flush_buffers(fCodecCtx);
+  end
+  else
+  begin
+    // we need a Workaround to avoid plopping noise with ogg-vorbis and
+    // mp3 (in older versions of FFmpeg).
+    // We will just reopen the codec.
+    FFmpegCore.LockAVCodec();
+    try
+      avcodec_close(fCodecCtx);
+      avcodec_open(fCodecCtx, fCodec);
+    finally
+      FFmpegCore.UnlockAVCodec();
+    end;
+  end;
+end;
+
+function TFFmpegDecodeStream.DecodeFrame(Buffer: PByteArray; BufferSize: integer): integer;
+var
+  PaketDecodedSize: integer; // size of packet data used for decoding
+  DataSize: integer;         // size of output data decoded by FFmpeg
+  BlockQueue: boolean;
+  SilenceDuration: double;
+  {$IFDEF DebugFFmpegDecode}
+  TmpPos: double;
+  {$ENDIF}
+begin
+  Result := -1;
+
+  if (EOF) then
+    Exit;
+
+  while(true) do
+  begin
+    // for titles with start_time > 0 we have to generate silence
+    // until we reach the pts of the first data packet.
+    if (fAudioPaketSilence > 0) then
+    begin
+      DataSize := Min(fAudioPaketSilence, BufferSize);
+      FillChar(Buffer[0], DataSize, 0);
+      Dec(fAudioPaketSilence, DataSize);
+      fAudioStreamPos := fAudioStreamPos + DataSize / fFormatInfo.BytesPerSec;
+      Result := DataSize;
+      Exit;
+    end;
+
+    // read packet data
+    while (fAudioPaketSize > 0) do
+    begin
+      DataSize := BufferSize;
+
+      {$IF LIBAVCODEC_VERSION >= 51030000} // 51.30.0
+      PaketDecodedSize := avcodec_decode_audio2(fCodecCtx, PSmallint(Buffer),
+                  DataSize, fAudioPaketData, fAudioPaketSize);
+      {$ELSE}
+      PaketDecodedSize := avcodec_decode_audio(fCodecCtx, PSmallint(Buffer),
+                  DataSize, fAudioPaketData, fAudioPaketSize);
+      {$IFEND}
+
+      if(PaketDecodedSize < 0) then
+      begin
+        // if error, skip frame
+        {$IFDEF DebugFFmpegDecode}
+        DebugWriteln('Skip audio frame');
+        {$ENDIF}
+        fAudioPaketSize := 0;
+        Break;
+      end;
+
+      Inc(PByte(fAudioPaketData), PaketDecodedSize);
+      Dec(fAudioPaketSize, PaketDecodedSize);
+
+      // check if avcodec_decode_audio returned data, otherwise fetch more frames
+      if (DataSize <= 0) then
+        Continue;
+
+      // update stream position by the amount of fetched data
+      fAudioStreamPos := fAudioStreamPos + DataSize / fFormatInfo.BytesPerSec;
+      
+      // we have data, return it and come back for more later
+      Result := DataSize;
+      Exit;
+    end;
+
+    // free old packet data
+    if (fAudioPaket.data <> nil) then
+      av_free_packet(@fAudioPaket);
+
+    // do not block queue on seeking (to avoid deadlocks on the DecoderLock)
+    if (IsSeeking()) then
+      BlockQueue := false
+    else
+      BlockQueue := true;
+
+    // request a new packet and block if none available.
+    // If this fails, the queue was aborted.
+    if (fPacketQueue.Get(fAudioPaket, BlockQueue) <= 0) then
+      Exit;
+
+    // handle Status-packet
+    if (PAnsiChar(fAudioPaket.data) = STATUS_PACKET) then
+    begin
+      fAudioPaket.data := nil;
+      fAudioPaketData := nil;
+      fAudioPaketSize := 0;
+
+      case (fAudioPaket.flags) of
+        PKT_STATUS_FLAG_FLUSH:
+        begin
+          // just used if SetPositionIntern was called without the flush flag.
+          FlushCodecBuffers;
+        end;
+        PKT_STATUS_FLAG_EOF: // end-of-file
+        begin
+          // ignore EOF while seeking
+          if (not IsSeeking()) then
+            SetEOF(true);
+          // buffer contains no data -> result = -1
+          Exit;
+        end;
+        PKT_STATUS_FLAG_ERROR:
+        begin
+          SetError(true);
+          Log.LogStatus('I/O Error', 'TFFmpegDecodeStream.DecodeFrame');
+          Exit;
+        end;
+        PKT_STATUS_FLAG_EMPTY:
+        begin
+          SilenceDuration := PDouble(fPacketQueue.GetStatusInfo(fAudioPaket))^;
+          fAudioPaketSilence := Round(SilenceDuration * fFormatInfo.SampleRate) * fFormatInfo.FrameSize;
+          fPacketQueue.FreeStatusInfo(fAudioPaket);
+        end
+        else
+        begin
+          Log.LogStatus('Unknown status', 'TFFmpegDecodeStream.DecodeFrame');
+        end;
+      end;
+
+      Continue;
+    end;
+
+    fAudioPaketData := fAudioPaket.data;
+    fAudioPaketSize := fAudioPaket.size;
+
+    // if available, update the stream position to the presentation time of this package
+    if(fAudioPaket.pts <> AV_NOPTS_VALUE) then
+    begin
+      {$IFDEF DebugFFmpegDecode}
+      TmpPos := fAudioStreamPos;
+      {$ENDIF}
+      fAudioStreamPos := av_q2d(fAudioStream^.time_base) * fAudioPaket.pts;
+      {$IFDEF DebugFFmpegDecode}
+      DebugWriteln('Timestamp: ' + floattostrf(fAudioStreamPos, ffFixed, 15, 3) + ' ' +
+                   '(Calc: ' + floattostrf(TmpPos, ffFixed, 15, 3) + '), ' +
+                   'Diff: ' + floattostrf(fAudioStreamPos-TmpPos, ffFixed, 15, 3));
+      {$ENDIF}
+    end;
+  end;
+end;
+
+function TFFmpegDecodeStream.ReadData(Buffer: PByteArray; BufferSize: integer): integer;
+var
+  CopyByteCount:   integer; // number of bytes to copy
+  RemainByteCount: integer; // number of bytes left (remain) to read
+  BufferPos: integer;
+
+  // prioritize pause requests
+  procedure LockDecoder();
+  begin
+    SDL_mutexP(fStateLock);
+    while (fDecoderPauseRequestCount > 0) do
+      SDL_CondWait(fDecoderResumeCond, fStateLock);
+    fDecoderLocked := true;
+    SDL_mutexV(fStateLock);
+  end;
+
+  procedure UnlockDecoder();
+  begin
+    SDL_mutexP(fStateLock);
+    fDecoderLocked := false;
+    SDL_CondBroadcast(fDecoderUnlockedCond);
+    SDL_mutexV(fStateLock);
+  end;
+
+begin
+  Result := -1;
+
+  // set number of bytes to copy to the output buffer
+  BufferPos := 0;
+
+  LockDecoder();
+  try
+    // leave if end-of-file is reached
+    if (EOF) then
+      Exit;
+
+    // copy data to output buffer
+    while (BufferPos < BufferSize) do
+    begin
+      // check if we need more data
+      if (fAudioBufferPos >= fAudioBufferSize) then
+      begin
+        fAudioBufferPos := 0;
+
+        // we have already sent all our data; get more
+        fAudioBufferSize := DecodeFrame(fAudioBuffer, AUDIO_BUFFER_SIZE);
+
+        // check for errors or EOF
+        if(fAudioBufferSize < 0) then
+        begin
+          Result := BufferPos;
+          Exit;
+        end;
+      end;
+
+      // calc number of new bytes in the decode-buffer
+      CopyByteCount := fAudioBufferSize - fAudioBufferPos;
+      // resize copy-count if more bytes available than needed (remaining bytes are used the next time)
+      RemainByteCount := BufferSize - BufferPos;
+      if (CopyByteCount > RemainByteCount) then
+        CopyByteCount := RemainByteCount;
+
+      Move(fAudioBuffer[fAudioBufferPos], Buffer[BufferPos], CopyByteCount);
+
+      Inc(BufferPos,      CopyByteCount);
+      Inc(fAudioBufferPos, CopyByteCount);
+    end;
+  finally
+    UnlockDecoder();
+  end;
+
+  Result := BufferSize;
+end;
+
+
+{ TAudioDecoder_FFmpeg }
+
+function TAudioDecoder_FFmpeg.GetName: String;
+begin
+  Result := 'FFmpeg_Decoder';
+end;
+
+function TAudioDecoder_FFmpeg.InitializeDecoder: boolean;
+begin
+  //Log.LogStatus('InitializeDecoder', 'UAudioDecoder_FFmpeg');
+  FFmpegCore := TMediaCore_FFmpeg.GetInstance();
+  av_register_all();
+
+  // Do not show uninformative error messages by default.
+  // FFmpeg prints all error-infos on the console by default what
+  // is very confusing as the playback of the files is correct.
+  // We consider these errors to be internal to FFMpeg. They can be fixed
+  // by the FFmpeg guys only and do not provide any useful information in
+  // respect to USDX.
+  {$IFNDEF EnableFFmpegErrorOutput}
+    {$IF LIBAVUTIL_VERSION_MAJOR >= 50}
+    av_log_set_level(AV_LOG_FATAL);
+    {$ELSE}
+    // FATAL and ERROR share one log-level, so we have to use QUIET
+    av_log_set_level(AV_LOG_QUIET);
+    {$IFEND}
+  {$ENDIF}
+
+  Result := true;
+end;
+
+function TAudioDecoder_FFmpeg.FinalizeDecoder(): boolean;
+begin
+  Result := true;
+end;
+
+function TAudioDecoder_FFmpeg.Open(const Filename: IPath): TAudioDecodeStream;
+var
+  Stream: TFFmpegDecodeStream;
+begin
+  Result := nil;
+
+  Stream := TFFmpegDecodeStream.Create();
+  if (not Stream.Open(Filename)) then
+  begin
+    Stream.Free;
+    Exit;
+  end;
+
+  Result := Stream;
+end;
+
+
+initialization
+  MediaManager.Add(TAudioDecoder_FFmpeg.Create);
+
+end.
diff --git a/songmanagement/src/media/UAudioInput_Bass.pas b/songmanagement/src/media/UAudioInput_Bass.pas
new file mode 100644
index 00000000..0e79b343
--- /dev/null
+++ b/songmanagement/src/media/UAudioInput_Bass.pas
@@ -0,0 +1,519 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioInput_Bass;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  SysUtils,
+  URecord,
+  UMusic;
+
+implementation
+
+uses
+  UMain,
+  UIni,
+  ULog,
+  UAudioCore_Bass,
+  UTextEncoding,
+  UCommon,    // (Note: for MakeLong on non-windows platforms)
+  {$IFDEF MSWINDOWS}
+  Windows,    // (Note: for MakeLong)
+  {$ENDIF}
+  bass;       // (Note: DWORD is redefined here -> insert after Windows-unit)
+
+type
+  TAudioInput_Bass = class(TAudioInputBase)
+    private
+      function EnumDevices(): boolean;
+    public
+      function GetName: String; override;
+      function InitializeRecord: boolean; override;
+      function FinalizeRecord: boolean; override;
+  end;
+
+  TBassInputDevice = class(TAudioInputDevice)
+    private
+      RecordStream: HSTREAM;
+      BassDeviceID: DWORD; // DeviceID used by BASS
+      SingleIn: boolean;
+
+      function SetInputSource(SourceIndex: integer): boolean;
+      function GetInputSource(): integer;
+    public
+      function Open(): boolean;
+      function Close(): boolean;
+      function Start(): boolean; override;
+      function Stop(): boolean;  override;
+
+      function GetVolume(): single;        override;
+      procedure SetVolume(Volume: single); override;
+  end;
+
+var
+  BassCore: TAudioCore_Bass;
+
+
+{ Global }
+
+{*
+ * Bass input capture callback.
+ * Params:
+ *   stream - BASS input stream
+ *   buffer - buffer of captured samples
+ *   len - size of buffer in bytes
+ *   user - players associated with left/right channels
+ *}
+function MicrophoneCallback(stream: HSTREAM; buffer: Pointer;
+    len: integer; inputDevice: Pointer): boolean; {$IFDEF MSWINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+begin
+  AudioInputProcessor.HandleMicrophoneData(buffer, len, inputDevice);
+  Result := true;
+end;
+
+
+{ TBassInputDevice }
+
+function TBassInputDevice.GetInputSource(): integer;
+var
+  SourceCnt: integer;
+  i: integer;
+  flags: DWORD;
+begin
+  // get input-source config (subtract virtual device to get BASS indices)
+  SourceCnt := Length(Source)-1;
+
+  // find source
+  Result := -1;
+  for i := 0 to SourceCnt-1 do
+  begin
+    // get input settings
+    flags := BASS_RecordGetInput(i, PSingle(nil)^);
+    if (flags = DWORD(-1)) then
+    begin
+      Log.LogError('BASS_RecordGetInput: ' + BassCore.ErrorGetString(), 'TBassInputDevice.GetInputSource');
+      Exit;
+    end;
+
+    // check if current source is selected
+    if ((flags and BASS_INPUT_OFF) = 0) then
+    begin
+      // selected source found
+      Result := i;
+      Exit;
+    end;
+  end;
+end;
+
+function TBassInputDevice.SetInputSource(SourceIndex: integer): boolean;
+var
+  SourceCnt: integer;
+  i: integer;
+  flags: DWORD;
+begin
+  Result := false;
+
+  // check for invalid source index
+  if (SourceIndex < 0) then
+    Exit;
+
+  // get input-source config (subtract virtual device to get BASS indices)
+  SourceCnt := Length(Source)-1;
+
+  // turn on selected source (turns off the others for single-in devices)
+  if (not BASS_RecordSetInput(SourceIndex, BASS_INPUT_ON, -1)) then
+  begin
+    Log.LogError('BASS_RecordSetInput: ' + BassCore.ErrorGetString(), 'TBassInputDevice.Start');
+    Exit;
+  end;
+
+  // turn off all other sources (not needed for single-in devices)
+  if (not SingleIn) then
+  begin
+    for i := 0 to SourceCnt-1 do
+    begin
+      if (i = SourceIndex) then
+        continue;
+      // get input settings
+      flags := BASS_RecordGetInput(i, PSingle(nil)^);
+      if (flags = DWORD(-1)) then
+      begin
+        Log.LogError('BASS_RecordGetInput: ' + BassCore.ErrorGetString(), 'TBassInputDevice.GetInputSource');
+        Exit;
+      end;
+      // deselect source if selected
+      if ((flags and BASS_INPUT_OFF) = 0) then
+        BASS_RecordSetInput(i, BASS_INPUT_OFF, -1);
+    end;
+  end;
+
+  Result := true;
+end;
+
+function TBassInputDevice.Open(): boolean;
+var
+  FormatFlags: DWORD;
+  SourceIndex: integer;
+const
+  latency = 20; // 20ms callback period (= latency)
+begin
+  Result := false;
+
+  if (not BASS_RecordInit(BassDeviceID)) then
+  begin
+    Log.LogError('BASS_RecordInit['+Name+']: ' +
+                 BassCore.ErrorGetString(), 'TBassInputDevice.Open');
+    Exit;
+  end;
+
+  if (not BassCore.ConvertAudioFormatToBASSFlags(AudioFormat.Format, FormatFlags)) then
+  begin
+    Log.LogError('Unhandled sample-format', 'TBassInputDevice.Open');
+    Exit;
+  end;
+
+  // start capturing in paused state
+  RecordStream := BASS_RecordStart(Round(AudioFormat.SampleRate), AudioFormat.Channels,
+                    MakeLong(FormatFlags or BASS_RECORD_PAUSE, latency),
+                    @MicrophoneCallback, Self);
+  if (RecordStream = 0) then
+  begin
+    Log.LogError('BASS_RecordStart: ' + BassCore.ErrorGetString(), 'TBassInputDevice.Open');
+    BASS_RecordFree;
+    Exit;
+  end;
+
+  // save current source selection and select new source
+  SourceIndex := Ini.InputDeviceConfig[CfgIndex].Input-1;
+  if (SourceIndex = -1) then
+  begin
+    // nothing to do if default source is used
+    SourceRestore := -1;
+  end
+  else
+  begin
+    // store current source-index and select new source
+    SourceRestore := GetInputSource();
+    SetInputSource(SourceIndex);
+  end;
+
+  Result := true;
+end;
+
+{* Start input-capturing on this device. *}
+function TBassInputDevice.Start(): boolean;
+begin
+  Result := false;
+
+  // recording already started -> stop first
+  if (RecordStream <> 0) then
+    Stop();
+
+  // TODO: Do not open the device here (takes too much time).
+  if not Open() then
+    Exit;
+
+  if (not BASS_ChannelPlay(RecordStream, true)) then
+  begin
+    Log.LogError('BASS_ChannelPlay: ' + BassCore.ErrorGetString(), 'TBassInputDevice.Start');
+    Exit;
+  end;
+
+  Result := true;
+end;
+
+{* Stop input-capturing on this device. *}
+function TBassInputDevice.Stop(): boolean;
+begin
+  Result := false;
+
+  if (RecordStream = 0) then
+    Exit;
+  if (not BASS_RecordSetDevice(BassDeviceID)) then
+    Exit;
+
+  if (not BASS_ChannelStop(RecordStream)) then
+  begin
+    Log.LogError('BASS_ChannelStop: ' + BassCore.ErrorGetString(), 'TBassInputDevice.Stop');
+  end;
+
+  // TODO: Do not close the device here (takes too much time).
+  Result := Close();
+end;
+
+function TBassInputDevice.Close(): boolean;
+begin
+  // restore source selection
+  if (SourceRestore >= 0) then
+  begin
+    SetInputSource(SourceRestore);
+  end;
+
+  // free data
+  if (not BASS_RecordFree()) then
+  begin
+    Log.LogError('BASS_RecordFree: ' + BassCore.ErrorGetString(), 'TBassInputDevice.Close');
+    Result := false;
+  end
+  else
+  begin
+    Result := true;
+  end;
+
+  RecordStream := 0;
+end;
+
+function TBassInputDevice.GetVolume(): single;
+var
+  SourceIndex: integer;
+  lVolume: Single;
+begin
+  Result := 0;
+
+  SourceIndex := Ini.InputDeviceConfig[CfgIndex].Input-1;
+  if (SourceIndex = -1) then
+  begin
+    // if default source used find selected source
+    SourceIndex := GetInputSource();
+    if (SourceIndex = -1) then
+      Exit;
+  end;
+
+  if (BASS_RecordGetInput(SourceIndex, lVolume) = DWORD(-1)) then
+  begin
+    Log.LogError('BASS_RecordGetInput: ' + BassCore.ErrorGetString() , 'TBassInputDevice.GetVolume');
+    Exit;
+  end;
+  Result := lVolume;
+end;
+
+procedure TBassInputDevice.SetVolume(Volume: single);
+var
+  SourceIndex: integer;
+begin
+  SourceIndex := Ini.InputDeviceConfig[CfgIndex].Input-1;
+  if (SourceIndex = -1) then
+  begin
+    // if default source used find selected source
+    SourceIndex := GetInputSource();
+    if (SourceIndex = -1) then
+      Exit;
+  end;
+
+  // clip volume to valid range
+  if (Volume > 1.0) then
+    Volume := 1.0
+  else if (Volume < 0) then
+    Volume := 0;
+
+  if (not BASS_RecordSetInput(SourceIndex, 0, Volume)) then
+  begin
+    Log.LogError('BASS_RecordSetInput: ' + BassCore.ErrorGetString() , 'TBassInputDevice.SetVolume');
+  end;
+end;
+
+
+{ TAudioInput_Bass }
+
+function  TAudioInput_Bass.GetName: String;
+begin
+  result := 'BASS_Input';
+end;
+
+function TAudioInput_Bass.EnumDevices(): boolean;
+var
+  Descr:      UTF8String;
+  SourceName: PChar;
+  Flags:      integer;
+  BassDeviceID: integer;
+  BassDevice:   TBassInputDevice;
+  DeviceIndex:  integer;
+  DeviceInfo: BASS_DEVICEINFO;
+  SourceIndex:  integer;
+  RecordInfo: BASS_RECORDINFO;
+  SelectedSourceIndex: integer;
+begin
+  result := false;
+
+  DeviceIndex := 0;
+  BassDeviceID := 0;
+  SetLength(AudioInputProcessor.DeviceList, 0);
+
+  // checks for recording devices and puts them into an array
+  while true do
+  begin
+    if (not BASS_RecordGetDeviceInfo(BassDeviceID, DeviceInfo)) then
+      break;
+
+    // try to initialize the device
+    if not BASS_RecordInit(BassDeviceID) then
+    begin
+      Log.LogStatus('Failed to initialize BASS Capture-Device['+inttostr(BassDeviceID)+']',
+                    'TAudioInput_Bass.InitializeRecord');
+    end
+    else
+    begin
+      SetLength(AudioInputProcessor.DeviceList, DeviceIndex+1);
+
+      // TODO: free object on termination
+      BassDevice := TBassInputDevice.Create();
+      AudioInputProcessor.DeviceList[DeviceIndex] := BassDevice;
+
+      BassDevice.BassDeviceID := BassDeviceID;
+
+      // BASS device names seem to be encoded with local encoding
+      // TODO: works for windows, check Linux + Mac OS X
+      Descr := DecodeStringUTF8(DeviceInfo.name, encLocale);
+
+      BassDevice.Name := UnifyDeviceName(Descr, DeviceIndex);
+
+      // zero info-struct as some fields might not be set (e.g. freq is just set on Vista and MacOSX)
+      FillChar(RecordInfo, SizeOf(RecordInfo), 0);
+      // retrieve recording device info
+      BASS_RecordGetInfo(RecordInfo);
+
+      // check if BASS has capture-freq. info
+      if (RecordInfo.freq > 0) then
+      begin
+        // use current input sample rate (available only on Windows Vista and OSX).
+        // Recording at this rate will give the best quality and performance, as no resampling is required.
+        // FIXME: does BASS use LSB/MSB or system integer values for 16bit?
+        BassDevice.AudioFormat := TAudioFormatInfo.Create(2, RecordInfo.freq, asfS16)
+      end
+      else
+      begin
+        // BASS does not provide an explizit input channel count (except BASS_RECORDINFO.formats)
+        // but it doesn't fail if we use stereo input on a mono device
+        // -> use stereo by default
+        BassDevice.AudioFormat := TAudioFormatInfo.Create(2, 44100, asfS16)
+      end;
+
+      // get info if multiple input-sources can be selected at once
+      BassDevice.SingleIn := RecordInfo.singlein;
+
+      // init list for capture buffers per channel
+      SetLength(BassDevice.CaptureChannel, BassDevice.AudioFormat.Channels);
+
+      BassDevice.MicSource := -1;
+      BassDevice.SourceRestore := -1;
+
+      // add a virtual default source (will not change mixer-settings)
+      SetLength(BassDevice.Source, 1);
+      BassDevice.Source[0].Name := DEFAULT_SOURCE_NAME;
+
+      // add real input sources
+      SourceIndex := 1;
+
+      // process each input
+      while true do
+      begin
+        SourceName := BASS_RecordGetInputName(SourceIndex-1);
+
+        {$IFDEF DARWIN}
+        // Under MacOSX the SingStar Mics have an empty InputName.
+        // So, we have to add a hard coded Workaround for this problem
+        // FIXME: - Do we need this anymore? Doesn't the (new) default source already solve this problem?
+        //        - Normally a nil return value of BASS_RecordGetInputName() means end-of-list, so maybe
+        //          BASS is not able to detect any mic-sources (the default source will work then).
+        //        - Does BASS_RecordGetInfo() return true or false? If it returns true in this case
+        //          we could use this value to check if the device exists.
+        //          Please check that, eddie.
+        //          If it returns false, then the source is not detected and it does not make sense to add a second
+        //          fake device here.
+        //          What about BASS_RecordGetInput()? Does it return a value <> -1?
+        //        - Does it even work at all with this fake source-index, now that input switching works?
+        //          This info was not used before (sources were never switched), so it did not matter what source-index was used.
+        //          But now BASS_RecordSetInput() will probably fail.
+        if ((SourceName = nil) and (SourceIndex = 1) and (Pos('USBMIC Serial#', Descr) > 0)) then
+          SourceName := 'Microphone'
+        {$ENDIF}
+        
+        if (SourceName = nil) then
+          break;
+
+        SetLength(BassDevice.Source, Length(BassDevice.Source)+1);
+        // BASS source names seem to be encoded with local encoding
+        // TODO: works for windows, check Linux + Mac OS X
+        BassDevice.Source[SourceIndex].Name := DecodeStringUTF8(SourceName, encLocale);
+
+        // get input-source info
+        Flags := BASS_RecordGetInput(SourceIndex, PSingle(nil)^);
+        if (Flags <> -1) then
+        begin
+          // chech if current source is a mic (and none was set before)
+          if ((Flags and BASS_INPUT_TYPE_MIC) <> 0) and
+             (BassDevice.MicSource = -1) then
+          begin
+            BassDevice.MicSource := SourceIndex;
+          end;
+        end;
+
+        Inc(SourceIndex);
+      end;
+
+      // FIXME: this call hangs in FPC (windows) every 2nd time USDX is called.
+      //   Maybe because the sound-device was not released properly?
+      BASS_RecordFree;
+
+      Inc(DeviceIndex);
+    end;
+
+    Inc(BassDeviceID);
+  end;
+
+  result := true;
+end;
+
+function TAudioInput_Bass.InitializeRecord(): boolean;
+begin
+  BassCore := TAudioCore_Bass.GetInstance();
+  if not BassCore.CheckVersion then
+  begin
+    Result := false;
+    Exit;
+  end;
+  Result := EnumDevices();
+end;
+
+function TAudioInput_Bass.FinalizeRecord(): boolean;
+begin
+  CaptureStop;
+  Result := inherited FinalizeRecord;
+end;
+
+
+initialization
+  MediaManager.Add(TAudioInput_Bass.Create);
+
+end.
diff --git a/songmanagement/src/media/UAudioInput_Portaudio.pas b/songmanagement/src/media/UAudioInput_Portaudio.pas
new file mode 100644
index 00000000..c7364eb4
--- /dev/null
+++ b/songmanagement/src/media/UAudioInput_Portaudio.pas
@@ -0,0 +1,537 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioInput_Portaudio;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I ../switches.inc}
+
+uses
+  Classes,
+  SysUtils,
+  UMusic;
+
+implementation
+
+uses
+  {$IFDEF UsePortmixer}
+  portmixer,
+  {$ENDIF}
+  portaudio,
+  ctypes,
+  UAudioCore_Portaudio,
+  UUnicodeUtils,
+  UTextEncoding,
+  UIni,
+  ULog,
+  UMain,
+  URecord;
+
+type
+  TAudioInput_Portaudio = class(TAudioInputBase)
+    private
+      AudioCore: TAudioCore_Portaudio;
+      function EnumDevices(): boolean;
+    public
+      function GetName: string; override;
+      function InitializeRecord: boolean; override;
+      function FinalizeRecord: boolean; override;
+  end;
+
+  TPortaudioInputDevice = class(TAudioInputDevice)
+    private
+      RecordStream: PPaStream;
+      {$IFDEF UsePortmixer}
+      Mixer: PPxMixer;
+      {$ENDIF}
+      PaDeviceIndex:  TPaDeviceIndex;
+    public
+      function Open():  boolean;
+      function Close(): boolean;
+      function Start(): boolean; override;
+      function Stop():  boolean; override;
+
+      function DetermineInputLatency(Info: PPaDeviceInfo): TPaTime;
+
+      function GetVolume(): single;        override;
+      procedure SetVolume(Volume: single); override;
+  end;
+
+function MicrophoneCallback(input: pointer; output: pointer; frameCount: culong;
+      timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
+      inputDevice: pointer): cint; cdecl; forward;
+
+function MicrophoneTestCallback(input: pointer; output: pointer; frameCount: culong;
+      timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
+      inputDevice: pointer): cint; cdecl; forward;
+
+{**
+ * Converts a string returned by Portaudio into UTF8.
+ * If the string already is in UTF8 no conversion is performed, otherwise
+ * the local encoding is used. 
+ *}
+function ConvertPaStringToUTF8(const Str: RawByteString): UTF8String;
+begin
+  if (IsUTF8String(Str)) then
+    Result := Str
+  else
+    Result := DecodeStringUTF8(Str, encLocale);  
+end;
+
+
+{ TPortaudioInputDevice }
+
+function TPortaudioInputDevice.DetermineInputLatency(Info: PPaDeviceInfo): TPaTime;
+begin
+  if (Ini.InputDeviceConfig[CfgIndex].Latency <> -1) then
+  begin
+    // autodetection off -> set user latency
+    Result := Ini.InputDeviceConfig[CfgIndex].Latency / 1000
+  end
+  else
+  begin
+    // on vista and xp the defaultLowInputLatency may be set to 0 but it works.
+    // TODO: correct too low latencies (what is a too low latency, maybe < 10ms?)
+    // TODO: retry with input-latency set to 20ms (defaultLowInputLatency might
+    //       not be set correctly in OSS)
+
+    // FIXME: according to the portaudio headers defaultHighInputLatency (approx. 40ms) is
+    // for robust non-interactive  applications and defaultLowInputLatency (approx. 15ms)
+    // for interactive performance.
+    // We need defaultLowInputLatency here but this setting is far too buggy. If the callback
+    // does not return quickly the stream will be stuck after returning from the callback
+    // and the callback will not be called anymore and mic-capturing stops.
+    // Audacity (in AudioIO.cpp) uses defaultHighInputLatency if software playthrough is on
+    // and even higher latencies (100ms) without playthrough so this should be ok for now.
+    //Result := Info^.defaultLowInputLatency;
+    Result := Info^.defaultHighInputLatency;
+  end;
+end;
+
+function TPortaudioInputDevice.Open(): boolean;
+var
+  Error:       TPaError;
+  inputParams: TPaStreamParameters;
+  deviceInfo:  PPaDeviceInfo;
+  {$IFDEF UsePortmixer}
+  SourceIndex: integer;
+  {$ENDIF}
+begin
+  Result := false;
+
+  // get input latency info
+  deviceInfo := Pa_GetDeviceInfo(PaDeviceIndex);
+
+  // set input stream parameters
+  with inputParams do
+  begin
+    device := PaDeviceIndex;
+    channelCount := AudioFormat.Channels;
+    sampleFormat := paInt16;
+    suggestedLatency := DetermineInputLatency(deviceInfo);
+    hostApiSpecificStreamInfo := nil;
+  end;
+
+  Log.LogStatus('Open ' + deviceInfo^.name, 'Portaudio');
+  Log.LogStatus('Latency of ' + deviceInfo^.name + ': ' + floatToStr(inputParams.suggestedLatency), 'Portaudio');
+
+  // open input stream
+  Error := Pa_OpenStream(RecordStream, @inputParams, nil,
+      AudioFormat.SampleRate,
+      paFramesPerBufferUnspecified, paNoFlag,
+      @MicrophoneCallback, pointer(Self));
+  if (Error <> paNoError) then
+  begin
+    Log.LogError('Error opening stream: ' + Pa_GetErrorText(Error), 'TPortaudioInputDevice.Open');
+    Exit;
+  end;
+
+  {$IFDEF UsePortmixer}
+    // open default mixer
+    Mixer := Px_OpenMixer(RecordStream, 0);
+    if (Mixer = nil) then
+    begin
+      Log.LogError('Error opening mixer: ' + Pa_GetErrorText(Error), 'TPortaudioInputDevice.Open');
+    end
+    else
+    begin
+      // save current source selection and select new source
+      SourceIndex := Ini.InputDeviceConfig[CfgIndex].Input-1;
+      if (SourceIndex = -1) then
+      begin
+        // nothing to do if default source is used
+        SourceRestore := -1;
+      end
+      else
+      begin
+        // store current source-index and select new source
+        SourceRestore := Px_GetCurrentInputSource(Mixer); // -1 in error case
+        Px_SetCurrentInputSource(Mixer, SourceIndex);
+      end;
+    end;
+  {$ENDIF}
+
+  Result := true;
+end;
+
+function TPortaudioInputDevice.Start(): boolean;
+var
+  Error: TPaError;
+begin
+  Result := false;
+
+  // recording already started -> stop first
+  if (RecordStream <> nil) then
+    Stop();
+
+  // TODO: Do not open the device here (takes too much time).
+  if (not Open()) then
+    Exit;
+
+  // start capture
+  Error := Pa_StartStream(RecordStream);
+  if (Error <> paNoError) then
+  begin
+    Log.LogError('Error starting stream: ' + Pa_GetErrorText(Error), 'TPortaudioInputDevice.Start');
+    Close();
+    RecordStream := nil;
+    Exit;
+  end;
+
+  Result := true;
+end;
+
+function TPortaudioInputDevice.Stop(): boolean;
+var
+  Error: TPaError;
+begin
+  Result := false;
+
+  if (RecordStream = nil) then
+    Exit;
+
+  // Note: do NOT call Pa_StopStream here!
+  // It gets stuck on devices with non-working callback as Pa_StopStream
+  // waits until all buffers have been handled (which never occurs in that case).
+  Error := Pa_AbortStream(RecordStream);
+  if (Error <> paNoError) then
+  begin
+    Log.LogError('Pa_AbortStream: ' + Pa_GetErrorText(Error), 'TPortaudioInputDevice.Stop');
+  end;
+
+  Result := Close();
+end;
+
+function TPortaudioInputDevice.Close(): boolean;
+var
+  Error: TPaError;
+begin
+  {$IFDEF UsePortmixer}
+    if (Mixer <> nil) then
+    begin
+      // restore source selection
+      if (SourceRestore >= 0) then
+      begin
+        Px_SetCurrentInputSource(Mixer, SourceRestore);
+      end;
+
+      // close mixer
+      Px_CloseMixer(Mixer);
+      Mixer := nil;
+    end;
+  {$ENDIF}
+
+  Error := Pa_CloseStream(RecordStream);
+  if (Error <> paNoError) then
+  begin
+    Log.LogError('Pa_CloseStream: ' + Pa_GetErrorText(Error), 'TPortaudioInputDevice.Close');
+    Result := false;
+  end
+  else
+  begin
+    Result := true;
+  end;
+
+  RecordStream := nil;
+end;
+
+function TPortaudioInputDevice.GetVolume(): single;
+begin
+  Result := 0;
+  {$IFDEF UsePortmixer}
+    if (Mixer <> nil) then
+      Result := Px_GetInputVolume(Mixer);
+  {$ENDIF}
+end;
+
+procedure TPortaudioInputDevice.SetVolume(Volume: single);
+begin
+  {$IFDEF UsePortmixer}
+    if (Mixer <> nil) then
+    begin
+      // clip to valid range
+      if (Volume > 1.0) then
+        Volume := 1.0
+      else if (Volume < 0) then
+        Volume := 0;
+      Px_SetInputVolume(Mixer, Volume);
+    end;
+  {$ENDIF}
+end;
+
+
+{ TAudioInput_Portaudio }
+
+function TAudioInput_Portaudio.GetName: String;
+begin
+  result := 'Portaudio';
+end;
+
+function TAudioInput_Portaudio.EnumDevices(): boolean;
+var
+  i:            integer;
+  deviceName:   UTF8String;
+  paApiIndex:   TPaHostApiIndex;
+  paApiInfo:    PPaHostApiInfo;
+  paDeviceIndex:TPaDeviceIndex;
+  paDeviceInfo: PPaDeviceInfo;
+  channelCnt:   integer;
+  deviceIndex:  integer;
+  err:          TPaError;
+  errMsg:       string;
+  paDevice:     TPortaudioInputDevice;
+  inputParams:  TPaStreamParameters;
+  stream:       PPaStream;
+  streamInfo:   PPaStreamInfo;
+  sampleRate:   double;
+  latency:      TPaTime;
+  {$IFDEF UsePortmixer}
+  mixer:        PPxMixer;
+  sourceCnt:    integer;
+  sourceIndex:  integer;
+  sourceName:   UTF8String;
+  {$ENDIF}
+const
+  MIN_TEST_LATENCY = 100 / 1000; // min. test latency of 100 ms to avoid removal of working devices
+begin
+  Result := false;
+
+  // choose the best available Audio-API
+  paApiIndex := AudioCore.GetPreferredApiIndex();
+  if (paApiIndex = -1) then
+  begin
+    Log.LogError('No working Audio-API found', 'TAudioInput_Portaudio.EnumDevices');
+    Exit;
+  end;
+
+  paApiInfo := Pa_GetHostApiInfo(paApiIndex);
+
+  deviceIndex := 0;
+
+  // init array-size to max. input-devices count
+  SetLength(AudioInputProcessor.DeviceList, paApiInfo^.deviceCount);
+  for i:= 0 to High(AudioInputProcessor.DeviceList) do
+  begin
+    // convert API-specific device-index to global index
+    paDeviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(paApiIndex, i);
+    paDeviceInfo := Pa_GetDeviceInfo(paDeviceIndex);
+
+    channelCnt := paDeviceInfo^.maxInputChannels;
+
+    // current device is no input device -> skip
+    if (channelCnt <= 0) then
+      continue;
+
+    // portaudio returns a channel-count of 128 for some devices
+    // (e.g. the "default"-device), so we have to detect those
+    // fantasy channel counts.
+    if (channelCnt > 8) then
+      channelCnt := 2;
+
+    paDevice := TPortaudioInputDevice.Create();
+    AudioInputProcessor.DeviceList[deviceIndex] := paDevice;
+
+    // retrieve device-name
+    deviceName := ConvertPaStringToUTF8(paDeviceInfo^.name);
+    paDevice.Name := UnifyDeviceName(deviceName, deviceIndex);
+    paDevice.PaDeviceIndex := paDeviceIndex;
+
+    sampleRate := paDeviceInfo^.defaultSampleRate;
+
+    // use a stable (high) latency so we do not remove working devices
+    if (paDeviceInfo^.defaultHighInputLatency > MIN_TEST_LATENCY) then
+      latency := paDeviceInfo^.defaultHighInputLatency
+    else
+      latency := MIN_TEST_LATENCY;
+
+    // setup desired input parameters
+    with inputParams do
+    begin
+      device := paDeviceIndex;
+      channelCount := channelCnt;
+      sampleFormat := paInt16;
+      suggestedLatency := latency;
+      hostApiSpecificStreamInfo := nil;
+    end;
+
+    // check souncard and adjust sample-rate
+    if (not AudioCore.TestDevice(@inputParams, nil, sampleRate)) then
+    begin
+      // ignore device if it does not work
+      Log.LogError('Device "'+paDevice.Name+'" does not work',
+                   'TAudioInput_Portaudio.EnumDevices');
+      paDevice.Free();
+      continue;
+    end;
+
+    // open device for further info
+    err := Pa_OpenStream(stream, @inputParams, nil, sampleRate,
+        paFramesPerBufferUnspecified, paNoFlag, @MicrophoneTestCallback, nil);
+    if (err <> paNoError) then
+    begin
+      // unable to open device -> skip
+      errMsg := Pa_GetErrorText(err);
+      Log.LogError('Device error: "'+ deviceName +'" ('+ errMsg +')',
+                   'TAudioInput_Portaudio.EnumDevices');
+      paDevice.Free();
+      continue;
+    end;
+
+    // adjust sample-rate (might be changed by portaudio)
+    streamInfo := Pa_GetStreamInfo(stream);
+    if (streamInfo <> nil) then
+    begin
+      if (sampleRate <> streamInfo^.sampleRate) then
+      begin
+        Log.LogStatus('Portaudio changed Samplerate from ' + FloatToStr(sampleRate) +
+            ' to ' + FloatToStr(streamInfo^.sampleRate),
+            'TAudioInput_Portaudio.InitializeRecord');
+        sampleRate := streamInfo^.sampleRate;
+      end;
+    end;
+    
+    // create audio-format info and resize capture-buffer array
+    paDevice.AudioFormat := TAudioFormatInfo.Create(
+        channelCnt,
+        sampleRate,
+        asfS16
+    );
+    SetLength(paDevice.CaptureChannel, paDevice.AudioFormat.Channels);
+
+    Log.LogStatus('InputDevice "'+paDevice.Name+'"@' +
+        IntToStr(paDevice.AudioFormat.Channels)+'x'+
+        FloatToStr(paDevice.AudioFormat.SampleRate)+'Hz ('+
+        FloatTostr(inputParams.suggestedLatency)+'sec)' ,
+        'Portaudio.EnumDevices');
+
+    // portaudio does not provide a source-type check
+    paDevice.MicSource := -1;
+    paDevice.SourceRestore := -1;
+
+    // add a virtual default source (will not change mixer-settings)
+    SetLength(paDevice.Source, 1);
+    paDevice.Source[0].Name := DEFAULT_SOURCE_NAME;
+
+    {$IFDEF UsePortmixer}
+      // use default mixer
+      mixer := Px_OpenMixer(stream, 0);
+
+      // get input count
+      sourceCnt := Px_GetNumInputSources(mixer);
+      SetLength(paDevice.Source, sourceCnt+1);
+
+      // get input names
+      for sourceIndex := 1 to sourceCnt do
+      begin
+        sourceName := Px_GetInputSourceName(mixer, sourceIndex-1);
+        paDevice.Source[sourceIndex].Name := ConvertPaStringToUTF8(sourceName);
+      end;
+
+      Px_CloseMixer(mixer);
+    {$ENDIF}
+
+    // close test-stream
+    Pa_CloseStream(stream);
+
+    Inc(deviceIndex);
+  end;
+
+  // adjust size to actual input-device count
+  SetLength(AudioInputProcessor.DeviceList, deviceIndex);
+
+  Log.LogStatus('#Input-Devices: ' + inttostr(deviceIndex), 'Portaudio');
+
+  Result := true;
+end;
+
+function TAudioInput_Portaudio.InitializeRecord(): boolean;
+begin
+  Result := false;
+  AudioCore := TAudioCore_Portaudio.GetInstance();
+
+  // initialize portaudio
+  if (not AudioCore.Initialize()) then
+     Exit;
+  Result := EnumDevices();
+end;
+
+function TAudioInput_Portaudio.FinalizeRecord: boolean;
+begin
+  CaptureStop;
+  AudioCore.Terminate();
+  Result := inherited FinalizeRecord();
+end;
+
+{*
+ * Portaudio input capture callback.
+ *}
+function MicrophoneCallback(input: pointer; output: pointer; frameCount: culong;
+      timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
+      inputDevice: pointer): cint; cdecl;
+begin
+  AudioInputProcessor.HandleMicrophoneData(input, frameCount*4, inputDevice);
+  result := paContinue;
+end;
+
+{*
+ * Portaudio test capture callback.
+ *}
+function MicrophoneTestCallback(input: pointer; output: pointer; frameCount: culong;
+      timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
+      inputDevice: pointer): cint; cdecl;
+begin
+  // this callback is called only once
+  result := paAbort;
+end;
+
+initialization
+  MediaManager.add(TAudioInput_Portaudio.Create);
+
+end.
diff --git a/songmanagement/src/media/UAudioPlaybackBase.pas b/songmanagement/src/media/UAudioPlaybackBase.pas
new file mode 100644
index 00000000..5f317257
--- /dev/null
+++ b/songmanagement/src/media/UAudioPlaybackBase.pas
@@ -0,0 +1,319 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioPlaybackBase;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMusic,
+  UTime,
+  UPath;
+
+type
+  TAudioPlaybackBase = class(TInterfacedObject, IAudioPlayback)
+    protected
+      OutputDeviceList: TAudioOutputDeviceList;
+      MusicStream: TAudioPlaybackStream;
+      function CreatePlaybackStream(): TAudioPlaybackStream; virtual; abstract;
+      procedure ClearOutputDeviceList();
+      function GetLatency(): double; virtual; abstract;
+
+      // open sound or music stream (used by Open() and OpenSound())
+      function OpenStream(const Filename: IPath): TAudioPlaybackStream;
+      function OpenDecodeStream(const Filename: IPath): TAudioDecodeStream;
+    public
+      function GetName: string; virtual; abstract;
+
+      function Open(const Filename: IPath): boolean; // true if succeed
+      procedure Close;
+
+      procedure Play;
+      procedure Pause;
+      procedure Stop;
+      procedure FadeIn(Time: real; TargetVolume: single);
+
+      procedure SetSyncSource(SyncSource: TSyncSource);
+
+      procedure SetPosition(Time: real);
+      function  GetPosition: real;
+
+      function InitializePlayback: boolean; virtual; abstract;
+      function FinalizePlayback: boolean; virtual;
+
+      //function SetOutputDevice(Device: TAudioOutputDevice): boolean;
+      function GetOutputDeviceList(): TAudioOutputDeviceList;
+
+      procedure SetAppVolume(Volume: single); virtual; abstract;
+      procedure SetVolume(Volume: single);
+      procedure SetLoop(Enabled: boolean);
+
+      procedure Rewind;
+      function  Finished: boolean;
+      function  Length: real;
+
+      // Sounds
+      function OpenSound(const Filename: IPath): TAudioPlaybackStream;
+      procedure PlaySound(Stream: TAudioPlaybackStream);
+      procedure StopSound(Stream: TAudioPlaybackStream);
+
+      // Equalizer
+      procedure GetFFTData(var Data: TFFTData);
+
+      // Interface for Visualizer
+      function GetPCMData(var Data: TPCMData): Cardinal;
+
+      function CreateVoiceStream(Channel: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream; virtual; abstract;
+  end;
+
+
+implementation
+
+uses
+  ULog,
+  SysUtils;
+
+{ TAudioPlaybackBase }
+
+function TAudioPlaybackBase.FinalizePlayback: boolean;
+begin
+  FreeAndNil(MusicStream);
+  ClearOutputDeviceList();
+  Result := true;
+end;
+
+function TAudioPlaybackBase.Open(const Filename: IPath): boolean;
+begin
+  // free old MusicStream
+  MusicStream.Free;
+
+  MusicStream := OpenStream(Filename);
+  if not assigned(MusicStream) then
+  begin
+    Result := false;
+    Exit;
+  end;
+
+  //MusicStream.AddSoundEffect(TVoiceRemoval.Create());
+
+  Result := true;
+end;
+
+procedure TAudioPlaybackBase.Close;
+begin
+  FreeAndNil(MusicStream);
+end;
+
+function TAudioPlaybackBase.OpenDecodeStream(const Filename: IPath): TAudioDecodeStream;
+var
+  i: integer;
+begin
+  for i := 0 to AudioDecoders.Count-1 do
+  begin
+    Result := IAudioDecoder(AudioDecoders[i]).Open(Filename);
+    if (assigned(Result)) then
+    begin
+      Log.LogInfo('Using decoder ' + IAudioDecoder(AudioDecoders[i]).GetName() +
+        ' for "' + Filename.ToNative + '"', 'TAudioPlaybackBase.OpenDecodeStream');
+      Exit;
+    end;
+  end;
+  Result := nil;
+end;
+
+procedure OnClosePlaybackStream(Stream: TAudioProcessingStream);
+var
+  PlaybackStream: TAudioPlaybackStream;
+  SourceStream: TAudioSourceStream;
+begin
+  PlaybackStream := TAudioPlaybackStream(Stream);
+  SourceStream := PlaybackStream.GetSourceStream();
+  SourceStream.Free;
+end;
+
+function TAudioPlaybackBase.OpenStream(const Filename: IPath): TAudioPlaybackStream;
+var
+  PlaybackStream: TAudioPlaybackStream;
+  DecodeStream: TAudioDecodeStream;
+begin
+  Result := nil;
+
+  //Log.LogStatus('Loading Sound: "' + Filename + '"', 'TAudioPlayback_Bass.OpenStream');
+
+  DecodeStream := OpenDecodeStream(Filename);
+  if (not assigned(DecodeStream)) then
+  begin
+    Log.LogStatus('Could not open "' + Filename.ToNative + '"', 'TAudioPlayback_Bass.OpenStream');
+    Exit;
+  end;
+
+  // create a matching playback-stream for the decoder
+  PlaybackStream := CreatePlaybackStream();
+  if (not PlaybackStream.Open(DecodeStream)) then
+  begin
+    FreeAndNil(PlaybackStream);
+    FreeAndNil(DecodeStream);
+    Exit;
+  end;
+
+  PlaybackStream.AddOnCloseHandler(OnClosePlaybackStream);
+
+  Result := PlaybackStream;
+end;
+
+procedure TAudioPlaybackBase.Play;
+begin
+  if assigned(MusicStream) then
+    MusicStream.Play();
+end;
+
+procedure TAudioPlaybackBase.Pause;
+begin
+  if assigned(MusicStream) then
+    MusicStream.Pause();
+end;
+
+procedure TAudioPlaybackBase.Stop;
+begin
+  if assigned(MusicStream) then
+    MusicStream.Stop();
+end;
+
+function TAudioPlaybackBase.Length: real;
+begin
+  if assigned(MusicStream) then
+    Result := MusicStream.Length
+  else
+    Result := 0;
+end;
+
+function TAudioPlaybackBase.GetPosition: real;
+begin
+  if assigned(MusicStream) then
+    Result := MusicStream.Position
+  else
+    Result := 0;
+end;
+
+procedure TAudioPlaybackBase.SetPosition(Time: real);
+begin
+  if assigned(MusicStream) then
+    MusicStream.Position := Time;
+end;
+
+procedure TAudioPlaybackBase.SetSyncSource(SyncSource: TSyncSource);
+begin
+  if assigned(MusicStream) then
+    MusicStream.SetSyncSource(SyncSource);
+end;
+
+procedure TAudioPlaybackBase.Rewind;
+begin
+  SetPosition(0);
+end;
+
+function TAudioPlaybackBase.Finished: boolean;
+begin
+  if assigned(MusicStream) then
+    Result := (MusicStream.Status = ssStopped)
+  else
+    Result := true;
+end;
+
+procedure TAudioPlaybackBase.SetVolume(Volume: single);
+begin
+  if assigned(MusicStream) then
+    MusicStream.Volume := Volume;
+end;
+
+procedure TAudioPlaybackBase.FadeIn(Time: real; TargetVolume: single);
+begin
+  if assigned(MusicStream) then
+    MusicStream.FadeIn(Time, TargetVolume);
+end;
+
+procedure TAudioPlaybackBase.SetLoop(Enabled: boolean);
+begin
+  if assigned(MusicStream) then
+    MusicStream.Loop := Enabled;
+end;
+
+// Equalizer
+procedure TAudioPlaybackBase.GetFFTData(var data: TFFTData);
+begin
+  if assigned(MusicStream) then
+    MusicStream.GetFFTData(data);
+end;
+
+{*
+ * Copies interleaved PCM SInt16 stereo samples into data.
+ * Returns the number of frames
+ *}
+function TAudioPlaybackBase.GetPCMData(var data: TPCMData): Cardinal;
+begin
+  if assigned(MusicStream) then
+    Result := MusicStream.GetPCMData(data)
+  else
+    Result := 0;
+end;
+
+function TAudioPlaybackBase.OpenSound(const Filename: IPath): TAudioPlaybackStream;
+begin
+  Result := OpenStream(Filename);
+end;
+
+procedure TAudioPlaybackBase.PlaySound(stream: TAudioPlaybackStream);
+begin
+  if assigned(stream) then
+    stream.Play();
+end;
+
+procedure TAudioPlaybackBase.StopSound(stream: TAudioPlaybackStream);
+begin
+  if assigned(stream) then
+    stream.Stop();
+end;
+
+procedure TAudioPlaybackBase.ClearOutputDeviceList();
+var
+  DeviceIndex: integer;
+begin
+  for DeviceIndex := 0 to High(OutputDeviceList) do
+    OutputDeviceList[DeviceIndex].Free();
+  SetLength(OutputDeviceList, 0);
+end;
+
+function TAudioPlaybackBase.GetOutputDeviceList(): TAudioOutputDeviceList;
+begin
+  Result := OutputDeviceList;
+end;
+
+end.
diff --git a/songmanagement/src/media/UAudioPlayback_Bass.pas b/songmanagement/src/media/UAudioPlayback_Bass.pas
new file mode 100644
index 00000000..1d7a44dc
--- /dev/null
+++ b/songmanagement/src/media/UAudioPlayback_Bass.pas
@@ -0,0 +1,758 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioPlayback_Bass;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+implementation
+
+uses
+  Classes,
+  Math,
+  UIni,
+  UMain,
+  UMusic,
+  UAudioPlaybackBase,
+  UAudioCore_Bass,
+  ULog,
+  sdl,
+  bass,
+  SysUtils;
+
+type
+  PHDSP = ^HDSP;
+
+type
+  TBassPlaybackStream = class(TAudioPlaybackStream)
+    private
+      Handle: HSTREAM;
+      NeedsRewind: boolean;
+      PausedSeek: boolean; // true if a seek was performed in pause state
+
+      procedure Reset();
+      function IsEOF(): boolean;
+    protected
+      function GetLatency(): double;        override;
+      function GetLoop(): boolean;          override;
+      procedure SetLoop(Enabled: boolean);  override;
+      function GetLength(): real;           override;
+      function GetStatus(): TStreamStatus;  override;
+      function GetVolume(): single;         override;
+      procedure SetVolume(Volume: single);  override;
+      function GetPosition: real;           override;
+      procedure SetPosition(Time: real);    override;
+    public
+      constructor Create();
+      destructor Destroy(); override;
+
+      function Open(SourceStream: TAudioSourceStream): boolean; override;
+      procedure Close();                    override;
+
+      procedure Play();                     override;
+      procedure Pause();                    override;
+      procedure Stop();                     override;
+      procedure FadeIn(Time: real; TargetVolume: single); override;
+
+      procedure AddSoundEffect(Effect: TSoundEffect);    override;
+      procedure RemoveSoundEffect(Effect: TSoundEffect); override;
+
+      procedure GetFFTData(var Data: TFFTData);           override;
+      function  GetPCMData(var Data: TPCMData): Cardinal; override;
+
+      function GetAudioFormatInfo(): TAudioFormatInfo; override;
+
+      function ReadData(Buffer: PByteArray; BufferSize: integer): integer;
+
+      property EOF: boolean READ IsEOF;
+  end;
+
+const
+  MAX_VOICE_DELAY = 0.020; // 20ms
+
+type
+  TBassVoiceStream = class(TAudioVoiceStream)
+    private
+      Handle: HSTREAM;
+    public
+      function Open(ChannelMap: integer; FormatInfo: TAudioFormatInfo): boolean; override;
+      procedure Close(); override;
+
+      procedure WriteData(Buffer: PByteArray; BufferSize: integer); override;
+      function ReadData(Buffer: PByteArray; BufferSize: integer): integer; override;
+      function IsEOF(): boolean; override;
+      function IsError(): boolean; override;
+  end;
+
+type
+  TAudioPlayback_Bass = class(TAudioPlaybackBase)
+    private
+      function EnumDevices(): boolean;
+    protected
+      function GetLatency(): double; override;
+      function CreatePlaybackStream(): TAudioPlaybackStream; override;
+    public
+      function GetName: String; override;
+      function InitializePlayback(): boolean; override;
+      function FinalizePlayback: boolean; override;
+      procedure SetAppVolume(Volume: single); override;
+      function CreateVoiceStream(ChannelMap: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream; override;
+  end;
+
+  TBassOutputDevice = class(TAudioOutputDevice)
+    private
+      BassDeviceID: DWORD; // DeviceID used by BASS
+  end;
+
+var
+  BassCore: TAudioCore_Bass;
+
+
+{ TBassPlaybackStream }
+
+function PlaybackStreamHandler(handle: HSTREAM; buffer: Pointer; length: DWORD; user: Pointer): DWORD;
+{$IFDEF MSWINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+var
+  PlaybackStream: TBassPlaybackStream;
+  BytesRead: integer;
+begin
+  PlaybackStream := TBassPlaybackStream(user);
+  if (not assigned (PlaybackStream)) then
+  begin
+    Result := BASS_STREAMPROC_END;
+    Exit;
+  end;
+
+  BytesRead := PlaybackStream.ReadData(buffer, length);
+  // check for errors
+  if (BytesRead < 0) then
+    Result := BASS_STREAMPROC_END
+  // check for EOF
+  else if (PlaybackStream.EOF) then
+    Result := BytesRead or BASS_STREAMPROC_END
+  // no error/EOF
+  else
+    Result := BytesRead;
+end;
+
+function TBassPlaybackStream.ReadData(Buffer: PByteArray; BufferSize: integer): integer;
+var
+  AdjustedSize: integer;
+  RequestedSourceSize, SourceSize: integer;
+  SkipCount: integer;
+  SourceFormatInfo: TAudioFormatInfo;
+  FrameSize: integer;
+  PadFrame: PByteArray;
+  //Info: BASS_INFO;
+  //Latency: double;
+begin
+  Result := -1;
+
+  if (not assigned(SourceStream)) then
+    Exit;
+
+  // sanity check
+  if (BufferSize = 0) then
+  begin
+    Result := 0;
+    Exit;
+  end;
+
+  SourceFormatInfo := SourceStream.GetAudioFormatInfo();
+  FrameSize := SourceFormatInfo.FrameSize;
+
+  // check how much data to fetch to be in synch
+  AdjustedSize := Synchronize(BufferSize, SourceFormatInfo);
+
+  // skip data if we are too far behind
+  SkipCount := AdjustedSize - BufferSize;
+  while (SkipCount > 0) do
+  begin
+    RequestedSourceSize := Min(SkipCount, BufferSize);
+    SourceSize := SourceStream.ReadData(Buffer, RequestedSourceSize);
+    // if an error or EOF occured stop skipping and handle error/EOF with the next ReadData()
+    if (SourceSize <= 0) then
+      break;
+    Dec(SkipCount, SourceSize);
+  end;
+
+  // get source data (e.g. from a decoder)
+  RequestedSourceSize := Min(AdjustedSize, BufferSize);
+  SourceSize := SourceStream.ReadData(Buffer, RequestedSourceSize);
+  if (SourceSize < 0) then
+    Exit;
+
+  // set preliminary result
+  Result := SourceSize;
+
+  // if we are to far ahead, fill output-buffer with last frame of source data
+  // Note that AdjustedSize is used instead of SourceSize as the SourceSize might
+  // be less than expected because of errors etc.
+  if (AdjustedSize < BufferSize) then
+  begin
+    // use either the last frame for padding or fill with zero
+    if (SourceSize >= FrameSize) then
+      PadFrame := @Buffer[SourceSize-FrameSize]
+    else
+      PadFrame := nil;
+
+    FillBufferWithFrame(@Buffer[SourceSize], BufferSize - SourceSize,
+                        PadFrame, FrameSize);
+    Result := BufferSize;
+  end;
+end;
+
+constructor TBassPlaybackStream.Create();
+begin
+  inherited;
+  Reset();
+end;
+
+destructor TBassPlaybackStream.Destroy();
+begin
+  Close();
+  inherited;
+end;
+
+function TBassPlaybackStream.Open(SourceStream: TAudioSourceStream): boolean;
+var
+  FormatInfo: TAudioFormatInfo;
+  FormatFlags: DWORD;
+begin
+  Result := false;
+
+  // close previous stream and reset state
+  Reset();
+
+  // sanity check if stream is valid
+  if not assigned(SourceStream) then
+    Exit;
+
+  Self.SourceStream := SourceStream;
+  FormatInfo := SourceStream.GetAudioFormatInfo();
+  if (not BassCore.ConvertAudioFormatToBASSFlags(FormatInfo.Format, FormatFlags)) then
+  begin
+    Log.LogError('Unhandled sample-format', 'TBassPlaybackStream.Open');
+    Exit;
+  end;
+
+  // create matching playback stream
+  Handle := BASS_StreamCreate(Round(FormatInfo.SampleRate), FormatInfo.Channels, formatFlags,
+      @PlaybackStreamHandler, Self);
+  if (Handle = 0) then
+  begin
+    Log.LogError('BASS_StreamCreate failed: ' + BassCore.ErrorGetString(BASS_ErrorGetCode()),
+                 'TBassPlaybackStream.Open');
+    Exit;
+  end;
+
+  Result := true;
+end;
+
+procedure TBassPlaybackStream.Close();
+begin
+  // stop and free stream
+  if (Handle <> 0) then
+  begin
+    Bass_StreamFree(Handle);
+    Handle := 0;
+  end;
+
+  // Note: PerformOnClose must be called before SourceStream is invalidated
+  PerformOnClose();
+  // unset source-stream
+  SourceStream := nil;
+end;
+
+procedure TBassPlaybackStream.Reset();
+begin
+  Close();
+  NeedsRewind := false;
+  PausedSeek := false;
+end;
+
+procedure TBassPlaybackStream.Play();
+var
+  NeedsFlush: boolean;
+begin
+  if (not assigned(SourceStream)) then
+    Exit;
+
+  NeedsFlush := true;
+
+  if (BASS_ChannelIsActive(Handle) = BASS_ACTIVE_PAUSED) then
+  begin
+    // only paused (and not seeked while paused) streams are not flushed
+    if (not PausedSeek) then
+      NeedsFlush := false;
+    // paused streams do not need a rewind
+    NeedsRewind := false;
+  end;
+
+  // rewind if necessary. Cases that require no rewind are:
+  // - stream was created and never played
+  // - stream was paused and is resumed now
+  // - stream was stopped and set to a new position already
+  if (NeedsRewind) then
+    SourceStream.Position := 0;
+
+  NeedsRewind := true;
+  PausedSeek := false;
+
+  // start playing and flush buffers on rewind
+  BASS_ChannelPlay(Handle, NeedsFlush);
+end;
+
+procedure TBassPlaybackStream.FadeIn(Time: real; TargetVolume: single);
+begin
+  // start stream
+  Play();
+  // start fade-in: slide from fadeStart- to fadeEnd-volume in FadeInTime
+  BASS_ChannelSlideAttribute(Handle, BASS_ATTRIB_VOL, TargetVolume, Trunc(Time * 1000));
+end;
+
+procedure TBassPlaybackStream.Pause();
+begin
+  BASS_ChannelPause(Handle);
+end;
+
+procedure TBassPlaybackStream.Stop();
+begin
+  BASS_ChannelStop(Handle);
+end;
+
+function TBassPlaybackStream.IsEOF(): boolean;
+begin
+  if (assigned(SourceStream)) then
+    Result := SourceStream.EOF
+  else
+    Result := true;
+end;
+
+function TBassPlaybackStream.GetLatency(): double;
+begin
+  // TODO: should we consider output latency for synching (needs BASS_DEVICE_LATENCY)?
+  //if (BASS_GetInfo(Info)) then
+  //  Latency := Info.latency / 1000
+  //else
+  //  Latency := 0;
+  Result := 0; 
+end;
+
+function TBassPlaybackStream.GetVolume(): single;
+var
+  lVolume: single;
+begin
+  if (not BASS_ChannelGetAttribute(Handle, BASS_ATTRIB_VOL, lVolume)) then
+  begin
+    Log.LogError('BASS_ChannelGetAttribute: ' + BassCore.ErrorGetString(),
+      'TBassPlaybackStream.GetVolume');
+    Result := 0;
+    Exit;
+  end;
+  Result := Round(lVolume);
+end;
+
+procedure TBassPlaybackStream.SetVolume(Volume: single);
+begin
+  // clamp volume
+  if Volume < 0 then
+    Volume := 0;
+  if Volume > 1.0 then
+    Volume := 1.0;
+  // set volume
+  BASS_ChannelSetAttribute(Handle, BASS_ATTRIB_VOL, Volume);
+end;
+
+function TBassPlaybackStream.GetPosition: real;
+var
+  BufferPosByte: QWORD;
+  BufferPosSec: double;
+begin
+  if assigned(SourceStream) then
+  begin
+    BufferPosByte := BASS_ChannelGetData(Handle, nil, BASS_DATA_AVAILABLE);
+    BufferPosSec := BASS_ChannelBytes2Seconds(Handle, BufferPosByte);
+    // decrease the decoding position by the amount buffered (and hence not played)
+    // in the BASS playback stream.
+    Result := SourceStream.Position - BufferPosSec;
+  end
+  else
+  begin
+    Result := -1;
+  end;
+end;
+
+procedure TBassPlaybackStream.SetPosition(Time: real);
+var
+  ChannelState: DWORD;
+begin
+  if assigned(SourceStream) then
+  begin
+    ChannelState := BASS_ChannelIsActive(Handle);
+    if (ChannelState = BASS_ACTIVE_STOPPED) then
+    begin
+      // if the stream is stopped, do not rewind when the stream is played next time
+      NeedsRewind := false
+    end
+    else if (ChannelState = BASS_ACTIVE_PAUSED) then
+    begin
+      // buffers must be flushed if in paused state but there is no
+      // BASS_ChannelFlush() function so we have to use BASS_ChannelPlay() called in Play().
+      PausedSeek := true;
+    end;
+
+    // set new position
+    SourceStream.Position := Time;
+  end;
+end;
+
+function TBassPlaybackStream.GetLength(): real;
+begin
+  if assigned(SourceStream) then
+    Result := SourceStream.Length
+  else
+    Result := -1;
+end;
+
+function TBassPlaybackStream.GetStatus(): TStreamStatus;
+var
+  State: DWORD;
+begin
+  State := BASS_ChannelIsActive(Handle);
+  case State of
+    BASS_ACTIVE_PLAYING,
+    BASS_ACTIVE_STALLED:
+      Result := ssPlaying;
+    BASS_ACTIVE_PAUSED:
+      Result := ssPaused;
+    BASS_ACTIVE_STOPPED:
+      Result := ssStopped;
+    else
+    begin
+      Log.LogError('Unknown status', 'TBassPlaybackStream.GetStatus');
+      Result := ssStopped;
+    end;
+  end;
+end;
+
+function TBassPlaybackStream.GetLoop(): boolean;
+begin
+  if assigned(SourceStream) then
+    Result := SourceStream.Loop
+  else
+    Result := false;
+end;
+
+procedure TBassPlaybackStream.SetLoop(Enabled: boolean);
+begin
+  if assigned(SourceStream) then
+    SourceStream.Loop := Enabled;
+end;
+
+procedure DSPProcHandler(handle: HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: Pointer);
+{$IFDEF MSWINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+var
+  Effect: TSoundEffect;
+begin
+  Effect := TSoundEffect(user);
+  if assigned(Effect) then
+    Effect.Callback(buffer, length);
+end;
+
+procedure TBassPlaybackStream.AddSoundEffect(Effect: TSoundEffect);
+var
+  DspHandle: HDSP;
+begin
+  if assigned(Effect.engineData) then
+  begin
+    Log.LogError('TSoundEffect.engineData already set', 'TBassPlaybackStream.AddSoundEffect');
+    Exit;
+  end;
+
+  DspHandle := BASS_ChannelSetDSP(Handle, @DSPProcHandler, Effect, 0);
+  if (DspHandle = 0) then
+  begin
+    Log.LogError(BassCore.ErrorGetString(), 'TBassPlaybackStream.AddSoundEffect');
+    Exit;
+  end;
+
+  GetMem(Effect.EngineData, SizeOf(HDSP));
+  PHDSP(Effect.EngineData)^ := DspHandle;
+end;
+
+procedure TBassPlaybackStream.RemoveSoundEffect(Effect: TSoundEffect);
+begin
+  if not assigned(Effect.EngineData) then
+  begin
+    Log.LogError('TSoundEffect.engineData invalid', 'TBassPlaybackStream.RemoveSoundEffect');
+    Exit;
+  end;
+
+  if not BASS_ChannelRemoveDSP(Handle, PHDSP(Effect.EngineData)^) then
+  begin
+    Log.LogError(BassCore.ErrorGetString(), 'TBassPlaybackStream.RemoveSoundEffect');
+    Exit;
+  end;
+
+  FreeMem(Effect.EngineData);
+  Effect.EngineData := nil;
+end;
+
+procedure TBassPlaybackStream.GetFFTData(var Data: TFFTData);
+begin
+  // get FFT channel data (Mono, FFT512 -> 256 values)
+  BASS_ChannelGetData(Handle, @Data, BASS_DATA_FFT512);
+end;
+
+{*
+ * Copies interleaved PCM SInt16 stereo samples into data.
+ * Returns the number of frames
+ *}
+function TBassPlaybackStream.GetPCMData(var Data: TPCMData): Cardinal;
+var
+  Info: BASS_CHANNELINFO;
+  nBytes: DWORD;
+begin
+  Result := 0;
+
+  FillChar(Data, SizeOf(TPCMData), 0);
+
+  // no support for non-stereo files at the moment
+  BASS_ChannelGetInfo(Handle, Info);
+  if (Info.chans <> 2) then
+    Exit;
+
+  nBytes := BASS_ChannelGetData(Handle, @Data, SizeOf(TPCMData));
+  if(nBytes <= 0) then
+    Result := 0
+  else
+    Result := nBytes div SizeOf(TPCMStereoSample);
+end;
+
+function TBassPlaybackStream.GetAudioFormatInfo(): TAudioFormatInfo;
+begin
+  if assigned(SourceStream) then
+    Result := SourceStream.GetAudioFormatInfo()
+  else
+    Result := nil;
+end;
+
+
+{ TBassVoiceStream }
+
+function TBassVoiceStream.Open(ChannelMap: integer; FormatInfo: TAudioFormatInfo): boolean;
+var
+  Flags: DWORD;
+begin
+  Result := false;
+
+  Close();
+
+  if (not inherited Open(ChannelMap, FormatInfo)) then
+    Exit;
+
+  // get channel flags
+  BassCore.ConvertAudioFormatToBASSFlags(FormatInfo.Format, Flags);
+
+  (*
+  // distribute the mics equally to both speakers
+  if ((ChannelMap and CHANNELMAP_LEFT) <> 0) then
+    Flags := Flags or BASS_SPEAKER_FRONTLEFT;
+  if ((ChannelMap and CHANNELMAP_RIGHT) <> 0) then
+    Flags := Flags or BASS_SPEAKER_FRONTRIGHT;
+  *)
+  
+  // create the channel
+  Handle := BASS_StreamCreate(Round(FormatInfo.SampleRate), 1, Flags, STREAMPROC_PUSH, nil);
+
+  // start the channel
+  BASS_ChannelPlay(Handle, true);
+
+  Result := true;
+end;
+
+procedure TBassVoiceStream.Close();
+begin
+  if (Handle <> 0) then
+  begin
+    BASS_ChannelStop(Handle);
+    BASS_StreamFree(Handle);
+  end;
+  inherited Close();
+end;
+
+procedure TBassVoiceStream.WriteData(Buffer: PByteArray; BufferSize: integer);
+var QueueSize: DWORD;
+begin
+  if ((Handle <> 0) and (BufferSize > 0)) then
+  begin
+    // query the queue size (normally 0)
+    QueueSize := BASS_StreamPutData(Handle, nil, 0);
+    // flush the buffer if the delay would be too high
+    if (QueueSize > MAX_VOICE_DELAY * FormatInfo.BytesPerSec) then
+      BASS_ChannelPlay(Handle, true);
+    // send new data to playback buffer
+    BASS_StreamPutData(Handle, Buffer, BufferSize);
+  end;
+end;
+
+// Note: we do not need the read-function for the BASS implementation
+function TBassVoiceStream.ReadData(Buffer: PByteArray; BufferSize: integer): integer;
+begin
+  Result := -1;
+end;
+
+function TBassVoiceStream.IsEOF(): boolean;
+begin
+  Result := false;
+end;
+
+function TBassVoiceStream.IsError(): boolean;
+begin
+  Result := false;
+end;
+
+
+{ TAudioPlayback_Bass }
+
+function TAudioPlayback_Bass.GetName: String;
+begin
+  Result := 'BASS_Playback';
+end;
+
+function TAudioPlayback_Bass.EnumDevices(): boolean;
+var
+  BassDeviceID: DWORD;
+  DeviceIndex: integer;
+  Device: TBassOutputDevice;
+  DeviceInfo: BASS_DEVICEINFO;
+begin
+  Result := true;
+
+  ClearOutputDeviceList();
+
+  // skip "no sound"-device (ID = 0)
+  BassDeviceID := 1;
+
+  while (true) do
+  begin
+    // check for device
+    if (not BASS_GetDeviceInfo(BassDeviceID, DeviceInfo)) then
+      Break;
+
+    // set device info
+    Device := TBassOutputDevice.Create();
+    Device.Name := DeviceInfo.name;
+    Device.BassDeviceID := BassDeviceID;
+
+    // add device to list
+    SetLength(OutputDeviceList, BassDeviceID);
+    OutputDeviceList[BassDeviceID-1] := Device;
+
+    Inc(BassDeviceID);
+  end;
+end;
+
+function TAudioPlayback_Bass.InitializePlayback(): boolean;
+begin
+  Result := false;
+
+  BassCore := TAudioCore_Bass.GetInstance();
+  if not BassCore.CheckVersion then
+    Exit;
+
+  EnumDevices();
+
+  //Log.BenchmarkStart(4);
+  //Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize');
+
+  // TODO: use BASS_DEVICE_LATENCY to determine the latency
+  if not BASS_Init(-1, 44100, 0, 0, nil) then
+  begin
+    Log.LogError('Could not initialize BASS', 'TAudioPlayback_Bass.InitializePlayback');
+    Exit;
+  end;
+
+  //Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4);
+
+  // config playing buffer
+  //BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10);
+  //BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
+
+  Result := true;
+end;
+
+function TAudioPlayback_Bass.FinalizePlayback(): boolean;
+begin
+  Close;
+  BASS_Free;
+  inherited FinalizePlayback();
+  Result := true;
+end;
+
+function TAudioPlayback_Bass.CreatePlaybackStream(): TAudioPlaybackStream;
+begin
+  Result := TBassPlaybackStream.Create();
+end;
+
+procedure TAudioPlayback_Bass.SetAppVolume(Volume: single);
+begin
+  // set volume for this application (ranges from 0..10000 since BASS 2.4)
+  BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Round(Volume*10000));
+end;
+
+function TAudioPlayback_Bass.CreateVoiceStream(ChannelMap: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream;
+var
+  VoiceStream: TAudioVoiceStream;
+begin
+  Result := nil;
+
+  VoiceStream := TBassVoiceStream.Create();
+  if (not VoiceStream.Open(ChannelMap, FormatInfo)) then
+  begin
+    VoiceStream.Free;
+    Exit;
+  end;
+
+  Result := VoiceStream;
+end;
+
+function TAudioPlayback_Bass.GetLatency(): double;
+begin
+  Result := 0;
+end;
+
+
+initialization
+  MediaManager.Add(TAudioPlayback_Bass.Create);
+
+end.
diff --git a/songmanagement/src/media/UAudioPlayback_Portaudio.pas b/songmanagement/src/media/UAudioPlayback_Portaudio.pas
new file mode 100644
index 00000000..6fbae6e3
--- /dev/null
+++ b/songmanagement/src/media/UAudioPlayback_Portaudio.pas
@@ -0,0 +1,385 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioPlayback_Portaudio;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  SysUtils,
+  UMusic;
+
+implementation
+
+uses
+  portaudio,
+  UAudioCore_Portaudio,
+  UAudioPlayback_SoftMixer,
+  ULog,
+  UIni,
+  UMain;
+
+type
+  TAudioPlayback_Portaudio = class(TAudioPlayback_SoftMixer)
+    private
+      paStream:  PPaStream;
+      AudioCore: TAudioCore_Portaudio;
+      Latency: double;
+      function OpenDevice(deviceIndex: TPaDeviceIndex): boolean;
+      function EnumDevices(): boolean;
+    protected
+      function InitializeAudioPlaybackEngine(): boolean; override;
+      function StartAudioPlaybackEngine(): boolean;      override;
+      procedure StopAudioPlaybackEngine();               override;
+      function FinalizeAudioPlaybackEngine(): boolean;   override;
+      function GetLatency(): double;                     override;
+    public
+      function GetName: String;                          override;
+  end;
+
+  TPortaudioOutputDevice = class(TAudioOutputDevice)
+    private
+      PaDeviceIndex:  TPaDeviceIndex;
+  end;
+
+
+{ TAudioPlayback_Portaudio }
+
+function PortaudioAudioCallback(input: Pointer; output: Pointer; frameCount: Longword;
+    timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
+    userData: Pointer): Integer; cdecl;
+var
+  Engine: TAudioPlayback_Portaudio;
+begin
+  Engine := TAudioPlayback_Portaudio(userData);
+  // update latency
+  Engine.Latency := timeInfo.outputBufferDacTime - timeInfo.currentTime;
+  // call superclass callback
+  Engine.AudioCallback(output, frameCount * Engine.FormatInfo.FrameSize);
+  Result := paContinue;
+end;
+
+function TAudioPlayback_Portaudio.GetName: String;
+begin
+  Result := 'Portaudio_Playback';
+end;
+
+function TAudioPlayback_Portaudio.OpenDevice(deviceIndex: TPaDeviceIndex): boolean;
+var
+  DeviceInfo : PPaDeviceInfo;
+  SampleRate : double;
+  OutParams  : TPaStreamParameters;
+  StreamInfo : PPaStreamInfo;
+  err        : TPaError;
+begin
+  Result := false;
+
+  DeviceInfo := Pa_GetDeviceInfo(deviceIndex);
+
+  Log.LogInfo('Audio-Output Device: ' + DeviceInfo^.name, 'TAudioPlayback_Portaudio.OpenDevice');
+
+  SampleRate := DeviceInfo^.defaultSampleRate;
+
+  with OutParams do
+  begin
+    device := deviceIndex;
+    channelCount := 2;
+    sampleFormat := paInt16;
+    suggestedLatency := DeviceInfo^.defaultLowOutputLatency;
+    hostApiSpecificStreamInfo := nil;
+  end;
+
+  // check souncard and adjust sample-rate
+  if not AudioCore.TestDevice(nil, @OutParams, SampleRate) then
+  begin
+    Log.LogStatus('TestDevice failed!', 'TAudioPlayback_Portaudio.OpenDevice');
+    Exit;
+  end;
+
+  // open output stream
+  err := Pa_OpenStream(paStream, nil, @OutParams, SampleRate,
+          paFramesPerBufferUnspecified,
+          paNoFlag, @PortaudioAudioCallback, Self);
+  if(err <> paNoError) then
+  begin
+    Log.LogStatus(Pa_GetErrorText(err), 'TAudioPlayback_Portaudio.OpenDevice');
+    paStream := nil;
+    Exit;
+  end;
+
+  // get estimated latency (will be updated with real latency in the callback)
+  StreamInfo := Pa_GetStreamInfo(paStream);
+  if (StreamInfo <> nil) then
+    Latency := StreamInfo^.outputLatency
+  else
+    Latency := 0;
+
+  FormatInfo := TAudioFormatInfo.Create(
+    OutParams.channelCount,
+    SampleRate,
+    asfS16 // FIXME: is paInt16 system-dependant or -independant?
+  );
+
+  Result := true;
+end;
+
+function TAudioPlayback_Portaudio.EnumDevices(): boolean;
+var
+  i:           integer;
+  paApiIndex:  TPaHostApiIndex;
+  paApiInfo:   PPaHostApiInfo;
+  deviceName:  string;
+  deviceIndex: TPaDeviceIndex;
+  deviceInfo:  PPaDeviceInfo;
+  channelCnt:  integer;
+  SC:          integer; // soundcard
+  err:         TPaError;
+  errMsg:      string;
+  paDevice:    TPortaudioOutputDevice;
+  outputParams: TPaStreamParameters;
+  stream:      PPaStream;
+  streamInfo:  PPaStreamInfo;
+  sampleRate:  double;
+  latency:     TPaTime;
+  cbPolls: integer;
+  cbWorks: boolean;
+begin
+  Result := false;
+
+(*
+  // choose the best available Audio-API
+  paApiIndex := AudioCore.GetPreferredApiIndex();
+  if(paApiIndex = -1) then
+  begin
+    Log.LogError('No working Audio-API found', 'TAudioPlayback_Portaudio.EnumDevices');
+    Exit;
+  end;
+
+  paApiInfo := Pa_GetHostApiInfo(paApiIndex);
+
+  SC := 0;
+
+  // init array-size to max. output-devices count
+  SetLength(OutputDeviceList, paApiInfo^.deviceCount);
+  for i:= 0 to High(OutputDeviceList) do
+  begin
+    // convert API-specific device-index to global index
+    deviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(paApiIndex, i);
+    deviceInfo := Pa_GetDeviceInfo(deviceIndex);
+
+    channelCnt := deviceInfo^.maxOutputChannels;
+
+    // current device is no output device -> skip
+    if (channelCnt <= 0) then
+      continue;
+
+    // portaudio returns a channel-count of 128 for some devices
+    // (e.g. the "default"-device), so we have to detect those
+    // fantasy channel counts.
+    if (channelCnt > 8) then
+      channelCnt := 2;
+
+    paDevice := TPortaudioOutputDevice.Create();
+    OutputDeviceList[SC] := paDevice;
+
+    // retrieve device-name
+    deviceName := deviceInfo^.name;
+    paDevice.Name := deviceName;
+    paDevice.PaDeviceIndex := deviceIndex;
+
+    if (deviceInfo^.defaultSampleRate > 0) then
+      sampleRate := deviceInfo^.defaultSampleRate
+    else
+      sampleRate := 44100;
+
+    // on vista and xp the defaultLowInputLatency may be set to 0 but it works.
+    // TODO: correct too low latencies (what is a too low latency, maybe < 10ms?)
+    latency := deviceInfo^.defaultLowInputLatency;
+
+    // setup desired output parameters
+    // TODO: retry with input-latency set to 20ms (defaultLowOutputLatency might
+    //       not be set correctly in OSS)
+    with outputParams do
+    begin
+      device := deviceIndex;
+      channelCount := channelCnt;
+      sampleFormat := paInt16;
+      suggestedLatency := latency;
+      hostApiSpecificStreamInfo := nil;
+    end;
+
+    // check if mic-callback works (might not be called on some devices)
+    if (not TAudioCore_Portaudio.TestDevice(nil, @outputParams, sampleRate)) then
+    begin
+      // ignore device if callback did not work
+      Log.LogError('Device "'+paDevice.Name+'" does not respond',
+                   'TAudioPlayback_Portaudio.InitializeRecord');
+      paDevice.Free();
+      continue;
+    end;
+
+    // open device for further info
+    err := Pa_OpenStream(stream, nil, @outputParams, sampleRate,
+        paFramesPerBufferUnspecified, paNoFlag, @MicrophoneTestCallback, nil);
+    if(err <> paNoError) then
+    begin
+      // unable to open device -> skip
+      errMsg := Pa_GetErrorText(err);
+      Log.LogError('Device error: "'+ deviceName +'" ('+ errMsg +')',
+                   'TAudioPlayback_Portaudio.InitializeRecord');
+      paDevice.Free();
+      continue;
+    end;
+
+    // adjust sample-rate (might be changed by portaudio)
+    streamInfo := Pa_GetStreamInfo(stream);
+    if (streamInfo <> nil) then
+    begin
+      if (sampleRate <> streamInfo^.sampleRate) then
+      begin
+        Log.LogStatus('Portaudio changed Samplerate from ' + FloatToStr(sampleRate) +
+            ' to ' + FloatToStr(streamInfo^.sampleRate),
+            'TAudioInput_Portaudio.InitializeRecord');
+        sampleRate := streamInfo^.sampleRate;
+      end;
+    end;
+
+    // create audio-format info and resize capture-buffer array
+    paDevice.AudioFormat := TAudioFormatInfo.Create(
+        channelCnt,
+        sampleRate,
+        asfS16
+    );
+    SetLength(paDevice.CaptureChannel, paDevice.AudioFormat.Channels);
+
+    Log.LogStatus('OutputDevice "'+paDevice.Name+'"@' +
+        IntToStr(paDevice.AudioFormat.Channels)+'x'+
+        FloatToStr(paDevice.AudioFormat.SampleRate)+'Hz ('+
+        FloatTostr(outputParams.suggestedLatency)+'sec)' ,
+        'TAudioInput_Portaudio.InitializeRecord');
+
+    // close test-stream
+    Pa_CloseStream(stream);
+
+    Inc(SC);
+  end;
+
+  // adjust size to actual input-device count
+  SetLength(OutputDeviceList, SC);
+
+  Log.LogStatus('#Output-Devices: ' + inttostr(SC), 'Portaudio');
+*)
+
+  Result := true;
+end;
+
+function TAudioPlayback_Portaudio.InitializeAudioPlaybackEngine(): boolean;
+var
+  paApiIndex      : TPaHostApiIndex;
+  paApiInfo       : PPaHostApiInfo;
+  paOutDevice     : TPaDeviceIndex;
+begin
+  Result := false;
+  AudioCore := TAudioCore_Portaudio.GetInstance();
+
+  // initialize portaudio
+  if (not AudioCore.Initialize()) then
+    Exit;
+
+  paApiIndex := AudioCore.GetPreferredApiIndex();
+  if (paApiIndex = -1) then
+  begin
+    Log.LogError('No working Audio-API found', 'TAudioPlayback_Portaudio.InitializeAudioPlaybackEngine');
+    Exit;
+  end;
+
+  EnumDevices();
+
+  paApiInfo := Pa_GetHostApiInfo(paApiIndex);
+  Log.LogInfo('Audio-Output API-Type: ' + paApiInfo^.name, 'TAudioPlayback_Portaudio.OpenDevice');
+
+  paOutDevice := paApiInfo^.defaultOutputDevice;
+  if (not OpenDevice(paOutDevice)) then
+  begin
+    Exit;
+  end;
+
+  Result := true;
+end;
+
+function TAudioPlayback_Portaudio.StartAudioPlaybackEngine(): boolean;
+var
+  err: TPaError;
+begin
+  Result := false;
+
+  if (paStream = nil) then
+    Exit;
+
+  err := Pa_StartStream(paStream);
+  if(err <> paNoError) then
+  begin
+    Log.LogStatus('Pa_StartStream: '+Pa_GetErrorText(err), 'UAudioPlayback_Portaudio');
+    Exit;
+  end;
+
+  Result := true;
+end;
+
+procedure TAudioPlayback_Portaudio.StopAudioPlaybackEngine();
+begin
+  if (paStream <> nil) then
+  begin
+    Pa_CloseStream(paStream);
+    // wait until stream is closed, otherwise Terminate() might cause a segfault
+    while (Pa_IsStreamActive(paStream) = 1) do
+      ;
+    paStream := nil;
+  end;
+end;
+
+function TAudioPlayback_Portaudio.FinalizeAudioPlaybackEngine(): boolean;
+begin
+  StopAudioPlaybackEngine();
+  Result := AudioCore.Terminate();
+end;
+
+function TAudioPlayback_Portaudio.GetLatency(): double;
+begin
+  Result := Latency;
+end;
+
+
+initialization
+  MediaManager.Add(TAudioPlayback_Portaudio.Create);
+
+end.
diff --git a/songmanagement/src/media/UAudioPlayback_SDL.pas b/songmanagement/src/media/UAudioPlayback_SDL.pas
new file mode 100644
index 00000000..8403ef03
--- /dev/null
+++ b/songmanagement/src/media/UAudioPlayback_SDL.pas
@@ -0,0 +1,182 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioPlayback_SDL;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+implementation
+
+uses
+  Classes,
+  sdl,
+  SysUtils,
+  UAudioPlayback_SoftMixer,
+  UMusic,
+  ULog,
+  UIni,
+  UMain;
+
+type
+  TAudioPlayback_SDL = class(TAudioPlayback_SoftMixer)
+    private
+      Latency: double;
+      function EnumDevices(): boolean;
+    protected
+      function InitializeAudioPlaybackEngine(): boolean; override;
+      function StartAudioPlaybackEngine(): boolean;      override;
+      procedure StopAudioPlaybackEngine();               override;
+      function FinalizeAudioPlaybackEngine(): boolean;   override;
+      function GetLatency(): double;                     override;
+    public
+      function GetName: String;                          override;
+      procedure MixBuffers(dst, src: PByteArray; size: Cardinal; volume: Single); override;
+  end;
+
+  
+{ TAudioPlayback_SDL }
+
+procedure SDLAudioCallback(userdata: Pointer; stream: PByteArray; len: integer); cdecl;
+var
+  Engine: TAudioPlayback_SDL;
+begin
+  Engine := TAudioPlayback_SDL(userdata);
+  Engine.AudioCallback(stream, len);
+end;
+
+function TAudioPlayback_SDL.GetName: String;
+begin
+  Result := 'SDL_Playback';
+end;
+
+function TAudioPlayback_SDL.EnumDevices(): boolean;
+begin
+  // Note: SDL does not provide Device-Selection capabilities (will be introduced in 1.3)
+  ClearOutputDeviceList();
+  SetLength(OutputDeviceList, 1);
+  OutputDeviceList[0] := TAudioOutputDevice.Create();
+  OutputDeviceList[0].Name := '[SDL Default-Device]';
+  Result := true;
+end;
+
+function TAudioPlayback_SDL.InitializeAudioPlaybackEngine(): boolean;
+var
+  DesiredAudioSpec, ObtainedAudioSpec: TSDL_AudioSpec;
+  SampleBufferSize: integer;
+begin
+  Result := false;
+
+  EnumDevices();
+
+  if (SDL_InitSubSystem(SDL_INIT_AUDIO) = -1) then
+  begin
+    Log.LogError('SDL_InitSubSystem failed!', 'TAudioPlayback_SDL.InitializeAudioPlaybackEngine');
+    Exit;
+  end;
+
+  SampleBufferSize := IAudioOutputBufferSizeVals[Ini.AudioOutputBufferSizeIndex];
+  if (SampleBufferSize <= 0) then
+  begin
+    // Automatic setting default
+    // FIXME: too much glitches with 1024 samples
+    SampleBufferSize := 2048; //1024;
+  end;
+
+  FillChar(DesiredAudioSpec, SizeOf(DesiredAudioSpec), 0);
+  with DesiredAudioSpec do
+  begin
+    freq := 44100;
+    format := AUDIO_S16SYS;
+    channels := 2;
+    samples := SampleBufferSize;
+    callback := @SDLAudioCallback;
+    userdata := Self;
+  end;
+
+  // Note: always use the "obtained" parameter, otherwise SDL might try to convert
+  // the samples itself if the desired format is not available. This might lead
+  // to problems if for example ALSA does not support 44100Hz and proposes 48000Hz.
+  // Without the obtained parameter, SDL would try to convert 44.1kHz to 48kHz with
+  // its crappy (non working) converter resulting in a wrong (too high) pitch.
+  if(SDL_OpenAudio(@DesiredAudioSpec, @ObtainedAudioSpec) = -1) then
+  begin
+    Log.LogStatus('SDL_OpenAudio: ' + SDL_GetError(), 'TAudioPlayback_SDL.InitializeAudioPlaybackEngine');
+    Exit;
+  end;
+
+  FormatInfo := TAudioFormatInfo.Create(
+    ObtainedAudioSpec.channels,
+    ObtainedAudioSpec.freq,
+    asfS16
+  );
+
+  // Note: SDL does not provide info of the internal buffer state.
+  // So we use the average buffer-size.
+  Latency := (ObtainedAudioSpec.samples/2) / FormatInfo.SampleRate;
+
+  Log.LogStatus('Opened audio device', 'TAudioPlayback_SDL.InitializeAudioPlaybackEngine');
+
+  Result := true;
+end;
+
+function TAudioPlayback_SDL.StartAudioPlaybackEngine(): boolean;
+begin
+  SDL_PauseAudio(0);
+  Result := true;
+end;
+
+procedure TAudioPlayback_SDL.StopAudioPlaybackEngine();
+begin
+  SDL_PauseAudio(1);
+end;
+
+function TAudioPlayback_SDL.FinalizeAudioPlaybackEngine(): boolean;
+begin
+  SDL_CloseAudio();
+  SDL_QuitSubSystem(SDL_INIT_AUDIO);
+  Result := true;
+end;
+
+function TAudioPlayback_SDL.GetLatency(): double;
+begin
+  Result := Latency;
+end;
+
+procedure TAudioPlayback_SDL.MixBuffers(dst, src: PByteArray; size: Cardinal; volume: Single);
+begin
+  SDL_MixAudio(PUInt8(dst), PUInt8(src), size, Round(volume * SDL_MIX_MAXVOLUME));
+end;
+
+
+initialization
+  MediaManager.add(TAudioPlayback_SDL.Create);
+
+end.
diff --git a/songmanagement/src/media/UAudioPlayback_SoftMixer.pas b/songmanagement/src/media/UAudioPlayback_SoftMixer.pas
new file mode 100644
index 00000000..11df4df5
--- /dev/null
+++ b/songmanagement/src/media/UAudioPlayback_SoftMixer.pas
@@ -0,0 +1,1204 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UAudioPlayback_SoftMixer;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  sdl,
+  SysUtils,
+  URingBuffer,
+  UMusic,
+  UAudioPlaybackBase;
+
+type
+  TAudioPlayback_SoftMixer = class;
+
+  TGenericPlaybackStream = class(TAudioPlaybackStream)
+    private
+      Engine: TAudioPlayback_SoftMixer;
+      LastReadSize: integer;  // size of data returned by the last ReadData() call
+      LastReadTime: Cardinal; // time of the last ReadData() call
+
+      SampleBuffer:      PByteArray;
+      SampleBufferSize:  integer;
+      SampleBufferCount: integer; // number of available bytes in SampleBuffer
+      SampleBufferPos:   integer;
+
+      SourceBuffer:      PByteArray;
+      SourceBufferSize:  integer;
+      SourceBufferCount: integer; // number of available bytes in SourceBuffer
+
+      Converter: TAudioConverter;
+      Status:    TStreamStatus;
+      InternalLock: PSDL_Mutex;
+      SoundEffects: TList;
+      fVolume: single;
+
+      FadeInStartTime, FadeInTime: cardinal;
+      FadeInStartVolume, FadeInTargetVolume: single;
+
+      NeedsRewind: boolean;
+
+      procedure Reset();
+
+      procedure ApplySoundEffects(Buffer: PByteArray; BufferSize: integer);
+      function InitFormatConversion(): boolean;
+      procedure FlushBuffers();
+
+      procedure LockSampleBuffer(); {$IFDEF HasInline}inline;{$ENDIF}
+      procedure UnlockSampleBuffer(); {$IFDEF HasInline}inline;{$ENDIF}
+    protected
+      function GetLatency(): double;        override;
+      function GetStatus(): TStreamStatus;  override;
+      function GetVolume(): single;         override;
+      procedure SetVolume(Volume: single);  override;
+      function GetLength(): real;           override;
+      function GetLoop(): boolean;          override;
+      procedure SetLoop(Enabled: boolean);  override;
+      function GetPosition: real;           override;
+      procedure SetPosition(Time: real);    override;
+
+      function GetRemainingBufferSize(): integer;
+    public
+      constructor Create(Engine: TAudioPlayback_SoftMixer);
+      destructor Destroy(); override;
+
+      function Open(SourceStream: TAudioSourceStream): boolean; override;
+      procedure Close();                    override;
+
+      procedure Play();                     override;
+      procedure Pause();                    override;
+      procedure Stop();                     override;
+      procedure FadeIn(Time: real; TargetVolume: single); override;
+
+      function GetAudioFormatInfo(): TAudioFormatInfo; override;
+
+      function ReadData(Buffer: PByteArray; BufferSize: integer): integer;
+
+      function GetPCMData(var Data: TPCMData): cardinal; override;
+      procedure GetFFTData(var Data: TFFTData);          override;
+
+      procedure AddSoundEffect(Effect: TSoundEffect);    override;
+      procedure RemoveSoundEffect(Effect: TSoundEffect); override;
+  end;
+
+  TAudioMixerStream = class
+    private
+      Engine: TAudioPlayback_SoftMixer;
+
+      ActiveStreams: TList;
+      MixerBuffer: PByteArray;
+      InternalLock: PSDL_Mutex;
+
+      AppVolume: single;
+
+      procedure Lock(); {$IFDEF HasInline}inline;{$ENDIF}
+      procedure Unlock(); {$IFDEF HasInline}inline;{$ENDIF}
+
+      function GetVolume(): single;
+      procedure SetVolume(Volume: single);
+    public
+      constructor Create(Engine: TAudioPlayback_SoftMixer);
+      destructor Destroy(); override;
+      procedure AddStream(Stream: TAudioPlaybackStream);
+      procedure RemoveStream(Stream: TAudioPlaybackStream);
+      function ReadData(Buffer: PByteArray; BufferSize: integer): integer;
+
+      property Volume: single read GetVolume write SetVolume;
+  end;
+
+  TAudioPlayback_SoftMixer = class(TAudioPlaybackBase)
+    private
+      MixerStream: TAudioMixerStream;
+    protected
+      FormatInfo: TAudioFormatInfo;
+
+      function InitializeAudioPlaybackEngine(): boolean; virtual; abstract;
+      function StartAudioPlaybackEngine(): boolean;      virtual; abstract;
+      procedure StopAudioPlaybackEngine();               virtual; abstract;
+      function FinalizeAudioPlaybackEngine(): boolean;   virtual; abstract;
+      procedure AudioCallback(Buffer: PByteArray; Size: integer); {$IFDEF HasInline}inline;{$ENDIF}
+
+      function CreatePlaybackStream(): TAudioPlaybackStream; override;
+    public
+      function GetName: string; override; abstract;
+      function InitializePlayback(): boolean; override;
+      function FinalizePlayback: boolean; override;
+
+      procedure SetAppVolume(Volume: single); override;
+
+      function CreateVoiceStream(ChannelMap: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream; override;
+
+      function GetMixer(): TAudioMixerStream; {$IFDEF HasInline}inline;{$ENDIF}
+      function GetAudioFormatInfo(): TAudioFormatInfo;
+
+      procedure MixBuffers(DstBuffer, SrcBuffer: PByteArray; Size: cardinal; Volume: single); virtual;
+  end;
+
+type
+  TGenericVoiceStream = class(TAudioVoiceStream)
+    private
+      VoiceBuffer: TRingBuffer;
+      BufferLock: PSDL_Mutex;
+      PlaybackStream: TGenericPlaybackStream;
+      Engine: TAudioPlayback_SoftMixer;
+    public
+      constructor Create(Engine: TAudioPlayback_SoftMixer);
+
+      function Open(ChannelMap: integer; FormatInfo: TAudioFormatInfo): boolean; override;
+      procedure Close(); override;
+      procedure WriteData(Buffer: PByteArray; BufferSize: integer); override;
+      function ReadData(Buffer: PByteArray; BufferSize: integer): integer; override;
+      function IsEOF(): boolean; override;
+      function IsError(): boolean; override;
+  end;
+
+const
+  SOURCE_BUFFER_FRAMES = 4096;
+
+const
+  MAX_VOICE_DELAY = 0.500; // 20ms
+
+implementation
+
+uses
+  Math,
+  ULog,
+  UIni,
+  UFFT,
+  UAudioConverter,
+  UMain;
+
+{ TAudioMixerStream }
+
+constructor TAudioMixerStream.Create(Engine: TAudioPlayback_SoftMixer);
+begin
+  inherited Create();
+
+  Self.Engine := Engine;
+
+  ActiveStreams := TList.Create;
+  InternalLock := SDL_CreateMutex();
+  AppVolume := 1.0;
+end;
+
+destructor TAudioMixerStream.Destroy();
+begin
+  if assigned(MixerBuffer) then
+    Freemem(MixerBuffer);
+  ActiveStreams.Free;
+  SDL_DestroyMutex(InternalLock);
+  inherited;
+end;
+
+procedure TAudioMixerStream.Lock();
+begin
+  SDL_mutexP(InternalLock);
+end;
+
+procedure TAudioMixerStream.Unlock();
+begin
+  SDL_mutexV(InternalLock);
+end;
+
+function TAudioMixerStream.GetVolume(): single;
+begin
+  Lock();
+  Result := AppVolume;
+  Unlock();
+end;
+
+procedure TAudioMixerStream.SetVolume(Volume: single);
+begin
+  Lock();
+  AppVolume := Volume;
+  Unlock();
+end;
+
+procedure TAudioMixerStream.AddStream(Stream: TAudioPlaybackStream);
+begin
+  if not assigned(Stream) then
+    Exit;
+
+  Lock();
+  // check if stream is already in list to avoid duplicates
+  if (ActiveStreams.IndexOf(Pointer(Stream)) = -1) then
+    ActiveStreams.Add(Pointer(Stream));
+  Unlock();
+end;
+
+(*
+ * Sets the entry of stream in the ActiveStreams-List to nil
+ * but does not remove it from the list (Count is not changed!).
+ * Otherwise iterations over the elements might fail due to a
+ * changed Count-property.
+ * Call ActiveStreams.Pack() to remove the nil-pointers
+ * or check for nil-pointers when accessing ActiveStreams.
+ *)
+procedure TAudioMixerStream.RemoveStream(Stream: TAudioPlaybackStream);
+var
+  Index: integer;
+begin
+  Lock();
+  Index := activeStreams.IndexOf(Pointer(Stream));
+  if (Index <> -1) then
+  begin
+    // remove entry but do not decrease count-property
+    ActiveStreams[Index] := nil;
+  end;
+  Unlock();
+end;
+
+function TAudioMixerStream.ReadData(Buffer: PByteArray; BufferSize: integer): integer;
+var
+  i: integer;
+  Size: integer;
+  Stream: TGenericPlaybackStream;
+  NeedsPacking: boolean;
+begin
+  Result := BufferSize;
+
+  // zero target-buffer (silence)
+  FillChar(Buffer^, BufferSize, 0);
+
+  // resize mixer-buffer if necessary
+  ReallocMem(MixerBuffer, BufferSize);
+  if not assigned(MixerBuffer) then
+    Exit;
+
+  Lock();
+
+  NeedsPacking := false;
+
+  // mix streams to one stream
+  for i := 0 to ActiveStreams.Count-1 do
+  begin
+    if (ActiveStreams[i] = nil) then
+    begin
+      NeedsPacking := true;
+      continue;
+    end;
+
+    Stream := TGenericPlaybackStream(ActiveStreams[i]);
+    // fetch data from current stream
+    Size := Stream.ReadData(MixerBuffer, BufferSize);
+    if (Size > 0) then
+    begin
+      // mix stream-data with mixer-buffer
+      // Note: use Self.appVolume instead of Self.Volume to prevent recursive locking
+      Engine.MixBuffers(Buffer, MixerBuffer, Size, AppVolume * Stream.Volume);
+    end;
+  end;
+
+  // remove nil-pointers from list
+  if (NeedsPacking) then
+  begin
+    ActiveStreams.Pack();
+  end;
+
+  Unlock();
+end;
+
+
+{ TGenericPlaybackStream }
+
+constructor TGenericPlaybackStream.Create(Engine: TAudioPlayback_SoftMixer);
+begin
+  inherited Create();
+  Self.Engine := Engine;
+  InternalLock := SDL_CreateMutex();
+  SoundEffects := TList.Create;
+  Status := ssStopped;
+  Reset();
+end;
+
+destructor TGenericPlaybackStream.Destroy();
+begin
+  Close();
+  SDL_DestroyMutex(InternalLock);
+  FreeAndNil(SoundEffects);
+  inherited;
+end;
+
+procedure TGenericPlaybackStream.Reset();
+begin
+  SourceStream := nil;
+
+  FreeAndNil(Converter);
+
+  FreeMem(SampleBuffer);
+  SampleBuffer := nil;
+  SampleBufferPos := 0;
+  SampleBufferSize := 0;
+  SampleBufferCount := 0;
+
+  FreeMem(SourceBuffer);
+  SourceBuffer := nil;
+  SourceBufferSize := 0;
+  SourceBufferCount := 0;
+
+  NeedsRewind := false;
+
+  fVolume := 0;
+  SoundEffects.Clear;
+  FadeInTime := 0;
+
+  LastReadSize := 0;
+end;
+
+function TGenericPlaybackStream.Open(SourceStream: TAudioSourceStream): boolean;
+begin
+  Result := false;
+
+  Close();
+
+  if not assigned(SourceStream) then
+    Exit;
+  Self.SourceStream := SourceStream;
+
+  if not InitFormatConversion() then
+  begin
+    // reset decode-stream so it will not be freed on destruction
+    Self.SourceStream := nil;
+    Exit;
+  end;
+
+  SourceBufferSize := SOURCE_BUFFER_FRAMES * SourceStream.GetAudioFormatInfo().FrameSize;
+  GetMem(SourceBuffer, SourceBufferSize);
+  fVolume := 1.0;
+
+  Result := true;
+end;
+
+procedure TGenericPlaybackStream.Close();
+begin
+  // stop audio-callback on this stream
+  Stop();
+
+  // Note: PerformOnClose must be called before SourceStream is invalidated
+  PerformOnClose();
+  // and free data
+  Reset();
+end;
+
+procedure TGenericPlaybackStream.LockSampleBuffer();
+begin
+  SDL_mutexP(InternalLock);
+end;
+
+procedure TGenericPlaybackStream.UnlockSampleBuffer();
+begin
+  SDL_mutexV(InternalLock);
+end;
+
+function TGenericPlaybackStream.InitFormatConversion(): boolean;
+var
+  SrcFormatInfo: TAudioFormatInfo;
+  DstFormatInfo: TAudioFormatInfo;
+begin
+  Result := false;
+
+  SrcFormatInfo := SourceStream.GetAudioFormatInfo();
+  DstFormatInfo := GetAudioFormatInfo();
+
+  // TODO: selection should not be done here, use a factory (TAudioConverterFactory) instead 
+  {$IF Defined(UseFFmpegResample)}
+  Converter := TAudioConverter_FFmpeg.Create();
+  {$ELSEIF Defined(UseSRCResample)}
+  Converter := TAudioConverter_SRC.Create();
+  {$ELSE}
+  Converter := TAudioConverter_SDL.Create();
+  {$IFEND}
+
+  Result := Converter.Init(SrcFormatInfo, DstFormatInfo);
+end;
+
+procedure TGenericPlaybackStream.Play();
+var
+  Mixer: TAudioMixerStream;
+begin
+  // only paused streams are not flushed
+  if (Status = ssPaused) then
+    NeedsRewind := false;
+
+  // rewind if necessary. Cases that require no rewind are:
+  // - stream was created and never played
+  // - stream was paused and is resumed now
+  // - stream was stopped and set to a new position already
+  if (NeedsRewind) then
+    SetPosition(0);
+
+  // update status
+  Status := ssPlaying;
+
+  NeedsRewind := true;
+
+  // add this stream to the mixer
+  Mixer := Engine.GetMixer();
+  if (Mixer <> nil) then
+    Mixer.AddStream(Self);
+end;
+
+procedure TGenericPlaybackStream.FadeIn(Time: real; TargetVolume: single);
+begin
+  FadeInTime := Trunc(Time * 1000);
+  FadeInStartTime := SDL_GetTicks();
+  FadeInStartVolume := fVolume;
+  FadeInTargetVolume := TargetVolume;
+  Play();
+end;
+
+procedure TGenericPlaybackStream.Pause();
+var
+  Mixer: TAudioMixerStream;
+begin
+  if (Status <> ssPlaying) then
+    Exit;
+
+  Status := ssPaused;
+
+  Mixer := Engine.GetMixer();
+  if (Mixer <> nil) then
+    Mixer.RemoveStream(Self);
+end;
+
+procedure TGenericPlaybackStream.Stop();
+var
+  Mixer: TAudioMixerStream;
+begin
+  if (Status = ssStopped) then
+    Exit;
+
+  Status := ssStopped;
+  // stop fading
+  FadeInTime := 0;
+
+  LastReadSize := 0;
+  
+  Mixer := Engine.GetMixer();
+  if (Mixer <> nil) then
+    Mixer.RemoveStream(Self);
+end;
+
+function TGenericPlaybackStream.GetLoop(): boolean;
+begin
+  if assigned(SourceStream) then
+    Result := SourceStream.Loop
+  else
+    Result := false;
+end;
+
+procedure TGenericPlaybackStream.SetLoop(Enabled: boolean);
+begin
+  if assigned(SourceStream) then
+    SourceStream.Loop := Enabled;
+end;
+
+function TGenericPlaybackStream.GetLength(): real;
+begin
+  if assigned(SourceStream) then
+    Result := SourceStream.Length
+  else
+    Result := -1;
+end;
+
+function TGenericPlaybackStream.GetLatency(): double;
+begin
+  Result := Engine.GetLatency();
+end;
+
+function TGenericPlaybackStream.GetStatus(): TStreamStatus;
+begin
+  Result := Status;
+end;
+
+function TGenericPlaybackStream.GetAudioFormatInfo(): TAudioFormatInfo;
+begin
+  Result := Engine.GetAudioFormatInfo();
+end;
+
+procedure TGenericPlaybackStream.FlushBuffers();
+begin
+  SampleBufferCount := 0;
+  SampleBufferPos := 0;
+  SourceBufferCount := 0;
+  LastReadSize := 0;
+end;
+
+procedure TGenericPlaybackStream.ApplySoundEffects(Buffer: PByteArray; BufferSize: integer);
+var
+  i: integer;
+begin
+  for i := 0 to SoundEffects.Count-1 do
+  begin
+    if (SoundEffects[i] <> nil) then
+    begin
+      TSoundEffect(SoundEffects[i]).Callback(Buffer, BufferSize);
+    end;
+  end;
+end;
+
+function TGenericPlaybackStream.ReadData(Buffer: PByteArray; BufferSize: integer): integer;
+var
+  ConversionInputCount: integer;
+  ConversionOutputSize: integer;   // max. number of converted data (= buffer size)
+  ConversionOutputCount: integer;  // actual number of converted data
+  SourceSize: integer;
+  NeededSampleBufferSize: integer;
+  BytesNeeded: integer;
+  SourceFormatInfo, OutputFormatInfo: TAudioFormatInfo;
+  SourceFrameSize, OutputFrameSize: integer;
+  SkipOutputCount: integer;  // number of output-data bytes to skip
+  SkipSourceCount: integer;  // number of source-data bytes to skip
+  FillCount: integer;  // number of bytes to fill with padding data
+  CopyCount: integer;
+  PadFrame: PByteArray;
+begin
+  Result := -1;
+
+  LastReadSize := 0;
+
+  // sanity check for the source-stream
+  if (not assigned(SourceStream)) then
+    Exit;
+  
+  SkipOutputCount := 0;
+  SkipSourceCount := 0;
+  FillCount := 0;
+
+  SourceFormatInfo := SourceStream.GetAudioFormatInfo();
+  SourceFrameSize := SourceFormatInfo.FrameSize;
+  OutputFormatInfo := GetAudioFormatInfo();
+  OutputFrameSize := OutputFormatInfo.FrameSize;
+
+  // synchronize (adjust buffer size)
+  BytesNeeded := Synchronize(BufferSize, OutputFormatInfo);
+  if (BytesNeeded > BufferSize) then
+  begin
+    SkipOutputCount := BytesNeeded - BufferSize;
+    BytesNeeded := BufferSize;
+  end
+  else if (BytesNeeded < BufferSize) then
+  begin
+    FillCount := BufferSize - BytesNeeded;
+  end;
+
+  // lock access to sample-buffer
+  LockSampleBuffer();
+  try
+
+    // skip sample-buffer data
+    SampleBufferPos := SampleBufferPos + SkipOutputCount;
+    // size of available bytes in SampleBuffer after skipping
+    SampleBufferCount := SampleBufferCount - SampleBufferPos;
+    // update byte skip-count
+    SkipOutputCount := -SampleBufferCount;
+
+    // now that we skipped all buffered data from the last pass, we have to skip
+    // data directly after fetching it from the source-stream.
+    if (SkipOutputCount > 0) then
+    begin
+      SampleBufferCount := 0;
+      // convert skip-count to source-format units and resize to a multiple of
+      // the source frame-size.
+      SkipSourceCount := Round((SkipOutputCount * OutputFormatInfo.GetRatio(SourceFormatInfo)) /
+                               SourceFrameSize) * SourceFrameSize;
+      SkipOutputCount := 0;
+    end;
+
+    // copy data to front of buffer
+    if ((SampleBufferCount > 0) and (SampleBufferPos > 0)) then
+      Move(SampleBuffer[SampleBufferPos], SampleBuffer[0], SampleBufferCount);
+    SampleBufferPos := 0;
+
+    // resize buffer to a reasonable size
+    if (BufferSize > SampleBufferCount) then
+    begin
+      // Note: use BufferSize instead of BytesNeeded to minimize the need for resizing
+      SampleBufferSize := BufferSize;
+      ReallocMem(SampleBuffer, SampleBufferSize);
+      if (not assigned(SampleBuffer)) then
+        Exit;
+    end;
+
+    // fill sample-buffer (fetch and convert one block of source data per loop)
+    while (SampleBufferCount < BytesNeeded) do
+    begin
+      // move remaining source data from the previous pass to front of buffer
+      if (SourceBufferCount > 0) then
+      begin
+        Move(SourceBuffer[SourceBufferSize-SourceBufferCount],
+             SourceBuffer[0],
+             SourceBufferCount);
+      end;
+
+      SourceSize := SourceStream.ReadData(
+          @SourceBuffer[SourceBufferCount], SourceBufferSize-SourceBufferCount);
+      // break on error (-1) or if no data is available (0), e.g. while seeking
+      if (SourceSize <= 0) then
+      begin
+        // if we do not have data -> exit
+        if (SourceBufferCount = 0) then
+        begin
+          FlushBuffers();
+          Exit;
+        end;
+        // if we have some data, stop retrieving data from the source stream
+        // and use the data we have so far
+        Break;
+      end;
+
+      SourceBufferCount := SourceBufferCount + SourceSize;
+
+      // end-of-file reached -> stop playback
+      if (SourceStream.EOF) then
+      begin
+        if (Loop) then
+          SourceStream.Position := 0
+        else
+          Stop();
+      end;
+
+      if (SkipSourceCount > 0) then
+      begin
+        // skip data and update source buffer count
+        SourceBufferCount := SourceBufferCount - SkipSourceCount;
+        SkipSourceCount := -SourceBufferCount;
+        // continue with next pass if we skipped all data
+        if (SourceBufferCount <= 0) then
+        begin
+          SourceBufferCount := 0;
+          Continue;
+        end;
+      end;
+
+      // calc buffer size (might be bigger than actual resampled byte count)
+      ConversionOutputSize := Converter.GetOutputBufferSize(SourceBufferCount);
+      NeededSampleBufferSize := SampleBufferCount + ConversionOutputSize;
+
+      // resize buffer if necessary
+      if (SampleBufferSize < NeededSampleBufferSize) then
+      begin
+        SampleBufferSize := NeededSampleBufferSize;
+        ReallocMem(SampleBuffer, SampleBufferSize);
+        if (not assigned(SampleBuffer)) then
+        begin
+          FlushBuffers();
+          Exit;
+        end;
+      end;
+
+      // resample source data (Note: ConversionInputCount might be adjusted by Convert())
+      ConversionInputCount := SourceBufferCount;
+      ConversionOutputCount := Converter.Convert(
+          SourceBuffer, @SampleBuffer[SampleBufferCount], ConversionInputCount);
+      if (ConversionOutputCount = -1) then
+      begin
+        FlushBuffers();
+        Exit;
+      end;
+
+      // adjust sample- and source-buffer count by the number of converted bytes
+      SampleBufferCount := SampleBufferCount + ConversionOutputCount;
+      SourceBufferCount := SourceBufferCount - ConversionInputCount;
+    end;
+
+    // apply effects
+    ApplySoundEffects(SampleBuffer, SampleBufferCount);
+
+    // copy data to result buffer
+    CopyCount := Min(BytesNeeded, SampleBufferCount);
+    Move(SampleBuffer[0], Buffer[BufferSize - BytesNeeded], CopyCount);
+    Dec(BytesNeeded, CopyCount);
+    SampleBufferPos := CopyCount;
+
+  // release buffer lock
+  finally
+    UnlockSampleBuffer();
+  end;
+
+  // pad the buffer with the last frame if we are to fast
+  if (FillCount > 0) then
+  begin
+    if (CopyCount >= OutputFrameSize) then
+      PadFrame := @Buffer[CopyCount-OutputFrameSize]
+    else
+      PadFrame := nil;
+    FillBufferWithFrame(@Buffer[CopyCount], FillCount,
+                        PadFrame, OutputFrameSize);
+  end;
+
+  // BytesNeeded now contains the number of remaining bytes we were not able to fetch
+  LastReadTime := SDL_GetTicks;
+  LastReadSize := BufferSize - BytesNeeded;
+  Result := LastReadSize;
+end;
+
+function TGenericPlaybackStream.GetPCMData(var Data: TPCMData): cardinal;
+var
+  ByteCount: integer;
+begin
+  Result := 0;
+
+  // just SInt16 stereo support for now
+  if ((Engine.GetAudioFormatInfo().Format <> asfS16) or
+      (Engine.GetAudioFormatInfo().Channels <> 2)) then
+  begin
+    Exit;
+  end;
+
+  // zero memory
+  FillChar(Data, SizeOf(Data), 0);
+
+  // TODO: At the moment just the first samples of the SampleBuffer
+  // are returned, even if there is newer data in the upper samples.
+
+  LockSampleBuffer();
+  ByteCount := Min(SizeOf(Data), SampleBufferCount);
+  if (ByteCount > 0) then
+  begin
+    Move(SampleBuffer[0], Data, ByteCount);
+  end;
+  UnlockSampleBuffer();
+  
+  Result := ByteCount div SizeOf(TPCMStereoSample);
+end;
+
+procedure TGenericPlaybackStream.GetFFTData(var Data: TFFTData);
+var
+  i: integer;
+  Frames: integer;
+  DataIn: PSingleArray;
+  AudioFormat: TAudioFormatInfo;
+begin
+  // only works with SInt16 and Float values at the moment
+  AudioFormat := GetAudioFormatInfo();
+
+  DataIn := AllocMem(FFTSize * SizeOf(single));
+  if (DataIn = nil) then
+    Exit;
+
+  LockSampleBuffer();
+  // TODO: We just use the first Frames frames, the others are ignored.
+  Frames := Min(FFTSize, SampleBufferCount div AudioFormat.FrameSize);
+  // use only first channel and convert data to float-values
+  case AudioFormat.Format of
+    asfS16:
+    begin
+      for i := 0 to Frames-1 do
+        DataIn[i] := PSmallInt(@SampleBuffer[i*AudioFormat.FrameSize])^ / -Low(SmallInt);
+    end;
+    asfFloat:
+    begin
+      for i := 0 to Frames-1 do
+        DataIn[i] := PSingle(@SampleBuffer[i*AudioFormat.FrameSize])^;
+    end;
+  end;
+  UnlockSampleBuffer();
+
+  WindowFunc(fwfHanning, FFTSize, DataIn);
+  PowerSpectrum(FFTSize, DataIn, @Data);
+  FreeMem(DataIn);
+
+  // resize data to a 0..1 range
+  for i := 0 to High(TFFTData) do
+  begin
+    Data[i] := Sqrt(Data[i]) / 100;
+  end;
+end;
+
+procedure TGenericPlaybackStream.AddSoundEffect(Effect: TSoundEffect);
+begin
+  if (not assigned(Effect)) then
+    Exit;
+
+  LockSampleBuffer();
+  // check if effect is already in list to avoid duplicates
+  if (SoundEffects.IndexOf(Pointer(Effect)) = -1) then
+    SoundEffects.Add(Pointer(Effect));
+  UnlockSampleBuffer();
+end;
+
+procedure TGenericPlaybackStream.RemoveSoundEffect(Effect: TSoundEffect);
+begin
+  LockSampleBuffer();
+  SoundEffects.Remove(Effect);
+  UnlockSampleBuffer();
+end;
+
+{**
+ * Returns the approximate number of bytes left in the audio engines buffer queue.
+ *}
+function TGenericPlaybackStream.GetRemainingBufferSize(): integer;
+var
+  TimeDiff: double;
+begin
+  if (LastReadSize <= 0) then
+  begin
+    Result := 0;
+  end
+  else
+  begin
+    TimeDiff := (SDL_GetTicks() - LastReadTime) / 1000;
+    // we gave the data-sink LastReadSize bytes at the last call to ReadData().
+    // Calculate how much of this should be left in the data-sink
+    Result := LastReadSize - Trunc(TimeDiff * Engine.FormatInfo.BytesPerSec);
+    if (Result < 0) then
+      Result := 0;
+  end;
+end;
+
+function TGenericPlaybackStream.GetPosition: real;
+var
+  BufferedTime: double;
+begin
+  if assigned(SourceStream) then
+  begin
+    LockSampleBuffer();
+
+    // the duration of source stream data that is buffered in this stream.
+    // (this is the data retrieved from the source but has not been resampled)
+    BufferedTime := SourceBufferCount / SourceStream.GetAudioFormatInfo().BytesPerSec;
+
+    // the duration of data that is buffered in this stream.
+    // (this is the already resampled data that has not yet been passed to the audio engine)
+    BufferedTime := BufferedTime + (SampleBufferCount - SampleBufferPos) / Engine.FormatInfo.BytesPerSec;
+
+    // Now consider the samples left in the engine's (e.g. SDL) buffer.
+    // Otherwise the result calculated so far will not change until the callback
+    // is called the next time.
+    // For example, if the buffer has a size of 2048 frames we would not be
+    // able to return a new new position for approx. 40ms (at 44.1kHz) which
+    // would be very bad for synching.
+    BufferedTime := BufferedTime + GetRemainingBufferSize() / Engine.FormatInfo.BytesPerSec;
+
+    // use the timestamp of the source as reference and subtract the time of
+    // the data that is still buffered and not yet output.
+    Result := SourceStream.Position - BufferedTime;
+
+    UnlockSampleBuffer();
+  end
+  else
+  begin
+    Result := -1;
+  end;
+end;
+
+procedure TGenericPlaybackStream.SetPosition(Time: real);
+begin
+  if assigned(SourceStream) then
+  begin
+    LockSampleBuffer();
+
+    SourceStream.Position := Time;
+    if (Status = ssStopped) then
+      NeedsRewind := false;
+    // do not use outdated data
+    FlushBuffers();
+
+    AvgSyncDiff := -1;
+    
+    UnlockSampleBuffer();
+  end;
+end;
+
+function TGenericPlaybackStream.GetVolume(): single;
+var
+  FadeAmount: single;
+begin
+  LockSampleBuffer();
+  // adjust volume if fading is enabled
+  if (FadeInTime > 0) then
+  begin
+    FadeAmount := (SDL_GetTicks() - FadeInStartTime) / FadeInTime;
+    // check if fade-target is reached
+    if (FadeAmount >= 1) then
+    begin
+      // target reached -> stop fading
+      FadeInTime := 0;
+      fVolume := FadeInTargetVolume;
+    end
+    else
+    begin
+      // fading in progress
+      fVolume := FadeAmount*FadeInTargetVolume + (1-FadeAmount)*FadeInStartVolume;
+    end;
+  end;
+  // return current volume
+  Result := fVolume;
+  UnlockSampleBuffer();
+end;
+
+procedure TGenericPlaybackStream.SetVolume(Volume: single);
+begin
+  LockSampleBuffer();
+  // stop fading
+  FadeInTime := 0;
+  // clamp volume
+  if (Volume > 1.0) then
+    fVolume := 1.0
+  else if (Volume < 0) then
+    fVolume := 0
+  else
+    fVolume := Volume;
+  UnlockSampleBuffer();
+end;
+
+
+{ TGenericVoiceStream }
+
+constructor TGenericVoiceStream.Create(Engine: TAudioPlayback_SoftMixer);
+begin
+  inherited Create();
+  Self.Engine := Engine;
+end;
+
+function TGenericVoiceStream.Open(ChannelMap: integer; FormatInfo: TAudioFormatInfo): boolean;
+var
+  BufferSize: integer;
+begin
+  Result := false;
+
+  Close();
+
+  if (not inherited Open(ChannelMap, FormatInfo)) then
+    Exit;
+
+  // Note:
+  // - use Self.FormatInfo instead of FormatInfo as the latter one might have a
+  //   channel size of 2.
+  // - the buffer-size must be a multiple of the FrameSize
+  BufferSize := (Ceil(MAX_VOICE_DELAY * Self.FormatInfo.BytesPerSec) div Self.FormatInfo.FrameSize) *
+                Self.FormatInfo.FrameSize;
+  VoiceBuffer := TRingBuffer.Create(BufferSize);
+
+  BufferLock := SDL_CreateMutex();
+
+
+  // create a matching playback stream for the voice-stream
+  PlaybackStream := TGenericPlaybackStream.Create(Engine);
+  // link voice- and playback-stream
+  if (not PlaybackStream.Open(Self)) then
+  begin
+    PlaybackStream.Free;
+    Exit;
+  end;
+
+  // start voice passthrough
+  PlaybackStream.Play();
+
+  Result := true;
+end;
+
+procedure TGenericVoiceStream.Close();
+begin
+  // stop and free the playback stream
+  FreeAndNil(PlaybackStream);
+
+  // free data
+  FreeAndNil(VoiceBuffer);
+  if (BufferLock <> nil) then
+    SDL_DestroyMutex(BufferLock);
+
+  inherited Close();
+end;
+
+procedure TGenericVoiceStream.WriteData(Buffer: PByteArray; BufferSize: integer);
+begin
+  // lock access to buffer
+  SDL_mutexP(BufferLock);
+  try
+    if (VoiceBuffer = nil) then
+      Exit;
+    VoiceBuffer.Write(Buffer, BufferSize);
+  finally
+    SDL_mutexV(BufferLock);
+  end;
+end;
+
+function TGenericVoiceStream.ReadData(Buffer: PByteArray; BufferSize: integer): integer;
+begin
+  Result := -1;
+
+  // lock access to buffer
+  SDL_mutexP(BufferLock);
+  try
+    if (VoiceBuffer = nil) then
+      Exit;
+    Result := VoiceBuffer.Read(Buffer, BufferSize);
+  finally
+    SDL_mutexV(BufferLock);
+  end;
+end;
+
+function TGenericVoiceStream.IsEOF(): boolean;
+begin
+  SDL_mutexP(BufferLock);
+  Result := (VoiceBuffer = nil);
+  SDL_mutexV(BufferLock);
+end;
+
+function TGenericVoiceStream.IsError(): boolean;
+begin
+  Result := false;
+end;
+
+
+{ TAudioPlayback_SoftMixer }
+
+function TAudioPlayback_SoftMixer.InitializePlayback: boolean;
+begin
+  Result := false;
+
+  //Log.LogStatus('InitializePlayback', 'UAudioPlayback_SoftMixer');
+
+  if (not InitializeAudioPlaybackEngine()) then
+    Exit;
+
+  MixerStream := TAudioMixerStream.Create(Self);
+
+  if (not StartAudioPlaybackEngine()) then
+    Exit;
+
+  Result := true;
+end;
+
+function TAudioPlayback_SoftMixer.FinalizePlayback: boolean;
+begin
+  Close;
+  StopAudioPlaybackEngine();
+
+  FreeAndNil(MixerStream);
+  FreeAndNil(FormatInfo);
+
+  FinalizeAudioPlaybackEngine();
+  inherited FinalizePlayback;
+  Result := true;
+end;
+
+procedure TAudioPlayback_SoftMixer.AudioCallback(Buffer: PByteArray; Size: integer);
+begin
+  MixerStream.ReadData(Buffer, Size);
+end;
+
+function TAudioPlayback_SoftMixer.GetMixer(): TAudioMixerStream;
+begin
+  Result := MixerStream;
+end;
+
+function TAudioPlayback_SoftMixer.GetAudioFormatInfo(): TAudioFormatInfo;
+begin
+  Result := FormatInfo;
+end;
+
+function TAudioPlayback_SoftMixer.CreatePlaybackStream(): TAudioPlaybackStream;
+begin
+  Result := TGenericPlaybackStream.Create(Self);
+end;
+
+function TAudioPlayback_SoftMixer.CreateVoiceStream(ChannelMap: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream;
+var
+  VoiceStream: TGenericVoiceStream;
+begin
+  Result := nil;
+
+  // create a voice stream
+  VoiceStream := TGenericVoiceStream.Create(Self);
+  if (not VoiceStream.Open(ChannelMap, FormatInfo)) then
+  begin
+    VoiceStream.Free;
+    Exit;
+  end;
+
+  Result := VoiceStream;
+end;
+
+procedure TAudioPlayback_SoftMixer.SetAppVolume(Volume: single);
+begin
+  // sets volume only for this application
+  MixerStream.Volume := Volume;
+end;
+
+procedure TAudioPlayback_SoftMixer.MixBuffers(DstBuffer, SrcBuffer: PByteArray; Size: cardinal; Volume: single);
+var
+  SampleIndex: cardinal;
+  SampleInt: integer;
+  SampleFlt: single;
+begin
+  SampleIndex := 0;
+  case FormatInfo.Format of
+    asfS16:
+    begin
+      while (SampleIndex < Size) do
+      begin
+        // apply volume and sum with previous mixer value
+        SampleInt := PSmallInt(@DstBuffer[SampleIndex])^ +
+                     Round(PSmallInt(@SrcBuffer[SampleIndex])^ * Volume);
+        // clip result
+        if (SampleInt > High(SmallInt)) then
+          SampleInt := High(SmallInt)
+        else if (SampleInt < Low(SmallInt)) then
+          SampleInt := Low(SmallInt);
+        // assign result
+        PSmallInt(@DstBuffer[SampleIndex])^ := SampleInt;
+        // increase index by one sample
+        Inc(SampleIndex, SizeOf(SmallInt));
+      end;
+    end;
+    asfFloat:
+    begin
+      while (SampleIndex < Size) do
+      begin
+        // apply volume and sum with previous mixer value
+        SampleFlt := PSingle(@DstBuffer[SampleIndex])^ +
+                     PSingle(@SrcBuffer[SampleIndex])^ * Volume;
+        // clip result
+        if (SampleFlt > 1.0) then
+          SampleFlt := 1.0
+        else if (SampleFlt < -1.0) then
+          SampleFlt := -1.0;
+        // assign result
+        PSingle(@DstBuffer[SampleIndex])^ := SampleFlt;
+        // increase index by one sample
+        Inc(SampleIndex, SizeOf(single));
+      end;
+    end;
+    else
+    begin
+      Log.LogError('Incompatible format', 'TAudioMixerStream.MixAudio');
+    end;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/media/UMediaCore_FFmpeg.pas b/songmanagement/src/media/UMediaCore_FFmpeg.pas
new file mode 100644
index 00000000..eb136995
--- /dev/null
+++ b/songmanagement/src/media/UMediaCore_FFmpeg.pas
@@ -0,0 +1,645 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMediaCore_FFmpeg;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Classes,
+  ctypes,
+  sdl,
+  avcodec,
+  avformat,
+  avutil,
+  avio,
+  swscale,
+  UMusic,
+  ULog,
+  UPath;
+
+type
+  PPacketQueue = ^TPacketQueue;
+  TPacketQueue = class
+    private
+      FirstListEntry: PAVPacketList;
+      LastListEntry:  PAVPacketList;
+      PacketCount: integer;
+      Mutex:     PSDL_Mutex;
+      Condition: PSDL_Cond;
+      Size: integer;
+      AbortRequest: boolean;
+    public
+      constructor Create();
+      destructor Destroy(); override;
+
+      function Put(Packet : PAVPacket): integer;
+      function PutStatus(StatusFlag: integer; StatusInfo: Pointer): integer;
+      procedure FreeStatusInfo(var Packet: TAVPacket);
+      function GetStatusInfo(var Packet: TAVPacket): Pointer;
+      function Get(var Packet: TAVPacket; Blocking: boolean): integer;
+      function GetSize(): integer;
+      procedure Flush();
+      procedure Abort();
+      function IsAborted(): boolean;
+  end;
+
+const
+  STATUS_PACKET: PChar = 'STATUS_PACKET';
+const
+  PKT_STATUS_FLAG_EOF     = 1; // signal end-of-file
+  PKT_STATUS_FLAG_FLUSH   = 2; // request the decoder to flush its avcodec decode buffers
+  PKT_STATUS_FLAG_ERROR   = 3; // signal an error state
+  PKT_STATUS_FLAG_EMPTY   = 4; // request the decoder to output empty data (silence or black frames)
+
+type
+  TMediaCore_FFmpeg = class
+    private
+      AVCodecLock: PSDL_Mutex;
+    public
+      constructor Create();
+      destructor Destroy(); override;
+      class function GetInstance(): TMediaCore_FFmpeg;
+
+      function GetErrorString(ErrorNum: integer): string;
+      function FindStreamIDs(FormatCtx: PAVFormatContext; out FirstVideoStream, FirstAudioStream: integer ): boolean;
+      function FindAudioStreamIndex(FormatCtx: PAVFormatContext): integer;
+      function ConvertFFmpegToAudioFormat(FFmpegFormat: TSampleFormat; out Format: TAudioSampleFormat): boolean;
+      procedure LockAVCodec();
+      procedure UnlockAVCodec();
+  end;
+
+implementation
+
+uses
+  SysUtils,
+  UConfig;
+
+function FFmpegStreamOpen(h: PURLContext; filename: PChar; flags: cint): cint; cdecl; forward;
+function FFmpegStreamRead(h: PURLContext; buf: PByteArray; size: cint): cint; cdecl; forward;
+function FFmpegStreamWrite(h: PURLContext; buf: PByteArray; size: cint): cint; cdecl; forward;
+function FFmpegStreamSeek(h: PURLContext; pos: int64; whence: cint): int64; cdecl; forward;
+function FFmpegStreamClose(h: PURLContext): cint; cdecl; forward;
+
+const
+  UTF8FileProtocol: TURLProtocol = (
+      name:      'ufile';
+      url_open:  FFmpegStreamOpen;
+      url_read:  FFmpegStreamRead;
+      url_write: FFmpegStreamWrite;
+      url_seek:  FFmpegStreamSeek;
+      url_close: FFmpegStreamClose;
+  );
+
+var
+  Instance: TMediaCore_FFmpeg;
+
+function AV_VERSION_INT(a, b, c: cardinal): cuint;
+begin
+  Result := (a shl 16) or (b shl 8) or c;
+end;
+
+procedure CheckVersions();
+var
+  libVersion: cuint;
+  headerVersion: cuint;
+
+  function hexVerToStr(Version: cuint): string;
+  var
+    Major, Minor, Release: cardinal;
+  begin
+    Major   := (Version shr 16) and $FF;;
+    Minor   := (Version shr 8) and $FF;
+    Release := Version and $FF;
+    Result := Format('%d.%d.%d', [Major, Minor, Release]);
+  end;
+
+begin
+  libVersion := avcodec_version();
+  headerVersion := AV_VERSION_INT(
+      LIBAVCODEC_VERSION_MAJOR,
+      LIBAVCODEC_VERSION_MINOR,
+      LIBAVCODEC_VERSION_RELEASE);
+  if (libVersion <> headerVersion) then
+  begin
+    Log.LogError(Format('%s header (%s) and DLL (%s) versions do not match.',
+        ['libavcodec', hexVerToStr(headerVersion), hexVerToStr(libVersion)]));
+  end;
+
+  {$IF LIBAVFORMAT_VERSION >= 52020000} // 52.20.0
+  libVersion := avformat_version();
+  headerVersion := AV_VERSION_INT(
+      LIBAVFORMAT_VERSION_MAJOR,
+      LIBAVFORMAT_VERSION_MINOR,
+      LIBAVFORMAT_VERSION_RELEASE);
+  if (libVersion <> headerVersion) then
+  begin
+    Log.LogError(Format('%s header (%s) and DLL (%s) versions do not match.',
+        ['libavformat', hexVerToStr(headerVersion), hexVerToStr(libVersion)]));
+  end;
+  {$IFEND}
+
+  {$IF LIBAVUTIL_VERSION >= 49008000} // 49.8.0
+  libVersion := avutil_version();
+  headerVersion := AV_VERSION_INT(
+      LIBAVUTIL_VERSION_MAJOR,
+      LIBAVUTIL_VERSION_MINOR,
+      LIBAVUTIL_VERSION_RELEASE);
+  if (libVersion <> headerVersion) then
+  begin
+    Log.LogError(Format('%s header (%s) and DLL (%s) versions do not match.',
+        ['libavutil', hexVerToStr(headerVersion), hexVerToStr(libVersion)]));
+  end;
+  {$IFEND}
+  
+  {$IF LIBSWSCALE_VERSION >= 000006001} // 0.6.1
+  libVersion := swscale_version();
+  headerVersion := AV_VERSION_INT(
+      LIBSWSCALE_VERSION_MAJOR,
+      LIBSWSCALE_VERSION_MINOR,
+      LIBSWSCALE_VERSION_RELEASE);
+  if (libVersion <> headerVersion) then
+  begin
+    Log.LogError(Format('%s header (%s) and DLL (%s) versions do not match.',
+        ['libswscale', hexVerToStr(headerVersion), hexVerToStr(libVersion)]));
+  end;
+  {$IFEND}
+end;
+
+constructor TMediaCore_FFmpeg.Create();
+begin
+  inherited;
+
+  CheckVersions();
+  av_register_protocol(@UTF8FileProtocol);
+  AVCodecLock := SDL_CreateMutex();
+end;
+
+destructor TMediaCore_FFmpeg.Destroy();
+begin
+  SDL_DestroyMutex(AVCodecLock);
+  inherited;
+end;
+
+class function TMediaCore_FFmpeg.GetInstance(): TMediaCore_FFmpeg;
+begin
+  if (not Assigned(Instance)) then
+    Instance := TMediaCore_FFmpeg.Create();
+  Result := Instance;
+end;
+
+procedure TMediaCore_FFmpeg.LockAVCodec();
+begin
+  SDL_mutexP(AVCodecLock);
+end;
+
+procedure TMediaCore_FFmpeg.UnlockAVCodec();
+begin
+  SDL_mutexV(AVCodecLock);
+end;
+
+function TMediaCore_FFmpeg.GetErrorString(ErrorNum: integer): string;
+begin
+  case ErrorNum of
+    AVERROR_IO:           Result := 'AVERROR_IO';
+    AVERROR_NUMEXPECTED:  Result := 'AVERROR_NUMEXPECTED';
+    AVERROR_INVALIDDATA:  Result := 'AVERROR_INVALIDDATA';
+    AVERROR_NOMEM:        Result := 'AVERROR_NOMEM';
+    AVERROR_NOFMT:        Result := 'AVERROR_NOFMT';
+    AVERROR_NOTSUPP:      Result := 'AVERROR_NOTSUPP';
+    AVERROR_NOENT:        Result := 'AVERROR_NOENT';
+    AVERROR_PATCHWELCOME: Result := 'AVERROR_PATCHWELCOME';
+    else                  Result := 'AVERROR_#'+inttostr(ErrorNum);
+  end;
+end;
+
+{
+  @param(FormatCtx is a PAVFormatContext returned from av_open_input_file )
+  @param(FirstVideoStream is an OUT value of type integer, this is the index of the video stream)
+  @param(FirstAudioStream is an OUT value of type integer, this is the index of the audio stream)
+  @returns(@true on success, @false otherwise)
+}
+function TMediaCore_FFmpeg.FindStreamIDs(FormatCtx: PAVFormatContext; out FirstVideoStream, FirstAudioStream: integer): boolean;
+var
+  i: integer;
+  Stream: PAVStream;
+begin
+  // find the first video stream
+  FirstAudioStream := -1;
+  FirstVideoStream := -1;
+
+  for i := 0 to FormatCtx.nb_streams-1 do
+  begin
+    Stream := FormatCtx.streams[i];
+
+{$IF LIBAVCODEC_VERSION < 52064000} // < 52.64.0
+    if (Stream.codec.codec_type = CODEC_TYPE_VIDEO) and
+       (FirstVideoStream < 0) then
+    begin
+      FirstVideoStream := i;
+    end;
+
+    if (Stream.codec.codec_type = CODEC_TYPE_AUDIO) and
+       (FirstAudioStream < 0) then
+    begin
+      FirstAudioStream := i;
+    end;
+  end;
+{$ELSE}
+    if (Stream.codec.codec_type = AVMEDIA_TYPE_VIDEO) and
+       (FirstVideoStream < 0) then
+    begin
+      FirstVideoStream := i;
+    end;
+
+    if (Stream.codec.codec_type = AVMEDIA_TYPE_AUDIO) and
+       (FirstAudioStream < 0) then
+    begin
+      FirstAudioStream := i;
+    end;
+  end;
+{$IFEND}
+
+  // return true if either an audio- or video-stream was found
+  Result := (FirstAudioStream > -1) or
+            (FirstVideoStream > -1) ;
+end;
+
+function TMediaCore_FFmpeg.FindAudioStreamIndex(FormatCtx: PAVFormatContext): integer;
+var
+  i: integer;
+  StreamIndex: integer;
+  Stream: PAVStream;
+begin
+  // find the first audio stream
+  StreamIndex := -1;
+
+  for i := 0 to FormatCtx^.nb_streams-1 do
+  begin
+    Stream := FormatCtx^.streams[i];
+
+{$IF LIBAVCODEC_VERSION < 52064000} // < 52.64.0
+    if (Stream.codec^.codec_type = CODEC_TYPE_AUDIO) then
+{$ELSE}
+    if (Stream.codec^.codec_type = AVMEDIA_TYPE_AUDIO) then
+{$IFEND}
+    begin
+      StreamIndex := i;
+      Break;
+    end;
+  end;
+
+  Result := StreamIndex;
+end;
+
+function TMediaCore_FFmpeg.ConvertFFmpegToAudioFormat(FFmpegFormat: TSampleFormat; out Format: TAudioSampleFormat): boolean;
+begin
+  case FFmpegFormat of
+    SAMPLE_FMT_U8:  Format := asfU8;
+    SAMPLE_FMT_S16: Format := asfS16;
+    SAMPLE_FMT_S32: Format := asfS32;
+    SAMPLE_FMT_FLT: Format := asfFloat;
+    SAMPLE_FMT_DBL: Format := asfDouble;
+    else begin
+      Result := false;
+      Exit;
+    end;
+  end;
+  Result := true;
+end;
+
+
+{**
+ * UTF-8 Filename wrapper based on:
+ * http://www.mail-archive.com/libav-user@mplayerhq.hu/msg02460.html
+ *}
+
+function FFmpegStreamOpen(h: PURLContext; filename: PChar; flags: cint): cint; cdecl;
+var
+  Stream: TStream;
+  Mode: word;
+  ProtPrefix: string;
+  FilePath: IPath;
+begin
+  // check for protocol prefix ('ufile:') and strip it
+  ProtPrefix := Format('%s:', [UTF8FileProtocol.name]);
+  if (StrLComp(filename, PChar(ProtPrefix), Length(ProtPrefix)) = 0) then
+  begin
+    Inc(filename, Length(ProtPrefix));
+  end;
+
+  FilePath := Path(filename);
+
+  if ((flags and URL_RDWR) <> 0) then
+    Mode := fmCreate
+  else if ((flags and URL_WRONLY) <> 0) then
+    Mode := fmCreate // TODO: fmCreate is Read+Write -> reopen with fmOpenWrite
+  else
+    Mode := fmOpenRead or fmShareDenyWrite;
+
+  Result := 0;
+
+  try
+    Stream := TBinaryFileStream.Create(FilePath, Mode);
+    h.priv_data := Stream;
+  except
+    Result := AVERROR_NOENT;
+  end;
+end;
+
+function FFmpegStreamRead(h: PURLContext; buf: PByteArray; size: cint): cint; cdecl;
+var
+  Stream: TStream;
+begin
+  Stream := TStream(h.priv_data);
+  if (Stream = nil) then
+    raise EInvalidContainer.Create('FFmpegStreamRead on nil');
+  try
+    Result := Stream.Read(buf[0], size);
+  except
+    Result := -1;
+  end;
+end;
+
+function FFmpegStreamWrite(h: PURLContext; buf: PByteArray; size: cint): cint; cdecl;
+var
+  Stream: TStream;
+begin
+  Stream := TStream(h.priv_data);
+  if (Stream = nil) then
+    raise EInvalidContainer.Create('FFmpegStreamWrite on nil');
+  try
+    Result := Stream.Write(buf[0], size);
+  except
+    Result := -1;
+  end;
+end;
+
+function FFmpegStreamSeek(h: PURLContext; pos: int64; whence: cint): int64; cdecl;
+var
+  Stream : TStream;
+  Origin : TSeekOrigin;
+begin
+  Stream := TStream(h.priv_data);
+  if (Stream = nil) then
+    raise EInvalidContainer.Create('FFmpegStreamSeek on nil');
+  case whence of
+    0 {SEEK_SET}: Origin := soBeginning;
+    1 {SEEK_CUR}: Origin := soCurrent;
+    2 {SEEK_END}: Origin := soEnd;
+    AVSEEK_SIZE: begin
+      Result := Stream.Size;
+      Exit;
+    end
+  else
+    Origin := soBeginning;
+  end;
+  Result := Stream.Seek(pos, Origin);
+end;
+
+function FFmpegStreamClose(h: PURLContext): cint; cdecl;
+var
+  Stream : TStream;
+begin
+  Stream := TStream(h.priv_data);
+  Stream.Free;
+  Result := 0;
+end;
+
+
+{ TPacketQueue }
+
+constructor TPacketQueue.Create();
+begin
+  inherited;
+
+  FirstListEntry := nil;
+  LastListEntry  := nil;
+  PacketCount := 0;
+  Size := 0;
+
+  Mutex := SDL_CreateMutex();
+  Condition := SDL_CreateCond();
+end;
+
+destructor TPacketQueue.Destroy();
+begin
+  Flush();
+  SDL_DestroyMutex(Mutex);
+  SDL_DestroyCond(Condition);
+  inherited;
+end;
+
+procedure TPacketQueue.Abort();
+begin
+  SDL_LockMutex(Mutex);
+
+  AbortRequest := true;
+
+  SDL_CondBroadcast(Condition);
+  SDL_UnlockMutex(Mutex);
+end;
+
+function TPacketQueue.IsAborted(): boolean;
+begin
+  SDL_LockMutex(Mutex);
+  Result := AbortRequest;
+  SDL_UnlockMutex(Mutex);
+end;
+
+function TPacketQueue.Put(Packet : PAVPacket): integer;
+var
+  CurrentListEntry : PAVPacketList;
+begin
+  Result := -1;
+
+  if (Packet = nil) then
+    Exit;
+
+  if (PChar(Packet^.data) <> STATUS_PACKET) then
+  begin
+    if (av_dup_packet(Packet) < 0) then
+      Exit;
+  end;
+
+  CurrentListEntry := av_malloc(SizeOf(TAVPacketList));
+  if (CurrentListEntry = nil) then
+    Exit;
+
+  CurrentListEntry^.pkt  := Packet^;
+  CurrentListEntry^.next := nil;
+
+  SDL_LockMutex(Mutex);
+  try
+    if (LastListEntry = nil) then
+      FirstListEntry := CurrentListEntry
+    else
+      LastListEntry^.next := CurrentListEntry;
+
+    LastListEntry := CurrentListEntry;
+    Inc(PacketCount);
+
+    Size := Size + CurrentListEntry^.pkt.size;
+    SDL_CondSignal(Condition);
+  finally
+    SDL_UnlockMutex(Mutex);
+  end;
+
+  Result := 0;
+end;
+
+(**
+ * Adds a status packet (EOF, Flush, etc.) to the end of the queue.
+ * StatusInfo can be used to pass additional information to the decoder.
+ * Only assign nil or a valid pointer to data allocated with Getmem() to
+ * StatusInfo because the pointer will be disposed with Freemem() on a call
+ * to Flush(). If the packet is removed from the queue it is the decoder's
+ * responsibility to free the StatusInfo data with FreeStatusInfo().
+ *)
+function TPacketQueue.PutStatus(StatusFlag: integer; StatusInfo: Pointer): integer;
+var
+  TempPacket: PAVPacket;
+begin
+  // create temp. package
+  TempPacket := av_malloc(SizeOf(TAVPacket));
+  if (TempPacket = nil) then
+  begin
+    Result := -1;
+    Exit;
+  end;
+  // init package
+  av_init_packet(TempPacket^);
+  TempPacket^.data  := Pointer(STATUS_PACKET);
+  TempPacket^.flags := StatusFlag;
+  TempPacket^.priv  := StatusInfo;
+  // put a copy of the package into the queue
+  Result := Put(TempPacket);
+  // data has been copied -> delete temp. package
+  av_free(TempPacket);
+end;
+
+procedure TPacketQueue.FreeStatusInfo(var Packet: TAVPacket);
+begin
+  if (Packet.priv <> nil) then
+    FreeMem(Packet.priv);
+end;
+
+function TPacketQueue.GetStatusInfo(var Packet: TAVPacket): Pointer;
+begin
+  Result := Packet.priv;
+end;
+
+function TPacketQueue.Get(var Packet: TAVPacket; Blocking: boolean): integer;
+var
+  CurrentListEntry: PAVPacketList;
+const
+  WAIT_TIMEOUT = 10; // timeout in ms
+begin
+  Result := -1;
+
+  SDL_LockMutex(Mutex);
+  try
+    while (true) do
+    begin
+      if (AbortRequest) then
+        Exit;
+
+      CurrentListEntry := FirstListEntry;
+      if (CurrentListEntry <> nil) then
+      begin
+        FirstListEntry := CurrentListEntry^.next;
+        if (FirstListEntry = nil) then
+          LastListEntry := nil;
+        Dec(PacketCount);
+
+        Size := Size - CurrentListEntry^.pkt.size;
+        Packet := CurrentListEntry^.pkt;
+        av_free(CurrentListEntry);
+
+        Result := 1;
+        Break;
+      end
+      else if (not Blocking) then
+      begin
+        Result := 0;
+        Break;
+      end
+      else
+      begin
+        // block until a new package arrives,
+        // but do not wait till infinity to avoid deadlocks
+        if (SDL_CondWaitTimeout(Condition, Mutex, WAIT_TIMEOUT) = SDL_MUTEX_TIMEDOUT) then
+        begin
+          Result := 0;
+          Break;
+        end;
+      end;
+    end;
+  finally
+    SDL_UnlockMutex(Mutex);
+  end;
+end;
+
+function TPacketQueue.GetSize(): integer;
+begin
+  SDL_LockMutex(Mutex);
+  Result := Size;
+  SDL_UnlockMutex(Mutex);
+end;
+
+procedure TPacketQueue.Flush();
+var
+  CurrentListEntry, TempListEntry: PAVPacketList;
+begin
+  SDL_LockMutex(Mutex);
+
+  CurrentListEntry := FirstListEntry;
+  while(CurrentListEntry <> nil) do
+  begin
+    TempListEntry := CurrentListEntry^.next;
+    // free status data
+    if (PChar(CurrentListEntry^.pkt.data) = STATUS_PACKET) then
+      FreeStatusInfo(CurrentListEntry^.pkt);
+    // free packet data
+    av_free_packet(@CurrentListEntry^.pkt);
+    // Note: param must be a pointer to a pointer!
+    av_freep(@CurrentListEntry);
+    CurrentListEntry := TempListEntry;
+  end;
+  LastListEntry := nil;
+  FirstListEntry := nil;
+  PacketCount := 0;
+  Size := 0;
+
+  SDL_UnlockMutex(Mutex);
+end;
+
+end.
diff --git a/songmanagement/src/media/UMediaCore_SDL.pas b/songmanagement/src/media/UMediaCore_SDL.pas
new file mode 100644
index 00000000..74c75e16
--- /dev/null
+++ b/songmanagement/src/media/UMediaCore_SDL.pas
@@ -0,0 +1,63 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMediaCore_SDL;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMusic,
+  sdl;
+
+function ConvertAudioFormatToSDL(Format: TAudioSampleFormat; out SDLFormat: UInt16): boolean;
+
+implementation
+
+function ConvertAudioFormatToSDL(Format: TAudioSampleFormat; out SDLFormat: UInt16): boolean;
+begin
+  case Format of
+    asfU8:     SDLFormat := AUDIO_U8;
+    asfS8:     SDLFormat := AUDIO_S8;
+    asfU16LSB: SDLFormat := AUDIO_U16LSB;
+    asfS16LSB: SDLFormat := AUDIO_S16LSB;
+    asfU16MSB: SDLFormat := AUDIO_U16MSB;
+    asfS16MSB: SDLFormat := AUDIO_S16MSB;
+    asfU16:    SDLFormat := AUDIO_U16;
+    asfS16:    SDLFormat := AUDIO_S16;
+    else begin
+      Result := false;
+      Exit;
+    end;
+  end;
+  Result := true;
+end;
+
+end.
diff --git a/songmanagement/src/media/UMedia_dummy.pas b/songmanagement/src/media/UMedia_dummy.pas
new file mode 100644
index 00000000..46cbe6b8
--- /dev/null
+++ b/songmanagement/src/media/UMedia_dummy.pas
@@ -0,0 +1,492 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMedia_dummy;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+implementation
+
+uses
+  SysUtils,
+  math,
+  UTime,
+  UMusic,
+  UPath;
+
+type
+    TAudio_Dummy = class( TInterfacedObject, IAudioPlayback, IAudioInput )
+    private
+      DummyOutputDeviceList: TAudioOutputDeviceList;
+    public
+      constructor Create();
+      function GetName: string;
+
+      function Init(): boolean;
+      function Finalize(): boolean;
+
+      function Open(const aFileName: IPath): boolean; // true if succeed
+      procedure Close;
+
+      procedure Play;
+      procedure Pause;
+      procedure Stop;
+
+      procedure SetPosition(Time: real);
+      function  GetPosition: real;
+
+      procedure SetSyncSource(SyncSource: TSyncSource);
+
+      // IAudioInput
+      function InitializeRecord: boolean;
+      function FinalizeRecord: boolean;
+      procedure CaptureStart;
+      procedure CaptureStop;
+      procedure GetFFTData(var data: TFFTData);
+      function GetPCMData(var data: TPCMData): Cardinal;
+
+      // IAudioPlayback
+      function InitializePlayback: boolean;
+      function FinalizePlayback: boolean;
+
+      function GetOutputDeviceList(): TAudioOutputDeviceList;
+      procedure FadeIn(Time: real; TargetVolume: single);
+      procedure SetAppVolume(Volume: single);
+      procedure SetVolume(Volume: single);
+      procedure Rewind;
+
+      procedure SetLoop(Enabled: boolean);
+      function GetLoop(): boolean;
+
+      function Finished: boolean;
+      function Length: real;
+
+      function OpenSound(const Filename: IPath): TAudioPlaybackStream;
+      procedure CloseSound(var PlaybackStream: TAudioPlaybackStream);
+      procedure PlaySound(stream: TAudioPlaybackStream);
+      procedure StopSound(stream: TAudioPlaybackStream);
+
+      function CreateVoiceStream(Channel: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream;
+      procedure CloseVoiceStream(var VoiceStream: TAudioVoiceStream);
+    end;
+
+    TVideo_Dummy = class( TInterfacedObject, IVideo )
+    public
+      procedure Close;
+
+      procedure Play;
+      procedure Pause;
+      procedure Stop;
+
+      procedure SetLoop(Enable: boolean);
+      function GetLoop(): boolean;
+
+      procedure SetPosition(Time: real);
+      function GetPosition: real;
+
+      procedure SetScreen(Screen: integer);
+      function GetScreen(): integer;
+
+      procedure SetScreenPosition(X, Y, Z: double);
+      procedure GetScreenPosition(var X, Y, Z: double);
+
+      procedure  SetWidth(Width: double);
+      function GetWidth(): double;
+
+      procedure  SetHeight(Height: double);
+      function GetHeight(): double;
+
+      procedure SetFrameRange(Range: TRectCoords);
+      function GetFrameRange(): TRectCoords;
+
+      function GetFrameAspect(): real;
+
+      procedure SetAspectCorrection(AspectCorrection: TAspectCorrection);
+      function GetAspectCorrection(): TAspectCorrection;
+
+      procedure SetAlpha(Alpha: double);
+      function GetAlpha(): double;
+
+      procedure SetReflectionSpacing(Spacing: double);
+      function GetReflectionSpacing(): double;
+
+      procedure GetFrame(Time: Extended);
+      procedure Draw();
+      procedure DrawReflection();
+
+      property Screen: integer read GetScreen;
+      property Width: double read GetWidth write SetWidth;
+      property Height: double read GetHeight write SetWidth;
+      property Alpha: double read GetAlpha write SetAlpha;
+      property ReflectionSpacing: double read GetReflectionSpacing write SetReflectionSpacing;
+      property FrameAspect: real read GetFrameAspect;
+      property AspectCorrection: TAspectCorrection read GetAspectCorrection;
+      property Loop: boolean read GetLoop write SetLoop;
+      property Position: real read GetPosition write SetPosition;
+    end;
+
+    TVideoPlayback_Dummy = class( TInterfacedObject, IVideoPlayback, IVideoVisualization )
+    public
+      constructor Create();
+      function GetName: string;
+
+      function Init(): boolean;
+      function Finalize(): boolean;
+
+      function Open(const FileName: IPath): IVideo;
+    end;
+
+function  TAudio_Dummy.GetName: string;
+begin
+  Result := 'AudioDummy';
+end;
+
+constructor TAudio_Dummy.Create();
+begin
+  inherited;
+end;
+
+function TAudio_Dummy.Init(): boolean;
+begin
+  Result := true;
+end;
+
+function TAudio_Dummy.Finalize(): boolean;
+begin
+  Result := true;
+end;
+
+function TAudio_Dummy.Open(const aFileName : IPath): boolean; // true if succeed
+begin
+  Result := false;
+end;
+
+procedure TAudio_Dummy.Close;
+begin
+end;
+
+procedure TAudio_Dummy.Play;
+begin
+end;
+
+procedure TAudio_Dummy.Pause;
+begin
+end;
+
+procedure TAudio_Dummy.Stop;
+begin
+end;
+
+procedure TAudio_Dummy.SetPosition(Time: real);
+begin
+end;
+
+function  TAudio_Dummy.GetPosition: real;
+begin
+  Result := 0;
+end;
+
+procedure TAudio_Dummy.SetSyncSource(SyncSource: TSyncSource);
+begin
+end;
+
+// IAudioInput
+function TAudio_Dummy.InitializeRecord: boolean;
+begin
+  Result := true;
+end;
+
+function TAudio_Dummy.FinalizeRecord: boolean;
+begin
+  Result := true;
+end;
+
+procedure TAudio_Dummy.CaptureStart;
+begin
+end;
+
+procedure TAudio_Dummy.CaptureStop;
+begin
+end;
+
+procedure TAudio_Dummy.GetFFTData(var data: TFFTData);
+begin
+end;
+
+function  TAudio_Dummy.GetPCMData(var data: TPCMData): Cardinal;
+begin
+  Result := 0;
+end;
+
+// IAudioPlayback
+function TAudio_Dummy.InitializePlayback: boolean;
+begin
+  SetLength(DummyOutputDeviceList, 1);
+  DummyOutputDeviceList[0] := TAudioOutputDevice.Create();
+  DummyOutputDeviceList[0].Name := '[Dummy Device]';
+  Result := true;
+end;
+
+function TAudio_Dummy.FinalizePlayback: boolean;
+begin
+  Result := true;
+end;
+
+function TAudio_Dummy.GetOutputDeviceList(): TAudioOutputDeviceList;
+begin
+  Result := DummyOutputDeviceList;
+end;
+
+procedure TAudio_Dummy.SetAppVolume(Volume: single);
+begin
+end;
+
+procedure TAudio_Dummy.SetVolume(Volume: single);
+begin
+end;
+
+procedure TAudio_Dummy.SetLoop(Enabled: boolean);
+begin
+end;
+
+function TAudio_Dummy.GetLoop(): boolean;
+begin
+  Result := false;
+end;
+
+procedure TAudio_Dummy.FadeIn(Time: real; TargetVolume: single);
+begin
+end;
+
+procedure TAudio_Dummy.Rewind;
+begin
+end;
+
+function TAudio_Dummy.Finished: boolean;
+begin
+  Result := false;
+end;
+
+function TAudio_Dummy.Length: real;
+begin
+  Result := 60;
+end;
+
+function TAudio_Dummy.OpenSound(const Filename: IPath): TAudioPlaybackStream;
+begin
+ Result := nil;
+end;
+
+procedure TAudio_Dummy.CloseSound(var PlaybackStream: TAudioPlaybackStream);
+begin
+end;
+
+procedure TAudio_Dummy.PlaySound(stream: TAudioPlaybackStream);
+begin
+end;
+
+procedure TAudio_Dummy.StopSound(stream: TAudioPlaybackStream);
+begin
+end;
+
+function TAudio_Dummy.CreateVoiceStream(Channel: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream;
+begin
+  Result := nil;
+end;
+
+procedure TAudio_Dummy.CloseVoiceStream(var VoiceStream: TAudioVoiceStream);
+begin
+end;
+
+
+{ TVideoPlayback_Dummy }
+
+procedure TVideo_Dummy.Close;
+begin
+end;
+
+procedure TVideo_Dummy.Play;
+begin
+end;
+
+procedure TVideo_Dummy.Pause;
+begin
+end;
+
+procedure TVideo_Dummy.Stop;
+begin
+end;
+
+procedure TVideo_Dummy.SetLoop(Enable: boolean);
+begin
+end;
+
+function TVideo_Dummy.GetLoop(): boolean;
+begin
+  Result := false;
+end;
+
+procedure TVideo_Dummy.SetPosition(Time: real);
+begin
+end;
+
+function TVideo_Dummy.GetPosition: real;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_Dummy.SetScreen(Screen: integer);
+begin
+end;
+
+function TVideo_Dummy.GetScreen(): integer;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_Dummy.SetScreenPosition(X, Y, Z: double);
+begin
+end;
+
+procedure TVideo_Dummy.GetScreenPosition(var X, Y, Z: double);
+begin
+  X := 0;
+  Y := 0;
+  Z := 0;
+end;
+
+procedure TVideo_Dummy.SetWidth(Width: double);
+begin
+end;
+
+function TVideo_Dummy.GetWidth(): double;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_Dummy.SetHeight(Height: double);
+begin
+end;
+
+function TVideo_Dummy.GetHeight(): double;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_Dummy.SetFrameRange(Range: TRectCoords);
+begin
+end;
+
+function TVideo_Dummy.GetFrameRange(): TRectCoords;
+begin
+  Result.Left := 0;
+  Result.Right := 0;
+  Result.Upper := 0;
+  Result.Lower := 0;
+end;
+
+function TVideo_Dummy.GetFrameAspect(): real;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_Dummy.SetAspectCorrection(AspectCorrection: TAspectCorrection);
+begin
+end;
+
+function TVideo_Dummy.GetAspectCorrection(): TAspectCorrection;
+begin
+  Result := acoStretch;
+end;
+
+procedure TVideo_Dummy.SetAlpha(Alpha: double);
+begin
+end;
+
+function TVideo_Dummy.GetAlpha(): double;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_Dummy.SetReflectionSpacing(Spacing: double);
+begin
+end;
+
+function TVideo_Dummy.GetReflectionSpacing(): double;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_Dummy.GetFrame(Time: Extended);
+begin
+end;
+
+procedure TVideo_Dummy.Draw();
+begin
+end;
+
+procedure TVideo_Dummy.DrawReflection();
+begin
+end;
+
+
+{ TVideoPlayback_Dummy }
+
+constructor TVideoPlayback_Dummy.Create();
+begin
+end;
+
+function TVideoPlayback_Dummy.GetName: string;
+begin
+  Result := 'VideoDummy';
+end;
+
+function TVideoPlayback_Dummy.Init(): boolean;
+begin
+  Result := true;
+end;
+
+function TVideoPlayback_Dummy.Finalize(): boolean;
+begin
+  Result := true;
+end;
+
+function TVideoPlayback_Dummy.Open(const FileName: IPath): IVideo;
+begin
+  Result := TVideo_Dummy.Create;
+end;
+
+
+initialization
+  MediaManager.Add(TAudio_Dummy.Create);
+  MediaManager.Add(TVideoPlayback_Dummy.Create);
+
+end.
diff --git a/songmanagement/src/media/UVideo.pas b/songmanagement/src/media/UVideo.pas
new file mode 100644
index 00000000..add7bdc8
--- /dev/null
+++ b/songmanagement/src/media/UVideo.pas
@@ -0,0 +1,1436 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UVideo;
+
+{*
+ * based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/)
+ *}
+
+// uncomment if you want to see the debug stuff
+{.$define DebugDisplay}
+{.$define DebugFrames}
+{.$define VideoBenchmark}
+{.$define Info}
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+// use BGR-format for accelerated colorspace conversion with swscale
+{$IFDEF UseSWScale}
+  {$DEFINE PIXEL_FMT_BGR}
+{$ENDIF}
+
+implementation
+
+uses
+  SysUtils,
+  Math,
+  SDL,
+  avcodec,
+  avformat,
+  avutil,
+  avio,
+  rational,
+  {$IFDEF UseSWScale}
+  swscale,
+  {$ENDIF}
+  gl,
+  glu,
+  glext,
+  textgl,
+  UMediaCore_FFmpeg,
+  UCommon,
+  UConfig,
+  ULog,
+  UMusic,
+  UGraphicClasses,
+  UGraphic,
+  UPath;
+
+{$DEFINE PIXEL_FMT_BGR}
+
+const
+{$IFDEF PIXEL_FMT_BGR}
+  PIXEL_FMT_OPENGL = GL_BGR;
+  PIXEL_FMT_FFMPEG = PIX_FMT_BGR24;
+  PIXEL_FMT_SIZE   = 3;
+
+  // looks strange on linux:
+  //PIXEL_FMT_OPENGL = GL_RGBA;
+  //PIXEL_FMT_FFMPEG = PIX_FMT_BGR32;
+  //PIXEL_FMT_SIZE   = 4;
+{$ELSE}
+  // looks strange on linux:
+  PIXEL_FMT_OPENGL = GL_RGB;
+  PIXEL_FMT_FFMPEG = PIX_FMT_RGB24;
+  PIXEL_FMT_SIZE   = 3;
+{$ENDIF}
+
+  ReflectionH = 0.5; //reflection height (50%)
+
+type
+  IVideo_FFmpeg = interface (IVideo)
+  ['{E640E130-C8C0-4399-AF02-67A3569313AB}']
+    function Open(const FileName: IPath): boolean;
+  end;
+
+  TVideo_FFmpeg = class( TInterfacedObject, IVideo_FFmpeg )
+  private
+    fOpened: boolean;     //**< stream successfully opened
+    fPaused: boolean;     //**< stream paused
+    fEOF: boolean;        //**< end-of-file state
+
+    fLoop: boolean;       //**< looping enabled
+
+    fStream:        PAVStream;
+    fStreamIndex :  integer;
+    fFormatContext: PAVFormatContext;
+    fCodecContext:  PAVCodecContext;
+    fCodec:         PAVCodec;
+
+    fAVFrame:     PAVFrame;
+    fAVFrameRGB:  PAVFrame;
+
+    fFrameBuffer: PByte;  //**< stores a FFmpeg video frame
+    fFrameTex:    GLuint; //**< OpenGL texture for FrameBuffer
+    fFrameTexValid: boolean; //**< if true, fFrameTex contains the current frame
+    fTexWidth, fTexHeight: cardinal;
+
+    {$IFDEF UseSWScale}
+    fSwScaleContext: PSwsContext;
+    {$ENDIF}
+
+    fScreen:          integer; //actual screen to draw on
+
+    fPosX:    double;
+    fPosY:    double;
+    fPosZ:    double;
+    fWidth:   double;
+    fHeight:  double;
+
+    fFrameRange:        TRectCoords;
+
+    fAlpha:             double;
+    fReflectionSpacing: double;
+
+
+    fAspect: real;        //**< width/height ratio
+    fAspectCorrection: TAspectCorrection;
+
+    fFrameDuration: extended; //**< duration of a video frame in seconds (= 1/fps)
+    fFrameTime: extended; //**< video time position (absolute)
+    fLoopTime: extended;  //**< start time of the current loop
+
+    fPboEnabled: boolean;
+    fPboId:      GLuint;
+    procedure Reset();
+    function DecodeFrame(): boolean;
+    procedure SynchronizeTime(Frame: PAVFrame; var pts: double);
+
+    procedure GetVideoRect(var ScreenRect, TexRect: TRectCoords);
+    procedure DrawBorders(ScreenRect: TRectCoords);
+    procedure DrawBordersReflected(ScreenRect: TRectCoords; AlphaUpper, AlphaLower: double);
+
+    procedure ShowDebugInfo();
+
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function Open(const FileName: IPath): boolean;
+    procedure Close;
+
+    procedure Play;
+    procedure Pause;
+    procedure Stop;
+
+    procedure SetLoop(Enable: boolean);
+    function GetLoop(): boolean;
+
+    procedure SetPosition(Time: real);
+    function GetPosition: real;
+
+    procedure SetScreen(Screen: integer);
+    function GetScreen(): integer;
+
+    procedure SetScreenPosition(X, Y, Z: double);
+    procedure GetScreenPosition(var X, Y, Z: double);
+
+    procedure SetWidth(Width: double);
+    function GetWidth(): double;
+
+    procedure SetHeight(Height: double);
+    function GetHeight(): double;
+
+    {**
+     * Sub-image of the video frame to draw.
+     * This can be used for zooming or similar purposes.
+     *}
+     procedure SetFrameRange(Range: TRectCoords);
+     function GetFrameRange(): TRectCoords;
+
+     function GetFrameAspect(): real;
+
+     procedure SetAspectCorrection(AspectCorrection: TAspectCorrection);
+     function GetAspectCorrection(): TAspectCorrection;
+
+     procedure SetAlpha(Alpha: double);
+     function GetAlpha(): double;
+
+     procedure SetReflectionSpacing(Spacing: double);
+     function GetReflectionSpacing(): double;
+
+     procedure GetFrame(Time: Extended);
+     procedure Draw();
+     procedure DrawReflection();
+  end;
+
+  TVideoPlayback_FFmpeg = class( TInterfacedObject, IVideoPlayback )
+  private
+    fInitialized: boolean;
+
+  public
+    function GetName: String;
+
+    function Init(): boolean;
+    function Finalize: boolean;
+
+    function Open(const FileName : IPath): IVideo;
+  end;
+
+var
+  FFmpegCore: TMediaCore_FFmpeg;
+
+
+// These are called whenever we allocate a frame buffer.
+// We use this to store the global_pts in a frame at the time it is allocated.
+function PtsGetBuffer(CodecCtx: PAVCodecContext; Frame: PAVFrame): integer; cdecl;
+var
+  pts: Pint64;
+  VideoPktPts: Pint64;
+begin
+  Result := avcodec_default_get_buffer(CodecCtx, Frame);
+  VideoPktPts := CodecCtx^.opaque;
+  if (VideoPktPts <> nil) then
+  begin
+    // Note: we must copy the pts instead of passing a pointer, because the packet
+    // (and with it the pts) might change before a frame is returned by av_decode_video.
+    pts := av_malloc(sizeof(int64));
+    pts^ := VideoPktPts^;
+    Frame^.opaque := pts;
+  end;
+end;
+
+procedure PtsReleaseBuffer(CodecCtx: PAVCodecContext; Frame: PAVFrame); cdecl;
+begin
+  if (Frame <> nil) then
+    av_freep(@Frame^.opaque);
+  avcodec_default_release_buffer(CodecCtx, Frame);
+end;
+
+
+{*------------------------------------------------------------------------------
+ * TVideoPlayback_ffmpeg
+ *------------------------------------------------------------------------------}
+
+function  TVideoPlayback_FFmpeg.GetName: String;
+begin
+  result := 'FFmpeg_Video';
+end;
+
+function TVideoPlayback_FFmpeg.Init(): boolean;
+begin
+  Result := true;
+
+  if (fInitialized) then
+    Exit;
+  fInitialized := true;
+
+  FFmpegCore := TMediaCore_FFmpeg.GetInstance();
+
+  av_register_all();
+end;
+
+function TVideoPlayback_FFmpeg.Finalize(): boolean;
+begin
+  Result := true;
+end;
+
+function TVideoPlayback_FFmpeg.Open(const FileName : IPath): IVideo;
+var
+  Video: IVideo_FFmpeg;
+begin
+  Video := TVideo_FFmpeg.Create;
+  if Video.Open(FileName) then
+    Result := Video
+  else
+    Result := nil;
+end;
+
+
+{* TVideo_FFmpeg *}
+
+constructor TVideo_FFmpeg.Create;
+begin
+  glGenTextures(1, PGLuint(@fFrameTex));
+  Reset();
+end;
+
+destructor TVideo_FFmpeg.Destroy;
+begin
+  Close();
+  glDeleteTextures(1, PGLuint(@fFrameTex));
+end;
+
+function TVideo_FFmpeg.Open(const FileName : IPath): boolean;
+var
+  errnum: Integer;
+  glErr: GLenum;
+  AudioStreamIndex: integer;
+begin
+  Result := false;
+  Reset();
+
+  fPboEnabled := PboSupported;
+
+  // use custom 'ufile' protocol for UTF-8 support
+  errnum := av_open_input_file(fFormatContext, PAnsiChar('ufile:'+FileName.ToUTF8), nil, 0, nil);
+  if (errnum <> 0) then
+  begin
+    Log.LogError('Failed to open file "'+ FileName.ToNative +'" ('+FFmpegCore.GetErrorString(errnum)+')');
+    Exit;
+  end;
+
+  // update video info
+  if (av_find_stream_info(fFormatContext) < 0) then
+  begin
+    Log.LogError('No stream info found', 'TVideoPlayback_ffmpeg.Open');
+    Close();
+    Exit;
+  end;
+  Log.LogInfo('VideoStreamIndex : ' + inttostr(fStreamIndex), 'TVideoPlayback_ffmpeg.Open');
+
+  // find video stream
+  FFmpegCore.FindStreamIDs(fFormatContext, fStreamIndex, AudioStreamIndex);
+  if (fStreamIndex < 0) then
+  begin
+    Log.LogError('No video stream found', 'TVideoPlayback_ffmpeg.Open');
+    Close();
+    Exit;
+  end;
+
+  fStream := fFormatContext^.streams[fStreamIndex];
+  fCodecContext := fStream^.codec;
+
+  fCodec := avcodec_find_decoder(fCodecContext^.codec_id);
+  if (fCodec = nil) then
+  begin
+    Log.LogError('No matching codec found', 'TVideoPlayback_ffmpeg.Open');
+    Close();
+    Exit;
+  end;
+
+  // set debug options
+  fCodecContext^.debug_mv := 0;
+  fCodecContext^.debug := 0;
+
+  // detect bug-workarounds automatically
+  fCodecContext^.workaround_bugs := FF_BUG_AUTODETECT;
+  // error resilience strategy (careful/compliant/agressive/very_aggressive)
+  //fCodecContext^.error_resilience := FF_ER_CAREFUL; //FF_ER_COMPLIANT;
+  // allow non spec compliant speedup tricks.
+  //fCodecContext^.flags2 := fCodecContext^.flags2 or CODEC_FLAG2_FAST;
+
+  // Note: avcodec_open() and avcodec_close() are not thread-safe and will
+  // fail if called concurrently by different threads.
+  FFmpegCore.LockAVCodec();
+  try
+    errnum := avcodec_open(fCodecContext, fCodec);
+  finally
+    FFmpegCore.UnlockAVCodec();
+  end;
+  if (errnum < 0) then
+  begin
+    Log.LogError('No matching codec found', 'TVideoPlayback_ffmpeg.Open');
+    Close();
+    Exit;
+  end;
+
+  // register custom callbacks for pts-determination
+  fCodecContext^.get_buffer := PtsGetBuffer;
+  fCodecContext^.release_buffer := PtsReleaseBuffer;
+
+  {$ifdef DebugDisplay}
+  DebugWriteln('Found a matching Codec: '+ fCodecContext^.Codec.Name + sLineBreak +
+    sLineBreak +
+    '  Width = '+inttostr(fCodecContext^.width) +
+    ', Height='+inttostr(fCodecContext^.height) + sLineBreak +
+    '  Aspect    : '+inttostr(fCodecContext^.sample_aspect_ratio.num) + '/' +
+                     inttostr(fCodecContext^.sample_aspect_ratio.den) + sLineBreak +
+    '  Framerate : '+inttostr(fCodecContext^.time_base.num) + '/' +
+                     inttostr(fCodecContext^.time_base.den));
+  {$endif}
+
+  // allocate space for decoded frame and rgb frame
+  fAVFrame := avcodec_alloc_frame();
+  fAVFrameRGB := avcodec_alloc_frame();
+  fFrameBuffer := av_malloc(avpicture_get_size(PIXEL_FMT_FFMPEG,
+      fCodecContext^.width, fCodecContext^.height));
+
+  if ((fAVFrame = nil) or (fAVFrameRGB = nil) or (fFrameBuffer = nil)) then
+  begin
+    Log.LogError('Failed to allocate buffers', 'TVideoPlayback_ffmpeg.Open');
+    Close();
+    Exit;
+  end;
+
+  // TODO: pad data for OpenGL to GL_UNPACK_ALIGNMENT
+  // (otherwise video will be distorted if width/height is not a multiple of the alignment)
+  errnum := avpicture_fill(PAVPicture(fAVFrameRGB), fFrameBuffer, PIXEL_FMT_FFMPEG,
+      fCodecContext^.width, fCodecContext^.height);
+  if (errnum < 0) then
+  begin
+    Log.LogError('avpicture_fill failed: ' + FFmpegCore.GetErrorString(errnum), 'TVideoPlayback_ffmpeg.Open');
+    Close();
+    Exit;
+  end;
+
+  // calculate some information for video display
+  fAspect := av_q2d(fCodecContext^.sample_aspect_ratio);
+  if (fAspect = 0) then
+    fAspect := fCodecContext^.width /
+               fCodecContext^.height
+  else
+    fAspect := fAspect * fCodecContext^.width /
+                         fCodecContext^.height;
+
+  fFrameDuration := 1/av_q2d(fStream^.r_frame_rate);
+
+  // hack to get reasonable framerate (for divx and others)
+  if (fFrameDuration < 0.02) then // 0.02 <-> 50 fps
+  begin
+    fFrameDuration := av_q2d(fStream^.r_frame_rate);
+    while (fFrameDuration > 50) do
+      fFrameDuration := fFrameDuration/10;
+    fFrameDuration := 1/fFrameDuration;
+  end;
+
+  Log.LogInfo('Framerate: '+inttostr(floor(1/fFrameDuration))+'fps', 'TVideoPlayback_ffmpeg.Open');
+
+  {$IFDEF UseSWScale}
+  // if available get a SWScale-context -> faster than the deprecated img_convert().
+  // SWScale has accelerated support for PIX_FMT_RGB32/PIX_FMT_BGR24/PIX_FMT_BGR565/PIX_FMT_BGR555.
+  // Note: PIX_FMT_RGB32 is a BGR- and not an RGB-format (maybe a bug)!!!
+  // The BGR565-formats (GL_UNSIGNED_SHORT_5_6_5) is way too slow because of its
+  // bad OpenGL support. The BGR formats have MMX(2) implementations but no speed-up
+  // could be observed in comparison to the RGB versions.
+  fSwScaleContext := sws_getContext(
+      fCodecContext^.width, fCodecContext^.height,
+      fCodecContext^.pix_fmt,
+      fCodecContext^.width, fCodecContext^.height,
+      PIXEL_FMT_FFMPEG,
+      SWS_FAST_BILINEAR, nil, nil, nil);
+  if (fSwScaleContext = nil) then
+  begin
+    Log.LogError('Failed to get swscale context', 'TVideoPlayback_ffmpeg.Open');
+    Close();
+    Exit;
+  end;
+  {$ENDIF}
+
+  fTexWidth   := Round(Power(2, Ceil(Log2(fCodecContext^.width))));
+  fTexHeight  := Round(Power(2, Ceil(Log2(fCodecContext^.height))));
+
+  if (fPboEnabled) then
+  begin
+    glGetError();
+
+    glGenBuffersARB(1, @fPboId);
+    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, fPboId);
+    glBufferDataARB(
+        GL_PIXEL_UNPACK_BUFFER_ARB,
+        fCodecContext^.width * fCodecContext^.height * PIXEL_FMT_SIZE,
+        nil,
+        GL_STREAM_DRAW_ARB);
+    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+
+    glErr := glGetError();
+    if (glErr <> GL_NO_ERROR) then
+    begin
+      fPboEnabled := false;
+      Log.LogError('PBO initialization failed: ' + gluErrorString(glErr), 'TVideo_FFmpeg.Open');
+    end;
+  end;
+
+  // we retrieve a texture just once with glTexImage2D and update it with glTexSubImage2D later.
+  // Benefits: glTexSubImage2D is faster and supports non-power-of-two widths/height.
+  glBindTexture(GL_TEXTURE_2D, fFrameTex);
+  glTexImage2D(GL_TEXTURE_2D, 0, 3, fTexWidth, fTexHeight, 0,
+      PIXEL_FMT_OPENGL, GL_UNSIGNED_BYTE, nil);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+  fOpened := true;
+  Result := true;
+end;
+
+procedure TVideo_FFmpeg.Reset();
+begin
+  // close previously opened video
+  Close();
+
+  fOpened := False;
+  fPaused := False;
+  fFrameDuration := 0;
+  fFrameTime := 0;
+  fStream := nil;
+  fStreamIndex := -1;
+  fFrameTexValid := false;
+
+  fEOF := false;
+
+  fLoop := false;
+  fLoopTime := 0;
+
+  fPboId := 0;
+
+  fAspectCorrection := acoCrop;
+
+  fScreen := 1;
+
+  fPosX := 0;
+  fPosY := 0;
+  fPosZ := 0;
+  fWidth := RenderW;
+  fHeight := RenderH;
+
+  fFrameRange.Left := 0;
+  fFrameRange.Right := 1;
+  fFrameRange.Upper := 0;
+  fFrameRange.Lower := 1;
+
+  fAlpha := 1;
+  fReflectionSpacing := 0;
+end;
+
+procedure TVideo_FFmpeg.Close;
+begin
+  if (fFrameBuffer <> nil) then
+    av_free(fFrameBuffer);
+  if (fAVFrameRGB <> nil) then
+    av_free(fAVFrameRGB);
+  if (fAVFrame <> nil) then
+    av_free(fAVFrame);
+
+  fAVFrame     := nil;
+  fAVFrameRGB  := nil;
+  fFrameBuffer := nil;
+
+  if (fCodecContext <> nil) then
+  begin
+    // avcodec_close() is not thread-safe
+    FFmpegCore.LockAVCodec();
+    try
+      avcodec_close(fCodecContext);
+    finally
+      FFmpegCore.UnlockAVCodec();
+    end;
+  end;
+
+  if (fFormatContext <> nil) then
+    av_close_input_file(fFormatContext);
+
+  fCodecContext  := nil;
+  fFormatContext := nil;
+
+  if (fPboId <> 0) then
+    glDeleteBuffersARB(1, @fPboId);
+
+  fOpened := False;
+end;
+
+procedure TVideo_FFmpeg.SynchronizeTime(Frame: PAVFrame; var pts: double);
+var
+  FrameDelay: double;
+begin
+  if (pts <> 0) then
+  begin
+    // if we have pts, set video clock to it
+    fFrameTime := pts;
+  end else
+  begin
+    // if we aren't given a pts, set it to the clock
+    pts := fFrameTime;
+  end;
+  // update the video clock
+  FrameDelay := av_q2d(fCodecContext^.time_base);
+  // if we are repeating a frame, adjust clock accordingly
+  FrameDelay := FrameDelay + Frame^.repeat_pict * (FrameDelay * 0.5);
+  fFrameTime := fFrameTime + FrameDelay;
+end;
+
+{**
+ * Decode a new frame from the video stream.
+ * The decoded frame is stored in fAVFrame. fFrameTime is updated to the new frame's
+ * time.
+ * @param pts will be updated to the presentation time of the decoded frame.
+ * returns true if a frame could be decoded. False if an error or EOF occured.
+ *}
+function TVideo_FFmpeg.DecodeFrame(): boolean;
+var
+  FrameFinished: Integer;
+  VideoPktPts: int64;
+  pbIOCtx: PByteIOContext;
+  errnum: integer;
+  AVPacket: TAVPacket;
+  pts: double;
+begin
+  Result := false;
+  FrameFinished := 0;
+
+  if fEOF then
+    Exit;
+
+  // read packets until we have a finished frame (or there are no more packets)
+  while (FrameFinished = 0) do
+  begin
+    errnum := av_read_frame(fFormatContext, AVPacket);
+    if (errnum < 0) then
+    begin
+      // failed to read a frame, check reason
+
+      {$IF (LIBAVFORMAT_VERSION_MAJOR >= 52)}
+      pbIOCtx := fFormatContext^.pb;
+      {$ELSE}
+      pbIOCtx := @fFormatContext^.pb;
+      {$IFEND}
+
+      // check for end-of-file (EOF is not an error)
+      if (url_feof(pbIOCtx) <> 0) then
+      begin
+        fEOF := true;
+        Exit;
+      end;
+
+      // check for errors
+      if (url_ferror(pbIOCtx) <> 0) then
+      begin
+        Log.LogError('Video decoding file error', 'TVideoPlayback_FFmpeg.DecodeFrame');
+        Exit;
+      end;
+
+      // url_feof() does not detect an EOF for some mov-files (e.g. deluxe.mov)
+      // so we have to do it this way.
+      if ((fFormatContext^.file_size <> 0) and
+          (pbIOCtx^.pos >= fFormatContext^.file_size)) then
+      begin
+        fEOF := true;
+        Exit;
+      end;
+
+      // error occured, log and exit
+      Log.LogError('Video decoding error', 'TVideoPlayback_FFmpeg.DecodeFrame');
+      Exit;
+    end;
+
+    // if we got a packet from the video stream, then decode it
+    if (AVPacket.stream_index = fStreamIndex) then
+    begin
+      // save pts to be stored in pFrame in first call of PtsGetBuffer()
+      VideoPktPts := AVPacket.pts;
+      fCodecContext^.opaque := @VideoPktPts;
+
+      // decode packet
+      avcodec_decode_video(fCodecContext, fAVFrame,
+          frameFinished, AVPacket.data, AVPacket.size);
+
+      // reset opaque data
+      fCodecContext^.opaque := nil;
+
+      // update pts
+      if (AVPacket.dts <> AV_NOPTS_VALUE) then
+      begin
+        pts := AVPacket.dts;
+      end
+      else if ((fAVFrame^.opaque <> nil) and
+               (Pint64(fAVFrame^.opaque)^ <> AV_NOPTS_VALUE)) then
+      begin
+        pts := Pint64(fAVFrame^.opaque)^;
+      end
+      else
+      begin
+        pts := 0;
+      end;
+
+      if fStream^.start_time <> AV_NOPTS_VALUE then
+        pts := pts - fStream^.start_time;
+
+      pts := pts * av_q2d(fStream^.time_base);
+
+      // synchronize time on each complete frame
+      if (frameFinished <> 0) then
+        SynchronizeTime(fAVFrame, pts);
+    end;
+
+    // free the packet from av_read_frame
+    av_free_packet( @AVPacket );
+  end;
+
+  Result := true;
+end;
+
+procedure TVideo_FFmpeg.GetFrame(Time: Extended);
+var
+  errnum: Integer;
+  glErr: GLenum;
+  CurrentTime: Extended;
+  TimeDiff: Extended;
+  DropFrameCount: Integer;
+  i: Integer;
+  Success: boolean;
+  BufferPtr: PGLvoid;
+const
+  SKIP_FRAME_DIFF = 0.010; // start skipping if we are >= 10ms too late
+begin
+  if not fOpened then
+    Exit;
+
+  if fPaused then
+    Exit;
+
+  {*
+   * Synchronization - begin
+   *}
+
+  // requested stream position (relative to the last loop's start)
+  if (fLoop) then
+    CurrentTime := Time - fLoopTime
+  else
+    CurrentTime := Time;
+
+  // check if current texture still contains the active frame
+  if (fFrameTexValid) then
+  begin
+    // time since the last frame was returned
+    TimeDiff := CurrentTime - fFrameTime;
+
+    {$IFDEF DebugDisplay}
+    DebugWriteln('Time:      '+inttostr(floor(Time*1000)) + sLineBreak +
+                 'VideoTime: '+inttostr(floor(fFrameTime*1000)) + sLineBreak +
+                 'TimeBase:  '+inttostr(floor(fFrameDuration*1000)) + sLineBreak +
+                 'TimeDiff:  '+inttostr(floor(TimeDifference*1000)));
+    {$endif}
+
+    // check if time has reached the next frame
+    if (TimeDiff < fFrameDuration) then
+    begin
+      {$ifdef DebugFrames}
+      // frame delay debug display
+      GoldenRec.Spawn(200,15,1,16,0,-1,ColoredStar,$00ff00);
+      {$endif}
+
+      {$IFDEF DebugDisplay}
+      DebugWriteln('not getting new frame' + sLineBreak +
+          'Time:      '+inttostr(floor(Time*1000)) + sLineBreak +
+          'VideoTime: '+inttostr(floor(fFrameTime*1000)) + sLineBreak +
+          'TimeBase:  '+inttostr(floor(fFrameDuration*1000)) + sLineBreak +
+          'TimeDiff:  '+inttostr(floor(TimeDifference*1000)));
+      {$endif}
+
+      // we do not need a new frame now
+      Exit;
+    end;
+  end;
+
+  {$IFDEF VideoBenchmark}
+  Log.BenchmarkStart(15);
+  {$ENDIF}
+
+  // fetch new frame (updates fFrameTime)
+  Success := DecodeFrame();
+  TimeDiff := CurrentTime - fFrameTime;
+
+  // check if we have to skip frames
+  // Either if we are one frame behind or if the skip threshold has been reached.
+  // Do not skip if the difference is less than fFrameDuration as there is no next frame.
+  // Note: We assume that fFrameDuration is the length of one frame.
+  if (TimeDiff >= Max(fFrameDuration, SKIP_FRAME_DIFF)) then
+  begin
+    {$IFDEF DebugFrames}
+    //frame drop debug display
+    GoldenRec.Spawn(200,55,1,16,0,-1,ColoredStar,$ff0000);
+    {$ENDIF}
+    {$IFDEF DebugDisplay}
+    DebugWriteln('skipping frames' + sLineBreak +
+        'TimeBase:  '+inttostr(floor(fFrameDuration*1000)) + sLineBreak +
+        'TimeDiff:  '+inttostr(floor(TimeDifference*1000)));
+    {$endif}
+
+    // update video-time
+    DropFrameCount := Trunc(TimeDiff / fFrameDuration);
+    fFrameTime := fFrameTime + DropFrameCount*fFrameDuration;
+
+    // skip frames
+    for i := 1 to DropFrameCount do
+      Success := DecodeFrame();
+  end;
+
+  // check if we got an EOF or error
+  if (not Success) then
+  begin
+    if fLoop then
+    begin
+      // we have to loop, so rewind
+      SetPosition(0);
+      // record the start-time of the current loop, so we can
+      // determine the position in the stream (fFrameTime-fLoopTime) later.
+      fLoopTime := Time;
+    end;
+    Exit;
+  end;
+
+  {*
+   * Synchronization - end
+   *}
+
+  // TODO: support for pan&scan
+  //if (fAVFrame.pan_scan <> nil) then
+  //begin
+  //  Writeln(Format('PanScan: %d/%d', [fAVFrame.pan_scan.width, fAVFrame.pan_scan.height]));
+  //end;
+
+  // otherwise we convert the pixeldata from YUV to RGB
+  {$IFDEF UseSWScale}
+  errnum := sws_scale(fSwScaleContext, @fAVFrame.data, @fAVFrame.linesize,
+          0, fCodecContext^.Height,
+          @fAVFrameRGB.data, @fAVFrameRGB.linesize);
+  {$ELSE}
+  // img_convert from lib/ffmpeg/avcodec.pas is actually deprecated.
+  // If ./configure does not find SWScale then this gives the error
+  // that the identifier img_convert is not known or similar.
+  // I think this should be removed, but am not sure whether there should
+  // be some other replacement or a warning, Therefore, I leave it for now.
+  // April 2009, mischi
+  errnum := img_convert(PAVPicture(fAVFrameRGB), PIXEL_FMT_FFMPEG,
+            PAVPicture(fAVFrame), fCodecContext^.pix_fmt,
+            fCodecContext^.width, fCodecContext^.height);
+  {$ENDIF}
+
+  if (errnum < 0) then
+  begin
+    Log.LogError('Image conversion failed', 'TVideoPlayback_ffmpeg.GetFrame');
+    Exit;
+  end;
+
+  {$IFDEF VideoBenchmark}
+  Log.BenchmarkEnd(15);
+  Log.BenchmarkStart(16);
+  {$ENDIF}
+
+  // TODO: data is not padded, so we will need to tell OpenGL.
+  //   Or should we add padding with avpicture_fill? (check which one is faster)
+  //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+  // glTexEnvi with GL_REPLACE might give a small speed improvement
+  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+  if (not fPboEnabled) then
+  begin
+    glBindTexture(GL_TEXTURE_2D, fFrameTex);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+        fCodecContext^.width, fCodecContext^.height,
+        PIXEL_FMT_OPENGL, GL_UNSIGNED_BYTE, fAVFrameRGB^.data[0]);
+  end
+  else // fPboEnabled
+  begin
+    glGetError();
+
+    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, fPboId);
+    glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB,
+        fCodecContext^.height * fCodecContext^.width * PIXEL_FMT_SIZE,
+        nil,
+        GL_STREAM_DRAW_ARB);
+
+    bufferPtr := glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+    if(bufferPtr <> nil) then
+    begin
+      Move(fAVFrameRGB^.data[0]^, bufferPtr^,
+           fCodecContext^.height * fCodecContext^.width * PIXEL_FMT_SIZE);
+
+      // release pointer to mapping buffer
+      glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
+    end;
+
+    glBindTexture(GL_TEXTURE_2D, fFrameTex);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+        fCodecContext^.width, fCodecContext^.height,
+        PIXEL_FMT_OPENGL, GL_UNSIGNED_BYTE, nil);
+
+    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    glErr := glGetError();
+    if (glErr <> GL_NO_ERROR) then
+      Log.LogError('PBO texture stream error: ' + gluErrorString(glErr), 'TVideo_FFmpeg.GetFrame');
+  end;
+
+  // reset to default
+  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+  if (not fFrameTexValid) then
+    fFrameTexValid := true;
+
+  {$ifdef DebugFrames}
+  //frame decode debug display
+  GoldenRec.Spawn(200, 35, 1, 16, 0, -1, ColoredStar, $ffff00);
+  {$endif}
+
+  {$IFDEF VideoBenchmark}
+  Log.BenchmarkEnd(16);
+  Log.LogBenchmark('FFmpeg', 15);
+  Log.LogBenchmark('Texture', 16);
+  {$ENDIF}
+end;
+
+procedure TVideo_FFmpeg.GetVideoRect(var ScreenRect, TexRect: TRectCoords);
+var
+  ScreenAspect: double;  // aspect of screen resolution
+  ScaledVideoWidth, ScaledVideoHeight: double;
+
+begin
+  // Three aspects to take into account:
+  //  1. Screen/display resolution (e.g. 1920x1080 -> 16:9)
+  //  2. Render aspect (fWidth x fHeight -> variable)
+  //  3. Movie aspect (video frame aspect stored in fAspect)
+  ScreenAspect := fWidth*((ScreenW/Screens)/RenderW)/(fHeight*(ScreenH/RenderH));
+
+  case fAspectCorrection of
+    acoStretch: begin
+      ScaledVideoWidth  := fWidth;
+      ScaledVideoHeight := fHeight;
+    end;
+
+    acoCrop: begin
+      if (ScreenAspect >= fAspect) then
+      begin
+        ScaledVideoWidth  := fWidth;
+        ScaledVideoHeight := fHeight * ScreenAspect/fAspect;
+      end else
+      begin
+        ScaledVideoHeight := fHeight;
+        ScaledVideoWidth  := fWidth * fAspect/ScreenAspect;
+      end;
+    end;
+
+    acoLetterBox: begin
+      if (ScreenAspect <= fAspect) then
+      begin
+        ScaledVideoWidth  := fWidth;
+        ScaledVideoHeight := fHeight * ScreenAspect/fAspect;
+      end else
+      begin
+        ScaledVideoHeight := fHeight;
+        ScaledVideoWidth  := fWidth * fAspect/ScreenAspect;
+      end;
+    end else
+      raise Exception.Create('Unhandled aspect correction!');
+  end;
+
+  //center video
+  ScreenRect.Left  := (fWidth - ScaledVideoWidth) / 2 + fPosX;
+  ScreenRect.Right := ScreenRect.Left + ScaledVideoWidth;
+  ScreenRect.Upper := (fHeight - ScaledVideoHeight) / 2 + fPosY;
+  ScreenRect.Lower := ScreenRect.Upper + ScaledVideoHeight;
+
+  // texture contains right/lower (power-of-2) padding.
+  // Determine the texture coords of the video frame.
+  TexRect.Left  := (fCodecContext^.width / fTexWidth) * fFrameRange.Left;
+  TexRect.Right := (fCodecContext^.width / fTexWidth) * fFrameRange.Right;
+  TexRect.Upper := (fCodecContext^.height / fTexHeight) * fFrameRange.Upper;
+  TexRect.Lower := (fCodecContext^.height / fTexHeight) * fFrameRange.Lower;
+end;
+
+procedure TVideo_FFmpeg.DrawBorders(ScreenRect: TRectCoords);
+  procedure DrawRect(left, right, upper, lower: double);
+  begin
+    glColor4f(0, 0, 0, fAlpha);
+    glBegin(GL_QUADS);
+      glVertex3f(left, upper, fPosZ);
+      glVertex3f(right, upper, fPosZ);
+      glVertex3f(right, lower, fPosZ);
+      glVertex3f(left, lower, fPosZ);
+    glEnd;
+  end;
+begin
+  //upper border
+  if(ScreenRect.Upper > fPosY) then
+    DrawRect(fPosX, fPosX+fWidth, fPosY, ScreenRect.Upper);
+
+  //lower border
+  if(ScreenRect.Lower < fPosY+fHeight) then
+    DrawRect(fPosX, fPosX+fWidth, ScreenRect.Lower, fPosY+fHeight);
+
+  //left border
+  if(ScreenRect.Left > fPosX) then
+    DrawRect(fPosX, ScreenRect.Left, fPosY, fPosY+fHeight);
+
+  //right border
+  if(ScreenRect.Right < fPosX+fWidth) then
+    DrawRect(ScreenRect.Right, fPosX+fWidth, fPosY, fPosY+fHeight);
+end;
+
+procedure TVideo_FFmpeg.DrawBordersReflected(ScreenRect: TRectCoords; AlphaUpper, AlphaLower: double);
+var
+  rPosUpper, rPosLower: double;
+
+  procedure DrawRect(left, right, upper, lower: double);
+  var
+    AlphaTop: double;
+    AlphaBottom: double;
+
+  begin
+    AlphaTop := AlphaUpper+(AlphaLower-AlphaUpper)*(upper-rPosUpper)/(fHeight*ReflectionH);
+    AlphaBottom := AlphaLower+(AlphaUpper-AlphaLower)*(rPosLower-lower)/(fHeight*ReflectionH);
+
+    glBegin(GL_QUADS);
+      glColor4f(0, 0, 0, AlphaTop);
+      glVertex3f(left, upper, fPosZ);
+      glVertex3f(right, upper, fPosZ);
+
+      glColor4f(0, 0, 0, AlphaBottom);
+      glVertex3f(right, lower, fPosZ);
+      glVertex3f(left, lower, fPosZ);
+    glEnd;
+  end;
+begin
+  rPosUpper := fPosY+fHeight+fReflectionSpacing;
+  rPosLower := rPosUpper+fHeight*ReflectionH;
+
+  //upper border
+  if(ScreenRect.Upper > rPosUpper) then
+    DrawRect(fPosX, fPosX+fWidth, rPosUpper, ScreenRect.Upper);
+
+  //lower border
+  if(ScreenRect.Lower < rPosLower) then
+    DrawRect(fPosX, fPosX+fWidth, ScreenRect.Lower, rPosLower);
+
+  //left border
+  if(ScreenRect.Left > fPosX) then
+    DrawRect(fPosX, ScreenRect.Left, rPosUpper, rPosLower);
+
+  //right border
+  if(ScreenRect.Right < fPosX+fWidth) then
+    DrawRect(ScreenRect.Right, fPosX+fWidth, rPosUpper, rPosLower);
+end;
+
+
+procedure TVideo_FFmpeg.Draw();
+var
+  ScreenRect:   TRectCoords;
+  TexRect:      TRectCoords;
+  HeightFactor: double;
+  WidthFactor:  double;
+
+begin
+  // exit if there's nothing to draw
+  if (not fOpened) then
+    Exit;
+
+  {$IFDEF VideoBenchmark}
+  Log.BenchmarkStart(15);
+  {$ENDIF}
+
+  // get texture and screen positions
+  GetVideoRect(ScreenRect, TexRect);
+
+  WidthFactor := (ScreenW/Screens) / RenderW;
+  HeightFactor := ScreenH / RenderH;
+
+  glScissor(
+    round(fPosX*WidthFactor + (ScreenW/Screens)*(fScreen-1)),
+    round((RenderH-fPosY-fHeight)*HeightFactor),
+    round(fWidth*WidthFactor),
+    round(fHeight*HeightFactor)
+    );
+
+  glEnable(GL_SCISSOR_TEST);
+  glEnable(GL_BLEND);
+  glDepthRange(0, 10);
+  glDepthFunc(GL_LEQUAL);
+  glEnable(GL_DEPTH_TEST);
+
+  glEnable(GL_TEXTURE_2D);
+  glBindTexture(GL_TEXTURE_2D, fFrameTex);
+  glColor4f(1, 1, 1, fAlpha);
+  glBegin(GL_QUADS);
+    // upper-left coord
+    glTexCoord2f(TexRect.Left, TexRect.Upper);
+    glVertex3f(ScreenRect.Left, ScreenRect.Upper, fPosZ);
+    // lower-left coord
+    glTexCoord2f(TexRect.Left, TexRect.Lower);
+    glVertex3f(ScreenRect.Left, ScreenRect.Lower, fPosZ);
+    // lower-right coord
+    glTexCoord2f(TexRect.Right, TexRect.Lower);
+    glVertex3f(ScreenRect.Right, ScreenRect.Lower, fPosZ);
+    // upper-right coord
+    glTexCoord2f(TexRect.Right, TexRect.Upper);
+    glVertex3f(ScreenRect.Right, ScreenRect.Upper, fPosZ);
+  glEnd;
+
+  glDisable(GL_TEXTURE_2D);
+  glBindTexture(GL_TEXTURE_2D, 0);
+
+  //draw black borders
+  DrawBorders(ScreenRect);
+
+  glDisable(GL_DEPTH_TEST);
+  glDisable(GL_BLEND);
+  glDisable(GL_SCISSOR_TEST);
+
+  {$IFDEF VideoBenchmark}
+  Log.BenchmarkEnd(15);
+  Log.LogBenchmark('Draw', 15);
+  {$ENDIF}
+
+  {$IF Defined(Info) or Defined(DebugFrames)}
+  ShowDebugInfo();
+  {$IFEND}
+end;
+
+procedure TVideo_FFmpeg.DrawReflection();
+var
+  ScreenRect:   TRectCoords;
+  TexRect:      TRectCoords;
+  HeightFactor: double;
+  WidthFactor:  double;
+
+  AlphaTop:     double;
+  AlphaBottom:  double;
+
+  AlphaUpper:   double;
+  AlphaLower:   double;
+
+begin
+  // exit if there's nothing to draw
+  if (not fOpened) then
+    Exit;
+
+  // get texture and screen positions
+  GetVideoRect(ScreenRect, TexRect);
+
+  WidthFactor := (ScreenW/Screens) / RenderW;
+  HeightFactor := ScreenH / RenderH;
+
+  glScissor(
+    round(fPosX*WidthFactor + (ScreenW/Screens)*(fScreen-1)),
+    round((RenderH-fPosY-fHeight-fReflectionSpacing-fHeight*ReflectionH)*HeightFactor),
+    round(fWidth*WidthFactor),
+    round(fHeight*HeightFactor*ReflectionH)
+    );
+
+  glEnable(GL_SCISSOR_TEST);
+  glEnable(GL_BLEND);
+  glDepthRange(0, 10);
+  glDepthFunc(GL_LEQUAL);
+  glEnable(GL_DEPTH_TEST);
+
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_TEXTURE_2D);
+  glBindTexture(GL_TEXTURE_2D, fFrameTex);
+
+  //calculate new ScreenRect coordinates for Reflection
+  ScreenRect.Lower := fPosY + fHeight + fReflectionSpacing
+    + (ScreenRect.Upper-fPosY) + (ScreenRect.Lower-ScreenRect.Upper)*ReflectionH;
+  ScreenRect.Upper := fPosY + fHeight + fReflectionSpacing
+    + (ScreenRect.Upper-fPosY);
+
+  AlphaUpper := fAlpha-0.3;
+  AlphaLower := 0;
+
+  AlphaTop := AlphaUpper-(AlphaLower-AlphaUpper)*
+    (ScreenRect.Upper-fPosY-fHeight-fReflectionSpacing)/fHeight;
+  AlphaBottom := AlphaLower+(AlphaUpper-AlphaLower)*
+    (fPosY+fHeight+fReflectionSpacing+fHeight*ReflectionH-ScreenRect.Lower)/fHeight;
+
+  glBegin(GL_QUADS);
+    //Top Left
+    glColor4f(1, 1, 1, AlphaTop);
+    glTexCoord2f(TexRect.Left, TexRect.Lower);
+    glVertex3f(ScreenRect.Left, ScreenRect.Upper, fPosZ);
+
+    //Bottom Left
+    glColor4f(1, 1, 1, AlphaBottom);
+    glTexCoord2f(TexRect.Left, (TexRect.Lower-TexRect.Upper)*(1-ReflectionH));
+    glVertex3f(ScreenRect.Left, ScreenRect.Lower, fPosZ);
+
+    //Bottom Right
+    glColor4f(1, 1, 1, AlphaBottom);
+    glTexCoord2f(TexRect.Right, (TexRect.Lower-TexRect.Upper)*(1-ReflectionH));
+    glVertex3f(ScreenRect.Right, ScreenRect.Lower, fPosZ);
+
+    //Top Right
+    glColor4f(1, 1, 1, AlphaTop);
+    glTexCoord2f(TexRect.Right, TexRect.Lower);
+    glVertex3f(ScreenRect.Right, ScreenRect.Upper, fPosZ);
+  glEnd;
+
+  glDisable(GL_TEXTURE_2D);
+  glBindTexture(GL_TEXTURE_2D, 0);
+
+  //draw black borders
+  DrawBordersReflected(ScreenRect, AlphaUpper, AlphaLower);
+
+  glDisable(GL_DEPTH_TEST);
+  glDisable(GL_BLEND);
+  glDisable(GL_SCISSOR_TEST);
+end;
+
+procedure TVideo_FFmpeg.ShowDebugInfo();
+begin
+  {$IFDEF Info}
+  if (fFrameTime+fFrameDuration < 0) then
+  begin
+    glColor4f(0.7, 1, 0.3, 1);
+    SetFontStyle (1);
+    SetFontItalic(False);
+    SetFontSize(27);
+    SetFontPos (300, 0);
+    glPrint('Delay due to negative VideoGap');
+    glColor4f(1, 1, 1, 1);
+  end;
+  {$ENDIF}
+
+  {$IFDEF DebugFrames}
+    glColor4f(0, 0, 0, 0.2);
+    glbegin(GL_QUADS);
+      glVertex2f(0, 0);
+      glVertex2f(0, 70);
+      glVertex2f(250, 70);
+      glVertex2f(250, 0);
+    glEnd;
+
+    glColor4f(1, 1, 1, 1);
+    SetFontStyle (1);
+    SetFontItalic(False);
+    SetFontSize(27);
+    SetFontPos (5, 0);
+    glPrint('delaying frame');
+    SetFontPos (5, 20);
+    glPrint('fetching frame');
+    SetFontPos (5, 40);
+    glPrint('dropping frame');
+  {$ENDIF}
+end;
+
+procedure TVideo_FFmpeg.Play;
+begin
+end;
+
+procedure TVideo_FFmpeg.Pause;
+begin
+  fPaused := not fPaused;
+end;
+
+procedure TVideo_FFmpeg.Stop;
+begin
+end;
+
+procedure TVideo_FFmpeg.SetLoop(Enable: boolean);
+begin
+  fLoop := Enable;
+  fLoopTime := 0;
+end;
+
+function TVideo_FFmpeg.GetLoop(): boolean;
+begin
+  Result := fLoop;
+end;
+
+{**
+ * Sets the stream's position.
+ * The stream is set to the first keyframe with timestamp <= Time.
+ * Note that fFrameTime is set to Time no matter if the actual position seeked to is
+ * at Time or the time of a preceding keyframe. fFrameTime will be updated to the
+ * actual frame time when GetFrame() is called the next time.
+ * @param Time new position in seconds
+ *}
+procedure TVideo_FFmpeg.SetPosition(Time: real);
+var
+  SeekFlags: integer;
+begin
+  if not fOpened then
+    Exit;
+
+  if (Time < 0) then
+    Time := 0;
+
+  // TODO: handle fLoop-times
+  //Time := Time mod VideoDuration;
+
+  // Do not use the AVSEEK_FLAG_ANY here. It will seek to any frame, even
+  // non keyframes (P-/B-frames). It will produce corrupted video frames as
+  // FFmpeg does not use the information of the preceding I-frame.
+  // The picture might be gray or green until the next keyframe occurs.
+  // Instead seek the first keyframe smaller than the requested time
+  // (AVSEEK_FLAG_BACKWARD). As this can be some seconds earlier than the
+  // requested time, let the sync in GetFrame() do its job.
+  SeekFlags := AVSEEK_FLAG_BACKWARD;
+
+  fFrameTime := Time;
+  fEOF := false;
+  fFrameTexValid := false;
+
+  if (av_seek_frame(fFormatContext,
+     fStreamIndex,
+     Round(Time / av_q2d(fStream^.time_base)),
+     SeekFlags) < 0) then
+  begin
+    Log.LogError('av_seek_frame() failed', 'TVideoPlayback_ffmpeg.SetPosition');
+    Exit;
+  end;
+
+  avcodec_flush_buffers(fCodecContext);
+end;
+
+function  TVideo_FFmpeg.GetPosition: real;
+begin
+  Result := fFrameTime;
+end;
+
+procedure TVideo_FFmpeg.SetScreen(Screen: integer);
+begin
+  fScreen := Screen;
+end;
+
+function TVideo_FFmpeg.GetScreen(): integer;
+begin
+  Result := fScreen;
+end;
+
+
+procedure TVideo_FFmpeg.SetScreenPosition(X, Y, Z: double);
+begin
+  fPosX := X;
+  fPosY := Y;
+  fPosZ := Z;
+end;
+
+procedure TVideo_FFmpeg.GetScreenPosition(var X, Y, Z: double);
+begin
+  X := fPosX;
+  Y := fPosY;
+  Z := fPosZ;
+end;
+
+
+procedure TVideo_FFmpeg.SetWidth(Width: double);
+begin
+  fWidth := Width;
+end;
+
+function TVideo_FFmpeg.GetWidth(): double;
+begin
+  Result := fWidth;
+end;
+
+
+procedure TVideo_FFmpeg.SetHeight(Height: double);
+begin
+  fHeight := Height;
+end;
+
+function TVideo_FFmpeg.GetHeight(): double;
+begin
+  Result := fHeight;
+end;
+
+
+procedure TVideo_FFmpeg.SetFrameRange(Range: TRectCoords);
+begin
+  fFrameRange := Range;
+end;
+
+function TVideo_FFmpeg.GetFrameRange(): TRectCoords;
+begin
+  Result := fFrameRange;
+end;
+
+
+function TVideo_FFmpeg.GetFrameAspect(): real;
+begin
+  Result := fAspect;
+end;
+
+
+procedure TVideo_FFmpeg.SetAspectCorrection(AspectCorrection: TAspectCorrection);
+begin
+  fAspectCorrection := AspectCorrection;
+end;
+
+function TVideo_FFmpeg.GetAspectCorrection(): TAspectCorrection;
+begin
+  Result := fAspectCorrection;
+end;
+
+
+
+procedure TVideo_FFmpeg.SetAlpha(Alpha: double);
+begin
+  fAlpha := Alpha;
+
+  if (fAlpha>1) then
+    fAlpha := 1;
+
+  if (fAlpha<0) then
+    fAlpha := 0;
+end;
+
+function TVideo_FFmpeg.GetAlpha(): double;
+begin
+  Result := fAlpha;
+end;
+
+
+procedure TVideo_FFmpeg.SetReflectionSpacing(Spacing: double);
+begin
+  fReflectionSpacing := Spacing;
+end;
+
+function TVideo_FFmpeg.GetReflectionSpacing(): double;
+begin
+  Result := fReflectionSpacing;
+end;
+
+
+initialization
+  MediaManager.Add(TVideoPlayback_FFmpeg.Create);
+
+end.
diff --git a/songmanagement/src/media/UVisualizer.pas b/songmanagement/src/media/UVisualizer.pas
new file mode 100644
index 00000000..1cdc3500
--- /dev/null
+++ b/songmanagement/src/media/UVisualizer.pas
@@ -0,0 +1,685 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UVisualizer;
+
+(* TODO:
+ *   - fix video/visualizer switching
+ *   - use GL_EXT_framebuffer_object for rendering to a separate framebuffer,
+ *     this will prevent plugins from messing up our render-context
+ *     (-> no stack corruption anymore, no need for Save/RestoreOpenGLState()).
+ *   - create a generic (C-compatible) interface for visualization plugins
+ *   - create a visualization plugin manager
+ *   - write a plugin for projectM in C/C++ (so we need no wrapper anymore)
+ *)
+
+{* Note:
+ * It would be easier to create a seperate Render-Context (RC) for projectM
+ * and switch to it when necessary. This can be achieved by pbuffers
+ * (slow and platform specific) or the OpenGL FramebufferObject (FBO) extension
+ * (fast and plattform-independent but not supported by older graphic-cards/drivers).
+ *
+ * See http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt
+ *
+ * To support as many cards as possible we will stick to the current dirty
+ * solution for now even if it is a pain to save/restore projectM's state due
+ * to bugs etc.
+ *
+ * This also restricts us to projectM. As other plug-ins might have different
+ * needs and bugs concerning the OpenGL state, USDX's state would probably be
+ * corrupted after the plug-in finshed drawing.
+ *}
+
+interface
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+{$ENDIF}
+
+{$I switches.inc}
+
+{.$DEFINE UseTexture}
+
+uses
+  SDL,
+  UGraphicClasses,
+  textgl,
+  math,
+  gl,
+  {$IFDEF UseTexture}
+  glu,
+  {$ENDIF}
+  SysUtils,
+  UIni,
+  projectM,
+  UMusic;
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UConfig,
+  UPath,
+  ULog;
+
+{$IF PROJECTM_VERSION < 1000000} // < 1.0
+// Initialization data used on projectM 0.9x creation.
+// Since projectM 1.0 this data is passed via the config-file.
+const
+  meshX = 32;
+  meshY = 24;
+  fps   = 30;
+  textureSize = 512;
+{$IFEND}
+
+type
+  TProjectMState = ( pmPlay, pmStop, pmPause );
+
+type
+  TGLMatrix = array[0..3, 0..3] of GLdouble;
+  TGLMatrixStack = array of TGLMatrix;
+
+type
+  TVideo_ProjectM = class( TInterfacedObject, IVideo )
+    private
+      fPm: TProjectM;
+      fProjectMPath : string;
+
+      fState: TProjectMState;
+
+      fScreen:  integer;
+
+      fVisualTex: GLuint;
+      fPCMData: TPCMData;
+      fRndPCMcount: integer;
+
+      fModelviewMatrixStack: TGLMatrixStack;
+      fProjectionMatrixStack: TGLMatrixStack;
+      fTextureMatrixStack:  TGLMatrixStack;
+
+      procedure InitProjectM;
+
+      function  GetRandomPCMData(var Data: TPCMData): Cardinal;
+
+      function GetMatrixStackDepth(MatrixMode: GLenum): GLint;
+      procedure SaveMatrixStack(MatrixMode: GLenum; var MatrixStack: TGLMatrixStack);
+      procedure RestoreMatrixStack(MatrixMode: GLenum; var MatrixStack: TGLMatrixStack);
+      procedure SaveOpenGLState();
+      procedure RestoreOpenGLState();
+
+    public
+      constructor Create;
+      destructor Destroy; override;
+
+      procedure Close;
+
+      procedure Play;
+      procedure Pause;
+      procedure Stop;
+
+      procedure SetPosition(Time: real);
+      function GetPosition: real;
+
+      procedure SetLoop(Enable: boolean);
+      function GetLoop(): boolean;
+
+      procedure SetScreen(Screen: integer);
+      function GetScreen(): integer;
+
+      procedure SetScreenPosition(X, Y, Z: double);
+      procedure GetScreenPosition(var X, Y, Z: double);
+
+      procedure  SetWidth(Width: double);
+      function GetWidth(): double;
+
+      procedure  SetHeight(Height: double);
+      function GetHeight(): double;
+
+      procedure SetFrameRange(Range: TRectCoords);
+      function GetFrameRange(): TRectCoords;
+
+      function GetFrameAspect(): real;
+
+      procedure SetAspectCorrection(AspectCorrection: TAspectCorrection);
+      function GetAspectCorrection(): TAspectCorrection;
+              
+      procedure SetAlpha(Alpha: double);
+      function GetAlpha(): double;
+
+      procedure SetReflectionSpacing(Spacing: double);
+      function GetReflectionSpacing(): double;
+
+      procedure GetFrame(Time: Extended);
+      procedure Draw();
+      procedure DrawReflection();
+  end;
+
+  TVideoPlayback_ProjectM = class( TInterfacedObject, IVideoVisualization )
+    private
+      fInitialized: boolean;
+
+    public
+      function GetName: String;
+
+      function Init(): boolean;
+      function Finalize(): boolean;
+
+      function Open(const aFileName: IPath): IVideo;
+  end;
+
+
+{ TVideoPlayback_ProjectM }
+
+function  TVideoPlayback_ProjectM.GetName: String;
+begin
+  Result := 'ProjectM';
+end;
+
+function TVideoPlayback_ProjectM.Init(): boolean;
+begin
+  Result := true;
+  if (fInitialized) then
+    Exit;
+  fInitialized := true;
+end;
+
+function TVideoPlayback_ProjectM.Finalize(): boolean;
+begin
+  Result := true;
+end;
+
+function TVideoPlayback_ProjectM.Open(const aFileName: IPath): IVideo;
+begin
+  Result := TVideo_ProjectM.Create;
+end;
+
+
+{ TVideo_ProjectM }
+
+constructor TVideo_ProjectM.Create;
+begin
+  fRndPCMcount := 0;
+
+  fProjectMPath := ProjectM_DataDir + PathDelim;
+
+  fState := pmStop;
+
+  {$IFDEF UseTexture}
+  glGenTextures(1, PglUint(@fVisualTex));
+  glBindTexture(GL_TEXTURE_2D, fVisualTex);
+
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  {$ENDIF}
+
+  InitProjectM();
+end;
+
+destructor TVideo_ProjectM.Destroy;
+begin
+  Close();
+  {$IFDEF UseTexture}
+  glDeleteTextures(1, PglUint(@fVisualTex));
+  {$ENDIF}
+end;
+
+procedure TVideo_ProjectM.Close;
+begin
+  FreeAndNil(fPm);
+end;
+
+procedure TVideo_ProjectM.Play;
+begin
+  if (fState = pmStop) and (assigned(fPm)) then
+    fPm.RandomPreset();
+  fState := pmPlay;
+end;
+
+procedure TVideo_ProjectM.Pause;
+begin
+  if (fState = pmPlay) then
+    fState := pmPause
+  else if (fState = pmPause) then
+    fState := pmPlay;
+end;
+
+procedure TVideo_ProjectM.Stop;
+begin
+  fState := pmStop;
+end;
+
+procedure TVideo_ProjectM.SetPosition(Time: real);
+begin
+  if assigned(fPm) then
+    fPm.RandomPreset();
+end;
+
+function TVideo_ProjectM.GetPosition: real;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_ProjectM.SetLoop(Enable: boolean);
+begin
+end;
+
+function TVideo_ProjectM.GetLoop(): boolean;
+begin
+  Result := true;
+end;
+
+procedure TVideo_ProjectM.SetScreen(Screen: integer);
+begin
+end;
+
+function TVideo_ProjectM.GetScreen(): integer;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_ProjectM.SetScreenPosition(X, Y, Z: double);
+begin
+end;
+
+procedure TVideo_ProjectM.GetScreenPosition(var X, Y, Z: double);
+begin
+  X := 0;
+  Y := 0;
+  Z := 0;
+end;
+
+procedure TVideo_ProjectM.SetWidth(Width: double);
+begin
+end;
+
+function TVideo_ProjectM.GetWidth(): double;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_ProjectM.SetHeight(Height: double);
+begin
+end;
+
+function TVideo_ProjectM.GetHeight(): double;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_ProjectM.SetFrameRange(Range: TRectCoords);
+begin
+end;
+
+function TVideo_ProjectM.GetFrameRange(): TRectCoords;
+begin
+  Result.Left := 0;
+  Result.Right := 0;
+  Result.Upper := 0;
+  Result.Lower := 0;
+end;
+
+function TVideo_ProjectM.GetFrameAspect(): real;
+begin
+  Result := 0;
+end;
+
+procedure TVideo_ProjectM.SetAspectCorrection(AspectCorrection: TAspectCorrection);
+begin
+end;
+
+function TVideo_ProjectM.GetAspectCorrection(): TAspectCorrection;
+begin
+  Result := acoStretch;
+end;
+
+procedure TVideo_ProjectM.SetAlpha(Alpha: double);
+begin
+end;
+
+function TVideo_ProjectM.GetAlpha(): double;
+begin
+  Result := 1;
+end;
+
+procedure TVideo_ProjectM.SetReflectionSpacing(Spacing: double);
+begin
+end;
+
+function TVideo_ProjectM.GetReflectionSpacing(): double;
+begin
+  Result := 0;
+end;
+
+{**
+ * Returns the stack depth of the given OpenGL matrix mode stack.
+ *}
+function TVideo_ProjectM.GetMatrixStackDepth(MatrixMode: GLenum): GLint;
+begin
+  // get number of matrices on stack
+  case (MatrixMode) of
+    GL_PROJECTION:
+      glGetIntegerv(GL_PROJECTION_STACK_DEPTH, @Result);
+    GL_MODELVIEW:
+      glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, @Result);
+    GL_TEXTURE:
+      glGetIntegerv(GL_TEXTURE_STACK_DEPTH, @Result);
+  end;
+end;
+
+{**
+ * Saves the current matrix stack using MatrixMode
+ * (one of GL_PROJECTION/GL_TEXTURE/GL_MODELVIEW)
+ *
+ * Use this function instead of just saving the current matrix with glPushMatrix().
+ * OpenGL specifies the depth of the GL_PROJECTION and GL_TEXTURE stacks to be
+ * at least 2 but projectM already uses 2 stack-entries so overflows might be
+ * possible on older hardware.
+ * In contrast to this the GL_MODELVIEW stack-size is at least 32, but this
+ * function should be used for the modelview stack too. We cannot rely on a
+ * proper stack management of the underlying visualizer (projectM).
+ * For example in the projectM versions 1.0 - 1.01 the modelview- and
+ * projection-matrices were popped without being pushed first.
+ *
+ * By saving the whole stack we are on the safe side, so a nasty bug in the
+ * visualizer does not corrupt USDX.
+ *}
+procedure TVideo_ProjectM.SaveMatrixStack(MatrixMode: GLenum;
+                var MatrixStack: TGLMatrixStack);
+var
+  I: integer;
+  StackDepth: GLint;
+begin
+  glMatrixMode(MatrixMode);
+
+  StackDepth := GetMatrixStackDepth(MatrixMode);
+  SetLength(MatrixStack, StackDepth);
+
+  // save current matrix stack
+  for I := StackDepth-1 downto 0 do
+  begin
+    // save current matrix
+    case (MatrixMode) of
+      GL_PROJECTION:
+        glGetDoublev(GL_PROJECTION_MATRIX, @MatrixStack[I]);
+      GL_MODELVIEW:
+        glGetDoublev(GL_MODELVIEW_MATRIX, @MatrixStack[I]);
+      GL_TEXTURE:
+        glGetDoublev(GL_TEXTURE_MATRIX, @MatrixStack[I]);
+    end;
+
+    // remove matrix from stack
+    if (I > 0) then
+      glPopMatrix();
+  end;
+
+  // reset default (first) matrix
+  glLoadIdentity();
+end;
+
+{**
+ * Restores the OpenGL matrix stack stored with SaveMatrixStack.
+ *}
+procedure TVideo_ProjectM.RestoreMatrixStack(MatrixMode: GLenum;
+                var MatrixStack: TGLMatrixStack);
+var
+  I: integer;
+  StackDepth: GLint;
+begin
+  glMatrixMode(MatrixMode);
+
+  StackDepth := GetMatrixStackDepth(MatrixMode);
+  // remove all (except the first) matrices from current stack
+  for I := 1 to StackDepth-1 do
+    glPopMatrix();
+
+  // rebuild stack
+  for I := 0 to High(MatrixStack) do
+  begin
+    glLoadMatrixd(@MatrixStack[I]);
+    if (I < High(MatrixStack)) then
+      glPushMatrix();
+  end;
+
+  // clean stored stack
+  SetLength(MatrixStack, 0);
+end;
+
+{**
+ * Saves the current OpenGL state.
+ * This is necessary to prevent projectM from corrupting USDX's current
+ * OpenGL state.
+ *
+ * The following steps are performed:
+ *   - All attributes are pushed to the attribute-stack
+ *   - Projection-/Texture-matrices are saved
+ *   - Modelview-matrix is pushed to the Modelview-stack
+ *   - the OpenGL error-state (glGetError) is cleared
+ *}
+procedure TVideo_ProjectM.SaveOpenGLState();
+begin
+  // save all OpenGL state-machine attributes
+  glPushAttrib(GL_ALL_ATTRIB_BITS);
+  glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
+
+  SaveMatrixStack(GL_PROJECTION, fProjectionMatrixStack);
+  SaveMatrixStack(GL_MODELVIEW, fModelviewMatrixStack);
+  SaveMatrixStack(GL_TEXTURE, fTextureMatrixStack);
+
+  glMatrixMode(GL_MODELVIEW);
+
+  // reset OpenGL error-state
+  glGetError();
+end;
+
+{**
+ * Restores the OpenGL state saved by SaveOpenGLState()
+ * and resets the error-state.
+ *}
+procedure TVideo_ProjectM.RestoreOpenGLState();
+begin
+  // reset OpenGL error-state
+  glGetError();
+
+  // restore matrix stacks
+  RestoreMatrixStack(GL_PROJECTION, fProjectionMatrixStack);
+  RestoreMatrixStack(GL_MODELVIEW, fModelviewMatrixStack);
+  RestoreMatrixStack(GL_TEXTURE, fTextureMatrixStack);
+
+  // restore all OpenGL state-machine attributes
+  // (also restores the matrix mode)
+  glPopClientAttrib();
+  glPopAttrib();
+end;
+
+procedure TVideo_ProjectM.InitProjectM;
+begin
+  // the OpenGL state must be saved before TProjectM.Create is called
+  SaveOpenGLState();
+  try
+
+    try
+      {$IF PROJECTM_VERSION >= 1000000} // >= 1.0
+      fPm := TProjectM.Create(fProjectMPath + 'config.inp');
+      {$ELSE}
+      fPm := TProjectM.Create(
+        meshX, meshY, fps, textureSize, ScreenW, ScreenH,
+        fProjectMPath + 'presets', fProjectMPath + 'fonts');
+      {$IFEND}
+    except on E: Exception do
+      begin
+        // Create() might fail if the config-file is not found
+        Log.LogError('TProjectM.Create: ' + E.Message, 'TVideoPlayback_ProjectM.VisualizerStart');
+        Exit;
+      end;
+    end;
+
+    // initialize OpenGL
+    fPm.ResetGL(ScreenW, ScreenH);
+    // skip projectM default-preset
+    fPm.RandomPreset();
+    // projectM >= 1.0 uses the OpenGL FramebufferObject (FBO) extension.
+    // Unfortunately it does NOT reset the framebuffer-context after
+    // TProjectM.Create. Either glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0) for
+    // a manual reset or TProjectM.RenderFrame() must be called.
+    // We use the latter so we do not need to load the FBO extension in USDX.
+    fPm.RenderFrame();
+  finally
+    RestoreOpenGLState();
+  end;
+end;
+
+procedure TVideo_ProjectM.GetFrame(Time: Extended);
+var
+  nSamples: cardinal;
+begin
+  if (fState <> pmPlay) then
+    Exit;
+
+  // get audio data
+  nSamples := AudioPlayback.GetPCMData(fPCMData);
+
+  // generate some data if non is available
+  if (nSamples = 0) then
+    nSamples := GetRandomPCMData(fPCMData);
+
+  // send audio-data to projectM
+  if (nSamples > 0) then
+    fPm.AddPCM16Data(PSmallInt(@fPCMData), nSamples);
+
+  // store OpenGL state (might be messed up otherwise)
+  SaveOpenGLState();
+  try
+    // setup projectM's OpenGL state
+    fPm.ResetGL(ScreenW, ScreenH);
+
+    // let projectM render a frame
+    fPm.RenderFrame();
+
+    {$IFDEF UseTexture}
+    glBindTexture(GL_TEXTURE_2D, fVisualTex);
+    glFlush();
+    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, fVisualWidth, fVisualHeight, 0);
+    {$ENDIF}
+  finally
+    // restore USDX OpenGL state
+    RestoreOpenGLState();
+  end;
+
+  // discard projectM's depth buffer information (avoid overlay)
+  glClear(GL_DEPTH_BUFFER_BIT);
+end;
+
+{**
+ * Draws the current frame to screen.
+ * TODO: this is not used yet. Data is directly drawn on GetFrame().
+ *}
+procedure TVideo_ProjectM.Draw();
+begin
+  {$IFDEF UseTexture}
+  // have a nice black background to draw on
+  if (fScreen = 1) then
+  begin
+    glClearColor(0, 0, 0, 0);
+    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+  end;
+
+  // exit if there's nothing to draw
+  if (fState <> pmPlay) then
+    Exit;
+
+  // setup display
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  // Use count of screens instead of 1 for the right corner
+  // otherwise we would draw the visualization streched over both screens
+  // another point is that we draw over the at this time drawn first
+  // screen, if Screen = 2
+  gluOrtho2D(0, Screens, 0, 1);
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity();
+
+  glEnable(GL_BLEND);
+  glEnable(GL_TEXTURE_2D);
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+  glBindTexture(GL_TEXTURE_2D, fVisualTex);
+  glColor4f(1, 1, 1, 1);
+
+  // draw projectM frame
+  // Screen is 1 to 2. So current screen is from (Screen - 1) to (Screen)
+  glBegin(GL_QUADS);
+    glTexCoord2f(0, 0); glVertex2f((fScreen - 1), 0);
+    glTexCoord2f(1, 0); glVertex2f(fScreen, 0);
+    glTexCoord2f(1, 1); glVertex2f(fScreen, 1);
+    glTexCoord2f(0, 1); glVertex2f((fScreen - 1), 1);
+  glEnd();
+
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_BLEND);
+
+  // restore state
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glMatrixMode(GL_MODELVIEW);
+  glPopMatrix();
+  {$ENDIF}
+end;
+
+procedure TVideo_ProjectM.DrawReflection();
+begin
+end;
+
+{**
+ * Produces random "sound"-data in case no audio-data is available.
+ * Otherwise the visualization will look rather boring.
+ *}
+function  TVideo_ProjectM.GetRandomPCMData(var Data: TPCMData): Cardinal;
+var
+  i: integer;
+begin
+  // Produce some fake PCM data
+  if (fRndPCMcount mod 500 = 0) then
+  begin
+    FillChar(Data, SizeOf(TPCMData), 0);
+  end
+  else
+  begin
+    for i := 0 to 511 do
+    begin
+      Data[i][0] := Random(High(Word)+1);
+      Data[i][1] := Random(High(Word)+1);
+    end;
+  end;
+  Inc(fRndPCMcount);
+  Result := 512;
+end;
+
+
+initialization
+  MediaManager.Add(TVideoPlayback_ProjectM.Create);
+
+end.
diff --git a/songmanagement/src/menu/UDisplay.pas b/songmanagement/src/menu/UDisplay.pas
new file mode 100644
index 00000000..6ec8e2ed
--- /dev/null
+++ b/songmanagement/src/menu/UDisplay.pas
@@ -0,0 +1,747 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UDisplay;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UCommon,
+  Math,
+  SDL,
+  gl,
+  glu,
+  SysUtils,
+  UMenu,
+  UPath,
+  UMusic,
+  UHookableEvent;
+
+type
+  TDisplay = class
+    private
+      ePreDraw: THookableEvent;
+      eDraw: THookableEvent;
+
+      // fade-to-black
+      BlackScreen:   boolean;
+
+      FadeEnabled:   boolean;  // true if fading is enabled
+      FadeFailed:    boolean;  // true if fading is possible (enough memory, etc.)
+      FadeStartTime: cardinal; // time when fading starts, 0 means that the fade texture must be initialized
+      DoneOnShow:    boolean;  // true if passed onShow after fading
+
+      FadeTex:       array[0..1] of GLuint;
+      TexW, TexH:    Cardinal;
+ 
+      FPSCounter:    cardinal;
+      LastFPS:       cardinal;
+      NextFPSSwap:   cardinal;
+
+      OSD_LastError: string;
+
+      { software cursor data }
+      Cursor_X:              double;
+      Cursor_Y:              double;
+      Cursor_Pressed:        boolean;
+      Cursor_HiddenByScreen: boolean; // hides software cursor and deactivate auto fade in
+
+      // used for cursor fade out when there is no movement
+      Cursor_Visible:      boolean;
+      Cursor_LastMove:     cardinal;
+      Cursor_Fade:         boolean;
+
+      procedure DrawDebugInformation;
+
+      { called by MoveCursor and OnMouseButton to update last move and start fade in }
+      procedure UpdateCursorFade;
+    public
+      NextScreen:          PMenu;
+      CurrentScreen:       PMenu;
+
+      // popup data
+      NextScreenWithCheck: Pmenu;
+      CheckOK:             boolean;
+
+      // FIXME: Fade is set to 0 in UMain and other files but not used here anymore.
+      Fade:                real;
+
+      constructor Create;
+      destructor  Destroy; override;
+
+      procedure InitFadeTextures();
+      
+      procedure SaveScreenShot;
+
+      function  Draw: boolean;
+
+      { calls ParseInput of cur or next Screen if assigned }
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown : boolean): boolean;
+
+      { sets SDL_ShowCursor depending on options set in Ini }
+      procedure SetCursor;
+
+      { called when cursor moves, positioning of software cursor }
+      procedure MoveCursor(X, Y: double);
+
+      { called when left or right mousebutton is pressed or released }
+      procedure OnMouseButton(Pressed: boolean);
+      { fades to specific screen (playing specified sound) }
+      function FadeTo(Screen: PMenu; const aSound: TAudioPlaybackStream = nil): PMenu;
+
+      { abort fading to the current screen, may be used in OnShow, or during fade process }
+      procedure AbortScreenChange;
+
+      { draws software cursor }
+      procedure DrawCursor;
+  end;
+
+var
+  Display: TDisplay;
+
+const
+  { constants for screen transition
+    time in milliseconds }
+  FADE_DURATION = 400;
+  { constants for software cursor effects
+    time in milliseconds }
+  CURSOR_FADE_IN_TIME = 500;      // seconds the fade in effect lasts
+  CURSOR_FADE_OUT_TIME = 2000;    // seconds the fade out effect lasts
+  CURSOR_AUTOHIDE_TIME = 5000;   // seconds until auto fade out starts if there is no mouse movement
+
+implementation
+
+uses
+  TextGL,
+  UCommandLine,
+  UGraphic,
+  UIni,
+  UImage,
+  ULog,
+  UMain,
+  UTexture,
+  UTime,
+  ULanguage,
+  UPathUtils;
+
+constructor TDisplay.Create;
+begin
+  inherited Create;
+
+  // create events for plugins
+  ePreDraw := THookableEvent.Create('Display.PreDraw');
+  eDraw := THookableEvent.Create('Display.Draw');
+
+  // init popup
+  CheckOK             := false;
+  NextScreen          := nil;
+  NextScreenWithCheck := nil;
+  BlackScreen         := false;
+
+  // init fade
+  FadeStartTime := 0;
+  FadeEnabled := (Ini.ScreenFade = 1);
+  FadeFailed  := false;
+  DoneOnShow  := false;
+
+  glGenTextures(2, PGLuint(@FadeTex));
+  InitFadeTextures();
+
+  // set LastError for OSD to No Error
+  OSD_LastError := 'No Errors';
+
+  // software cursor default values
+  Cursor_LastMove := 0;
+  Cursor_Visible  := false;
+  Cursor_Pressed  := false;
+  Cursor_X        := -1;
+  Cursor_Y        := -1;
+  Cursor_Fade     := false;
+  Cursor_HiddenByScreen := true;
+end;
+
+destructor TDisplay.Destroy;
+begin
+  glDeleteTextures(2, @FadeTex);
+  inherited Destroy;
+end;
+
+procedure TDisplay.InitFadeTextures();
+var
+  i: integer;
+begin
+  TexW := Round(Power(2, Ceil(Log2(ScreenW div Screens))));
+  TexH := Round(Power(2, Ceil(Log2(ScreenH))));
+
+  for i := 0 to 1 do
+  begin
+    glBindTexture(GL_TEXTURE_2D, FadeTex[i]);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexImage2D(GL_TEXTURE_2D, 0, 3, TexW, TexH, 0, GL_RGB, GL_UNSIGNED_BYTE, nil);
+  end;
+end;
+
+function TDisplay.Draw: boolean;
+var
+  S:               integer;
+  FadeStateSquare: real;
+  FadeW, FadeH:    real;
+  FadeCopyW, FadeCopyH: integer;
+  currentTime:     cardinal;
+  glError:         glEnum;
+
+begin
+  Result := true;
+
+  for S := 1 to Screens do
+  begin
+    ScreenAct := S;
+
+    //if Screens = 1 then ScreenX := 0;
+    //if (Screens = 2) and (S = 1) then ScreenX := -1;
+    //if (Screens = 2) and (S = 2) then ScreenX := 1;
+    ScreenX := 0;
+
+    glViewPort((S-1) * ScreenW div Screens, 0, ScreenW div Screens, ScreenH);
+
+    // popup check was successful... move on
+    if CheckOK then
+    begin
+      if assigned(NextScreenWithCheck) then
+      begin
+        NextScreen := NextScreenWithCheck;
+        NextScreenWithCheck := nil;
+        CheckOk := false;
+      end
+      else
+      begin
+        // on end of game fade to black before exit
+        BlackScreen := true;
+      end;
+    end;
+
+    if (not assigned(NextScreen)) and (not BlackScreen) then
+    begin
+      ePreDraw.CallHookChain(false);
+      CurrentScreen.Draw;
+
+      // popup
+      if (ScreenPopupError <> nil) and ScreenPopupError.Visible then
+        ScreenPopupError.Draw
+      else if (ScreenPopupInfo <> nil) and ScreenPopupInfo.Visible then
+        ScreenPopupInfo.Draw
+      else if (ScreenPopupCheck <> nil) and ScreenPopupCheck.Visible then
+        ScreenPopupCheck.Draw;
+
+      // fade
+      FadeStartTime := 0;
+      if ((Ini.ScreenFade = 1) and (not FadeFailed)) then
+        FadeEnabled := true
+      else
+        FadeEnabled := false;
+
+      eDraw.CallHookChain(false);
+    end
+    else
+    begin
+      // disable fading if initialization failed
+      if (FadeEnabled and FadeFailed) then
+      begin
+        FadeEnabled := false;
+      end;
+      
+      if (FadeEnabled and not FadeFailed) then
+      begin
+        // create fading texture if we're just starting
+        if FadeStartTime = 0 then
+        begin
+          // draw screen that will be faded
+          ePreDraw.CallHookChain(false);
+          CurrentScreen.Draw;
+          eDraw.CallHookChain(false);
+
+          // clear OpenGL errors, otherwise fading might be disabled due to some
+          // older errors in previous OpenGL calls.
+          glGetError();
+
+          FadeCopyW := ScreenW div Screens;
+          FadeCopyH := ScreenH;
+
+          // it is possible that our fade textures are too small after a window
+          // resize. In that case resize the fade texture to fit the requirements.
+          if (TexW < FadeCopyW) or (TexH < FadeCopyH) then
+            InitFadeTextures();
+
+          // copy screen to texture
+          glBindTexture(GL_TEXTURE_2D, FadeTex[S-1]);
+          glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (S-1) * ScreenW div Screens, 0,
+            FadeCopyW, FadeCopyH);
+
+          glError := glGetError();
+          if (glError <> GL_NO_ERROR) then
+          begin
+            FadeFailed := true;
+            Log.LogError('Fading disabled: ' + gluErrorString(glError), 'TDisplay.Draw');
+          end;
+
+          if not BlackScreen and (S = 1) and not DoneOnShow then
+          begin
+            NextScreen.OnShow;
+            DoneOnShow := true;
+          end;
+
+
+          // set fade time once on second screen (or first if screens = 1)
+          if (Screens = 1) or (S = 2) then
+            FadeStartTime := SDL_GetTicks;
+        end; // end texture creation in first fading step
+
+        if not BlackScreen then
+        begin
+          ePreDraw.CallHookChain(false);
+          NextScreen.Draw; // draw next screen
+          eDraw.CallHookChain(false);
+        end
+        else if ScreenAct = 1 then
+        begin
+          // draw black screen
+          glClearColor(0, 0, 0, 1);
+          glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+        end;
+
+        // and draw old screen over it... slowly fading out
+        if (FadeStartTime = 0) then
+          FadeStateSquare := 0 // for first screen if screens = 2
+        else
+          FadeStateSquare := sqr((SDL_GetTicks - FadeStartTime) / FADE_DURATION);
+
+        if (FadeStateSquare < 1) then
+        begin
+          FadeW := (ScreenW div Screens)/TexW;
+          FadeH := ScreenH/TexH;
+
+          glBindTexture(GL_TEXTURE_2D, FadeTex[S-1]);
+          // TODO: check if glTexEnvi() gives any speed improvement
+          //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+          glColor4f(1, 1, 1, 1-FadeStateSquare);
+
+          glEnable(GL_TEXTURE_2D);
+          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+          glEnable(GL_BLEND);
+          glBegin(GL_QUADS);
+            glTexCoord2f((0+FadeStateSquare/2)*FadeW, (0+FadeStateSquare/2)*FadeH);
+            glVertex2f(0,   RenderH);
+
+            glTexCoord2f((0+FadeStateSquare/2)*FadeW, (1-FadeStateSquare/2)*FadeH);
+            glVertex2f(0,   0);
+
+            glTexCoord2f((1-FadeStateSquare/2)*FadeW, (1-FadeStateSquare/2)*FadeH);
+            glVertex2f(RenderW, 0);
+
+            glTexCoord2f((1-FadeStateSquare/2)*FadeW, (0+FadeStateSquare/2)*FadeH);
+            glVertex2f(RenderW, RenderH);
+          glEnd;
+          glDisable(GL_BLEND);
+          glDisable(GL_TEXTURE_2D);
+
+          // reset to default
+          //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+        end;
+      end
+
+      // there is no need to init next screen if it is a black screen
+      else if not BlackScreen then
+      begin
+        NextScreen.OnShow;
+      end;
+
+      if ((FadeStartTime + FADE_DURATION < SDL_GetTicks) or
+          (not FadeEnabled) or FadeFailed) and
+         ((Screens = 1) or (S = 2)) then
+      begin
+        // fade out complete...
+        FadeStartTime := 0;
+        DoneOnShow := false;
+        CurrentScreen.onHide;
+        CurrentScreen.ShowFinish := false;
+        CurrentScreen := NextScreen;
+        NextScreen := nil;
+        if not BlackScreen then
+        begin
+          CurrentScreen.OnShowFinish;
+          CurrentScreen.ShowFinish := true;
+        end
+        else
+        begin
+          Result := false;
+          Break;
+        end;
+      end;
+    end; // if
+
+    // Draw OSD only on first Screen if Debug Mode is enabled
+    if ((Ini.Debug = 1) or (Params.Debug)) and (S = 1) then
+      DrawDebugInformation;
+
+    if not BlackScreen then
+      DrawCursor;
+  end; // for
+end;
+
+{ sets SDL_ShowCursor depending on options set in Ini }
+procedure TDisplay.SetCursor;
+var
+  Cursor: Integer;
+begin
+  Cursor := 0;
+
+  if (CurrentScreen <> @ScreenSing) or (Cursor_HiddenByScreen) then
+  begin // hide cursor on singscreen
+    if (Ini.Mouse = 0) and (Ini.FullScreen = 0) then
+      // show sdl (os) cursor in window mode even when mouse support is off
+      Cursor := 1
+    else if (Ini.Mouse = 1) then
+      // show sdl (os) cursor when hardware cursor is selected
+      Cursor := 1;
+
+    if (Ini.Mouse <> 2) then
+      Cursor_HiddenByScreen := false;
+  end
+  else if (Ini.Mouse <> 2) then
+    Cursor_HiddenByScreen := true;
+
+
+  SDL_ShowCursor(Cursor);
+
+  if (Ini.Mouse = 2) then
+  begin
+    if Cursor_HiddenByScreen then
+    begin
+      // show software cursor
+      Cursor_HiddenByScreen := false;
+      Cursor_Visible := false;
+      Cursor_Fade := false;
+    end
+    else if (CurrentScreen = @ScreenSing) then
+    begin
+      // hide software cursor in singscreen
+      Cursor_HiddenByScreen := true;
+      Cursor_Visible := false;
+      Cursor_Fade := false;
+    end;
+  end;
+end;
+
+{ called by MoveCursor and OnMouseButton to update last move and start fade in }
+procedure TDisplay.UpdateCursorFade;
+var
+  Ticks: cardinal;
+begin
+  Ticks := SDL_GetTicks;
+
+  { fade in on movement (or button press) if not first movement }
+  if (not Cursor_Visible) and (Cursor_LastMove <> 0) then
+  begin
+    if Cursor_Fade then // we use a trick here to consider progress of fade out
+      Cursor_LastMove := Ticks - round(CURSOR_FADE_IN_TIME * (1 - (Ticks - Cursor_LastMove)/CURSOR_FADE_OUT_TIME))
+    else
+      Cursor_LastMove := Ticks;
+
+    Cursor_Visible := true;
+    Cursor_Fade := true;
+  end
+  else if not Cursor_Fade then
+  begin
+    Cursor_LastMove := Ticks;
+  end;
+end;
+
+{ called when cursor moves, positioning of software cursor }
+procedure TDisplay.MoveCursor(X, Y: double);
+begin
+  if (Ini.Mouse = 2) and
+     ((X <> Cursor_X) or (Y <> Cursor_Y)) then
+  begin
+    Cursor_X := X;
+    Cursor_Y := Y;
+
+    UpdateCursorFade;
+  end;
+end;
+
+{ called when left or right mousebutton is pressed or released }
+procedure TDisplay.OnMouseButton(Pressed: boolean);
+begin
+  if (Ini.Mouse = 2) then
+  begin
+    Cursor_Pressed := Pressed;
+
+    UpdateCursorFade;
+  end;
+end;
+
+{ draws software cursor }
+procedure TDisplay.DrawCursor;
+var
+  Alpha: single;
+  Ticks: cardinal;
+  DrawX: double;
+begin
+  if (Ini.Mouse = 2) and ((Screens = 1) or ((ScreenAct - 1) = (Round(Cursor_X+16) div RenderW))) then
+  begin // draw software cursor
+    Ticks := SDL_GetTicks;
+
+    if (Cursor_Visible) and (Cursor_LastMove + CURSOR_AUTOHIDE_TIME <= Ticks) then
+    begin // start fade out after 5 secs w/o activity
+      Cursor_Visible := false;
+      Cursor_LastMove := Ticks;
+      Cursor_Fade := true;
+    end;
+    
+    // fading
+    if Cursor_Fade then
+    begin
+      if Cursor_Visible then
+      begin // fade in
+        if (Cursor_LastMove + CURSOR_FADE_IN_TIME <= Ticks) then
+          Cursor_Fade := false
+        else
+          Alpha := sin((Ticks - Cursor_LastMove) * 0.5 * pi / CURSOR_FADE_IN_TIME) * 0.7;
+      end
+      else
+      begin //fade out
+        if (Cursor_LastMove + CURSOR_FADE_OUT_TIME <= Ticks) then
+          Cursor_Fade := false
+        else
+          Alpha := cos((Ticks - Cursor_LastMove) * 0.5 * pi / CURSOR_FADE_OUT_TIME) * 0.7;
+      end;
+    end;
+
+    // no else if here because we may turn off fade in if block
+    if not Cursor_Fade then
+    begin
+      if Cursor_Visible then
+        Alpha := 0.7 // alpha when cursor visible and not fading
+      else
+        Alpha := 0;  // alpha when cursor is hidden
+    end;
+
+    if (Alpha > 0) and (not Cursor_HiddenByScreen) then
+    begin
+      DrawX := Cursor_X;
+      if (ScreenAct = 2) then
+        DrawX := DrawX - RenderW;
+      glColor4f(1, 1, 1, Alpha);
+      glEnable(GL_TEXTURE_2D);
+      glEnable(GL_BLEND);
+      glDisable(GL_DEPTH_TEST);
+
+      if (Cursor_Pressed) and (Tex_Cursor_Pressed.TexNum > 0) then
+        glBindTexture(GL_TEXTURE_2D, Tex_Cursor_Pressed.TexNum)
+      else
+        glBindTexture(GL_TEXTURE_2D, Tex_Cursor_Unpressed.TexNum);
+
+      glBegin(GL_QUADS);
+        glTexCoord2f(0, 0);
+        glVertex2f(DrawX, Cursor_Y);
+
+        glTexCoord2f(0, 1);
+        glVertex2f(DrawX, Cursor_Y + 32);
+
+        glTexCoord2f(1, 1);
+        glVertex2f(DrawX + 32, Cursor_Y + 32);
+
+        glTexCoord2f(1, 0);
+        glVertex2f(DrawX + 32, Cursor_Y);
+      glEnd;
+
+      glDisable(GL_BLEND);
+      glDisable(GL_TEXTURE_2D);
+    end;
+  end;
+end;
+
+function TDisplay.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown : boolean): boolean;
+begin
+  if (assigned(NextScreen)) then
+    Result := NextScreen^.ParseInput(PressedKey, CharCode, PressedDown)
+  else if (assigned(CurrentScreen)) then
+    Result := CurrentScreen^.ParseInput(PressedKey, CharCode, PressedDown)
+  else
+    Result := True;
+end;
+
+{ abort fading to the next screen, may be used in OnShow, or during fade process }
+procedure TDisplay.AbortScreenChange;
+  var
+    Temp: PMenu;
+begin
+  // this is some kind of "hack" it is based on the
+  // code that is used to change the screens in TDisplay.Draw
+  // we should rewrite this whole behaviour, as it is not well
+  // structured and not well extendable. Also we should offer
+  // a possibility to change screens to plugins
+  // change this code when restructuring is done
+  if (assigned(NextScreen)) then
+  begin
+    // we have to swap the screens
+    Temp := CurrentScreen;
+    CurrentScreen := NextScreen;
+    NextScreen := Temp;
+
+    // and call the OnShow procedure of the previous screen
+    // because it was already called by default fade procedure
+    NextScreen.OnShow;
+    
+  end;
+end;
+
+{ fades to specific screen (playing specified sound)
+  returns old screen }
+function TDisplay.FadeTo(Screen: PMenu; const aSound: TAudioPlaybackStream = nil): PMenu;
+begin
+  Result := CurrentScreen;
+  if (Result <> nil) then
+  begin
+    if (aSound <> nil) then
+      Result.FadeTo(Screen, aSound)
+    else
+      Result.FadeTo(Screen);
+  end;
+end;
+
+procedure TDisplay.SaveScreenShot;
+var
+  Num:        integer;
+  FileName:   IPath;
+  Prefix:     UTF8String;
+  ScreenData: PChar;
+  Surface:    PSDL_Surface;
+  Success:    boolean;
+  Align:      integer;
+  RowSize:    integer;
+begin
+  // Exit if Screenshot-path does not exist or read-only
+  if (ScreenshotsPath.IsUnset) then
+    Exit;
+
+  for Num := 1 to 9999 do
+  begin
+    // fill prefix to 4 digits with leading '0', e.g. '0001'
+    Prefix := Format('screenshot%.4d', [Num]);
+    FileName := ScreenshotsPath.Append(Prefix + '.png');
+    if not FileName.Exists() then
+      break;
+  end;
+
+  // we must take the row-alignment (4byte by default) into account
+  glGetIntegerv(GL_PACK_ALIGNMENT, @Align);
+  // calc aligned row-size
+  RowSize := ((ScreenW*3 + (Align-1)) div Align) * Align;
+
+  GetMem(ScreenData, RowSize * ScreenH);
+  glReadPixels(0, 0, ScreenW, ScreenH, GL_RGB, GL_UNSIGNED_BYTE, ScreenData);
+  // on big endian machines (powerpc) this may need to be changed to
+  // Needs to be tests. KaMiSchi Sept 2008
+  // in this case one may have to add " glext, " to the list of used units
+  //  glReadPixels(0, 0, ScreenW, ScreenH, GL_BGR, GL_UNSIGNED_BYTE, ScreenData);
+  Surface := SDL_CreateRGBSurfaceFrom(
+      ScreenData, ScreenW, ScreenH, 24, RowSize,
+      $0000FF, $00FF00, $FF0000, 0);
+
+  //  Success := WriteJPGImage(FileName, Surface, 95);
+  //  Success := WriteBMPImage(FileName, Surface);
+  Success := WritePNGImage(FileName, Surface);
+  if Success then
+    ScreenPopupInfo.ShowPopup(Format(Language.Translate('SCREENSHOT_SAVED'), [FileName.GetName.ToUTF8()]))
+  else
+    ScreenPopupError.ShowPopup(Language.Translate('SCREENSHOT_FAILED'));
+
+  SDL_FreeSurface(Surface);
+  FreeMem(ScreenData);
+end;
+
+//------------
+// DrawDebugInformation - procedure draw fps and some other informations on screen
+//------------
+procedure TDisplay.DrawDebugInformation;
+var
+  Ticks: cardinal;
+begin
+  // Some White Background for information
+  glEnable(GL_BLEND);
+  glDisable(GL_TEXTURE_2D);
+  glColor4f(1, 1, 1, 0.5);
+  glBegin(GL_QUADS);
+    glVertex2f(690, 44);
+    glVertex2f(690, 0);
+    glVertex2f(800, 0);
+    glVertex2f(800, 44);
+  glEnd;
+  glDisable(GL_BLEND);
+
+  // set font specs
+  SetFontStyle(ftNormal);
+  SetFontSize(21);
+  SetFontItalic(false);
+  glColor4f(0, 0, 0, 1);
+
+  // calculate fps
+  Ticks := SDL_GetTicks();
+  if (Ticks >= NextFPSSwap) then
+  begin
+    LastFPS := FPSCounter * 4;
+    FPSCounter := 0;
+    NextFPSSwap := Ticks + 250;
+  end;
+
+  Inc(FPSCounter);
+
+  // draw text
+
+  // fps
+  SetFontPos(695, 0);
+  glPrint ('FPS: ' + InttoStr(LastFPS));
+
+  // rspeed
+  SetFontPos(695, 13);
+  glPrint ('RSpeed: ' + InttoStr(Round(1000 * TimeMid)));
+
+  // lasterror
+  SetFontPos(695, 26);
+  glColor4f(1, 0, 0, 1);
+  glPrint (OSD_LastError);
+
+  glColor4f(1, 1, 1, 1);
+end;
+
+end.
diff --git a/songmanagement/src/menu/UDrawTexture.pas b/songmanagement/src/menu/UDrawTexture.pas
new file mode 100644
index 00000000..bc136f11
--- /dev/null
+++ b/songmanagement/src/menu/UDrawTexture.pas
@@ -0,0 +1,139 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UDrawTexture;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UTexture;
+
+procedure DrawLine(X1, Y1, X2, Y2, ColR, ColG, ColB: real);
+procedure DrawQuad(X,  Y,  W,  H,  ColR, ColG, ColB: real);
+procedure DrawTexture(Texture: TTexture);
+
+implementation
+
+uses
+  gl;
+
+procedure DrawLine(X1, Y1, X2, Y2, ColR, ColG, ColB: real);
+begin
+  glColor3f(ColR, ColG, ColB);
+  glBegin(GL_LINES);
+    glVertex2f(x1, y1);
+    glVertex2f(x2, y2);
+  glEnd;
+end;
+
+procedure DrawQuad(X, Y, W, H, ColR, ColG, ColB: real);
+begin
+  glColor3f(ColR, ColG, ColB);
+  glBegin(GL_QUADS);
+    glVertex2f(x,   y);
+    glVertex2f(x,   y+h);
+    glVertex2f(x+w, y+h);
+    glVertex2f(x+w, y);
+  glEnd;
+end;
+
+procedure DrawTexture(Texture: TTexture);
+var
+  x1, x2, x3, x4:     real;
+  y1, y2, y3, y4:     real;
+  xt1, xt2, xt3, xt4: real;
+  yt1, yt2, yt3, yt4: real;
+begin
+  with Texture do
+  begin
+    glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha);
+    glEnable(GL_TEXTURE_2D);
+    glEnable(GL_BLEND);
+    glDepthRange(0, 10);
+    glDepthFunc(GL_LEQUAL);
+//    glDepthFunc(GL_GEQUAL);
+    glEnable(GL_DEPTH_TEST);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+//    glBlendFunc(GL_SRC_COLOR, GL_ZERO);
+    glBindTexture(GL_TEXTURE_2D, TexNum);
+
+    x1 := x;
+    x2 := x;
+    x3 := x+w*scaleW;
+    x4 := x+w*scaleW;
+    y1 := y;
+    y2 := y+h*scaleH;
+    y3 := y+h*scaleH;
+    y4 := y;
+    if Rot <> 0 then
+    begin
+      xt1 := x1 - (x + w/2);
+      xt2 := x2 - (x + w/2);
+      xt3 := x3 - (x + w/2);
+      xt4 := x4 - (x + w/2);
+      yt1 := y1 - (y + h/2);
+      yt2 := y2 - (y + h/2);
+      yt3 := y3 - (y + h/2);
+      yt4 := y4 - (y + h/2);
+
+      x1 := (x + w/2) + xt1 * cos(Rot) - yt1 * sin(Rot);
+      x2 := (x + w/2) + xt2 * cos(Rot) - yt2 * sin(Rot);
+      x3 := (x + w/2) + xt3 * cos(Rot) - yt3 * sin(Rot);
+      x4 := (x + w/2) + xt4 * cos(Rot) - yt4 * sin(Rot);
+
+      y1 := (y + h/2) + yt1 * cos(Rot) + xt1 * sin(Rot);
+      y2 := (y + h/2) + yt2 * cos(Rot) + xt2 * sin(Rot);
+      y3 := (y + h/2) + yt3 * cos(Rot) + xt3 * sin(Rot);
+      y4 := (y + h/2) + yt4 * cos(Rot) + xt4 * sin(Rot);
+
+    end;
+
+{
+    glBegin(GL_QUADS);
+      glTexCoord2f(0,    0);    glVertex3f(x1, y1, z);
+      glTexCoord2f(0,    TexH); glVertex3f(x2, y2, z);
+      glTexCoord2f(TexW, TexH); glVertex3f(x3, y3, z);
+      glTexCoord2f(TexW, 0);    glVertex3f(x4, y4, z);
+    glEnd;
+}
+
+    glBegin(GL_QUADS);
+      glTexCoord2f(TexX1*TexW, TexY1*TexH); glVertex3f(x1, y1, z);
+      glTexCoord2f(TexX1*TexW, TexY2*TexH); glVertex3f(x2, y2, z);
+      glTexCoord2f(TexX2*TexW, TexY2*TexH); glVertex3f(x3, y3, z);
+      glTexCoord2f(TexX2*TexW, TexY1*TexH); glVertex3f(x4, y4, z);
+    glEnd;
+  end;
+  glDisable(GL_DEPTH_TEST); 
+  glDisable(GL_TEXTURE_2D);
+end;
+
+end.
diff --git a/songmanagement/src/menu/UMenu.pas b/songmanagement/src/menu/UMenu.pas
new file mode 100644
index 00000000..b011eddf
--- /dev/null
+++ b/songmanagement/src/menu/UMenu.pas
@@ -0,0 +1,1804 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenu;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  Math,
+  gl,
+  SDL,
+  UPath,
+  UMenuBackground,
+  UMenuButton,
+  UMenuButtonCollection,
+  UMenuInteract,
+  UMenuSelectSlide,
+  UMenuStatic,
+  UMenuText,
+  UMusic,
+  UTexture,
+  UThemes;
+
+type
+{  Int16 = SmallInt;}
+
+  PMenu = ^TMenu;
+  TMenu = class
+    protected
+      Background:       TMenuBackground;
+
+      Interactions:     array of TInteract;
+      SelInteraction:   integer;
+
+      ButtonPos:        integer;
+      Button:           array of TButton;
+
+      SelectsS:         array of TSelectSlide;
+      ButtonCollection: array of TButtonCollection;
+    public
+      Text:       array of TText;
+      Statics:     array of TStatic;
+      mX:         integer; // mouse X
+      mY:         integer; // mouse Y
+
+      Fade:       integer; // fade type
+      ShowFinish: boolean; // true if there is no fade
+      RightMbESC: boolean; // true to simulate ESC keypress when RMB is pressed
+
+      destructor Destroy; override;
+      constructor Create; overload; virtual;
+      //constructor Create(Back: string); overload; virtual; // Back is a JPG resource name for background
+      //constructor Create(Back: string; W, H: integer); overload; virtual; // W and H are the number of overlaps
+
+      // interaction
+      procedure AddInteraction(Typ, Num: integer);
+      procedure SetInteraction(Num: integer); virtual;
+      property Interaction: integer read SelInteraction write SetInteraction;
+
+      // procedure load bg, texts, statics and button collections from themebasic
+      procedure LoadFromTheme(const ThemeBasic: TThemeBasic);
+
+      procedure PrepareButtonCollections(const Collections: AThemeButtonCollection);
+      procedure AddButtonCollection(const ThemeCollection: TThemeButtonCollection; const Num: byte);
+
+      // background
+      procedure AddBackground(ThemedSettings: TThemeBackground);
+
+      // static
+      function AddStatic(ThemeStatic: TThemeStatic): integer; overload;
+      function AddStatic(X, Y, W, H: real; const TexName: IPath): integer; overload;
+      function AddStatic(X, Y, W, H: real; const TexName: IPath; Typ: TTextureType): integer; overload;
+      function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const TexName: IPath; Typ: TTextureType): integer; overload;
+      function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const TexName: IPath; Typ: TTextureType): integer; overload;
+      function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const TexName: IPath; Typ: TTextureType; Color: integer): integer; overload;
+      function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const TexName: IPath; Typ: TTextureType; Color: integer): integer; overload;
+      function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; TexX1, TexY1, TexX2, TexY2: real; const TexName: IPath; Typ: TTextureType; Color: integer; Reflection: boolean; ReflectionSpacing: real): integer; overload;
+
+      // text
+      function AddText(ThemeText: TThemeText): integer; overload;
+      function AddText(X, Y: real; const Text_: UTF8String): integer; overload;
+      function AddText(X, Y: real; Style: integer; Size, ColR, ColG, ColB: real; const Text: UTF8String): integer; overload;
+      function AddText(X, Y, W: real; Style: integer; Size, ColR, ColG, ColB: real; Align: integer; const Text_: UTF8String; Reflection_: boolean; ReflectionSpacing_: real; Z : real): integer; overload;
+
+      // button
+      procedure SetButtonLength(Length: cardinal); //Function that Set Length of Button Array in one Step instead of register new Memory for every Button
+      function AddButton(ThemeButton: TThemeButton): integer; overload;
+      function AddButton(X, Y, W, H: real; const TexName: IPath): integer; overload;
+      function AddButton(X, Y, W, H: real; const TexName: IPath; Typ: TTextureType; Reflection: boolean): integer; overload;
+      function AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real; const TexName: IPath; Typ: TTextureType; Reflection: boolean; ReflectionSpacing, DeSelectReflectionSpacing: real): integer; overload;
+      procedure ClearButtons;
+      procedure AddButtonText(AddX, AddY: real; const AddText: UTF8String); overload;
+      procedure AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; const AddText: UTF8String); overload;
+      procedure AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: UTF8String); overload;
+      procedure AddButtonText(CustomButton: TButton; AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: UTF8String); overload;
+
+      // select slide
+      function AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; const Values: array of UTF8String): integer; overload;
+      function AddSelectSlide(X, Y, W, H, SkipX, SBGW, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt,
+        TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt,
+        SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt,
+        STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real;
+        const TexName: IPath; Typ: TTextureType; const SBGName: IPath; SBGTyp: TTextureType;
+        const Caption: UTF8String; var Data: integer): integer; overload;
+      procedure AddSelectSlideOption(const AddText: UTF8String); overload;
+      procedure AddSelectSlideOption(SelectNo: cardinal; const AddText: UTF8String); overload;
+      procedure UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; const Values: array of UTF8String; var Data: integer);
+
+//      function AddWidget(X, Y : UInt16; WidgetSrc : PSDL_Surface): Int16;
+//      procedure ClearWidgets(MinNumber : Int16);
+      procedure FadeTo(Screen: PMenu); overload;
+      procedure FadeTo(Screen: PMenu; aSound: TAudioPlaybackStream); overload;
+      //popup hack
+      procedure CheckFadeTo(Screen: PMenu; Msg: UTF8String);
+
+      function DrawBG: boolean; virtual;
+      function DrawFG: boolean; virtual;
+      function Draw: boolean; virtual;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown : boolean): boolean; virtual;
+      function ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; virtual;
+      function InRegion(X, Y: real; A: TMouseOverRect): boolean;
+      function InteractAt(X, Y: real): integer;
+      function CollectionAt(X, Y: real): integer;
+      procedure OnShow; virtual;
+      procedure OnShowFinish; virtual;
+      procedure OnHide; virtual;
+
+      procedure SetAnimationProgress(Progress: real); virtual;
+
+      function IsSelectable(Int: cardinal): boolean;
+    
+      procedure InteractNext; virtual;
+      procedure InteractCustom(CustomSwitch: integer); virtual;
+      procedure InteractPrev; virtual;
+      procedure InteractInc; virtual;
+      procedure InteractDec; virtual;
+      procedure InteractNextRow; virtual; // this is for the options screen, so button down makes sense
+      procedure InteractPrevRow; virtual; // this is for the options screen, so button up makes sense
+      procedure AddBox(X, Y, W, H: real);
+  end;
+
+function RGBFloatToInt(R, G, B: double): cardinal;
+
+const
+  MENU_MDOWN = 8;
+  MENU_MUP   = 0;
+
+  pmMove    = 1;
+  pmClick   = 2;
+  pmUnClick = 3;
+
+  iButton           = 0; // interaction type
+  iText             = 2;
+  iSelectS          = 3;
+  iBCollectionChild = 5;
+
+//  fBlack = 0; // fade type
+//  fWhite = 1;
+
+implementation
+
+uses
+  UCommon,
+  UCovers,
+  UDisplay,
+  UDrawTexture,
+  UGraphic,
+  ULog,
+  UMain,
+  USkins,
+  UTime,
+  //Background types
+  UMenuBackgroundNone,
+  UMenuBackgroundColor,
+  UMenuBackgroundTexture,
+  UMenuBackgroundVideo,
+  UMenuBackgroundFade;
+
+destructor TMenu.Destroy;
+var
+  I: integer;
+begin
+  for I := 0 to High(Button) do
+    Button[I].Free;
+  for I := 0 to High(ButtonCollection) do
+    ButtonCollection[I].Free;
+  for I := 0 to High(SelectsS) do
+    SelectsS[I].Free;
+  for I := 0 to High(Text) do
+    Text[I].Free;
+  for I := 0 to High(Statics) do
+    Statics[I].Free;
+
+  Background.Free;
+
+  //Log.LogError('Unloaded Succesful: ' + ClassName);
+  inherited;
+end;
+
+constructor TMenu.Create;
+begin
+  inherited;
+
+  Fade := 0;//fWhite;
+
+  SetLength(Statics, 0);
+  SetLength(Button, 0);
+
+  //Set ButtonPos to Autoset Length
+  ButtonPos := -1;
+
+  Background := nil;
+
+  RightMbESC := true;
+end;
+{
+constructor TMenu.Create(Back: string);
+begin
+  inherited Create;
+
+  if Back <> '' then
+  begin
+//    BackImg := Texture.GetTexture(true, Back, TEXTURE_TYPE_PLAIN, 0);
+    BackImg := Texture.GetTexture(Back, TEXTURE_TYPE_PLAIN, 0); // new theme system
+    BackImg.W := 800;//640;
+    BackImg.H := 600;//480;
+    BackW := 1;
+    BackH := 1;
+  end
+  else
+    BackImg.TexNum := 0;
+
+   //Set ButtonPos to Autoset Length
+   ButtonPos := -1;
+end;
+
+constructor TMenu.Create(Back: string; W, H: integer);
+begin
+  Create(Back);
+  BackImg.W := BackImg.W / W;
+  BackImg.H := BackImg.H / H;
+  BackW := W;
+  BackH := H;
+end;   }
+
+function RGBFloatToInt(R, G, B: double): cardinal;
+begin
+  Result := (Trunc(255 * R) shl 16) or
+            (Trunc(255 * G) shl  8) or
+             Trunc(255 * B);
+end;
+
+procedure TMenu.AddInteraction(Typ, Num: integer);
+var
+  IntNum: integer;
+begin
+  IntNum := Length(Interactions);
+  SetLength(Interactions, IntNum+1);
+  Interactions[IntNum].Typ := Typ;
+  Interactions[IntNum].Num := Num;
+  Interaction := 0;
+end;
+
+procedure TMenu.SetInteraction(Num: integer);
+var
+  OldNum, OldTyp: integer;
+  NewNum, NewTyp: integer;
+begin
+  // set inactive
+  OldNum := Interactions[Interaction].Num;
+  OldTyp := Interactions[Interaction].Typ;
+
+  NewNum := Interactions[Num].Num;
+  NewTyp := Interactions[Num].Typ;
+
+  case OldTyp of
+    iButton:  Button[OldNum].Selected := false;
+    iText:    Text[OldNum].Selected := false;
+    iSelectS: SelectsS[OldNum].Selected := false;
+    //Button Collection Mod
+    iBCollectionChild:
+      begin
+        Button[OldNum].Selected := false;
+      
+        // deselect collection if next button is not from collection
+        if (NewTyp <> iButton) or (Button[NewNum].Parent <> Button[OldNum].Parent) then
+          ButtonCollection[Button[OldNum].Parent-1].Selected := false;
+      end;
+  end;
+
+  // set active
+  SelInteraction := Num;
+  case NewTyp of
+    iButton:  Button[NewNum].Selected := true;
+    iText:    Text[NewNum].Selected := true;
+    iSelectS: SelectsS[NewNum].Selected := true;
+
+    //Button Collection Mod
+    iBCollectionChild:
+      begin
+        Button[NewNum].Selected := true;
+        ButtonCollection[Button[NewNum].Parent-1].Selected := true;
+      end;
+  end;
+end;
+
+//----------------------
+//LoadFromTheme - Load BG, Texts, Statics and
+//Button Collections from ThemeBasic
+//----------------------
+procedure TMenu.LoadFromTheme(const ThemeBasic: TThemeBasic);
+var
+  I: integer;
+begin
+  //Add Button Collections (Set Button CollectionsLength)
+  //Button Collections are Created when the first ChildButton is Created
+  PrepareButtonCollections(ThemeBasic.ButtonCollection);
+
+  //Add Background
+  AddBackground(ThemeBasic.Background);
+
+  //Add Statics and Texts
+  for I := 0 to High(ThemeBasic.Statics) do
+    AddStatic(ThemeBasic.Statics[I]);
+
+  for I := 0 to High(ThemeBasic.Text) do
+    AddText(ThemeBasic.Text[I]);
+end;
+
+procedure TMenu.AddBackground(ThemedSettings: TThemeBackground);
+  var
+    FileExt: string;
+
+  function IsInArray(const Piece: string; const A: array of string): boolean;
+  var
+    I: integer;
+  begin
+    Result := false;
+  
+    for I := 0 to High(A) do
+      if (A[I] = Piece) then
+      begin
+        Result := true;
+        Exit;
+      end;
+  end;
+
+  function TryBGCreate(Typ: cMenuBackground): boolean;
+  begin
+    Result := true;
+
+    try
+      Background := Typ.Create(ThemedSettings);
+    except
+      on E: EMenuBackgroundError do
+      begin //Background failes to create
+        Freeandnil(Background);
+        Result := false;
+      end;
+    end;
+  end;
+
+begin
+  FreeAndNil(Background);
+
+  case ThemedSettings.BGType of
+    bgtAuto: begin //Automaticly choose one out of BGT_Texture, BGT_Video or BGT_Color
+
+      if (Length(ThemedSettings.Tex) > 0) then
+      begin
+
+        //At first some intelligent try to decide which BG to load
+        FileExt := LowerCase(Skin.GetTextureFileName(ThemedSettings.Tex).GetExtension.ToUTF8);
+
+        if IsInArray(FileExt, SUPPORTED_EXTS_BACKGROUNDTEXTURE) then
+          TryBGCreate(TMenuBackgroundTexture)
+        else if IsInArray(FileExt, SUPPORTED_EXTS_BACKGROUNDVIDEO) then
+          TryBGCreate(TMenuBackgroundVideo);
+
+        //If the intelligent method don't succeed
+        //do it by trial and error
+        if (Background = nil) then
+        begin
+          //Try Textured Bg
+          if not TryBGCreate(TMenuBackgroundTexture) then
+            TryBgCreate(TMenuBackgroundVideo); //Try Video BG
+
+          //Color is fallback if Background = nil
+        end;
+      end;
+    end;
+
+    bgtColor: begin
+      try
+        Background := TMenuBackgroundColor.Create(ThemedSettings);
+      except
+        on E: EMenuBackgroundError do
+        begin
+          Log.LogError(E.Message);
+          freeandnil(Background);
+        end;
+      end;
+    end;
+
+    bgtTexture: begin
+      try
+        Background := TMenuBackgroundTexture.Create(ThemedSettings);
+      except
+        on E: EMenuBackgroundError do
+        begin
+          Log.LogError(E.Message);
+          freeandnil(Background);
+        end;
+      end;
+    end;
+
+    bgtVideo: begin
+      try
+        Background := TMenuBackgroundVideo.Create(ThemedSettings);
+      except
+        on E: EMenuBackgroundError do
+        begin
+          Log.LogError(E.Message);
+          freeandnil(Background);
+        end;
+      end;
+    end;
+
+    bgtNone: begin
+      try
+        Background := TMenuBackgroundNone.Create(ThemedSettings);
+      except
+        on E: EMenuBackgroundError do
+        begin
+          Log.LogError(E.Message);
+          freeandnil(Background);
+        end;
+      end;
+    end;
+
+    bgtFade: begin
+      try
+        Background := TMenuBackgroundFade.Create(ThemedSettings);
+      except
+        on E: EMenuBackgroundError do
+        begin
+          Log.LogError(E.Message);
+          freeandnil(Background);
+        end;
+      end;
+    end;
+  end;
+
+  //Fallback to None Background or Colored Background
+  if (Background = nil) then
+  begin
+    if (ThemedSettings.BGType = bgtColor) then
+      Background := TMenuBackgroundNone.Create(ThemedSettings)
+    else
+      Background := TMenuBackgroundColor.Create(ThemedSettings)
+  end;
+end;
+
+//----------------------
+//PrepareButtonCollections:
+//Add Button Collections (Set Button CollectionsLength)
+//----------------------
+procedure TMenu.PrepareButtonCollections(const Collections: AThemeButtonCollection);
+var
+  I: integer;
+begin
+  SetLength(ButtonCollection, Length(Collections));
+  for I := 0 to High(ButtonCollection) do
+    AddButtonCollection(Collections[I], I);
+end;
+
+//----------------------
+//AddButtonCollection:
+//Create a Button Collection;
+//----------------------
+procedure TMenu.AddButtonCollection(const ThemeCollection: TThemeButtonCollection; const Num: byte);
+var
+  BT, BTLen:         integer;
+  TempCol, TempDCol: cardinal;
+
+begin
+  if (Num > High(ButtonCollection)) then
+    exit;
+
+  TempCol := 0;
+
+  // colorize hack
+  if (ThemeCollection.Style.Typ = TEXTURE_TYPE_COLORIZED) then
+  begin
+    TempCol  := RGBFloatToInt(ThemeCollection.Style.ColR, ThemeCollection.Style.ColG, ThemeCollection.Style.ColB);
+    TempDCol := RGBFloatToInt(ThemeCollection.Style.DColR, ThemeCollection.Style.DColG, ThemeCollection.Style.DColB);
+    // give encoded color to GetTexture()
+    ButtonCollection[Num] := TButtonCollection.Create(
+      Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.Tex), TEXTURE_TYPE_COLORIZED, TempCol),
+      Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.Tex), TEXTURE_TYPE_COLORIZED, TempDCol));
+  end
+  else
+  begin
+    ButtonCollection[Num] := TButtonCollection.Create(Texture.GetTexture(
+      Skin.GetTextureFileName(ThemeCollection.Style.Tex), ThemeCollection.Style.Typ));
+  end;
+
+  //Set Parent menu
+  ButtonCollection[Num].ScreenButton := @Self.Button;
+
+  //Set Attributes
+  ButtonCollection[Num].FirstChild := ThemeCollection.FirstChild;
+  ButtonCollection[Num].CountChilds := ThemeCollection.ChildCount;
+  ButtonCollection[Num].Parent := Num + 1;
+
+  //Set Style
+  ButtonCollection[Num].X := ThemeCollection.Style.X;
+  ButtonCollection[Num].Y := ThemeCollection.Style.Y;
+  ButtonCollection[Num].W := ThemeCollection.Style.W;
+  ButtonCollection[Num].H := ThemeCollection.Style.H;
+  if (ThemeCollection.Style.Typ <> TEXTURE_TYPE_COLORIZED) then
+  begin
+    ButtonCollection[Num].SelectColR := ThemeCollection.Style.ColR;
+    ButtonCollection[Num].SelectColG := ThemeCollection.Style.ColG;
+    ButtonCollection[Num].SelectColB := ThemeCollection.Style.ColB;
+    ButtonCollection[Num].DeselectColR := ThemeCollection.Style.DColR;
+    ButtonCollection[Num].DeselectColG := ThemeCollection.Style.DColG;
+    ButtonCollection[Num].DeselectColB := ThemeCollection.Style.DColB;
+  end;
+  ButtonCollection[Num].SelectInt := ThemeCollection.Style.Int;
+  ButtonCollection[Num].DeselectInt := ThemeCollection.Style.DInt;
+  ButtonCollection[Num].Texture.TexX1 := 0;
+  ButtonCollection[Num].Texture.TexY1 := 0;
+  ButtonCollection[Num].Texture.TexX2 := 1;
+  ButtonCollection[Num].Texture.TexY2 := 1;
+  ButtonCollection[Num].SetSelect(false);
+
+  ButtonCollection[Num].Reflection := ThemeCollection.Style.Reflection;
+  ButtonCollection[Num].Reflectionspacing := ThemeCollection.Style.ReflectionSpacing;
+  ButtonCollection[Num].DeSelectReflectionspacing := ThemeCollection.Style.DeSelectReflectionSpacing;
+
+  ButtonCollection[Num].Z := ThemeCollection.Style.Z;
+
+  //Some Things from ButtonFading
+  ButtonCollection[Num].SelectH := ThemeCollection.Style.SelectH;
+  ButtonCollection[Num].SelectW := ThemeCollection.Style.SelectW;
+
+  ButtonCollection[Num].Fade := ThemeCollection.Style.Fade;
+  ButtonCollection[Num].FadeText := ThemeCollection.Style.FadeText;
+  if (ThemeCollection.Style.Typ = TEXTURE_TYPE_COLORIZED) then
+  begin
+    ButtonCollection[Num].FadeTex := Texture.GetTexture(
+      Skin.GetTextureFileName(ThemeCollection.Style.FadeTex), TEXTURE_TYPE_COLORIZED, TempCol)
+  end
+  else
+  begin
+    ButtonCollection[Num].FadeTex := Texture.GetTexture(
+      Skin.GetTextureFileName(ThemeCollection.Style.FadeTex), ThemeCollection.Style.Typ);
+  end;
+  ButtonCollection[Num].FadeTexPos := ThemeCollection.Style.FadeTexPos;
+
+  BTLen := Length(ThemeCollection.Style.Text);
+  for BT := 0 to BTLen-1 do
+  begin
+      AddButtonText(ButtonCollection[Num], ThemeCollection.Style.Text[BT].X, ThemeCollection.Style.Text[BT].Y,
+        ThemeCollection.Style.Text[BT].ColR, ThemeCollection.Style.Text[BT].ColG, ThemeCollection.Style.Text[BT].ColB,
+        ThemeCollection.Style.Text[BT].Font, ThemeCollection.Style.Text[BT].Size, ThemeCollection.Style.Text[BT].Align,
+        ThemeCollection.Style.Text[BT].Text);
+  end;
+end;
+
+function TMenu.AddStatic(ThemeStatic: TThemeStatic): integer;
+begin
+  Result := AddStatic(ThemeStatic.X, ThemeStatic.Y, ThemeStatic.W, ThemeStatic.H, ThemeStatic.Z,
+    ThemeStatic.ColR, ThemeStatic.ColG, ThemeStatic.ColB,
+    ThemeStatic.TexX1, ThemeStatic.TexY1, ThemeStatic.TexX2, ThemeStatic.TexY2,
+    Skin.GetTextureFileName(ThemeStatic.Tex),
+    ThemeStatic.Typ, $FFFFFF, ThemeStatic.Reflection, ThemeStatic.Reflectionspacing);
+end;
+
+function TMenu.AddStatic(X, Y, W, H: real; const TexName: IPath): integer;
+begin
+  Result := AddStatic(X, Y, W, H, TexName, TEXTURE_TYPE_PLAIN);
+end;
+
+function TMenu.AddStatic(X, Y, W, H: real;
+       ColR, ColG, ColB: real;
+			 const TexName: IPath;
+			 Typ: TTextureType): integer;
+begin
+  Result := AddStatic(X, Y, W, H, ColR, ColG, ColB, TexName, Typ, $FFFFFF);
+end;
+
+function TMenu.AddStatic(X, Y, W, H, Z: real;
+       ColR, ColG, ColB: real;
+			 const TexName: IPath;
+			 Typ: TTextureType): integer;
+begin
+  Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, TexName, Typ, $FFFFFF);
+end;
+
+function TMenu.AddStatic(X, Y, W, H: real;
+       const TexName: IPath;
+			 Typ: TTextureType): integer;
+var
+  StatNum: integer;
+begin
+  // adds static
+  StatNum := Length(Statics);
+  SetLength(Statics, StatNum + 1);
+  Statics[StatNum] := TStatic.Create(Texture.GetTexture(TexName, Typ, $FF00FF)); // new skin
+
+  // configures static
+  Statics[StatNum].Texture.X := X;
+  Statics[StatNum].Texture.Y := Y;
+  Statics[StatNum].Texture.W := W;
+  Statics[StatNum].Texture.H := H;
+  Statics[StatNum].Visible := true;
+  Result := StatNum;
+end;
+
+function TMenu.AddStatic(X, Y, W, H: real;
+                         ColR, ColG, ColB: real;
+			 const TexName: IPath;
+			 Typ: TTextureType;
+			 Color: integer): integer;
+begin
+  Result := AddStatic(X, Y, W, H, 0, ColR, ColG, ColB, TexName, Typ, Color);
+end;
+
+function TMenu.AddStatic(X, Y, W, H, Z: real;
+                         ColR, ColG, ColB: real;
+			 const TexName: IPath;
+			 Typ: TTextureType;
+			 Color: integer): integer;
+begin
+  Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, 0, 0, 1, 1, TexName, Typ, Color, false, 0);
+end;
+
+function TMenu.AddStatic(X, Y, W, H, Z: real;
+                         ColR, ColG, ColB: real;
+			 TexX1, TexY1, TexX2, TexY2: real;
+			 const TexName: IPath;
+			 Typ: TTextureType;
+			 Color: integer;
+			 Reflection: boolean;
+			 ReflectionSpacing: real): integer;
+var
+  StatNum: integer;
+begin
+  // adds static
+  StatNum := Length(Statics);
+  SetLength(Statics, StatNum + 1);
+
+  // colorize hack
+  if (Typ = TEXTURE_TYPE_COLORIZED) then
+  begin
+    // give encoded color to GetTexture()
+    Statics[StatNum] := TStatic.Create(Texture.GetTexture(TexName, Typ, RGBFloatToInt(ColR, ColG, ColB)));
+  end
+  else
+  begin
+    Statics[StatNum] := TStatic.Create(Texture.GetTexture(TexName, Typ, Color)); // new skin
+  end;
+                     
+  // configures static
+  Statics[StatNum].Texture.X := X;
+  Statics[StatNum].Texture.Y := Y;
+
+  //Set height and width via sprite size if omitted
+  if(H = 0) then
+    Statics[StatNum].Texture.H := Statics[StatNum].Texture.H
+  else
+    Statics[StatNum].Texture.H := H;
+
+  if(W = 0) then
+    Statics[StatNum].Texture.W := Statics[StatNum].Texture.W
+  else
+    Statics[StatNum].Texture.W := W;
+
+  Statics[StatNum].Texture.Z := Z;
+  if (Typ <> TEXTURE_TYPE_COLORIZED) then
+  begin
+    Statics[StatNum].Texture.ColR := ColR;
+    Statics[StatNum].Texture.ColG := ColG;
+    Statics[StatNum].Texture.ColB := ColB;
+  end;
+  Statics[StatNum].Texture.TexX1 := TexX1;
+  Statics[StatNum].Texture.TexY1 := TexY1;
+  Statics[StatNum].Texture.TexX2 := TexX2;
+  Statics[StatNum].Texture.TexY2 := TexY2;
+  Statics[StatNum].Texture.Alpha := 1;
+  Statics[StatNum].Visible := true;
+
+  //ReflectionMod
+  Statics[StatNum].Reflection := Reflection;
+  Statics[StatNum].ReflectionSpacing := ReflectionSpacing;
+
+  Result := StatNum;
+end;
+
+function TMenu.AddText(ThemeText: TThemeText): integer;
+begin
+  Result := AddText(ThemeText.X, ThemeText.Y, ThemeText.W, ThemeText.Font, ThemeText.Size,
+    ThemeText.ColR, ThemeText.ColG, ThemeText.ColB, ThemeText.Align, ThemeText.Text, ThemeText.Reflection, ThemeText.ReflectionSpacing, ThemeText.Z);
+end;
+
+function TMenu.AddText(X, Y: real; const Text_: UTF8String): integer;
+var
+  TextNum: integer;
+begin
+  // adds text
+  TextNum := Length(Text);
+  SetLength(Text, TextNum + 1);
+  Text[TextNum] := TText.Create(X, Y, Text_);
+  Result := TextNum;
+end;
+
+function TMenu.AddText(X, Y: real;
+                      Style: integer;
+                      Size, ColR, ColG, ColB: real;
+                      const Text: UTF8String): integer;
+begin
+  Result := AddText(X, Y, 0, Style, Size, ColR, ColG, ColB, 0, Text, false, 0, 0);
+end;
+
+function TMenu.AddText(X, Y, W: real;
+                       Style: integer;
+                       Size, ColR, ColG, ColB: real;
+                       Align: integer;
+                       const Text_: UTF8String;
+                       Reflection_: boolean;
+                       ReflectionSpacing_: real;
+                       Z : real): integer;
+var
+  TextNum: integer;
+begin
+  // adds text
+  TextNum := Length(Text);
+  SetLength(Text, TextNum + 1);
+  Text[TextNum] := TText.Create(X, Y, W, Style, Size, ColR, ColG, ColB, Align, Text_, Reflection_, ReflectionSpacing_, Z);
+  Result := TextNum;
+end;
+
+//Function that Set Length of Button boolean in one Step instead of register new Memory for every Button
+procedure TMenu.SetButtonLength(Length: cardinal);
+begin
+  if (ButtonPos = -1) and (Length > 0) then
+  begin
+    //Set Length of Button
+    SetLength(Button, Length);
+
+    //Set ButtonPos to start with 0
+    ButtonPos := 0;
+  end;
+end;
+
+// Method to add a button in our TMenu. It returns the assigned ButtonNumber
+function TMenu.AddButton(ThemeButton: TThemeButton): integer;
+var
+  BT:    integer;
+  BTLen: integer;
+begin
+  Result := AddButton(ThemeButton.X, ThemeButton.Y, ThemeButton.W, ThemeButton.H,
+    ThemeButton.ColR, ThemeButton.ColG, ThemeButton.ColB, ThemeButton.Int,
+    ThemeButton.DColR, ThemeButton.DColG, ThemeButton.DColB, ThemeButton.DInt,
+    Skin.GetTextureFileName(ThemeButton.Tex), ThemeButton.Typ,
+    ThemeButton.Reflection, ThemeButton.Reflectionspacing, ThemeButton.DeSelectReflectionspacing);
+
+  Button[Result].Z := ThemeButton.Z;
+
+  //Button Visibility
+  Button[Result].Visible := ThemeButton.Visible;
+
+  //Some Things from ButtonFading
+  Button[Result].SelectH := ThemeButton.SelectH;
+  Button[Result].SelectW := ThemeButton.SelectW;
+
+  Button[Result].Fade := ThemeButton.Fade;
+  Button[Result].FadeText := ThemeButton.FadeText;
+  if (ThemeButton.Typ = TEXTURE_TYPE_COLORIZED) then
+  begin
+    Button[Result].FadeTex := Texture.GetTexture(
+      Skin.GetTextureFileName(ThemeButton.FadeTex), TEXTURE_TYPE_COLORIZED,
+      RGBFloatToInt(ThemeButton.ColR, ThemeButton.ColG, ThemeButton.ColB));
+  end
+  else
+  begin
+    Button[Result].FadeTex := Texture.GetTexture(
+      Skin.GetTextureFileName(ThemeButton.FadeTex), ThemeButton.Typ);
+  end;
+
+  Button[Result].FadeTexPos := ThemeButton.FadeTexPos;
+
+  BTLen := Length(ThemeButton.Text);
+  for BT := 0 to BTLen-1 do
+  begin
+    AddButtonText(ThemeButton.Text[BT].X, ThemeButton.Text[BT].Y,
+      ThemeButton.Text[BT].ColR, ThemeButton.Text[BT].ColG, ThemeButton.Text[BT].ColB,
+      ThemeButton.Text[BT].Font, ThemeButton.Text[BT].Size, ThemeButton.Text[BT].Align,
+      ThemeButton.Text[BT].Text);
+  end;
+
+  // bautton collection mod
+  if (ThemeButton.Parent <> 0) then
+  begin
+    // if collection exists then change interaction to child button
+    if (@ButtonCollection[ThemeButton.Parent-1] <> nil) then
+    begin
+      Interactions[High(Interactions)].Typ := iBCollectionChild;
+      Button[Result].Visible := false;
+
+      for BT := 0 to BTLen-1 do
+        Button[Result].Text[BT].Alpha := 0;
+
+      Button[Result].Parent := ThemeButton.Parent;
+      if (ButtonCollection[ThemeButton.Parent-1].Fade) then
+        Button[Result].Texture.Alpha := 0;
+    end;
+  end;
+end;
+
+function TMenu.AddButton(X, Y, W, H: real; const TexName: IPath): integer;
+begin
+  Result := AddButton(X, Y, W, H, TexName, TEXTURE_TYPE_PLAIN, false);
+end;
+
+function TMenu.AddButton(X, Y, W, H: real; const TexName: IPath; Typ: TTextureType; Reflection: boolean): integer;
+begin
+  Result := AddButton(X, Y, W, H, 1, 1, 1, 1, 1, 1, 1, 0.5, TexName, TEXTURE_TYPE_PLAIN, Reflection, 15, 15);
+end;
+
+function TMenu.AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real;
+                         const TexName: IPath;
+			 Typ: TTextureType;
+                         Reflection: boolean;
+			 ReflectionSpacing, DeSelectReflectionSpacing: real): integer;
+begin
+  // adds button
+  //SetLength is used once to reduce Memory usement
+  if (ButtonPos <> -1) then
+  begin
+    Result := ButtonPos;
+    Inc(ButtonPos)
+  end
+  else //Old Method -> Reserve new Memory for every Button
+  begin
+    Result := Length(Button);
+    SetLength(Button, Result + 1);
+  end;
+
+  // colorize hack
+  if (Typ = TEXTURE_TYPE_COLORIZED) then
+  begin
+    // give encoded color to GetTexture()
+    Button[Result] := TButton.Create(Texture.GetTexture(TexName, Typ, RGBFloatToInt(ColR, ColG, ColB)),
+                                     Texture.GetTexture(TexName, Typ, RGBFloatToInt(DColR, DColG, DColB)));
+  end
+  else
+  begin
+    Button[Result] := TButton.Create(Texture.GetTexture(TexName, Typ));
+  end;
+
+  // configures button
+  Button[Result].X := X;
+  Button[Result].Y := Y;
+  Button[Result].W := W;
+  Button[Result].H := H;
+  if (Typ <> TEXTURE_TYPE_COLORIZED) then
+  begin
+    Button[Result].SelectColR := ColR;
+    Button[Result].SelectColG := ColG;
+    Button[Result].SelectColB := ColB;
+    Button[Result].DeselectColR := DColR;
+    Button[Result].DeselectColG := DColG;
+    Button[Result].DeselectColB := DColB;
+  end;
+  Button[Result].SelectInt := Int;
+  Button[Result].DeselectInt := DInt;
+  Button[Result].Texture.TexX1 := 0;
+  Button[Result].Texture.TexY1 := 0;
+  Button[Result].Texture.TexX2 := 1;
+  Button[Result].Texture.TexY2 := 1;
+  Button[Result].SetSelect(false);
+
+  Button[Result].Reflection := Reflection;
+  Button[Result].Reflectionspacing := ReflectionSpacing;
+  Button[Result].DeSelectReflectionspacing := DeSelectReflectionSpacing;
+
+  // button collection mod
+  Button[Result].Parent := 0;
+
+  // adds interaction
+  AddInteraction(iButton, Result);
+  Interaction := 0;
+end;
+
+procedure TMenu.ClearButtons;
+begin
+  Setlength(Button, 0);
+end;
+
+// method to draw our tmenu and all his child buttons
+function TMenu.DrawBG: boolean;
+begin
+  Background.Draw;
+  Result := true;
+end;
+
+function TMenu.DrawFG: boolean;
+var
+  J: integer;
+begin
+  // We don't forget about newly implemented static for nice skin ...
+  for J := 0 to High(Statics) do
+    Statics[J].Draw;
+
+  // ... and slightly implemented menutext unit
+  for J := 0 to High(Text) do
+    Text[J].Draw;
+
+  //  Draw all ButtonCollections
+  for J := 0 to High(ButtonCollection) do
+    ButtonCollection[J].Draw;
+
+  // Second, we draw all of our buttons
+  for J := 0 to High(Button) do
+    Button[J].Draw;
+
+  for J := 0 to High(SelectsS) do
+    SelectsS[J].Draw;
+
+  // Third, we draw all our widgets
+  //  for J := 0 to Length(WidgetsSrc) - 1 do
+  //    SDL_BlitSurface(WidgetsSrc[J], nil, ParentBackBuf, WidgetsRect[J]);
+  Result := true;
+end;
+
+function TMenu.Draw: boolean;
+begin
+  DrawBG;
+  DrawFG;
+  Result := true;
+end;
+
+{
+function TMenu.GetNextScreen(): PMenu;
+begin
+  Result := NextScreen;
+end;
+}
+
+{
+function TMenu.AddWidget(X, Y: UInt16; WidgetSrc: PSDL_Surface): Int16;
+var
+  WidgetNum: Int16;
+begin
+  if (Assigned(WidgetSrc)) then
+  begin
+    WidgetNum := Length(WidgetsSrc);
+
+    SetLength(WidgetsSrc, WidgetNum + 1);
+    SetLength(WidgetsRect, WidgetNum + 1);
+
+    WidgetsSrc[WidgetNum] := WidgetSrc;
+    WidgetsRect[WidgetNum] := new(PSDL_Rect);
+    WidgetsRect[WidgetNum]^.x := X;
+    WidgetsRect[WidgetNum]^.y := Y;
+    WidgetsRect[WidgetNum]^.w := WidgetSrc^.w;
+    WidgetsRect[WidgetNum]^.h := WidgetSrc^.h;
+
+    Result := WidgetNum;
+  end
+  else
+    Result := -1;
+end;
+}
+
+{
+procedure TMenu.ClearWidgets(MinNumber: Int16);
+var
+  J: Int16;
+begin
+  for J := MinNumber to (Length(WidgetsSrc) - 1) do
+  begin
+    SDL_FreeSurface(WidgetsSrc[J]);
+    dispose(WidgetsRect[J]);
+  end;
+
+  SetLength(WidgetsSrc, MinNumber);
+  SetLength(WidgetsRect, MinNumber);
+end;
+}
+
+function TMenu.IsSelectable(Int: cardinal): boolean;
+begin
+  Result := true;
+  case Interactions[Int].Typ of
+    //Button
+    iButton: Result := Button[Interactions[Int].Num].Visible and Button[Interactions[Int].Num].Selectable;
+
+    //Select Slide
+    iSelectS: Result := SelectsS[Interactions[Int].Num].Visible;
+
+    //ButtonCollection Child
+    iBCollectionChild:
+      Result := (ButtonCollection[Button[Interactions[Int].Num].Parent - 1].FirstChild - 1 = Int) and ((Interactions[Interaction].Typ <> iBCollectionChild) or (Button[Interactions[Interaction].Num].Parent <> Button[Interactions[Int].Num].Parent));
+  end;
+end;
+
+// implemented for the sake of usablility
+// [curser down] picks the button left to the actual atm
+// this behaviour doesn't make sense for two rows of buttons
+procedure TMenu.InteractPrevRow;
+var
+  Int: integer;
+begin
+// these two procedures just make sense for at least 5 buttons, because we
+// usually start a second row when there are more than 4 buttons
+  Int := Interaction;
+
+  Int := Int - ceil(Length(Interactions) / 2);
+
+  //Set Interaction
+  if ((Int < 0) or (Int > Length(Interactions) - 1)) then
+    Int         := Interaction // invalid button, keep current one
+  else
+    Interaction := Int;        // select row above
+end;
+
+procedure TMenu.InteractNextRow;
+var
+  Int: integer;
+begin
+  Int := Interaction;
+
+  Int := Int + ceil(Length(Interactions) / 2);
+
+  //Set Interaction
+  if ((Int < 0) or (Int > Length(Interactions) - 1)) then
+    Int         := Interaction // invalid button, keep current one
+  else
+    Interaction := Int;        // select row above
+end;
+
+procedure TMenu.InteractNext;
+var
+  Int: integer;
+begin
+  Int := Interaction;
+
+  // change interaction as long as it's needed
+  repeat
+    Int := (Int + 1) mod Length(Interactions);
+
+    //If no Interaction is Selectable Simply Select Next
+    if (Int = Interaction) then
+      Break;
+
+  until IsSelectable(Int);
+
+  //Set Interaction
+  Interaction := Int;
+end;
+
+procedure TMenu.InteractPrev;
+var
+  Int: integer;
+begin
+  Int := Interaction;
+
+  // change interaction as long as it's needed
+  repeat
+    Int := Int - 1;
+    if Int = -1 then
+      Int := High(Interactions);
+
+    //If no Interaction is Selectable Simply Select Next
+    if (Int = Interaction) then
+      Break;
+  until IsSelectable(Int);
+
+  //Set Interaction
+  Interaction := Int
+end;
+
+procedure TMenu.InteractCustom(CustomSwitch: integer);
+{ needed only for below
+var
+  Num:   integer;
+  Typ:   integer;
+  Again: boolean;
+}
+begin
+  //Code Commented atm, because it needs to be Rewritten
+  //it doesn't work with Button Collections
+  {then
+  begin
+    CustomSwitch:= CustomSwitch*(-1);
+    Again := true;
+  // change interaction as long as it's needed
+  while (Again = true) do
+  begin
+    Num := SelInteraction - CustomSwitch;
+    if Num = -1 then
+      Num := High(Interactions);
+    Interaction := Num;
+    Again := false; // reset, default to accept changing interaction
+
+    // checking newly interacted element
+    Num := Interactions[Interaction].Num;
+    Typ := Interactions[Interaction].Typ;
+    case Typ of
+    iButton:
+      begin
+        if Button[Num].Selectable = false then
+	  Again := true;
+      end;
+    end; // case
+  end; // while
+  end
+  else if num>0 then
+  begin
+    Again := true;
+    // change interaction as long as it's needed
+  while (Again = true) do
+  begin
+    Num := (Interaction + CustomSwitch) Mod Length(Interactions);
+    Interaction := Num;
+    Again := false; // reset, default to accept changing interaction
+
+    // checking newly interacted element
+    Num := Interactions[Interaction].Num;
+    Typ := Interactions[Interaction].Typ;
+    case Typ of
+    iButton:
+      begin
+        if Button[Num].Selectable = false then
+	  Again := true;
+      end;
+    end; // case
+  end; // while
+    end     }
+end;
+
+procedure TMenu.FadeTo(Screen: PMenu);
+begin
+  Display.Fade := 0;
+  Display.NextScreen := Screen;
+end;
+
+procedure TMenu.FadeTo(Screen: PMenu; aSound: TAudioPlaybackStream);
+begin
+  FadeTo( Screen );
+  AudioPlayback.PlaySound( aSound );
+end;
+
+procedure OnSaveEncodingError(Value: boolean; Data: Pointer);
+begin
+  Display.CheckOK := Value;
+  if (Value) then
+  begin
+    //Hack to Finish Singscreen correct on Exit with Q Shortcut
+    if (Display.NextScreenWithCheck = nil) then
+    begin
+      if (Display.CurrentScreen = @ScreenSing) then
+        ScreenSing.Finish
+      {else if (Display.CurrentScreen = @ScreenSingModi) then
+        ScreenSingModi.Finish;}
+    end;
+  end
+  else
+  begin
+    Display.NextScreenWithCheck := nil;
+  end;
+end;
+
+//popup hack
+procedure TMenu.CheckFadeTo(Screen: PMenu; Msg: UTF8String);
+begin
+  Display.Fade := 0;
+  Display.NextScreenWithCheck := Screen;
+  Display.CheckOK := false;
+  ScreenPopupCheck.ShowPopup(msg, OnSaveEncodingError, nil, false);
+end;
+
+procedure TMenu.AddButtonText(AddX, AddY: real; const AddText: UTF8String);
+begin
+  AddButtonText(AddX, AddY, 1, 1, 1, AddText);
+end;
+
+procedure TMenu.AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; const AddText: UTF8String);
+var
+  Il: integer;
+begin
+  with Button[High(Button)] do
+  begin
+    Il := Length(Text);
+    SetLength(Text, Il+1);
+    Text[Il] := TText.Create(X + AddX, Y + AddY, AddText);
+    Text[Il].ColR := ColR;
+    Text[Il].ColG := ColG;
+    Text[Il].ColB := ColB;
+    Text[Il].Int := 1;//0.5;
+  end;
+end;
+
+procedure TMenu.AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: UTF8String);
+var
+  Il: integer;
+begin
+  with Button[High(Button)] do
+  begin
+    Il := Length(Text);
+    SetLength(Text, Il+1);
+    Text[Il] := TText.Create(X + AddX, Y + AddY, AddText);
+    Text[Il].ColR := ColR;
+    Text[Il].ColG := ColG;
+    Text[Il].ColB := ColB;
+    Text[Il].Int := 1;//0.5;
+    Text[Il].Style := Font;
+    Text[Il].Size := Size;
+    Text[Il].Align := Align;
+  end;
+end;
+
+procedure TMenu.AddButtonText(CustomButton: TButton; AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: UTF8String);
+var
+  Il: integer;
+begin
+  with CustomButton do
+  begin
+    Il := Length(Text);
+    SetLength(Text, Il+1);
+    Text[Il] := TText.Create(X + AddX, Y + AddY, AddText);
+    Text[Il].ColR := ColR;
+    Text[Il].ColG := ColG;
+    Text[Il].ColB := ColB;
+    Text[Il].Int := 1;//0.5;
+    Text[Il].Style := Font;
+    Text[Il].Size := Size;
+    Text[Il].Align := Align;
+  end;
+end;
+
+function TMenu.AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; const Values: array of UTF8String): integer;
+var
+  SO: integer;
+begin
+  Result := AddSelectSlide(ThemeSelectS.X, ThemeSelectS.Y, ThemeSelectS.W, ThemeSelectS.H, ThemeSelectS.SkipX, ThemeSelectS.SBGW,
+    ThemeSelectS.ColR, ThemeSelectS.ColG, ThemeSelectS.ColB, ThemeSelectS.Int,
+    ThemeSelectS.DColR, ThemeSelectS.DColG, ThemeSelectS.DColB, ThemeSelectS.DInt,
+    ThemeSelectS.TColR, ThemeSelectS.TColG, ThemeSelectS.TColB, ThemeSelectS.TInt,
+    ThemeSelectS.TDColR, ThemeSelectS.TDColG, ThemeSelectS.TDColB, ThemeSelectS.TDInt,
+    ThemeSelectS.SBGColR, ThemeSelectS.SBGColG, ThemeSelectS.SBGColB, ThemeSelectS.SBGInt,
+    ThemeSelectS.SBGDColR, ThemeSelectS.SBGDColG, ThemeSelectS.SBGDColB, ThemeSelectS.SBGDInt,
+    ThemeSelectS.STColR, ThemeSelectS.STColG, ThemeSelectS.STColB, ThemeSelectS.STInt,
+    ThemeSelectS.STDColR, ThemeSelectS.STDColG, ThemeSelectS.STDColB, ThemeSelectS.STDInt,
+    Skin.GetTextureFileName(ThemeSelectS.Tex), ThemeSelectS.Typ,
+    Skin.GetTextureFileName(ThemeSelectS.TexSBG), ThemeSelectS.TypSBG,
+    ThemeSelectS.Text, Data);
+  for SO := 0 to High(Values) do
+    AddSelectSlideOption(Values[SO]);
+
+  SelectsS[High(SelectsS)].Text.Size := ThemeSelectS.TextSize;
+
+  SelectsS[High(SelectsS)].Texture.Z := ThemeSelectS.Z;
+  SelectsS[High(SelectsS)].TextureSBG.Z := ThemeSelectS.Z;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowL.Z := ThemeSelectS.Z;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowR.Z := ThemeSelectS.Z;
+
+  SelectsS[High(SelectsS)].showArrows := ThemeSelectS.showArrows;
+  SelectsS[High(SelectsS)].oneItemOnly := ThemeSelectS.oneItemOnly;
+
+  //Generate Lines
+  SelectsS[High(SelectsS)].GenLines;
+
+  SelectsS[High(SelectsS)].SelectedOption := SelectsS[High(SelectsS)].SelectOptInt; // refresh
+end;
+
+function TMenu.AddSelectSlide(X, Y, W, H, SkipX, SBGW, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt,
+  TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt,
+  SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt,
+  STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real;
+  const TexName: IPath; Typ: TTextureType; const SBGName: IPath; SBGTyp: TTextureType;
+  const Caption: UTF8String; var Data: integer): integer;
+var
+  S: integer;
+  I: integer;
+begin
+  S := Length(SelectsS);
+  SetLength(SelectsS, S + 1);
+  SelectsS[S] := TSelectSlide.Create;
+
+  if (Typ = TEXTURE_TYPE_COLORIZED) then
+  begin
+    SelectsS[S].Colorized := true;
+    SelectsS[S].Texture := Texture.GetTexture(TexName, Typ, RGBFloatToInt(ColR, ColG, ColB));
+    SelectsS[S].DeselectTexture := Texture.GetTexture(TexName, Typ, RGBFloatToInt(DColR, DColG, DColB));
+  end
+  else
+  begin
+    SelectsS[S].Colorized := false;
+    SelectsS[S].Texture := Texture.GetTexture(TexName, Typ);
+    
+    SelectsS[S].ColR := ColR;
+    SelectsS[S].ColG := ColG;
+    SelectsS[S].ColB := ColB;
+
+    SelectsS[S].DColR := DColR;
+    SelectsS[S].DColG := DColG;
+    SelectsS[S].DColB := DColB;
+  end;
+  
+  SelectsS[S].Int := Int;
+  SelectsS[S].DInt := DInt; 
+
+  SelectsS[S].X := X;
+  SelectsS[S].Y := Y;
+  SelectsS[S].W := W;
+  SelectsS[S].H := H;  
+
+  if (SBGTyp = TEXTURE_TYPE_COLORIZED) then
+  begin
+    SelectsS[S].ColorizedSBG := true;
+    SelectsS[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp, RGBFloatToInt(SBGColR, SBGColG, SBGColB));
+    SelectsS[S].DeselectTextureSBG := Texture.GetTexture(SBGName, SBGTyp, RGBFloatToInt(SBGDColR, SBGDColG, SBGDColB));
+  end
+  else
+  begin
+    SelectsS[S].ColorizedSBG := false;
+    SelectsS[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp);
+
+    SelectsS[S].SBGColR := SBGColR;
+    SelectsS[S].SBGColG := SBGColG;
+    SelectsS[S].SBGColB := SBGColB;
+
+    SelectsS[S].SBGDColR := SBGDColR;
+    SelectsS[S].SBGDColG := SBGDColG;
+    SelectsS[S].SBGDColB := SBGDColB;
+  end;
+
+
+  SelectsS[S].SBGInt := SBGInt;
+  SelectsS[S].SBGDInt := SBGDInt;
+  
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowL   := Tex_SelectS_ArrowL;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowL.X := X + W + SkipX;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowL.Y := Y + (H - Tex_SelectS_ArrowL.H) / 2;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowL.W := Tex_SelectS_ArrowL.W;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowL.H := Tex_SelectS_ArrowL.H;
+
+
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowR   := Tex_SelectS_ArrowR;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowR.X := X + W + SkipX + SBGW - Tex_SelectS_ArrowR.W;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowR.Y := Y + (H - Tex_SelectS_ArrowR.H) / 2;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowR.W := Tex_SelectS_ArrowR.W;
+  SelectsS[High(SelectsS)].Tex_SelectS_ArrowR.H := Tex_SelectS_ArrowR.H;
+
+  SelectsS[S].TextureSBG.X := X + W + SkipX;
+  SelectsS[S].TextureSBG.Y := Y;
+  SelectsS[S].SBGW := SBGW;
+  SelectsS[S].TextureSBG.H := H;
+
+  SelectsS[S].Text.X := X + 20;
+  SelectsS[S].Text.Y := Y + (SelectsS[S].TextureSBG.H / 2) - 15;
+  SelectsS[S].Text.Text := Caption;
+  SelectsS[S].Text.Size := 30;
+  SelectsS[S].Text.Visible := true;
+  SelectsS[S].TColR := TColR;
+  SelectsS[S].TColG := TColG;
+  SelectsS[S].TColB := TColB;
+  SelectsS[S].TInt := TInt;
+  SelectsS[S].TDColR := TDColR;
+  SelectsS[S].TDColG := TDColG;
+  SelectsS[S].TDColB := TDColB;
+  SelectsS[S].TDInt := TDInt;
+
+  SelectsS[S].STColR := STColR;
+  SelectsS[S].STColG := STColG;
+  SelectsS[S].STColB := STColB;
+  SelectsS[S].STInt := STInt;
+  SelectsS[S].STDColR := STDColR;
+  SelectsS[S].STDColG := STDColG;
+  SelectsS[S].STDColB := STDColB;
+  SelectsS[S].STDInt := STDInt;
+
+  // new
+  SelectsS[S].Texture.TexX1 := 0;
+  SelectsS[S].Texture.TexY1 := 0;
+  SelectsS[S].Texture.TexX2 := 1;
+  SelectsS[S].Texture.TexY2 := 1;
+  SelectsS[S].TextureSBG.TexX1 := 0;
+  SelectsS[S].TextureSBG.TexY1 := 0;
+  SelectsS[S].TextureSBG.TexX2 := 1;
+  SelectsS[S].TextureSBG.TexY2 := 1;
+
+  // Sets Data to copy the value of selectops to global value;
+  SelectsS[S].PData := @Data;
+  // Configures Select options
+  {//SelectsS[S].TextOpt[0].Text := IntToStr(I+1);
+  SelectsS[S].TextOpt[0].Size := 30;
+  SelectsS[S].TextOpt[0].Align := 1;
+
+  SelectsS[S].TextOpt[0].ColR := SelectsS[S].STDColR;
+  SelectsS[S].TextOpt[0].ColG := SelectsS[S].STDColG;
+  SelectsS[S].TextOpt[0].ColB := SelectsS[S].STDColB;
+  SelectsS[S].TextOpt[0].Int := SelectsS[S].STDInt;
+  SelectsS[S].TextOpt[0].Visible := true; }
+
+  // Sets default value of selectopt from Data;
+  SelectsS[S].SelectedOption := Data;
+
+  // Disables default selection
+  SelectsS[S].SetSelect(false);
+
+  {// Configures 3 select options
+  for I := 0 to 2 do
+  begin
+    SelectsS[S].TextOpt[I].X := SelectsS[S].TextureSBG.X + 20 + (50 + 20) + (150 - 20) * I;
+    SelectsS[S].TextOpt[I].Y := SelectsS[S].TextureSBG.Y + 20;
+    SelectsS[S].TextOpt[I].Text := IntToStr(I+1);
+    SelectsS[S].TextOpt[I].Size := 30;
+    SelectsS[S].TextOpt[I].Align := 1;
+
+    SelectsS[S].TextOpt[I].ColR := SelectsS[S].STDColR;
+    SelectsS[S].TextOpt[I].ColG := SelectsS[S].STDColG;
+    SelectsS[S].TextOpt[I].ColB := SelectsS[S].STDColB;
+    SelectsS[S].TextOpt[I].Int := SelectsS[S].STDInt;
+    SelectsS[S].TextOpt[I].Visible := true;
+  end;}
+
+  // adds interaction
+  AddInteraction(iSelectS, S);
+  Result := S;
+end;
+
+procedure TMenu.AddSelectSlideOption(const AddText: UTF8String);
+begin
+  AddSelectSlideOption(High(SelectsS), AddText);
+end;
+
+procedure TMenu.AddSelectSlideOption(SelectNo: cardinal; const AddText: UTF8String);
+var
+  SO: integer;
+begin
+  SO := Length(SelectsS[SelectNo].TextOptT);
+
+  SetLength(SelectsS[SelectNo].TextOptT, SO + 1);
+  SelectsS[SelectNo].TextOptT[SO] := AddText;
+{
+  SelectsS[S].SelectedOption := SelectsS[S].SelectOptInt; // refresh
+
+  if SO = Selects[S].PData^ then
+    Selects[S].SelectedOption := SO;
+}
+end;
+
+procedure TMenu.UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide;
+  SelectNum: integer; const Values: array of UTF8String; var Data: integer);
+var
+  SO: integer;
+begin
+  SetLength(SelectsS[SelectNum].TextOptT, 0);
+  for SO := 0 to High(Values) do
+    AddSelectSlideOption(SelectNum, Values[SO]);
+
+  SelectsS[SelectNum].GenLines;
+
+//  SelectsS[SelectNum].SelectedOption := SelectsS[SelectNum].SelectOptInt; // refresh
+//  SelectS[SelectNum].SetSelectOpt(Data);
+//  SelectS[SelectNum].SelectedOption := 0;//Data;
+
+//  Log.LogError(IntToStr(High(SelectsS[SelectNum].TextOptT)));
+//  if 0 <= High(SelectsS[SelectNum].TextOptT) then
+
+  SelectsS[SelectNum].PData := @Data;
+  SelectsS[SelectNum].SelectedOption := Data;
+end;
+
+procedure TMenu.InteractInc;
+var
+  Num:   integer;
+  Value: integer;
+begin
+  case Interactions[Interaction].Typ of
+    iSelectS: begin
+        Num := Interactions[Interaction].Num;
+        Value := SelectsS[Num].SelectedOption;
+//        Value := (Value + 1) Mod (Length(SelectsS[Num].TextOptT));
+
+        // limit
+        Value := Value + 1;
+        if Value <= High(SelectsS[Num].TextOptT) then
+          SelectsS[Num].SelectedOption := Value;
+      end;
+    //Button Collection Mod
+    iBCollectionChild:
+      begin
+
+        //Select Next Button in Collection
+        for Num := 1 to High(Button) do
+        begin
+          Value := (Interaction + Num) Mod Length(Button);
+          if Value = 0 then
+          begin
+            InteractNext;
+            Break;
+          end;
+          if (Button[Value].Parent = Button[Interaction].Parent) then
+          begin
+            Interaction := Value;
+            Break;
+          end;
+        end;
+      end;
+    //interact Next if there is Nothing to Change
+    else InteractNext;
+  end;
+end;
+
+procedure TMenu.InteractDec;
+var
+  Num:   integer;
+  Value: integer;
+begin
+  case Interactions[Interaction].Typ of
+    iSelectS: begin
+        Num := Interactions[Interaction].Num;
+        Value := SelectsS[Num].SelectedOption;
+        Value := Value - 1;
+//        if Value = -1 then
+//          Value := High(SelectsS[Num].TextOptT);
+
+        if Value >= 0 then
+          SelectsS[Num].SelectedOption := Value;
+      end;
+    //Button Collection Mod
+    iBCollectionChild:
+      begin
+        //Select Prev Button in Collection
+        for Num := High(Button) downto 1 do
+        begin
+          Value := (Interaction + Num) Mod Length(Button);
+          if Value = High(Button) then
+          begin
+            InteractPrev;
+            Break;
+          end;
+          if (Button[Value].Parent = Button[Interaction].Parent) then
+          begin
+            Interaction := Value;
+            Break;
+          end;
+        end;
+      end;
+    // interact prev if there is nothing to change
+    else
+      begin
+        InteractPrev;
+        // if buttoncollection with more than 1 entry then select last entry
+        if (Button[Interactions[Interaction].Num].Parent <> 0) and (ButtonCollection[Button[Interactions[Interaction].Num].Parent-1].CountChilds > 1) then
+        begin
+          //Select Last Child
+          for Num := High(Button) downto 1 do
+          begin
+            Value := (Interaction + Num) Mod Length(Button);
+            if (Button[Value].Parent = Button[Interaction].Parent) then
+            begin
+              Interaction := Value;
+              Break;
+            end;
+          end;
+        end;
+      end;
+  end;
+end;
+
+procedure TMenu.AddBox(X, Y, W, H: real);
+begin
+  AddStatic(X,   Y,   W,   H,   0, 0, 0, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED);
+  AddStatic(X+2, Y+2, W-4, H-4, 1, 1, 1, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED);
+end;
+
+procedure TMenu.OnShow;
+begin
+  // FIXME: this needs some work. First, there should be a variable like
+  // VideoBackground so we can check whether a video-background is enabled or not.
+  // Second, a video should be stopped if the screen is hidden, but the Video.Stop()
+  // method is not implemented by now. This is necessary for theme-switching too.
+  // At the moment videos cannot be turned off without restarting USDX.
+
+  {// check if a background texture was found
+  if (BackImg.TexNum = 0)  then
+  begin
+    // try to open an animated background
+    // Note: newer versions of ffmpeg are able to open images like jpeg
+    //   so do not pass an image's filename to VideoPlayback.Open()
+    if fileexists( fFileName ) then
+    begin
+      if VideoPlayback.Open( fFileName ) then
+      begin
+        VideoBGTimer.SetTime(0);
+        VideoPlayback.Play;
+      end;
+    end;
+  end; }
+  if (Background = nil) then
+    AddBackground(DEFAULT_BACKGROUND);
+
+  Background.OnShow;
+end;
+
+procedure TMenu.OnShowFinish;
+begin
+  // nothing
+end;
+
+procedure TMenu.OnHide;
+begin
+  // nothing
+  Background.OnFinish;
+end;
+
+function TMenu.ParseInput(PressedKey: Cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  // nothing
+  Result := true;
+end;
+
+function TMenu.ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean;
+var
+  nBut: integer;
+  Action: TMouseClickAction;
+begin
+  //default mouse parsing: clicking generates return keypress,
+  //  mousewheel selects in select slide
+  //override ParseMouse to customize
+  Result := true;
+
+  if RightMbESC and (MouseButton = SDL_BUTTON_RIGHT) and BtnDown then
+  begin
+    //if RightMbESC is set, send ESC keypress
+    Result:=ParseInput(SDLK_ESCAPE, 0, true);
+  end;
+
+  // transfer mousecords to the 800x600 raster we use to draw
+  X := Round((X / (ScreenW / Screens)) * RenderW);
+  if (X > RenderW) then
+    X := X - RenderW;
+  Y := Round((Y / ScreenH) * RenderH);
+
+  // allways go to next screen if we don't have any interactions
+  if Length(Interactions) = 0 then
+  begin
+    if (BtnDown) and (MouseButton = SDL_BUTTON_LEFT) then
+      Result := ParseInput(SDLK_RETURN, 0, true);
+  end
+  else
+  begin
+    nBut := InteractAt(X, Y);
+    if nBut >= 0 then
+    begin
+      //select on mouse-over
+      if nBut <> Interaction then
+        SetInteraction(nBut);
+
+      Action := maNone;
+
+      if (BtnDown) then
+      begin
+        if (MouseButton = SDL_BUTTON_LEFT) then
+        begin
+          //click button or SelectS
+          if (Interactions[nBut].Typ = iSelectS) then
+            Action := SelectsS[Interactions[nBut].Num].OnClick(X, Y)
+          else
+            Action := maReturn;
+        end
+        else if (MouseButton = SDL_BUTTON_WHEELDOWN) then
+        begin //forward on select slide with mousewheel
+          if (Interactions[nBut].Typ = iSelectS) then
+            Action := maRight;
+        end
+        else if (MouseButton = SDL_BUTTON_WHEELUP) then
+        begin //backward on select slide with mousewheel
+          if (Interactions[nBut].Typ = iSelectS) then
+            Action := maLeft;
+        end;
+      end;
+
+        // do the action we have to do ;)
+      case Action of
+        maReturn: Result := ParseInput(SDLK_RETURN, 0, true);
+        maLeft:   Result := ParseInput(SDLK_LEFT, 0, true);
+        maRight:  Result := ParseInput(SDLK_RIGHT, 0, true);
+      end;
+    end
+    else
+    begin
+      nBut := CollectionAt(X, Y);
+      if (nBut >= 0) and (not ButtonCollection[nBut].Selected) then
+      begin
+        // if over button collection, that is not already selected
+        // -> select first child but don't allow click
+        nBut := ButtonCollection[nBut].FirstChild - 1;
+        if nBut <> Interaction then
+          SetInteraction(nBut);
+      end;
+    end;
+  end;
+end;
+
+function TMenu.InRegion(X, Y: real; A: TMouseOverRect): boolean;
+begin
+  // check whether A contains X and Y
+  Result := (X >= A.X) and (X <= A.X + A.W) and (Y >= A.Y) and (Y <= A.Y + A.H);
+end;
+
+//takes x,y coordinates and returns the interaction number
+//of the control at this position
+function TMenu.InteractAt(X, Y: real): integer;
+var
+  i, nBut: integer;
+begin
+  Result := -1;
+  for i := Low(Interactions) to High(Interactions) do
+  begin
+    case Interactions[i].Typ of
+      iButton:
+        if InRegion(X, Y, Button[Interactions[i].Num].GetMouseOverArea) and
+           Button[Interactions[i].Num].Visible then
+        begin
+          Result:=i;
+          exit;
+        end;
+      iBCollectionChild:
+        if InRegion(X, Y, Button[Interactions[i].Num].GetMouseOverArea) then
+        begin
+          Result:=i;
+          exit;
+        end;
+      iSelectS:
+        if InRegion(X, Y, SelectSs[Interactions[i].Num].GetMouseOverArea)  then
+      	begin
+          Result:=i;
+          exit;
+        end;
+    end;
+  end;
+end;
+
+//takes x,y coordinates and returns the button collection id
+function TMenu.CollectionAt(X, Y: real): integer;
+var
+  i, nBut: integer;
+begin
+  Result := -1;
+  for i:= Low(ButtonCollection) to High(ButtonCollection) do
+  begin
+    if InRegion(X, Y, ButtonCollection[i].GetMouseOverArea) and
+        ButtonCollection[i].Visible then
+    begin
+      Result:=i;
+      exit;
+    end;
+  end;
+end;
+
+procedure TMenu.SetAnimationProgress(Progress: real);
+begin
+  // nothing
+end;
+
+end.
diff --git a/songmanagement/src/menu/UMenuBackground.pas b/songmanagement/src/menu/UMenuBackground.pas
new file mode 100644
index 00000000..0e2e63a6
--- /dev/null
+++ b/songmanagement/src/menu/UMenuBackground.pas
@@ -0,0 +1,83 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuBackground;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  UThemes;
+
+//TMenuBackground - abstraction class for MenuBackgrounds
+//this is a class, not an interface because of the constructors
+//and destructors
+//--------
+
+type
+  EMenuBackgroundError = class(Exception);
+  TMenuBackground = class
+    constructor Create(const ThemedSettings: TThemeBackground); virtual;
+    procedure   OnShow; virtual;
+    procedure   Draw; virtual;
+    procedure   OnFinish; virtual;
+    destructor  Destroy; override;
+  end;
+  cMenuBackground = class of TMenuBackground;
+
+implementation
+
+constructor TMenuBackground.Create(const ThemedSettings: TThemeBackground);
+begin
+  inherited Create;
+end;
+
+destructor  TMenuBackground.Destroy;
+begin
+  inherited;
+end;
+
+procedure   TMenuBackground.OnShow;
+begin
+
+end;
+
+procedure   TMenuBackground.OnFinish;
+begin
+
+end;
+
+procedure   TMenuBackground.Draw;
+begin
+
+end;
+
+end.
diff --git a/songmanagement/src/menu/UMenuBackgroundColor.pas b/songmanagement/src/menu/UMenuBackgroundColor.pas
new file mode 100644
index 00000000..45b58c1e
--- /dev/null
+++ b/songmanagement/src/menu/UMenuBackgroundColor.pas
@@ -0,0 +1,73 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuBackgroundColor;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UThemes,
+  UMenuBackground;
+
+//TMenuBackgroundColor - Background Color
+//--------
+
+type
+  TMenuBackgroundColor = class (TMenuBackground)
+    private
+      Color: TRGB;
+    public
+      constructor Create(const ThemedSettings: TThemeBackground); override;
+      procedure   Draw; override;
+  end;
+
+implementation
+uses
+  gl,
+  glext,
+  UGraphic;
+
+constructor TMenuBackgroundColor.Create(const ThemedSettings: TThemeBackground);
+begin
+  inherited;
+  Color := ThemedSettings.Color;
+end;
+
+procedure   TMenuBackgroundColor.Draw;
+begin
+  if (ScreenAct = 1) then
+  begin //just clear once, even when using two screens
+   glClearColor(Color.R, Color.G, Color.B, 0);
+   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+  end;
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/menu/UMenuBackgroundFade.pas b/songmanagement/src/menu/UMenuBackgroundFade.pas
new file mode 100644
index 00000000..6d877baa
--- /dev/null
+++ b/songmanagement/src/menu/UMenuBackgroundFade.pas
@@ -0,0 +1,176 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuBackgroundFade;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UThemes,
+  UTexture,
+  UMenuBackground,
+  UPath;
+
+//TMenuBackgroundFade - Background Fade In for Overlay screens
+//--------
+
+type
+  TMenuBackgroundFade = class (TMenuBackground)
+    private
+      Tex:        TTexture;
+      Color:      TRGB;
+      Alpha:      real;
+      
+      useTexture: boolean;
+
+      FadeTime:   cardinal;
+    public
+      constructor Create(const ThemedSettings: TThemeBackground); override;
+      procedure   OnShow; override;
+      procedure   Draw; override;
+      destructor  Destroy; override;
+  end;
+
+const
+  FADEINTIME = 1500; //Time the bg fades in
+
+implementation
+uses
+  sdl,
+  gl,
+  glext,
+  USkins,
+  UCommon,
+  UGraphic;
+
+constructor TMenuBackgroundFade.Create(const ThemedSettings: TThemeBackground);
+var
+  texFilename: IPath;
+begin
+  inherited;
+  FadeTime := 0;
+
+  Color := ThemedSettings.Color;
+  Alpha := ThemedSettings.Alpha;
+  if (Length(ThemedSettings.Tex) > 0) then
+  begin
+    texFilename := Skin.GetTextureFileName(ThemedSettings.Tex);
+    Tex         := Texture.GetTexture(texFilename, TEXTURE_TYPE_PLAIN);
+
+    UseTexture  := (Tex.TexNum <> 0);
+  end
+  else
+    UseTexture := false;
+
+  if (not UseTexture) then
+    FreeandNil(Tex);
+end;
+
+destructor  TMenuBackgroundFade.Destroy;
+begin
+  //Why isn't there any Tex.free method?
+  {if UseTexture then
+    FreeandNil(Tex); }
+  inherited;
+end;
+
+procedure   TMenuBackgroundFade.OnShow;
+begin
+  FadeTime := SDL_GetTicks;
+end;
+
+procedure   TMenuBackgroundFade.Draw;
+var
+  Progress: real;
+begin
+  if FadeTime = 0 then
+    Progress := Alpha
+  else
+    Progress := Alpha * (SDL_GetTicks - FadeTime) / FADEINTIME;
+
+  if Progress > Alpha then
+  begin
+    FadeTime := 0;
+    Progress := Alpha;
+  end;
+
+  if (UseTexture) then
+  begin //Draw Texture to Screen
+    if (ScreenAct = 1) then //Clear just once when in dual screen mode
+      glClear(GL_DEPTH_BUFFER_BIT);
+
+    glEnable(GL_TEXTURE_2D);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    glColorRGB(Color, Progress);
+    glBindTexture(GL_TEXTURE_2D, Tex.TexNum);
+
+    glBegin(GL_QUADS);
+      glTexCoord2f(Tex.TexX1*Tex.TexW, Tex.TexY1*Tex.TexH);
+      glVertex2f(0, 0);
+
+      glTexCoord2f(Tex.TexX1*Tex.TexW, Tex.TexY2*Tex.TexH);
+      glVertex2f(0, 600);
+
+      glTexCoord2f(Tex.TexX2*Tex.TexW, Tex.TexY2*Tex.TexH);
+      glVertex2f(800, 600);
+
+      glTexCoord2f(Tex.TexX2*Tex.TexW, Tex.TexY1*Tex.TexH);
+      glVertex2f(800, 0);
+    glEnd;
+
+    glDisable(GL_BLEND);
+    glDisable(GL_TEXTURE_2D);
+  end
+  else
+  begin //Clear Screen w/ progress Alpha + Color
+    if (ScreenAct = 1) then //Clear just once when in dual screen mode
+      glClear(GL_DEPTH_BUFFER_BIT);
+      
+    glDisable(GL_TEXTURE_2D);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    glColorRGB(Color, Progress);
+
+    glBegin(GL_QUADS);
+      glVertex2f(0, 0);
+      glVertex2f(0, 600);
+      glVertex2f(800, 600);
+      glVertex2f(800, 0);
+    glEnd;
+
+    glDisable(GL_BLEND);
+  end;  
+end;
+
+end.
diff --git a/songmanagement/src/menu/UMenuBackgroundNone.pas b/songmanagement/src/menu/UMenuBackgroundNone.pas
new file mode 100644
index 00000000..c64f3023
--- /dev/null
+++ b/songmanagement/src/menu/UMenuBackgroundNone.pas
@@ -0,0 +1,70 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuBackgroundNone;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UThemes,
+  UMenuBackground;
+
+//TMenuBackgroundNone - Just no Background (e.g. for Overlays)
+//--------
+
+type
+  TMenuBackgroundNone = class (TMenuBackground)
+    private
+
+    public
+      constructor Create(const ThemedSettings: TThemeBackground); override;
+      procedure   Draw; override;
+  end;
+
+implementation
+uses
+  gl,
+  glext,
+  UGraphic;
+
+constructor TMenuBackgroundNone.Create(const ThemedSettings: TThemeBackground);
+begin
+  inherited;
+end;
+
+procedure   TMenuBackgroundNone.Draw;
+begin
+  //Do just nothing in here!
+  If (ScreenAct = 1) then //Clear just once when in dual screen mode
+    glClear(GL_DEPTH_BUFFER_BIT);
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/menu/UMenuBackgroundTexture.pas b/songmanagement/src/menu/UMenuBackgroundTexture.pas
new file mode 100644
index 00000000..f71637ff
--- /dev/null
+++ b/songmanagement/src/menu/UMenuBackgroundTexture.pas
@@ -0,0 +1,126 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuBackgroundTexture;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UThemes,
+  UTexture,
+  UMenuBackground,
+  UPath;
+
+//TMenuBackgroundColor - Background Color
+//--------
+
+type
+  TMenuBackgroundTexture = class (TMenuBackground)
+    private
+      Tex: TTexture;
+      Color: TRGB;
+    public
+      constructor Create(const ThemedSettings: TThemeBackground); override;
+      procedure   Draw; override;
+      destructor  Destroy; override;
+  end;
+
+const
+  SUPPORTED_EXTS_BACKGROUNDTEXTURE: array[0..13] of string = ('.png', '.bmp', '.jpg', '.jpeg', '.gif', '.pnm', '.ppm', '.pgm', '.pbm', '.xpm', '.lbm', '.pcx', '.tga', '.tiff');
+
+implementation
+uses
+  USkins,
+  UCommon,
+  SysUtils,
+  gl,
+  glext,
+  UGraphic;
+
+constructor TMenuBackgroundTexture.Create(const ThemedSettings: TThemeBackground);
+var
+  texFilename: IPath;
+begin
+  inherited;
+
+  if (Length(ThemedSettings.Tex) = 0) then
+    raise EMenuBackgroundError.Create('TMenuBackgroundTexture: No texture filename present');
+
+  Color       := ThemedSettings.Color;
+
+  texFilename := Skin.GetTextureFileName(ThemedSettings.Tex);
+  Tex         := Texture.GetTexture(texFilename, TEXTURE_TYPE_PLAIN);
+
+  if (Tex.TexNum = 0) then
+  begin
+    freeandnil(Tex);
+    raise EMenuBackgroundError.Create('TMenuBackgroundTexture: Can''t load texture');
+  end;
+end;
+
+destructor  TMenuBackgroundTexture.Destroy;
+begin
+  //freeandnil(Tex); <- this causes an Access Violation o0
+  inherited;
+end;
+
+procedure   TMenuBackgroundTexture.Draw;
+begin
+  If (ScreenAct = 1) then //Clear just once when in dual screen mode
+    glClear(GL_DEPTH_BUFFER_BIT);
+    
+  glColorRGB(Color);
+
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  glBindTexture(GL_TEXTURE_2D, Tex.TexNum);
+
+  glBegin(GL_QUADS);
+    glTexCoord2f(Tex.TexX1*Tex.TexW, Tex.TexY1*Tex.TexH);
+    glVertex2f(0, 0);
+
+    glTexCoord2f(Tex.TexX1*Tex.TexW, Tex.TexY2*Tex.TexH);
+    glVertex2f(0, 600);
+
+    glTexCoord2f(Tex.TexX2*Tex.TexW, Tex.TexY2*Tex.TexH);
+    glVertex2f(800, 600);
+
+    glTexCoord2f(Tex.TexX2*Tex.TexW, Tex.TexY1*Tex.TexH);
+    glVertex2f(800, 0);
+  glEnd;
+
+  glDisable(GL_BLEND);
+  glDisable(GL_TEXTURE_2D);
+end;
+
+end.
diff --git a/songmanagement/src/menu/UMenuBackgroundVideo.pas b/songmanagement/src/menu/UMenuBackgroundVideo.pas
new file mode 100644
index 00000000..9a33e721
--- /dev/null
+++ b/songmanagement/src/menu/UMenuBackgroundVideo.pas
@@ -0,0 +1,211 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuBackgroundVideo;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UThemes,
+  UMenuBackground,
+  UMusic,
+  UVideo,
+  UPath;
+
+//TMenuBackgroundColor - Background Color
+//--------
+
+type
+  //DefaultBGVideoPlayback = TVideoPlayback_FFmpeg;
+
+{type
+  TBGVideoPool = class;
+
+  PBGVideoPoolItem = ^TBGVideoPoolItem;
+  TBGVideoPoolItem = record
+    Parent: TBGVideoPool;
+    VideoPlayback = IVideoPlayback;
+    ReferenceCounter: cardinal; //Number of Creations
+  end;
+
+  TBGVideo = class
+    private
+      myItem: PBGVideoPoolItem;
+    public
+      constructor Create(Item: PBGVideoPoolItem); override;
+
+      function    GetVideoPlayback: IVideoPlayback;
+      procedure   Draw;
+
+      destructor  Destroy;
+  end;
+
+  TBGVideoPool = class
+    private
+      Items: PBGVideoPoolItem;
+    public
+      constructor Create;
+
+      function    GetBGVideo(filename: IPath): TBGVideo;
+      procedure   RemoveItem(
+      procedure   FreeAllItems;
+
+      destructor  Destroy;
+  end;
+
+type }
+  TMenuBackgroundVideo = class (TMenuBackground)
+    private
+      fFilename: IPath;
+      fBgVideo: IVideo;
+    public
+      constructor Create(const ThemedSettings: TThemeBackground); override;
+      procedure   OnShow; override;
+      procedure   Draw; override;
+      procedure   OnFinish; override;
+      destructor  Destroy; override;
+  end;
+
+{var
+  BGVideoPool: TBGVideoPool;  }
+const
+  SUPPORTED_EXTS_BACKGROUNDVIDEO: array[0..6] of string = ('.avi', '.mov', '.divx', '.mpg', '.mp4', '.mpeg', '.m2v');
+
+implementation
+
+uses
+  gl,
+  glext,
+  SysUtils,
+  UTime,
+  USkins,
+  UCommon,
+  UGraphic;
+
+constructor TMenuBackgroundVideo.Create(const ThemedSettings: TThemeBackground);
+begin
+  inherited;
+  if (Length(ThemedSettings.Tex) = 0) then
+    raise EMenuBackgroundError.Create('TMenuBackgroundVideo: No video filename present');
+
+  fFileName := Skin.GetTextureFileName(ThemedSettings.Tex);
+  if (not fFilename.IsFile) then
+    raise EMenuBackgroundError.Create('TMenuBackgroundVideo: Can''t load background video: ' + fFilename.ToNative);
+end;
+
+destructor  TMenuBackgroundVideo.Destroy;
+begin
+end;
+
+procedure TMenuBackgroundVideo.OnShow;
+begin
+  fBgVideo := VideoPlayback.Open(fFileName);
+  if (fBgVideo <> nil) then
+  begin
+    VideoBGTimer.SetTime(0);
+    VideoBGTimer.Start();
+    fBgVideo.Loop := true;
+    fBgVideo.Play;
+  end;
+end;
+
+procedure   TMenuBackgroundVideo.OnFinish;
+begin
+  // unload video
+  fBgVideo := nil;
+end;
+
+procedure TMenuBackgroundVideo.Draw;
+begin
+  // clear just once when in dual screen mode
+  if (ScreenAct = 1) then
+  begin
+    glClear(GL_DEPTH_BUFFER_BIT);
+    // video failure -> draw blank background
+    if (fBgVideo = nil) then
+      glClear(GL_COLOR_BUFFER_BIT);
+  end;
+
+  if (fBgVideo <> nil) then
+  begin
+    fBgVideo.GetFrame(VideoBGTimer.GetTime());
+    fBgVideo.SetScreen(ScreenAct);
+    fBgVideo.Draw();
+  end;
+end;
+
+// Implementation of TBGVideo
+//--------
+{constructor TBGVideo.Create(Item: PBGVideoPoolItem);
+begin
+  myItem := PBGVideoPoolItem;
+  Inc(myItem.ReferenceCounter);
+end;
+
+destructor  TBGVideo.Destroy;
+begin
+  Dec(myItem.ReferenceCounter);
+end;
+
+function    TBGVideo.GetVideoPlayback: IVideoPlayback;
+begin
+
+end;
+
+procedure   TBGVideo.Draw;
+begin
+
+end;
+
+// Implementation of TBGVideoPool
+//--------
+
+constructor TBGVideoPool.Create;
+begin
+
+end;
+
+destructor  TBGVideoPool.Destroy;
+begin
+
+end;
+
+function    TBGVideoPool.GetBGVideo(filename: IPath): TBGVideo;
+begin
+
+end;
+
+procedure   TBGVideoPool.FreeAllItems;
+begin
+
+end;  }
+
+end.
diff --git a/songmanagement/src/menu/UMenuButton.pas b/songmanagement/src/menu/UMenuButton.pas
new file mode 100644
index 00000000..868a86f3
--- /dev/null
+++ b/songmanagement/src/menu/UMenuButton.pas
@@ -0,0 +1,647 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuButton;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  TextGL,
+  UTexture,
+  gl,
+  UMenuText,
+  SDL,
+  UMenuInteract;
+
+type
+  CButton = class of TButton;
+
+  TButton = class
+    protected
+      SelectBool:   boolean;
+
+      FadeProgress: real;
+      FadeLastTick: cardinal;
+
+      DeSelectW,
+      DeSelectH,
+      PosX,
+      PosY:         real;
+
+
+    public
+      Text:                      array of TText;
+      Texture:                   TTexture; // Button Screen position and size
+      Texture2:                  TTexture; // second texture only used for fading full resolution covers
+
+      Colorized:                 boolean;
+      DeSelectTexture:           TTexture; // texture for colorized hack
+
+      FadeTex:                   TTexture; //Texture for beautiful fading
+      FadeTexPos:                byte;     //Pos of the FadeTexture (0: Top, 1: Left, 2: Bottom, 3: Right)
+
+      DeselectType:              integer;  // not used yet
+      Visible:                   boolean;
+
+      Reflection:                boolean;
+      Reflectionspacing,
+      DeSelectReflectionspacing: real;
+
+      Fade,
+      FadeText:                  boolean;
+
+      Selectable:                boolean;
+
+      //Number of the Parent Collection, 0 if in no Collection
+      Parent:  byte;
+
+      SelectColR,
+      SelectColG,
+      SelectColB,
+      SelectInt,
+      SelectTInt:   real;
+      //Fade Mod
+      SelectW:      real;
+      SelectH:      real;
+
+      DeselectColR,
+      DeselectColG,
+      DeselectColB,
+      DeselectInt,
+      DeselectTInt: real;
+
+      procedure SetY(Value: real);
+      procedure SetX(Value: real);
+      procedure SetW(Value: real);
+      procedure SetH(Value: real);
+
+      procedure SetSelect(Value: boolean); virtual;
+      property X: real read PosX write SetX;
+      property Y: real read PosY write SetY;
+      property Z: real read Texture.z write Texture.z;
+      property W: real read DeSelectW write SetW;
+      property H: real read DeSelectH write SetH;
+      property Selected: boolean read SelectBool write SetSelect;
+
+      procedure   Draw; virtual;
+
+      constructor Create(); overload;
+      constructor Create(Textura: TTexture); overload;
+      constructor Create(Textura, DSTexture: TTexture); overload;
+      destructor  Destroy; override;
+
+      function GetMouseOverArea: TMouseOverRect;
+  end;
+
+implementation
+
+uses 
+  SysUtils,
+  UDrawTexture;
+
+procedure TButton.SetX(Value: real);
+{var
+  dx:   real;
+  T:    integer;    // text}
+begin
+  {dY := Value - Texture.y;
+
+  Texture.X := Value;
+
+  for T := 0 to High(Text) do
+    Text[T].X := Text[T].X + dY;}
+
+  PosX := Value;
+  if (FadeTex.TexNum = 0) then
+    Texture.X := Value;
+
+end;
+
+procedure TButton.SetY(Value: real);
+{var
+  dY: real;
+  T:  integer;    // text}
+begin
+  {dY := Value - PosY;
+
+
+  for T := 0 to High(Text) do
+    Text[T].Y := Text[T].Y + dY;}
+
+  PosY := Value;
+  if (FadeTex.TexNum = 0) then
+    Texture.y := Value;
+end;
+
+procedure TButton.SetW(Value: real);
+begin
+  if SelectW = DeSelectW then
+    SelectW := Value;
+
+  DeSelectW := Value;
+
+  if not Fade then
+  begin
+    if SelectBool then
+      Texture.W := SelectW
+    else
+      Texture.W := DeSelectW;
+  end;
+end;
+
+procedure TButton.SetH(Value: real);
+begin
+  if SelectH = DeSelectH then
+    SelectH := Value;
+
+  DeSelectH := Value;
+
+  if not Fade then
+  begin
+    if SelectBool then
+      Texture.H := SelectH
+    else
+      Texture.H := DeSelectH;
+  end;
+end;
+
+procedure TButton.SetSelect(Value : boolean);
+var
+  T: integer;
+begin
+  SelectBool := Value;
+
+  if (Value) then
+  begin
+    Texture.ColR  := SelectColR;
+    Texture.ColG  := SelectColG;
+    Texture.ColB  := SelectColB;
+    Texture.Int   := SelectInt;
+
+    Texture2.ColR := SelectColR;
+    Texture2.ColG := SelectColG;
+    Texture2.ColB := SelectColB;
+    Texture2.Int  := SelectInt;
+
+    for T := 0 to High(Text) do
+      Text[T].Int := SelectTInt;
+
+    //Fade Mod
+    if Fade then
+    begin
+      if (FadeProgress <= 0) then
+        FadeProgress := 0.125;
+    end
+    else
+    begin
+      Texture.W := SelectW;
+      Texture.H := SelectH;
+    end;
+  end
+  else
+  begin
+    Texture.ColR  := DeselectColR;
+    Texture.ColG  := DeselectColG;
+    Texture.ColB  := DeselectColB;
+    Texture.Int   := DeselectInt;
+
+    Texture2.ColR := DeselectColR;
+    Texture2.ColG := DeselectColG;
+    Texture2.ColB := DeselectColB;
+    Texture2.Int  := DeselectInt;
+
+    for T := 0 to High(Text) do
+      Text[T].Int := DeselectTInt;
+
+    //Fade Mod
+    if Fade then
+    begin
+      if (FadeProgress >= 1) then
+        FadeProgress := 0.875;
+    end
+    else
+    begin
+      Texture.W := DeSelectW;
+      Texture.H := DeSelectH;
+    end;
+  end;
+end;
+
+// ***** Public methods ****** //
+
+procedure TButton.Draw;
+var
+  T:       integer;
+  Tick:    cardinal;
+  Spacing: real;
+begin
+  if Visible then
+  begin
+    //Fade Mod
+    T:=0;
+    if Fade then
+    begin
+      if (FadeProgress < 1) and (FadeProgress > 0) then
+      begin
+        Tick := SDL_GetTicks() div 16;
+        if (Tick <> FadeLastTick) then
+        begin
+          FadeLastTick := Tick;
+
+          if SelectBool then
+            FadeProgress := FadeProgress + 0.125
+          else
+            FadeProgress := FadeProgress - 0.125;
+
+          if (FadeText) then
+          begin
+            for T := 0 to high(Text) do
+            begin
+              Text[T].MoveX := (SelectW - DeSelectW) * FadeProgress;
+              Text[T].MoveY := (SelectH - DeSelectH) * FadeProgress;
+            end;
+          end;
+
+        end;
+      end;
+
+      //Method without Fade Texture
+      if (FadeTex.TexNum = 0) then
+      begin
+        Texture.W         := DeSelectW + (SelectW - DeSelectW) * FadeProgress;
+        Texture.H         := DeSelectH + (SelectH - DeSelectH) * FadeProgress;
+        DeSelectTexture.W := Texture.W;
+        DeSelectTexture.H := Texture.H;
+      end
+      else //method with Fade Texture
+      begin
+        Texture.W         := DeSelectW;
+        Texture.H         := DeSelectH;
+        DeSelectTexture.W := Texture.W;
+        DeSelectTexture.H := Texture.H;
+
+        FadeTex.ColR      := Texture.ColR;
+        FadeTex.ColG      := Texture.ColG;
+        FadeTex.ColB      := Texture.ColB;
+        FadeTex.Int       := Texture.Int;
+
+        FadeTex.Z         := Texture.Z;
+
+        FadeTex.Alpha     := Texture.Alpha;
+        FadeTex.TexX1     := 0;
+        FadeTex.TexX2     := 1;
+        FadeTex.TexY1     := 0;
+        FadeTex.TexY2     := 1;
+
+        case FadeTexPos of
+          0: //FadeTex on Top
+            begin
+              //Standard Texture
+              Texture.X := PosX;
+              Texture.Y := PosY + (SelectH - DeSelectH) * FadeProgress;
+              DeSelectTexture.X := Texture.X;
+              DeSelectTexture.Y := Texture.Y;
+              //Fade Tex
+              FadeTex.X := PosX;
+              FadeTex.Y := PosY;
+              FadeTex.W := Texture.W;
+              FadeTex.H := (SelectH - DeSelectH) * FadeProgress;
+              FadeTex.ScaleW := Texture.ScaleW;
+              //Some Hack that Fixes a little Space between both Textures
+              FadeTex.TexY2 := 0.9;
+            end;
+          1: //FadeTex on Left
+            begin
+              //Standard Texture
+              Texture.X := PosX + (SelectW - DeSelectW) * FadeProgress;
+              Texture.Y := PosY;
+              DeSelectTexture.X := Texture.X;
+              DeSelectTexture.Y := Texture.Y;
+              //Fade Tex
+              FadeTex.X := PosX;
+              FadeTex.Y := PosY;
+              FadeTex.H := Texture.H;
+              FadeTex.W := (SelectW - DeSelectW) * FadeProgress;
+              FadeTex.ScaleH := Texture.ScaleH;
+              //Some Hack that Fixes a little Space between both Textures
+              FadeTex.TexX2 := 0.9;
+            end;
+          2: //FadeTex on Bottom
+            begin
+              //Standard Texture
+              Texture.X := PosX;
+              Texture.Y := PosY;
+              DeSelectTexture.X := Texture.X;
+              DeSelectTexture.Y := Texture.Y;
+              //Fade Tex
+              FadeTex.X := PosX;
+              FadeTex.Y := PosY  + (SelectH - DeSelectH) * FadeProgress;;
+              FadeTex.W := Texture.W;
+              FadeTex.H := (SelectH - DeSelectH) * FadeProgress;
+              FadeTex.ScaleW := Texture.ScaleW;
+              //Some Hack that Fixes a little Space between both Textures
+              FadeTex.TexY1 := 0.1;
+            end;
+          3: //FadeTex on Right
+            begin
+              //Standard Texture
+              Texture.X := PosX;
+              Texture.Y := PosY;
+              DeSelectTexture.X := Texture.X;
+              DeSelectTexture.Y := Texture.Y;
+              //Fade Tex
+              FadeTex.X := PosX + (SelectW - DeSelectW) * FadeProgress;
+              FadeTex.Y := PosY;
+              FadeTex.H := Texture.H;
+              FadeTex.W := (SelectW - DeSelectW) * FadeProgress;
+              FadeTex.ScaleH := Texture.ScaleH;
+              //Some Hack that Fixes a little Space between both Textures
+              FadeTex.TexX1 := 0.1;
+            end;
+        end;
+      end;
+    end
+    else if (FadeText) then
+    begin
+      Text[T].MoveX := (SelectW - DeSelectW);
+      Text[T].MoveY := (SelectH - DeSelectH);
+    end;
+
+    if SelectBool or (FadeProgress > 0) or not Colorized then
+      DrawTexture(Texture)
+    else
+    begin
+      DeSelectTexture.X := Texture.X;
+      DeSelectTexture.Y := Texture.Y;
+      DeSelectTexture.H := Texture.H;
+      DeSelectTexture.W := Texture.W;
+      DrawTexture(DeSelectTexture);
+    end;
+
+    //Draw FadeTex
+    if (FadeTex.TexNum > 0) then
+      DrawTexture(FadeTex);
+
+    if Texture2.Alpha > 0 then
+    begin
+      Texture2.ScaleW := Texture.ScaleW;
+      Texture2.ScaleH := Texture.ScaleH;
+
+      Texture2.X := Texture.X;
+      Texture2.Y := Texture.Y;
+      Texture2.W := Texture.W;
+      Texture2.H := Texture.H;
+
+      Texture2.ColR := Texture.ColR;
+      Texture2.ColG := Texture.ColG;
+      Texture2.ColB := Texture.ColB;
+      Texture2.Int := Texture.Int;
+
+      Texture2.Z := Texture.Z;
+
+      DrawTexture(Texture2);
+    end;
+
+    //Reflection Mod
+    if (Reflection) then // Draw Reflections
+    begin
+      if (FadeProgress <> 0) and (FadeProgress <> 1) then
+      begin
+        Spacing := DeSelectReflectionspacing - (DeSelectReflectionspacing - Reflectionspacing) * FadeProgress;
+      end
+      else if SelectBool then
+        Spacing := Reflectionspacing
+      else
+        Spacing := DeSelectReflectionspacing;
+
+      if SelectBool or not Colorized then
+      with Texture do
+      begin
+        //Bind Tex and GL Attributes
+        glEnable(GL_TEXTURE_2D);
+        glEnable(GL_BLEND);
+
+        glDepthRange(0, 10);
+        glDepthFunc(GL_LEQUAL);
+        glEnable(GL_DEPTH_TEST);
+
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        glBindTexture(GL_TEXTURE_2D, TexNum);
+
+        //Draw
+        glBegin(GL_QUADS);//Top Left
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3);
+          glTexCoord2f(TexX1*TexW, TexY2*TexH);
+          glVertex3f(x, y+h*scaleH+ Spacing, z);
+
+          //Bottom Left
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, 0);
+          glTexCoord2f(TexX1*TexW, TexY1+TexH*0.5);
+          glVertex3f(x, y+h*scaleH + h*scaleH/2 + Spacing, z);
+
+
+          //Bottom Right
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, 0);
+          glTexCoord2f(TexX2*TexW, TexY1+TexH*0.5);
+          glVertex3f(x+w*scaleW, y+h*scaleH + h*scaleH/2 + Spacing, z);
+
+          //Top Right
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3);
+          glTexCoord2f(TexX2*TexW, TexY2*TexH);
+          glVertex3f(x+w*scaleW, y+h*scaleH + Spacing, z);
+        glEnd;
+
+        glDisable(GL_TEXTURE_2D);
+        glDisable(GL_DEPTH_TEST);
+        glDisable(GL_BLEND);
+      end
+      else
+      with DeSelectTexture do
+      begin
+        //Bind Tex and GL Attributes
+        glEnable(GL_TEXTURE_2D);
+        glEnable(GL_BLEND);
+
+        glDepthRange(0, 10);
+        glDepthFunc(GL_LEQUAL);
+        glEnable(GL_DEPTH_TEST);
+
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        glBindTexture(GL_TEXTURE_2D, TexNum);
+
+        //Draw
+        glBegin(GL_QUADS);//Top Left
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3);
+          glTexCoord2f(TexX1*TexW, TexY2*TexH);
+          glVertex3f(x, y+h*scaleH+ Spacing, z);
+
+          //Bottom Left
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, 0);
+          glTexCoord2f(TexX1*TexW, TexY1+TexH*0.5);
+          glVertex3f(x, y+h*scaleH + h*scaleH/2 + Spacing, z);
+
+          //Bottom Right
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, 0);
+          glTexCoord2f(TexX2*TexW, TexY1+TexH*0.5);
+          glVertex3f(x+w*scaleW, y+h*scaleH + h*scaleH/2 + Spacing, z);
+
+          //Top Right
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3);
+          glTexCoord2f(TexX2*TexW, TexY2*TexH);
+          glVertex3f(x+w*scaleW, y+h*scaleH + Spacing, z);
+        glEnd;
+
+        glDisable(GL_TEXTURE_2D);
+        glDisable(GL_DEPTH_TEST);
+        glDisable(GL_BLEND);
+      end;
+    end;
+
+    for T := 0 to High(Text) do
+    begin
+      Text[T].Draw;
+    end;
+  end;
+end;
+
+function TButton.GetMouseOverArea: TMouseOverRect;
+begin
+  if (FadeTex.TexNum = 0) then
+  begin
+    Result.X := Texture.X;
+    Result.Y := Texture.Y;
+    Result.W := Texture.W;
+    Result.H := Texture.H;
+  end
+  else
+  begin
+    case FadeTexPos of
+      0: begin // fade tex on top
+        Result.X := Texture.X;
+        Result.Y := FadeTex.Y;
+        Result.W := Texture.W;
+        Result.H := FadeTex.H + Texture.H;
+      end;
+
+      1: begin // fade tex on left side
+        Result.X := FadeTex.X;
+        Result.Y := Texture.Y;
+        Result.W := FadeTex.W + Texture.W;
+        Result.H := Texture.H;
+      end;
+
+      2: begin // fade tex on bottom
+        Result.X := Texture.X;
+        Result.Y := Texture.Y;
+        Result.W := Texture.W;
+        Result.H := FadeTex.H + Texture.H;
+      end;
+
+      3: begin // fade tex on right side
+        Result.X := Texture.X;
+        Result.Y := Texture.Y;
+        Result.W := FadeTex.W + Texture.W;
+        Result.H := Texture.H;
+      end;
+    end;
+  end;
+end;
+
+
+destructor TButton.Destroy;
+begin
+  inherited;
+end;
+
+constructor TButton.Create();
+begin
+  inherited Create;
+  // We initialize all to 0, nil or false
+  Visible        := true;
+  SelectBool     := false;
+  DeselectType   := 0;
+  Selectable     := true;
+  Reflection     := false;
+  Colorized      := false;
+
+  SelectColR     := 1;
+  SelectColG     := 1;
+  SelectColB     := 1;
+  SelectInt      := 1;
+  SelectTInt     := 1;
+
+  DeselectColR   := 1;
+  DeselectColG   := 1;
+  DeselectColB   := 1;
+  DeselectInt    := 0.5;
+  DeselectTInt   := 1;
+
+  Fade           := false;
+  FadeTex.TexNum := 0;
+  FadeProgress   := 0;
+  FadeText       := false;
+  SelectW        := DeSelectW;
+  SelectH        := DeSelectH;
+
+  PosX           := 0;
+  PosY           := 0;
+
+  Parent         := 0;
+end;
+
+constructor TButton.Create(Textura: TTexture);
+begin
+  Create();
+  Texture         := Textura;
+  DeSelectTexture := Textura;
+  Texture.ColR    := 0;
+  Texture.ColG    := 0.5;
+  Texture.ColB    := 0;
+  Texture.Int     := 1;
+  Colorized       := false;
+end;
+
+// Button has the texture-type "colorized"
+// Two textures are generated, one with Col the other one with DCol
+// Check UMenu.pas line 680 to see the call ( AddButton() )
+constructor TButton.Create(Textura, DSTexture: TTexture);
+begin
+  Create();
+  Texture         := Textura;
+  DeSelectTexture := DSTexture;
+  Texture.ColR    := 1;
+  Texture.ColG    := 1;
+  Texture.ColB    := 1;
+  Texture.Int     := 1;
+  Colorized       := true;
+end;
+
+end.
diff --git a/songmanagement/src/menu/UMenuButtonCollection.pas b/songmanagement/src/menu/UMenuButtonCollection.pas
new file mode 100644
index 00000000..8b7a1c3f
--- /dev/null
+++ b/songmanagement/src/menu/UMenuButtonCollection.pas
@@ -0,0 +1,101 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuButtonCollection;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenuButton;
+
+type
+  //----------------
+  //TButtonCollection
+  //No Extra Attributes or Functions ATM
+  //----------------
+  AButton = array of TButton;
+  PAButton = ^AButton;
+  TButtonCollection = class(TButton)
+    //num of the First Button, that can be Selected
+    FirstChild: byte;
+    CountChilds: byte;
+    
+    ScreenButton: PAButton;
+
+    procedure SetSelect(Value : boolean); override;
+    procedure Draw; override;
+  end;
+
+implementation
+
+procedure TButtonCollection.SetSelect(Value : boolean);
+var
+  Index: integer;
+begin
+  inherited;
+
+  //Set Visible for Every Button that is a Child of this ButtonCollection
+  if (not Fade) then
+    for Index := 0 to High(ScreenButton^) do
+      if (ScreenButton^[Index].Parent = Parent) then
+        ScreenButton^[Index].Visible := Value;
+end;
+
+procedure TButtonCollection.Draw;
+var
+  I, J: integer;
+begin
+  inherited;
+  //If fading is activated, Fade Child Buttons
+  if (Fade) then
+  begin
+    for I := 0 to High(ScreenButton^) do
+      if (ScreenButton^[I].Parent = Parent) then
+      begin
+        if (FadeProgress < 0.5) then
+        begin
+          ScreenButton^[I].Visible := SelectBool;
+
+          for J := 0 to High(ScreenButton^[I].Text) do
+            ScreenButton^[I].Text[J].Visible := SelectBool;
+        end
+        else
+        begin
+          ScreenButton^[I].Texture.Alpha := (FadeProgress-0.666)*3;
+          
+          for J := 0 to High(ScreenButton^[I].Text) do
+            ScreenButton^[I].Text[J].Alpha := (FadeProgress-0.666)*3;
+        end;
+      end;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/menu/UMenuEqualizer.pas b/songmanagement/src/menu/UMenuEqualizer.pas
new file mode 100644
index 00000000..8f57e44a
--- /dev/null
+++ b/songmanagement/src/menu/UMenuEqualizer.pas
@@ -0,0 +1,320 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuEqualizer;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMusic,
+  UThemes;
+
+type
+  //----------------
+  //Tms_Equalizer
+  //Class displaying an equalizer (Songscreen)
+  //----------------
+  Tms_Equalizer = class(TObject)
+    private
+      FFTData: TFFTData; // moved here to avoid stack overflows
+      BandData: array of byte;
+      RefreshTime: cardinal;
+
+      Source: IAudioPlayback;
+
+      procedure Analyse;
+    public
+      X: integer;
+      Y: integer;
+      Z: real;
+
+      W: integer;
+      H: integer;
+      Space: integer;
+
+      Visible: boolean;
+      Alpha:   real;
+      Color:   TRGB;
+
+      Direction:  boolean;
+      BandLength: integer;
+
+      Reflection:        boolean;
+      Reflectionspacing: real;
+
+
+      constructor Create(Source: IAudioPlayback; mySkin: TThemeEqualizer);
+
+      procedure Draw;
+      procedure SetBands(Value: byte);
+      function  GetBands: byte;
+      property  Bands: byte read GetBands write SetBands;
+      procedure SetSource(newSource: IAudioPlayback);
+  end;
+
+implementation
+uses
+  math,
+  SDL,
+  gl,
+  glext;
+
+constructor Tms_Equalizer.Create(Source: IAudioPlayback; mySkin: TThemeEqualizer);
+var
+  I: integer;
+begin
+  if (Source <> nil) then
+  begin
+    X          := mySkin.X;
+    Y          := mySkin.Y;
+    W          := mySkin.W;
+    H          := mySkin.H;
+    Z          := mySkin.Z;
+
+    Space      := mySkin.Space;
+
+    Visible    := mySkin.Visible;
+    Alpha      := mySkin.Alpha;
+    Color.R    := mySkin.ColR;
+    Color.G    := mySkin.ColG;
+    Color.B    := mySkin.ColB;
+
+    Direction  := mySkin.Direction;
+    Bands      := mySkin.Bands;
+    BandLength := mySkin.Length;
+
+    Reflection := mySkin.Reflection;
+    Reflectionspacing := mySkin.Reflectionspacing;
+
+    Self.Source := Source;
+
+
+    //Check if Visible
+    if (Bands  <= 0)  or
+       (BandLength <= 0)  or
+       (W      <= 0)  or
+       (H      <= 0)  or
+       (Alpha  <= 0)  then
+      Visible := false;
+
+    //ClearArray
+    for I := low(BandData) to high(BandData) do
+      BandData[I] := 3;
+  end
+  else
+    Visible := false;
+end;
+
+//--------
+// evaluate FFT-Data
+//--------
+procedure Tms_Equalizer.Analyse;
+var
+  I:            integer;
+  ChansPerBand: byte;        // channels per band
+  MaxChannel:   integer;
+  Pos:          real;
+  CurBand:      integer;
+begin
+  Source.GetFFTData(FFTData);
+
+  Pos := 0;
+  // use only the first approx. 92 of 256 FFT-channels (approx. up to 8kHz
+  ChansPerBand := ceil(92 / Bands); // How much channels are used for one Band
+  MaxChannel := ChansPerBand * Bands - 1;
+
+  // Change Lengths
+  for i := 0 to MaxChannel do
+  begin
+    // Gain higher freq. data so that the bars are visible
+    if i > 35 then
+      FFTData[i] := FFTData[i] * 8
+    else if i > 11 then
+      FFTData[i] := FFTData[i] * 4.5
+    else
+      FFTData[i] := FFTData[i] * 1.1;
+
+    // clamp data
+    if (FFTData[i] > 1) then
+      FFTData[i] := 1;
+
+    // Get max. pos
+    if (FFTData[i] * BandLength > Pos) then
+      Pos := FFTData[i] * BandLength;
+
+    // Check if this is the last channel in the band
+    if ((i+1) mod ChansPerBand = 0) then
+    begin
+      CurBand := i div ChansPerBand;
+
+      // Smooth delay if new equalizer is lower than the old one
+      if ((BandData[CurBand] > Pos) and (BandData[CurBand] > 1)) then
+        BandData[CurBand] := BandData[CurBand] - 1
+      else
+        BandData[CurBand] := Round(Pos);
+
+      Pos := 0;
+    end;
+  end;
+end;
+
+//--------
+// Draw SpectrumAnalyser, Call Analyse
+//--------
+procedure Tms_Equalizer.Draw;
+var
+  CurTime:    cardinal;
+  PosX, PosY: real;
+  I, J:       integer;
+  Diff:       real;
+
+  function GetAlpha(Diff: single): single;
+  begin
+    if Direction then
+      Result := (Alpha * 0.6) * (0.5 - Diff/(BandLength * (H + Space)))
+    else
+      Result := (Alpha * 0.6) * (0.5 - Diff/(Bands      * (H + Space)));
+  end;
+
+begin
+  if (Visible) and not (AudioPlayback.Finished) then
+  begin
+    //Call Analyse if necessary
+    CurTime := SDL_GetTicks();
+    if (CurTime > RefreshTime) then
+    begin
+      Analyse;
+
+      RefreshTime := CurTime + 44;
+    end;
+
+    //Draw Equalizer Bands
+    // Setup OpenGL
+    glColorRGB(Color, Alpha);
+    glDisable(GL_TEXTURE_2D);
+    glEnable(GL_BLEND);
+
+    // Set position of the first equalizer bar
+    PosY := Y;
+    PosX := X;
+
+    // Draw bars for each band
+    for I := 0 to High(BandData) do
+    begin
+      // Reset to lower or left position depending on the drawing-direction
+      if Direction then // Vertical bars
+        // FIXME: Is Y the upper or lower coordinate?
+        PosY := Y //+ (H + Space) * BandLength
+      else                                   // Horizontal bars
+        PosX := X;
+
+      // Draw the bar as a stack of blocks
+      for J := 1 to BandData[I] do
+      begin
+        // Draw block
+        glBegin(GL_QUADS);
+          glVertex3f(PosX, PosY, Z);
+          glVertex3f(PosX, PosY+H, Z);
+          glVertex3f(PosX+W, PosY+H, Z);
+          glVertex3f(PosX+W, PosY, Z);
+        glEnd;
+
+        if (Reflection) and (J <= BandLength div 2) then
+        begin
+          Diff := (Y-PosY) + H;
+
+          //Draw Reflection
+          if Direction then
+          begin
+            glBegin(GL_QUADS);
+              glColorRGB(Color, GetAlpha(Diff));
+              glVertex3f(PosX, Diff + Y + ReflectionSpacing, Z);
+
+              //bottom v
+              glColorRGB(Color, GetAlpha(Diff + H));
+              glVertex3f(PosX, Diff + Y+H + ReflectionSpacing, Z);
+              glVertex3f(PosX+W, Diff + Y+H + ReflectionSpacing, Z);
+
+              glColorRGB(Color, GetAlpha(Diff));
+              glVertex3f(PosX+W, Diff + Y + ReflectionSpacing, Z);
+            glEnd;
+          end
+          else
+          begin
+            glBegin(GL_QUADS);
+              glColorRGB(Color, GetAlpha(Diff));
+              glVertex3f(PosX, Diff + Y + (H + Space)*Bands + ReflectionSpacing, Z);
+              glVertex3f(PosX, Diff + Y+H  + (H + Space)*Bands + ReflectionSpacing, Z);
+              glVertex3f(PosX+W, Diff + Y+H  + (H + Space)*Bands + ReflectionSpacing, Z);
+              glVertex3f(PosX+W, Diff + Y + (H + Space)*Bands + ReflectionSpacing, Z);
+              glColorRGB(Color, GetAlpha(Diff + H));
+            glEnd;
+          end;
+
+          glColorRGB(Color, Alpha);
+        end;
+
+
+        // Calc position of the bar's next block
+        if Direction then // Vertical bars
+          PosY := PosY - H - Space
+        else                                   // Horizontal bars
+          PosX := PosX + W + Space;
+      end;
+
+      // Calc position of the next bar
+      if Direction then // Vertical bars
+        PosX := PosX + W + Space
+      else                                   // Horizontal bars
+        PosY := PosY + H + Space;
+    end;
+
+
+  end;
+end;
+
+procedure Tms_Equalizer.SetBands(Value: byte);
+begin
+  SetLength(BandData, Value);
+end;
+
+function  Tms_Equalizer.GetBands: byte;
+begin
+  Result := Length(BandData);
+end;
+
+procedure Tms_Equalizer.SetSource(newSource: IAudioPlayback);
+begin
+  if (newSource <> nil) then
+    Source := newSource;
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/menu/UMenuInteract.pas b/songmanagement/src/menu/UMenuInteract.pas
new file mode 100644
index 00000000..7cb92025
--- /dev/null
+++ b/songmanagement/src/menu/UMenuInteract.pas
@@ -0,0 +1,54 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuInteract;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+type
+  TInteract = record // for moving thru menu
+    Typ: integer;  // 0 - button, 1 - select, 2 - Text, 3 - Select SLide, 5 - ButtonCollection Child
+    Num: integer;  // number of this item in proper list like buttons, selects
+  end;
+
+  { to handle the area where the mouse is over a control }
+  TMouseOverRect = record
+    X, Y: Real;
+    W, H: Real;
+  end;
+
+  { to handle the on click action }
+  TMouseClickAction = (maNone, maReturn, maLeft, maRight);
+
+implementation
+
+end.
+ 
\ No newline at end of file
diff --git a/songmanagement/src/menu/UMenuSelectSlide.pas b/songmanagement/src/menu/UMenuSelectSlide.pas
new file mode 100644
index 00000000..09ce3b9f
--- /dev/null
+++ b/songmanagement/src/menu/UMenuSelectSlide.pas
@@ -0,0 +1,541 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuSelectSlide;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  gl,
+  TextGL,
+  UMenuText,
+  UTexture,
+  UMenuInteract;
+
+type
+  PSelectSlide = ^TSelectSlide;
+  TSelectSlide = class
+    private
+      SelectBool:       boolean;
+
+      function AdjustOptionTextToFit(OptText: UTF8String): UTF8String;
+    public
+      // objects
+      Text:             TText; // Main text describing option
+      TextOpt:          array of TText; // 3 texts in the position of possible options
+      TextOptT:         array of UTF8String; // array of names for possible options
+
+      Texture:          TTexture; // Select Texture
+      TextureSBG:       TTexture; // Background Selections Texture
+
+      Colorized:          boolean;
+      DeSelectTexture:    TTexture; // texture for colorized hack
+      ColorizedSBG:       boolean;
+      DeSelectTextureSBG: TTexture; // texture for colorized hack Select BG
+
+      Tex_SelectS_ArrowL:    TTexture; // Texture for left arrow
+      Tex_SelectS_ArrowR:    TTexture; // Texture for right arrow
+
+      SelectOptInt:     integer;
+      PData:            ^integer;
+
+      //For automatically Setting LineCount
+      Lines: byte;
+
+      //Arrows on/off
+      showArrows: boolean;      //default is false
+
+      //whether to show one item or all that fit into the select
+      oneItemOnly: boolean;      //default is false
+
+      //Visibility
+      Visible: boolean;
+
+      // for selection and deselection
+      // main static
+      ColR:     real;
+      ColG:     real;
+      ColB:     real;
+      Int:      real;
+      DColR:    real;
+      DColG:    real;
+      DColB:    real;
+      DInt:     real;
+
+      // main text
+      TColR:    real;
+      TColG:    real;
+      TColB:    real;
+      TInt:     real;
+      TDColR:   real;
+      TDColG:   real;
+      TDColB:   real;
+      TDInt:    real;
+
+      // selection background static
+      SBGColR:    real;
+      SBGColG:    real;
+      SBGColB:    real;
+      SBGInt:     real;
+      SBGDColR:   real;
+      SBGDColG:   real;
+      SBGDColB:   real;
+      SBGDInt:    real;
+
+      // selection text
+      STColR:     real;
+      STColG:     real;
+      STColB:     real;
+      STInt:      real;
+      STDColR:    real;
+      STDColG:    real;
+      STDColB:    real;
+      STDInt:     real;
+      
+      // position and size
+      property X: real read Texture.x write Texture.x;
+      property Y: real read Texture.y write Texture.y;
+      property W: real read Texture.w write Texture.w;
+      property H: real read Texture.h write Texture.h;
+//      property X2: real read Texture2.x write Texture2.x;
+//      property Y2: real read Texture2.y write Texture2.y;
+//      property W2: real read Texture2.w write Texture2.w;
+//      property H2: real read Texture2.h write Texture2.h;
+
+      property SBGW: real read TextureSBG.w write TextureSBG.w;
+
+      // procedures
+      procedure SetSelect(Value: boolean);
+      property Selected: boolean read SelectBool write SetSelect;
+      procedure SetSelectOpt(Value: integer);
+      property SelectedOption: integer read SelectOptInt write SetSelectOpt;
+      procedure Draw;
+      constructor Create;
+
+      //Automatically Generate Lines (Texts)
+      procedure genLines;
+
+      function GetMouseOverArea: TMouseOverRect;
+      function OnClick(X, Y: Real): TMouseClickAction;
+  end;
+
+const
+  ArrowAlphaOptionsLeft = 1;
+  ArrowAlphaNoOptionsLeft = 0;
+  MinItemSpacing = 5;
+  MinSideSpacing = 24;
+
+implementation
+
+uses
+  math,
+  SysUtils,
+  UDrawTexture,
+  ULog;
+
+// ------------ Select
+constructor TSelectSlide.Create;
+begin
+  inherited Create;
+  Text := TText.Create;
+  SetLength(TextOpt, 1);
+  TextOpt[0] := TText.Create;
+  Visible := true;
+
+  Colorized := false;
+  ColorizedSBG := false;
+  ColR := 1;
+  ColG := 1;
+  ColB := 1;
+  Int := 1;
+  DColR := 1;
+  DColG := 1;
+  DColB := 1;
+  DInt := 1;
+
+  SBGColR := 1;
+  SBGColG := 1;
+  SBGColB := 1;
+  SBGInt := 1;
+  SBGDColR := 1;
+  SBGDColG := 1;
+  SBGDColB := 1;
+  SBGDInt := 1;
+end;
+
+procedure TSelectSlide.SetSelect(Value: boolean);
+{var
+  SO: integer;
+  I:  integer;}
+begin
+  SelectBool := Value;
+  if Value then
+  begin
+    Texture.ColR := ColR;
+    Texture.ColG := ColG;
+    Texture.ColB := ColB;
+    Texture.Int := Int;
+
+    Text.ColR := TColR;
+    Text.ColG := TColG;
+    Text.ColB := TColB;
+    Text.Int := TInt;
+
+    TextureSBG.ColR := SBGColR;
+    TextureSBG.ColG := SBGColG;
+    TextureSBG.ColB := SBGColB;
+    TextureSBG.Int := SBGInt;
+  end
+  else
+  begin
+    if Colorized then
+      DeSelectTexture.Int := DInt
+    else
+    begin
+      Texture.ColR := DColR;
+      Texture.ColG := DColG;
+      Texture.ColB := DColB;
+      Texture.Int := DInt;
+    end;
+
+    Text.ColR := TDColR;
+    Text.ColG := TDColG;
+    Text.ColB := TDColB;
+    Text.Int := TDInt;
+
+    if (ColorizedSBG) then
+      DeselectTextureSBG.Int := SBGDInt
+    else
+    begin
+      TextureSBG.ColR := SBGDColR;
+      TextureSBG.ColG := SBGDColG;
+      TextureSBG.ColB := SBGDColB;
+      TextureSBG.Int := SBGDInt;
+    end;
+  end;
+end;
+
+procedure TSelectSlide.SetSelectOpt(Value: integer);
+var
+  SO:    integer;
+  HalfL: integer;
+  HalfR: integer;
+
+  procedure DoSelection(Sel: cardinal);
+  var
+    I: integer;
+  begin
+    for I := Low(TextOpt) to High(TextOpt) do
+    begin
+      TextOpt[I].ColR := STDColR;
+      TextOpt[I].ColG := STDColG;
+      TextOpt[I].ColB := STDColB;
+      TextOpt[I].Int := STDInt;
+    end;
+
+    if (integer(Sel) <= High(TextOpt)) then
+    begin
+      TextOpt[Sel].ColR := STColR;
+      TextOpt[Sel].ColG := STColG;
+      TextOpt[Sel].ColB := STColB;
+      TextOpt[Sel].Int := STInt;
+      end;
+    end;
+
+begin
+  SelectOptInt := Value;
+  PData^ := Value;
+
+  if (Length(TextOpt) > 0) and (Length(TextOptT) > 0) then
+  begin
+
+    //First option selected
+    if (Value <= 0) then
+    begin
+      Value := 0;
+
+      Tex_SelectS_ArrowL.alpha := ArrowAlphaNoOptionsLeft;
+      if (Length(TextOptT) > 1) then
+        Tex_SelectS_ArrowR.alpha := ArrowAlphaOptionsLeft
+      else
+        Tex_SelectS_ArrowR.alpha := ArrowAlphaNoOptionsLeft;
+
+      for SO := Low(TextOpt) to High(TextOpt) do
+      begin
+        TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[SO]);
+      end;
+
+      DoSelection(0);
+    end
+
+    //Last option selected
+    else if (Value >= High(TextOptT)) then
+    begin
+      Value := High(TextOptT);
+
+      Tex_SelectS_ArrowL.alpha := ArrowAlphaOptionsLeft;
+      Tex_SelectS_ArrowR.alpha := ArrowAlphaNoOptionsLeft;
+
+      for SO := High(TextOpt) downto Low(TextOpt) do
+      begin
+        TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[High(TextOptT) - (Lines - SO - 1)]);
+      end;
+      DoSelection(Lines - 1);
+    end
+
+    //in between first and last
+    else
+    begin
+      Tex_SelectS_ArrowL.alpha := ArrowAlphaOptionsLeft;
+      Tex_SelectS_ArrowR.alpha := ArrowAlphaOptionsLeft;
+
+      HalfL := Ceil((Lines - 1) / 2);
+      HalfR := Lines - 1 - HalfL;
+
+      //Selected option is near to the left side
+      if (Value <= HalfL) then
+      begin
+        //Change texts
+      	for SO := Low(TextOpt) to High(TextOpt) do
+      	begin
+      	  TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[SO]);
+      	end;
+
+      	DoSelection(Value);
+      end
+
+      //Selected option is near to the right side
+      else if (Value > High(TextOptT) - HalfR) then
+      begin
+      	HalfR := High(TextOptT) - Value;
+      	HalfL := Lines - 1 - HalfR;
+      	//Change texts
+       	for SO := High(TextOpt) downto Low(TextOpt) do
+       	begin
+	        TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[High(TextOptT) - (Lines - SO - 1)]);
+      	end;
+
+      	DoSelection (HalfL);
+      end
+
+      else
+      begin
+      	//Change Texts
+       	for SO := Low(TextOpt) to High(TextOpt) do
+      	begin
+	        TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[Value - HalfL + SO]);
+      	end;
+
+        DoSelection(HalfL);
+      end;
+    end;
+  end;
+end;
+
+{ cuts the text if it is too long to fit on the selectbg }
+function TSelectSlide.AdjustOptionTextToFit(OptText: UTF8String): UTF8String;
+  var
+    MaxLen: real;
+    Len: integer;
+begin
+  Result := OptText;
+  
+  if (TextureSBG.W > 0) then
+  begin
+    MaxLen := TextureSBG.W - MinSideSpacing * 2;
+
+    SetFontStyle(ftNormal);
+    SetFontSize(Text.Size);
+
+    // we will remove min. 2 letters by default and replace them w/ points
+    // if the whole text don't fit
+    Len := Length(OptText) - 1;
+
+    while (glTextWidth(Result) > MaxLen) and (Len > 0) do
+    begin
+      { ensure that we only cut at full letters }
+      { this code may be a problem if there is a text that
+        consists of many multi byte characters and only few
+        one byte characters }
+      repeat
+        Dec(Len);
+      until (byte(OptText[Len]) and 128) = 0;
+      
+      Result := copy(OptText, 1, Len) + '..';
+    end;
+  end;
+end;
+
+procedure TSelectSlide.Draw;
+var
+  SO: integer;
+begin
+  if Visible then
+  begin
+    if SelectBool or not Colorized then
+    begin
+      DrawTexture(Texture);
+    end
+    else
+    begin
+      DeselectTexture.X := Texture.X;
+      DeselectTexture.Y := Texture.Y;
+      DeselectTexture.W := Texture.W;
+      DeselectTexture.H := Texture.H;
+      DrawTexture(DeselectTexture);
+    end;
+
+    if SelectBool or not ColorizedSBG then
+    begin
+      DrawTexture(TextureSBG);
+    end
+    else
+    begin
+      DeselectTextureSBG.X := TextureSBG.X;
+      DeselectTextureSBG.Y := TextureSBG.Y;
+      DeselectTextureSBG.W := TextureSBG.W;
+      DeselectTextureSBG.H := TextureSBG.H;
+      DrawTexture(DeselectTextureSBG);
+    end;
+
+    if showArrows then
+    begin
+      DrawTexture(Tex_SelectS_ArrowL);
+      DrawTexture(Tex_SelectS_ArrowR);
+    end;
+
+    Text.Draw;
+
+    for SO := Low(TextOpt) to High(TextOpt) do
+      TextOpt[SO].Draw;
+  end;
+end;
+
+procedure TSelectSlide.GenLines;
+var
+  maxlength: real;
+  I:         integer;
+begin
+  SetFontStyle(ftNormal{Text.Style});
+  SetFontSize(Text.Size);
+  maxlength := 0;
+
+  for I := Low(TextOptT) to High(TextOptT) do
+  begin
+    if (glTextWidth(TextOptT[I]) > maxlength) then
+      maxlength := glTextWidth(TextOptT[I]);
+  end;
+
+
+  if (oneItemOnly = false) then
+  begin
+    //show all items
+    Lines := floor((TextureSBG.W - MinSideSpacing * 2) / (maxlength + MinItemSpacing));
+    if (Lines > Length(TextOptT)) then
+      Lines := Length(TextOptT);
+
+    if (Lines <= 0) then
+      Lines := 1;
+  end
+  else
+  begin
+    //show one item only
+    Lines := 1;
+  end;
+
+  //Free old Space used by Texts
+  for I := Low(TextOpt) to High(TextOpt) do
+    TextOpt[I].Free;
+    
+  SetLength (TextOpt, Lines);
+
+  for I := Low(TextOpt) to High(TextOpt) do
+  begin
+    TextOpt[I] := TText.Create;
+    TextOpt[I].Size := Text.Size;
+    TextOpt[I].Visible := true;
+    TextOpt[I].Style := 0;
+
+    TextOpt[I].ColR := STDColR;
+    TextOpt[I].ColG := STDColG;
+    TextOpt[I].ColB := STDColB;
+    TextOpt[I].Int := STDInt;
+
+    // generate positions
+    TextOpt[I].Y := TextureSBG.Y + (TextureSBG.H - Text.Size) / 2;
+
+    // better look with 2 options and a single option
+    if (Lines = 2) then
+    begin
+      TextOpt[I].X := TextureSBG.X + 20 + (TextureSBG.W -40 - glTextWidth(TextOptT[1])) * I;
+      TextOpt[I].Align := 0;
+    end
+    else if (Lines = 1) then
+    begin
+      TextOpt[I].X := TextureSBG.X + (TextureSBG.W / 2);
+      TextOpt[I].Align := 1; //center text
+    end
+    else
+    begin
+      TextOpt[I].X := TextureSBG.X + TextureSBG.W / 2 + (TextureSBG.W - MinSideSpacing*2) * (I / Lines - 0.5);
+      TextOpt[I].Align := 0;
+    end;
+  end;
+end;
+
+function TSelectSlide.GetMouseOverArea: TMouseOverRect;
+begin
+  Result.X := Texture.X;
+  Result.Y := Texture.Y;
+  Result.W := (TextureSBG.X + TextureSBG.W) - Result.X;
+  Result.H := Max(Texture.H, TextureSBG.H);
+end;
+
+function TSelectSlide.OnClick(X, Y: Real): TMouseClickAction;
+  var
+    AreaW: Real;
+begin
+  // default: press return on click 
+  Result := maReturn;
+
+  // use left sides to inc or dec selection by click
+  AreaW := TextureSbg.W / 20;
+
+  if (Y >= TextureSBG.Y) and (Y <= TextureSBG.Y + TextureSBG.H) then
+  begin
+    if (X >= TextureSBG.X) and (X <= TextureSBG.X + AreaW) then
+      Result := maLeft   // hit left area
+    else if (X >= TextureSBG.X + TextureSBG.W - AreaW) and (X <= TextureSBG.X + TextureSBG.W) then
+      Result := maRight; // hit right area
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/menu/UMenuStatic.pas b/songmanagement/src/menu/UMenuStatic.pas
new file mode 100644
index 00000000..72f4eb36
--- /dev/null
+++ b/songmanagement/src/menu/UMenuStatic.pas
@@ -0,0 +1,117 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuStatic;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UTexture,
+  gl;
+
+type
+  TStatic = class
+    public
+      Texture:           TTexture; // Button Screen position and size
+      Visible:           boolean;
+
+      //Reflection Mod
+      Reflection:        boolean;
+      Reflectionspacing: real;
+
+      procedure Draw;
+      constructor Create(Textura: TTexture); overload;
+  end;
+
+implementation
+uses
+  UDrawTexture;
+
+procedure TStatic.Draw;
+begin
+  if Visible then
+  begin
+    DrawTexture(Texture);
+
+  //Reflection Mod
+    if (Reflection) then // Draw Reflections
+    begin
+      with Texture do
+      begin
+        //Bind Tex and GL Attributes
+        glEnable(GL_TEXTURE_2D);
+        glEnable(GL_BLEND);
+
+        glDepthRange(0, 10);
+        glDepthFunc(GL_LEQUAL);
+        glEnable(GL_DEPTH_TEST);
+
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        glBindTexture(GL_TEXTURE_2D, TexNum);
+
+        //Draw
+        glBegin(GL_QUADS);//Top Left
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3);
+          glTexCoord2f(TexX1*TexW, TexY2*TexH);
+          glVertex3f(x, y+h*scaleH+ Reflectionspacing, z);
+
+          //Bottom Left
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, 0);
+          glTexCoord2f(TexX1*TexW, 0.5*TexH+TexY1);
+          glVertex3f(x, y+h*scaleH + h*scaleH/2 + Reflectionspacing, z);
+
+
+          //Bottom Right
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, 0);
+          glTexCoord2f(TexX2*TexW, 0.5*TexH+TexY1);
+          glVertex3f(x+w*scaleW, y+h*scaleH + h*scaleH/2 + Reflectionspacing, z);
+
+          //Top Right
+          glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3);
+          glTexCoord2f(TexX2*TexW, TexY2*TexH);
+          glVertex3f(x+w*scaleW, y+h*scaleH + Reflectionspacing, z);
+        glEnd;
+
+        glDisable(GL_TEXTURE_2D);
+        glDisable(GL_DEPTH_TEST);
+        glDisable(GL_BLEND);
+      end;
+    end;
+  end;
+end;
+
+constructor TStatic.Create(Textura: TTexture);
+begin
+  inherited Create;
+  Texture := Textura;
+end;
+
+end.
diff --git a/songmanagement/src/menu/UMenuText.pas b/songmanagement/src/menu/UMenuText.pas
new file mode 100644
index 00000000..ab180b77
--- /dev/null
+++ b/songmanagement/src/menu/UMenuText.pas
@@ -0,0 +1,379 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuText;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  math,
+  SysUtils,
+  gl, 
+  SDL,
+  TextGL,
+  UTexture;
+
+type
+  TText = class
+    private
+      SelectBool:  boolean;
+      TextString:  UTF8String;
+      TextTiles:   array of UTF8String;
+
+      STicks:      cardinal;
+      SelectBlink: boolean;
+    public
+      X:      real;
+      Y:      real;
+      Z:      real;
+      MoveX:  real;       // some modifier for x - position that don't affect the real Y
+      MoveY:  real;       // some modifier for y - position that don't affect the real Y
+      W:      real;       // text wider than W is broken
+//      H:      real;
+      Size:   real;
+      ColR:   real;
+      ColG:   real;
+      ColB:   real;
+      Alpha:  real;
+      Int:    real;
+      Style:   integer;
+      Visible: boolean;
+      Align:   integer; // 0 = left, 1 = center, 2 = right
+
+      // reflection
+      Reflection:        boolean;
+      ReflectionSpacing: real;
+
+      procedure SetSelect(Value: boolean);
+      property Selected: boolean read SelectBool write SetSelect;
+
+      procedure SetText(Value: UTF8String);
+      property  Text: UTF8String read TextString write SetText;
+
+      procedure DeleteLastLetter; //< Deletes the rightmost letter
+
+      procedure Draw;
+      constructor Create; overload;
+      constructor Create(X, Y: real; const Text: UTF8String); overload;
+      constructor Create(ParX, ParY, ParW: real; ParStyle: integer; ParSize, ParColR, ParColG, ParColB: real; ParAlign: integer; const ParText: UTF8String; ParReflection: boolean; ParReflectionSpacing: real; ParZ: real); overload;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UUnicodeUtils,
+  StrUtils;
+
+procedure TText.SetSelect(Value: boolean);
+begin
+  SelectBool := Value;
+  
+  // set cursor visible
+  SelectBlink := true;
+  STicks := SDL_GetTicks() div 550;
+end;
+
+procedure TText.SetText(Value: UTF8String);
+var
+  NextPos:   cardinal;  // next pos of a space etc.
+  LastPos:   cardinal;  // last pos "
+  LastBreak: cardinal;  // last break
+  isBreak:   boolean;   // true if the break is not caused because the text is out of the area
+  FirstWord: word;      // is first word after break?
+  Len:       word;      // length of the tiles array
+
+  function GetNextPos: boolean;
+  var
+    T1, {T2,} T3: cardinal;
+  begin
+    LastPos := NextPos;
+
+    // next space (if width is given)
+    if (W > 0) then
+      T1 := PosEx(' ', Value, LastPos + 1)
+    else
+      T1 := Length(Value);
+
+    {// next -
+    T2 := PosEx('-', Value, LastPos + 1);}
+
+    // next break
+    T3 := PosEx('\n', Value, LastPos + 1);
+
+    if T1 = 0 then
+      T1 := Length(Value);
+    {if T2 = 0 then
+      T2 := Length(Value); }
+    if T3 = 0 then
+      T3 := Length(Value);
+
+    // get nearest pos
+    NextPos := min(T1, T3{min(T2, T3)});
+
+    if (LastPos = cardinal(Length(Value))) then
+      NextPos := 0;
+
+    isBreak := (NextPos = T3) and (NextPos <> cardinal(Length(Value)));
+    Result := (NextPos <> 0);
+  end;
+
+  procedure AddBreak(const From, bTo: cardinal);
+  begin
+    if (isBreak) or (bTo - From >= 1) then
+    begin
+      Inc(Len);
+      SetLength (TextTiles, Len);
+      TextTiles[Len-1] := Trim(Copy(Value, From, bTo - From));
+
+      if isBreak then
+        LastBreak := bTo + 2
+      else
+        LastBreak := bTo + 1;
+      FirstWord := 0;
+    end;
+  end;
+
+begin
+  // set TextString
+  TextString := Value;
+
+  // set cursor visible
+  SelectBlink := true;
+  STicks := SDL_GetTicks() div 550;
+
+  // exit if there is no need to create tiles
+  if (W <= 0) and (Pos('\n', Value) = 0) then
+  begin
+    SetLength (TextTiles, 1);
+    TextTiles[0] := Value;
+    Exit;
+  end;
+
+  // create tiles
+  // reset text array
+  SetLength (TextTiles, 0);
+  Len := 0;
+
+  // reset counter vars
+  LastPos := 1;
+  NextPos := 1;
+  LastBreak := 1;
+  FirstWord := 1;
+
+  if (W > 0) then
+  begin
+    // set font properties
+    SetFontStyle(Style);
+    SetFontSize(Size);
+  end;
+
+  // go through text
+  while (GetNextPos) do
+  begin
+      // break in text
+      if isBreak then
+      begin
+        // look for break before the break
+        if (glTextWidth(Copy(Value, LastBreak, NextPos - LastBreak + 1)) > W) AND (NextPos-LastPos > 1) then
+        begin
+          isBreak := false;
+          // not the first word after break, so we don't have to break within a word
+          if (FirstWord > 1) then
+          begin
+            // add break before actual position, because there the text fits the area
+            AddBreak(LastBreak, LastPos);
+          end
+          else // first word after break break within the word
+          begin
+            // to do
+            // AddBreak(LastBreak, LastBreak + 155);
+          end;
+        end;
+
+        isBreak := true;
+        // add break from text
+        AddBreak(LastBreak, NextPos);
+      end
+      // text comes out of the text area -> createbreak
+      else if (glTextWidth(Copy(Value, LastBreak, NextPos - LastBreak + 1)) > W) then
+      begin
+        // not the first word after break, so we don't have to break within a word
+        if (FirstWord > 1) then
+        begin
+          // add break before actual position, because there the  text fits the area
+          AddBreak(LastBreak, LastPos);
+        end
+        else // first word after break -> break within the word
+        begin
+          // to do
+          // AddBreak(LastBreak, LastBreak + 155);
+        end;
+      end;
+    //end;
+    Inc(FirstWord)
+  end;
+  // add ending
+  AddBreak(LastBreak, Length(Value)+1);
+end;
+
+procedure TText.DeleteLastLetter;
+begin
+  SetText(UTF8Copy(TextString, 1, LengthUTF8(TextString)-1));
+end;
+
+procedure TText.Draw;
+var
+  X2, Y2: real;
+  Text2:  UTF8String;
+  I:      integer;
+  Ticks:  cardinal;
+begin
+  if Visible then
+  begin
+    SetFontStyle(Style);
+    SetFontSize(Size);
+    SetFontItalic(false);
+
+    glColor4f(ColR*Int, ColG*Int, ColB*Int, Alpha);
+
+    // reflection
+    if Reflection then
+      SetFontReflection(true, ReflectionSpacing)
+    else
+      SetFontReflection(false,0);
+
+    // if selected set blink...
+    if SelectBool then
+    begin
+      Ticks := SDL_GetTicks() div 550;
+      if Ticks <> STicks then
+      begin // change visability
+        STicks := Ticks;
+        SelectBlink := Not SelectBlink;
+      end;
+    end;
+
+    {if (false) then // no width set draw as one long string
+    begin
+      if not (SelectBool AND SelectBlink) then
+        Text2 := Text
+      else
+        Text2 := Text + '|';
+
+      case Align of
+        0: X2 := X;
+        1: X2 := X - glTextWidth(Text2)/2;
+        2: X2 := X - glTextWidth(Text2);
+      end;
+
+      SetFontPos(X2, Y);
+      glPrint(Text2);
+      SetFontStyle(ftNormal); // reset to default
+    end
+    else
+    begin}
+    // now use always:
+    // draw text as many strings
+      Y2 := Y + MoveY;
+      for I := 0 to High(TextTiles) do
+      begin
+        if (not (SelectBool and SelectBlink)) or (I <> High(TextTiles)) then
+          Text2 := TextTiles[I]
+        else
+          Text2 := TextTiles[I] + '|';
+
+        case Align of
+          1: X2 := X + MoveX - glTextWidth(Text2)/2; { centered }
+          2: X2 := X + MoveX - glTextWidth(Text2); { right aligned }
+          else X2 := X + MoveX; { left aligned (default) }
+        end;
+
+        SetFontPos(X2, Y2);
+
+        SetFontZ(Z);
+
+        glPrint(Text2);
+
+        {if Size >= 10 then
+          Y2 := Y2 + Size * 0.93
+        else}
+        if (Style = ftBold) then
+          Y2 := Y2 + Size * 0.93
+        else
+          Y2 := Y2 + Size * 0.72;
+      end;
+      SetFontStyle(ftNormal); // reset to default
+
+    //end;
+  end;
+end;
+
+constructor TText.Create;
+begin
+  Create(0, 0, '');
+end;
+
+constructor TText.Create(X, Y: real; const Text: UTF8String);
+begin
+  Create(X, Y, 0, ftNormal, 30, 0, 0, 0, 0, Text, false, 0, 0);
+end;
+
+constructor TText.Create(ParX, ParY, ParW: real;
+                         ParStyle: integer;
+                         ParSize, ParColR, ParColG, ParColB: real;
+                         ParAlign: integer;
+                         const ParText: UTF8String;
+                         ParReflection: boolean;
+                         ParReflectionSpacing: real;
+                         ParZ: real);
+begin
+  inherited Create;
+  Alpha := 1;
+  X := ParX;
+  Y := ParY;
+  W := ParW;
+  Z := ParZ;
+  Style := ParStyle;
+  Size := ParSize;
+  Text := ParText;
+  ColR := ParColR;
+  ColG := ParColG;
+  ColB := ParColB;
+  Int := 1;
+  Align := ParAlign;
+  SelectBool := false;
+  Visible := true;
+  Reflection := ParReflection;
+  ReflectionSpacing := ParReflectionSpacing;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenCredits.pas b/songmanagement/src/screens/UScreenCredits.pas
new file mode 100644
index 00000000..90c0fa19
--- /dev/null
+++ b/songmanagement/src/screens/UScreenCredits.pas
@@ -0,0 +1,1329 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenCredits;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  SDL,
+  SDL_Image,
+  gl,
+  UMenu,
+  UDisplay,
+  UTexture,
+  UMusic,
+  UFiles,
+  UThemes,
+  UPath,
+  UGraphicClasses;
+
+{ beat detection constants and types }
+const
+  SubChannelCount = 32;
+  HistoryLength = 44;
+  SamplesPerChannel = (FFTSize div 2) div SubChannelCount;
+  BeatEnergyModifier = 80; // modifies detected energy
+                           // higher values equal a more sensitive detection
+
+type
+  TEnergyHistory = array [0..HistoryLength-1] of single;
+  TSubchannelHistory = array [0..SubChannelCount-1] of TEnergyHistory;
+
+type
+  TCreditsStages=(InitialDelay, Intro, MainPart, Outro);
+
+  TScreenCredits = class(TMenu)
+    private
+      CreditsPath: IPath;
+
+      Credits_X:     real;
+      Credits_Time:  cardinal;
+      CTime_hold:    cardinal;
+
+      credits_bg_tex:      TTexture;
+      credits_bg_ovl:      TTexture;
+      //credits_bg_logo:   TTexture;
+      credits_names:       array of TTexture;
+      intro_layer01:       TTexture;
+      intro_layer02:       TTexture;
+      intro_layer03:       TTexture;
+      intro_layer04:       TTexture;
+      intro_layer05:       TTexture;
+      intro_layer06:       TTexture;
+      intro_layer07:       TTexture;
+      intro_layer08:       TTexture;
+      intro_layer09:       TTexture;
+      outro_bg:            TTexture;
+      outro_esc:           TTexture;
+      outro_exd:           TTexture;
+
+      CurrentScrollStart, CurrentScrollEnd: integer;
+
+      CRDTS_Stage: TCreditsStages;
+
+      { beat detection }
+      SubChannelHistory: TSubchannelHistory;
+
+      { mouse movement easter eggs: }
+      MouseMoved: boolean;
+      MouseX, MouseY: double;
+
+      { saves last x and y angle for easter egg }
+      LogoAngleX, LogoAngleY: single;
+
+      procedure LoadNameTextures;
+
+      { draw different stages }
+      procedure DrawInitialDelay;
+
+      { Intro }
+      procedure DrawIntro;
+      procedure DrawLayeredLogo(Separation, Scale, AngleX, AngleY, AngleZ: single);
+
+      { Main }
+      procedure DrawMain;
+      procedure DrawMainBG;
+      procedure DrawFunkyText;
+
+      procedure DrawMainFG;
+
+      procedure DrawNames;
+      procedure DoLogoBling;
+
+      { Outro }
+      procedure DrawOutro;
+
+
+      { beat detection }
+      procedure DetectBeat;
+    protected
+      { beat detection stuff
+        protected cause we need this information for "on beat
+        effect"}
+      LastBeatTime: cardinal;
+      BeatDetected: boolean;
+      CTime:        cardinal;
+    public
+      Fadeout: boolean;
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      function ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; override;
+      procedure OnShow; override;
+      procedure OnHide; override;
+      function Draw: boolean; override;
+   end;
+
+const
+  Funky_Text: string =
+    'Grandma Deluxe has arrived! Thanks to Corvus5 for the massive work on UltraStar, Wome for the nice tune you are hearing, '+
+    'all the people who put massive effort and work in new songs (do not forget UltraStar w/o songs would be nothing), ppl from '+
+    'irc helping us - eBandit and Gabari, scene ppl who really helped instead of compiling and running away. Greetings to DennisTheMenace for betatesting, '+
+    'Demoscene.tv, pouet.net, KakiArts, Sourceforge,..';
+
+{ texture names (loaded from gameshared/resources/credits}
+  CRDTS_BG_FILE           = 'credits_v5_bg.png';
+  CRDTS_OVL_FILE          = 'credits_v5_overlay.png';
+  INTRO_L01_FILE          = 'intro-l-01.png';
+  INTRO_L02_FILE          = 'intro-l-02.png';
+  INTRO_L03_FILE          = 'intro-l-03.png';
+  INTRO_L04_FILE          = 'intro-l-04.png';
+  INTRO_L05_FILE          = 'intro-l-05.png';
+  INTRO_L06_FILE          = 'intro-l-06.png';
+  INTRO_L07_FILE          = 'intro-l-07.png';
+  INTRO_L08_FILE          = 'intro-l-08.png';
+  INTRO_L09_FILE          = 'intro-l-09.png';
+  OUTRO_BG_FILE           = 'outro-bg.png';
+  OUTRO_ESC_FILE          = 'outro-esc.png';
+  OUTRO_EXD_FILE          = 'outro-exit-dark.png';
+
+{ some timings }
+  Delay_Before_Start = 20;
+  Intro_Flare_Start = 60;
+  Intro_Zoom_End = 149;
+  Intro_Stand_End = 155;
+  Intro_Separation_End = 170;
+  Intro_FadeToWhite_Start = 261;
+  Intro_Zoomout_Start = 271;
+  Main_Start = 271;
+  Main_OnBeatTwinkle_Start = 280;
+  Main_Names_Start = 359;
+  Main_Names_End = 2833;
+  Main_FadeOut_Start = 3096;
+  Tune_End = 3366;
+
+{ cosntants for developer names }
+
+type
+  TFadeEffect = procedure (const Tex: TTexture; Progress: double);
+  TCRTZ_Developer = record
+    Name: string;           // developer name for texture loading (names_"devel".png)
+    Twinkle: boolean;       // should there be twinkles on show
+    FadeIn:   TFadeEffect;  // fade in effect
+    Draw:     TFadeEffect;  // effect during draw
+    FadeOut:  TFadeEffect;  // fade out effect
+  end;
+
+{ effects are called with blending, texture and matrix prepared }
+procedure Effect_Draw             (const Tex: TTexture; Progress: double);
+procedure Effect_OnBeatJitter     (const Tex: TTexture; Progress: double);
+
+procedure Effect_Rotate_Left_Top  (const Tex: TTexture; Progress: double);
+procedure Effect_Rotate_Right_Bot (const Tex: TTexture; Progress: double);
+procedure Effect_ZoomIn_Rotate    (const Tex: TTexture; Progress: double);
+procedure Effect_ZoomOut_Shift    (const Tex: TTexture; Progress: double);
+procedure Effect_Shift_Left       (const Tex: TTexture; Progress: double);
+procedure Effect_Shift_Right_Top  (const Tex: TTexture; Progress: double);
+procedure Effect_Flip_Bot         (const Tex: TTexture; Progress: double);
+procedure Effect_Flip_Right_Top   (const Tex: TTexture; Progress: double);
+procedure Effect_Flip_Right       (const Tex: TTexture; Progress: double);
+procedure Effect_Flip_Right_Bot   (const Tex: TTexture; Progress: double);
+procedure Effect_Rotate_Right_Top (const Tex: TTexture; Progress: double);
+procedure Effect_Shift_Weird      (const Tex: TTexture; Progress: double);
+procedure Effect_Shift_Right_Bot  (const Tex: TTexture; Progress: double);
+procedure Effect_Rotate_Right_Top2(const Tex: TTexture; Progress: double);
+procedure Effect_Flip_Left_Bot    (const Tex: TTexture; Progress: double);
+procedure Effect_Flip_Right_Top2  (const Tex: TTexture; Progress: double);
+procedure Effect_Twinkle_Down     (const Tex: TTexture; Progress: double);
+
+const
+  Developers: array[0..10] of TCRTZ_Developer = (
+    (Name: 'alexanders';  Twinkle: true;  FadeIn: Effect_Rotate_Left_Top;   Draw: Effect_OnBeatJitter;  FadeOut: Effect_Rotate_Right_Bot),
+    (Name: 'blindy';      Twinkle: true;  FadeIn: Effect_ZoomIn_Rotate;     Draw: Effect_OnBeatJitter;  FadeOut: Effect_ZoomOut_Shift),
+    (Name: 'brunzel';     Twinkle: true;  FadeIn: Effect_Shift_Left;        Draw: Effect_Draw;          FadeOut: Effect_Shift_Right_Top),
+    (Name: 'canni';       Twinkle: true;  FadeIn: Effect_Flip_Bot;          Draw: Effect_Draw;          FadeOut: Effect_Flip_Right_Top),
+    (Name: 'hennymcc';    Twinkle: true;  FadeIn: Effect_Flip_Right;        Draw: Effect_OnBeatJitter;  FadeOut: Effect_Flip_Right_Bot),
+    (Name: 'jaybinks';    Twinkle: true;  FadeIn: Effect_Rotate_Right_Top;  Draw: Effect_OnBeatJitter;  FadeOut: Effect_Shift_Weird),
+    (Name: 'krueger';     Twinkle: true;  FadeIn: Effect_Shift_Right_Bot;   Draw: Effect_OnBeatJitter;  FadeOut: Effect_Rotate_Right_Top2),
+    (Name: 'mezzox';      Twinkle: true;  FadeIn: Effect_Flip_Left_Bot;     Draw: Effect_OnBeatJitter;  FadeOut: Effect_Flip_Right_Top),
+    (Name: 'mischi';      Twinkle: true;  FadeIn: Effect_Shift_Weird;       Draw: Effect_OnBeatJitter;  FadeOut: Effect_Flip_Bot),
+    (Name: 'mog';         Twinkle: false; FadeIn: Effect_Twinkle_Down;      Draw: Effect_OnBeatJitter;  FadeOut: Effect_ZoomIn_Rotate),
+    (Name: 'whiteshark';  Twinkle: true;  FadeIn: Effect_Rotate_Right_Top2; Draw: Effect_OnBeatJitter;  FadeOut: Effect_Shift_Left)
+  );
+
+  { name specific times }
+  TimePerName = (Main_Names_End - Main_Names_Start) div Length(Developers);
+  NameFadeTime = 12;   // duration of fade in/out in 1/100 secs
+  NameWaitTime = 5;    // delay between fade out and fade in of the next devel in 1/100 secs
+  NameTwinkleTime = 2; // duration of star effects in 1/100 secs
+  BeatJitterTime = 3;  // duration of on beat jitter effect
+  { position at which the names show up
+    note: due to use of translate this is the center
+    of the names not the upper left corner as usual }
+  NameX = 223;
+  NameY = 329;
+  NameW = 326;
+  NameH = 258;
+
+implementation
+
+uses
+  Math,
+  ULog,
+  UGraphic,
+  UMain,
+  UIni,
+  USongs,
+  Textgl,
+  ULanguage,
+  UCommon,
+  UPathUtils;
+
+function TScreenCredits.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    case PressedKey of
+
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE,
+      SDLK_RETURN :
+        begin
+          FadeTo(@ScreenMain);
+          AudioPlayback.PlaySound(SoundLib.Back);
+        end;
+{
+      SDLK_SPACE:
+         begin
+           setlength(CTime_hold,length(CTime_hold)+1);
+           CTime_hold[high(CTime_hold)]:=CTime;
+         end;
+}
+     end; // esac
+    end;  // fi
+end;
+
+function TScreenCredits.ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean;
+begin
+  Result := inherited ParseMouse(MouseButton, BtnDown, X, Y);
+  
+  { calculate mouse coordinates from -1 to 1
+    relative to screen center }
+  MouseX := (X - (ScreenW / Screens) / 2) / ((ScreenW / Screens) / 2);
+  MouseY := (Y - ScreenH / 2) / (ScreenH / 2);
+
+  MouseMoved := true;
+end;
+
+procedure TScreenCredits.LoadNameTextures;
+  var I: integer;
+begin
+  SetLength(credits_names, Length(Developers));
+
+  for I  := 0 to High(Developers) do
+  begin
+    credits_names[I] := Texture.LoadTexture(CreditsPath.Append('names_' + Developers[I].Name + '.png'),  TEXTURE_TYPE_TRANSPARENT, 0);
+  end;
+end;
+
+constructor TScreenCredits.Create;
+begin
+  inherited Create;
+
+  CreditsPath := ResourcesPath.Append('credits', pdAppend);
+
+  credits_bg_tex := Texture.LoadTexture(CreditsPath.Append(CRDTS_BG_FILE), TEXTURE_TYPE_PLAIN, 0);
+  credits_bg_ovl := Texture.LoadTexture(CreditsPath.Append(CRDTS_OVL_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+
+  LoadNameTextures;
+
+  intro_layer01 := Texture.LoadTexture(CreditsPath.Append(INTRO_L01_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+  intro_layer02 := Texture.LoadTexture(CreditsPath.Append(INTRO_L02_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+  intro_layer03 := Texture.LoadTexture(CreditsPath.Append(INTRO_L03_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+  intro_layer04 := Texture.LoadTexture(CreditsPath.Append(INTRO_L04_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+  intro_layer05 := Texture.LoadTexture(CreditsPath.Append(INTRO_L05_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+  intro_layer06 := Texture.LoadTexture(CreditsPath.Append(INTRO_L06_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+  intro_layer07 := Texture.LoadTexture(CreditsPath.Append(INTRO_L07_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+  intro_layer08 := Texture.LoadTexture(CreditsPath.Append(INTRO_L08_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+  intro_layer09 := Texture.LoadTexture(CreditsPath.Append(INTRO_L09_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+
+  outro_bg  := Texture.LoadTexture(CreditsPath.Append(OUTRO_BG_FILE),  TEXTURE_TYPE_PLAIN, 0);
+  outro_esc := Texture.LoadTexture(CreditsPath.Append(OUTRO_ESC_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+  outro_exd := Texture.LoadTexture(CreditsPath.Append(OUTRO_EXD_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+
+  CRDTS_Stage:=InitialDelay;
+end;
+
+procedure TScreenCredits.OnShow;
+begin
+  inherited;
+
+ { pause background music }
+  SoundLib.PauseBgMusic;
+
+  CRDTS_Stage    := InitialDelay;
+  CTime := 0;
+  Credits_X      := 580;
+
+  { open credits tune, we play it after initial delay }
+  AudioPlayback.Open(soundpath.Append('wome-credits-tune.mp3')); // thank you wetue
+
+  { reset twinkling stars }
+  GoldenRec.KillAll;
+  
+  { reset mouse coords }
+  MouseMoved := false;
+  MouseX := 0;
+  MouseY := 0;
+
+  { hide cursor }
+  Display.SetCursor;
+end;
+
+procedure TScreenCredits.OnHide;
+begin
+  AudioPlayback.Stop;
+
+  { show cursor }
+  Display.SetCursor;
+
+  SoundLib.StartBgMusic;
+end;
+
+function TScreenCredits.Draw: boolean;
+  var
+    T: cardinal;
+begin
+  Result := true;
+  
+  // reset beat detection
+  BeatDetected := false;
+
+  T := SDL_GetTicks() div 33;
+  if T <> Credits_Time then
+  begin
+    Credits_Time := T;
+    inc(CTime);
+    inc(CTime_hold);
+    Credits_X := Credits_X-2;
+
+    if (CRDTS_Stage = InitialDelay) and (CTime >= Delay_Before_Start) then
+    begin
+      CRDTS_Stage := Intro;
+      CTime := 0;
+      AudioPlayback.Play;
+    end
+    else if (CRDTS_Stage = Intro) and (CTime >= Main_Start) then
+    begin
+      CRDTS_Stage := MainPart;
+    end
+    else if (CRDTS_Stage = MainPart) and (CTime >= Tune_End) then
+    begin
+      CRDTS_Stage := Outro;
+    end;
+    
+    // dis does teh muiwk y0r   to be translated :-)
+    DetectBeat;
+  end;
+
+  case CRDTS_Stage of
+    InitialDelay: DrawInitialDelay;
+    Intro:        DrawIntro;
+    MainPart:     DrawMain;
+    Outro:        DrawOutro;  
+  end;
+
+  // make the stars shine
+  GoldenRec.Draw;
+end;
+
+procedure TScreenCredits.DrawInitialDelay;
+begin
+  glClearColor(0, 0, 0, 0);
+  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+end;
+
+procedure TScreenCredits.DrawIntro;
+  var
+    Separation, Scale,
+    AngleX, AngleY, AngleZ: single;
+    FlareX, FlareY: single;
+    I: integer;
+begin
+  glClearColor(0, 0, 0, 0);
+  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+
+  { rotate logo anti clockwise and make it grow }
+  if (CTime >= Intro_Separation_End) then
+  begin
+    Separation := 1;
+    Scale := 1 + sqr(CTime - Intro_Separation_End) / (32 * (Main_Start - Intro_Separation_End));
+    AngleX := 0;
+    AngleY := 0;
+    AngleZ := 20 * sqr(CTime - Intro_Separation_End) / sqr((Main_Start - Intro_Separation_End) / 2);
+  end
+
+  { separate layers }
+  else if (CTime >= Intro_Stand_End) then
+  begin
+    Separation := 0.5 + 0.5 * (CTime - Intro_Stand_End) / (Intro_Separation_End - Intro_Stand_End);
+    Scale := 1;
+    AngleX := 0;
+    AngleY := 0;
+    AngleZ := 0;
+  end
+
+  { stand still }
+  else if (CTime >= Intro_Zoom_End) then
+  begin
+    Separation := 0.5;
+    Scale := 1;
+    AngleX := 0;
+    AngleY := 0;
+    AngleZ := 0;
+  end
+
+  { rotate left }
+  else 
+  begin
+    Separation := 0.5 + 0.5 * (Intro_Zoom_End - CTime) / (Intro_Zoom_End);
+    Scale := 1;
+    AngleX := 10 * (Intro_Zoom_End - CTime) / (Intro_Zoom_End);
+    AngleY := 20 * (Intro_Zoom_End - CTime) / (Intro_Zoom_End);
+    AngleZ := 0;
+  end;
+
+  { the user moved the mouse, overwrite X and Y angle with
+    according to mouse position }
+  if (MouseMoved) then
+  begin
+    // calculate destination angle
+    AngleX := 30 * MouseY;
+    AngleY := 30 * MouseX;
+
+    { move angle towards destination }
+    if not SameValue(LogoAngleX, AngleX, 0.001) then
+      AngleX := LogoAngleX + 0.05 * (AngleX - LogoAngleX);
+
+    if not SameValue(LogoAngleY, AngleY, 0.001) then
+      AngleY := LogoAngleY + 0.05 * (AngleY - LogoAngleY);
+  end;
+
+  // save last angle
+  LogoAngleX := AngleX;
+  LogoAngleY := AngleY;
+
+  DrawLayeredLogo(Separation, Scale, AngleX, AngleY, AngleZ);
+
+  { do some sparkling effects }
+  if (CTime < Intro_Zoom_End) and (CTime > Intro_Flare_Start) then
+  begin
+    for I := 1 to 3 do
+    begin
+       FlareX := 410 + Floor((CTime - Intro_Flare_Start) / (Intro_Zoom_End - Intro_Flare_Start) * (536 - 410)) + RandomRange(-5, 5);
+       FlareY := Floor((Intro_Zoom_End - CTime) / 22) + RandomRange(285, 301);
+       GoldenRec.Spawn(FlareX, FlareY, 1, 16, 0, -1, Flare, 0);
+    end;
+  end;
+
+  { fade to white at end }
+  if Ctime > Intro_FadeToWhite_Start then
+  begin
+    glColor4f(1, 1, 1, sqr(CTime - Intro_FadeToWhite_Start) * (CTime - Intro_FadeToWhite_Start) / sqr(Main_Start - Intro_FadeToWhite_Start));
+    glEnable(GL_BLEND);
+    glBegin(GL_QUADS);
+      glVertex2f(  0,   0);
+      glVertex2f(  0, 600);
+      glVertex2f(800, 600);
+      glVertex2f(800,   0);
+    glEnd;
+    glDisable(GL_BLEND);
+  end;
+end;
+
+procedure Start3D;
+begin
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix;
+  glLoadIdentity;
+  glFrustum(-0.3 * 4 / 3, 0.3 * 4 / 3, -0.3, 0.3, 1, 1000);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity;
+end;
+
+procedure End3D;
+begin
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix;
+  glMatrixMode(GL_MODELVIEW);
+end;
+
+procedure TScreenCredits.DrawLayeredLogo(Separation, Scale, AngleX, AngleY, AngleZ: single);
+  var
+    TotalAngle: single;
+begin
+  Start3D;
+  glPushMatrix;
+
+  glEnable(GL_TEXTURE_2D);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+
+  glTranslatef(0, 0, -5 + 0.5 * Separation);
+
+  TotalAngle := Abs(AngleX) + Abs(AngleY) + Abs(AngleZ);
+  if not isZero(TotalAngle) then
+    glRotatef(TotalAngle, AngleX / TotalAngle, AngleY / TotalAngle, AngleZ / TotalAngle);
+
+  glScalef(Scale, Scale, 1);
+
+  glScalef(4/3, -1, 1);
+  glColor4f(1, 1, 1, 1);
+
+  glBindTexture(GL_TEXTURE_2D, intro_layer01.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex3f(-1, -1, -0.4 * Separation);
+    glTexCoord2f(0, 1); glVertex3f(-1,  1, -0.4 * Separation);
+    glTexCoord2f(1, 1); glVertex3f( 1,  1, -0.4 * Separation);
+    glTexCoord2f(1, 0); glVertex3f( 1, -1, -0.4 * Separation);
+  glEnd;
+
+  glBindTexture(GL_TEXTURE_2D, intro_layer02.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex3f(-1, -1, -0.3 * Separation);
+    glTexCoord2f(0, 1); glVertex3f(-1,  1, -0.3 * Separation);
+    glTexCoord2f(1, 1); glVertex3f( 1,  1, -0.3 * Separation);
+    glTexCoord2f(1, 0); glVertex3f( 1, -1, -0.3 * Separation);
+  glEnd;
+
+  glBindTexture(GL_TEXTURE_2D, intro_layer03.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex3f(-1, -1, -0.2 * Separation);
+    glTexCoord2f(0, 1); glVertex3f(-1,  1, -0.2 * Separation);
+    glTexCoord2f(1, 1); glVertex3f( 1,  1, -0.2 * Separation);
+    glTexCoord2f(1, 0); glVertex3f( 1, -1, -0.2 * Separation);
+  glEnd;
+
+  glBindTexture(GL_TEXTURE_2D, intro_layer04.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex3f(-1, -1, -0.1 * Separation);
+    glTexCoord2f(0, 1); glVertex3f(-1,  1, -0.1 * Separation);
+    glTexCoord2f(1, 1); glVertex3f( 1,  1, -0.1 * Separation);
+    glTexCoord2f(1, 0); glVertex3f( 1, -1, -0.1 * Separation);
+  glEnd;
+
+  glBindTexture(GL_TEXTURE_2D, intro_layer05.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex3f(-1, -1, 0 * Separation);
+    glTexCoord2f(0, 1); glVertex3f(-1,  1, 0 * Separation);
+    glTexCoord2f(1, 1); glVertex3f( 1,  1, 0 * Separation);
+    glTexCoord2f(1, 0); glVertex3f( 1, -1, 0 * Separation);
+  glEnd;
+
+  glBindTexture(GL_TEXTURE_2D, intro_layer06.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex3f(-1, -1, 0.1 * Separation);
+    glTexCoord2f(0, 1); glVertex3f(-1,  1, 0.1 * Separation);
+    glTexCoord2f(1, 1); glVertex3f( 1,  1, 0.1 * Separation);
+    glTexCoord2f(1, 0); glVertex3f( 1, -1, 0.1 * Separation);
+  glEnd;
+
+  glBindTexture(GL_TEXTURE_2D, intro_layer07.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex3f(-1, -1, 0.2 * Separation);
+    glTexCoord2f(0, 1); glVertex3f(-1,  1, 0.2 * Separation);
+    glTexCoord2f(1, 1); glVertex3f( 1,  1, 0.2 * Separation);
+    glTexCoord2f(1, 0); glVertex3f( 1, -1, 0.2 * Separation);
+  glEnd;
+
+  glBindTexture(GL_TEXTURE_2D, intro_layer08.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex3f(-1, -1, 0.3 * Separation);
+    glTexCoord2f(0, 1); glVertex3f(-1,  1, 0.3 * Separation);
+    glTexCoord2f(1, 1); glVertex3f( 1,  1, 0.3 * Separation);
+    glTexCoord2f(1, 0); glVertex3f( 1, -1, 0.3 * Separation);
+  glEnd;
+
+  glBindTexture(GL_TEXTURE_2D, intro_layer09.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex3f(-1, -1, 0.22 * Separation);
+    glTexCoord2f(0, 1); glVertex3f(-1,  1, 0.22 * Separation);
+    glTexCoord2f(1, 1); glVertex3f( 1,  1, 0.22 * Separation);
+    glTexCoord2f(1, 0); glVertex3f( 1, -1, 0.22 * Separation);
+  glEnd;
+
+  glDisable(Gl_Texture_2D);
+  glDisable(GL_BLEND);
+
+  glPopMatrix;
+  End3D;
+end;
+
+procedure TScreenCredits.DrawMain;  
+begin
+  DrawMainBG;
+  DrawFunkyText;
+  DrawNames;
+  DrawMainFG;
+  DoLogoBling;
+
+  // fade out at end of main part
+  if (Ctime > Main_FadeOut_Start) then
+  begin
+    glColor4f(0, 0, 0, (CTime - Main_FadeOut_Start) / (Tune_End - Main_FadeOut_Start));
+    glEnable(GL_BLEND);
+    glBegin(GL_QUADS);
+      glVertex2f(  0,   0);
+      glVertex2f(  0, 600);
+      glVertex2f(800, 600);
+      glVertex2f(800,   0);
+    glEnd;
+    glDisable(GL_BLEND);
+  end;
+end;
+
+procedure TScreenCredits.DrawMainBG;
+begin
+  glEnable(GL_TEXTURE_2D);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+
+  glColor4f(1, 1, 1, 1);
+  glBindTexture(GL_TEXTURE_2D, credits_bg_tex.TexNum);
+  glBegin(Gl_Quads);
+    glTexCoord2f(       0,        0); glVertex2f(      0,       0);
+    glTexCoord2f(       0, 600/1024); glVertex2f(      0, RenderH);
+    glTexCoord2f(800/1024, 600/1024); glVertex2f(RenderW, RenderH);
+    glTexCoord2f(800/1024,        0); glVertex2f(RenderW,       0);
+  glEnd;
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_BLEND);
+end;
+
+procedure TScreenCredits.DrawFunkyText;
+var
+  S:           integer;
+  X, Y, A:     real;
+  visibleText: string;
+begin
+  SetFontSize(30);
+
+  // init ScrollingText
+  if (CTime = Main_Start) then
+  begin
+    // set position of text
+    Credits_X          := 600;
+    CurrentScrollStart := 1;
+    CurrentScrollEnd   := 1;
+  end;
+
+  if (CTime > Main_Start) and
+     (CurrentScrollStart < length(Funky_Text)) then
+  begin
+    X := 0;
+    visibleText := Copy(Funky_Text, CurrentScrollStart, CurrentScrollEnd);
+
+    for S := 1 to length(visibleText) do
+    begin
+      Y := abs(sin((Credits_X + X) * 0.93 { * (((Credits_X + X)) / 1200) } / 100 * pi));
+      SetFontPos(Credits_X + X, 538 - Y * (Credits_X + X) * (Credits_X + X) * (Credits_X + X) / 1000000);
+
+      if (Credits_X + X > 32) then
+        A := 17
+      else if (Credits_X + X >= 15) then
+        A := Credits_X + X - 15
+      else
+        A := 0;
+
+      glColor4f(230 / 255 - 40 / 255 + Y * (Credits_X + X)/  900,
+                200 / 255 - 30 / 255 + Y * (Credits_X + X)/ 1000,
+                155 / 255 - 20 / 255 + Y * (Credits_X + X)/ 1100,
+                  A / 17);
+      glPrint(visibleText[S]);
+      X := X + glTextWidth(visibleText[S]);
+    end;
+
+    if (Credits_X < 0) and (CurrentScrollStart < length(Funky_Text)) then
+    begin
+      Credits_X := Credits_X + glTextWidth(Funky_Text[CurrentScrollStart]);
+      inc(CurrentScrollStart);
+    end;
+
+    visibleText := Copy(Funky_Text, CurrentScrollStart, CurrentScrollEnd);
+
+    if (Credits_X + glTextWidth(visibleText) < 600) and
+       (CurrentScrollEnd < length(Funky_Text)) then
+    begin
+      inc(CurrentScrollEnd);
+    end;
+  end;
+{
+// timing hack
+  X:=5;
+  SetFontStyle(2);
+  SetFontItalic(false);
+  SetFontSize(27);
+  glColor4f(1, 1, 1, 1);
+  for S := 0 to high(CTime_hold) do
+  begin
+    visibleText := inttostr(CTime_hold[S]);
+    SetFontPos (500, X);
+    glPrint(visibleText[0]);
+    X := X + 20;
+  end;
+}
+end;
+
+procedure TScreenCredits.DrawNames;
+  var
+    Dev: integer;
+    Ticks: integer;
+    DevTicks: integer;
+    TwinkleW, TwinkleH: integer;
+begin
+  Ticks := (CTime - Main_Names_Start);
+  Dev := Ticks div TimePerName;
+  DevTicks := Ticks mod TimePerName;
+
+  {// debug stuff
+  SetFontPos(20, 20);
+  glPrint('Ticks: ' + IntToStr(Ticks));
+  SetFontPos(20, 45);
+  glPrint('Dev: ' + IntToStr(Dev));
+  SetFontPos(20, 70);
+  glPrint('DevTicks: ' + IntToStr(DevTicks)); //}
+
+  if (Ticks >= 0) and (Dev <= High(Developers)) then
+  begin
+    { spawn twinkling stars }
+    if (Developers[Dev].Twinkle) and (DevTicks >= NameFadeTime) and (DevTicks <= NameFadeTime + NameTwinkleTime) then
+    begin
+      TwinkleW := Round(NameW * 0.6);
+      TwinkleH := Round(NameH * 0.6);
+
+      GoldenRec.Spawn(NameX + RandomRange(-TwinkleW, TwinkleW), NameY + RandomRange(-TwinkleH, TwinkleH), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+      GoldenRec.Spawn(NameX + RandomRange(-TwinkleW, TwinkleW), NameY + RandomRange(-TwinkleH, TwinkleH), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+      GoldenRec.Spawn(NameX + RandomRange(-TwinkleW, TwinkleW), NameY + RandomRange(-TwinkleH, TwinkleH), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+      GoldenRec.Spawn(NameX + RandomRange(-TwinkleW, TwinkleW), NameY + RandomRange(-TwinkleH, TwinkleH), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+      GoldenRec.Spawn(NameX + RandomRange(-TwinkleW, TwinkleW), NameY + RandomRange(-TwinkleH, TwinkleH), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+      GoldenRec.Spawn(NameX + RandomRange(-TwinkleW, TwinkleW), NameY + RandomRange(-TwinkleH, TwinkleH), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+      GoldenRec.Spawn(NameX + RandomRange(-TwinkleW, TwinkleW), NameY + RandomRange(-TwinkleH, TwinkleH), 1, 16, 0, -1, PerfectLineTwinkle, 0);
+      GoldenRec.Spawn(NameX + RandomRange(-TwinkleW, TwinkleW), NameY + RandomRange(-TwinkleH, TwinkleH), 1, 16, 0, -1, PerfectLineTwinkle, 1);
+      GoldenRec.Spawn(NameX + RandomRange(-TwinkleW, TwinkleW), NameY + RandomRange(-TwinkleH, TwinkleH), 1, 16, 0, -1, PerfectLineTwinkle, 5);
+    end;
+
+    { prepare drawing }
+    glPushMatrix;
+    glTranslatef(NameX, NameY, 0);
+    glBindTexture(GL_TEXTURE_2D, credits_names[Dev].TexNum);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glEnable(GL_BLEND);
+    glEnable(GL_TEXTURE_2D);
+
+    // calculate progress and call effect
+    if (DevTicks <= NameFadeTime) then
+      Developers[Dev].FadeIn(credits_names[Dev], DevTicks / NameFadeTime)
+    else if (DevTicks >= TimePerName - NameFadeTime - NameWaitTime) then
+    begin
+      if (DevTicks < TimePerName - NameWaitTime) then
+        Developers[Dev].FadeOut(credits_names[Dev], ((TimePerName - NameWaitTime) - DevTicks) / NameFadeTime);
+    end
+    else
+      Developers[Dev].Draw(credits_names[Dev], (DevTicks - NameFadeTime) / (TimePerName - NameFadeTime * 2 - NameWaitTime));
+
+    glDisable(GL_TEXTURE_2D);
+    glDisable(GL_BLEND);
+    glPopMatrix;
+  end;
+end;
+
+procedure TScreenCredits.DrawMainFG;
+begin
+  glEnable(GL_TEXTURE_2D);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+  glColor4f(1, 1, 1, 1);
+  glBindTexture(GL_TEXTURE_2D, credits_bg_ovl.TexNum);
+  glBegin(gl_Quads);
+    glTexCoord2f(      0,        0); glVertex2f(800-393,   0);
+    glTexCoord2f(      0, 600/1024); glVertex2f(800-393, 600);
+    glTexCoord2f(393/512, 600/1024); glVertex2f(800,     600);
+    glTexCoord2f(393/512,        0); glVertex2f(800,       0);
+  glEnd;
+
+
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_BLEND);
+end;
+
+procedure TScreenCredits.DoLogoBling;
+  const
+    myLogoCoords: array[0..27,0..1] of cardinal = (
+      ( 39,32),( 84,32),(100,16),(125,24),
+      (154,31),(156,58),(168,32),(203,36),
+      (258,34),(251,50),(274,93),(294,84),
+      (232,54),(278,62),(319,34),(336,92),
+      (347,23),(374,32),(377,58),(361,83),
+      (385,91),(405,91),(429,35),(423,51),
+      (450,32),(485,34),(444,91),(486,93)
+    );
+  var
+    Coords: integer;
+    StartFrame: integer;
+begin
+  if (CTime > Main_OnBeatTwinkle_Start ) and
+     (CTime < Main_FadeOut_Start) then
+    begin
+      { spawn stars only in frames where a beat was detected }
+      if BeatDetected then
+      begin
+         StartFrame := RandomRange(6, 16);
+         Coords := RandomRange(0, 27);
+
+         GoldenRec.Spawn(myLogoCoords[Coords,0], myLogoCoords[Coords,1], 16-StartFrame, StartFrame, 0, -1, PerfectNote, 0);
+      end;
+    end;
+end;
+
+procedure TScreenCredits.DrawOutro;
+begin
+  if CTime = Tune_End then
+  begin
+    CTime_hold := 0;
+    AudioPlayback.Stop;
+    AudioPlayback.Open(SoundPath.Append('credits-outro-tune.mp3'));
+    AudioPlayback.SetVolume(0.2);
+    AudioPlayback.SetLoop(true);
+    AudioPlayback.Play;
+  end;
+
+  if CTime_hold > 231 then
+  begin
+    AudioPlayback.Play;
+    Ctime_hold := 0;
+  end;
+
+  glClearColor(0, 0, 0, 0);
+  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+
+  // do something useful
+  // outro background
+  glEnable(GL_TEXTURE_2D);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+
+  glColor4f(1, 1, 1, 1);
+  glBindTexture(GL_TEXTURE_2D, outro_bg.TexNum);
+  glBegin(gl_quads);
+    glTexCoord2f(       0,        0); glVertex2f(  0,   0);
+    glTexCoord2f(       0, 600/1024); glVertex2f(  0, 600);
+    glTexCoord2f(800/1024, 600/1024); glVertex2f(800, 600);
+    glTexCoord2f(800/1024,        0); glVertex2f(800,   0);
+  glEnd;
+
+  // outro overlays
+  glColor4f(1, 1, 1, (2 + sin(CTime / 15)) / 3);
+  glBindTexture(GL_TEXTURE_2D, outro_esc.TexNum);
+  glBegin(Gl_Quads);
+    glTexCoord2f(      0,       0); glVertex2f(  0,   0);
+    glTexCoord2f(      0, 223/256); glVertex2f(  0, 223);
+    glTexCoord2f(487/512, 223/256); glVertex2f(487, 223);
+    glTexCoord2f(487/512,       0); glVertex2f(487,   0);
+  glEnd;
+
+  if (RandomRange(0,20) <= 18) then
+  begin
+    glColor4f(1, 1, 1, 1);
+    glBindTexture(GL_TEXTURE_2D, outro_exd.TexNum);
+    glBegin(Gl_Quads);
+      glTexCoord2f(      0,       0); glVertex2f(800-310, 600-247);
+      glTexCoord2f(      0, 247/256); glVertex2f(800-310, 600    );
+      glTexCoord2f(310/512, 247/256); glVertex2f(800,     600    );
+      glTexCoord2f(310/512,       0); glVertex2f(800,     600-247);
+    glEnd;
+  end;
+
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_BLEND);
+
+  // outro scrollers?
+  // ...
+end;
+
+{ name effects }
+{ effects are called with blending texture and matrix prepared }
+procedure Effect_Draw (const Tex: TTexture; Progress: double);
+begin
+  glColor4f(1, 1, 1, 1);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_OnBeatJitter (const Tex: TTexture; Progress: double);
+  var
+    Diff: cardinal;
+    Alpha: double;
+begin
+  Diff := ScreenCredits.CTime - ScreenCredits.LastBeatTime;
+  if (Diff < BeatJitterTime) then  
+    Alpha := 0.5 + 0.5 * Diff / BeatJitterTime
+  else
+    Alpha := 1;
+
+  glColor4f(1, 1, 1, Alpha);
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Rotate_Left_Top (const Tex: TTexture; Progress: double);
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  gltranslatef(-NameX, 0, 0);
+  glrotatef(Progress * 90 + 270, 0, 0, 1);
+  gltranslatef(NameX, 0, 0);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Rotate_Right_Bot (const Tex: TTexture; Progress: double);
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  gltranslatef(NameX, 0, 0);
+  glrotatef((Progress - 1) * 90, 0, 0, 1);
+  gltranslatef(-NameX, 0, 0);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_ZoomIn_Rotate (const Tex: TTexture; Progress: double);
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  glscalef(sqr(Progress), sqr(Progress), sqr(Progress));
+  glrotatef(Progress * 360, 0, 0, 1);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_ZoomOut_Shift (const Tex: TTexture; Progress: double);
+  var
+    X: double;
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  X := (1 - Progress);
+  gltranslatef(X * 300, -X * 100, 0);
+  glscalef(1 + X, 1 + X, 1 + X);
+  glrotatef(X * 90, 0, 0, 1);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Shift_Left (const Tex: TTexture; Progress: double);
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  glTranslatef((Progress - 1) * 210, 0, 0);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Shift_Right_Top (const Tex: TTexture; Progress: double);
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  glTranslatef((1 - Progress) * 210, (Progress - 1) * 105, 0);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Flip_Bot (const Tex: TTexture; Progress: double);
+  var
+    X: double;
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  X := NameH * (1 - Progress);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2 - 1.5 * X, -NameH/2 + 1.5 * X);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2 + 1.5 * X, -NameH/2 + 1.5 * X);
+  glEnd;
+end;
+
+procedure Effect_Flip_Right_Top (const Tex: TTexture; Progress: double);
+  var
+    X: double;
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  X := NameW * (1 - Progress);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2 + X, -NameH/2 - X/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2 + X,  NameH/2 - (X * 1.5 * NameH / NameW));
+    glTexCoord2f(1, 1); glVertex2f( NameW/2 + X,  NameH/2 + X / 4);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2 + X, -NameH/2 - X / 4);
+  glEnd;
+end;
+
+procedure Effect_Flip_Right (const Tex: TTexture; Progress: double);
+  var
+    X: double;
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  X := NameW * (1 - Progress);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2,     -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,      NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2 - X,  NameH/2 + X * 1.5);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2 - X, -NameH/2 - X * 1.5);
+  glEnd;
+end;
+
+procedure Effect_Flip_Right_Bot (const Tex: TTexture; Progress: double);
+  var
+    X: double;
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  X := NameW * (1 - Progress);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2 + X * 1.5, -NameH/2 + X * 1.5);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2 + X * 1.2,  NameH/2 + X);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2 + X / 2,    NameH/2 + X / 4);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2 + X * 1.5, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Rotate_Right_Top (const Tex: TTexture; Progress: double);
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  glTranslatef(NameX, 0, 0);
+  glrotatef((1 - Progress) * 90, 0, 0, 1);
+  glTranslatef(-NameX, 0, 0);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Shift_Weird (const Tex: TTexture; Progress: double);
+  var
+    X: double;
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  X := (Progress - 1);
+
+  glTranslatef(X * 200, X * 100, 0);
+  glScalef(Progress, Progress, Progress);
+  glRotatef(X * 90, 0, 0, 1);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Shift_Right_Bot (const Tex: TTexture; Progress: double);
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  glTranslatef((1 - Progress) * 200, (1 - Progress) * 100, 0);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Rotate_Right_Top2 (const Tex: TTexture; Progress: double);
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  glTranslatef(0, -NameX, 0);
+  glRotatef((Progress - 1) * 90, 0, 0, 1);
+  glTranslatef(0, NameX, 0);
+  glRotatef((1 - Progress) * 90, 0, 0, 1);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH/2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2,  NameH/2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2,  NameH/2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH/2);
+  glEnd;
+end;
+
+procedure Effect_Flip_Left_Bot (const Tex: TTexture; Progress: double);
+  var
+    X: double;
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  X := (1 - Progress) * NameW;
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2 - X,       -NameH/2 + X / 4);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2 - X / 4,    NameH/2 + X / 4);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2 - X * 1.2,  NameH/2 + X / 2);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2 - X * 1.5, -NameH/2 + X * 1.5);
+  glEnd;
+end;
+
+procedure Effect_Flip_Right_Top2 (const Tex: TTexture; Progress: double);
+  var
+    X: double;
+begin
+  glColor4f(1, 1, 1, Progress);
+
+  X := (1 - Progress) * NameW;
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2 + X,     -NameH/2 - X / 2);
+    glTexCoord2f(0, 1); glVertex2f(-NameW/2 + X,      NameH/2 + X / 2);
+    glTexCoord2f(1, 1); glVertex2f( NameW/2 + X / 4,  NameH/2 - X / 4);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2 + X / 4, -NameH/2 + X / 4);
+  glEnd;
+end;
+
+procedure Effect_Twinkle_Down     (const Tex: TTexture; Progress: double);
+begin
+  // draw name
+  glColor4f(1, 1, 1, 1);
+
+  glTranslatef(0, NameH/2, 0);
+
+  glBegin(gl_Quads);
+    glTexCoord2f(0, 0); glVertex2f(-NameW/2, -NameH * Progress);
+    glTexCoord2f(0, Progress); glVertex2f(-NameW/2, 0);
+    glTexCoord2f(1, Progress); glVertex2f( NameW/2, 0);
+    glTexCoord2f(1, 0); glVertex2f( NameW/2, -NameH * Progress);
+  glEnd;
+
+  //spawn some stars on the edge
+  GoldenRec.Spawn(NameX + RandomRange(-NameW div 2, NameW div 2), NameY - NameH/2 + (1 - Progress) * NameH, 1, 16, 0, -1, PerfectLineTwinkle, 0);
+  GoldenRec.Spawn(NameX + RandomRange(-NameW div 2, NameW div 2), NameY - NameH/2 + (1 - Progress) * NameH, 1, 16, 0, -1, PerfectLineTwinkle, 1);
+  GoldenRec.Spawn(NameX + RandomRange(-NameW div 2, NameW div 2), NameY - NameH/2 + (1 - Progress) * NameH, 1, 16, 0, -1, PerfectLineTwinkle, 5);
+  GoldenRec.Spawn(NameX + RandomRange(-NameW div 2, NameW div 2), NameY - NameH/2 + (1 - Progress) * NameH, 1, 16, 0, -1, PerfectLineTwinkle, 0);
+  GoldenRec.Spawn(NameX + RandomRange(-NameW div 2, NameW div 2), NameY - NameH/2 + (1 - Progress) * NameH, 1, 16, 0, -1, PerfectLineTwinkle, 1);
+  GoldenRec.Spawn(NameX + RandomRange(-NameW div 2, NameW div 2), NameY - NameH/2 + (1 - Progress) * NameH, 1, 16, 0, -1, PerfectLineTwinkle, 5);
+  GoldenRec.Spawn(NameX + RandomRange(-NameW div 2, NameW div 2), NameY - NameH/2 + (1 - Progress) * NameH, 1, 16, 0, -1, PerfectLineTwinkle, 0);
+  GoldenRec.Spawn(NameX + RandomRange(-NameW div 2, NameW div 2), NameY - NameH/2 + (1 - Progress) * NameH, 1, 16, 0, -1, PerfectLineTwinkle, 1);
+  GoldenRec.Spawn(NameX + RandomRange(-NameW div 2, NameW div 2), NameY - NameH/2 + (1 - Progress) * NameH, 1, 16, 0, -1, PerfectLineTwinkle, 5);
+end;
+
+{ beat detection algorithm
+  based on a tutorial from Fr�d�ric Patin on gamedev.net
+  http://www.gamedev.net/reference/programming/features/beatdetection/default.asp }
+
+{ calculates average value of a history buffer }
+function Average(History: TEnergyHistory): single;
+  var I: integer; 
+begin
+  Result := 0;
+
+  for I := 0 to HistoryLength - 1 do
+    Result := Result + History[I];
+
+  Result := Result / HistoryLength;
+end;
+
+{ calculates variance value of a history buffer }
+function Variance(History: TEnergyHistory; Average: single): single;
+  var I: integer;
+begin
+  Result := 0;
+
+  for I := 0 to HistoryLength - 1 do
+    Result := Result + sqr(History[I] - Average);
+
+  Result := Result / HistoryLength;
+end;
+
+{ shifts all values of the history to the right and
+  adds the new value at the front }
+procedure AddHistory(Value: single; var History: TEnergyHistory);
+  var I: integer;
+begin
+  for I := HistoryLength - 1 downto 1 do
+    History[I] := History[I-1];
+
+  History[0] := Value;
+end;
+
+{ calculates instant energy from FFT data for a specific
+  subchannel (0..SubChannelCount - 1) }
+function CalculateInstantEnergy(SubChannel: integer; Data: TFFTData): single;
+  var I: integer;
+begin
+  Result := 0;
+  for I := SubChannel * SamplesPerChannel to (SubChannel + 1) * SamplesPerChannel - 1 do
+    Result := Result + Data[I] * BeatEnergyModifier;
+
+  Result := Result / SamplesPerChannel;
+end;
+
+procedure TScreenCredits.DetectBeat;
+  var
+    Data: TFFTData;
+    I: integer;
+    Instant: single;
+    C, E, V: single;
+begin
+  AudioPlayback.GetFFTData(Data);
+
+  // do beatdetection for every subchannel
+  for I := 0 to SubChannelCount - 1 do
+  begin
+    Instant := CalculateInstantEnergy(I, Data);
+    E := Average(SubchannelHistory[I]);
+    V := Variance(SubchannelHistory[I], E);
+
+    C := (-0.0025714 * V) + 1.5142857;
+
+    AddHistory(Instant, SubChannelHistory[I]);
+
+    if (Instant > 2) and (Instant > C * E) then
+    begin
+      // beat detected
+      BeatDetected := true;
+      LastBeatTime := CTime;
+    end;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenEdit.pas b/songmanagement/src/screens/UScreenEdit.pas
new file mode 100644
index 00000000..12e2948c
--- /dev/null
+++ b/songmanagement/src/screens/UScreenEdit.pas
@@ -0,0 +1,164 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenEdit;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  UThemes;
+
+type
+  TScreenEdit = class(TMenu)
+    public
+      TextDescription:     integer;
+      TextDescriptionLong: integer;
+
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure InteractNext; override;
+      procedure InteractPrev; override;
+      procedure InteractInc; override;
+      procedure InteractDec; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UMusic,
+  USkins,
+  UUnicodeUtils,
+  SysUtils;
+
+function TScreenEdit.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+  SDL_ModState: word;
+begin
+  Result := true;
+
+  SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT +
+    KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT + KMOD_RALT);
+
+  if (PressedDown) then
+  begin // Key Down
+        // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenMain);
+        end;
+      SDLK_RETURN:
+        begin
+          if Interaction = 0 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Start);
+            FadeTo(@ScreenEditConvert);
+          end;
+
+          if Interaction = 1 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Back);
+            FadeTo(@ScreenMain);
+          end;
+        end;
+
+      SDLK_DOWN:  InteractInc;
+      SDLK_UP:    InteractDec;
+      SDLK_RIGHT: InteractNext;
+      SDLK_LEFT:  InteractPrev;
+    end;
+  end;
+end;
+
+constructor TScreenEdit.Create;
+begin
+  inherited Create;
+
+  TextDescription := AddText(Theme.Edit.TextDescription);
+
+  LoadFromTheme(Theme.Edit);
+
+  AddButton(Theme.Edit.ButtonConvert);
+{ Some ideas for more:
+  AddButton(Theme.Edit.ButtonEditHeaders);
+  AddButton(Theme.Edit.ButtonAdjustGap);
+}
+  AddButton(Theme.Edit.ButtonExit);
+
+  Interaction := 0;
+end;
+
+procedure TScreenEdit.InteractNext;
+begin
+  inherited InteractNext;
+  Text[TextDescription].Text := Theme.Edit.Description[Interaction];
+end;
+
+procedure TScreenEdit.InteractPrev;
+begin
+  inherited InteractPrev;
+  Text[TextDescription].Text := Theme.Edit.Description[Interaction];
+end;
+
+procedure TScreenEdit.InteractDec;
+begin
+  inherited InteractDec;
+  Text[TextDescription].Text := Theme.Edit.Description[Interaction];
+end;
+
+procedure TScreenEdit.InteractInc;
+begin
+  inherited InteractInc;
+  Text[TextDescription].Text := Theme.Edit.Description[Interaction];
+end;
+
+procedure TScreenEdit.SetAnimationProgress(Progress: real);
+begin
+  Statics[0].Texture.ScaleW := Progress;
+  Statics[0].Texture.ScaleH := Progress;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenEditConvert.pas b/songmanagement/src/screens/UScreenEditConvert.pas
new file mode 100644
index 00000000..8b13d410
--- /dev/null
+++ b/songmanagement/src/screens/UScreenEditConvert.pas
@@ -0,0 +1,826 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenEditConvert;
+
+{*
+ * See
+ * MIDI Recommended Practice (RP-017): SMF Lyric Meta Event Definition
+ *   http://www.midi.org/techspecs/rp17.php
+ * MIDI Recommended Practice (RP-026): SMF Language and Display Extensions
+ *   http://www.midi.org/techspecs/rp26.php
+ * MIDI File Format
+ *   http://www.sonicspot.com/guide/midifiles.html
+ * KMIDI File Format
+ *   http://gnese.free.fr/Projects/KaraokeTime/Fichiers/karfaq.html
+ *   http://journals.rpungin.fotki.com/karaoke/category/midi
+ *
+ * There are two widely spread karaoke formats:
+ * - KMIDI (.kar), an inofficial midi extension by Tune 1000
+ * - Standard Midi files with lyric meta-tags (SMF with lyrics, .mid).
+ *
+ * KMIDI uses two tracks, the first just contains a header (mostly track 2) and
+ * the second the lyrics (track 3). It uses text meta tags for the lyrics.
+ * SMF uses just one track (normally track 1) and uses lyric meta tags for storage.
+ *
+ * Most files are in the KMIDI format. Some Midi files contain both lyric types.
+ *}
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  math,
+  UMenu,
+  SDL,
+  {$IFDEF UseMIDIPort}
+  MidiFile,
+  MidiOut,
+  {$ENDIF}
+  ULog,
+  USongs,
+  USong,
+  UMusic,
+  UThemes,
+  UPath;
+
+type
+  TMidiNote = record
+    Event:     integer;
+    EventType: integer;
+    Channel:   integer;
+    Start:     real;
+    Len:       real;
+    Data1:     integer;
+    Data2:     integer;
+    Str:       UTF8String; // normally ASCII
+  end;
+
+  TLyricType = (ltKMIDI, ltSMFLyric);
+
+  TTrack = record
+    Note:   array of TMidiNote;
+    Name:   UTF8String; // normally ASCII
+    Status: set of (tsNotes, tsLyrics); //< track contains notes, lyrics or both
+    LyricType: set of TLyricType;
+    NoteType:  (ntNone, ntAvail);
+  end;
+
+  TNote = record
+    Start:    integer;
+    Len:      integer;
+    Tone:     integer;
+    Lyric:    UTF8String;
+    NewSentence:  boolean;
+  end;
+
+  TArrayTrack = array of TTrack;
+
+  TScreenEditConvert = class(TMenu)
+    private
+      Tracks:    TArrayTrack; // current track
+      ColR:      array[0..100] of real;
+      ColG:      array[0..100] of real;
+      ColB:      array[0..100] of real;
+      Len:       real;
+      SelTrack:  integer;     // index of selected track
+      fFileName: IPath;
+
+      {$IFDEF UseMIDIPort}
+      MidiFile:  TMidiFile;
+      MidiOut:   TMidiOutput;
+      {$ENDIF}
+
+      BPM:       real;
+      Ticks:     real;
+      Note:      array of TNote;
+
+      procedure AddLyric(Start: integer; LyricType: TLyricType; Text: UTF8String);
+      procedure Extract(out Song: TSong; out Lines: TLines);
+
+      {$IFDEF UseMIDIPort}
+      procedure MidiFile1MidiEvent(event: PMidiEvent);
+      {$ENDIF}
+
+      function CountSelectedTracks: integer;
+
+    public
+      constructor Create; override;
+      procedure OnShow; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      function Draw: boolean; override;
+      procedure OnHide; override;
+  end;
+
+implementation
+
+uses
+  SysUtils,
+  TextGL,
+  gl,
+  UDrawTexture,
+  UFiles,
+  UGraphic,
+  UIni,
+  UMain,
+  UPathUtils,
+  USkins,
+  ULanguage,
+  UTextEncoding,
+  UUnicodeUtils;
+
+const
+  // MIDI/KAR lyrics are specified to be ASCII only.
+  // Assume backward compatible CP1252 encoding.
+  DEFAULT_ENCODING = encCP1252;
+
+const
+  MIDI_EVENTTYPE_NOTEOFF    = $8;
+  MIDI_EVENTTYPE_NOTEON     = $9;
+  MIDI_EVENTTYPE_META_SYSEX = $F;
+
+  MIDI_EVENT_META = $FF;
+  MIDI_META_TEXT   = $1;
+  MIDI_META_LYRICS = $5;
+
+function TScreenEditConvert.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+{$IFDEF UseMIDIPort}
+var
+  SResult: TSaveSongResult;
+  Playing: boolean;
+  MidiTrack: TMidiTrack;
+  Song:  TSong;
+  Lines: TLines;
+{$ENDIF}
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          {$IFDEF UseMIDIPort}
+          if (MidiFile <> nil) then
+            MidiFile.StopPlaying;
+          {$ENDIF}
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenEdit);
+        end;
+
+      SDLK_RETURN:
+        begin
+          if Interaction = 0 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Start);
+            ScreenOpen.Filename := GamePath.Append('file.mid');
+            ScreenOpen.BackScreen := @ScreenEditConvert;
+            FadeTo(@ScreenOpen);
+          end
+          else if Interaction = 1 then
+          begin
+            {$IFDEF UseMIDIPort}
+            if (MidiFile <> nil) then
+            begin
+              MidiFile.OnMidiEvent := MidiFile1MidiEvent;
+              //MidiFile.GoToTime(MidiFile.GetTrackLength div 2);
+              MidiFile.StartPlaying;
+            end;
+            {$ENDIF}
+          end
+          else if Interaction = 2 then
+          begin
+            {$IFDEF UseMIDIPort}
+            if (MidiFile <> nil) then
+            begin
+              MidiFile.OnMidiEvent := nil;
+              MidiFile.StartPlaying;
+            end;
+            {$ENDIF}
+          end
+          else if Interaction = 3 then
+          begin
+            {$IFDEF UseMIDIPort}
+            if CountSelectedTracks > 0 then
+            begin
+              Extract(Song, Lines);
+              SResult := SaveSong(Song, Lines, fFileName.SetExtension('.txt'),
+                       false);
+              FreeAndNil(Song);
+              if (SResult = ssrOK) then
+                ScreenPopupInfo.ShowPopup(Language.Translate('INFO_FILE_SAVED'))
+              else
+                ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
+            end
+            else
+            begin
+              ScreenPopupError.ShowPopup(Language.Translate('EDITOR_ERROR_NO_TRACK_SELECTED'));
+            end;
+            {$ENDIF}
+          end;
+
+        end;
+
+      SDLK_SPACE:
+        begin
+          {$IFDEF UseMIDIPort}
+          if (MidiFile <> nil) then
+          begin
+            if (Tracks[SelTrack].NoteType = ntAvail) and
+               (Tracks[SelTrack].LyricType <> []) then
+            begin
+              if (Tracks[SelTrack].Status = []) then
+                Tracks[SelTrack].Status := [tsNotes]
+              else if (Tracks[SelTrack].Status = [tsNotes]) then
+                Tracks[SelTrack].Status := [tsLyrics]
+              else if (Tracks[SelTrack].Status = [tsLyrics]) then
+                Tracks[SelTrack].Status := [tsNotes, tsLyrics]
+              else if (Tracks[SelTrack].Status = [tsNotes, tsLyrics]) then
+                Tracks[SelTrack].Status := [];
+            end
+            else if (Tracks[SelTrack].NoteType = ntAvail) then
+            begin
+              if (Tracks[SelTrack].Status = []) then
+                Tracks[SelTrack].Status := [tsNotes]
+              else
+                Tracks[SelTrack].Status := [];
+            end
+            else if (Tracks[SelTrack].LyricType <> []) then
+            begin
+              if (Tracks[SelTrack].Status = []) then
+                Tracks[SelTrack].Status := [tsLyrics]
+              else
+                Tracks[SelTrack].Status := [];
+            end;
+
+            Playing := (MidiFile.GetCurrentTime > 0);
+            MidiFile.StopPlaying();
+            MidiTrack := MidiFile.GetTrack(SelTrack);
+            if tsNotes in Tracks[SelTrack].Status then
+              MidiTrack.OnMidiEvent := MidiFile1MidiEvent
+            else
+              MidiTrack.OnMidiEvent := nil;
+            if (Playing) then
+              MidiFile.ContinuePlaying();
+          end;
+          {$ENDIF}
+        end;
+
+      SDLK_RIGHT:
+        begin
+          InteractNext;
+        end;
+
+      SDLK_LEFT:
+        begin
+          InteractPrev;
+        end;
+
+      SDLK_DOWN:
+        begin
+          Inc(SelTrack);
+          if SelTrack > High(Tracks) then
+            SelTrack := 0;
+        end;
+      SDLK_UP:
+        begin
+          Dec(SelTrack);
+          if SelTrack < 0 then
+            SelTrack := High(Tracks);
+        end;
+    end;
+  end;
+end;
+
+procedure TScreenEditConvert.AddLyric(Start: integer; LyricType: TLyricType; Text: UTF8String);
+var
+  N:    integer;
+begin
+  // find corresponding note
+  N := 0;
+  while (N <= High(Note)) do
+  begin
+    if Note[N].Start = Start then
+      Break;
+    Inc(N);
+  end;
+
+  // check if note was found
+  if (N > High(Note)) then
+    Exit;
+  
+  // set text
+  if (LyricType = ltKMIDI) then
+  begin
+    // end of paragraph
+    if Copy(Text, 1, 1) = '\' then
+    begin
+      Delete(Text, 1, 1);
+    end
+    // end of line
+    else if Copy(Text, 1, 1) = '/' then
+    begin
+      Delete(Text, 1, 1);
+      Note[N].NewSentence := true;
+    end;
+  end
+  else // SMFLyric
+  begin
+    // Line Feed -> end of paragraph
+    if Copy(Text, 1, 1) = #$0A then
+    begin
+      Delete(Text, 1, 1);
+    end
+    // Carriage Return -> end of line
+    else if Copy(Text, 1, 1) = #$0D then
+    begin
+      Delete(Text, 1, 1);
+      Note[N].NewSentence := true;
+    end;
+  end;
+
+  // overwrite lyric or append
+  if Note[N].Lyric = '-' then
+    Note[N].Lyric := Text
+  else
+    Note[N].Lyric := Note[N].Lyric + Text;
+end;
+
+procedure TScreenEditConvert.Extract(out Song: TSong; out Lines: TLines);
+
+var
+  T:    integer;
+  C:    integer;
+  N:    integer;
+  Nu:   integer;
+  NoteTemp: TNote;
+  Move: integer;
+  Max, Min: integer;
+  LyricType: TLyricType;
+  Text: UTF8String;
+begin
+  // song info
+  Song := TSong.Create();
+  Song.Clear();
+  Song.Resolution := 4;
+  SetLength(Song.BPM, 1);
+  Song.BPM[0].BPM := BPM*4;
+  SetLength(Note, 0);
+
+  // extract notes
+  for T := 0 to High(Tracks) do
+  begin
+    if tsNotes in Tracks[T].Status then
+    begin
+      for N := 0 to High(Tracks[T].Note) do
+      begin
+        if (Tracks[T].Note[N].EventType = MIDI_EVENTTYPE_NOTEON) and
+           (Tracks[T].Note[N].Data2 > 0) then
+        begin
+          Nu := Length(Note);
+          SetLength(Note, Nu + 1);
+          Note[Nu].Start := Round(Tracks[T].Note[N].Start / Ticks);
+          Note[Nu].Len := Round(Tracks[T].Note[N].Len / Ticks);
+          Note[Nu].Tone := Tracks[T].Note[N].Data1 - 12*5;
+          Note[Nu].Lyric := '-';
+        end;
+      end;
+    end;
+  end;
+
+  // extract lyrics (and artist + title info)
+  for T := 0 to High(Tracks) do
+  begin
+    if not (tsLyrics in Tracks[T].Status) then
+      Continue;
+
+    for N := 0 to High(Tracks[T].Note) do
+    begin
+      if (Tracks[T].Note[N].Event = MIDI_EVENT_META) then
+      begin
+        // determine and validate lyric meta tag
+        if (ltKMIDI in Tracks[T].LyricType) and
+           (Tracks[T].Note[N].Data1 = MIDI_META_TEXT) then
+        begin
+          Text := Tracks[T].Note[N].Str;
+          
+          // check for meta info
+          if (Length(Text) > 2) and (Text[1] = '@') then
+          begin
+            case Text[2] of
+              'L': Song.Language := Copy(Text, 3, Length(Text)); // language
+              'T': begin // title info
+                if (Song.Artist = '') then
+                  Song.Artist := Copy(Text, 3, Length(Text))
+                else if (Song.Title = '') then
+                  Song.Title := Copy(Text, 3, Length(Text));
+              end;
+            end;
+            Continue;
+          end;
+
+          LyricType := ltKMIDI;
+        end
+        else if (ltSMFLyric in Tracks[T].LyricType) and
+                (Tracks[T].Note[N].Data1 = MIDI_META_LYRICS) then
+        begin
+          LyricType := ltSMFLyric;
+        end
+        else
+        begin
+          // unknown meta event
+          Continue;
+        end;
+
+        AddLyric(Round(Tracks[T].Note[N].Start / Ticks), LyricType, Tracks[T].Note[N].Str);
+      end;
+    end;
+  end;
+
+  // sort notes
+  for N := 0 to High(Note) do
+    for Nu := 0 to High(Note)-1 do
+      if Note[Nu].Start > Note[Nu+1].Start then
+      begin
+        NoteTemp := Note[Nu];
+        Note[Nu] := Note[Nu+1];
+        Note[Nu+1] := NoteTemp;
+      end;
+
+  // move to 0 at beginning
+  Move := Note[0].Start;
+  for N := 0 to High(Note) do
+    Note[N].Start := Note[N].Start - Move;
+
+  // copy notes
+  SetLength(Lines.Line, 1);
+  Lines.Number     := 1;
+  Lines.High       := 0;
+  Lines.Current    := 0;
+  Lines.Resolution := 0;
+  Lines.NotesGAP   := 0;
+  Lines.ScoreValue := 0;
+
+  C := 0;
+  N := 0;
+  Lines.Line[C].HighNote := -1;
+
+  for Nu := 0 to High(Note) do
+  begin
+    if Note[Nu].NewSentence then // new line
+    begin
+      SetLength(Lines.Line, Length(Lines.Line)+1);
+      Lines.Number := Lines.Number + 1;
+      Lines.High := Lines.High + 1;
+      C := C + 1;
+      N := 0;
+      SetLength(Lines.Line[C].Note, 0);
+      Lines.Line[C].HighNote := -1;
+
+      //Calculate Start of the Last Sentence
+      if (C > 0) and (Nu > 0) then
+      begin
+        Max := Note[Nu].Start;
+        Min := Note[Nu-1].Start + Note[Nu-1].Len;
+        
+        case (Max - Min) of
+          0:    Lines.Line[C].Start := Max;
+          1:    Lines.Line[C].Start := Max;
+          2:    Lines.Line[C].Start := Max - 1;
+          3:    Lines.Line[C].Start := Max - 2;
+          else
+            if ((Max - Min) > 4) then
+              Lines.Line[C].Start := Min + 2
+            else
+              Lines.Line[C].Start := Max;
+
+        end; // case
+
+      end;
+    end;
+
+    // create space for new note
+    SetLength(Lines.Line[C].Note, Length(Lines.Line[C].Note)+1);
+    Inc(Lines.Line[C].HighNote);
+
+    // initialize note
+    Lines.Line[C].Note[N].Start := Note[Nu].Start;
+    Lines.Line[C].Note[N].Length := Note[Nu].Len;
+    Lines.Line[C].Note[N].Tone := Note[Nu].Tone;
+    Lines.Line[C].Note[N].Text := DecodeStringUTF8(Note[Nu].Lyric, DEFAULT_ENCODING);
+    Lines.Line[C].Note[N].NoteType := ntNormal;
+    Inc(N);
+  end;
+end;
+
+function TScreenEditConvert.CountSelectedTracks: integer;
+var
+  T:    integer; // track
+begin
+  Result := 0;
+  for T := 0 to High(Tracks) do
+    if tsNotes in Tracks[T].Status then
+      Inc(Result);
+end;
+
+{$IFDEF UseMIDIPort}
+procedure TScreenEditConvert.MidiFile1MidiEvent(event: PMidiEvent);
+begin
+  //Log.LogStatus(IntToStr(event.event), 'MIDI');
+  try
+    MidiOut.PutShort(event.event, event.data1, event.data2);
+  except
+    MidiFile.StopPlaying();
+  end;
+end;
+{$ENDIF}
+
+constructor TScreenEditConvert.Create;
+var
+  P:  integer;
+begin
+  inherited Create;
+  AddButton(40, 20, 100, 40, Skin.GetTextureFileName('ButtonF'));
+  AddButtonText(15, 5, 0, 0, 0, 'Open');
+  //Button[High(Button)].Text[0].Size := 11;
+
+  AddButton(160, 20, 100, 40, Skin.GetTextureFileName('ButtonF'));
+  AddButtonText(25, 5, 0, 0, 0, 'Play');
+
+  AddButton(280, 20, 200, 40, Skin.GetTextureFileName('ButtonF'));
+  AddButtonText(25, 5, 0, 0, 0, 'Play Selected');
+
+  AddButton(500, 20, 100, 40, Skin.GetTextureFileName('ButtonF'));
+  AddButtonText(20, 5, 0, 0, 0, 'Save');
+
+  fFileName := PATH_NONE;
+
+  for P := 0 to 100 do
+  begin
+    ColR[P] := Random(10)/10;
+    ColG[P] := Random(10)/10;
+    ColB[P] := Random(10)/10;
+  end;
+
+end;
+
+procedure TScreenEditConvert.OnShow;
+{$IFDEF UseMIDIPort}
+var
+  T:    integer; // track
+  N:    integer; // note
+  MidiTrack: TMidiTrack;
+  MidiEvent: PMidiEvent;
+  FileOpened: boolean;
+  KMIDITrackIndex, SMFTrackIndex: integer;
+{$ENDIF}
+begin
+  inherited;
+
+  Interaction := 0;
+
+{$IFDEF UseMIDIPort}
+  MidiOut := TMidiOutput.Create(nil);
+  Log.LogInfo(MidiOut.ProductName, 'MIDI');
+  MidiOut.Open;
+  MidiFile := nil;
+  SetLength(Tracks, 0);
+
+  // Filename is only <> PATH_NONE if we called the OpenScreen before
+  fFilename := ScreenOpen.Filename;
+  if (fFilename = PATH_NONE) then
+    Exit;
+  ScreenOpen.Filename := PATH_NONE;
+
+  FileOpened := false;
+  if fFileName.Exists then
+  begin
+    MidiFile := TMidiFile.Create(nil);
+    MidiFile.Filename := fFileName;
+    try
+      MidiFile.ReadFile;
+      FileOpened := true;
+    except
+      MidiFile.Free;
+    end;
+  end;
+
+  if (not FileOpened) then
+  begin
+    ScreenPopupError.ShowPopup(Language.Translate('ERROR_FILE_NOT_FOUND'));
+    Exit;
+  end;
+
+  Len := 0;
+  SelTrack := 0;
+  BPM := MidiFile.Bpm;
+  Ticks := MidiFile.TicksPerQuarter / 4;
+
+  KMIDITrackIndex := -1;
+  SMFTrackIndex := -1;
+
+  SetLength(Tracks, MidiFile.NumberOfTracks);
+  for T := 0 to MidiFile.NumberOfTracks-1 do
+    Tracks[T].LyricType := [];
+
+  for T := 0 to MidiFile.NumberOfTracks-1 do
+  begin
+    MidiTrack := MidiFile.GetTrack(T);
+    MidiTrack.OnMidiEvent := nil;
+    Tracks[T].Name := DecodeStringUTF8(MidiTrack.getName, DEFAULT_ENCODING);
+    Tracks[T].NoteType := ntNone;
+    Tracks[T].Status := [];
+
+    SetLength(Tracks[T].Note, MidiTrack.getEventCount());
+    for N := 0 to MidiTrack.getEventCount-1 do
+    begin
+      MidiEvent := MidiTrack.GetEvent(N);
+
+      Tracks[T].Note[N].Start     := MidiEvent.time;
+      Tracks[T].Note[N].Len       := MidiEvent.len;
+      Tracks[T].Note[N].Event     := MidiEvent.event;
+      Tracks[T].Note[N].EventType := MidiEvent.event shr 4;
+      Tracks[T].Note[N].Channel   := MidiEvent.event and $0F;
+      Tracks[T].Note[N].Data1     := MidiEvent.data1;
+      Tracks[T].Note[N].Data2     := MidiEvent.data2;
+      Tracks[T].Note[N].Str       := DecodeStringUTF8(MidiEvent.str, DEFAULT_ENCODING);
+
+      if (Tracks[T].Note[N].Event = MIDI_EVENT_META) then
+      begin
+        case (Tracks[T].Note[N].Data1) of
+          MIDI_META_TEXT: begin
+            // KMIDI lyrics (uses MIDI_META_TEXT events)
+            if (StrLComp(PAnsiChar(Tracks[T].Note[N].Str), '@KMIDI KARAOKE FILE', 19) = 0) and
+               (High(Tracks) >= T+1) then
+            begin
+              // The '@KMIDI ...' mark is in the first track (mostly named 'Soft Karaoke')
+              // but the lyrics are in the second track (named 'Words')
+              Tracks[T+1].LyricType := Tracks[T+1].LyricType + [ltKMIDI];
+              KMIDITrackIndex := T+1;
+            end;
+          end;
+          MIDI_META_LYRICS: begin
+            // lyrics in Standard Midi File format found (uses MIDI_META_LYRICS events)
+            Tracks[T].LyricType := Tracks[T].LyricType + [ltSMFLyric];
+            SMFTrackIndex := T;
+          end;
+        end;
+      end
+      else if (Tracks[T].Note[N].EventType = MIDI_EVENTTYPE_NOTEON) then
+      begin
+        // notes available
+        Tracks[T].NoteType := ntAvail;
+      end;
+
+      if Tracks[T].Note[N].Start + Tracks[T].Note[N].Len > Len then
+        Len := Tracks[T].Note[N].Start + Tracks[T].Note[N].Len;
+    end;
+  end;
+
+  // set default lyric track. Prefer KMIDI.
+  if (KMIDITrackIndex > -1) then
+    Tracks[KMIDITrackIndex].Status := Tracks[KMIDITrackIndex].Status + [tsLyrics]
+  else if (SMFTrackIndex > -1) then
+    Tracks[SMFTrackIndex].Status := Tracks[SMFTrackIndex].Status + [tsLyrics];
+{$ENDIF}
+end;
+
+function TScreenEditConvert.Draw: boolean;
+var
+  Count:  integer;
+  Count2: integer;
+  Bottom: real;
+  X:      real;
+  Y:      real;
+  Height: real;
+  YSkip:  real;
+begin
+  // draw static menu
+  inherited Draw;
+
+  Y := 100;
+
+  Height := min(480, 40 * Length(Tracks));
+  Bottom := Y + Height;
+
+  YSkip := Height / Length(Tracks);
+
+  // highlight selected track
+  DrawQuad(10, Y+SelTrack*YSkip, 780, YSkip, 0.8, 0.8, 0.8);
+
+  // track-selection info
+  for Count := 0 to High(Tracks) do
+    if Tracks[Count].Status <> [] then
+      DrawQuad(10, Y + Count*YSkip, 50, YSkip, 0.8, 0.3, 0.3);
+  glColor3f(0, 0, 0);
+  for Count := 0 to High(Tracks) do
+  begin
+    if Tracks[Count].NoteType = ntAvail then
+    begin
+      if tsNotes in Tracks[Count].Status then
+        glColor3f(0, 0, 0)
+      else
+        glColor3f(0.7, 0.7, 0.7);
+      SetFontPos(25, Y + Count*YSkip + 10);
+      SetFontSize(15);
+      glPrint('N');
+    end;
+    if Tracks[Count].LyricType <> [] then
+    begin
+      if tsLyrics in Tracks[Count].Status then
+        glColor3f(0, 0, 0)
+      else
+        glColor3f(0.7, 0.7, 0.7);
+      SetFontPos(40, Y + Count*YSkip + 10);
+      SetFontSize(15);
+      glPrint('L');
+    end;
+  end;
+
+  DrawLine( 10, Y,  10, Bottom, 0, 0, 0);
+  DrawLine( 60, Y,  60, Bottom, 0, 0, 0);
+  DrawLine(790, Y, 790, Bottom, 0, 0, 0);
+
+  for Count := 0 to Length(Tracks) do
+    DrawLine(10, Y + Count*YSkip, 790, Y + Count*YSkip, 0, 0, 0);
+
+  for Count := 0 to High(Tracks) do
+  begin
+    SetFontPos(65, Y + Count*YSkip);
+    SetFontSize(15);
+    glPrint(Tracks[Count].Name);
+  end;
+
+  for Count := 0 to High(Tracks) do
+  begin
+    for Count2 := 0 to High(Tracks[Count].Note) do
+    begin
+      if Tracks[Count].Note[Count2].EventType = MIDI_EVENTTYPE_NOTEON then
+        DrawQuad(60 + Tracks[Count].Note[Count2].Start/Len * 725,
+                 Y + (Count+1)*YSkip - Tracks[Count].Note[Count2].Data1*35/127,
+                 3, 3,
+                 ColR[Count], ColG[Count], ColB[Count]);
+      if Tracks[Count].Note[Count2].EventType = 15 then
+        DrawLine(60 + Tracks[Count].Note[Count2].Start/Len * 725, Y + 0.75 * YSkip + Count*YSkip,
+                 60 + Tracks[Count].Note[Count2].Start/Len * 725, Y + YSkip + Count*YSkip,
+                 ColR[Count], ColG[Count], ColB[Count]);
+    end;
+  end;
+
+  // playing line
+  {$IFDEF UseMIDIPort}
+  if (MidiFile <> nil) then
+    X := 60 + MidiFile.GetCurrentTime/MidiFile.GetTrackLength*730;
+  {$ENDIF}
+  DrawLine(X, Y, X, Bottom, 0.3, 0.3, 0.3);
+
+  Result := true;
+end;
+
+procedure TScreenEditConvert.OnHide;
+begin
+{$IFDEF UseMIDIPort}
+  FreeAndNil(MidiFile);
+  MidiOut.Close;
+  FreeAndNil(MidiOut);
+{$ENDIF}
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenEditHeader.pas b/songmanagement/src/screens/UScreenEditHeader.pas
new file mode 100644
index 00000000..1d697bc9
--- /dev/null
+++ b/songmanagement/src/screens/UScreenEditHeader.pas
@@ -0,0 +1,445 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenEditHeader;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  USongs,
+  USong,
+  UPath,
+  UThemes;
+
+type
+  TScreenEditHeader = class(TMenu)
+    public
+      CurrentSong:      TSong;
+      TextTitle:        integer;
+      TextArtist:       integer;
+      TextMp3:          integer;
+      TextBackground:   integer;
+      TextVideo:        integer;
+      TextVideoGAP:     integer;
+      TextRelative:     integer;
+      TextResolution:   integer;
+      TextNotesGAP:     integer;
+      TextStart:        integer;
+      TextGAP:          integer;
+      TextBPM:          integer;
+      StaticTitle:      integer;
+      StaticArtist:     integer;
+      StaticMp3:        integer;
+      StaticBackground: integer;
+      StaticVideo:      integer;
+      StaticVideoGAP:   integer;
+      StaticRelative:   integer;
+      StaticResolution: integer;
+      StaticNotesGAP:   integer;
+      StaticStart:      integer;
+      StaticGAP:        integer;
+      StaticBPM:        integer;
+      Sel:              array[0..11] of boolean;
+      procedure SetRoundButtons;
+
+      constructor Create; override;
+      procedure OnShow; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+{      function Draw: boolean; override;
+      procedure Finish;}
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UMusic,
+  SysUtils,
+  UFiles,
+  USkins,
+  UTexture,
+  UUnicodeUtils;
+
+function TScreenEditHeader.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+  T:    integer;
+begin
+  Result := true;
+  if (PressedDown) then    // Key Down
+   begin   // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE:
+        begin
+          //Music.PlayBack;
+          //FadeTo(@MainScreen);
+          Result := false;
+        end;
+
+      SDLK_RETURN:
+        begin
+          if Interaction = 1 then
+          begin
+            //Save;
+          end;
+        end;
+
+      SDLK_RIGHT:
+        begin
+          case Interaction of
+            0..0: InteractNext;
+            1:    Interaction := 0;
+          end;
+        end;
+
+      SDLK_LEFT:
+        begin
+          case Interaction of
+            0:    Interaction := 1;
+            1..1: InteractPrev;
+          end;
+        end;
+
+      SDLK_DOWN:
+        begin
+          case Interaction of
+            0..1:  Interaction := 2;
+            2..12: InteractNext;
+            13:    Interaction := 0;
+          end;
+        end;
+
+      SDLK_UP:
+        begin
+          case Interaction of
+            0..1:  Interaction := 13;
+            2:     Interaction := 0;
+            3..13: InteractPrev;
+          end;
+        end;
+
+      SDLK_BACKSPACE:
+        begin
+          T := Interaction - 2 + TextTitle;
+          if (Interaction >= 2) and (Interaction <= 13) and (Length(Text[T].Text) >= 1) then
+          begin
+            Text[T].DeleteLastLetter;
+            SetRoundButtons;            
+          end;
+        end;
+
+    end;
+    case CharCode of
+      32..255:
+        begin
+          if (Interaction >= 2) and (Interaction <= 13) then
+          begin
+            Text[Interaction - 2 + TextTitle].Text :=
+              Text[Interaction - 2 + TextTitle].Text + UCS4ToUTF8String(CharCode);
+            SetRoundButtons;
+          end;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenEditHeader.Create;
+begin
+  inherited Create;
+
+  AddButton(40, 20, 100, 40, Skin.GetTextureFileName('ButtonF'));
+  AddButtonText(15, 5, 'Open');
+
+  AddButton(160, 20, 100, 40, Skin.GetTextureFileName('ButtonF'));
+  AddButtonText(20, 5, 'Save');
+
+  AddBox(80, 60, 640, 550);
+
+  AddText(160, 110 + 0*30, 0, 30, 0, 0, 0, 'Title:');
+  AddText(160, 110 + 1*30, 0, 30, 0, 0, 0, 'Artist:');
+  AddText(160, 110 + 2*30, 0, 30, 0, 0, 0, 'MP3:');
+
+  AddText(160, 110 + 4*30, 0, 30, 0, 0, 0, 'Background:');
+  AddText(160, 110 + 5*30, 0, 30, 0, 0, 0, 'Video:');
+  AddText(160, 110 + 6*30, 0, 30, 0, 0, 0, 'VideoGAP:');
+
+  AddText(160, 110 + 8*30,  0, 30, 0, 0, 0, 'Relative:');
+  AddText(160, 110 + 9*30,  0, 30, 0, 0, 0, 'Resolution:');
+  AddText(160, 110 + 10*30, 0, 30, 0, 0, 0, 'NotesGAP:');
+
+  AddText(160, 110 + 12*30, 0, 30, 0, 0, 0, 'Start:');
+  AddText(160, 110 + 13*30, 0, 30, 0, 0, 0, 'GAP:');
+  AddText(160, 110 + 14*30, 0, 30, 0, 0, 0, 'BPM:');
+
+  TextTitle  := AddText(340, 110 + 0*30, 0, 30, 0, 0, 0, '');
+  TextArtist := AddText(340, 110 + 1*30, 0, 30, 0, 0, 0, '');
+  TextMp3    := AddText(340, 110 + 2*30, 0, 30, 0, 0, 0, '');
+
+  TextBackground := AddText(340, 110 + 4*30, 0, 30, 0, 0, 0, '');
+  TextVideo      := AddText(340, 110 + 5*30, 0, 30, 0, 0, 0, '');
+  TextVideoGAP   := AddText(340, 110 + 6*30, 0, 30, 0, 0, 0, '');
+
+  TextRelative   := AddText(340, 110 + 8*30, 0, 30, 0, 0, 0, '');
+  TextResolution := AddText(340, 110 + 9*30, 0, 30, 0, 0, 0, '');
+  TextNotesGAP   := AddText(340, 110 + 10*30, 0, 30, 0, 0, 0, '');
+
+  TextStart :=  AddText(340, 110 + 12*30, 0, 30, 0, 0, 0, '');
+  TextGAP   :=  AddText(340, 110 + 13*30, 0, 30, 0, 0, 0, '');
+  TextBPM   :=  AddText(340, 110 + 14*30, 0, 30, 0, 0, 0, '');
+
+  StaticTitle      := AddStatic(130, 115 + 0*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticArtist     := AddStatic(130, 115 + 1*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticMp3        := AddStatic(130, 115 + 2*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticBackground := AddStatic(130, 115 + 4*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticVideo      := AddStatic(130, 115 + 5*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticVideoGAP   := AddStatic(130, 115 + 6*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticRelative   := AddStatic(130, 115 + 8*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticResolution := AddStatic(130, 115 + 9*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticNotesGAP   := AddStatic(130, 115 + 10*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticStart      := AddStatic(130, 115 + 12*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticGAP        := AddStatic(130, 115 + 13*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+  StaticBPM        := AddStatic(130, 115 + 14*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+
+  AddInteraction(iText, TextTitle);
+  AddInteraction(iText, TextArtist);
+  AddInteraction(iText, TextMp3);
+  AddInteraction(iText, TextBackground);
+  AddInteraction(iText, TextVideo);
+  AddInteraction(iText, TextVideoGAP);
+  AddInteraction(iText, TextRelative);
+  AddInteraction(iText, TextResolution);
+  AddInteraction(iText, TextNotesGAP);
+  AddInteraction(iText, TextStart);
+  AddInteraction(iText, TextGAP);
+  AddInteraction(iText, TextBPM);
+end;
+
+procedure TScreenEditHeader.OnShow;
+begin
+  inherited;
+
+{  if FileExists(FileName) then  // load file
+  begin
+    CurrentSong.FileName := FileName;
+    SkanujPlik(CurrentSong);
+
+    SetLength(TrueBoolStrs, 1);
+    TrueBoolStrs[0] := 'yes';
+    SetLength(FalseBoolStrs, 1);
+    FalseBoolStrs[0] := 'no';
+
+    Text[TextTitle].Text :=   CurrentSong.Title;
+    Text[TextArtist].Text :=  CurrentSong.Artist;
+    Text[TextMP3].Text :=     CurrentSong.Mp3;
+    Text[TextBackground].Text :=  CurrentSong.Background;
+    Text[TextVideo].Text :=       CurrentSong.Video;
+    Text[TextVideoGAP].Text :=    FloatToStr(CurrentSong.VideoGAP);
+    Text[TextRelative].Text :=    BoolToStr(CurrentSong.Relative, true);
+    Text[TextResolution].Text :=  IntToStr(CurrentSong.Resolution);
+    Text[TextNotesGAP].Text :=    IntToStr(CurrentSong.NotesGAP);
+    Text[TextStart].Text := FloatToStr(CurrentSong.Start);
+    Text[TextGAP].Text :=   FloatToStr(CurrentSong.GAP);
+    Text[TextBPM].Text :=   FloatToStr(CurrentSong.BPM[0].BPM);
+    SetRoundButtons;
+  end;}
+
+  Interaction := 0;
+end;
+
+(*function TScreenEdit.Draw: boolean;
+var
+  Min:     integer;
+  Sec:     integer;
+  Count:   integer;
+  AktBeat: integer;
+begin
+{  glClearColor(1,1,1,1);
+
+  // control music
+  if PlaySentence then
+  begin
+    // stop the music
+    if (Music.Position > PlayStopTime) then
+    begin
+      Music.Stop;
+      PlaySentence := false;
+    end;
+
+    // click
+    if (Click) and (PlaySentence) then
+    begin
+      AktBeat := Floor(CurrentSong.BPM[0].BPM * (Music.Position - CurrentSong.GAP / 1000) / 60);
+      Text[TextDebug].Text := IntToStr(AktBeat);
+      if AktBeat <> LastClick then
+      begin
+        for Count := 0 to Czesci[0].Czesc[Czesci[0].Akt].HighNut do
+          if (Czesci[0].Czesc[Czesci[0].Akt].Nuta[Count].Start = AktBeat) then
+          begin
+            Music.PlayClick;
+            LastClick := AktBeat;
+          end;
+      end;
+    end; // click
+  end; // if PlaySentence
+
+  Text[TextSentence].Text := IntToStr(Czesci[0].Akt + 1) + ' / ' + IntToStr(Czesci[0].Ilosc);
+  Text[TextNote].Text := IntToStr(AktNuta + 1) + ' / ' + IntToStr(Czesci[0].Czesc[Czesci[0].Akt].LengthNote);
+
+  // Song info
+  Text[TextBPM].Text := FloatToStr(CurrentSong.BPM[0].BPM / 4);
+  Text[TextGAP].Text := FloatToStr(CurrentSong.GAP);
+
+  // Note info
+  Text[TextNStart].Text :=    IntToStr(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start);
+  Text[TextNDlugosc].Text :=  IntToStr(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc);
+  Text[TextNTon].Text :=      IntToStr(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Ton);
+  Text[TextNText].Text :=              Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Text;
+
+  // draw static menu
+  inherited Draw;
+
+  // draw notes
+  SingDrawNoteLines(20, 300, 780, 15);
+  SingDrawBeatDelimeters(40, 300, 760, 0);
+  SingDrawCzesc(40, 405, 760, 0);
+
+  // draw text
+  Lyric.Draw;}
+
+end;*)
+
+procedure TScreenEditHeader.SetRoundButtons;
+begin
+  if Length(Text[TextTitle].Text) > 0 then
+    Statics[StaticTitle].Visible := true
+  else
+    Statics[StaticTitle].Visible := false;
+
+  if Length(Text[TextArtist].Text) > 0 then
+    Statics[StaticArtist].Visible := true
+  else
+    Statics[StaticArtist].Visible := false;
+
+  if Length(Text[TextMp3].Text) > 0 then
+    Statics[StaticMp3].Visible := true
+  else 
+    Statics[StaticMp3].Visible := false;
+
+  if Length(Text[TextBackground].Text) > 0 then
+    Statics[StaticBackground].Visible := true
+  else
+    Statics[StaticBackground].Visible := false;
+
+  if Length(Text[TextVideo].Text) > 0 then
+    Statics[StaticVideo].Visible := true
+  else
+    Statics[StaticVideo].Visible := false;
+
+  try
+    StrToFloat(Text[TextVideoGAP].Text);
+    if StrToFloat(Text[TextVideoGAP].Text)<> 0 then
+      Statics[StaticVideoGAP].Visible := true
+    else
+      Statics[StaticVideoGAP].Visible := false;
+  except
+    Statics[StaticVideoGAP].Visible := false;
+  end;
+
+  if LowerCase(Text[TextRelative].Text) = 'yes' then
+    Statics[StaticRelative].Visible := true
+  else
+    Statics[StaticRelative].Visible := false;
+
+  try
+    StrToInt(Text[TextResolution].Text);
+    if (StrToInt(Text[TextResolution].Text) <> 0) and (StrToInt(Text[TextResolution].Text) >= 1) then
+      Statics[StaticResolution].Visible := true
+    else
+      Statics[StaticResolution].Visible := false;
+  except
+    Statics[StaticResolution].Visible := false;
+  end;
+
+  try
+    StrToInt(Text[TextNotesGAP].Text);
+    Statics[StaticNotesGAP].Visible := true;
+  except
+    Statics[StaticNotesGAP].Visible := false;
+  end;
+
+  // start
+  try
+    StrToFloat(Text[TextStart].Text);
+    if (StrToFloat(Text[TextStart].Text) > 0) then
+      Statics[StaticStart].Visible := true
+    else
+      Statics[StaticStart].Visible := false;
+  except
+    Statics[StaticStart].Visible := false;
+  end;
+
+  // GAP
+  try
+    StrToFloat(Text[TextGAP].Text);
+    Statics[StaticGAP].Visible := true;
+  except
+    Statics[StaticGAP].Visible := false;
+  end;
+
+  // BPM
+  try
+    StrToFloat(Text[TextBPM].Text);
+    if (StrToFloat(Text[TextBPM].Text) > 0) then
+      Statics[StaticBPM].Visible := true
+    else
+      Statics[StaticBPM].Visible := false;
+  except
+    Statics[StaticBPM].Visible := false;
+  end;
+
+end;
+
+(*procedure TScreenEdit.Finish;
+begin
+//
+end;*)
+
+end.
diff --git a/songmanagement/src/screens/UScreenEditSub.pas b/songmanagement/src/screens/UScreenEditSub.pas
new file mode 100644
index 00000000..fb3f04ce
--- /dev/null
+++ b/songmanagement/src/screens/UScreenEditSub.pas
@@ -0,0 +1,1809 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenEditSub;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+{$I switches.inc}
+
+uses
+  UMenu,
+  UMusic,
+  SDL,
+  SysUtils,
+  UFiles,
+  UTime,
+  USongs,
+  USong,
+  UIni,
+  ULog,
+  UTexture,
+  UMenuText,
+  UEditorLyrics,
+  Math,
+  gl,
+  {$IFDEF UseMIDIPort}
+  MidiOut,
+  MidiCons,
+  {$ENDIF}
+  UThemes;
+
+type
+  TScreenEditSub = class(TMenu)
+    private
+      AktBeat:          integer;
+      //Variable is True if no Song is loaded
+      Error:            boolean;
+      
+      TextNote:         integer;
+      TextSentence:     integer;
+      TextTitle:        integer;
+      TextArtist:       integer;
+      TextMp3:          integer;
+      TextBPM:          integer;
+      TextGAP:          integer;
+      TextDebug:        integer;
+      TextNStart:       integer;
+      TextNLength:      integer;
+      TextNTon:         integer;
+      TextNText:        integer;
+      CurrentNote:      integer;
+      PlaySentence:     boolean;
+      PlaySentenceMidi: boolean;
+      PlayStopTime:     real;
+      LastClick:        integer;
+      Click:            boolean;
+      CopySrc:          integer;
+
+      {$IFDEF UseMIDIPort}
+      MidiOut:          TMidiOutput;
+      {$endif}
+
+      MidiStart:        real;
+      MidiStop:         real;
+      MidiTime:         real;
+      MidiPos:          real;
+      MidiLastNote:     integer;
+
+      TextEditMode:     boolean;
+      editText:         UTF8String; //backup of current text in text-edit-mode
+
+      Lyric:            TEditorLyrics;
+
+      procedure DivideBPM;
+      procedure MultiplyBPM;
+      procedure LyricsCapitalize;
+      procedure LyricsCorrectSpaces;
+      procedure FixTimings;
+      procedure DivideSentence;
+      procedure JoinSentence;
+      procedure DivideNote;
+      procedure DeleteNote;
+      procedure TransposeNote(Transpose: integer);
+      procedure ChangeWholeTone(Tone: integer);
+      procedure MoveAllToEnd(Move: integer);
+      procedure MoveTextToRight;
+      procedure MarkSrc;
+      procedure PasteText;
+      procedure CopySentence(Src, Dst: integer);
+      procedure CopySentences(Src, Dst, Num: integer);
+      procedure DrawStatics;
+      procedure DrawInfoBar(x, y, w, h: integer);
+      //Note Name Mod
+      function GetNoteName(Note: integer): string;
+    public
+      Tex_Background:     TTexture;
+      FadeOut:            boolean;
+      constructor Create; override;
+      procedure OnShow; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      function ParseInputEditText(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+      function Draw: boolean; override;
+      procedure OnHide; override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UDraw,
+  UNote,
+  USkins,
+  ULanguage,
+  UTextEncoding,
+  UUnicodeUtils,
+  UPath;
+
+
+procedure OnSaveEncodingError(Value: boolean; Data: Pointer);
+var
+  SResult: TSaveSongResult;
+  FilePath: IPath;
+  Success: boolean;
+begin
+  Success := false;
+  if (Value) then
+  begin
+    CurrentSong.Encoding := encUTF8;
+    FilePath := CurrentSong.Path.Append(CurrentSong.FileName);
+    // create backup file
+    FilePath.CopyFile(Path(FilePath.ToUTF8 + '.ansi.bak'), false);
+    // store in UTF-8 encoding
+    SResult := SaveSong(CurrentSong, Lines[0], FilePath,
+             boolean(Data));
+    Success := (SResult = ssrOK);
+  end;
+
+  if (Success) then
+    ScreenPopupInfo.ShowPopup(Language.Translate('INFO_FILE_SAVED'))
+  else
+    ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
+end;
+
+// Method for input parsing. If false is returned, GetNextWindow
+// should be checked to know the next window to load;
+function TScreenEditSub.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+  SDL_ModState:  word;
+  R:    real;
+  SResult: TSaveSongResult;
+begin
+  Result := true;
+
+  if TextEditMode then
+  begin
+    Result := ParseInputEditText(PressedKey, CharCode, PressedDown);
+  end
+  else
+  begin
+
+  SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT
+    + KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT  + KMOD_RALT {+ KMOD_CAPS});
+
+  if (PressedDown) then  // Key Down
+  begin
+    // check normal keys
+    case PressedKey of
+      SDLK_Q:
+        begin
+          Result := false;
+          Exit;
+        end;
+      SDLK_S:
+        begin
+          // Save Song
+          SResult := SaveSong(CurrentSong, Lines[0], CurrentSong.Path.Append(CurrentSong.FileName),
+                   (SDL_ModState = KMOD_LSHIFT));
+          if (SResult = ssrOK) then
+          begin
+            //ScreenPopupInfo.ShowPopup(Language.Translate('INFO_FILE_SAVED'));
+            Text[TextDebug].Text := Language.Translate('INFO_FILE_SAVED');
+          end
+          else if (SResult = ssrEncodingError) then
+          begin
+            ScreenPopupCheck.ShowPopup(Language.Translate('ENCODING_ERROR_ASK_FOR_UTF8'), OnSaveEncodingError,
+                Pointer(SDL_ModState = KMOD_LSHIFT), true);
+          end
+          else
+          begin
+            ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
+          end;
+          Exit;
+        end;
+
+      SDLK_R:   //reload
+        begin
+          AudioPlayback.Stop;
+          {$IFDEF UseMIDIPort}
+          MidiOut.Close;
+          MidiOut.Free;
+          {$ENDIF}
+          Lyric.Free;
+
+          onShow;
+          Text[TextDebug].Text := 'song reloaded'; //TODO: Language.Translate('SONG_RELOADED'); 
+        end;
+
+      SDLK_D:
+        begin
+          // Divide lengths by 2
+          if (SDL_ModState = KMOD_LSHIFT) then
+          begin
+            DivideBPM;
+            Exit;
+          end;
+        end;
+      SDLK_M:
+        begin
+          // Multiply lengths by 2
+          if (SDL_ModState = KMOD_LSHIFT) then
+          begin
+            MultiplyBPM;
+            Exit;
+          end;
+        end;
+      SDLK_C:
+        begin
+          // Capitalize letter at the beginning of line
+          if SDL_ModState = 0 then
+            LyricsCapitalize;
+
+          // Correct spaces
+          if SDL_ModState = KMOD_LSHIFT then
+            LyricsCorrectSpaces;
+
+          // Copy sentence
+          if SDL_ModState = KMOD_LCTRL then
+            MarkSrc;
+
+          Exit;
+        end;
+      SDLK_V:
+        begin
+          // Paste text
+          if SDL_ModState = KMOD_LCTRL then
+          begin
+            if Lines[0].Line[Lines[0].Current].HighNote >= Lines[0].Line[CopySrc].HighNote then
+              PasteText
+            else
+              Log.LogStatus('PasteText: invalid range', 'TScreenEditSub.ParseInput');
+          end;
+
+          if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then
+          begin
+            CopySentence(CopySrc, Lines[0].Current);
+          end;
+        end;
+      SDLK_T:
+        begin
+          // Fixes timings between sentences
+          FixTimings;
+          Exit;
+        end;
+      SDLK_P:
+        begin
+          if SDL_ModState = 0 then
+          begin
+            // Play Sentence
+            Click := true;
+            AudioPlayback.Stop;
+            R := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start);
+            if R <= AudioPlayback.Length then
+            begin
+              AudioPlayback.Position := R;
+              PlayStopTime := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_);
+              PlaySentence := true;
+              AudioPlayback.Play;
+              LastClick := -100;
+            end;
+          end
+          else if SDL_ModState = KMOD_LSHIFT then
+          begin
+            PlaySentenceMidi := true;
+
+            MidiTime := USTime.GetTime;
+            MidiStart := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start);
+            MidiStop := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_);
+
+            LastClick := -100;
+          end
+          else if SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL then
+          begin
+            PlaySentenceMidi := true;
+            MidiTime  := USTime.GetTime;
+            MidiStart := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start);
+            MidiStop  := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_);
+            LastClick := -100;
+
+            PlaySentence := true;
+            Click := true;
+            AudioPlayback.Stop;
+            AudioPlayback.Position := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start)+0{-0.10};
+            PlayStopTime := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_)+0;
+            AudioPlayback.Play;
+            LastClick := -100;
+          end;
+          Exit;
+        end;
+      
+      // Golden Note
+      SDLK_G:
+        begin
+          if (Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType = ntGolden) then
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntNormal
+          else
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntGolden;
+          
+          Exit;
+        end;
+      
+      // Freestyle Note
+      SDLK_F:
+        begin
+          if (Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType = ntFreestyle) then
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntNormal
+          else
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntFreestyle;
+
+            // update lyrics
+            Lyric.AddLine(Lines[0].Current);
+            Lyric.Selected := CurrentNote;
+          
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          FadeTo(@ScreenSong);
+        end;
+
+      SDLK_BACKQUOTE:
+        begin
+          // Increase Note Length (same as Alt + Right)
+          Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+          if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+            Inc(Lines[0].Line[Lines[0].Current].End_);
+        end;
+
+      SDLK_EQUALS:
+        begin
+          // Increase BPM
+          if SDL_ModState = 0 then
+            CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 5) + 1) / 5; // (1/20)
+          if SDL_ModState = KMOD_LSHIFT then
+            CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM + 4; // (1/1)
+          if SDL_ModState = KMOD_LCTRL then
+            CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 25) + 1) / 25; // (1/100)
+        end;
+
+      SDLK_MINUS:
+        begin
+          // Decrease BPM
+          if SDL_ModState = 0 then
+            CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 5) - 1) / 5;
+          if SDL_ModState = KMOD_LSHIFT then
+            CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM - 4;
+          if SDL_ModState = KMOD_LCTRL then
+            CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 25) - 1) / 25;
+        end;
+
+      SDLK_4:
+        begin
+          if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then
+          begin
+            CopySentence(CopySrc, Lines[0].Current);
+            CopySentence(CopySrc+1, Lines[0].Current+1);
+            CopySentence(CopySrc+2, Lines[0].Current+2);
+            CopySentence(CopySrc+3, Lines[0].Current+3);
+          end;
+
+          if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT + KMOD_LALT then
+          begin
+            CopySentences(CopySrc, Lines[0].Current, 4);
+          end;
+        end;
+      SDLK_5:
+        begin
+          if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then
+          begin
+            CopySentence(CopySrc, Lines[0].Current);
+            CopySentence(CopySrc+1, Lines[0].Current+1);
+            CopySentence(CopySrc+2, Lines[0].Current+2);
+            CopySentence(CopySrc+3, Lines[0].Current+3);
+            CopySentence(CopySrc+4, Lines[0].Current+4);
+          end;
+
+          if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT + KMOD_LALT then
+          begin
+            CopySentences(CopySrc, Lines[0].Current, 5);
+          end;
+        end;
+
+      SDLK_9:
+        begin
+          // Decrease GAP
+          if SDL_ModState = 0 then
+            CurrentSong.GAP := CurrentSong.GAP - 10;
+          if SDL_ModState = KMOD_LSHIFT then
+            CurrentSong.GAP := CurrentSong.GAP - 1000;
+        end;
+      SDLK_0:
+        begin
+          // Increase GAP
+          if SDL_ModState = 0 then
+            CurrentSong.GAP := CurrentSong.GAP + 10;
+          if SDL_ModState = KMOD_LSHIFT then
+            CurrentSong.GAP := CurrentSong.GAP + 1000;
+        end;
+
+      SDLK_KP_PLUS:
+        begin
+          // Increase tone of all notes
+          if SDL_ModState = 0 then
+            ChangeWholeTone(1);
+          if SDL_ModState = KMOD_LSHIFT then
+            ChangeWholeTone(12);
+        end;
+
+      SDLK_KP_MINUS:
+        begin
+          // Decrease tone of all notes
+          if SDL_ModState = 0 then
+            ChangeWholeTone(-1);
+          if SDL_ModState = KMOD_LSHIFT then
+            ChangeWholeTone(-12);
+        end;
+
+      SDLK_SLASH:
+        begin
+          if SDL_ModState = 0 then
+          begin
+            // Insert start of sentece
+            if CurrentNote > 0 then
+              DivideSentence;
+          end;
+
+          if SDL_ModState = KMOD_LSHIFT then
+          begin
+            // Join next sentence with current
+            if Lines[0].Current < Lines[0].High then
+              JoinSentence;
+          end;
+
+          if SDL_ModState = KMOD_LCTRL then
+          begin
+            // divide note
+            DivideNote;
+          end;
+
+        end;
+
+      SDLK_F4:
+        begin
+          // Enter Text Edit Mode
+          editText := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text;
+          TextEditMode := true;
+        end;
+
+      SDLK_SPACE:
+        begin
+          if (SDL_ModState = 0) or (SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL) then
+          begin
+            // Play Sentence
+            PlaySentenceMidi := false; // stop midi
+            PlaySentence := true;
+            Click := false;
+            AudioPlayback.Stop;
+            AudioPlayback.Position := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+            PlayStopTime := (GetTimeFromBeat(
+              Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start +
+              Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length));
+            AudioPlayback.Play;
+            LastClick := -100;
+          end;
+
+          if (SDL_ModState = KMOD_LSHIFT) or (SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL) then
+          begin
+            // Play Midi
+            PlaySentenceMidi := true;
+
+            MidiTime := USTime.GetTime;
+            MidiStart := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+            MidiStop := GetTimeFromBeat(
+              Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start +
+              Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+
+            LastClick := -100;
+          end;
+        end;
+
+      SDLK_RETURN:
+        begin
+        end;
+
+      SDLK_DELETE:
+        begin
+          if SDL_ModState = KMOD_LCTRL then
+          begin
+            // deletes current note
+            DeleteNote;
+          end;
+        end;
+
+      SDLK_PERIOD:
+        begin
+          // moves text to right in current sentence
+          MoveTextToRight;
+        end;
+
+      SDLK_RIGHT:
+        begin
+          // right
+          if SDL_ModState = 0 then
+          begin
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+            Inc(CurrentNote);
+            if CurrentNote > Lines[0].Line[Lines[0].Current].HighNote then
+              CurrentNote := 0;
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+            Lyric.Selected := CurrentNote;
+          end;
+
+          // ctrl + right
+          if (SDL_ModState = KMOD_LCTRL) or (SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT) then
+          begin
+            if Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length > 1 then
+            begin
+              Dec(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+              Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+              if CurrentNote = 0 then
+              begin
+                Inc(Lines[0].Line[Lines[0].Current].Start);
+              end;
+            end;
+          end;
+
+          // shift + right
+          if SDL_ModState = KMOD_LSHIFT then
+          begin
+            Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+            if CurrentNote = 0 then
+            begin
+              Inc(Lines[0].Line[Lines[0].Current].Start);
+            end;
+            if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+              Inc(Lines[0].Line[Lines[0].Current].End_);
+          end;
+
+          // alt + right
+          if (SDL_ModState = KMOD_LALT) or (SDL_ModState = KMOD_LALT + KMOD_LSHIFT) then
+          begin
+            Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+            if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+              Inc(Lines[0].Line[Lines[0].Current].End_);
+          end;
+
+          // alt + ctrl + shift + right = move all from cursor to right
+          if SDL_ModState = KMOD_LALT + KMOD_LCTRL + KMOD_LSHIFT then
+          begin
+            MoveAllToEnd(1);
+          end;
+
+        end;
+
+      SDLK_LEFT:
+        begin
+          // left
+          if SDL_ModState = 0 then
+          begin
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+            Dec(CurrentNote);
+            if CurrentNote = -1 then
+              CurrentNote := Lines[0].Line[Lines[0].Current].HighNote;
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+            Lyric.Selected := CurrentNote;
+          end;
+
+          // ctrl + left
+          if (SDL_ModState = KMOD_LCTRL) or (SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT) then
+          begin
+            Dec(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+            Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+            if CurrentNote = 0 then
+            begin
+              Dec(Lines[0].Line[Lines[0].Current].Start);
+            end;
+          end;
+
+          // shift + left
+          if SDL_ModState = KMOD_LSHIFT then
+          begin
+            Dec(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+
+            // resizing sentences
+            if CurrentNote = 0 then
+            begin
+              Dec(Lines[0].Line[Lines[0].Current].Start);
+            end;
+
+            if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+              Dec(Lines[0].Line[Lines[0].Current].End_);
+
+          end;
+
+          // alt + left
+          if (SDL_ModState = KMOD_LALT) or (SDL_ModState = KMOD_LALT + KMOD_LSHIFT) then
+          begin
+            if Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length > 1 then
+            begin
+              Dec(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+              if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+                Dec(Lines[0].Line[Lines[0].Current].End_);
+            end;
+          end;
+
+          // alt + ctrl + shift + right = move all from cursor to left
+          if SDL_ModState = KMOD_LALT + KMOD_LCTRL + KMOD_LSHIFT then
+          begin
+            MoveAllToEnd(-1);
+          end;
+
+        end;
+
+      SDLK_DOWN:
+        begin
+
+          // skip to next sentence
+          if SDL_ModState = 0 then
+          begin
+            {$IFDEF UseMIDIPort}
+            MidiOut.PutShort(MIDI_NOTEOFF or 1,
+                Lines[0].Line[Lines[0].Current].Note[MidiLastNote].Tone + 60,
+                127);
+            PlaySentenceMidi := false;
+            {$ENDIF}
+
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+            Inc(Lines[0].Current);
+            CurrentNote := 0;
+            if Lines[0].Current > Lines[0].High then
+              Lines[0].Current := 0;
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+
+            Lyric.AddLine(Lines[0].Current);
+            Lyric.Selected := 0;
+            AudioPlayback.Stop;
+            PlaySentence := false;
+          end;
+
+          // decrease tone
+          if SDL_ModState = KMOD_LSHIFT then
+          begin
+            TransposeNote(-1);
+          end;
+
+        end;
+
+      SDLK_UP:
+        begin
+
+          // skip to previous sentence
+          if SDL_ModState = 0 then
+          begin
+            {$IFDEF UseMIDIPort}
+            MidiOut.PutShort(MIDI_NOTEOFF or 1,
+                Lines[0].Line[Lines[0].Current].Note[MidiLastNote].Tone + 60,
+                127);
+            PlaySentenceMidi := false;
+            {$endif}
+
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+            Dec(Lines[0].Current);
+            CurrentNote := 0;
+            if Lines[0].Current = -1 then
+              Lines[0].Current := Lines[0].High;
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+
+            Lyric.AddLine(Lines[0].Current);
+            Lyric.Selected := 0;
+            AudioPlayback.Stop;
+            PlaySentence := false;
+          end;
+
+          // increase tone
+          if SDL_ModState = KMOD_LSHIFT then
+          begin
+            TransposeNote(1);
+          end;
+        end;
+
+      end; // case
+    end;
+  end; // if
+end;
+
+function TScreenEditSub.ParseInputEditText(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+  SDL_ModState:  word;
+begin
+  // used when in Text Edit Mode
+  Result := true;
+
+  SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT
+    + KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT  + KMOD_RALT {+ KMOD_CAPS});
+
+  if (PressedDown) then
+  begin
+    // check normal keys
+    if (IsPrintableChar(CharCode)) then
+    begin
+      Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text :=
+        Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text + UCS4ToUTF8String(CharCode);
+
+      Lyric.AddLine(Lines[0].Current);
+      Lyric.Selected := CurrentNote;
+      Exit;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE:
+        begin
+          Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text := editText;
+          Lyric.AddLine(Lines[0].Current);
+          Lyric.Selected := CurrentNote;
+          TextEditMode := false;
+        end;
+      SDLK_F4, SDLK_RETURN:
+        begin
+          // Exit Text Edit Mode
+          TextEditMode := false;
+        end;
+      SDLK_BACKSPACE:
+        begin
+          UTF8Delete(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text,
+            LengthUTF8(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text), 1);
+          Lyric.AddLine(Lines[0].Current);
+          Lyric.Selected := CurrentNote;
+        end;
+      SDLK_RIGHT:
+        begin
+          // right
+          if SDL_ModState = 0 then
+          begin
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+            Inc(CurrentNote);
+            if CurrentNote > Lines[0].Line[Lines[0].Current].HighNote then
+              CurrentNote := 0;
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+            Lyric.Selected := CurrentNote;
+            editText := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text;
+          end;
+        end;
+      SDLK_LEFT:
+        begin
+          // left
+          if SDL_ModState = 0 then
+          begin
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+            Dec(CurrentNote);
+            if CurrentNote = -1 then
+              CurrentNote := Lines[0].Line[Lines[0].Current].HighNote;
+            Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+            Lyric.Selected := CurrentNote;
+            editText := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text;
+          end;
+      end;
+    end;
+  end;
+end;
+
+{
+procedure TScreenEditSub.NewBeat;
+begin
+  // click
+  for Pet := 0 to Lines[0].Line[Lines[0].Current].HighNut do
+    if (Lines[0].Line[Lines[0].Current].Note[Pet].Start = Czas.AktBeat) then
+      Music.PlayClick;
+end;
+}
+
+procedure TScreenEditSub.DivideBPM;
+var
+  C:    integer;
+  N:    integer;
+
+begin
+  CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM / 2;
+
+  for C := 0 to Lines[0].High do
+  begin
+    Lines[0].Line[C].Start := Lines[0].Line[C].Start div 2;
+    Lines[0].Line[C].End_  := Lines[0].Line[C].End_ div 2;
+    for N := 0 to Lines[0].Line[C].HighNote do
+    begin
+      Lines[0].Line[C].Note[N].Start  := Lines[0].Line[C].Note[N].Start div 2;
+      Lines[0].Line[C].Note[N].Length := Round(Lines[0].Line[C].Note[N].Length / 2);
+    end; // N
+  end; // C
+end;
+
+procedure TScreenEditSub.MultiplyBPM;
+var
+  C:    integer;
+  N:    integer;
+begin
+  CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM * 2;
+  for C := 0 to Lines[0].High do
+  begin
+    Lines[0].Line[C].Start := Lines[0].Line[C].Start * 2;
+    Lines[0].Line[C].End_  := Lines[0].Line[C].End_ * 2;
+    for N := 0 to Lines[0].Line[C].HighNote do
+    begin
+      Lines[0].Line[C].Note[N].Start  := Lines[0].Line[C].Note[N].Start * 2;
+      Lines[0].Line[C].Note[N].Length := Lines[0].Line[C].Note[N].Length * 2;
+    end; // N
+  end; // C
+end;
+
+procedure TScreenEditSub.LyricsCapitalize;
+var
+  C:    integer;
+  //N:    integer; // temporary
+  S:    string;
+begin
+  // temporary
+  {
+  for C := 0 to Lines[0].High do
+    for N := 0 to Lines[0].Line[C].HighNut do
+      Lines[0].Line[C].Note[N].Text := UTF8LowerCase(Lines[0].Line[C].Note[N].Text);
+  }
+
+  for C := 0 to Lines[0].High do
+  begin
+    S := AnsiUpperCase(Copy(Lines[0].Line[C].Note[0].Text, 1, 1));
+    S := S + Copy(Lines[0].Line[C].Note[0].Text, 2, Length(Lines[0].Line[C].Note[0].Text)-1);
+    Lines[0].Line[C].Note[0].Text := S;
+  end; // C
+end;
+
+procedure TScreenEditSub.LyricsCorrectSpaces;
+var
+  C:    integer;
+  N:    integer;
+begin
+  for C := 0 to Lines[0].High do
+  begin
+    // correct starting spaces in the first word
+    while Copy(Lines[0].Line[C].Note[0].Text, 1, 1) = ' ' do
+      Lines[0].Line[C].Note[0].Text := Copy(Lines[0].Line[C].Note[0].Text, 2, 100);
+
+    // move spaces on the start to the end of the previous note
+    for N := 1 to Lines[0].Line[C].HighNote do
+    begin
+      while (Copy(Lines[0].Line[C].Note[N].Text, 1, 1) = ' ') do
+      begin
+        Lines[0].Line[C].Note[N].Text := Copy(Lines[0].Line[C].Note[N].Text, 2, 100);
+        Lines[0].Line[C].Note[N-1].Text := Lines[0].Line[C].Note[N-1].Text + ' ';
+      end;
+    end; // N
+
+    // correct '-'  to '- '
+    for N := 0 to Lines[0].Line[C].HighNote do
+    begin
+      if Lines[0].Line[C].Note[N].Text = '-' then
+        Lines[0].Line[C].Note[N].Text := '- ';
+    end; // N
+
+    // add space to the previous note when the current word is '- '
+    for N := 1 to Lines[0].Line[C].HighNote do
+    begin
+      if Lines[0].Line[C].Note[N].Text  = '- ' then
+        Lines[0].Line[C].Note[N-1].Text := Lines[0].Line[C].Note[N-1].Text + ' ';
+    end; // N
+
+    // correct too many spaces at the end of note
+    for N := 0 to Lines[0].Line[C].HighNote do
+    begin
+      while Copy(Lines[0].Line[C].Note[N].Text, Length(Lines[0].Line[C].Note[N].Text)-1, 2) = '  ' do
+        Lines[0].Line[C].Note[N].Text := Copy(Lines[0].Line[C].Note[N].Text, 1, Length(Lines[0].Line[C].Note[N].Text)-1);
+    end; // N
+
+    // and correct if there is no space at the end of sentence
+    N := Lines[0].Line[C].HighNote;
+    if Copy(Lines[0].Line[C].Note[N].Text, Length(Lines[0].Line[C].Note[N].Text), 1) <> ' ' then
+      Lines[0].Line[C].Note[N].Text := Lines[0].Line[C].Note[N].Text + ' ';
+
+  end; // C
+end;
+
+procedure TScreenEditSub.FixTimings;
+var
+  C:    integer;
+  S:    integer;
+  Min:  integer;
+  Max:  integer;
+begin
+  for C := 1 to Lines[0].High do
+  begin
+    with Lines[0].Line[C-1] do
+    begin
+      Min := Note[HighNote].Start + Note[HighNote].Length;
+      Max := Lines[0].Line[C].Note[0].Start;
+      case (Max - Min) of
+        0:    S := Max;
+        1:    S := Max;
+        2:    S := Max - 1;
+        3:    S := Max - 2;
+        else
+          if ((Max - Min) > 4) then
+            S := Min + 2
+          else
+            S := Max;
+      end; // case
+
+      Lines[0].Line[C].Start := S;
+    end; // with
+  end; // for
+end;
+
+procedure TScreenEditSub.DivideSentence;
+var
+  C:      integer;
+  CStart: integer;
+  CNew:   integer;
+  CLen:   integer;
+  N:      integer;
+  NStart: integer;
+  NHigh:  integer;
+begin
+  // increase sentence length by 1
+  CLen := Length(Lines[0].Line);
+  SetLength(Lines[0].Line, CLen + 1);
+  Inc(Lines[0].Number);
+  Inc(Lines[0].High);
+
+  // move needed sentences to one forward. newly has the copy of divided sentence
+  CStart := Lines[0].Current;
+  for C := CLen-1 downto CStart do
+    Lines[0].Line[C+1] := Lines[0].Line[C];
+
+  // clear and set new sentence
+  CNew := CStart + 1;
+  NStart := CurrentNote;
+  Lines[0].Line[CNew].Start := Lines[0].Line[CStart].Note[NStart].Start;
+  Lines[0].Line[CNew].Lyric := '';
+  Lines[0].Line[CNew].End_ := 0;
+  Lines[0].Line[CNew].BaseNote := 0;//High(integer); // TODO: High (integer) will causes a memory exception later in this procedure. Weird!
+  Lines[0].Line[CNew].HighNote := -1;
+  SetLength(Lines[0].Line[CNew].Note, 0);
+
+  // move right notes to new sentences
+  NHigh := Lines[0].Line[CStart].HighNote;
+  for N := NStart to NHigh do
+  begin
+    // increase sentence counters
+    with Lines[0].Line[CNew] do
+    begin
+      Inc(HighNote);
+      SetLength(Note, HighNote + 1);
+      Note[HighNote] := Lines[0].Line[CStart].Note[N];
+      End_ := Note[HighNote].Start + Note[HighNote].Length;
+      
+      if Note[HighNote].Tone < BaseNote then
+        BaseNote := Note[HighNote].Tone;
+    end;
+  end;
+
+  // clear old notes and set sentence counters
+  Lines[0].Line[CStart].HighNote := NStart - 1;
+  Lines[0].Line[CStart].End_ := Lines[0].Line[CStart].Note[NStart-1].Start +
+    Lines[0].Line[CStart].Note[NStart-1].Length;
+  SetLength(Lines[0].Line[CStart].Note, Lines[0].Line[CStart].HighNote + 1);
+
+  //recalculate BaseNote of the divided Sentence
+  with Lines[0].Line[CStart] do
+  begin
+    BaseNote := High(integer);
+
+    for N := 0 to HighNote do
+      if Note[N].Tone < BaseNote then
+        BaseNote := Note[N].Tone;
+  end;
+
+  Lines[0].Current := Lines[0].Current + 1;
+  CurrentNote := 0;
+  Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+  Lyric.AddLine(Lines[0].Current);
+end;
+
+procedure TScreenEditSub.JoinSentence;
+var
+  C:      integer;
+  N:      integer;
+  NStart: integer;
+  NDst:   integer;
+begin
+  C := Lines[0].Current;
+
+  // set new sentence
+  NStart := Lines[0].Line[C].HighNote + 1;
+  Lines[0].Line[C].HighNote := Lines[0].Line[C].HighNote + Lines[0].Line[C+1].HighNote + 1;
+  SetLength(Lines[0].Line[C].Note, Lines[0].Line[C].HighNote + 1);
+
+  // move right notes to new sentences
+  for N := 0 to Lines[0].Line[C+1].HighNote do
+  begin
+    NDst := NStart + N;
+    Lines[0].Line[C].Note[NDst] := Lines[0].Line[C+1].Note[N];
+  end;
+
+  // increase sentence counters
+  NDst := Lines[0].Line[C].HighNote;
+  Lines[0].Line[C].End_ := Lines[0].Line[C].Note[NDst].Start +
+    Lines[0].Line[C].Note[NDst].Length;
+
+  // move needed sentences to one backward.
+  for C := Lines[0].Current + 1 to Lines[0].High - 1 do
+    Lines[0].Line[C] := Lines[0].Line[C+1];
+
+  // increase sentence length by 1
+  SetLength(Lines[0].Line, Length(Lines[0].Line) - 1);
+  Dec(Lines[0].Number);
+  Dec(Lines[0].High);
+end;
+
+procedure TScreenEditSub.DivideNote;
+var
+  C:    integer;
+  N:    integer;
+begin
+  C := Lines[0].Current;
+
+  with Lines[0].Line[C] do
+  begin
+    Inc(HighNote);
+    SetLength(Note, HighNote + 1);
+
+    // we copy all notes including selected one
+    for N := HighNote downto CurrentNote+1 do
+    begin
+      Note[N] := Note[N-1];
+    end;
+
+    // Note[Cur] and Note[Cur + 1] is identical at this point
+    // modify first note
+    Note[CurrentNote].Length := Note[CurrentNote+1].Length div 2 + Note[CurrentNote+1].Length mod 2;
+
+    // 2nd note
+    Note[CurrentNote+1].Start := Note[CurrentNote].Start + Note[CurrentNote].Length;
+    Note[CurrentNote+1].Length := Note[CurrentNote + 1].Length div 2;
+
+    Note[CurrentNote+1].Text := '~';
+    Note[CurrentNote+1].Color := 1;
+  end;
+
+  // update lyric display
+  Lyric.AddLine(Lines[0].Current);
+  Lyric.Selected := CurrentNote;
+end;
+
+procedure TScreenEditSub.DeleteNote;
+var
+  C:    integer;
+  N:    integer;
+begin
+  C := Lines[0].Current;
+
+  //Do Not delete Last Note
+  if (Lines[0].Line[C].HighNote > 0) then
+  begin
+    // we copy all notes from the next to the selected one
+    for N := CurrentNote+1 to Lines[0].Line[C].HighNote do
+    begin
+      Lines[0].Line[C].Note[N-1] := Lines[0].Line[C].Note[N];
+    end;
+    
+    Dec(Lines[0].Line[C].HighNote);
+
+    SetLength(Lines[0].Line[C].Note, Lines[0].Line[C].HighNote + 1);
+
+    // last note was deleted
+    if (CurrentNote > Lines[0].Line[C].HighNote) then
+    begin
+      // select new last note
+      CurrentNote := Lines[0].Line[C].HighNote;
+
+      // correct Line ending
+      with Lines[0].Line[C] do
+        End_ := Note[HighNote].Start + Note[HighNote].Length;
+    end;
+
+    Lines[0].Line[C].Note[CurrentNote].Color := 2;
+  end
+  // Last Note of current Sentence Deleted - > Delete Sentence
+  // if there are more than two left
+  else if (Lines[0].High > 1) then
+  begin
+    //Move all Sentences after the current to the Left
+    for N := C+1 to Lines[0].High do
+      Lines[0].Line[N-1] := Lines[0].Line[N];
+
+    //Delete Last Sentence
+    SetLength(Lines[0].Line, Lines[0].High);
+    Lines[0].High := High(Lines[0].Line);
+    Lines[0].Number := Length(Lines[0].Line);
+
+    CurrentNote := 0;
+    if (C > 0) then
+      Lines[0].Current := C - 1
+    else
+      Lines[0].Current := 0;
+
+    Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+  end;
+
+  // update lyric display
+  Lyric.AddLine(Lines[0].Current);
+  Lyric.Selected := CurrentNote;
+end;
+
+procedure TScreenEditSub.TransposeNote(Transpose: integer);
+begin
+  Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone, Transpose);
+end;
+
+procedure TScreenEditSub.ChangeWholeTone(Tone: integer);
+var
+  C:  integer;
+  N:  integer;
+begin
+  for C := 0 to Lines[0].High do
+  begin
+    Lines[0].Line[C].BaseNote := Lines[0].Line[C].BaseNote + Tone;
+    for N := 0 to Lines[0].Line[C].HighNote do
+      Lines[0].Line[C].Note[N].Tone := Lines[0].Line[C].Note[N].Tone + Tone;
+  end;
+end;
+
+procedure TScreenEditSub.MoveAllToEnd(Move: integer);
+var
+  C:    integer;
+  N:    integer;
+  NStart: integer;
+begin
+  for C := Lines[0].Current to Lines[0].High do
+  begin
+    NStart := 0;
+    if C = Lines[0].Current then
+      NStart := CurrentNote;
+    for N := NStart to Lines[0].Line[C].HighNote do
+    begin
+      Inc(Lines[0].Line[C].Note[N].Start, Move); // move note start
+
+      if N = 0 then
+      begin // fix beginning
+        Inc(Lines[0].Line[C].Start, Move);
+      end;
+
+      if N = Lines[0].Line[C].HighNote then // fix ending
+        Inc(Lines[0].Line[C].End_, Move);
+
+    end; // for
+  end; // for
+end;
+
+procedure TScreenEditSub.MoveTextToRight;
+var
+  C:      integer;
+  N:      integer;
+  NHigh:  integer;
+begin
+  {
+  C := Lines[0].Current;
+
+  for N := Lines[0].Line[C].HighNut downto 1 do
+  begin
+    Lines[0].Line[C].Note[N].Text := Lines[0].Line[C].Note[N-1].Text;
+  end; // for
+
+  Lines[0].Line[C].Note[0].Text := '- ';
+  }
+
+  C := Lines[0].Current;
+  NHigh := Lines[0].Line[C].HighNote;
+
+  // last word
+  Lines[0].Line[C].Note[NHigh].Text := Lines[0].Line[C].Note[NHigh-1].Text + Lines[0].Line[C].Note[NHigh].Text;
+
+  // other words
+  for N := NHigh - 1 downto CurrentNote + 1 do
+  begin
+    Lines[0].Line[C].Note[N].Text := Lines[0].Line[C].Note[N-1].Text;
+  end; // for
+  Lines[0].Line[C].Note[CurrentNote].Text := '- ';
+end;
+
+procedure TScreenEditSub.MarkSrc;
+begin
+  CopySrc := Lines[0].Current;
+end;
+
+procedure TScreenEditSub.PasteText;
+var
+  C:    integer;
+  N:    integer;
+begin
+  C := Lines[0].Current;
+
+  for N := 0 to Lines[0].Line[CopySrc].HighNote do
+    Lines[0].Line[C].Note[N].Text := Lines[0].Line[CopySrc].Note[N].Text;
+end;
+
+procedure TScreenEditSub.CopySentence(Src, Dst: integer);
+var
+  N:     integer;
+  Time1: integer;
+  Time2: integer;
+  TD:    integer;
+begin
+  Time1 := Lines[0].Line[Src].Note[0].Start;
+  Time2 := Lines[0].Line[Dst].Note[0].Start;
+  TD := Time2-Time1;
+
+  SetLength(Lines[0].Line[Dst].Note, Lines[0].Line[Src].HighNote + 1);
+  Lines[0].Line[Dst].HighNote := Lines[0].Line[Src].HighNote;
+  for N := 0 to Lines[0].Line[Src].HighNote do
+  begin
+    Lines[0].Line[Dst].Note[N].Text := Lines[0].Line[Src].Note[N].Text;
+    Lines[0].Line[Dst].Note[N].Length := Lines[0].Line[Src].Note[N].Length;
+    Lines[0].Line[Dst].Note[N].Tone := Lines[0].Line[Src].Note[N].Tone;
+    Lines[0].Line[Dst].Note[N].Start := Lines[0].Line[Src].Note[N].Start + TD;
+  end;
+  N := Lines[0].Line[Src].HighNote;
+  Lines[0].Line[Dst].End_ := Lines[0].Line[Dst].Note[N].Start + Lines[0].Line[Dst].Note[N].Length;
+end;
+
+procedure TScreenEditSub.CopySentences(Src, Dst, Num: integer);
+var
+  C:      integer;
+begin
+  // create place for new sentences
+  SetLength(Lines[0].Line, Lines[0].Number + Num - 1);
+
+  // moves sentences next to the destination
+  for C := Lines[0].High downto Dst + 1 do
+  begin
+    Lines[0].Line[C + Num - 1] := Lines[0].Line[C];
+  end;
+
+  // prepares new sentences: sets sentence start and create first note
+  for C := 1 to Num-1 do
+  begin
+    Lines[0].Line[Dst + C].Start := Lines[0].Line[Dst + C - 1].Note[0].Start +
+      (Lines[0].Line[Src + C].Note[0].Start - Lines[0].Line[Src + C - 1].Note[0].Start);
+    SetLength(Lines[0].Line[Dst + C].Note, 1);
+    Lines[0].Line[Dst + C].HighNote := 0;
+    Lines[0].Line[Dst + C].Note[0].Start := Lines[0].Line[Dst + C].Start;
+    Lines[0].Line[Dst + C].Note[0].Length := 1;
+    Lines[0].Line[Dst + C].End_ := Lines[0].Line[Dst + C].Start + 1;
+  end;
+
+  // increase counters
+  Lines[0].Number := Lines[0].Number + Num - 1;
+  Lines[0].High := Lines[0].High + Num - 1;
+
+  for C := 0 to Num-1 do
+    CopySentence(Src + C, Dst + C);
+end;
+
+procedure TScreenEditSub.DrawStatics;
+var
+  x, y, w, h: Integer;
+begin
+  //Theme:
+  //bg
+  glDisable(GL_BLEND);
+
+  x := 0;
+  y := 0;
+  w := 800;
+  h := 600;
+  glColor4f(0.3, 0.5, 0.6, 1);
+  glbegin(gl_quads);
+   glVertex2f(x, y);
+   glVertex2f(x, y+h);
+   glVertex2f(x+w, y+h);
+   glVertex2f(x+w, y);
+  glEnd;
+
+  // Line
+  glColor4f(0.9, 0.9, 0.9, 1);
+  x := 20;
+  y := 5;
+  w := 200;
+  h := 40;
+  glbegin(gl_quads);
+   glVertex2f(x, y);
+   glVertex2f(x, y+h);
+   glVertex2f(x+w, y+h);
+   glVertex2f(x+w, y);
+  glEnd;
+
+  // Note
+  x := 260;
+  y := 5;
+  w := 200;
+  h := 40;
+  glbegin(gl_quads);
+   glVertex2f(x, y);
+   glVertex2f(x, y+h);
+   glVertex2f(x+w, y+h);
+   glVertex2f(x+w, y);
+  glEnd;
+
+  // some borders
+  x := 20;
+  y := 55;
+  w := 760;
+  h := 236;
+  glColor4f(0.9, 0.9, 0.9, 1);
+  glbegin(gl_quads);
+   glVertex2f(x, y);
+   glVertex2f(x, y+h);
+   glVertex2f(x+w, y+h);
+   glVertex2f(x+w, y);
+  glEnd;
+
+  glColor4f(0, 0, 0, 1);
+  glLineWidth(2);
+  glBegin(GL_LINE_LOOP);
+    glVertex2f(x-1, y-1);
+    glVertex2f(x+w+1, y-1);
+    glVertex2f(x+w+1, y+h+1);
+    glVertex2f(x-1, y+h+1);
+  glEnd;
+
+  x := 20;
+  y := 305;
+  w := 760;
+  h := 135;
+  glColor4f(0.9, 0.9, 0.9, 1);
+  glbegin(gl_quads);
+   glVertex2f(x, y);
+   glVertex2f(x, y+h);
+   glVertex2f(x+w, y+h);
+   glVertex2f(x+w, y);
+  glEnd;
+
+  glColor4f(0, 0, 0, 1);
+  glLineWidth(2);
+  glBegin(GL_LINE_LOOP);
+    glVertex2f(x-1, y-1);
+    glVertex2f(x+w+1, y-1);
+    glVertex2f(x+w+1, y+h+1);
+    glVertex2f(x-1, y+h+1);
+  glEnd;
+
+  x := 20;
+  y := 500;
+  w := 760;
+  h := 40;
+  glColor4f(0.9, 0.9, 0.9, 1);
+  glbegin(gl_quads);
+   glVertex2f(x, y);
+   glVertex2f(x, y+h);
+   glVertex2f(x+w, y+h);
+   glVertex2f(x+w, y);
+  glEnd;
+
+  glColor4f(0, 0, 0, 1);
+  glLineWidth(2);
+  glBegin(GL_LINE_LOOP);
+    glVertex2f(x-1, y-1);
+    glVertex2f(x+w+1, y-1);
+    glVertex2f(x+w+1, y+h+1);
+    glVertex2f(x-1, y+h+1);
+  glEnd;
+
+  glLineWidth(1);
+end;
+
+procedure TScreenEditSub.DrawInfoBar(x, y, w, h: integer);
+var
+  start, end_:        integer;
+  SongStart, SongEnd: integer;
+  ww:                 integer;
+
+  pos:                real;
+  br:                 real;
+
+  line, note:         integer;
+  numLines, numNotes: integer;
+
+begin
+  numLines := Length(Lines[0].Line);
+
+  if(numLines=0) then
+    Exit;
+
+  SongStart := Lines[0].Line[0].Note[0].Start;
+  SongEnd := Lines[0].Line[numLines-1].End_;
+  ww := SongEnd - SongStart;
+
+  glColor4f(0, 0, 0, 1);
+  glDisable(GL_BLEND);
+  glLineWidth(2);
+  glBegin(GL_LINE_LOOP);
+    glVertex2f(x-1, y-1);
+    glVertex2f(x+w+1, y-1);
+    glVertex2f(x+w+1, y+h+1);
+    glVertex2f(x-1, y+h+1);
+  glEnd;
+
+  glColor4f(0.9, 0.9, 0.9, 1);
+  glbegin(gl_quads);
+   glVertex2f(x, y);
+   glVertex2f(x, y+h);
+   glVertex2f(x+w, y+h);
+   glVertex2f(x+w, y);
+  glEnd;
+
+
+  for line := 0 to numLines - 1 do
+  begin
+    if (line = Lines[0].Current) and not (PlaySentence or PlaySentenceMidi) then
+      glColor4f(0.4, 0.4, 0, 1)
+    else
+      glColor4f(1, 0.6, 0, 1);
+
+
+    start := Lines[0].Line[line].Note[0].Start;
+    end_ := Lines[0].Line[line].Note[Lines[0].Line[line].HighNote].Start+
+      Lines[0].Line[line].Note[Lines[0].Line[line].HighNote].Length;
+
+    pos := (start - SongStart)/ww*w;
+    br := (end_-start)/ww*w;
+
+    glbegin(gl_quads);
+      glVertex2f(x+pos, y);
+      glVertex2f(x+pos, y+h);
+      glVertex2f(x+pos+br, y+h);
+      glVertex2f(x+pos+br, y);
+    glEnd;
+  end;
+
+  if(PlaySentence or PlaySentenceMidi) then
+  begin
+    glColor4f(0, 0, 0, 0.5);
+    pos := 0;
+    br := (AktBeat - SongStart)/ww*w;
+    if (br>w) then
+      br := w;
+  end else
+  begin
+    glColor4f(1, 0, 0, 1);
+    pos := (Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start - SongStart)/ww*w;
+    br := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length/ww*w;
+    if (br<1) then
+      br := 1;
+  end;
+
+  glEnable(GL_BLEND);
+  glbegin(gl_quads);
+    glVertex2f(x+pos, y);
+    glVertex2f(x+pos, y+h);
+    glVertex2f(x+pos+br, y+h);
+    glVertex2f(x+pos+br, y);
+  glEnd;
+  glDisable(GL_BLEND);
+
+  glLineWidth(1);
+end;
+
+constructor TScreenEditSub.Create;
+begin
+  inherited Create;
+  SetLength(Player, 1);
+
+  // line
+  AddText(40, 11, 1, 30, 0, 0, 0, 'Line:');
+  TextSentence := AddText(110, 11, 1, 30, 0, 0, 0, '0 / 0');
+
+
+  // Note
+  AddText(282, 11, 1, 30, 0, 0, 0, 'Note:');
+  TextNote := AddText(360, 11, 1, 30, 0, 0, 0, '0 / 0');
+
+  // file info
+  AddText(30, 65,  0, 24, 0, 0, 0, 'Title:');
+  AddText(30, 90,  0, 24, 0, 0, 0, 'Artist:');
+  AddText(30, 115, 0, 24, 0, 0, 0, 'Mp3:');
+  AddText(30, 140, 0, 24, 0, 0, 0, 'BPM:');
+  AddText(30, 165, 0, 24, 0, 0, 0, 'GAP:');
+
+  TextTitle :=  AddText(180, 65,  0, 24, 0, 0, 0, 'a');
+  TextArtist := AddText(180, 90,  0, 24, 0, 0, 0, 'b');
+  TextMp3 :=    AddText(180, 115, 0, 24, 0, 0, 0, 'c');
+  TextBPM :=    AddText(180, 140, 0, 24, 0, 0, 0, 'd');
+  TextGAP :=    AddText(180, 165, 0, 24, 0, 0, 0, 'e');
+
+  // note info
+  AddText(30, 190,  0, 24, 0, 0, 0, 'Start:');
+  AddText(30, 215,  0, 24, 0, 0, 0, 'Duration:');
+  AddText(30, 240,  0, 24, 0, 0, 0, 'Tone:');
+  AddText(30, 265,  0, 24, 0, 0, 0, 'Text:');      //AddText(500, 265,  0, 8, 0, 0, 0, 'VideoGap:');
+
+  TextNStart :=   AddText(180, 190,  0, 24, 0, 0, 0, 'a');
+  TextNLength :=  AddText(180, 215,  0, 24, 0, 0, 0, 'b');
+  TextNTon :=     AddText(180, 240,  0, 24, 0, 0, 0, 'c');
+  TextNText :=    AddText(180, 265,  0, 24, 0, 0, 0, 'd');
+
+  //TextVideoGap :=  AddText(600, 265,  0, 24, 0, 0, 0, 'e');
+
+  // debug
+  TextDebug :=  AddText(30, 550, 0, 27, 0, 0, 0, '');
+
+end;
+
+procedure TScreenEditSub.OnShow;
+var
+  FileExt: IPath;
+begin
+  inherited;
+
+  AudioPlayback.Stop;
+  PlaySentence := false;
+  PlaySentenceMidi := false;
+
+  Log.LogStatus('Initializing', 'TEditScreen.OnShow');
+  Lyric := TEditorLyrics.Create;
+
+  ResetSingTemp;
+
+  try 
+    //Check if File is XML
+    FileExt := CurrentSong.FileName.GetExtension;
+    if FileExt.ToUTF8 = '.xml' then
+      Error := not CurrentSong.LoadXMLSong()
+    else
+    begin
+      // reread header with custom tags
+      Error := not CurrentSong.Analyse(true);
+      if not Error then
+        Error := not CurrentSong.LoadSong;
+    end;
+  except
+    Error := true;
+  end;
+
+  if Error then
+  begin
+    //Error Loading Song -> Go back to Song Screen and Show some Error Message
+    FadeTo(@ScreenSong);
+    ScreenPopupError.ShowPopup (Language.Translate('ERROR_CORRUPT_SONG'));
+    Exit;
+  end
+  else
+  begin
+  {$IFDEF UseMIDIPort}
+    MidiOut := TMidiOutput.Create(nil);
+    MidiOut.Open;
+  {$ENDIF}
+    Text[TextTitle].Text :=   CurrentSong.Title;
+    Text[TextArtist].Text :=  CurrentSong.Artist;
+    Text[TextMp3].Text :=     CurrentSong.Mp3.ToUTF8;
+
+    Lines[0].Current := 0;
+    CurrentNote := 0;
+    Lines[0].Line[0].Note[0].Color := 2;
+    AudioPlayback.Open(CurrentSong.Path.Append(CurrentSong.Mp3));
+    //Set Down Music Volume for Better hearability of Midi Sounds
+    //Music.SetVolume(0.4);
+
+    Lyric.Clear;
+    Lyric.X := 400;
+    Lyric.Y := 500;
+    Lyric.Align := atCenter;
+    Lyric.Size := 42;
+    Lyric.ColR := 0;
+    Lyric.ColG := 0;
+    Lyric.ColB := 0;
+    Lyric.ColSR := Skin_FontHighlightR;
+    Lyric.ColSG := Skin_FontHighlightG;
+    Lyric.ColSB := Skin_FontHighlightB;
+    Lyric.AddLine(0);
+    Lyric.Selected := 0;
+
+    NotesH := 7;
+    NotesW := 4;
+
+  end;
+
+  //Interaction := 0;
+  TextEditMode := false;
+end;
+
+function TScreenEditSub.Draw: boolean;
+var
+  Pet:    integer;
+begin
+
+  glClearColor(1,1,1,1);
+
+  // midi music
+  if PlaySentenceMidi then
+  begin
+   {$IFDEF UseMIDIPort}
+    MidiPos := USTime.GetTime - MidiTime + MidiStart;
+
+    // stop the music
+    if (MidiPos > MidiStop) then
+    begin
+      MidiOut.PutShort(MIDI_NOTEOFF or 1,
+          Lines[0].Line[Lines[0].Current].Note[MidiLastNote].Tone + 60,
+          127);
+      PlaySentenceMidi := false;
+    end;
+  {$ENDIF}
+
+    // click
+    AktBeat := Floor(GetMidBeat(MidiPos - CurrentSong.GAP / 1000));
+    Text[TextDebug].Text := IntToStr(AktBeat);
+
+    if AktBeat <> LastClick then
+    begin
+      for Pet := 0 to Lines[0].Line[Lines[0].Current].HighNote do
+        if (Lines[0].Line[Lines[0].Current].Note[Pet].Start = AktBeat) then
+        begin
+
+          LastClick := AktBeat;
+          {$IFDEF UseMIDIPort}
+          if Pet > 0 then
+          begin
+            MidiOut.PutShort(MIDI_NOTEOFF or 1,
+                Lines[0].Line[Lines[0].Current].Note[Pet-1].Tone + 60,
+                127);
+          end;
+          MidiOut.PutShort(MIDI_NOTEON or 1,
+              Lines[0].Line[Lines[0].Current].Note[Pet].Tone + 60,
+              127);
+          MidiLastNote := Pet;
+          {$ENDIF}
+
+        end;
+    end;
+  end; // if PlaySentenceMidi
+
+  // mp3 music
+  if PlaySentence then
+  begin
+    // stop the music
+    if (AudioPlayback.Position > PlayStopTime) then
+    begin
+      AudioPlayback.Stop;
+      PlaySentence := false;
+    end;
+
+    // click
+    if (Click) and (PlaySentence) then
+    begin
+      //AktBeat := Floor(CurrentSong.BPM[0].BPM * (Music.Position - CurrentSong.GAP / 1000) / 60);
+      AktBeat := Floor(GetMidBeat(AudioPlayback.Position - CurrentSong.GAP / 1000));
+      Text[TextDebug].Text := IntToStr(AktBeat);
+      if AktBeat <> LastClick then
+      begin
+        for Pet := 0 to Lines[0].Line[Lines[0].Current].HighNote do
+          if (Lines[0].Line[Lines[0].Current].Note[Pet].Start = AktBeat) then
+          begin
+            AudioPlayback.PlaySound( SoundLib.Click );
+            LastClick := AktBeat;
+          end;
+      end;
+    end; // click
+  end; // if PlaySentence
+  
+
+  Text[TextSentence].Text := IntToStr(Lines[0].Current + 1) + ' / ' + IntToStr(Lines[0].Number);
+  Text[TextNote].Text := IntToStr(CurrentNote + 1) + ' / ' + IntToStr(Lines[0].Line[Lines[0].Current].HighNote + 1);
+
+  // Song info
+  Text[TextBPM].Text := FloatToStr(CurrentSong.BPM[0].BPM / 4);
+  Text[TextGAP].Text := FloatToStr(CurrentSong.GAP);
+
+  //Error reading Variables when no Song is loaded
+  if not Error then
+  begin
+    // Note info
+    Text[TextNStart].Text :=  IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+    Text[TextNLength].Text := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+    Text[TextNTon].Text :=    IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone) + ' ( ' + GetNoteName(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone) + ' )';
+    Text[TextNText].Text :=   Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text;
+  end;
+
+  // Text Edit Mode
+  if TextEditMode then
+    Text[TextNText].Text := Text[TextNText].Text + '|'; 
+
+  // draw static menu
+  DrawStatics;
+  DrawInfoBar(20, 460, 760, 20);
+  //inherited Draw;
+  DrawFG;
+  // draw notes
+  SingDrawNoteLines(20, 305, 780, 15);
+  //Error Drawing when no Song is loaded
+  if not Error then
+  begin
+    SingDrawBeatDelimeters(40, 305, 760, 0);
+    EditDrawLine(40, 410, 760, 0, 15);
+  end;
+
+  // draw text
+  Lyric.Draw;
+
+  Result := true;
+end;
+
+procedure TScreenEditSub.OnHide;
+begin
+  {$IFDEF UseMIDIPort}
+  MidiOut.Close;
+  MidiOut.Free;
+  {$ENDIF}
+  Lyric.Free;
+  //Music.SetVolume(1.0);
+end;
+
+function TScreenEditSub.GetNoteName(Note: integer): string;
+var
+  N1, N2: integer;
+begin
+  if (Note > 0) then
+  begin
+    N1 := Note mod 12;
+    N2 := Note div 12;
+  end
+  else
+  begin
+    N1 := (Note + (-Trunc(Note/12)+1)*12) mod 12;
+    N2 := -1;
+  end;
+
+  case N1 of
+    0: Result := 'c';
+    1: Result := 'c#';
+    2: Result := 'd';
+    3: Result := 'd#';
+    4: Result := 'e';
+    5: Result := 'f';
+    6: Result := 'f#';
+    7: Result := 'g';
+    8: Result := 'g#';
+    9: Result := 'a';
+    10: Result := 'b';
+    11: Result := 'h';
+  end;
+
+  case N2 of
+    0: Result := UpperCase(Result); //Normal Uppercase Note, 1: Normal lowercase Note
+    2: Result := Result + '''';     //One Striped
+    3: Result := Result + '''''';   //Two Striped
+    4: Result := Result + ''''''''; //etc.
+    5: Result := Result + '''''''''';
+    6: Result := Result + '''''''''''';
+    7: Result := Result + '''''''''''''';
+  end;
+end;
+
+end.
\ No newline at end of file
diff --git a/songmanagement/src/screens/UScreenLevel.pas b/songmanagement/src/screens/UScreenLevel.pas
new file mode 100644
index 00000000..1ead9773
--- /dev/null
+++ b/songmanagement/src/screens/UScreenLevel.pas
@@ -0,0 +1,139 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenLevel;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  UDisplay,
+  UMusic,
+  UFiles,
+  SysUtils,
+  UThemes;
+
+type
+  TScreenLevel = class(TMenu)
+    public
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UIni,
+  USong,
+  UTexture,
+  UUnicodeUtils;
+
+function TScreenLevel.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          AudioPlayback.PlaySound(SoundLib.Back);
+
+          if Ini.OnSongClick = sSelectPlayer then
+            FadeTo(@ScreenMain)
+          else
+            FadeTo(@ScreenName);
+        end;
+
+      SDLK_RETURN:
+        begin
+          Ini.Difficulty := Interaction;
+          Ini.SaveLevel;
+          AudioPlayback.PlaySound(SoundLib.Start);
+          //Set Standard Mode
+          ScreenSong.Mode := smNormal;
+          FadeTo(@ScreenSong);
+        end;
+
+      // Up and Down could be done at the same time,
+      // but I don't want to declare variables inside
+      // functions like this one, called so many times
+      SDLK_DOWN:    InteractNext;
+      SDLK_UP:      InteractPrev;
+      SDLK_RIGHT:   InteractNext;
+      SDLK_LEFT:    InteractPrev;
+    end;
+  end;
+end;
+
+constructor TScreenLevel.Create;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.Level);
+
+  AddButton(Theme.Level.ButtonEasy);
+  AddButton(Theme.Level.ButtonMedium);
+  AddButton(Theme.Level.ButtonHard);
+
+  Interaction := 0;
+end;
+
+procedure TScreenLevel.OnShow;
+begin
+  inherited;
+
+  Interaction := Ini.Difficulty;
+end;
+
+procedure TScreenLevel.SetAnimationProgress(Progress: real);
+begin
+  Button[0].Texture.ScaleW := Progress;
+  Button[1].Texture.ScaleW := Progress;
+  Button[2].Texture.ScaleW := Progress;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenLoading.pas b/songmanagement/src/screens/UScreenLoading.pas
new file mode 100644
index 00000000..e368f181
--- /dev/null
+++ b/songmanagement/src/screens/UScreenLoading.pas
@@ -0,0 +1,78 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenLoading;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  SysUtils,
+  UThemes,
+  gl;
+
+type
+  TScreenLoading = class(TMenu)
+    public
+      Fadeout: boolean;
+
+      constructor Create; override;
+      procedure OnShow; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UTime;
+
+function TScreenLoading.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+end;
+
+constructor TScreenLoading.Create;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.Loading);
+
+  Fadeout := false;
+end;
+
+procedure TScreenLoading.OnShow;
+begin
+  inherited;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenMain.pas b/songmanagement/src/screens/UScreenMain.pas
new file mode 100644
index 00000000..aa313cf6
--- /dev/null
+++ b/songmanagement/src/screens/UScreenMain.pas
@@ -0,0 +1,296 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenMain;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  UDisplay,
+  UMusic,
+  UFiles,
+  SysUtils,
+  UThemes;
+
+type
+  TScreenMain = class(TMenu)
+  private
+    { ticks when the user interacted, used to start credits
+      after a period of time w/o user interaction }
+    UserInteractionTicks: cardinal;
+  public
+    TextDescription:     integer;
+    TextDescriptionLong: integer;
+
+    constructor Create; override;
+    function ParseInput(PressedKey: Cardinal; CharCode: UCS4Char;
+      PressedDown: boolean): boolean; override;
+    function ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; override;
+    procedure OnShow; override;
+    procedure SetInteraction(Num: integer); override;
+    procedure SetAnimationProgress(Progress: real); override;
+    function Draw: boolean; override;
+  end;
+
+const
+  { start credits after 60 seconds w/o interaction }
+  TicksUntilCredits = 60 * 1000;
+
+implementation
+
+uses
+  UGraphic,
+  UNote,
+  UIni,
+  UTexture,
+  USongs,
+  Textgl,
+  ULanguage,
+  UParty,
+  UScreenCredits,
+  USkins,
+  UUnicodeUtils;
+
+function TScreenMain.ParseInput(PressedKey: Cardinal; CharCode: UCS4Char;
+  PressedDown: boolean): boolean;
+var
+  SDL_ModState: word;
+begin
+  Result := true;
+
+  { reset user interaction timer }
+  UserInteractionTicks := SDL_GetTicks;
+
+  SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT +
+    KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT + KMOD_RALT);
+
+  if (PressedDown) then
+  begin // Key Down
+        // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'): begin
+        Result := false;
+        Exit;
+      end;
+      Ord('C'): begin
+        if (SDL_ModState = KMOD_LALT) then
+        begin
+          FadeTo(@ScreenCredits, SoundLib.Start);
+          Exit;
+        end;
+      end;
+      Ord('M'): begin
+        if (Ini.Players >= 1) and (Party.ModesAvailable) then
+        begin
+          FadeTo(@ScreenPartyOptions, SoundLib.Start);
+          Exit;
+        end;
+      end;
+
+      Ord('S'): begin
+        FadeTo(@ScreenStatMain, SoundLib.Start);
+        Exit;
+      end;
+
+      Ord('E'): begin
+        FadeTo(@ScreenEdit, SoundLib.Start);
+        Exit;
+      end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE:
+      begin
+        Result := false;
+      end;
+
+      SDLK_RETURN:
+      begin
+        //Solo
+        if (Interaction = 0) then
+        begin
+          if (Songs.SongList.Count >= 1) then
+          begin
+            if (Ini.Players >= 0) and (Ini.Players <= 3) then
+              PlayersPlay := Ini.Players + 1;
+            if (Ini.Players = 4) then
+              PlayersPlay := 6;
+
+            if Ini.OnSongClick = sSelectPlayer then
+              FadeTo(@ScreenLevel)
+            else
+            begin
+              ScreenName.Goto_SingScreen := false;
+              FadeTo(@ScreenName, SoundLib.Start);
+            end;
+          end
+          else //show error message
+            ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_SONGS'));
+        end;
+
+        //Multi
+        if Interaction = 1 then
+        begin
+          if (Songs.SongList.Count >= 1) then
+          begin
+            FadeTo(@ScreenPartyOptions, SoundLib.Start);
+          end
+          else //show error message, No Songs Loaded
+            ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_SONGS'));
+        end;
+
+        //Stats
+        if Interaction = 2 then
+        begin
+          FadeTo(@ScreenStatMain, SoundLib.Start);
+        end;
+
+        //Editor
+        if Interaction = 3 then
+        begin
+          {$IFDEF UseMIDIPort}
+          FadeTo(@ScreenEdit, SoundLib.Start);
+          {$ELSE}
+          ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_EDITOR'));
+          {$ENDIF}
+        end;
+
+        //Options
+        if Interaction = 4 then
+        begin
+          FadeTo(@ScreenOptions, SoundLib.Start);
+        end;
+
+        //Exit
+        if Interaction = 5 then
+        begin
+          Result := false;
+        end;
+      end;
+      {**
+       * Up and Down could be done at the same time,
+       * but I don't want to declare variables inside
+       * functions like this one, called so many times
+       *}
+      SDLK_DOWN: InteractInc;
+      SDLK_UP: InteractDec;
+      SDLK_RIGHT: InteractNext;
+      SDLK_LEFT: InteractPrev;
+    end;
+  end
+  else // Key Up
+    case PressedKey of
+      SDLK_RETURN:
+      begin
+      end;
+    end;
+end;
+
+function TScreenMain.ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean;
+begin
+  // default mouse behaviour
+  Result := inherited ParseMouse(MouseButton, BtnDown, X, Y);
+
+  { reset user interaction timer }
+  UserInteractionTicks := SDL_GetTicks;
+end;
+
+constructor TScreenMain.Create;
+begin
+  inherited Create;
+{**
+ * Attention ^^:
+ * New Creation Order needed because of LoadFromTheme
+ * and Button Collections.
+ * At First Custom Texts and Statics
+ * Then LoadFromTheme
+ * after LoadFromTheme the Buttons and Selects
+ *}
+  TextDescription     := AddText(Theme.Main.TextDescription);
+  TextDescriptionLong := AddText(Theme.Main.TextDescriptionLong);
+
+  LoadFromTheme(Theme.Main);
+
+  AddButton(Theme.Main.ButtonSolo);
+  AddButton(Theme.Main.ButtonMulti);
+  AddButton(Theme.Main.ButtonStat);
+  AddButton(Theme.Main.ButtonEditor);
+  AddButton(Theme.Main.ButtonOptions);
+  AddButton(Theme.Main.ButtonExit);
+
+  Interaction := 0;
+end;
+
+procedure TScreenMain.OnShow;
+begin
+  inherited;
+
+  SoundLib.StartBgMusic;
+
+ {**
+  * Clean up TPartyGame here
+  * at the moment there is no better place for this
+  *}
+  Party.Clear;
+
+  { reset user interaction timer }
+  UserInteractionTicks := SDL_GetTicks;
+end;
+
+function TScreenMain.Draw: boolean;
+begin
+  Result := inherited Draw;
+
+  { start credits after a period w/o user interaction }
+  if (UserInteractionTicks + TicksUntilCredits < SDL_GetTicks) then
+  begin
+    FadeTo(@ScreenCredits, SoundLib.Start);
+  end;  
+end;
+
+procedure TScreenMain.SetInteraction(Num: integer);
+begin
+  inherited SetInteraction(Num);
+  Text[TextDescription].Text     := Theme.Main.Description[Interaction];
+  Text[TextDescriptionLong].Text := Theme.Main.DescriptionLong[Interaction];
+end;
+
+procedure TScreenMain.SetAnimationProgress(Progress: real);
+begin
+  Statics[0].Texture.ScaleW := Progress;
+  Statics[0].Texture.ScaleH := Progress;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenName.pas b/songmanagement/src/screens/UScreenName.pas
new file mode 100644
index 00000000..42af50d7
--- /dev/null
+++ b/songmanagement/src/screens/UScreenName.pas
@@ -0,0 +1,284 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenName;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils, 
+  SDL,
+  UDisplay,
+  UFiles,
+  UMenu,
+  UMusic,
+  UThemes;
+
+type
+  TScreenName = class(TMenu)
+    public
+      Goto_SingScreen: boolean; //If true then next Screen in SingScreen
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+implementation
+
+uses
+  UCommon,
+  UGraphic, 
+  UIni,
+  UNote,
+  UTexture,
+  UUnicodeUtils;
+
+
+function TScreenName.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+  I: integer;
+  SDL_ModState: word;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+
+    SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT
+    + KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT  + KMOD_RALT);
+
+    // check normal keys
+    if (IsPrintableChar(CharCode)) then
+    begin
+      Button[Interaction].Text[0].Text := Button[Interaction].Text[0].Text +
+                                          UCS4ToUTF8String(CharCode);
+      Exit;
+    end;
+
+    // check special keys
+    case PressedKey of
+      // Templates for Names Mod
+      SDLK_F1:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[0] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[0];
+         end;
+      SDLK_F2:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[1] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[1];
+         end;
+      SDLK_F3:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[2] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[2];
+         end;
+      SDLK_F4:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[3] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[3];
+         end;
+      SDLK_F5:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[4] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[4];
+         end;
+      SDLK_F6:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[5] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[5];
+         end;
+      SDLK_F7:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[6] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[6];
+         end;
+      SDLK_F8:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[7] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[7];
+         end;
+      SDLK_F9:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[8] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[8];
+         end;
+      SDLK_F10:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[9] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[9];
+         end;
+      SDLK_F11:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[10] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[10];
+         end;
+      SDLK_F12:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[11] := Button[Interaction].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interaction].Text[0].Text := Ini.NameTemplate[11];
+         end;
+
+      SDLK_BACKSPACE:
+        begin
+          Button[Interaction].Text[0].DeleteLastLetter();
+        end;
+
+      SDLK_ESCAPE :
+        begin
+          Ini.SaveNames;
+          AudioPlayback.PlaySound(SoundLib.Back);
+          if GoTo_SingScreen then
+            FadeTo(@ScreenSong)
+          else
+            FadeTo(@ScreenMain);
+        end;
+
+      SDLK_RETURN:
+        begin
+          for I := 1 to 6 do
+            Ini.Name[I-1] := Button[I-1].Text[0].Text;
+          Ini.SaveNames;
+          AudioPlayback.PlaySound(SoundLib.Start);
+
+          if GoTo_SingScreen then
+            FadeTo(@ScreenSing)
+          else
+            FadeTo(@ScreenLevel);
+
+          GoTo_SingScreen := false;
+        end;
+
+      // Up and Down could be done at the same time,
+      // but I don't want to declare variables inside
+      // functions like this one, called so many times
+      SDLK_DOWN:    InteractNext;
+      SDLK_UP:      InteractPrev;
+      SDLK_RIGHT:   InteractNext;
+      SDLK_LEFT:    InteractPrev;
+    end;
+  end;
+end;
+
+constructor TScreenName.Create;
+var
+  I:    integer;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.Name);
+
+  for I := 1 to 6 do
+    AddButton(Theme.Name.ButtonPlayer[I]);
+
+  Interaction := 0;
+end;
+
+procedure TScreenName.OnShow;
+var
+  I:    integer;
+begin
+  inherited;
+  
+  for I := 1 to 6 do
+    Button[I-1].Text[0].Text := Ini.Name[I-1];
+
+  for I := 1 to PlayersPlay do
+  begin
+    Button[I-1].Visible := true;
+    Button[I-1].Selectable := true;
+  end;
+
+  for I := PlayersPlay+1 to 6 do
+  begin
+    Button[I-1].Visible := false;
+    Button[I-1].Selectable := false;
+  end;
+
+end;
+
+procedure TScreenName.SetAnimationProgress(Progress: real);
+var
+  I:    integer;
+begin
+  for I := 1 to 6 do
+    Button[I-1].Texture.ScaleW := Progress;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenOpen.pas b/songmanagement/src/screens/UScreenOpen.pas
new file mode 100644
index 00000000..70b883c4
--- /dev/null
+++ b/songmanagement/src/screens/UScreenOpen.pas
@@ -0,0 +1,231 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenOpen;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  Math,
+  SysUtils,
+  gl,
+  SDL,
+  UPath,
+  UMenu,
+  UMusic,
+  UFiles,
+  UTime,
+  USongs,
+  UIni,
+  ULog,
+  UTexture,
+  UMenuText,
+  ULyrics,
+  UThemes;
+
+type
+  TScreenOpen = class(TMenu)
+    private
+      //fTextF:      array[0..1] of integer;
+      fTextN:      integer; // text-box ID of filename
+      fFilename:   IPath;
+      fBackScreen: PMenu;
+
+      procedure AddBox(X, Y, W, H: real);
+    public
+      constructor Create; override;
+      procedure OnShow; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+
+      {**
+       * Set by the caller to provide a default filename.
+       * Set to the selected filename after calling this screen or to PATH_NONE
+       * if the screen was aborted.
+       * TODO: maybe pass this value with a callback OnValueChanged()
+       *}
+      property Filename: IPath READ fFilename WRITE fFilename;
+      {** The screen that is shown after this screen is closed (set by the caller) *}
+      property BackScreen: PMenu READ fBackScreen WRITE fBackScreen;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UDraw,
+  UMain,
+  UScreenEditConvert,
+  USkins,
+  UUnicodeUtils;
+
+function TScreenOpen.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+
+  if (PressedDown) then  // Key Down
+  begin
+    // check normal keys
+    if (IsPrintableChar(CharCode)) then
+    begin
+      if (Interaction = 0) then
+      begin
+        Text[fTextN].Text := Text[fTextN].Text + UCS4ToUTF8String(CharCode);
+        Exit;
+      end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_BACKSPACE: // del
+        begin
+          if Interaction = 0 then
+          begin
+            Text[fTextN].DeleteLastLetter;
+          end;
+        end;
+
+      SDLK_ESCAPE:
+        begin
+          //Empty Filename and go to last Screen
+          fFileName := PATH_NONE;
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(fBackScreen);
+        end;
+
+      SDLK_RETURN:
+        begin
+          if (Interaction = 2) then
+          begin
+            //Update Filename and go to last Screen
+            fFileName := Path(Text[fTextN].Text);
+            AudioPlayback.PlaySound(SoundLib.Back);
+            FadeTo(fBackScreen);
+          end
+          else if (Interaction = 1) then
+          begin
+            //Empty Filename and go to last Screen
+            fFileName := PATH_NONE;
+            AudioPlayback.PlaySound(SoundLib.Back);
+            FadeTo(fBackScreen);
+          end;
+        end;
+
+      SDLK_LEFT:
+        begin
+          InteractPrev;
+        end;
+
+      SDLK_RIGHT:
+        begin
+          InteractNext;
+        end;
+
+      SDLK_DOWN:
+        begin
+        end;
+
+      SDLK_UP:
+        begin
+        end;
+    end;
+  end;
+end;
+
+procedure TScreenOpen.AddBox(X, Y, W, H: real);
+begin
+  AddStatic(X,   Y,   W,   H,   0, 0, 0, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED);
+  AddStatic(X+2, Y+2, W-4, H-4, 1, 1, 1, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED);
+end;
+
+constructor TScreenOpen.Create;
+begin
+  inherited Create;
+
+  fFilename := PATH_NONE;
+
+  // line
+  {
+  AddStatic(20, 10, 80, 30, 0, 0, 0, 'MainBar', 'JPG', TEXTURE_TYPE_COLORIZED);
+  AddText(35, 17, 1, 18, 1, 1, 1, 'line');
+  TextSentence := AddText(120, 14, 1, 24, 0, 0, 0, '0 / 0');
+  }
+
+  // file list
+  //AddBox(400, 100, 350, 450);
+
+  //TextF[0] :=  AddText(430, 155,  0, 24, 0, 0, 0, 'a');
+  //TextF[1] :=  AddText(430, 180,  0, 24, 0, 0, 0, 'a');
+
+  // file name
+  AddBox(20, 540, 500, 40);
+  fTextN := AddText(50, 548, 0, 24, 0, 0, 0, fFileName.ToUTF8);
+  AddInteraction(iText, fTextN);
+
+  // buttons
+  {AddButton(540, 540, 100, 40, Skin.SkinPath + Skin.ButtonF);
+  AddButtonText(10, 5, 0, 0, 0, 'Cancel');
+
+  AddButton(670, 540, 100, 40, Skin.SkinPath + Skin.ButtonF);
+  AddButtonText(30, 5, 0, 0, 0, 'OK');}
+  // buttons
+  AddButton(540, 540, 100, 40, Skin.GetTextureFileName('ButtonF'));
+  AddButtonText(10, 5, 0, 0, 0, 'Cancel');
+
+  AddButton(670, 540, 100, 40, Skin.GetTextureFileName('ButtonF'));
+  AddButtonText(30, 5, 0, 0, 0, 'OK');
+
+end;
+
+procedure TScreenOpen.OnShow;
+begin
+  inherited;
+
+  Interaction := 0;
+  Text[fTextN].Text := fFilename.ToUTF8();
+end;
+
+(*
+function TScreenEditSub.Draw: boolean;
+var
+  Min:     integer;
+  Sec:     integer;
+  AktBeat: integer;
+begin
+
+end;
+
+procedure TScreenEditSub.Finish;
+begin
+//
+end;
+*)
+
+end.
diff --git a/songmanagement/src/screens/UScreenOptions.pas b/songmanagement/src/screens/UScreenOptions.pas
new file mode 100644
index 00000000..30e3e9c4
--- /dev/null
+++ b/songmanagement/src/screens/UScreenOptions.pas
@@ -0,0 +1,234 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenOptions;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  SysUtils,
+  UMenu,
+  UDisplay,
+  UMusic,
+  UFiles,
+  UIni,
+  UThemes;
+
+type
+  TScreenOptions = class(TMenu)
+    public
+      TextDescription:    integer;
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure InteractNext; override;
+      procedure InteractPrev; override;
+      procedure InteractNextRow; override;
+      procedure InteractPrevRow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UUnicodeUtils;
+
+function TScreenOptions.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          Ini.Save;
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenMain);
+        end;
+      SDLK_RETURN:
+        begin
+          if SelInteraction = 0 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Start);
+            FadeTo(@ScreenOptionsGame);
+          end;
+
+          if SelInteraction = 1 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Start);
+            FadeTo(@ScreenOptionsGraphics);
+          end;
+
+          if SelInteraction = 2 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Start);
+            FadeTo(@ScreenOptionsSound);
+          end;
+
+          if SelInteraction = 3 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Start);
+            FadeTo(@ScreenOptionsLyrics);
+          end;
+
+          if SelInteraction = 4 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Start);
+            FadeTo(@ScreenOptionsThemes);
+          end;
+
+          if SelInteraction = 5 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Start);
+            FadeTo(@ScreenOptionsRecord);
+          end;
+
+          if SelInteraction = 6 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Start);
+            FadeTo(@ScreenOptionsAdvanced);
+          end;
+
+          if SelInteraction = 7 then
+          begin
+            Ini.Save;
+            AudioPlayback.PlaySound(SoundLib.Back);
+            FadeTo(@ScreenMain);
+          end;
+        end;
+      SDLK_DOWN:    InteractNextRow;
+      SDLK_UP:      InteractPrevRow;
+      SDLK_RIGHT:   InteractNext;
+      SDLK_LEFT:    InteractPrev;
+    end;
+  end;
+end;
+
+constructor TScreenOptions.Create;
+begin
+  inherited Create;
+
+  TextDescription := AddText(Theme.Options.TextDescription);
+
+  LoadFromTheme(Theme.Options);
+
+  AddButton(Theme.Options.ButtonGame);
+  if (Length(Button[0].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[0]);
+
+  AddButton(Theme.Options.ButtonGraphics);
+  if (Length(Button[1].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[1]);
+
+  AddButton(Theme.Options.ButtonSound);
+  if (Length(Button[2].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[2]);
+
+  AddButton(Theme.Options.ButtonLyrics);
+  if (Length(Button[3].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[3]);
+
+  AddButton(Theme.Options.ButtonThemes);
+  if (Length(Button[4].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[4]);
+
+  AddButton(Theme.Options.ButtonRecord);
+  if (Length(Button[5].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[5]);
+
+  AddButton(Theme.Options.ButtonAdvanced);
+  if (Length(Button[6].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[6]);
+
+  AddButton(Theme.Options.ButtonExit);
+  if (Length(Button[7].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[7]);
+
+  Interaction := 0;
+end;
+
+procedure TScreenOptions.OnShow;
+begin
+  inherited;
+  // continue possibly stopped bg-music (stopped in record options)
+  SoundLib.StartBgMusic;
+end;
+
+procedure TScreenOptions.InteractNext;
+begin
+  inherited InteractNext;
+  Text[TextDescription].Text := Theme.Options.Description[Interaction];
+end;
+
+procedure TScreenOptions.InteractPrev;
+begin
+  inherited InteractPrev;
+  Text[TextDescription].Text := Theme.Options.Description[Interaction];
+end;
+
+procedure TScreenOptions.InteractNextRow;
+begin
+  inherited InteractNextRow;
+  Text[TextDescription].Text := Theme.Options.Description[Interaction];
+end;
+
+procedure TScreenOptions.InteractPrevRow;
+begin
+  inherited InteractPrevRow;
+  Text[TextDescription].Text := Theme.Options.Description[Interaction];
+end;
+
+procedure TScreenOptions.SetAnimationProgress(Progress: real);
+begin
+  Button[0].Texture.ScaleW := Progress;
+  Button[1].Texture.ScaleW := Progress;
+  Button[2].Texture.ScaleW := Progress;
+  Button[3].Texture.ScaleW := Progress;
+  Button[4].Texture.ScaleW := Progress;
+  Button[5].Texture.ScaleW := Progress;
+  Button[6].Texture.ScaleW := Progress;
+  Button[7].Texture.ScaleW := Progress;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenOptionsAdvanced.pas b/songmanagement/src/screens/UScreenOptionsAdvanced.pas
new file mode 100644
index 00000000..dd727dd8
--- /dev/null
+++ b/songmanagement/src/screens/UScreenOptionsAdvanced.pas
@@ -0,0 +1,168 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenOptionsAdvanced;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  UMenu,
+  UDisplay,
+  UMusic,
+  UFiles,
+  UIni,
+  UThemes;
+
+type
+  TScreenOptionsAdvanced = class(TMenu)
+    public
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UUnicodeUtils,
+  SysUtils;
+
+function TScreenOptionsAdvanced.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          Ini.Save;
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenOptions);
+        end;
+      SDLK_RETURN:
+        begin
+          //SelectLoadAnimation Hidden because it is useless atm
+          //if SelInteraction = 7 then begin
+          if SelInteraction = 6 then
+          begin
+            Ini.Save;
+            AudioPlayback.PlaySound(SoundLib.Back);
+            FadeTo(@ScreenOptions);
+          end;
+        end;
+      SDLK_DOWN:
+        InteractNext;
+      SDLK_UP :
+        InteractPrev;
+      SDLK_RIGHT:
+        begin
+          //SelectLoadAnimation Hidden because it is useless atm
+          //if (SelInteraction >= 0) and (SelInteraction <= 6) then begin
+          if (SelInteraction >= 0) and (SelInteraction <= 5) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractInc;
+          end;
+        end;
+      SDLK_LEFT:
+        begin
+          //SelectLoadAnimation Hidden because it is useless atm
+          //if (SelInteraction >= 0) and (SelInteraction <= 6) then begin
+          if (SelInteraction >= 0) and (SelInteraction <= 5) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractDec;
+          end;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenOptionsAdvanced.Create;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.OptionsAdvanced);
+
+  //SelectLoadAnimation Hidden because it is useless atm
+  //AddSelect(Theme.OptionsAdvanced.SelectLoadAnimation, Ini.LoadAnimation, ILoadAnimationTranslated);
+  Theme.OptionsAdvanced.SelectScreenFade.showArrows := true;
+  Theme.OptionsAdvanced.SelectScreenFade.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsAdvanced.SelectScreenFade, Ini.ScreenFade, IScreenFadeTranslated);
+
+  Theme.OptionsAdvanced.SelectEffectSing.showArrows := true;
+  Theme.OptionsAdvanced.SelectEffectSing.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsAdvanced.SelectEffectSing, Ini.EffectSing, IEffectSingTranslated);
+
+  Theme.OptionsAdvanced.SelectLineBonus.showArrows := true;
+  Theme.OptionsAdvanced.SelectLineBonus.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsAdvanced.SelectLineBonus, Ini.LineBonus, ILineBonusTranslated);
+
+  Theme.OptionsAdvanced.SelectOnSongClick.showArrows := true;
+  Theme.OptionsAdvanced.SelectOnSongClick.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsAdvanced.SelectOnSongClick, Ini.OnSongClick, IOnSongClickTranslated);
+
+  Theme.OptionsAdvanced.SelectAskbeforeDel.showArrows := true;
+  Theme.OptionsAdvanced.SelectAskbeforeDel.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsAdvanced.SelectAskbeforeDel, Ini.AskBeforeDel, IAskbeforeDelTranslated);
+
+  Theme.OptionsAdvanced.SelectPartyPopup.showArrows := true;
+  Theme.OptionsAdvanced.SelectPartyPopup.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsAdvanced.SelectPartyPopup, Ini.PartyPopup, IPartyPopupTranslated);
+
+  AddButton(Theme.OptionsAdvanced.ButtonExit);
+  if (Length(Button[0].Text)=0) then
+    AddButtonText(20, 5, Theme.Options.Description[7]);
+
+  Interaction := 0;
+end;
+
+procedure TScreenOptionsAdvanced.OnShow;
+begin
+  inherited;
+
+  Interaction := 0;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenOptionsGame.pas b/songmanagement/src/screens/UScreenOptionsGame.pas
new file mode 100644
index 00000000..39de61e4
--- /dev/null
+++ b/songmanagement/src/screens/UScreenOptionsGame.pas
@@ -0,0 +1,175 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenOptionsGame;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  UMenu,
+  UDisplay,
+  UMusic,
+  UFiles,
+  UIni,
+  UThemes,
+  USongs;
+
+type
+  TScreenOptionsGame = class(TMenu)
+    public
+      old_Tabs, old_Sorting: integer;
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure RefreshSongs;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UUnicodeUtils,
+  SysUtils;
+
+function TScreenOptionsGame.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if PressedDown then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          AudioPlayback.PlaySound(SoundLib.Back);
+          RefreshSongs;
+          FadeTo(@ScreenOptions);
+        end;
+      SDLK_RETURN:
+        begin
+          if SelInteraction = 6 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Back);
+            RefreshSongs;
+            FadeTo(@ScreenOptions);
+          end;
+        end;
+      SDLK_DOWN:
+        InteractNext;
+      SDLK_UP :
+        InteractPrev;
+      SDLK_RIGHT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction <= 5) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractInc;
+          end;
+        end;
+      SDLK_LEFT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction <= 5) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractDec;
+          end;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenOptionsGame.Create;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.OptionsGame);
+
+  //Refresh Songs Patch
+  old_Sorting := Ini.Sorting;
+  old_Tabs    := Ini.Tabs;
+
+  Theme.OptionsGame.SelectPlayers.showArrows  := true;
+  Theme.OptionsGame.SelectPlayers.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGame.SelectPlayers,    Ini.Players,    IPlayers);
+
+  Theme.OptionsGame.SelectDifficulty.showArrows  := true;
+  Theme.OptionsGame.SelectDifficulty.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGame.SelectDifficulty, Ini.Difficulty, IDifficultyTranslated);
+
+  Theme.OptionsGame.SelectLanguage.showArrows  := true;
+  Theme.OptionsGame.SelectLanguage.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGame.SelectLanguage,   Ini.Language,   ILanguageTranslated);
+
+  Theme.OptionsGame.SelectTabs.showArrows  := true;
+  Theme.OptionsGame.SelectTabs.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGame.SelectTabs,       Ini.Tabs,       ITabsTranslated);
+
+  Theme.OptionsGame.SelectSorting.showArrows  := true;
+  Theme.OptionsGame.SelectSorting.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGame.SelectSorting,    Ini.Sorting,    ISortingTranslated);
+
+  Theme.OptionsGame.SelectDebug.showArrows  := true;
+  Theme.OptionsGame.SelectDebug.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGame.SelectDebug,      Ini.Debug,      IDebugTranslated);
+
+
+
+  AddButton(Theme.OptionsGame.ButtonExit);
+  if (Length(Button[0].Text) = 0) then
+    AddButtonText(20, 5, Theme.Options.Description[7]);
+
+end;
+
+//Refresh Songs Patch
+procedure TScreenOptionsGame.RefreshSongs;
+begin
+  if (ini.Sorting <> old_Sorting) or (ini.Tabs <> old_Tabs) then
+    ScreenSong.Refresh;
+end;
+
+procedure TScreenOptionsGame.OnShow;
+begin
+  inherited;
+
+//  Interaction := 0;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenOptionsGraphics.pas b/songmanagement/src/screens/UScreenOptionsGraphics.pas
new file mode 100644
index 00000000..e2aacccd
--- /dev/null
+++ b/songmanagement/src/screens/UScreenOptionsGraphics.pas
@@ -0,0 +1,164 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenOptionsGraphics;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  UDisplay,
+  UMusic,
+  UFiles,
+  UIni,
+  UThemes;
+
+type
+  TScreenOptionsGraphics = class(TMenu)
+    public
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UUnicodeUtils,
+  SysUtils;
+
+function TScreenOptionsGraphics.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          Ini.Save;
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenOptions);
+        end;
+      SDLK_RETURN:
+        begin
+          if SelInteraction = 6 then
+          begin
+            Ini.Save;
+            AudioPlayback.PlaySound(SoundLib.Back);
+            // FIXME: changing the video mode does not work this way in windows
+            // and MacOSX as all textures will be invalidated through this.
+            // See the ALT+TAB code too.
+            {$IF Defined(Linux) or Defined(FreeBSD)}
+            Reinitialize3D();
+            {$IFEND}
+            FadeTo(@ScreenOptions);
+          end;
+        end;
+      SDLK_DOWN:
+        InteractNext;
+      SDLK_UP :
+        InteractPrev;
+      SDLK_RIGHT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction < 6) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractInc;
+          end;
+        end;
+      SDLK_LEFT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction < 6) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractDec;
+          end;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenOptionsGraphics.Create;
+begin
+  inherited Create;
+  LoadFromTheme(Theme.OptionsGraphics);
+
+  Theme.OptionsGraphics.SelectResolution.showArrows := true;
+  Theme.OptionsGraphics.SelectResolution.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGraphics.SelectResolution,   Ini.Resolution, IResolution);
+
+  Theme.OptionsGraphics.SelectFullscreen.showArrows := true;
+  Theme.OptionsGraphics.SelectFullscreen.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGraphics.SelectFullscreen,   Ini.Fullscreen, IFullScreenTranslated);
+
+  Theme.OptionsGraphics.SelectDepth.showArrows := true;
+  Theme.OptionsGraphics.SelectDepth.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGraphics.SelectDepth,        Ini.Depth, IDepth);
+
+  Theme.OptionsGraphics.SelectVisualizer.showArrows := true;
+  Theme.OptionsGraphics.SelectVisualizer.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGraphics.SelectVisualizer,   Ini.VisualizerOption, IVisualizerTranslated);
+
+  Theme.OptionsGraphics.SelectOscilloscope.showArrows := true;
+  Theme.OptionsGraphics.SelectOscilloscope.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGraphics.SelectOscilloscope, Ini.Oscilloscope, IOscilloscopeTranslated);
+
+  Theme.OptionsGraphics.SelectMovieSize.showArrows := true;
+  Theme.OptionsGraphics.SelectMovieSize.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsGraphics.SelectMovieSize,    Ini.MovieSize, IMovieSizeTranslated);
+
+  AddButton(Theme.OptionsGraphics.ButtonExit);
+  if (Length(Button[0].Text)=0) then
+    AddButtonText(20, 5, Theme.Options.Description[7]);
+
+end;
+
+procedure TScreenOptionsGraphics.OnShow;
+begin
+  inherited;
+
+  Interaction := 0;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenOptionsLyrics.pas b/songmanagement/src/screens/UScreenOptionsLyrics.pas
new file mode 100644
index 00000000..468082de
--- /dev/null
+++ b/songmanagement/src/screens/UScreenOptionsLyrics.pas
@@ -0,0 +1,147 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenOptionsLyrics;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  UDisplay,
+  UMusic,
+  UFiles,
+  UIni,
+  UThemes;
+
+type
+  TScreenOptionsLyrics = class(TMenu)
+    public
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UUnicodeUtils,
+  SysUtils;
+
+function TScreenOptionsLyrics.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          Ini.Save;
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenOptions);
+        end;
+      SDLK_RETURN:
+        begin
+          if SelInteraction = 3 then
+          begin
+            Ini.Save;
+            AudioPlayback.PlaySound(SoundLib.Back);
+            FadeTo(@ScreenOptions);
+          end;
+        end;
+      SDLK_DOWN:
+        InteractNext;
+      SDLK_UP :
+        InteractPrev;
+      SDLK_RIGHT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction <= 3) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractInc;
+          end;
+        end;
+      SDLK_LEFT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction <= 3) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractDec;
+          end;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenOptionsLyrics.Create;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.OptionsLyrics);
+
+  Theme.OptionsLyrics.SelectLyricsFont.showArrows := true;
+  Theme.OptionsLyrics.SelectLyricsFont.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsLyrics.SelectLyricsFont, Ini.LyricsFont, ILyricsFontTranslated);
+
+  Theme.OptionsLyrics.SelectLyricsEffect.showArrows := true;
+  Theme.OptionsLyrics.SelectLyricsEffect.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsLyrics.SelectLyricsEffect, Ini.LyricsEffect, ILyricsEffectTranslated);
+
+  Theme.OptionsLyrics.SelectNoteLines.showArrows := true;
+  Theme.OptionsLyrics.SelectNoteLines.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsLyrics.SelectNoteLines, Ini.NoteLines, INoteLinesTranslated);
+
+  AddButton(Theme.OptionsLyrics.ButtonExit);
+  if (Length(Button[0].Text)=0) then
+    AddButtonText(20, 5, Theme.Options.Description[7]);
+
+end;
+
+procedure TScreenOptionsLyrics.OnShow;
+begin
+  inherited;
+
+  Interaction := 0;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenOptionsRecord.pas b/songmanagement/src/screens/UScreenOptionsRecord.pas
new file mode 100644
index 00000000..7af598e5
--- /dev/null
+++ b/songmanagement/src/screens/UScreenOptionsRecord.pas
@@ -0,0 +1,836 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenOptionsRecord;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UThemes,
+  UMusic,
+  URecord,
+  UMenu;
+
+type
+  TDrawState = record
+    ChannelIndex: integer;
+    R, G, B: real;    // mapped player color (normal)
+    RD, GD, BD: real; // mapped player color (dark)
+  end;
+
+  TPeakInfo = record
+    Volume: single;
+    Time: cardinal;
+  end;
+
+  TScreenOptionsRecord = class(TMenu)
+    private
+      // max. count of input-channels determined for all devices
+      MaxChannelCount: integer;
+
+      // current input device
+      CurrentDeviceIndex: integer;
+      PreviewDeviceIndex: integer;
+
+      // string arrays for select-slide options
+      InputSourceNames: array of UTF8String;
+      InputDeviceNames: array of UTF8String;
+
+      // dynamic generated themes for channel select-sliders
+      SelectSlideChannelTheme: array of TThemeSelectSlide;
+
+      // indices for widget-updates
+      SelectInputSourceID:   integer;
+      SelectSlideChannelID: array of integer;
+
+      // interaction IDs
+      ExitButtonIID: integer;
+
+      // dummy data for non-available channels
+      ChannelToPlayerMapDummy: integer;
+
+      // preview channel-buffers
+      PreviewChannel: array of TCaptureBuffer;
+      ChannelPeak: array of TPeakInfo;
+
+      // Device source volume
+      SourceVolume: single;
+      NextVolumePollTime: cardinal;
+
+      procedure StartPreview;
+      procedure StopPreview;
+      procedure UpdateInputDevice;
+      function ValidateSettings: boolean;
+      procedure ChangeVolume(VolumeChange: single);
+      procedure DrawVolume(x, y, Width, Height: single);
+      procedure DrawVUMeter(const State: TDrawState; x, y, Width, Height: single);
+      procedure DrawPitch(const State: TDrawState; x, y, Width, Height: single);
+    public
+      constructor Create; override;
+      function    Draw: boolean; override;
+      function    ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure   OnShow; override;
+      procedure   OnHide; override;
+  end;
+
+const
+  PeakDecay = 0.2; // strength of peak-decay (reduction after one sec)
+
+const
+  BarHeight  = 11; // height of each bar (volume/vu-meter/pitch)
+  BarUpperSpacing = 1;  // spacing between a bar-area and the previous widget
+  BarLowerSpacing = 3;  // spacing between a bar-area and the next widget
+  SourceBarsTotalHeight = BarHeight + BarUpperSpacing + BarLowerSpacing;
+  ChannelBarsTotalHeight = 2*BarHeight + BarUpperSpacing + BarLowerSpacing;
+
+implementation
+
+uses
+  SysUtils,
+  Math,
+  SDL,
+  gl,
+  TextGL,
+  UGraphic,
+  UDraw,
+  ULanguage,
+  UMain,
+  UMenuSelectSlide,
+  UMenuText,
+  UFiles,
+  UDisplay,
+  UIni,
+  UUnicodeUtils,
+  ULog;
+
+function TScreenOptionsRecord.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+      Ord('+'):
+        begin
+          // FIXME: add a nice volume-slider instead
+          // or at least provide visualization and acceleration if the user holds the key pressed.
+          ChangeVolume(0.02);
+        end;
+      Ord('-'):
+        begin
+          // FIXME: add a nice volume-slider instead
+          // or at least provide visualization and acceleration if the user holds the key pressed.
+          ChangeVolume(-0.02);
+        end;
+      Ord('T'):
+        begin
+          if ((SDL_GetModState() and KMOD_SHIFT) <> 0) then
+            Ini.ThresholdIndex := (Ini.ThresholdIndex + Length(IThresholdVals) - 1) mod Length(IThresholdVals)
+          else
+            Ini.ThresholdIndex := (Ini.ThresholdIndex + 1) mod Length(IThresholdVals);
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE:
+        begin
+          // TODO: Show Save/Abort screen
+          if (ValidateSettings()) then
+          begin
+            Ini.Save;
+            AudioPlayback.PlaySound(SoundLib.Back);
+            FadeTo(@ScreenOptions);
+          end;
+        end;
+      SDLK_RETURN:
+        begin
+          if (SelInteraction = ExitButtonIID) then
+          begin
+            if (ValidateSettings()) then
+            begin
+              Ini.Save;
+              AudioPlayback.PlaySound(SoundLib.Back);
+              FadeTo(@ScreenOptions);
+            end;
+          end;
+        end;
+      SDLK_DOWN:
+        InteractNext;
+      SDLK_UP :
+        InteractPrev;
+      SDLK_RIGHT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction < ExitButtonIID) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractInc;
+          end;
+          UpdateInputDevice;
+        end;
+      SDLK_LEFT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction < ExitButtonIID) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractDec;
+          end;
+          UpdateInputDevice;
+        end;
+    end;
+  end;
+end;
+
+function TScreenOptionsRecord.ValidateSettings: boolean;
+var
+  BadPlayer: integer;
+begin
+  BadPlayer := AudioInputProcessor.ValidateSettings();
+  if (BadPlayer <> 0) then
+  begin
+    ScreenPopupError.ShowPopup(
+        Format(Language.Translate('ERROR_PLAYER_DEVICE_ASSIGNMENT'),
+        [BadPlayer]));
+    Result := false;
+  end
+  else
+  begin
+    Result := true;
+  end;
+end;
+
+constructor TScreenOptionsRecord.Create;
+var
+  DeviceIndex:  integer;
+  SourceIndex:  integer;
+  ChannelIndex: integer;
+  InputDevice: TAudioInputDevice;
+  InputDeviceCfg: PInputDeviceConfig;
+  ChannelTheme: ^TThemeSelectSlide;
+  //ButtonTheme: TThemeButton;
+  WidgetYPos: integer;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.OptionsRecord);
+
+  // set CurrentDeviceIndex to a valid device
+  if (Length(AudioInputProcessor.DeviceList) > 0) then
+    CurrentDeviceIndex := 0
+  else
+    CurrentDeviceIndex := -1;
+
+  PreviewDeviceIndex := -1;
+
+  WidgetYPos := 0;
+
+  // init sliders if at least one device was detected
+  if (Length(AudioInputProcessor.DeviceList) > 0) then
+  begin
+    InputDevice := AudioInputProcessor.DeviceList[CurrentDeviceIndex];
+    InputDeviceCfg := @Ini.InputDeviceConfig[InputDevice.CfgIndex];
+
+    // init device-selection slider
+    SetLength(InputDeviceNames, Length(AudioInputProcessor.DeviceList));
+    for DeviceIndex := 0 to High(AudioInputProcessor.DeviceList) do
+    begin
+      InputDeviceNames[DeviceIndex] := AudioInputProcessor.DeviceList[DeviceIndex].Name;
+    end;
+    // add device-selection slider (InteractionID: 0)
+    Theme.OptionsRecord.SelectSlideCard.showArrows := true;
+    Theme.OptionsRecord.SelectSlideCard.oneItemOnly := true;
+    AddSelectSlide(Theme.OptionsRecord.SelectSlideCard, CurrentDeviceIndex, InputDeviceNames);
+
+    // init source-selection slider
+    SetLength(InputSourceNames, Length(InputDevice.Source));
+    for SourceIndex := 0 to High(InputDevice.Source) do
+    begin
+      InputSourceNames[SourceIndex] := InputDevice.Source[SourceIndex].Name;
+    end;
+
+    Theme.OptionsRecord.SelectSlideInput.showArrows := true;
+    Theme.OptionsRecord.SelectSlideInput.oneItemOnly := true;
+    // add source-selection slider (InteractionID: 1)
+    SelectInputSourceID := AddSelectSlide(Theme.OptionsRecord.SelectSlideInput,
+        InputDeviceCfg.Input, InputSourceNames);
+
+    // add space for source volume bar
+    WidgetYPos := Theme.OptionsRecord.SelectSlideInput.Y +
+                  Theme.OptionsRecord.SelectSlideInput.H +
+                  SourceBarsTotalHeight;
+
+    // find max. channel count of all devices
+    MaxChannelCount := 0;
+    for DeviceIndex := 0 to High(AudioInputProcessor.DeviceList) do
+    begin
+      if (AudioInputProcessor.DeviceList[DeviceIndex].AudioFormat.Channels > MaxChannelCount) then
+        MaxChannelCount := AudioInputProcessor.DeviceList[DeviceIndex].AudioFormat.Channels;
+    end;
+
+    // init channel-to-player mapping sliders
+    SetLength(SelectSlideChannelID, MaxChannelCount);
+    SetLength(SelectSlideChannelTheme, MaxChannelCount);
+
+    for ChannelIndex := 0 to MaxChannelCount-1 do
+    begin
+      // copy reference slide
+      SelectSlideChannelTheme[ChannelIndex] :=
+        Theme.OptionsRecord.SelectSlideChannel;
+      // set current channel-theme
+      ChannelTheme := @SelectSlideChannelTheme[ChannelIndex];
+      // adjust vertical position
+      ChannelTheme.Y := WidgetYPos;
+      // calc size of next slide (add space for bars)
+      WidgetYPos := WidgetYPos + ChannelTheme.H + ChannelBarsTotalHeight;
+      // append channel index to name
+      ChannelTheme.Text := ChannelTheme.Text + IntToStr(ChannelIndex+1);
+
+      // show/hide widgets depending on whether the channel exists
+      if (ChannelIndex < Length(InputDeviceCfg.ChannelToPlayerMap)) then
+      begin
+        // current device has this channel
+
+        // add slider
+        SelectSlideChannelID[ChannelIndex] := AddSelectSlide(ChannelTheme^,
+          InputDeviceCfg.ChannelToPlayerMap[ChannelIndex], IChannelPlayerTranslated);
+      end
+      else
+      begin
+        // current device does not have that many channels
+
+        // add slider but hide it and assign a dummy variable to it
+        SelectSlideChannelID[ChannelIndex] := AddSelectSlide(ChannelTheme^,
+          ChannelToPlayerMapDummy, IChannelPlayerTranslated);
+        SelectsS[SelectSlideChannelID[ChannelIndex]].Visible := false;
+      end;
+    end;
+  end;
+
+  // add Exit-button
+  AddButton(Theme.OptionsRecord.ButtonExit);
+  if (Length(Button[0].Text) = 0) then
+    AddButtonText(20, 5, Theme.Options.Description[7]);
+  // store InteractionID
+  if (Length(AudioInputProcessor.DeviceList) > 0) then
+    ExitButtonIID := MaxChannelCount + 2
+  else
+    ExitButtonIID := 0;
+
+  // set focus
+  Interaction := 0;
+end;
+
+procedure TScreenOptionsRecord.UpdateInputDevice;
+var
+  SourceIndex: integer;
+  InputDevice: TAudioInputDevice;
+  InputDeviceCfg: PInputDeviceConfig;
+  ChannelIndex: integer;
+begin
+  //Log.LogStatus('Update input-device', 'TScreenOptionsRecord.UpdateCard') ;
+
+  StopPreview();
+
+  // set CurrentDeviceIndex to a valid device
+  if (CurrentDeviceIndex > High(AudioInputProcessor.DeviceList)) then
+    CurrentDeviceIndex := 0;
+
+  // update sliders if at least one device was detected
+  if (Length(AudioInputProcessor.DeviceList) > 0) then
+  begin
+    InputDevice := AudioInputProcessor.DeviceList[CurrentDeviceIndex];
+    InputDeviceCfg := @Ini.InputDeviceConfig[InputDevice.CfgIndex];
+
+    // update source-selection slider
+    SetLength(InputSourceNames, Length(InputDevice.Source));
+    for SourceIndex := 0 to High(InputDevice.Source) do
+    begin
+      InputSourceNames[SourceIndex] := InputDevice.Source[SourceIndex].Name;
+    end;
+    UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideInput, SelectInputSourceID,
+        InputSourceNames, InputDeviceCfg.Input);
+
+    // update channel-to-player mapping sliders
+    for ChannelIndex := 0 to MaxChannelCount-1 do
+    begin
+      // show/hide widgets depending on whether the channel exists
+      if (ChannelIndex < Length(InputDeviceCfg.ChannelToPlayerMap)) then
+      begin
+        // current device has this channel
+
+        // show slider
+        UpdateSelectSlideOptions(SelectSlideChannelTheme[ChannelIndex],
+          SelectSlideChannelID[ChannelIndex], IChannelPlayerTranslated,
+          InputDeviceCfg.ChannelToPlayerMap[ChannelIndex]);
+        SelectsS[SelectSlideChannelID[ChannelIndex]].Visible := true;
+      end
+      else
+      begin
+        // current device does not have that many channels
+
+        // hide slider and assign a dummy variable to it
+        UpdateSelectSlideOptions(SelectSlideChannelTheme[ChannelIndex],
+          SelectSlideChannelID[ChannelIndex], IChannelPlayerTranslated,
+          ChannelToPlayerMapDummy);
+        SelectsS[SelectSlideChannelID[ChannelIndex]].Visible := false;
+      end;
+    end;
+  end;
+
+  StartPreview();
+end;
+
+procedure TScreenOptionsRecord.ChangeVolume(VolumeChange: single);
+var
+  InputDevice: TAudioInputDevice;
+  Volume: single;
+begin
+  // validate CurrentDeviceIndex
+  if ((CurrentDeviceIndex < 0) or
+      (CurrentDeviceIndex > High(AudioInputProcessor.DeviceList))) then
+  begin
+    Exit;
+  end;
+
+  InputDevice := AudioInputProcessor.DeviceList[CurrentDeviceIndex];
+  if not assigned(InputDevice) then
+    Exit;
+
+  // set new volume
+  Volume := InputDevice.GetVolume() + VolumeChange;
+  InputDevice.SetVolume(Volume);
+  //DebugWriteln('Volume: ' + floattostr(InputDevice.GetVolume));
+
+  // volume must be polled again 
+  NextVolumePollTime := 0;
+end;
+
+procedure TScreenOptionsRecord.OnShow;
+var
+  ChannelIndex: integer;
+begin
+  inherited;
+
+  // BgMusic distracts too much, pause it
+  SoundLib.PauseBgMusic;
+
+  Interaction := 0;
+
+  // create preview sound-buffers
+  SetLength(PreviewChannel, MaxChannelCount);
+  for ChannelIndex := 0 to High(PreviewChannel) do
+    PreviewChannel[ChannelIndex] := TCaptureBuffer.Create();
+
+  SetLength(ChannelPeak, MaxChannelCount);
+
+  UpdateInputDevice();
+end;
+
+procedure TScreenOptionsRecord.OnHide;
+var
+  ChannelIndex: integer;
+begin
+  StopPreview();
+
+  // free preview buffers
+  for ChannelIndex := 0 to High(PreviewChannel) do
+    PreviewChannel[ChannelIndex].Free;
+  SetLength(PreviewChannel, 0);
+  SetLength(ChannelPeak, 0);
+end;
+
+procedure TScreenOptionsRecord.StartPreview;
+var
+  ChannelIndex: integer;
+  Device: TAudioInputDevice;
+begin
+  if ((CurrentDeviceIndex >= 0) and
+      (CurrentDeviceIndex <= High(AudioInputProcessor.DeviceList))) then
+  begin
+    Device := AudioInputProcessor.DeviceList[CurrentDeviceIndex];
+    // set preview channel as active capture channel
+    for ChannelIndex := 0 to High(Device.CaptureChannel) do
+    begin
+      PreviewChannel[ChannelIndex].Clear();
+      Device.LinkCaptureBuffer(ChannelIndex, PreviewChannel[ChannelIndex]);
+      FillChar(ChannelPeak[ChannelIndex], SizeOf(TPeakInfo), 0);
+    end;
+    Device.Start();
+    PreviewDeviceIndex := CurrentDeviceIndex;
+
+    // volume must be polled again
+    NextVolumePollTime := 0;
+  end;
+end;
+
+procedure TScreenOptionsRecord.StopPreview;
+var
+  ChannelIndex: integer;
+  Device: TAudioInputDevice;
+begin
+  if ((PreviewDeviceIndex >= 0) and
+      (PreviewDeviceIndex <= High(AudioInputProcessor.DeviceList))) then
+  begin
+    Device := AudioInputProcessor.DeviceList[PreviewDeviceIndex];
+    Device.Stop;
+    for ChannelIndex := 0 to High(Device.CaptureChannel) do
+      Device.LinkCaptureBuffer(ChannelIndex, nil);
+  end;
+  PreviewDeviceIndex := -1;
+end;
+
+procedure TScreenOptionsRecord.DrawVolume(x, y, Width, Height: single);
+var
+  x1, y1, x2, y2: single;
+  VolBarInnerWidth: integer;
+  Volume: single;
+const
+  VolBarInnerHSpacing = 2;
+  VolBarInnerVSpacing = 1;
+begin
+  // coordinates for black rect
+  x1 := x;
+  y1 := y;
+  x2 := x1 + Width;
+  y2 := y1 + Height;
+
+  // init blend mode
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+
+  // draw black background-rect
+  glColor4f(0, 0, 0, 0.8);
+  glBegin(GL_QUADS);
+    glVertex2f(x1, y1);
+    glVertex2f(x2, y1);
+    glVertex2f(x2, y2);
+    glVertex2f(x1, y2);
+  glEnd();
+
+  VolBarInnerWidth := Trunc(Width - 2*VolBarInnerHSpacing);
+
+  // TODO: if no volume is available, show some info (a blue bar maybe)
+  if (SourceVolume >= 0) then
+    Volume := SourceVolume
+  else
+    Volume := 0;
+
+  // coordinates for first half of the volume bar
+  x1 := x + VolBarInnerHSpacing;
+  x2 := x1 + VolBarInnerWidth * Volume;
+  y1 := y1 + VolBarInnerVSpacing;
+  y2 := y2 - VolBarInnerVSpacing;
+
+  // draw volume-bar
+  glBegin(GL_QUADS);
+    // draw volume bar
+    glColor3f(0.4, 0.3, 0.3);
+    glVertex2f(x1, y1);
+    glVertex2f(x1, y2);
+    glColor3f(1, 0.1, 0.1);
+    glVertex2f(x2, y2);
+    glVertex2f(x2, y1);
+  glEnd();
+
+  { not needed anymore
+  // coordinates for separator
+  x1 := x + VolBarInnerHSpacing;
+  x2 := x1 + VolBarInnerWidth;
+
+  // draw separator
+  glBegin(GL_LINE_STRIP);
+    glColor4f(0.1, 0.1, 0.1, 0.2);
+    glVertex2f(x1,        y2);
+    glColor4f(0.4, 0.4, 0.4, 0.2);
+    glVertex2f((x1+x2)/2, y2);
+    glColor4f(0.1, 0.1, 0.1, 0.2);
+    glVertex2f(x2,        y2);
+  glEnd();
+  }
+
+  glDisable(GL_BLEND);
+end;
+
+procedure TScreenOptionsRecord.DrawVUMeter(const State: TDrawState; x, y, Width, Height: single);
+var
+  x1, y1, x2, y2: single;
+  Volume, PeakVolume: single;
+  Delta: single;
+  VolBarInnerWidth: integer;
+const
+  VolBarInnerHSpacing = 2;
+  VolBarInnerVSpacing = 1;
+begin
+  // coordinates for black rect
+  x1 := x;
+  y1 := y;
+  x2 := x1 + Width;
+  y2 := y1 + Height;
+
+  // init blend mode
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+
+  // draw black background-rect
+  glColor4f(0, 0, 0, 0.8);
+  glBegin(GL_QUADS);
+    glVertex2f(x1, y1);
+    glVertex2f(x2, y1);
+    glVertex2f(x2, y2);
+    glVertex2f(x1, y2);
+  glEnd();
+
+  VolBarInnerWidth := Trunc(Width - 2*VolBarInnerHSpacing);
+
+  // vertical positions
+  y1 := y1 + VolBarInnerVSpacing;
+  y2 := y2 - VolBarInnerVSpacing;
+
+  // coordinates for bevel
+  x1 := x + VolBarInnerHSpacing;
+  x2 := x1 + VolBarInnerWidth;
+
+  glBegin(GL_QUADS);
+    Volume := PreviewChannel[State.ChannelIndex].MaxSampleVolume();
+
+    // coordinates for volume bar
+    x1 := x + VolBarInnerHSpacing;
+    x2 := x1 + VolBarInnerWidth * Volume;
+
+    // draw volume bar
+    glColor3f(State.RD, State.GD, State.BD);
+    glVertex2f(x1, y1);
+    glVertex2f(x1, y2);
+    glColor3f(State.R, State.G, State.B);
+    glVertex2f(x2, y2);
+    glVertex2f(x2, y1);
+
+    Delta := (SDL_GetTicks() - ChannelPeak[State.ChannelIndex].Time)/1000;
+    PeakVolume := ChannelPeak[State.ChannelIndex].Volume - Delta*Delta*PeakDecay;
+
+    // determine new peak-volume
+    if (Volume > PeakVolume) then
+    begin
+      PeakVolume := Volume;
+      ChannelPeak[State.ChannelIndex].Volume := Volume;
+      ChannelPeak[State.ChannelIndex].Time := SDL_GetTicks();
+    end;
+
+    x1 := x + VolBarInnerHSpacing + VolBarInnerWidth * PeakVolume;
+    x2 := x1 + 2;
+
+    // draw peak
+    glColor3f(0.8, 0.8, 0.8);
+    glVertex2f(x1, y1);
+    glVertex2f(x1, y2);
+    glVertex2f(x2, y2);
+    glVertex2f(x2, y1);
+
+    // draw threshold
+    x1 := x + VolBarInnerHSpacing;
+    x2 := x1 + VolBarInnerWidth * IThresholdVals[Ini.ThresholdIndex];
+
+    glColor4f(0.3, 0.3, 0.3, 0.6);
+    glVertex2f(x1, y1);
+    glVertex2f(x1, y2);
+    glVertex2f(x2, y2);
+    glVertex2f(x2, y1);
+  glEnd();
+
+  glDisable(GL_BLEND);
+end;
+
+procedure TScreenOptionsRecord.DrawPitch(const State: TDrawState; x, y, Width, Height: single);
+var
+  x1, y1, x2, y2: single;
+  i: integer;
+  ToneBoxWidth: real;
+  ToneString: string;
+  ToneStringWidth, ToneStringHeight: real;
+  ToneStringMaxWidth: real;
+  ToneStringCenterXOffset: real;
+const
+  PitchBarInnerHSpacing = 2;
+  PitchBarInnerVSpacing = 1;
+begin
+  // calc tone pitch
+  PreviewChannel[State.ChannelIndex].AnalyzeBuffer();
+
+  // coordinates for black rect
+  x1 := x;
+  y1 := y;
+  x2 := x + Width;
+  y2 := y + Height;
+
+  // init blend mode
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+
+  // draw black background-rect
+  glColor4f(0, 0, 0, 0.8);
+  glBegin(GL_QUADS);
+    glVertex2f(x1, y1);
+    glVertex2f(x2, y1);
+    glVertex2f(x2, y2);
+    glVertex2f(x1, y2);
+  glEnd();
+
+  // coordinates for tone boxes
+  ToneBoxWidth := Width / NumHalftones;
+  y1 := y1 + PitchBarInnerVSpacing;
+  y2 := y2 - PitchBarInnerVSpacing;
+
+  glBegin(GL_QUADS);
+    // draw tone boxes
+    for i := 0 to NumHalftones-1 do
+    begin
+      x1 := x + i * ToneBoxWidth + PitchBarInnerHSpacing;
+      x2 := x1 + ToneBoxWidth - 2*PitchBarInnerHSpacing;
+
+      if ((PreviewChannel[State.ChannelIndex].ToneValid) and
+          (PreviewChannel[State.ChannelIndex].ToneAbs = i)) then
+      begin
+        // highlight current tone-pitch
+        glColor3f(1, i / (NumHalftones-1), 0)
+      end
+      else
+      begin
+        // grey other tone-pitches
+        glColor3f(0.3, i / (NumHalftones-1) * 0.3, 0);
+      end;
+
+      glVertex2f(x1, y1);
+      glVertex2f(x2, y1);
+      glVertex2f(x2, y2);
+      glVertex2f(x1, y2);
+    end;
+  glEnd();
+
+  glDisable(GL_BLEND);
+
+  ///
+  // draw the name of the tone
+  ///////
+
+  ToneString := PreviewChannel[State.ChannelIndex].ToneString;
+  ToneStringHeight := ChannelBarsTotalHeight;
+
+  // initialize font
+  // TODO: what about reflection, italic etc.?
+  SetFontSize(ToneStringHeight);
+
+  // center
+  // Note: for centering let us assume that G#4 has the max. horizontal extent
+  ToneStringWidth := glTextWidth(ToneString);
+  ToneStringMaxWidth := glTextWidth('G#4');
+  ToneStringCenterXOffset := (ToneStringMaxWidth-ToneStringWidth) / 2;
+
+  // draw
+  SetFontPos(x-ToneStringWidth-ToneStringCenterXOffset, y-ToneStringHeight/2);
+  glColor3f(0, 0, 0);
+  glPrint(ToneString);
+end;
+
+function TScreenOptionsRecord.Draw: boolean;
+var
+  Device: TAudioInputDevice;
+  DeviceCfg: PInputDeviceConfig;
+  SelectSlide: TSelectSlide;
+  BarXOffset, BarYOffset, BarWidth: real;
+  ChannelIndex: integer;
+  State: TDrawState;
+begin
+  DrawBG;
+  DrawFG;
+
+  if ((PreviewDeviceIndex >= 0) and
+      (PreviewDeviceIndex <= High(AudioInputProcessor.DeviceList))) then
+  begin
+    Device := AudioInputProcessor.DeviceList[PreviewDeviceIndex];
+    DeviceCfg := @Ini.InputDeviceConfig[Device.CfgIndex];
+
+    // update source volume
+    if (SDL_GetTicks() >= NextVolumePollTime) then
+    begin
+      NextVolumePollTime := SDL_GetTicks() + 500; // next poll in 500ms
+      SourceVolume := Device.GetVolume();
+    end;
+
+    // get source select slide
+    SelectSlide := SelectsS[SelectInputSourceID];
+    BarXOffset := SelectSlide.TextureSBG.X;
+    BarYOffset := SelectSlide.TextureSBG.Y + SelectSlide.TextureSBG.H + BarUpperSpacing;
+    BarWidth   := SelectSlide.TextureSBG.W;
+    DrawVolume(SelectSlide.TextureSBG.X, BarYOffset, BarWidth, BarHeight);
+
+    for ChannelIndex := 0 to High(Device.CaptureChannel) do
+    begin
+      // load player color mapped to current input channel
+      if (DeviceCfg.ChannelToPlayerMap[ChannelIndex] <> CHANNEL_OFF) then
+      begin
+        // set mapped channel to corresponding player-color
+        LoadColor(State.R, State.G, State.B, 'P'+ IntToStr(DeviceCfg.ChannelToPlayerMap[ChannelIndex]) + 'Dark');
+      end
+      else
+      begin
+        // set non-mapped channel to white
+        State.R := 1; State.G := 1; State.B := 1;
+      end;
+
+      // dark player colors
+      State.RD := 0.2 * State.R;
+      State.GD := 0.2 * State.G;
+      State.BD := 0.2 * State.B;
+
+      // channel select slide
+      SelectSlide := SelectsS[SelectSlideChannelID[ChannelIndex]];
+
+      BarXOffset := SelectSlide.TextureSBG.X;
+      BarYOffset := SelectSlide.TextureSBG.Y + SelectSlide.TextureSBG.H + BarUpperSpacing;
+      BarWidth   := SelectSlide.TextureSBG.W;
+
+      State.ChannelIndex := ChannelIndex;
+
+      DrawVUMeter(State, BarXOffset, BarYOffset, BarWidth, BarHeight);
+      DrawPitch(State, BarXOffset, BarYOffset+BarHeight, BarWidth, BarHeight);
+    end;
+  end;
+
+  Result := true;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenOptionsSound.pas b/songmanagement/src/screens/UScreenOptionsSound.pas
new file mode 100644
index 00000000..c0efa4d8
--- /dev/null
+++ b/songmanagement/src/screens/UScreenOptionsSound.pas
@@ -0,0 +1,187 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenOptionsSound;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  UMenu,
+  UDisplay,
+  UMusic,
+  UFiles,
+  UIni,
+  UThemes;
+
+type
+  TScreenOptionsSound = class(TMenu)
+  public
+    constructor Create; override;
+    function ParseInput(PressedKey: Cardinal; CharCode: UCS4Char;
+      PressedDown: boolean): boolean; override;
+    procedure OnShow; override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UUnicodeUtils,
+  SysUtils;
+
+function TScreenOptionsSound.ParseInput(PressedKey: cardinal;
+  CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+        // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+      begin
+        Result := false;
+        Exit;
+      end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE:
+      begin
+        Ini.Save;
+        AudioPlayback.PlaySound(SoundLib.Back);
+        FadeTo(@ScreenOptions);
+      end;
+      SDLK_RETURN:
+      begin
+        if SelInteraction = 8 then
+        begin
+          Ini.Save;
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenOptions);
+        end;
+      end;
+      SDLK_DOWN:
+        InteractNext;
+      SDLK_UP:
+        InteractPrev;
+      SDLK_RIGHT:
+      begin
+        if (SelInteraction >= 0) and (SelInteraction < 8) then
+        begin
+          AudioPlayback.PlaySound(SoundLib.Option);
+          InteractInc;
+        end;
+      end;
+      SDLK_LEFT:
+      begin
+        if (SelInteraction >= 0) and (SelInteraction < 8) then
+        begin
+          AudioPlayback.PlaySound(SoundLib.Option);
+          InteractDec;
+        end;
+      end;
+    end;
+  end;
+
+{**
+ * Actually this one isn't pretty - but it does the trick of
+ * turning the background music on/off in "real time"
+ * bgm = background music
+ * TODO: - Fetching the SelectInteraction via something more descriptive
+ *       - Obtaining the current value of a select is imho ugly
+ *}
+  if (SelInteraction = 1) then
+  begin
+    if TBackgroundMusicOption(SelectsS[1].SelectedOption) = bmoOn then
+      SoundLib.StartBgMusic
+    else
+      SoundLib.PauseBgMusic;
+  end;
+  
+end;
+
+constructor TScreenOptionsSound.Create;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.OptionsSound);
+
+  Theme.OptionsSound.SelectSlideVoicePassthrough.showArrows := true;
+  Theme.OptionsSound.SelectSlideVoicePassthrough.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsSound.SelectSlideVoicePassthrough, Ini.VoicePassthrough, IVoicePassthroughTranslated);
+
+  Theme.OptionsSound.SelectBackgroundMusic.showArrows := true;
+  Theme.OptionsSound.SelectBackgroundMusic.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsSound.SelectBackgroundMusic, Ini.BackgroundMusicOption, IBackgroundMusicTranslated);
+
+  // TODO: - MicBoost needs to be moved to ScreenOptionsRecord
+  Theme.OptionsSound.SelectMicBoost.showArrows := true;
+  Theme.OptionsSound.SelectMicBoost.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsSound.SelectMicBoost, Ini.MicBoost, IMicBoostTranslated);
+
+
+  Theme.OptionsSound.SelectClickAssist.showArrows := true;
+  Theme.OptionsSound.SelectClickAssist.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsSound.SelectClickAssist, Ini.ClickAssist, IClickAssistTranslated);
+
+  Theme.OptionsSound.SelectBeatClick.showArrows := true;
+  Theme.OptionsSound.SelectBeatClick.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsSound.SelectBeatClick, Ini.BeatClick, IBeatClickTranslated);
+
+  Theme.OptionsSound.SelectThreshold.showArrows := true;
+  Theme.OptionsSound.SelectThreshold.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsSound.SelectThreshold, Ini.ThresholdIndex, IThreshold);
+
+  Theme.OptionsSound.SelectSlidePreviewVolume.showArrows := true;
+  Theme.OptionsSound.SelectSlidePreviewVolume.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsSound.SelectSlidePreviewVolume, Ini.PreviewVolume, IPreviewVolumeTranslated);
+
+  Theme.OptionsSound.SelectSlidePreviewFading.showArrows := true;
+  Theme.OptionsSound.SelectSlidePreviewFading.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsSound.SelectSlidePreviewFading, Ini.PreviewFading, IPreviewFadingTranslated);
+
+  AddButton(Theme.OptionsSound.ButtonExit);
+  if (Length(Button[0].Text) = 0) then
+    AddButtonText(20, 5, Theme.Options.Description[7]);
+
+  Interaction := 0;
+end;
+
+procedure TScreenOptionsSound.OnShow;
+begin
+  inherited;
+  Interaction := 0;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenOptionsThemes.pas b/songmanagement/src/screens/UScreenOptionsThemes.pas
new file mode 100644
index 00000000..29d8a9dc
--- /dev/null
+++ b/songmanagement/src/screens/UScreenOptionsThemes.pas
@@ -0,0 +1,237 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenOptionsThemes;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  UMenu,
+  UDisplay,
+  UMusic,
+  UFiles,
+  UIni,
+  UThemes;
+
+type
+  TScreenOptionsThemes = class(TMenu)
+    private
+      procedure ReloadTheme;
+    public
+      SkinSelect: integer;
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure InteractInc; override;
+      procedure InteractDec; override;
+  end;
+
+implementation
+
+uses 
+  SysUtils,
+  UGraphic,
+  UMain,
+  UPathUtils,
+  UUnicodeUtils,
+  USkins;
+
+function TScreenOptionsThemes.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          Ini.Save;
+
+          // Reload all screens, after Theme changed
+          // Todo : JB - Check if theme was actually changed
+          UGraphic.UnLoadScreens();
+          UGraphic.LoadScreens();
+
+          AudioPlayback.PlaySound(SoundLib.Back);
+
+          // select theme button in new created options screen
+          ScreenOptions.Interaction := 4;
+
+          FadeTo(@ScreenOptions);
+        end;
+      SDLK_RETURN:
+        begin
+          if SelInteraction = 3 then
+          begin
+            Ini.Save;
+
+            // Reload all screens, after Theme changed
+            // Todo : JB - Check if theme was actually changed
+            UGraphic.UnLoadScreens();
+            UGraphic.LoadScreens();
+
+            AudioPlayback.PlaySound(SoundLib.Back);
+
+            // select theme button in new created options screen
+            ScreenOptions.Interaction := 4;
+
+            FadeTo(@ScreenOptions);
+          end;
+        end;
+      SDLK_DOWN:
+        InteractNext;
+      SDLK_UP :
+        InteractPrev;
+      SDLK_RIGHT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction <= 2) then 
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractInc;
+          end;
+        end;
+      SDLK_LEFT:
+        begin
+          if (SelInteraction >= 0) and (SelInteraction <= 2) then 
+          begin
+            AudioPlayback.PlaySound(SoundLib.Option);
+            InteractDec;
+          end;
+        end;
+    end;
+  end;
+end;
+
+procedure TScreenOptionsThemes.InteractInc;
+begin
+  inherited InteractInc;
+
+  //Update Skins
+  if (SelInteraction = 0) then
+  begin
+    Skin.OnThemeChange;
+    UpdateSelectSlideOptions(Theme.OptionsThemes.SelectSkin, SkinSelect, ISkin, Ini.SkinNo);
+
+    // set skin to themes default skin
+    Ini.SkinNo := Theme.Themes[Ini.Theme].DefaultSkin;
+  end;
+
+  { set skins default color }
+  if (SelInteraction = 0) or (SelInteraction = 1) then
+  begin
+    Ini.Color := Skin.GetDefaultColor(Ini.SkinNo);
+  end;
+
+  ReloadTheme();
+end;
+
+procedure TScreenOptionsThemes.InteractDec;
+begin
+  inherited InteractDec;
+
+  //Update Skins
+  if (SelInteraction = 0 ) then
+  begin
+    Skin.OnThemeChange;
+    UpdateSelectSlideOptions (Theme.OptionsThemes.SelectSkin, SkinSelect, ISkin, Ini.SkinNo);
+
+    // set skin to themes default skin
+    Ini.SkinNo := Theme.Themes[Ini.Theme].DefaultSkin;
+  end;
+
+  { set skins default color }
+  if (SelInteraction = 0) or (SelInteraction = 1) then
+  begin
+    Ini.Color := Skin.GetDefaultColor(Ini.SkinNo);
+  end;
+
+  ReloadTheme();
+end;
+
+constructor TScreenOptionsThemes.Create;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.OptionsThemes);
+
+  Theme.OptionsThemes.SelectTheme.showArrows := true;
+  Theme.OptionsThemes.SelectTheme.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsThemes.SelectTheme, Ini.Theme, ITheme);
+
+  Theme.OptionsThemes.SelectSkin.showArrows := true;
+  Theme.OptionsThemes.SelectSkin.oneItemOnly := true;
+  SkinSelect := AddSelectSlide(Theme.OptionsThemes.SelectSkin, Ini.SkinNo, ISkin);
+
+  Theme.OptionsThemes.SelectColor.showArrows := true;
+  Theme.OptionsThemes.SelectColor.oneItemOnly := true;
+  AddSelectSlide(Theme.OptionsThemes.SelectColor, Ini.Color, IColorTranslated);
+
+  AddButton(Theme.OptionsThemes.ButtonExit);
+  if (Length(Button[0].Text)=0) then
+    AddButtonText(20, 5, Theme.Options.Description[7]);
+end;
+
+procedure TScreenOptionsThemes.OnShow;
+begin
+  inherited;
+
+  Interaction := 0;
+end;
+
+procedure TScreenOptionsThemes.ReloadTheme;
+begin
+  Theme.LoadTheme(Ini.Theme, Ini.Color);
+
+  ScreenOptionsThemes := TScreenOptionsThemes.create();
+  ScreenOptionsThemes.onshow;
+  Display.CurrentScreen := @ScreenOptionsThemes;
+
+  ScreenOptionsThemes.Interaction    := self.Interaction;
+  ScreenOptionsThemes.Draw;
+
+  Display.Draw;
+  SwapBuffers;
+
+  Self.Destroy;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenPartyNewRound.pas b/songmanagement/src/screens/UScreenPartyNewRound.pas
new file mode 100644
index 00000000..8024108c
--- /dev/null
+++ b/songmanagement/src/screens/UScreenPartyNewRound.pas
@@ -0,0 +1,334 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenPartyNewRound;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  SysUtils,
+  UMenu,
+  UDisplay,
+  UMusic,
+  UFiles,
+  UThemes;
+
+type
+  TScreenPartyNewRound = class(TMenu)
+    public
+      //Texts:
+      TextRound: array [0..6] of cardinal;
+
+      TextWinner: array [0..6] of cardinal;
+
+      TextNextRound: cardinal;
+      TextNextRoundNo: cardinal;
+      TextNextPlayer1: cardinal;
+      TextNextPlayer2: cardinal;
+      TextNextPlayer3: cardinal;
+
+      //Statics
+      StaticRound: array [0..6] of cardinal;
+
+      //Scores
+      TextScoreTeam1: cardinal;
+      TextScoreTeam2: cardinal;
+      TextScoreTeam3: cardinal;
+      TextNameTeam1: cardinal;
+      TextNameTeam2: cardinal;
+      TextNameTeam3: cardinal;
+
+      TextTeam1Players: cardinal;
+      TextTeam2Players: cardinal;
+      TextTeam3Players: cardinal;
+
+      StaticTeam1: cardinal;
+      StaticTeam2: cardinal;
+      StaticTeam3: cardinal;
+      StaticNextPlayer1: cardinal;
+      StaticNextPlayer2: cardinal;
+      StaticNextPlayer3: cardinal;
+
+
+
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UIni,
+  UTexture,
+  UParty,
+  ULanguage,
+  USong,
+  ULog,
+  UUnicodeUtils;
+
+function TScreenPartyNewRound.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          AudioPlayback.PlaySound(SoundLib.Back);
+          CheckFadeTo(@ScreenMain,'MSG_END_PARTY');
+        end;
+
+      SDLK_RETURN:
+        begin
+          AudioPlayback.PlaySound(SoundLib.Start);
+          Party.CallBeforeSongSelect;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenPartyNewRound.Create;
+begin
+  inherited Create;
+
+  TextRound[0] := AddText (Theme.PartyNewRound.TextRound1);
+  TextRound[1] := AddText (Theme.PartyNewRound.TextRound2);
+  TextRound[2] := AddText (Theme.PartyNewRound.TextRound3);
+  TextRound[3] := AddText (Theme.PartyNewRound.TextRound4);
+  TextRound[4] := AddText (Theme.PartyNewRound.TextRound5);
+  TextRound[5] := AddText (Theme.PartyNewRound.TextRound6);
+  TextRound[6] := AddText (Theme.PartyNewRound.TextRound7);
+
+  TextWinner[0] := AddText (Theme.PartyNewRound.TextWinner1);
+  TextWinner[1] := AddText (Theme.PartyNewRound.TextWinner2);
+  TextWinner[2] := AddText (Theme.PartyNewRound.TextWinner3);
+  TextWinner[3] := AddText (Theme.PartyNewRound.TextWinner4);
+  TextWinner[4] := AddText (Theme.PartyNewRound.TextWinner5);
+  TextWinner[5] := AddText (Theme.PartyNewRound.TextWinner6);
+  TextWinner[6] := AddText (Theme.PartyNewRound.TextWinner7);
+
+  TextNextRound := AddText (Theme.PartyNewRound.TextNextRound);
+  TextNextRoundNo := AddText (Theme.PartyNewRound.TextNextRoundNo);
+  TextNextPlayer1 := AddText (Theme.PartyNewRound.TextNextPlayer1);
+  TextNextPlayer2 := AddText (Theme.PartyNewRound.TextNextPlayer2);
+  TextNextPlayer3 := AddText (Theme.PartyNewRound.TextNextPlayer3);
+
+  StaticRound[0] := AddStatic (Theme.PartyNewRound.StaticRound1);
+  StaticRound[1] := AddStatic (Theme.PartyNewRound.StaticRound2);
+  StaticRound[2] := AddStatic (Theme.PartyNewRound.StaticRound3);
+  StaticRound[3] := AddStatic (Theme.PartyNewRound.StaticRound4);
+  StaticRound[4] := AddStatic (Theme.PartyNewRound.StaticRound5);
+  StaticRound[5] := AddStatic (Theme.PartyNewRound.StaticRound6);
+  StaticRound[6] := AddStatic (Theme.PartyNewRound.StaticRound7);
+
+  //Scores
+  TextScoreTeam1 := AddText (Theme.PartyNewRound.TextScoreTeam1);
+  TextScoreTeam2 := AddText (Theme.PartyNewRound.TextScoreTeam2);
+  TextScoreTeam3 := AddText (Theme.PartyNewRound.TextScoreTeam3);
+  TextNameTeam1 := AddText (Theme.PartyNewRound.TextNameTeam1);
+  TextNameTeam2 := AddText (Theme.PartyNewRound.TextNameTeam2);
+  TextNameTeam3 := AddText (Theme.PartyNewRound.TextNameTeam3);
+
+  //Players
+  TextTeam1Players := AddText (Theme.PartyNewRound.TextTeam1Players);
+  TextTeam2Players := AddText (Theme.PartyNewRound.TextTeam2Players);
+  TextTeam3Players := AddText (Theme.PartyNewRound.TextTeam3Players);
+
+  StaticTeam1 := AddStatic (Theme.PartyNewRound.StaticTeam1);
+  StaticTeam2 := AddStatic (Theme.PartyNewRound.StaticTeam2);
+  StaticTeam3 := AddStatic (Theme.PartyNewRound.StaticTeam3);
+  StaticNextPlayer1 := AddStatic (Theme.PartyNewRound.StaticNextPlayer1);
+  StaticNextPlayer2 := AddStatic (Theme.PartyNewRound.StaticNextPlayer2);
+  StaticNextPlayer3 := AddStatic (Theme.PartyNewRound.StaticNextPlayer3);
+
+  LoadFromTheme(Theme.PartyNewRound);
+end;
+
+procedure TScreenPartyNewRound.OnShow;
+var
+  I: integer;
+  function GetTeamPlayers(const Num: integer): UTF8String;
+  var
+    Players: array of UTF8String;
+    J: integer;
+  begin
+    if (Num > High(Party.Teams)) or (Num < 0) then
+      exit;
+
+    //Create Players array
+    SetLength(Players, Length(Party.Teams[Num].Players));
+    For J := 0 to High(Party.Teams[Num].Players) do
+      Players[J] := UTF8String(Party.Teams[Num].Players[J].Name);
+
+    //Implode and Return
+    Result := Language.Implode(Players);
+  end;
+begin
+  inherited;
+
+  //Set Visibility of Round Infos
+  for I := 0 to 6 do
+  begin
+    if (I <= High(Party.Rounds)) then
+    begin
+      Statics[StaticRound[I]].Visible := True;
+      Text[TextRound[I]].Visible := True;
+      Text[TextWinner[I]].Visible := True;
+
+      // update texts:
+      Text[TextRound[I]].Text := Language.Translate('MODE_' + uppercase(Party.Modes[Party.Rounds[I].Mode].Name) + '_NAME');
+      Text[TextWinner[I]].Text := Party.GetWinnerString(I);
+    end
+    else
+    begin
+      Statics[StaticRound[I]].Visible := False;
+      Text[TextRound[I]].Visible := False;
+      Text[TextWinner[I]].Visible := False;
+    end;
+  end;
+
+
+  //Display Scores
+  if (Length(Party.Teams) >= 1) then
+  begin
+    Text[TextScoreTeam1].Text := InttoStr(Party.Teams[0].Score);
+    Text[TextNameTeam1].Text := UTF8String(Party.Teams[0].Name);
+    Text[TextTeam1Players].Text := GetTeamPlayers(0);
+
+    Text[TextScoreTeam1].Visible := true;
+    Text[TextNameTeam1].Visible := true;
+    Text[TextTeam1Players].Visible := true;
+    Statics[StaticTeam1].Visible := true;
+    Statics[StaticNextPlayer1].Visible := true;
+  end
+  else
+  begin
+    Text[TextScoreTeam1].Visible := false;
+    Text[TextNameTeam1].Visible := false;
+    Text[TextTeam1Players].Visible := false;
+    Statics[StaticTeam1].Visible := false;
+    Statics[StaticNextPlayer1].Visible := false;
+  end;
+
+  if (Length(Party.Teams) >= 2) then
+  begin
+    Text[TextScoreTeam2].Text := InttoStr(Party.Teams[1].Score);
+    Text[TextNameTeam2].Text := UTF8String(Party.Teams[1].Name);
+    Text[TextTeam2Players].Text := GetTeamPlayers(1);
+
+    Text[TextScoreTeam2].Visible := true;
+    Text[TextNameTeam2].Visible := true;
+    Text[TextTeam2Players].Visible := true;
+    Statics[StaticTeam2].Visible := true;
+    Statics[StaticNextPlayer2].Visible := true;
+  end
+  else
+  begin
+    Text[TextScoreTeam2].Visible := false;
+    Text[TextNameTeam2].Visible := false;
+    Text[TextTeam2Players].Visible := false;
+    Statics[StaticTeam2].Visible := false;
+    Statics[StaticNextPlayer2].Visible := false;
+  end;
+
+  if (Length(Party.Teams) >= 3) then
+  begin
+    Text[TextScoreTeam3].Text := InttoStr(Party.Teams[2].Score);
+    Text[TextNameTeam3].Text := UTF8String(Party.Teams[2].Name);
+    Text[TextTeam3Players].Text := GetTeamPlayers(2);
+
+    Text[TextScoreTeam3].Visible := true;
+    Text[TextNameTeam3].Visible := true;
+    Text[TextTeam3Players].Visible := true;
+    Statics[StaticTeam3].Visible := true;
+    Statics[StaticNextPlayer3].Visible := true;
+  end
+  else
+  begin
+    Text[TextScoreTeam3].Visible := false;
+    Text[TextNameTeam3].Visible := false;
+    Text[TextTeam3Players].Visible := false;
+    Statics[StaticTeam3].Visible := false;
+    Statics[StaticNextPlayer3].Visible := false;
+  end;  
+
+  //nextRound Texts
+  Text[TextNextRound].Text := Language.Translate('MODE_' + uppercase(Party.Modes[Party.Rounds[Party.CurrentRound].Mode].Name) + '_DESC');
+  Text[TextNextRoundNo].Text := InttoStr(Party.CurrentRound + 1);
+  if (Length(Party.Teams) >= 1) then
+  begin
+    Text[TextNextPlayer1].Text := Party.Teams[0].Players[Party.Teams[0].NextPlayer].Name;
+    Text[TextNextPlayer1].Visible := true;
+  end
+  else
+    Text[TextNextPlayer1].Visible := false;
+
+  if (Length(Party.Teams) >= 2) then
+  begin
+    Text[TextNextPlayer2].Text := Party.Teams[1].Players[Party.Teams[1].NextPlayer].Name;
+    Text[TextNextPlayer2].Visible := true;
+  end
+  else
+    Text[TextNextPlayer2].Visible := false;
+
+  if (Length(Party.Teams) >= 3) then
+  begin
+    Text[TextNextPlayer3].Text := Party.Teams[2].Players[Party.Teams[2].NextPlayer].Name;
+    Text[TextNextPlayer3].Visible := true;
+  end
+  else
+    Text[TextNextPlayer3].Visible := false;
+end;
+
+procedure TScreenPartyNewRound.SetAnimationProgress(Progress: real);
+begin
+  {Button[0].Texture.ScaleW := Progress;
+  Button[1].Texture.ScaleW := Progress;
+  Button[2].Texture.ScaleW := Progress; }
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenPartyOptions.pas b/songmanagement/src/screens/UScreenPartyOptions.pas
new file mode 100644
index 00000000..f63b37fb
--- /dev/null
+++ b/songmanagement/src/screens/UScreenPartyOptions.pas
@@ -0,0 +1,284 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenPartyOptions;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  UDisplay,
+  UMusic,
+  UFiles,
+  SysUtils,
+  UThemes;
+
+type
+  TScreenPartyOptions = class(TMenu)
+    private
+      SelectLevel:     cardinal;
+      SelectPlayList:  cardinal;
+      SelectPlayList2: cardinal;
+      SelectRounds:    cardinal;
+
+      IPlaylist: array[0..2] of UTF8String;
+      IPlaylist2: array of UTF8String;
+
+      PlayList:  integer;
+      PlayList2: integer;
+      
+      procedure SetPlaylist2;
+    public 
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UIni,
+  UTexture,
+  ULanguage,
+  UParty,
+  USong,
+  UPlaylist,
+  USongs,
+  UUnicodeUtils;
+
+function TScreenPartyOptions.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+  I, J: integer;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenMain);
+        end;
+
+      SDLK_RETURN:
+        begin
+          //Don'T start when Playlist is Selected and there are no Playlists
+          if (Playlist = 2) and (Length(PlaylistMan.Playlists) = 0) then
+            Exit;
+
+          //Save Difficulty
+          Ini.Difficulty := SelectsS[SelectLevel].SelectedOption;
+          Ini.SaveLevel;
+
+          //Save Playlist
+          PlaylistMan.Mode := TSingMode( Playlist );
+          PlaylistMan.CurPlayList := High(cardinal);
+          //if Category Selected Search Category ID
+          if Playlist = 1 then
+          begin
+            J := -1;
+            for I := 0 to high(CatSongs.Song) do
+            begin
+              if CatSongs.Song[I].Main then
+                Inc(J);
+
+              if J = Playlist2 then
+              begin
+                PlaylistMan.CurPlayList := I;
+                Break;
+              end;
+            end;
+
+            //No Categorys or Invalid Entry
+            if PlaylistMan.CurPlayList = High(cardinal) then
+              Exit;
+          end
+          else
+            PlaylistMan.CurPlayList := Playlist2;
+
+          AudioPlayback.PlaySound(SoundLib.Start);
+          //Go to Player Screen
+          FadeTo(@ScreenPartyPlayer);
+        end;
+
+      // Up and Down could be done at the same time,
+      // but I don't want to declare variables inside
+      // functions like this one, called so many times
+      SDLK_DOWN:    InteractNext;
+      SDLK_UP:      InteractPrev;
+      SDLK_RIGHT:
+        begin
+          AudioPlayback.PlaySound(SoundLib.Option);
+          InteractInc;
+
+          //Change Playlist2 if Playlist is Changed
+          if (Interaction = 1) then
+          begin
+            SetPlaylist2;
+          end;
+        end;
+      SDLK_LEFT:
+        begin
+          AudioPlayback.PlaySound(SoundLib.Option);
+          InteractDec;
+
+          //Change Playlist2 if Playlist is Changed
+          if (Interaction = 1) then
+          begin
+            SetPlaylist2;
+          end;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenPartyOptions.Create;
+begin
+  inherited Create;
+  //Fill IPlaylist
+  IPlaylist[0] := Language.Translate('PARTY_PLAYLIST_ALL');
+  IPlaylist[1] := Language.Translate('PARTY_PLAYLIST_CATEGORY');
+  IPlaylist[2] := Language.Translate('PARTY_PLAYLIST_PLAYLIST');
+
+  //Fill IPlaylist2
+  SetLength(IPlaylist2, 1);
+  IPlaylist2[0] := '---';
+
+  //Clear all Selects
+  PlayList := 0;
+  PlayList2 := 0;
+
+  //Load Screen From Theme
+  LoadFromTheme(Theme.PartyOptions);
+
+  Theme.PartyOptions.SelectLevel.oneItemOnly := true;
+  Theme.PartyOptions.SelectLevel.showArrows := true;
+  SelectLevel     := AddSelectSlide(Theme.PartyOptions.SelectLevel, Ini.Difficulty, Theme.ILevel);
+
+  Theme.PartyOptions.SelectPlayList.oneItemOnly := true;
+  Theme.PartyOptions.SelectPlayList.showArrows := true;
+  SelectPlayList  := AddSelectSlide(Theme.PartyOptions.SelectPlayList, PlayList, IPlaylist);
+
+  Theme.PartyOptions.SelectPlayList2.oneItemOnly := true;
+  Theme.PartyOptions.SelectPlayList2.showArrows := true;
+  SelectPlayList2 := AddSelectSlide(Theme.PartyOptions.SelectPlayList2, PlayList2, IPlaylist2);
+
+  Interaction := 0;
+end;
+
+procedure TScreenPartyOptions.SetPlaylist2;
+var
+  I: integer;
+begin
+  case Playlist of
+    0:
+      begin
+        SetLength(IPlaylist2, 1);
+        IPlaylist2[0] := '---';
+      end;
+    1:
+      begin
+        SetLength(IPlaylist2, 0);
+        for I := 0 to high(CatSongs.Song) do
+        begin
+          if (CatSongs.Song[I].Main) then
+          begin
+            SetLength(IPlaylist2, Length(IPlaylist2) + 1);
+            IPlaylist2[high(IPlaylist2)] := CatSongs.Song[I].Artist;
+          end;
+        end;
+
+        if (Length(IPlaylist2) = 0) then
+        begin
+          SetLength(IPlaylist2, 1);
+          IPlaylist2[0] := 'No Categories found';
+        end;
+      end;
+    2:
+      begin
+        if (Length(PlaylistMan.Playlists) > 0) then
+        begin
+          SetLength(IPlaylist2, Length(PlaylistMan.Playlists));
+          PlaylistMan.GetNames(IPlaylist2);
+        end
+        else
+        begin
+          SetLength(IPlaylist2, 1);
+          IPlaylist2[0] := 'No Playlists found';
+        end;
+      end;
+  end;
+
+  Playlist2 := 0;
+  UpdateSelectSlideOptions(Theme.PartyOptions.SelectPlayList2, 2, IPlaylist2, Playlist2);
+end;
+
+procedure TScreenPartyOptions.OnShow;
+begin
+  inherited;
+
+  Party.Clear;
+
+  // check if there are loaded modes
+  if Party.ModesAvailable then
+  begin
+    // modes are loaded
+    Randomize;
+  end
+  else
+  begin // no modes found
+    ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_PLUGINS'));
+    Display.AbortScreenChange;
+  end;
+end;
+
+procedure TScreenPartyOptions.SetAnimationProgress(Progress: real);
+begin
+  {for I := 0 to 6 do
+    SelectS[I].Texture.ScaleW := Progress;}
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenPartyPlayer.pas b/songmanagement/src/screens/UScreenPartyPlayer.pas
new file mode 100644
index 00000000..a7f4d627
--- /dev/null
+++ b/songmanagement/src/screens/UScreenPartyPlayer.pas
@@ -0,0 +1,449 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenPartyPlayer;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  UDisplay,
+  UMusic,
+  UFiles,
+  SysUtils,
+  UThemes;
+
+type
+  TScreenPartyPlayer = class(TMenu)
+    private
+      CountTeams: integer;
+      CountPlayer: array [0..2] of integer;
+
+      SelectTeams:     cardinal;
+      SelectPlayers: array [0..2] of cardinal;
+      procedure UpdateInterface;
+      procedure UpdateParty;
+    public
+      Team1Name: cardinal;
+      Player1Name: cardinal;
+      Player2Name: cardinal;
+      Player3Name: cardinal;
+      Player4Name: cardinal;
+
+      Team2Name: cardinal;
+      Player5Name: cardinal;
+      Player6Name: cardinal;
+      Player7Name: cardinal;
+      Player8Name: cardinal;
+
+      Team3Name: cardinal;
+      Player9Name: cardinal;
+      Player10Name: cardinal;
+      Player11Name: cardinal;
+      Player12Name: cardinal;
+
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+const
+  ITeams:   array[0..1] of UTF8String = ('2', '3');
+  IPlayers: array[0..3] of UTF8String = ('1', '2', '3', '4');
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UIni,
+  UTexture,
+  UParty,
+  UUnicodeUtils,
+  UScreenPartyOptions,
+  ULanguage;
+
+procedure TScreenPartyPlayer.UpdateInterface;
+  var
+    I: integer;
+    Btn: integer;
+begin
+  SelectsS[SelectPlayers[2]].Visible := (CountTeams = 1);
+
+  Btn := 0;
+  for I := 0 to 2 do
+  begin
+    if (CountTeams + 1 >= I) then
+    begin
+      Button[Btn + 0].Visible := true;
+      Button[Btn + 1].Visible := (CountPlayer[I] + 1 >= 1);
+      Button[Btn + 2].Visible := (CountPlayer[I] + 1 >= 2);
+      Button[Btn + 3].Visible := (CountPlayer[I] + 1 >= 3);
+      Button[Btn + 4].Visible := (CountPlayer[I] + 1 >= 4);
+    end
+    else
+    begin
+      Button[Btn + 0].Visible := false;
+      Button[Btn + 1].Visible := false;
+      Button[Btn + 2].Visible := false;
+      Button[Btn + 3].Visible := false;
+      Button[Btn + 4].Visible := false;
+    end;
+    Inc(Btn, 5);
+  end;
+end;
+
+procedure TScreenPartyPlayer.UpdateParty;
+  var
+    I, J: integer;
+begin
+  {//Save PlayerNames
+  for I := 0 to PartySession.Teams.NumTeams-1 do
+  begin
+    PartySession.Teams.Teaminfo[I].Name := PChar(Button[I*5].Text[0].Text);
+    for J := 0 to PartySession.Teams.Teaminfo[I].NumPlayers-1 do
+    begin
+      PartySession.Teams.Teaminfo[I].Playerinfo[J].Name := PChar(Button[I*5 + J+1].Text[0].Text);
+      PartySession.Teams.Teaminfo[I].Playerinfo[J].TimesPlayed := 0;
+    end;
+  end; }
+
+  // add teams to party
+
+  for I := 0 to CountTeams + 1 do
+  begin
+    Party.AddTeam(Button[I * 5].Text[0].Text);
+
+    for J := 0 to CountPlayer[I] do
+      Party.AddPlayer(I, Button[I * 5 + 1 + J].Text[0].Text);
+  end;
+
+  if (Party.ModesAvailable) then
+  begin //mode for current playersetup available
+    FadeTo(@ScreenPartyRounds, SoundLib.Start);
+  end
+  else
+  begin
+    // no mode available for current player setup
+    ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_MODES_FOR_CURRENT_SETUP'));
+    Party.Clear;
+  end;
+end;
+
+function TScreenPartyPlayer.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+  SDL_ModState:  word;
+  procedure IntNext;
+  begin
+    repeat
+      InteractNext;
+    until ((Interactions[Interaction].Typ = iSelectS) and
+      SelectsS[Interactions[Interaction].Num].Visible) or
+      (Button[Interactions[Interaction].Num].Visible);
+  end;
+  procedure IntPrev;
+  begin
+    repeat
+      InteractPrev;
+    until ((Interactions[Interaction].Typ = iSelectS) and
+      SelectsS[Interactions[Interaction].Num].Visible) or
+      (Button[Interactions[Interaction].Num].Visible);
+  end;
+begin
+  Result := true;
+
+  if (PressedDown) then
+    SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT
+        + KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT  + KMOD_RALT)
+  else
+    SDL_ModState := 0;
+
+  // Key Down
+  // check normal keys
+  if (Interactions[Interaction].Typ = iButton) then
+  begin
+    case CharCode of
+      Ord('0')..Ord('9'),
+      Ord('a')..Ord('z'),
+      Ord('A')..Ord('Z'),
+      Ord(' '), Ord('-'), Ord('_'), Ord('!'), Ord(','), Ord('<'), Ord('/'),
+      Ord('*'), Ord('?'), Ord(''''), Ord('"'):
+        begin
+          Button[Interactions[Interaction].Num].Text[0].Text :=
+            Button[Interactions[Interaction].Num].Text[0].Text + UCS4ToUTF8String(CharCode);
+          Exit;
+        end;
+    end;
+
+
+    // check special keys
+    case PressedKey of
+      // Templates for Names Mod
+      SDLK_F1:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[0] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[0];
+         end;
+      SDLK_F2:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[1] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[1];
+         end;
+      SDLK_F3:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[2] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[2];
+         end;
+      SDLK_F4:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[3] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[3];
+         end;
+      SDLK_F5:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[4] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[4];
+         end;
+      SDLK_F6:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[5] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[5];
+         end;
+      SDLK_F7:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[6] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[6];
+         end;
+      SDLK_F8:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[7] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[7];
+         end;
+      SDLK_F9:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[8] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[8];
+         end;
+      SDLK_F10:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[9] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[9];
+         end;
+      SDLK_F11:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[10] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[10];
+         end;
+      SDLK_F12:
+       if (SDL_ModState = KMOD_LALT) then
+         begin
+           Ini.NameTemplate[11] := Button[Interactions[Interaction].Num].Text[0].Text;
+         end
+         else
+         begin
+           Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[11];
+         end;
+
+      SDLK_BACKSPACE:
+        begin
+          Button[Interactions[Interaction].Num].Text[0].DeleteLastLetter;
+        end;
+    end;
+  end;
+
+  case PressedKey of
+    SDLK_ESCAPE:
+      begin
+        Ini.SaveNames;
+        AudioPlayback.PlaySound(SoundLib.Back);
+        FadeTo(@ScreenPartyOptions);
+      end;
+
+    SDLK_RETURN: UpdateParty;
+
+    // Up and Down could be done at the same time,
+    // but I don't want to declare variables inside
+    // functions like this one, called so many times
+    SDLK_DOWN:    IntNext;
+    SDLK_UP:      IntPrev;
+    SDLK_RIGHT:
+      begin
+        if (Interaction in [0,2,8,14]) then
+        begin
+          AudioPlayback.PlaySound(SoundLib.Option);
+          InteractInc;
+
+          UpdateInterface;
+        end;
+      end;
+    SDLK_LEFT:
+      begin
+        if (Interaction in [0,2,8,14]) then
+        begin
+          AudioPlayback.PlaySound(SoundLib.Option);
+          InteractDec;
+
+          UpdateInterface;
+        end;
+      end;
+  end;
+end;
+
+constructor TScreenPartyPlayer.Create;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.PartyPlayer);
+
+  Theme.PartyPlayer.SelectTeams.oneItemOnly := true;
+  Theme.PartyPlayer.SelectTeams.showArrows := true;
+  SelectTeams     := AddSelectSlide(Theme.PartyPlayer.SelectTeams, CountTeams, ITeams);
+
+  Team1Name := AddButton(Theme.PartyPlayer.Team1Name);
+  Theme.PartyPlayer.SelectPlayers1.oneItemOnly := true;
+  Theme.PartyPlayer.SelectPlayers1.showArrows := true;
+  SelectPlayers[0]  := AddSelectSlide(Theme.PartyPlayer.SelectPlayers1, CountPlayer[0], IPlayers);
+
+  AddButton(Theme.PartyPlayer.Player1Name);
+  AddButton(Theme.PartyPlayer.Player2Name);
+  AddButton(Theme.PartyPlayer.Player3Name);
+  AddButton(Theme.PartyPlayer.Player4Name);
+
+  Team2Name := AddButton(Theme.PartyPlayer.Team2Name);
+  Theme.PartyPlayer.SelectPlayers2.oneItemOnly := true;
+  Theme.PartyPlayer.SelectPlayers2.showArrows := true;
+  SelectPlayers[1]  := AddSelectSlide(Theme.PartyPlayer.SelectPlayers2, CountPlayer[1], IPlayers);
+
+  AddButton(Theme.PartyPlayer.Player5Name);
+  AddButton(Theme.PartyPlayer.Player6Name);
+  AddButton(Theme.PartyPlayer.Player7Name);
+  AddButton(Theme.PartyPlayer.Player8Name);
+
+  Team3Name := AddButton(Theme.PartyPlayer.Team3Name);
+  Theme.PartyPlayer.SelectPlayers3.oneItemOnly := true;
+  Theme.PartyPlayer.SelectPlayers3.showArrows := true;
+  SelectPlayers[2]  := AddSelectSlide(Theme.PartyPlayer.SelectPlayers3, CountPlayer[2], IPlayers);
+  
+  AddButton(Theme.PartyPlayer.Player9Name);
+  AddButton(Theme.PartyPlayer.Player10Name);
+  AddButton(Theme.PartyPlayer.Player11Name);
+  AddButton(Theme.PartyPlayer.Player12Name);
+
+  Interaction := 0;
+
+  //Clear Selects
+  CountTeams := 0;
+  CountPlayer[0] := 0;
+  CountPlayer[1] := 0;
+  CountPlayer[2] := 0;
+end;
+
+procedure TScreenPartyPlayer.OnShow;
+var
+  I:    integer;
+begin
+  inherited;
+
+  // Templates for Names Mod
+  for I := 1 to 4 do
+    Button[I].Text[0].Text := Ini.Name[I-1];
+
+  for I := 6 to 9 do
+    Button[I].Text[0].Text := Ini.Name[I-2];
+
+  for I := 11 to 14 do
+    Button[I].Text[0].Text := Ini.Name[I-3];
+
+    Button[0].Text[0].Text := Ini.NameTeam[0];
+    Button[5].Text[0].Text := Ini.NameTeam[1];
+    Button[10].Text[0].Text := Ini.NameTeam[2];
+    // Templates for Names Mod end
+
+  Party.Clear;
+
+  UpdateInterface;
+end;
+
+procedure TScreenPartyPlayer.SetAnimationProgress(Progress: real);
+var
+  I:    integer;
+begin
+  {for I := 0 to high(Button) do
+    Button[I].Texture.ScaleW := Progress;   }
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenPartyRounds.pas b/songmanagement/src/screens/UScreenPartyRounds.pas
new file mode 100644
index 00000000..070c9eb8
--- /dev/null
+++ b/songmanagement/src/screens/UScreenPartyRounds.pas
@@ -0,0 +1,233 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/branches/experimental/Lua/src/screens/UScreenPartyOptions.pas $
+ * $Id: UScreenPartyOptions.pas 2036 2009-12-14 20:59:44Z whiteshark0 $
+ *}
+
+unit UScreenPartyRounds;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  UDisplay,
+  UMusic,
+  UFiles,
+  SysUtils,
+  UThemes;
+
+type
+  TScreenPartyRounds = class(TMenu)
+    private
+      SelectRoundCount: cardinal;
+      SelectRound: array [0..6] of cardinal;
+
+      RoundCount: integer;
+      Round: array [0..6] of integer;
+
+      IModeNames: array of UTF8String;
+      IModeIDs: array of integer;
+
+      procedure UpdateInterface;
+      procedure StartParty;
+    public
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+const
+  IRoundCount:  array[0..5] of UTF8String = ('2', '3', '4', '5', '6', '7');
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UIni,
+  UTexture,
+  ULanguage,
+  UParty,
+  USong,
+  UPlaylist,
+  USongs,
+  UUnicodeUtils;
+
+procedure TScreenPartyRounds.UpdateInterface;
+  var
+    I: integer;
+    ActualRounds: integer;
+begin
+  ActualRounds := RoundCount + 2;
+
+  for I := 0 to High(SelectRound) do
+    SelectsS[SelectRound[I]].Visible := (I < ActualRounds);
+end;
+
+procedure TScreenPartyRounds.StartParty;
+  var
+    GameRounds: ARounds;
+    I: integer;
+begin
+  SetLength(GameRounds, RoundCount + 2);
+
+  for I := 0 to High(GameRounds) do
+    GameRounds[I] := IModeIds[Round[I]];
+
+  // start party game
+  if (Party.StartGame(GameRounds)) then
+  begin
+    FadeTo(@ScreenPartyNewRound, SoundLib.Start);
+  end
+  else
+  begin
+    //error starting party game
+    ScreenPopupError.ShowPopup(Language.Translate('ERROR_CAN_NOT_START_PARTY'));
+  end;
+end;
+
+function TScreenPartyRounds.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenPartyPlayer);
+        end;
+
+      SDLK_RETURN: StartParty;
+
+      // Up and Down could be done at the same time,
+      // but I don't want to declare variables inside
+      // functions like this one, called so many times
+      SDLK_DOWN:    InteractNext;
+      SDLK_UP:      InteractPrev;
+      SDLK_RIGHT:
+        begin
+          AudioPlayback.PlaySound(SoundLib.Option);
+          InteractInc;
+
+          if Interaction = 0 then
+            UpdateInterface;
+        end;
+      SDLK_LEFT:
+        begin
+          AudioPlayback.PlaySound(SoundLib.Option);
+          InteractDec;
+
+          if Interaction = 0 then
+            UpdateInterface;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenPartyRounds.Create;
+  var
+    I: integer;
+begin
+  inherited Create;
+  RoundCount := 5;
+
+  //Load Screen From Theme
+  LoadFromTheme(Theme.PartyRounds);
+
+  Theme.PartyRounds.SelectRoundCount.oneItemOnly := true;
+  Theme.PartyRounds.SelectRoundCount.showArrows := true;
+  SelectRoundCount := AddSelectSlide(Theme.PartyRounds.SelectRoundCount, RoundCount, IRoundCount);
+
+  SetLength(IModeNames, 1);
+  IModeNames[0] := '---';
+  for I := 0 to high(Theme.PartyRounds.SelectRound) do
+  begin
+    Round[I] := 0;
+    Theme.PartyRounds.SelectRound[I].oneItemOnly := true;
+    Theme.PartyRounds.SelectRound[I].showArrows := true;
+    SelectRound[I] := AddSelectSlide(Theme.PartyRounds.SelectRound[I], Round[I], IModeNames);
+  end;
+
+
+  Interaction := 0;
+end;
+
+procedure TScreenPartyRounds.OnShow;
+  var
+    ModeList: AParty_ModeList;
+    I: integer;
+begin
+  inherited;
+
+  // check if there are loaded modes
+  if Party.ModesAvailable then
+  begin
+    UpdateInterface;
+    
+    ModeList := Party.GetAvailableModes;
+    SetLength(IModeNames, Length(ModeList));
+    SetLength(IModeIds, Length(ModeList));
+    for I := 0 to High(ModeList) do
+    begin
+      IModeNames[I] := ModeList[I].Name;
+      IModeIds[I]   := ModeList[I].Index;
+    end;
+
+    for I := 0 to High(SelectRound) do
+      UpdateSelectSlideOptions(Theme.PartyRounds.SelectRound[I] , SelectRound[I], IModeNames, Round[I]);
+  end
+  else
+  begin
+    // no mode available for current player setup
+    ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_MODES_FOR_CURRENT_SETUP'));
+    Party.Clear;
+    Display.AbortScreenChange;
+  end;
+end;
+
+procedure TScreenPartyRounds.SetAnimationProgress(Progress: real);
+begin
+  {for I := 0 to 6 do
+    SelectS[I].Texture.ScaleW := Progress;}
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenPartyScore.pas b/songmanagement/src/screens/UScreenPartyScore.pas
new file mode 100644
index 00000000..62c97161
--- /dev/null
+++ b/songmanagement/src/screens/UScreenPartyScore.pas
@@ -0,0 +1,334 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenPartyScore;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  SysUtils,
+  UMenu,
+  UDisplay,
+  UMusic,
+  UThemes;
+
+type
+  TScreenPartyScore = class(TMenu)
+    public
+      TextScoreTeam1:    cardinal;
+      TextScoreTeam2:    cardinal;
+      TextScoreTeam3:    cardinal;
+      TextNameTeam1:     cardinal;
+      TextNameTeam2:     cardinal;
+      TextNameTeam3:     cardinal;
+      StaticTeam1:       cardinal;
+      StaticTeam1BG:     cardinal;
+      StaticTeam1Deco:   cardinal;
+      StaticTeam2:       cardinal;
+      StaticTeam2BG:     cardinal;
+      StaticTeam2Deco:   cardinal;
+      StaticTeam3:       cardinal;
+      StaticTeam3BG:     cardinal;
+      StaticTeam3Deco:   cardinal;
+      TextWinner:        cardinal;
+
+      DecoTex:          array[0..5] of integer;
+      DecoColor:        array[0..5] of Record
+                                        R, G, B: real;
+                        end;
+
+      MaxScore:          word;
+      
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UParty,
+  ULanguage,
+  UTexture,
+  USkins,
+  UUnicodeUtils;
+
+function TScreenPartyScore.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE,
+      SDLK_RETURN :
+        begin
+          AudioPlayback.PlaySound(SoundLib.Start);
+
+          Party.NextRound; //< go to next round
+
+          if (not Party.GameFinished) then
+          begin
+            FadeTo(@ScreenPartyNewRound);
+          end
+          else
+          begin
+            FadeTo(@ScreenPartyWin);
+          end;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenPartyScore.Create;
+var
+  Tex:  TTexture;
+  R, G, B: real;
+  Color: integer;
+begin
+  inherited Create;
+
+  TextScoreTeam1 := AddText (Theme.PartyScore.TextScoreTeam1);
+  TextScoreTeam2 := AddText (Theme.PartyScore.TextScoreTeam2);
+  TextScoreTeam3 := AddText (Theme.PartyScore.TextScoreTeam3);
+  TextNameTeam1 := AddText (Theme.PartyScore.TextNameTeam1);
+  TextNameTeam2 := AddText (Theme.PartyScore.TextNameTeam2);
+  TextNameTeam3 := AddText (Theme.PartyScore.TextNameTeam3);
+
+  StaticTeam1 := AddStatic (Theme.PartyScore.StaticTeam1);
+  StaticTeam1BG := AddStatic (Theme.PartyScore.StaticTeam1BG);
+  StaticTeam1Deco := AddStatic (Theme.PartyScore.StaticTeam1Deco);
+  StaticTeam2 := AddStatic (Theme.PartyScore.StaticTeam2);
+  StaticTeam2BG := AddStatic (Theme.PartyScore.StaticTeam2BG);
+  StaticTeam2Deco := AddStatic (Theme.PartyScore.StaticTeam2Deco);
+  StaticTeam3 := AddStatic (Theme.PartyScore.StaticTeam3);
+  StaticTeam3BG := AddStatic (Theme.PartyScore.StaticTeam3BG);
+  StaticTeam3Deco := AddStatic (Theme.PartyScore.StaticTeam3Deco);
+
+  TextWinner := AddText (Theme.PartyScore.TextWinner);
+
+  //Load Deco Textures
+  if Theme.PartyScore.DecoTextures.ChangeTextures then
+  begin
+    //Get Color
+    LoadColor(R, G, B, Theme.PartyScore.DecoTextures.FirstColor);
+    Color := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
+    DecoColor[0].R := R;
+    DecoColor[0].G := G;
+    DecoColor[0].B := B;
+
+    //Load Texture
+    Tex := Texture.LoadTexture(
+      Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.FirstTexture),
+      Theme.PartyScore.DecoTextures.FirstTyp, Color);
+    DecoTex[0] := Tex.TexNum;
+
+    //Get Second Color
+    LoadColor(R, G, B, Theme.PartyScore.DecoTextures.SecondColor);
+    Color := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
+    DecoColor[1].R := R;
+    DecoColor[1].G := G;
+    DecoColor[1].B := B;
+
+    //Load Second Texture
+    Tex := Texture.LoadTexture(
+      Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.SecondTexture),
+      Theme.PartyScore.DecoTextures.SecondTyp, Color);
+    DecoTex[1] := Tex.TexNum;
+
+    //Get Third Color
+    LoadColor(R, G, B, Theme.PartyScore.DecoTextures.ThirdColor);
+    Color := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
+    DecoColor[2].R := R;
+    DecoColor[2].G := G;
+    DecoColor[2].B := B;
+
+    //Load Third Texture
+    Tex := Texture.LoadTexture(
+      Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.ThirdTexture),
+      Theme.PartyScore.DecoTextures.ThirdTyp, Color);
+    DecoTex[2] := Tex.TexNum;
+  end;
+
+  LoadFromTheme(Theme.PartyScore);
+end;
+
+procedure TScreenPartyScore.OnShow;
+var
+  Ranking: AParty_TeamRanking;
+begin
+  inherited;
+
+  // indicate that round is finished
+  Party.RoundPlayed;
+
+  // get rankings for current round
+  Ranking := Party.Rounds[Party.CurrentRound].Ranking;
+
+
+  {//Set Statics Length
+  Statics[StaticTeam1].Texture.ScaleW := ScreenSingModi.PlayerInfo.Playerinfo[0].Percentage / 100;
+  Statics[StaticTeam2].Texture.ScaleW := ScreenSingModi.PlayerInfo.Playerinfo[1].Percentage / 100;
+  Statics[StaticTeam3].Texture.ScaleW := ScreenSingModi.PlayerInfo.Playerinfo[2].Percentage / 100;
+
+  //fix: prevents statics from drawn out of bounds.
+  if Statics[StaticTeam1].Texture.ScaleW > 99 then Statics[StaticTeam1].Texture.ScaleW := 99;
+  if Statics[StaticTeam2].Texture.ScaleW > 99 then Statics[StaticTeam2].Texture.ScaleW := 99;
+  if Statics[StaticTeam3].Texture.ScaleW > 99 then Statics[StaticTeam3].Texture.ScaleW := 99; }
+
+  //Set Winnertext
+  Text[TextWinner].Text := Format(Language.Translate('PARTY_SCORE_WINS'), [Party.GetWinnerString(Party.CurrentRound)]);
+
+  if (Length(Party.Teams) >= 1) then
+  begin
+    Text[TextScoreTeam1].Text := InttoStr(Party.Teams[0].Score);
+    Text[TextNameTeam1].Text := Utf8String(Party.Teams[0].Name);
+
+    //Set Deco Texture
+    if Theme.PartyScore.DecoTextures.ChangeTextures then
+    begin
+      if (Length(Ranking) >= 1) and (Ranking[0].Rank >= 1) and (Ranking[0].Rank <= Length(DecoTex)) then
+      begin
+        Statics[StaticTeam1Deco].Texture.TexNum := DecoTex[Ranking[0].Rank-1];
+        Statics[StaticTeam1Deco].Texture.ColR := DecoColor[Ranking[0].Rank-1].R;
+        Statics[StaticTeam1Deco].Texture.ColG := DecoColor[Ranking[0].Rank-1].G;
+        Statics[StaticTeam1Deco].Texture.ColB := DecoColor[Ranking[0].Rank-1].B;
+      end;
+    end;
+
+    Text[TextScoreTeam1].Visible := true;
+    Text[TextNameTeam1].Visible := true;
+    Statics[StaticTeam1].Visible := true;
+    Statics[StaticTeam1BG].Visible := true;
+    Statics[StaticTeam1Deco].Visible := true;
+  end
+  else
+  begin
+    Text[TextScoreTeam1].Visible := false;
+    Text[TextNameTeam1].Visible := false;
+    Statics[StaticTeam1].Visible := false;
+    Statics[StaticTeam1BG].Visible := false;
+    Statics[StaticTeam1Deco].Visible := false;
+  end;
+
+  if (Length(Party.Teams) >= 2) then
+  begin
+    Text[TextScoreTeam2].Text := InttoStr(Party.Teams[1].Score);
+    Text[TextNameTeam2].Text := UTF8String(Party.Teams[1].Name);
+
+    //Set Deco Texture
+    if Theme.PartyScore.DecoTextures.ChangeTextures then
+    begin
+      if (Length(Ranking) >= 2) and (Ranking[1].Rank >= 1) and (Ranking[1].Rank <= Length(DecoTex)) then
+      begin
+        Statics[StaticTeam2Deco].Texture.TexNum := DecoTex[Ranking[1].Rank-1];
+        Statics[StaticTeam2Deco].Texture.ColR := DecoColor[Ranking[1].Rank-1].R;
+        Statics[StaticTeam2Deco].Texture.ColG := DecoColor[Ranking[1].Rank-1].G;
+        Statics[StaticTeam2Deco].Texture.ColB := DecoColor[Ranking[1].Rank-1].B;
+      end;
+    end;
+
+    Text[TextScoreTeam2].Visible := true;
+    Text[TextNameTeam2].Visible := true;
+    Statics[StaticTeam2].Visible := true;
+    Statics[StaticTeam2BG].Visible := true;
+    Statics[StaticTeam2Deco].Visible := true;
+  end
+  else
+  begin
+    Text[TextScoreTeam2].Visible := false;
+    Text[TextNameTeam2].Visible := false;
+    Statics[StaticTeam2].Visible := false;
+    Statics[StaticTeam2BG].Visible := false;
+    Statics[StaticTeam2Deco].Visible := false;
+  end;
+
+  if (Length(Party.Teams) >= 3) then
+  begin
+    Text[TextScoreTeam3].Text := InttoStr(Party.Teams[2].Score);
+    Text[TextNameTeam3].Text := UTF8String(Party.Teams[2].Name);
+
+    //Set Deco Texture
+    if Theme.PartyScore.DecoTextures.ChangeTextures then
+    begin
+      if (Length(Ranking) >= 3) and (Ranking[2].Rank >= 1) and (Ranking[2].Rank <= Length(DecoTex)) then
+      begin
+        Statics[StaticTeam3Deco].Texture.TexNum := DecoTex[Ranking[2].Rank-1];
+        Statics[StaticTeam3Deco].Texture.ColR := DecoColor[Ranking[2].Rank-1].R;
+        Statics[StaticTeam3Deco].Texture.ColG := DecoColor[Ranking[2].Rank-1].G;
+        Statics[StaticTeam3Deco].Texture.ColB := DecoColor[Ranking[2].Rank-1].B;
+      end;
+    end;
+
+    Text[TextScoreTeam3].Visible := true;
+    Text[TextNameTeam3].Visible := true;
+    Statics[StaticTeam3].Visible := true;
+    Statics[StaticTeam3BG].Visible := true;
+    Statics[StaticTeam3Deco].Visible := true;
+  end
+  else
+  begin
+    Text[TextScoreTeam3].Visible := false;
+    Text[TextNameTeam3].Visible := false;
+    Statics[StaticTeam3].Visible := false;
+    Statics[StaticTeam3BG].Visible := false;
+    Statics[StaticTeam3Deco].Visible := false;
+  end;
+
+  //start Background-Music
+  SoundLib.StartBgMusic;
+end;
+
+procedure TScreenPartyScore.SetAnimationProgress(Progress: real);
+begin
+  {if (ScreenSingModi.PlayerInfo.NumPlayers >= 1) then
+    Statics[StaticTeam1].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[0].Percentage / 100;
+  if (ScreenSingModi.PlayerInfo.NumPlayers >= 2) then
+    Statics[StaticTeam2].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[1].Percentage / 100;
+  if (ScreenSingModi.PlayerInfo.NumPlayers >= 3) then
+    Statics[StaticTeam3].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[2].Percentage / 100;}
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenPartyWin.pas b/songmanagement/src/screens/UScreenPartyWin.pas
new file mode 100644
index 00000000..ed8d017c
--- /dev/null
+++ b/songmanagement/src/screens/UScreenPartyWin.pas
@@ -0,0 +1,295 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenPartyWin;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  SysUtils,
+  UMenu,
+  UDisplay,
+  UMusic,
+  UThemes;
+
+type
+  TScreenPartyWin = class(TMenu)
+    public
+      TextScoreTeam1:    cardinal;
+      TextScoreTeam2:    cardinal;
+      TextScoreTeam3:    cardinal;
+      TextNameTeam1:     cardinal;
+      TextNameTeam2:     cardinal;
+      TextNameTeam3:     cardinal;
+      StaticTeam1:       cardinal;
+      StaticTeam1BG:     cardinal;
+      StaticTeam1Deco:   cardinal;
+      StaticTeam2:       cardinal;
+      StaticTeam2BG:     cardinal;
+      StaticTeam2Deco:   cardinal;
+      StaticTeam3:       cardinal;
+      StaticTeam3BG:     cardinal;
+      StaticTeam3Deco:   cardinal;
+      TextWinner:        cardinal;
+
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UParty,
+  ULanguage,
+  UUnicodeUtils;
+
+function TScreenPartyWin.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE,
+      SDLK_RETURN :
+        begin
+          AudioPlayback.PlaySound(SoundLib.Start);
+          FadeTo(@ScreenMain);
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenPartyWin.Create;
+begin
+  inherited Create;
+
+  TextScoreTeam1 := AddText (Theme.PartyWin.TextScoreTeam1);
+  TextScoreTeam2 := AddText (Theme.PartyWin.TextScoreTeam2);
+  TextScoreTeam3 := AddText (Theme.PartyWin.TextScoreTeam3);
+  TextNameTeam1 := AddText (Theme.PartyWin.TextNameTeam1);
+  TextNameTeam2 := AddText (Theme.PartyWin.TextNameTeam2);
+  TextNameTeam3 := AddText (Theme.PartyWin.TextNameTeam3);
+
+  StaticTeam1 := AddStatic (Theme.PartyWin.StaticTeam1);
+  StaticTeam1BG := AddStatic (Theme.PartyWin.StaticTeam1BG);
+  StaticTeam1Deco := AddStatic (Theme.PartyWin.StaticTeam1Deco);
+  StaticTeam2 := AddStatic (Theme.PartyWin.StaticTeam2);
+  StaticTeam2BG := AddStatic (Theme.PartyWin.StaticTeam2BG);
+  StaticTeam2Deco := AddStatic (Theme.PartyWin.StaticTeam2Deco);
+  StaticTeam3 := AddStatic (Theme.PartyWin.StaticTeam3);
+  StaticTeam3BG := AddStatic (Theme.PartyWin.StaticTeam3BG);
+  StaticTeam3Deco := AddStatic (Theme.PartyWin.StaticTeam3Deco);
+
+  TextWinner := AddText (Theme.PartyWin.TextWinner);
+
+  LoadFromTheme(Theme.PartyWin);
+end;
+
+procedure TScreenPartyWin.OnShow;
+var
+ I: integer;
+ Ranking: AParty_TeamRanking;
+
+  Function GetTeamColor(Team: integer): cardinal;
+  var
+    NameString: string;
+  begin
+    NameString := 'P' + InttoStr(Team+1) + 'Dark';
+
+    Result := ColorExists(NameString);
+  end;
+
+begin
+  inherited;
+
+  // get team ranking
+  // Ranking is sorted by score
+  Ranking := Party.GetTeamRanking;
+
+  //Set Winnertext
+  Text[TextWinner].Text := Format(Language.Translate('PARTY_SCORE_WINS'), [Party.GetWinnerString(-1)]);
+  if (Length(Party.Teams) >= 1) then
+  begin
+    Text[TextScoreTeam1].Text := IntToStr(Party.Teams[Ranking[0].Team].Score);
+    Text[TextNameTeam1].Text := Party.Teams[Ranking[0].Team].Name;
+
+    Text[TextScoreTeam1].Visible := true;
+    Text[TextNameTeam1].Visible := true;
+    Statics[StaticTeam1].Visible := true;
+    Statics[StaticTeam1BG].Visible := true;
+    Statics[StaticTeam1Deco].Visible := true;
+
+    //Set Static Color to Team Color
+    if (Theme.PartyWin.StaticTeam1BG.Color = 'TeamColor') then
+    begin
+      I := GetTeamColor(Ranking[0].Team);
+      if (I <> -1) then
+      begin
+        Statics[StaticTeam1BG].Texture.ColR := Color[I].RGB.R;
+        Statics[StaticTeam1BG].Texture.ColG := Color[I].RGB.G;
+        Statics[StaticTeam1BG].Texture.ColB := Color[I].RGB.B;
+      end;
+    end;
+
+    if (Theme.PartyWin.StaticTeam1.Color = 'TeamColor') then
+    begin
+      I := GetTeamColor(Ranking[0].Team);
+      if (I <> -1) then
+      begin
+        Statics[StaticTeam1].Texture.ColR := Color[I].RGB.R;
+        Statics[StaticTeam1].Texture.ColG := Color[I].RGB.G;
+        Statics[StaticTeam1].Texture.ColB := Color[I].RGB.B;
+      end;
+    end;
+  end
+  else
+  begin
+    Text[TextScoreTeam1].Visible := false;
+    Text[TextNameTeam1].Visible := false;
+    Statics[StaticTeam1].Visible := false;
+    Statics[StaticTeam1BG].Visible := false;
+    Statics[StaticTeam1Deco].Visible := false;
+  end;
+
+  if (Length(Party.Teams) >= 2) then
+  begin
+    Text[TextScoreTeam2].Text := IntToStr(Party.Teams[Ranking[1].Team].Score);
+    Text[TextNameTeam2].Text := Party.Teams[Ranking[1].Team].Name;
+
+    Text[TextScoreTeam2].Visible := true;
+    Text[TextNameTeam2].Visible := true;
+    Statics[StaticTeam2].Visible := true;
+    Statics[StaticTeam2BG].Visible := true;
+    Statics[StaticTeam2Deco].Visible := true;
+
+    //Set Static Color to Team Color
+    if (Theme.PartyWin.StaticTeam2BG.Color = 'TeamColor') then
+    begin
+      I := GetTeamColor(Ranking[1].Team);
+      if (I <> -1) then
+      begin
+        Statics[StaticTeam2BG].Texture.ColR := Color[I].RGB.R;
+        Statics[StaticTeam2BG].Texture.ColG := Color[I].RGB.G;
+        Statics[StaticTeam2BG].Texture.ColB := Color[I].RGB.B;
+      end;
+    end;
+
+    if (Theme.PartyWin.StaticTeam2.Color = 'TeamColor') then
+    begin
+      I := GetTeamColor(Ranking[1].Team);
+      if (I <> -1) then
+      begin
+        Statics[StaticTeam2].Texture.ColR := Color[I].RGB.R;
+        Statics[StaticTeam2].Texture.ColG := Color[I].RGB.G;
+        Statics[StaticTeam2].Texture.ColB := Color[I].RGB.B;
+      end;
+    end;
+  end
+  else
+  begin
+    Text[TextScoreTeam2].Visible := false;
+    Text[TextNameTeam2].Visible := false;
+    Statics[StaticTeam2].Visible := false;
+    Statics[StaticTeam2BG].Visible := false;
+    Statics[StaticTeam2Deco].Visible := false;
+  end;
+
+  if (Length(Party.Teams) >= 3) then
+  begin
+    Text[TextScoreTeam3].Text := IntToStr(Party.Teams[Ranking[2].Team].Score);
+    Text[TextNameTeam3].Text := Party.Teams[Ranking[2].Team].Name;
+
+    Text[TextScoreTeam3].Visible := true;
+    Text[TextNameTeam3].Visible := true;
+    Statics[StaticTeam3].Visible := true;
+    Statics[StaticTeam3BG].Visible := true;
+    Statics[StaticTeam3Deco].Visible := true;
+
+    //Set Static Color to Team Color
+    if (Theme.PartyWin.StaticTeam3BG.Color = 'TeamColor') then
+    begin
+      I := GetTeamColor(Ranking[2].Team);
+      if (I <> -1) then
+      begin
+        Statics[StaticTeam3BG].Texture.ColR := Color[I].RGB.R;
+        Statics[StaticTeam3BG].Texture.ColG := Color[I].RGB.G;
+        Statics[StaticTeam3BG].Texture.ColB := Color[I].RGB.B;
+      end;
+    end;
+
+    if (Theme.PartyWin.StaticTeam3.Color = 'TeamColor') then
+    begin
+      I := GetTeamColor(Ranking[2].Team);
+      if (I <> -1) then
+      begin
+        Statics[StaticTeam3].Texture.ColR := Color[I].RGB.R;
+        Statics[StaticTeam3].Texture.ColG := Color[I].RGB.G;
+        Statics[StaticTeam3].Texture.ColB := Color[I].RGB.B;
+      end;
+    end;
+  end
+  else
+  begin
+    Text[TextScoreTeam3].Visible := false;
+    Text[TextNameTeam3].Visible := false;
+    Statics[StaticTeam3].Visible := false;
+    Statics[StaticTeam3BG].Visible := false;
+    Statics[StaticTeam3Deco].Visible := false;
+  end;
+end;
+
+procedure TScreenPartyWin.SetAnimationProgress(Progress: real);
+begin
+  {if (ScreenSingModi.PlayerInfo.NumPlayers >= 1) then
+    Statics[StaticTeam1].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[0].Score / maxScore;
+  if (ScreenSingModi.PlayerInfo.NumPlayers >= 2) then
+    Statics[StaticTeam2].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[1].Score / maxScore;
+  if (ScreenSingModi.PlayerInfo.NumPlayers >= 3) then
+    Statics[StaticTeam3].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[2].Score / maxScore;}
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenPopup.pas b/songmanagement/src/screens/UScreenPopup.pas
new file mode 100644
index 00000000..fdf4a69c
--- /dev/null
+++ b/songmanagement/src/screens/UScreenPopup.pas
@@ -0,0 +1,308 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenPopup;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  SysUtils,
+  UMenu,
+  UMusic,
+  UFiles,
+  UThemes;
+
+type
+  TPopupCheckHandler = procedure(Value: boolean; Data: Pointer);
+
+  TScreenPopupCheck = class(TMenu)
+    private
+      fHandler: TPopupCheckHandler;
+      fHandlerData: Pointer;
+
+    public
+      Visible: boolean; // whether the menu should be drawn
+
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure ShowPopup(const Msg: UTF8String; Handler: TPopupCheckHandler;
+          HandlerData: Pointer; DefaultValue: boolean = false);
+      function Draw: boolean; override;
+  end;
+
+type
+  TScreenPopup = class(TMenu)
+    {
+    private
+      CurMenu: byte; //Num of the cur. Shown Menu
+    }
+    public
+      Visible: boolean; //Whether the Menu should be Drawn
+
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure OnHide; override;
+      procedure ShowPopup(const Msg: UTF8String);
+      function Draw: boolean; override;
+  end;
+
+  TScreenPopupError = class(TScreenPopup)
+    public
+      constructor Create;
+  end;
+
+  TScreenPopupInfo = class(TScreenPopup)
+    public
+      constructor Create;
+  end;
+
+var
+  //ISelections: array of string;
+  SelectValue: integer;
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UIni,
+  UTexture,
+  ULanguage,
+  UParty,
+  UPlaylist,
+  UDisplay,
+  UUnicodeUtils;
+
+{ TScreenPopupCheck }
+
+function TScreenPopupCheck.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+  Value: boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          Value := false;
+          Visible := false;
+          Result := false;
+        end;
+
+      SDLK_RETURN:
+        begin
+          Value := (Interaction = 0);
+          Visible := false;
+          Result := false;
+        end;
+
+      SDLK_DOWN:  InteractNext;
+      SDLK_UP:    InteractPrev;
+ 
+      SDLK_RIGHT: InteractNext;
+      SDLK_LEFT:  InteractPrev;
+    end;
+  end;
+
+  if (not Result) then
+  begin
+    if (@fHandler <> nil) then
+      fHandler(Value, fHandlerData);
+  end;
+end;
+
+constructor TScreenPopupCheck.Create;
+begin
+  inherited Create;
+
+  fHandler := nil;
+  fHandlerData := nil;
+
+  AddText(Theme.CheckPopup.TextCheck);
+  
+  LoadFromTheme(Theme.CheckPopup);
+
+  AddButton(Theme.CheckPopup.Button1);
+  if (Length(Button[0].Text) = 0) then
+    AddButtonText(14, 20, 'Button 1');
+
+  AddButton(Theme.CheckPopup.Button2);
+  if (Length(Button[1].Text) = 0) then
+    AddButtonText(14, 20, 'Button 2');
+
+  Interaction := 0;
+end;
+
+function TScreenPopupCheck.Draw: boolean;
+begin
+  Result := inherited Draw;
+end;
+
+procedure TScreenPopupCheck.OnShow;
+begin
+  inherited;
+end;
+
+procedure TScreenPopupCheck.ShowPopup(const Msg: UTF8String; Handler: TPopupCheckHandler;
+    HandlerData: Pointer; DefaultValue: boolean);
+begin
+  if (DefaultValue) then
+    Interaction := 0
+  else
+    Interaction := 1;
+  Visible := true;  //Set Visible
+  fHandler := Handler;
+  fHandlerData := HandlerData;
+
+  Text[0].Text := Language.Translate(msg);
+
+  Button[0].Visible := true;
+  Button[1].Visible := true;
+
+  Button[0].Text[0].Text := Language.Translate('SONG_MENU_YES');
+  Button[1].Text[0].Text := Language.Translate('SONG_MENU_NO');
+
+  Background.OnShow
+end;
+
+{ TScreenPopup }
+
+function TScreenPopup.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+
+    case PressedKey of
+      SDLK_Q:
+        begin
+          Result := false;
+        end;
+
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          Visible := false;
+          Result := false;
+        end;
+
+      SDLK_RETURN:
+        begin
+          Visible := false;
+          Result := false;
+        end;
+
+      SDLK_DOWN:    InteractNext;
+      SDLK_UP:      InteractPrev;
+
+      SDLK_RIGHT: InteractNext;
+      SDLK_LEFT: InteractPrev;
+    end;
+  end;
+end;
+
+constructor TScreenPopup.Create;
+begin
+  inherited Create;
+
+  AddText(Theme.ErrorPopup.TextError);
+
+  LoadFromTheme(Theme.ErrorPopup);
+
+  AddButton(Theme.ErrorPopup.Button1);
+  if (Length(Button[0].Text) = 0) then
+    AddButtonText(14, 20, 'Button 1');
+
+  Interaction := 0;
+end;
+
+function TScreenPopup.Draw: boolean;
+begin
+  Draw := inherited Draw;
+end;
+
+procedure TScreenPopup.OnShow;
+begin
+  inherited;
+
+end;
+
+procedure TScreenPopup.OnHide;
+begin
+end;
+
+procedure TScreenPopup.ShowPopup(const Msg: UTF8String);
+begin
+  Interaction := 0; //Reset Interaction
+  Visible := true;  //Set Visible
+  Background.OnShow;
+
+{  //dirty hack... Text[0] is invisible for some strange reason
+  for i:=1 to high(Text) do
+    if i-1 <= high(msg) then
+    begin
+      Text[i].Visible := true;
+      Text[i].Text := msg[i-1];
+    end
+    else
+    begin
+      Text[i].Visible := false;
+    end;}
+  Text[0].Text := msg;
+
+  Button[0].Visible := true;
+
+  Button[0].Text[0].Text := 'OK';
+end;
+
+{ TScreenPopupError }
+
+constructor TScreenPopupError.Create;
+begin
+  inherited;
+  Text[1].Text := Language.Translate('MSG_ERROR_TITLE');
+end;
+
+{ TScreenPopupInfo }
+
+constructor TScreenPopupInfo.Create;
+begin
+  inherited;
+  Text[1].Text := Language.Translate('MSG_INFO_TITLE');
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenScore.pas b/songmanagement/src/screens/UScreenScore.pas
new file mode 100644
index 00000000..de7675bf
--- /dev/null
+++ b/songmanagement/src/screens/UScreenScore.pas
@@ -0,0 +1,1187 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenScore;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  SysUtils,
+  UDisplay,
+  UMusic,
+  USongs,
+  UThemes,
+  gl,
+  math,
+  UTexture;
+
+const
+  ZBars:            real = 0.8;   // Z value for the bars
+  ZRatingPic:       real = 0.8;   // Z value for the rating pictures
+
+  EaseOut_MaxSteps: real = 10;    // that's the speed of the bars (10 is fast | 100 is slower)
+
+  BarRaiseSpeed:    cardinal = 14; // Time for raising the bar one step higher (in ms)
+
+type
+  TScoreBarType = (sbtScore, sbtLine, sbtGolden);
+  TPlayerScoreScreenTexture = record            // holds all colorized textures for up to 6 players
+    //Bar textures
+    Score_NoteBarLevel_Dark:     TTexture;      // Note
+    Score_NoteBarRound_Dark:     TTexture;      // that's the round thing on top
+
+    Score_NoteBarLevel_Light:    TTexture;      // LineBonus | Phrasebonus
+    Score_NoteBarRound_Light:    TTexture;
+
+    Score_NoteBarLevel_Lightest: TTexture;      // GoldenNotes
+    Score_NoteBarRound_Lightest: TTexture;
+
+    Player_Id_Box: TTexture;                    // boxes with player numbers
+  end;
+
+  TPlayerScoreScreenData = record               // holds the positions and other data
+    Bar_Y:                  real;
+    Bar_Actual_Height:      real;               // this one holds the actual height of the bar, while we animate it
+    BarScore_ActualHeight:  real;
+    BarLine_ActualHeight:   real;
+    BarGolden_ActualHeight: real;
+  end;
+
+  TPlayerScoreRatingPics = record               // a fine array of the rating pictures
+    RateEaseStep:  integer;
+    RateEaseValue: real;
+  end;
+
+  { hold maps of players to the different positions }
+  TPlayerPositionMap = record
+    Position: byte; // 1..6: Position of Player; 0: no position (e.g. too little screens)
+    Screen: byte;   // 0 - Screen 1; 1 - Screen 2
+    BothScreens: boolean; // true if player is drawn on both screens
+  end;
+  APlayerPositionMap = array of TPlayerPositionMap;
+
+  { textures for playerstatics of seconds screen players }
+  TPlayerStaticTexture = record
+    Tex: TTexture;    
+  end;
+
+  TScreenScore = class(TMenu)
+    private
+      { holds position and screen of players(index)
+        set by calling MapPlayerstoPosition() }
+      PlayerPositionMap: APlayerPositionMap;
+
+      BarTime:            cardinal;
+
+      aPlayerScoreScreenTextures: array[1..6] of TPlayerScoreScreenTexture;
+      aPlayerScoreScreenDatas:    array[1..6] of TPlayerScoreScreenData;
+      aPlayerScoreScreenRatings:  array[1..6] of TPlayerScoreRatingPics;
+
+      BarScore_EaseOut_Step:  real;
+      BarPhrase_EaseOut_Step: real;
+      BarGolden_EaseOut_Step: real;
+
+      TextArtist:             integer;
+      TextTitle:              integer;
+
+      TextArtistTitle:        integer;
+
+      TextName:             array[1..6] of integer;
+      TextScore:            array[1..6] of integer;
+
+      TextNotes:            array[1..6] of integer;
+      TextNotesScore:       array[1..6] of integer;
+      TextLineBonus:        array[1..6] of integer;
+      TextLineBonusScore:   array[1..6] of integer;
+      TextGoldenNotes:      array[1..6] of integer;
+      TextGoldenNotesScore: array[1..6] of integer;
+      TextTotal:            array[1..6] of integer;
+      TextTotalScore:       array[1..6] of integer;
+
+      PlayerStatic:         array[1..6] of array of integer;
+      { texture pairs for swapping when screens = 2
+        first array level: index of player ( actually this is a position
+          1    - Player 1 if PlayersPlay = 1 <- we don't need swapping here
+          2..3 - Player 1 and 2 or 3 and 4 if PlayersPlay = 2 or 4
+          4..6 - Player 1 - 3 or 4 - 6 if PlayersPlay = 3 or 6 )
+        second array level: different playerstatics for positions
+        third array level: texture for screen 1 or 2 }
+      PlayerStaticTextures: array[1..6] of array of array [1..2] of TPlayerStaticTexture;
+      PlayerTexts:          array[1..6] of array of integer;
+
+      StaticBoxLightest:    array[1..6] of integer;
+      StaticBoxLight:       array[1..6] of integer;
+      StaticBoxDark:        array[1..6] of integer;
+      { texture pairs for swapping when screens = 2
+        for boxes
+        first array level: index of player ( actually this is a position
+          1    - Player 1 if PlayersPlay = 1 <- we don't need swapping here
+          2..3 - Player 1 and 2 or 3 and 4 if PlayersPlay = 2 or 4
+          4..6 - Player 1 - 3 or 4 - 6 if PlayersPlay = 3 or 6 )
+        second array level: different boxes for positions (0: lightest; 1: light; 2: dark)
+        third array level: texture for screen 1 or 2 }
+      PlayerBoxTextures: array[1..6] of array[0..2] of array [1..2] of TPlayerStaticTexture;
+
+      StaticBackLevel:      array[1..6] of integer;
+      StaticBackLevelRound: array[1..6] of integer;
+      StaticLevel:          array[1..6] of integer;
+      StaticLevelRound:     array[1..6] of integer;
+
+      { statics with players ids }
+      StaticPlayerIdBox:    array[1..6] of integer;
+      TexturePlayerIdBox:   array[1..6] of TTexture;
+
+      Animation:            real;
+
+      TextScore_ActualValue:  array[1..6] of integer;
+      TextPhrase_ActualValue: array[1..6] of integer;
+      TextGolden_ActualValue: array[1..6] of integer;
+
+      procedure MapPlayersToPosition;
+
+      procedure FillPlayer(Item, P: integer);
+      procedure FillPlayerItems(PlayerNumber: integer);
+
+      procedure UpdateAnimation;
+      {****
+       * helpers for bar easing
+       *}
+      procedure EaseBarIn(PlayerNumber: integer; BarType: TScoreBarType);
+      procedure EaseScoreIn(PlayerNumber: integer; ScoreType: TScoreBarType);
+
+      procedure DrawPlayerBars;
+
+      procedure DrawBar(BarType: TScoreBarType; PlayerNumber: integer; BarStartPosY: single; NewHeight: real);
+
+      {****
+       * helpers for rating picture
+       *}
+      procedure ShowRating(PlayerNumber: integer);
+      function  CalculateBouncing(PlayerNumber: integer): real;
+      procedure DrawRating(PlayerNumber: integer; Rating: integer);
+
+      { for player static texture swapping }
+      procedure LoadSwapTextures;
+      procedure SwapToScreen(Screen: integer);
+    public
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      function ParseMouse(MouseButton: Integer; BtnDown: Boolean; X, Y: integer): boolean; override;
+      procedure OnShow; override;
+      procedure OnShowFinish; override;
+      function Draw: boolean; override;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UScreenSong,
+  UMenuStatic,
+  UTime,
+  UIni,
+  USkins,
+  ULog,
+  ULanguage,
+  UNote,
+  UUnicodeUtils;
+
+
+function TScreenScore.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE,
+      SDLK_RETURN:
+        begin
+          FadeTo(@ScreenTop5);
+          Exit;
+        end;
+
+      SDLK_SYSREQ:
+        begin
+          Display.SaveScreenShot;
+        end;
+    end;
+  end;
+end;
+
+function TScreenScore.ParseMouse(MouseButton: Integer; BtnDown: Boolean; X, Y: integer): boolean;
+begin
+  Result := True;
+  if (MouseButton = SDL_BUTTON_LEFT) and BtnDown then begin
+    //left-click anywhere sends return
+    ParseInput(SDLK_RETURN, 0, true);
+  end;
+end;
+
+procedure TScreenScore.LoadSwapTextures;
+  var
+    P, I: integer;
+    PlayerNum, PlayerNum2: integer;
+    Color: string;
+    R, G, B: real;
+    StaticNum: integer;
+    ThemeStatic: TThemeStatic;
+begin
+  { we only need to load swapping textures if in dualscreen mode }
+  if Screens = 2 then
+  begin
+    { load swapping textures for custom statics }
+    for P := low(PlayerStatic) to High(PlayerStatic) do
+    begin
+      SetLength(PlayerStaticTextures[P], Length(PlayerStatic[P]));
+
+      { get the players that actually are on this position }
+      case P of
+        1: begin
+          PlayerNum := 1;
+          PlayerNum2 := 1;
+        end;
+
+        2, 3: begin
+          PlayerNum := P - 1;
+          PlayerNum2 := PlayerNum + 2;
+        end;
+
+        4..6: begin
+          PlayerNum := P - 3;
+          PlayerNum2 := PlayerNum + 3;
+        end;
+      end;
+
+      for I := 0 to High(PlayerStatic[P]) do
+      begin
+        // copy current statics texture to texture for screen 1
+        PlayerStaticTextures[P, I, 1].Tex := Statics[PlayerStatic[P, I]].Texture;
+
+        // fallback to first screen texture for 2nd screen
+        PlayerStaticTextures[P, I, 2].Tex := PlayerStaticTextures[P, I, 1].Tex;
+
+        { texture for second screen }
+        { we only change color for statics with playercolor
+          and with Texture type colorized
+          also we don't need to swap for one player position }
+        if (P <> 1) and
+           (Theme.Score.PlayerStatic[P, I].Typ = Texture_Type_Colorized) and
+           (Length(Theme.Score.PlayerStatic[P, I].Color) >= 2) and
+           (copy(Theme.Score.PlayerStatic[P, I].Color, 1, 2) = 'P' + IntToStr(PlayerNum)) then
+        begin
+          // get the color
+          Color := Theme.Score.PlayerStatic[P, I].Color;
+          Color[2] := IntToStr(PlayerNum2)[1];
+          LoadColor(R, G, B, Color);
+
+          with Theme.Score.PlayerStatic[P, I] do
+            PlayerStaticTextures[P, I, 2].Tex := Texture.GetTexture(Skin.GetTextureFileName(Tex), Typ, RGBFloatToInt(R, G, B));
+
+          PlayerStaticTextures[P, I, 2].Tex.X := Statics[PlayerStatic[P, I]].Texture.X;
+          PlayerStaticTextures[P, I, 2].Tex.Y := Statics[PlayerStatic[P, I]].Texture.Y;
+          PlayerStaticTextures[P, I, 2].Tex.W := Statics[PlayerStatic[P, I]].Texture.W;
+          PlayerStaticTextures[P, I, 2].Tex.H := Statics[PlayerStatic[P, I]].Texture.H;
+        end;
+      end;
+    end;
+
+    { load swap textures for boxes }
+    for P := low(PlayerBoxTextures) to High(PlayerBoxTextures) do
+    begin
+      { get the players that actually are on this position }
+      case P of
+        1: begin
+          PlayerNum := 1;
+          PlayerNum2 := 1;
+        end;
+
+        2, 3: begin
+          PlayerNum := P - 1;
+          PlayerNum2 := PlayerNum + 2;
+        end;
+
+        4..6: begin
+          PlayerNum := P - 3;
+          PlayerNum2 := PlayerNum + 3;
+        end;
+      end;
+
+      for I := 0 to High(PlayerBoxTextures[P]) do
+      begin
+        case I of
+          0: begin
+            StaticNum := StaticBoxLightest[P];
+            ThemeStatic := Theme.Score.StaticBoxLightest[P];
+          end;
+          1: begin
+            StaticNum := StaticBoxLight[P];
+            ThemeStatic := Theme.Score.StaticBoxLight[P];
+          end;
+          2: begin
+            StaticNum := StaticBoxDark[P];
+            ThemeStatic := Theme.Score.StaticBoxDark[P];
+          end;
+        end;
+        // copy current statics texture to texture for screen 1
+        PlayerBoxTextures[P, I, 1].Tex := Statics[StaticNum].Texture;
+
+        // fallback to first screen texture for 2nd screen
+        PlayerBoxTextures[P, I, 2].Tex := PlayerBoxTextures[P, I, 1].Tex;
+
+        { texture for second screen }
+        { we only change color for statics with playercolor
+          and with Texture type colorized
+          also we don't need to swap for one player position }
+        if (P <> 1) and
+           (ThemeStatic.Typ = Texture_Type_Colorized) and
+           (Length(ThemeStatic.Color) >= 2) and
+           (copy(ThemeStatic.Color, 1, 2) = 'P' + IntToStr(PlayerNum)) then
+        begin
+          // get the color
+          Color := ThemeStatic.Color;
+          Color[2] := IntToStr(PlayerNum2)[1];
+          LoadColor(R, G, B, Color);
+
+          with ThemeStatic do
+            PlayerBoxTextures[P, I, 2].Tex := Texture.GetTexture(Skin.GetTextureFileName(Tex), Typ, RGBFloatToInt(R, G, B));
+
+          PlayerBoxTextures[P, I, 2].Tex.X := Statics[StaticNum].Texture.X;
+          PlayerBoxTextures[P, I, 2].Tex.Y := Statics[StaticNum].Texture.Y;
+          PlayerBoxTextures[P, I, 2].Tex.W := Statics[StaticNum].Texture.W;
+          PlayerBoxTextures[P, I, 2].Tex.H := Statics[StaticNum].Texture.H;
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TScreenScore.SwapToScreen(Screen: integer);
+  var
+    P, I: integer;
+begin
+  { if screens = 2 and playerplay <= 3 the 2nd screen shows the
+    textures of screen 1 }
+  if (PlayersPlay <= 3) and (Screen = 2) then
+    Screen := 1;
+
+  { set correct box textures }
+  for I := 0 to High(PlayerPositionMap) do
+  begin
+    if (PlayerPositionMap[I].Position > 0) and ((ScreenAct = PlayerPositionMap[I].Screen) or (PlayerPositionMap[I].BothScreens)) then
+    begin
+      // we just set the texture specific stuff
+      // so we don't overwrite e.g. width and height
+      with Statics[StaticPlayerIdBox[PlayerPositionMap[I].Position]].Texture do
+      begin
+        TexNum := aPlayerScoreScreenTextures[I+1].Player_Id_Box.TexNum;
+        TexW := aPlayerScoreScreenTextures[I+1].Player_Id_Box.TexW;
+        TexH := aPlayerScoreScreenTextures[I+1].Player_Id_Box.TexH;
+      end;
+    end;
+  end;
+
+  if (Screens = 2) then
+  begin
+    { to keep it simple we just swap all statics, not just the shown ones }
+    for P := Low(PlayerStatic) to High(PlayerStatic) do
+      for I := 0 to High(PlayerStatic[P]) do
+      begin
+        Statics[PlayerStatic[P, I]].Texture := PlayerStaticTextures[P, I, Screen].Tex;
+      end;
+
+    { box statics }
+    for P := Low(PlayerStatic) to High(PlayerStatic) do
+    begin
+      Statics[StaticBoxLightest[P]].Texture := PlayerBoxTextures[P, 0, Screen].Tex;
+      Statics[StaticBoxLight[P]].Texture := PlayerBoxTextures[P, 1, Screen].Tex;
+      Statics[StaticBoxDark[P]].Texture := PlayerBoxTextures[P, 2, Screen].Tex;
+    end;
+  end;
+end;
+
+constructor TScreenScore.Create;
+var
+  Player:  integer;
+  Counter: integer;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.Score);
+
+  // These two texts arn't used in the deluxe skin
+  TextArtist      := AddText(Theme.Score.TextArtist);
+  TextTitle       := AddText(Theme.Score.TextTitle);
+
+  TextArtistTitle := AddText(Theme.Score.TextArtistTitle);
+
+  for Player := 1 to 6 do
+  begin
+    SetLength(PlayerStatic[Player], Length(Theme.Score.PlayerStatic[Player]));
+    SetLength(PlayerTexts[Player],  Length(Theme.Score.PlayerTexts[Player]));
+
+    for Counter := 0 to High(Theme.Score.PlayerStatic[Player]) do
+      PlayerStatic[Player, Counter]      := AddStatic(Theme.Score.PlayerStatic[Player, Counter]);
+
+    
+
+    for Counter := 0 to High(Theme.Score.PlayerTexts[Player]) do
+      PlayerTexts[Player, Counter]       := AddText(Theme.Score.PlayerTexts[Player, Counter]);
+
+    TextName[Player]             := AddText(Theme.Score.TextName[Player]);
+    TextScore[Player]            := AddText(Theme.Score.TextScore[Player]);
+
+    TextNotes[Player]            := AddText(Theme.Score.TextNotes[Player]);
+    TextNotesScore[Player]       := AddText(Theme.Score.TextNotesScore[Player]);
+    TextLineBonus[Player]        := AddText(Theme.Score.TextLineBonus[Player]);
+    TextLineBonusScore[Player]   := AddText(Theme.Score.TextLineBonusScore[Player]);
+    TextGoldenNotes[Player]      := AddText(Theme.Score.TextGoldenNotes[Player]);
+    TextGoldenNotesScore[Player] := AddText(Theme.Score.TextGoldenNotesScore[Player]);
+    TextTotal[Player]            := AddText(Theme.Score.TextTotal[Player]);
+    TextTotalScore[Player]       := AddText(Theme.Score.TextTotalScore[Player]);
+
+    StaticBoxLightest[Player]    := AddStatic(Theme.Score.StaticBoxLightest[Player]);
+    StaticBoxLight[Player]       := AddStatic(Theme.Score.StaticBoxLight[Player]);
+    StaticBoxDark[Player]        := AddStatic(Theme.Score.StaticBoxDark[Player]);
+
+    StaticBackLevel[Player]      := AddStatic(Theme.Score.StaticBackLevel[Player]);
+    StaticBackLevelRound[Player] := AddStatic(Theme.Score.StaticBackLevelRound[Player]);
+    StaticLevel[Player]          := AddStatic(Theme.Score.StaticLevel[Player]);
+    StaticLevelRound[Player]     := AddStatic(Theme.Score.StaticLevelRound[Player]);
+    StaticPlayerIdBox[Player]    := AddStatic(Theme.Score.StaticPlayerIdBox[Player]);
+
+    //textures
+    aPlayerScoreScreenTextures[Player].Score_NoteBarLevel_Dark     := Tex_Score_NoteBarLevel_Dark[Player];
+    aPlayerScoreScreenTextures[Player].Score_NoteBarRound_Dark     := Tex_Score_NoteBarRound_Dark[Player];
+
+    aPlayerScoreScreenTextures[Player].Score_NoteBarLevel_Light    := Tex_Score_NoteBarLevel_Light[Player];
+    aPlayerScoreScreenTextures[Player].Score_NoteBarRound_Light    := Tex_Score_NoteBarRound_Light[Player];
+
+    aPlayerScoreScreenTextures[Player].Score_NoteBarLevel_Lightest := Tex_Score_NoteBarLevel_Lightest[Player];
+    aPlayerScoreScreenTextures[Player].Score_NoteBarRound_Lightest := Tex_Score_NoteBarRound_Lightest[Player];
+    aPlayerScoreScreenTextures[Player].Player_Id_Box := Texture.GetTexture(Skin.GetTextureFileName('PlayerIDBox0' + IntToStr(Player)), Texture_Type_Transparent);
+  end;
+
+  LoadSwapTextures;
+end;
+
+procedure TScreenScore.MapPlayersToPosition;
+  var
+    ArrayStartModifier: integer;
+    PlayersPerScreen: integer;
+    I: integer;
+begin
+  // all statics / texts are loaded at start - so that we have them all even if we change the amount of players
+  // To show the corrects statics / text from the them, we simply modify the start of the according arrays
+  // 1 Player -> Player[0].Score         (The score for one player starts at 0)
+  //          -> Statics[1]              (The statics for the one player screen start at 1)
+  // 2 Player -> Player[0..1].Score
+  //          -> Statics[2..3]
+  // 3 Player -> Player[0..5].Score
+  //          -> Statics[4..6]
+  case PlayersPlay of
+    1:    ArrayStartModifier := 1;
+    2, 4: ArrayStartModifier := 2;
+    3, 6: ArrayStartModifier := 4;
+  else
+    ArrayStartModifier := 0; //this should never happen
+  end;
+
+  if (PlayersPlay <= 3) then
+    PlayersPerScreen := PlayersPlay
+  else
+    PlayersPerScreen := PlayersPlay div 2;
+
+  SetLength(PlayerPositionMap, PlayersPlay);
+
+  // actually map players to positions
+  for I := 0 to PlayersPlay - 1 do
+  begin
+    PlayerPositionMap[I].Screen := (I div PlayersPerScreen) + 1;
+    if (PlayerPositionMap[I].Screen > Screens) then
+      PlayerPositionMap[I].Position := 0
+    else
+      PlayerPositionMap[I].Position := ArrayStartModifier + (I mod PlayersPerScreen);
+    PlayerPositionMap[I].BothScreens := (PlayersPlay <= 3) and (Screens > 1);
+  end;
+end;
+
+procedure TScreenScore.UpdateAnimation;
+var
+  CurrentTime: integer;
+  I: integer;
+begin
+  CurrentTime := SDL_GetTicks();
+
+  if (ScreenAct = 1) and ShowFinish then
+    while (CurrentTime >= BarTime) do
+    begin
+      Inc(BarTime, BarRaiseSpeed);
+
+      // We actually arise them in the right order, but we have to draw them in reverse order (golden -> phrase -> mainscore)
+      if (BarScore_EaseOut_Step < EaseOut_MaxSteps * 10) then
+        BarScore_EaseOut_Step:= BarScore_EaseOut_Step + 1
+
+      // PhrasenBonus
+      else if (BarPhrase_EaseOut_Step < EaseOut_MaxSteps * 10) then
+        BarPhrase_EaseOut_Step := BarPhrase_EaseOut_Step + 1
+
+      // GoldenNotebonus
+      else if (BarGolden_EaseOut_Step < EaseOut_MaxSteps * 10) then
+        BarGolden_EaseOut_Step := BarGolden_EaseOut_Step + 1
+
+      // rating icon
+      else
+        for I := 1 to PlayersPlay do
+          CalculateBouncing(I);
+    end;
+end;
+
+procedure TScreenScore.DrawPlayerBars;
+  var
+    I: integer;
+begin
+  for I := 0 to PlayersPlay-1 do
+  begin
+    if (PlayerPositionMap[I].Position > 0) and ((ScreenAct = PlayerPositionMap[I].Screen) or (PlayerPositionMap[I].BothScreens)) then
+    begin
+      if (BarScore_EaseOut_Step >= (EaseOut_MaxSteps * 10)) then
+      begin
+        if (BarPhrase_EaseOut_Step >= (EaseOut_MaxSteps * 10)) then
+        begin
+          // Draw golden score bar #
+          EaseBarIn(I + 1, sbtGolden);
+          EaseScoreIn(I + 1, sbtGolden);
+        end;
+
+        // Draw phrase score bar #
+        EaseBarIn(I + 1, sbtLine);
+        EaseScoreIn(I + 1, sbtLine);
+      end;
+
+      // Draw plain score bar #
+      EaseBarIn(I + 1, sbtScore);
+      EaseScoreIn(I + 1, sbtScore);
+    end;
+  end;
+end;
+
+procedure TScreenScore.OnShow;
+var
+  P: integer;  // player
+  I: integer;
+  V: array[1..6] of boolean; // visibility array
+
+begin
+
+  {**
+   * Turn backgroundmusic on
+   *}
+  SoundLib.StartBgMusic;
+
+  inherited;
+
+  MapPlayersToPosition;
+
+  for P := 1 to PlayersPlay do
+  begin
+    // data
+    aPlayerScoreScreenDatas[P].Bar_Y                  := Theme.Score.StaticBackLevel[PlayerPositionMap[P-1].Position].Y;
+
+    // ratings
+    aPlayerScoreScreenRatings[P].RateEaseStep         := 1;
+    aPlayerScoreScreenRatings[P].RateEaseValue        := 20;
+
+    // actual values
+    TextScore_ActualValue[P]  := 0;
+    TextPhrase_ActualValue[P] := 0;
+    TextGolden_ActualValue[P] := 0;
+  end;
+
+  Text[TextArtist].Text      := CurrentSong.Artist;
+  Text[TextTitle].Text       := CurrentSong.Title;
+  Text[TextArtistTitle].Text := CurrentSong.Artist + ' - ' + CurrentSong.Title;
+
+  // set visibility
+  case PlayersPlay of
+    1:  begin
+          V[1] := true;
+          V[2] := false;
+          V[3] := false;
+          V[4] := false;
+          V[5] := false;
+          V[6] := false;
+        end;
+    2, 4:  begin
+          V[1] := false;
+          V[2] := true;
+          V[3] := true;
+          V[4] := false;
+          V[5] := false;
+          V[6] := false;
+        end;
+    3, 6:  begin
+          V[1] := false;
+          V[2] := false;
+          V[3] := false;
+          V[4] := true;
+          V[5] := true;
+          V[6] := true;
+        end;
+  end;
+
+  for P := 1 to 6 do
+  begin
+   Text[TextName[P]].Visible               := V[P];
+   Text[TextScore[P]].Visible              := V[P];
+
+    // We set alpha to 0 , so we can nicely blend them in when we need them
+    Text[TextScore[P]].Alpha                   := 0;
+    Text[TextNotesScore[P]].Alpha              := 0;
+    Text[TextNotes[P]].Alpha                   := 0;
+    Text[TextLineBonus[P]].Alpha               := 0;
+    Text[TextLineBonusScore[P]].Alpha          := 0;
+    Text[TextGoldenNotes[P]].Alpha             := 0;
+    Text[TextGoldenNotesScore[P]].Alpha        := 0;
+    Text[TextTotal[P]].Alpha                   := 0;
+    Text[TextTotalScore[P]].Alpha              := 0;
+    Statics[StaticBoxLightest[P]].Texture.Alpha := 0;
+    Statics[StaticBoxLight[P]].Texture.Alpha    := 0;
+    Statics[StaticBoxDark[P]].Texture.Alpha     := 0;
+
+    Text[TextNotes[P]].Visible              := V[P];
+    Text[TextNotesScore[P]].Visible         := V[P];
+    Text[TextLineBonus[P]].Visible          := V[P];
+    Text[TextLineBonusScore[P]].Visible     := V[P];
+    Text[TextGoldenNotes[P]].Visible        := V[P];
+    Text[TextGoldenNotesScore[P]].Visible   := V[P];
+    Text[TextTotal[P]].Visible              := V[P];
+    Text[TextTotalScore[P]].Visible         := V[P];
+
+    for I := 0 to high(PlayerStatic[P]) do
+      Statics[PlayerStatic[P, I]].Visible    := V[P];
+
+    for I := 0 to high(PlayerTexts[P]) do
+      Text[PlayerTexts[P, I]].Visible       := V[P];
+
+    Statics[StaticBoxLightest[P]].Visible    := V[P];
+    Statics[StaticBoxLight[P]].Visible       := V[P];
+    Statics[StaticBoxDark[P]].Visible        := V[P];
+
+    Statics[StaticPlayerIdBox[P]].Visible     := V[P];
+
+    // we draw that on our own
+    Statics[StaticBackLevel[P]].Visible      := false;
+    Statics[StaticBackLevelRound[P]].Visible := false;
+    Statics[StaticLevel[P]].Visible          := false;
+    Statics[StaticLevelRound[P]].Visible     := false;
+  end;
+
+  BarScore_EaseOut_Step  := 1;
+  BarPhrase_EaseOut_Step := 1;
+  BarGolden_EaseOut_Step := 1;
+end;
+
+procedure TScreenScore.onShowFinish;
+var
+  index: integer;
+begin
+  for index := 1 to (PlayersPlay) do
+  begin
+    TextScore_ActualValue[index]  := 0;
+    TextPhrase_ActualValue[index] := 0;
+    TextGolden_ActualValue[index] := 0;
+  end;
+
+  BarTime := SDL_GetTicks();
+end;
+
+function TScreenScore.Draw: boolean;
+var
+  PlayerCounter: integer;
+begin
+{*
+  player[0].ScoreInt       := 7000;
+  player[0].ScoreLineInt   := 2000;
+  player[0].ScoreGoldenInt := 1000;
+  player[0].ScoreTotalInt  := 10000;
+
+  player[1].ScoreInt       := 2500;
+  player[1].ScoreLineInt   := 1100;
+  player[1].ScoreGoldenInt :=  900;
+  player[1].ScoreTotalInt  := 4500;
+//*}
+  // swap static textures to current screen ones
+  SwapToScreen(ScreenAct);
+
+  //Draw the Background
+  DrawBG;
+
+  // Let's start to arise the bars
+  UpdateAnimation;
+
+  // we have to swap the themeobjects values on every draw
+  // to support dual screen
+  for PlayerCounter := 1 to PlayersPlay do
+  begin
+    FillPlayerItems(PlayerCounter);
+  end;
+
+  if (ShowFinish) then
+    DrawPlayerBars;
+
+  //Draw Theme Objects
+  DrawFG;
+
+(*
+    //todo: i need a clever method to draw statics with their z value
+    for I := 0 to Length(Statics) - 1 do
+      Statics[I].Draw;
+    for I := 0 to Length(Text) - 1 do
+      Text[I].Draw;
+*)
+
+  Result := true;
+end;
+
+procedure TscreenScore.FillPlayerItems(PlayerNumber: integer);
+var
+  ThemeIndex: integer;
+begin
+  ThemeIndex := PlayerPositionMap[PlayerNumber-1].Position;
+  if (ThemeIndex > 0) and ((ScreenAct = PlayerPositionMap[PlayerNumber-1].Screen) or (PlayerPositionMap[PlayerNumber-1].BothScreens)) then
+  begin
+    // todo: take the name from player[PlayerNumber].Name instead of the ini when this is done (mog)
+    Text[TextName[ThemeIndex]].Text := Ini.Name[PlayerNumber-1];
+    // end todo
+
+    //golden
+    Text[TextGoldenNotesScore[ThemeIndex]].Text         := IntToStr(TextGolden_ActualValue[PlayerNumber]);
+    Text[TextGoldenNotesScore[ThemeIndex]].Alpha        := (BarGolden_EaseOut_Step / 100);
+
+    Statics[StaticBoxLightest[ThemeIndex]].Texture.Alpha := (BarGolden_EaseOut_Step / 100);
+    Text[TextGoldenNotes[ThemeIndex]].Alpha             := (BarGolden_EaseOut_Step / 100);
+
+    // line bonus
+    Text[TextLineBonusScore[ThemeIndex]].Text           := IntToStr(TextPhrase_ActualValue[PlayerNumber]);
+    Text[TextLineBonusScore[ThemeIndex]].Alpha          := (BarPhrase_EaseOut_Step / 100);
+
+    Statics[StaticBoxLight[ThemeIndex]].Texture.Alpha    := (BarPhrase_EaseOut_Step / 100);
+    Text[TextLineBonus[ThemeIndex]].Alpha               := (BarPhrase_EaseOut_Step / 100);
+
+    // plain score
+    Text[TextNotesScore[ThemeIndex]].Text               := IntToStr(TextScore_ActualValue[PlayerNumber]);
+    Text[TextNotes[ThemeIndex]].Alpha                   := (BarScore_EaseOut_Step / 100);
+
+    Statics[StaticBoxDark[ThemeIndex]].Texture.Alpha     := (BarScore_EaseOut_Step / 100);
+    Text[TextNotesScore[ThemeIndex]].Alpha              := (BarScore_EaseOut_Step / 100);
+
+    // total score
+    Text[TextTotalScore[ThemeIndex]].Text               := IntToStr(TextScore_ActualValue[PlayerNumber] + TextPhrase_ActualValue[PlayerNumber] + TextGolden_ActualValue[PlayerNumber]);
+    Text[TextTotalScore[ThemeIndex]].Alpha              := (BarScore_EaseOut_Step / 100);
+
+    Text[TextTotal[ThemeIndex]].Alpha                   := (BarScore_EaseOut_Step / 100);
+
+    if(BarGolden_EaseOut_Step = 100) then
+    begin
+      ShowRating(PlayerNumber);
+    end;
+  end;
+end;
+
+procedure TScreenScore.ShowRating(PlayerNumber: integer);
+var
+  Rating: integer;
+  ThemeIndex: integer;
+begin
+  ThemeIndex := PlayerPositionMap[PlayerNumber-1].Position;
+  if (ThemeIndex > 0) and ((ScreenAct = PlayerPositionMap[PlayerNumber-1].Screen) or (PlayerPositionMap[PlayerNumber-1].BothScreens)) then
+  begin
+    case (Player[PlayerNumber-1].ScoreTotalInt) of
+     0..2009:
+       begin
+         Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_TONE_DEAF');
+         Rating := 0;
+       end;
+     2010..4009:
+       begin
+         Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_AMATEUR');
+         Rating := 1;
+       end;
+     4010..5009:
+       begin
+         Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_WANNABE');
+         Rating := 2;
+       end;
+     5010..6009:
+       begin
+         Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_HOPEFUL');
+         Rating := 3;
+       end;
+     6010..7509:
+       begin
+         Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_RISING_STAR');
+         Rating := 4;
+       end;
+     7510..8509:
+       begin
+         Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_LEAD_SINGER');
+         Rating := 5;
+       end;
+     8510..9009:
+       begin
+         Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_SUPERSTAR');
+         Rating := 6;
+       end;
+     9010..10000:
+       begin
+         Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_ULTRASTAR');
+         Rating := 7;
+       end;
+    else
+      Rating := 0; // Cheata :P
+    end;
+
+    //todo: this could break if the width is not given, for instance when there's a skin with no picture for ratings
+    if ( Theme.Score.StaticRatings[ThemeIndex].W > 0 ) and  ( aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue > 0 ) then
+    begin
+      Text[TextScore[ThemeIndex]].Alpha := aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue / Theme.Score.StaticRatings[ThemeIndex].W;
+    end;
+    // end todo
+
+    DrawRating(PlayerNumber, Rating);
+  end;
+end;
+
+procedure TscreenScore.DrawRating(PlayerNumber: integer; Rating: integer);
+var
+  Posx:  real;
+  Posy:  real;
+  Width: real;
+  ThemeIndex: integer;
+begin
+  ThemeIndex := PlayerPositionMap[PlayerNumber-1].Position;
+
+  PosX := Theme.Score.StaticRatings[ThemeIndex].X + (Theme.Score.StaticRatings[ThemeIndex].W  * 0.5);
+  PosY := Theme.Score.StaticRatings[ThemeIndex].Y + (Theme.Score.StaticRatings[ThemeIndex].H  * 0.5); ;
+
+  Width := aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue/2;
+
+  glBindTexture(GL_TEXTURE_2D, Tex_Score_Ratings[Rating].TexNum);
+
+  glEnable(GL_TEXTURE_2D);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+
+  glBegin(GL_QUADS);
+    glTexCoord2f(0, 0);                                                           glVertex2f(PosX - Width,  PosY - Width);
+    glTexCoord2f(Tex_Score_Ratings[Rating].TexW, 0);                              glVertex2f(PosX + Width,  PosY - Width);
+    glTexCoord2f(Tex_Score_Ratings[Rating].TexW, Tex_Score_Ratings[Rating].TexH); glVertex2f(PosX + Width,  PosY + Width);
+    glTexCoord2f(0, Tex_Score_Ratings[Rating].TexH);                              glVertex2f(PosX - Width,  PosY + Width);
+  glEnd;
+
+  glDisable(GL_BLEND);
+  glDisable(GL_TEXTURE_2d);
+end;
+
+function TscreenScore.CalculateBouncing(PlayerNumber: integer): real;
+var
+  p, s:              real;
+
+  RaiseStep, MaxVal: real;
+  EaseOut_Step:      integer;
+  ThemeIndex: integer;
+begin
+  ThemeIndex := PlayerPositionMap[PlayerNumber-1].Position;
+
+  EaseOut_Step  := aPlayerScoreScreenRatings[PlayerNumber].RateEaseStep;
+  MaxVal        := Theme.Score.StaticRatings[ThemeIndex].W;
+
+  RaiseStep     := EaseOut_Step;
+
+  if (MaxVal > 0) and (RaiseStep > 0) then
+    RaiseStep := RaiseStep / MaxVal;
+
+  if (RaiseStep = 1) then
+  begin
+    Result := MaxVal;
+  end
+  else
+  begin
+    p := MaxVal * 0.4;
+
+    s           := p/(2*PI) * arcsin (1);
+    Result := MaxVal * power(2,-5 * RaiseStep) * sin( (RaiseStep * MaxVal - s) * (2 * PI) / p) + MaxVal;
+
+    inc(aPlayerScoreScreenRatings[PlayerNumber].RateEaseStep);
+    aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue := Result;
+  end;
+end;
+
+procedure TscreenScore.EaseBarIn(PlayerNumber: integer; BarType: TScoreBarType);
+const
+  RaiseSmoothness: integer = 100;
+var
+  MaxHeight:    real;
+  NewHeight:    real;
+
+  Height2Reach: real;
+  RaiseStep:    real;
+  BarStartPosY: single;
+
+  lTmp:         real;
+  Score:        integer;
+  ThemeIndex: integer;
+begin
+  ThemeIndex := PlayerPositionMap[PlayerNumber-1].Position;
+  MaxHeight    := Theme.Score.StaticBackLevel[ThemeIndex].H;
+
+  // let's get the points according to the bar we draw
+  // score array starts at 0, which means the score for player 1 is in score[0]
+  // EaseOut_Step is the actual step in the raising process, like the 20iest step of EaseOut_MaxSteps
+  if (BarType = sbtScore) then
+  begin
+    Score        := Player[PlayerNumber - 1].ScoreInt;
+    RaiseStep    := BarScore_EaseOut_Step;
+    BarStartPosY := Theme.Score.StaticBackLevel[ThemeIndex].Y + MaxHeight;
+  end
+  else if (BarType = sbtLine) then
+  begin
+    Score        := Player[PlayerNumber - 1].ScoreLineInt;
+    RaiseStep    := BarPhrase_EaseOut_Step;
+    BarStartPosY := Theme.Score.StaticBackLevel[ThemeIndex].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight + MaxHeight;
+  end
+  else if (BarType = sbtGolden) then
+  begin
+    Score        := Player[PlayerNumber - 1].ScoreGoldenInt;
+    RaiseStep    := BarGolden_EaseOut_Step;
+    BarStartPosY := Theme.Score.StaticBackLevel[ThemeIndex].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight - aPlayerScoreScreenDatas[PlayerNumber].BarLine_ActualHeight + MaxHeight;
+  end;
+
+  // the height dependend of the score
+  Height2Reach := (Score / MAX_SONG_SCORE) * MaxHeight;
+
+  if (aPlayerScoreScreenDatas[PlayerNumber].Bar_Actual_Height < Height2Reach) then
+  begin
+    // Check http://proto.layer51.com/d.aspx?f=400 for more info on easing functions
+    // Calculate the actual step according to the maxsteps
+    RaiseStep := RaiseStep / EaseOut_MaxSteps;
+
+    // quadratic easing out - decelerating to zero velocity
+    // -end_position * current_time * ( current_time - 2 ) + start_postion
+    lTmp := (-Height2Reach * RaiseStep * (RaiseStep - 20) + BarStartPosY);
+
+    if ( RaiseSmoothness > 0 ) and ( lTmp > 0 ) then
+      NewHeight := lTmp / RaiseSmoothness;
+
+  end
+  else
+    NewHeight := Height2Reach;
+
+  DrawBar(BarType, PlayerNumber, BarStartPosY, NewHeight);
+
+  if (BarType = sbtScore) then
+    aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight  := NewHeight
+  else if (BarType = sbtLine) then
+    aPlayerScoreScreenDatas[PlayerNumber].BarLine_ActualHeight   := NewHeight
+  else if (BarType = sbtGolden) then
+    aPlayerScoreScreenDatas[PlayerNumber].BarGolden_ActualHeight := NewHeight;
+end;
+
+procedure TscreenScore.DrawBar(BarType: TScoreBarType; PlayerNumber: integer; BarStartPosY: single; NewHeight: real);
+var
+  Width:        real;
+  BarStartPosX: real;
+  ThemeIndex: integer;
+begin
+  ThemeIndex := PlayerPositionMap[PlayerNumber-1].Position;
+
+  // this is solely for better readability of the drawing
+  Width        := Theme.Score.StaticBackLevel[ThemeIndex].W;
+  BarStartPosX := Theme.Score.StaticBackLevel[ThemeIndex].X;
+
+  glColor4f(1, 1, 1, 1);
+
+  // set the texture for the bar
+  if (BarType = sbtScore) then
+    glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarLevel_Dark.TexNum);
+  if (BarType = sbtLine) then
+    glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarLevel_Light.TexNum);
+  if (BarType = sbtGolden) then
+    glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarLevel_Lightest.TexNum);
+
+  //draw it
+  glEnable(GL_TEXTURE_2D);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+
+  glBegin(GL_QUADS);
+    glTexCoord2f(0, 0); glVertex3f(BarStartPosX,         BarStartPosY - NewHeight, ZBars);
+    glTexCoord2f(1, 0); glVertex3f(BarStartPosX + Width, BarStartPosY - NewHeight, ZBars);
+    glTexCoord2f(1, 1); glVertex3f(BarStartPosX + Width, BarStartPosY,             ZBars);
+    glTexCoord2f(0, 1); glVertex3f(BarStartPosX,         BarStartPosY,             ZBars);
+  glEnd;
+
+  glDisable(GL_BLEND);
+  glDisable(GL_TEXTURE_2d);
+
+  //the round thing on top
+  if (BarType = sbtScore) then
+    glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarRound_Dark.TexNum);
+  if (BarType = sbtLine) then
+    glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarRound_Light.TexNum);
+  if (BarType = sbtGolden) then
+    glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarRound_Lightest.TexNum);
+
+  glEnable(GL_TEXTURE_2D);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+
+  glBegin(GL_QUADS);
+    glTexCoord2f(0, 0); glVertex3f(BarStartPosX,         (BarStartPosY - Statics[StaticLevelRound[ThemeIndex]].Texture.h) - NewHeight, ZBars);
+    glTexCoord2f(1, 0); glVertex3f(BarStartPosX + Width, (BarStartPosY - Statics[StaticLevelRound[ThemeIndex]].Texture.h) - NewHeight, ZBars);
+    glTexCoord2f(1, 1); glVertex3f(BarStartPosX + Width,  BarStartPosY - NewHeight,                                                     ZBars);
+    glTexCoord2f(0, 1); glVertex3f(BarStartPosX,          BarStartPosY - NewHeight,                                                     ZBars);
+  glEnd;
+
+  glDisable(GL_BLEND);
+  glDisable(GL_TEXTURE_2d);
+end;
+
+procedure TScreenScore.EaseScoreIn(PlayerNumber: integer; ScoreType: TScoreBarType);
+const
+  RaiseSmoothness: integer = 100;
+var
+  RaiseStep:        real;
+  lTmpA:            real;
+  ScoreReached:     integer;
+  EaseOut_Step:     real;
+  ActualScoreValue: integer;
+begin
+  if (ScoreType = sbtScore) then
+  begin
+    EaseOut_Step     := BarScore_EaseOut_Step;
+    ActualScoreValue := TextScore_ActualValue[PlayerNumber];
+    ScoreReached     := Player[PlayerNumber-1].ScoreInt;
+  end;
+  if (ScoreType = sbtLine) then
+  begin
+    EaseOut_Step     := BarPhrase_EaseOut_Step;
+    ActualScoreValue := TextPhrase_ActualValue[PlayerNumber];
+    ScoreReached     := Player[PlayerNumber-1].ScoreLineInt;
+  end;
+  if (ScoreType = sbtGolden) then
+  begin
+    EaseOut_Step     := BarGolden_EaseOut_Step;
+    ActualScoreValue := TextGolden_ActualValue[PlayerNumber];
+    ScoreReached     := Player[PlayerNumber-1].ScoreGoldenInt;
+  end;
+
+  // EaseOut_Step is the actual step in the raising process, like the 20iest step of EaseOut_MaxSteps
+  RaiseStep := EaseOut_Step;
+
+  if (ActualScoreValue < ScoreReached) then
+  begin
+    // Calculate the actual step according to the maxsteps
+    RaiseStep := RaiseStep / EaseOut_MaxSteps;
+
+    // quadratic easing out - decelerating to zero velocity
+    // -end_position * current_time * ( current_time - 2 ) + start_postion
+    lTmpA := (-ScoreReached * RaiseStep * (RaiseStep - 20));
+    if ( lTmpA           > 0 ) and
+       ( RaiseSmoothness > 0 ) then
+    begin
+      if (ScoreType = sbtScore) then
+        TextScore_ActualValue[PlayerNumber]  := floor( lTmpA / RaiseSmoothness);
+      if (ScoreType = sbtLine) then
+        TextPhrase_ActualValue[PlayerNumber] := floor( lTmpA / RaiseSmoothness);
+      if (ScoreType = sbtGolden) then
+        TextGolden_ActualValue[PlayerNumber] := floor( lTmpA / RaiseSmoothness);
+    end;
+  end
+  else
+  begin
+    if (ScoreType = sbtScore) then
+      TextScore_ActualValue[PlayerNumber]    := ScoreReached;
+    if (ScoreType = sbtLine) then
+      TextPhrase_ActualValue[PlayerNumber]   := ScoreReached;
+    if (ScoreType = sbtGolden) then
+      TextGolden_ActualValue[PlayerNumber]   := ScoreReached;
+  end;
+end;
+
+procedure TScreenScore.FillPlayer(Item, P: integer);
+var
+  S:    string;
+begin
+  Text[TextName[Item]].Text := Ini.Name[P];
+
+  S := IntToStr((Round(Player[P].Score) div 10) * 10);
+  while (Length(S)<4) do
+    S := '0' + S;
+  Text[TextNotesScore[Item]].Text := S;
+
+  //  while (Length(S)<5) do S := '0' + S;
+  //  Text[TextTotalScore[Item]].Text := S;
+
+  //fixed: line bonus and golden notes don't show up,
+  //       another bug: total score was shown without added golden-, linebonus
+  S := IntToStr(Player[P].ScoreTotalInt);
+  while (Length(S)<5) do
+    S := '0' + S;
+  Text[TextTotalScore[Item]].Text := S;
+
+  S := IntToStr(Player[P].ScoreLineInt);
+  while (Length(S)<4) do
+    S := '0' + S;
+  Text[TextLineBonusScore[Item]].Text := S;
+
+  S := IntToStr(Player[P].ScoreGoldenInt);
+  while (Length(S)<4) do
+    S := '0' + S;
+  Text[TextGoldenNotesScore[Item]].Text := S;
+  //end of fix
+
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenSing.pas b/songmanagement/src/screens/UScreenSing.pas
new file mode 100644
index 00000000..3b8fda40
--- /dev/null
+++ b/songmanagement/src/screens/UScreenSing.pas
@@ -0,0 +1,1071 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenSing;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  SDL,
+  TextGL,
+  gl,
+  UFiles,
+  UGraphicClasses,
+  UIni,
+  ULog,
+  ULyrics,
+  UMenu,
+  UMusic,
+  USingScores,
+  USongs,
+  UTexture,
+  UThemes,
+  UPath,
+  UTime,
+  UHookableEvent;
+
+type
+  TLyricsSyncSource = class(TSyncSource)
+    function GetClock(): real; override;
+  end;
+
+  TMusicSyncSource = class(TSyncSource)
+    function GetClock(): real; override;
+  end;
+
+  TTimebarMode = (
+    tbmCurrent,   // current song position
+    tbmRemaining, // remaining time
+    tbmTotal      // total time
+  );
+
+type
+  TScreenSing = class(TMenu)
+  private
+    fShowVisualization: boolean;
+    fCurrentVideo: IVideo;
+    fVideoClip:    IVideo;
+    fLyricsSync: TLyricsSyncSource;
+    fMusicSync: TMusicSyncSource;
+    fTimebarMode: TTimebarMode;
+  protected
+    eSongLoaded: THookableEvent; //< event is called after lyrics of a song are loaded on OnShow
+    Paused:     boolean; //pause Mod
+    NumEmptySentences: integer;
+  public
+    // timebar fields
+    StaticTimeProgress: integer;
+    TextTimeText: integer;
+
+    StaticP1: integer;
+    TextP1:   integer;
+
+    // shown when game is in 2/4 player modus
+    StaticP1TwoP: integer;
+    TextP1TwoP:   integer;
+
+    // shown when game is in 3/6 player modus
+    StaticP1ThreeP: integer;
+    TextP1ThreeP:   integer;
+
+    StaticP2R: integer;
+    TextP2R:   integer;
+
+    StaticP2M: integer;
+    TextP2M:   integer;
+
+    StaticP3R: integer;
+    TextP3R:   integer;
+
+    StaticPausePopup: integer;
+
+    Tex_Background: TTexture;
+    FadeOut: boolean;
+    Lyrics:  TLyricEngine;
+
+    // score manager:
+    Scores: TSingScores;
+
+    //the song was sung to the end
+    SungToEnd: boolean;
+
+    // some settings to be set by plugins
+    Settings: record
+      Finish: Boolean; //< if true, screen will finish on next draw
+
+      LyricsVisible: Boolean; //< shows or hides lyrics
+      NotesVisible: Integer; //< if bit[playernum] is set the notes for the specified player are visible. By default all players notes are visible
+
+      PlayerEnabled: Integer; //< defines whether a player can score atm
+    end;
+    procedure ClearSettings;
+    procedure ApplySettings; //< applies changes of settings record
+    procedure EndSong;
+
+    constructor Create; override;
+    procedure OnShow; override;
+    procedure OnShowFinish; override;
+    procedure OnHide; override;
+
+    function ParseInput(PressedKey: cardinal; CharCode: UCS4Char;
+      PressedDown: boolean): boolean; override;
+    function Draw: boolean; override;
+
+    procedure Finish; virtual;
+    procedure Pause; // toggle pause
+
+    procedure OnSentenceEnd(SentenceIndex: cardinal);     // for linebonus + singbar
+    procedure OnSentenceChange(SentenceIndex: cardinal);  // for golden notes
+  end;
+
+implementation
+
+uses
+  Classes,
+  Math,
+  UDraw,
+  UGraphic,
+  ULanguage,
+  UNote,
+  URecord,
+  USong,
+  UDisplay,
+  UParty,
+  UUnicodeUtils;
+
+// method for input parsing. if false is returned, getnextwindow
+// should be checked to know the next window to load;
+
+function TScreenSing.ParseInput(PressedKey: Cardinal; CharCode: UCS4Char;
+  PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // key down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+      begin
+        // when not ask before exit then finish now
+        if (Ini.AskbeforeDel <> 1) then
+          Finish
+        // else just pause and let the popup make the work
+        else if not Paused then
+          Pause;
+
+        Result := false;
+        Exit;
+      end;
+
+      // show visualization
+      Ord('V'):
+      begin
+        fShowVisualization := not fShowVisualization;
+
+        if fShowVisualization then
+        begin
+          fCurrentVideo := Visualization.Open(PATH_NONE);
+          fCurrentVideo.play;
+        end
+        else
+        begin
+          fCurrentVideo := fVideoClip;
+        end;
+        Exit;
+      end;
+
+      // pause
+      Ord('P'):
+      begin
+        Pause;
+        Exit;
+      end;
+
+      // toggle time display
+      Ord('T'):
+      begin
+        if (fTimebarMode = High(TTimebarMode)) then
+          fTimebarMode := Low(TTimebarMode)
+        else
+          Inc(fTimebarMode);
+        Exit;
+      end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE:
+      begin
+        // record sound hack:
+        //Sound[0].BufferLong
+
+        Finish;
+        FadeOut := true;
+        AudioPlayback.PlaySound(SoundLib.Back);
+      end;
+
+      SDLK_SPACE:
+      begin
+        Pause;
+      end;
+
+      SDLK_TAB: // change visualization preset
+      begin
+        if fShowVisualization then
+          fCurrentVideo.Position := now; // move to a random position
+      end;
+
+      SDLK_RETURN:
+      begin
+      end;
+
+      // up and down could be done at the same time,
+      // but i don't want to declare variables inside
+      // functions like this one, called so many times
+      SDLK_DOWN:
+      begin
+      end;
+      SDLK_UP:
+      begin
+      end;
+    end;
+  end;
+end;
+
+// pause mod
+procedure TScreenSing.Pause;
+begin
+  if (not Paused) then  // enable pause
+  begin
+    // pause time
+    Paused := true;
+
+    LyricsState.Pause();
+
+    // pause music
+    AudioPlayback.Pause;
+
+    // pause video
+    if (fCurrentVideo <> nil) then
+      fCurrentVideo.Pause;
+
+  end
+  else              // disable pause
+  begin
+    LyricsState.Start();
+
+    // play music
+    AudioPlayback.Play;
+
+    // video
+    if (fCurrentVideo <> nil) then
+      fCurrentVideo.Pause;
+
+    Paused := false;
+  end;
+end;
+// pause mod end
+
+constructor TScreenSing.Create;
+begin
+  inherited Create;
+
+  //too dangerous, a mouse button is quickly pressed by accident
+  RightMbESC := false;
+
+  fShowVisualization := false;
+
+  fCurrentVideo := nil;
+
+  // create score class
+  Scores := TSingScores.Create;
+  Scores.LoadfromTheme;
+
+  LoadFromTheme(Theme.Sing);
+
+  // timebar
+  StaticTimeProgress := AddStatic(Theme.Sing.StaticTimeProgress);
+  TextTimeText := AddText(Theme.Sing.TextTimeText);
+
+  // 1 player       | P1
+  StaticP1 := AddStatic(Theme.Sing.StaticP1);
+  TextP1   := AddText(Theme.Sing.TextP1);
+
+  // 2 or 4 players | P1
+  StaticP1TwoP := AddStatic(Theme.Sing.StaticP1TwoP);
+  TextP1TwoP   := AddText(Theme.Sing.TextP1TwoP);
+
+  //                | P2
+  StaticP2R := AddStatic(Theme.Sing.StaticP2R);
+  TextP2R   := AddText(Theme.Sing.TextP2R);
+
+  // 3 or 6 players | P1
+  StaticP1ThreeP := AddStatic(Theme.Sing.StaticP1ThreeP);
+  TextP1ThreeP   := AddText(Theme.Sing.TextP1ThreeP);
+
+  //                | P2
+  StaticP2M := AddStatic(Theme.Sing.StaticP2M);
+  TextP2M   := AddText(Theme.Sing.TextP2M);
+
+  //                | P3
+  StaticP3R := AddStatic(Theme.Sing.StaticP3R);
+  TextP3R   := AddText(Theme.Sing.TextP3R);
+
+  StaticPausePopup := AddStatic(Theme.Sing.PausePopUp);
+
+  // <note> pausepopup is not visibile at the beginning </note>
+  Statics[StaticPausePopup].Visible := false;
+
+  Lyrics := TLyricEngine.Create(
+      Theme.LyricBar.UpperX, Theme.LyricBar.UpperY, Theme.LyricBar.UpperW, Theme.LyricBar.UpperH,
+      Theme.LyricBar.LowerX, Theme.LyricBar.LowerY, Theme.LyricBar.LowerW, Theme.LyricBar.LowerH);
+
+  fLyricsSync := TLyricsSyncSource.Create();
+  fMusicSync := TMusicSyncSource.Create();
+
+  eSongLoaded := THookableEvent.Create('ScreenSing.SongLoaded');
+
+  ClearSettings;
+end;
+
+procedure TScreenSing.OnShow;
+var
+  Index:  integer;
+  V1:     boolean;
+  V1TwoP: boolean;   // position of score box in two player mode
+  V1ThreeP: boolean; // position of score box in three player mode
+  V2R:    boolean;
+  V2M:    boolean;
+  V3R:    boolean;
+  Color: TRGB;
+  VideoFile, BgFile: IPath;
+  success: boolean;
+  BadPlayer: integer;
+begin
+  inherited;
+
+  Log.LogStatus('Begin', 'OnShow');
+  FadeOut := false;
+
+  //the song was sung to the end
+  SungToEnd := false;
+  ClearSettings;
+  Party.CallBeforeSing;
+
+  // reset video playback engine
+  fCurrentVideo := nil;
+
+  // setup score manager
+  Scores.ClearPlayers; // clear old player values
+  Color.R := 0;
+  Color.G := 0;
+  Color.B := 0; // dummy atm  <- \(O.o)/? B like bummy?
+
+  // add new players
+  for Index := 0 to PlayersPlay - 1 do
+  begin
+    Scores.AddPlayer(Tex_ScoreBG[Index], Color);
+  end;
+
+  Scores.Init; // get positions for players
+
+  // prepare players
+  SetLength(Player, PlayersPlay);
+
+  case PlayersPlay of
+    1:
+    begin
+      V1     := true;
+      V1TwoP := false;
+      V1ThreeP := false;
+      V2R    := false;
+      V2M    := false;
+      V3R    := false;
+    end;
+    2:
+    begin
+      V1     := false;
+      V1TwoP := true;
+      V1ThreeP := false;
+      V2R    := true;
+      V2M    := false;
+      V3R    := false;
+    end;
+    3:
+    begin
+      V1     := false;
+      V1TwoP := false;
+      V1ThreeP := true;
+      V2R    := false;
+      V2M    := true;
+      V3R    := true;
+    end;
+    4:
+    begin // double screen
+      V1     := false;
+      V1TwoP := true;
+      V1ThreeP := false;
+      V2R    := true;
+      V2M    := false;
+      V3R    := false;
+    end;
+    6:
+    begin // double screen
+      V1     := false;
+      V1TwoP := false;
+      V1ThreeP := true;
+      V2R    := false;
+      V2M    := true;
+      V3R    := true;
+    end;
+
+  end;
+
+  // this one is shown in 1P mode
+  Statics[StaticP1].Visible := V1;
+  Text[TextP1].Visible     := V1;
+
+  // this one is shown in 2/4P mode
+  Statics[StaticP1TwoP].Visible := V1TwoP;
+  Text[TextP1TwoP].Visible     := V1TwoP;
+
+  Statics[StaticP2R].Visible := V2R;
+  Text[TextP2R].Visible     := V2R;
+
+  // this one is shown in 3/6P mode
+  Statics[StaticP1ThreeP].Visible := V1ThreeP;
+  Text[TextP1ThreeP].Visible     := V1ThreeP;
+
+  Statics[StaticP2M].Visible := V2M;
+  Text[TextP2M].Visible     := V2M;
+
+  Statics[StaticP3R].Visible := V3R;
+  Text[TextP3R].Visible     := V3R;
+
+  fTimebarMode := tbmCurrent;
+
+  // FIXME: sets path and filename to ''
+  ResetSingTemp;
+
+  CurrentSong := CatSongs.Song[CatSongs.Selected];
+
+  // FIXME: bad style, put the try-except into loadsong() and not here
+  try
+    // check if file is xml
+    if CurrentSong.FileName.GetExtension.ToUTF8 = '.xml' then
+      success := CurrentSong.AnalyseXML and CurrentSong.LoadXMLSong()
+    else
+      success := CurrentSong.Analyse and CurrentSong.LoadSong();
+  except
+    success := false;
+  end;
+
+  if (not success) then
+  begin
+    // error loading song -> go back to previous screen and show some error message
+    Display.AbortScreenChange;
+    // select new song in party mode
+    if ScreenSong.Mode = smPartyMode then
+      ScreenSong.SelectRandomSong();
+    if (Length(CurrentSong.LastError) > 0) then
+      ScreenPopupError.ShowPopup(Format(Language.Translate(CurrentSong.LastError), [CurrentSong.ErrorLineNo]))
+    else
+      ScreenPopupError.ShowPopup(Language.Translate('ERROR_CORRUPT_SONG'));
+    // FIXME: do we need this?
+    CurrentSong.Path := CatSongs.Song[CatSongs.Selected].Path;
+    Exit;
+  end;
+
+  {*
+   * == Background ==
+   * We have four types of backgrounds:
+   *   + Blank        : Nothing has been set, this is our fallback
+   *   + Picture      : Picture has been set, and exists - otherwise we fallback
+   *   + Video        : Video has been set, and exists - otherwise we fallback
+   *   + Visualization: + Off        : No visualization
+   *                    + WhenNoVideo: Overwrites blank and picture
+   *                    + On         : Overwrites blank, picture and video
+   *}
+
+  {*
+   * set background to: video
+   *}
+  fShowVisualization := false;
+  VideoFile := CurrentSong.Path.Append(CurrentSong.Video);
+  if (Ini.VideoEnabled = 1) and CurrentSong.Video.IsSet() and VideoFile.IsFile then
+  begin
+    fVideoClip := VideoPlayback.Open(VideoFile);
+    fCurrentVideo := fVideoClip;
+    if (fVideoClip <> nil) then
+    begin
+      fShowVisualization := false;
+      fCurrentVideo.Position := CurrentSong.VideoGAP + CurrentSong.Start;
+      fCurrentVideo.Play;
+    end;
+  end;
+
+  {*
+   * set background to: picture
+   *}
+  if (CurrentSong.Background.IsSet) and (fVideoClip = nil)
+    and (TVisualizerOption(Ini.VisualizerOption) = voOff)  then
+  begin
+    BgFile := CurrentSong.Path.Append(CurrentSong.Background);
+    try
+      Tex_Background := Texture.LoadTexture(BgFile);
+    except
+      Log.LogError('Background could not be loaded: ' + BgFile.ToNative);
+      Tex_Background.TexNum := 0;
+    end
+  end
+  else
+  begin
+    Tex_Background.TexNum := 0;
+  end;
+
+  {*
+   * set background to: visualization (Overwrites all)
+   *}
+  if (TVisualizerOption(Ini.VisualizerOption) in [voOn]) then
+  begin
+    fShowVisualization := true;
+    fCurrentVideo := Visualization.Open(PATH_NONE);
+    if (fCurrentVideo <> nil) then
+      fCurrentVideo.Play;
+  end;
+
+  {*
+   * set background to: visualization (Videos are still shown)
+   *}
+  if ((TVisualizerOption(Ini.VisualizerOption) in [voWhenNoVideo]) and
+     (fVideoClip = nil)) then
+  begin
+    fShowVisualization := true;
+    fCurrentVideo := Visualization.Open(PATH_NONE);
+    if (fCurrentVideo <> nil) then
+      fCurrentVideo.Play;
+  end;
+
+  // prepare lyrics timer
+  LyricsState.Reset();
+  LyricsState.SetCurrentTime(CurrentSong.Start);
+  LyricsState.StartTime := CurrentSong.Gap;
+  if (CurrentSong.Finish > 0) then
+    LyricsState.TotalTime := CurrentSong.Finish / 1000
+  else
+    LyricsState.TotalTime := AudioPlayback.Length;
+  LyricsState.UpdateBeats();
+
+  BadPlayer := AudioInputProcessor.CheckPlayersConfig(PlayersPlay);
+  if (BadPlayer <> 0) then
+  begin
+    ScreenPopupError.ShowPopup(
+        Format(Language.Translate('ERROR_PLAYER_NO_DEVICE_ASSIGNMENT'),
+        [BadPlayer]));
+  end;
+
+  // prepare and start voice-capture
+  AudioInput.CaptureStart;
+
+  // clear the scores of all players
+
+  for Index := 0 to High(Player) do
+    with Player[Index] do
+    begin
+      Score          := 0;
+      ScoreLine      := 0;
+      ScoreGolden    := 0;
+
+      ScoreInt       := 0;
+      ScoreLineInt   := 0;
+      ScoreGoldenInt := 0;
+      ScoreTotalInt  := 0;
+
+      ScoreLast      := 0;
+
+      LastSentencePerfect := false;
+    end;
+
+  // main text
+  Lyrics.Clear(CurrentSong.BPM[0].BPM, CurrentSong.Resolution);
+
+  // set custom options
+  case Ini.LyricsFont of
+    0: // normal fonts
+    begin
+      Lyrics.FontStyle := ftNormal;
+
+      Lyrics.LineColor_en.R := Skin_FontR;
+      Lyrics.LineColor_en.G := Skin_FontG;
+      Lyrics.LineColor_en.B := Skin_FontB;
+      Lyrics.LineColor_en.A := 1;
+
+      Lyrics.LineColor_dis.R := 0.4;
+      Lyrics.LineColor_dis.G := 0.4;
+      Lyrics.LineColor_dis.B := 0.4;
+      Lyrics.LineColor_dis.A := 1;
+
+      Lyrics.LineColor_act.R := 0.02;
+      Lyrics.LineColor_act.G := 0.6;
+      Lyrics.LineColor_act.B := 0.8;
+      Lyrics.LineColor_act.A := 1;
+    end;
+    1, 2: // outline fonts
+    begin
+      if (Ini.LyricsFont = 1) then
+        Lyrics.FontStyle := ftOutline1
+      else
+        Lyrics.FontStyle := ftOutline2;
+
+      Lyrics.LineColor_en.R := 0.75;
+      Lyrics.LineColor_en.G := 0.75;
+      Lyrics.LineColor_en.B := 1;
+      Lyrics.LineColor_en.A := 1;
+
+      Lyrics.LineColor_dis.R := 0.8;
+      Lyrics.LineColor_dis.G := 0.8;
+      Lyrics.LineColor_dis.B := 0.8;
+      Lyrics.LineColor_dis.A := 1;
+
+      Lyrics.LineColor_act.R := 0.5;
+      Lyrics.LineColor_act.G := 0.5;
+      Lyrics.LineColor_act.B := 1;
+      Lyrics.LineColor_act.A := 1;
+    end;
+  end; // case
+
+  // initialize lyrics by filling its queue
+  while (not Lyrics.IsQueueFull) and
+        (Lyrics.LineCounter <= High(Lines[0].Line)) do
+  begin
+    Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]);
+  end;
+
+  // deactivate pause
+  Paused := false;
+
+  // kill all stars not killed yet (goldenstarstwinkle mod)
+  GoldenRec.SentenceChange;
+
+  // set position of line bonus - line bonus end
+  // set number of empty sentences for line bonus
+  NumEmptySentences := 0;
+  for Index := Low(Lines[0].Line) to High(Lines[0].Line) do
+    if Lines[0].Line[Index].TotalNotes = 0 then
+      Inc(NumEmptySentences);
+
+  eSongLoaded.CallHookChain(False);
+
+  Log.LogStatus('End', 'OnShow');
+end;
+
+procedure TScreenSing.onShowFinish;
+begin
+  // hide cursor on singscreen show    
+  Display.SetCursor;
+
+  // prepare music
+  // Important: AudioPlayback must not be initialized in onShow() as TScreenSong
+  // uses stops AudioPlayback in onHide() which interferes with TScreenSings onShow.
+  AudioPlayback.Open(CurrentSong.Path.Append(CurrentSong.Mp3));
+  AudioPlayback.SetVolume(1.0);
+  AudioPlayback.Position := CurrentSong.Start;
+
+  // synchronize music
+  if (Ini.SyncTo = Ord(stLyrics)) then
+    AudioPlayback.SetSyncSource(fLyricsSync)
+  else
+    AudioPlayback.SetSyncSource(nil);
+
+  // synchronize lyrics (do not set this before AudioPlayback is initialized)
+  if (Ini.SyncTo = Ord(stMusic)) then
+    LyricsState.SetSyncSource(fMusicSync)
+  else
+    LyricsState.SetSyncSource(nil);
+
+  // start lyrics
+  LyricsState.Start(true);
+
+  // start music
+  AudioPlayback.Play();
+
+  // start timer
+  CountSkipTimeSet;
+end;
+
+procedure TScreenSing.ClearSettings;
+begin
+  Settings.Finish := False;
+  Settings.LyricsVisible := True;
+  Settings.NotesVisible := high(Integer);
+  Settings.PlayerEnabled := high(Integer);
+end;
+
+{ applies changes of settings record }
+procedure TScreenSing.ApplySettings;
+begin
+  //
+end;
+
+procedure TScreenSing.EndSong;
+begin
+  Settings.Finish := True;
+end;
+
+procedure TScreenSing.OnHide;
+begin
+  // background texture
+  if (Tex_Background.TexNum > 0) then
+  begin
+    glDeleteTextures(1, PGLuint(@Tex_Background.TexNum));
+    Tex_Background.TexNum := 0;
+  end;
+
+  Background.OnFinish;
+  Display.SetCursor;
+end;
+
+function TScreenSing.Draw: boolean;
+var
+  DisplayTime:  real;
+  DisplayPrefix: string;
+  DisplayMin:   integer;
+  DisplaySec:   integer;
+  T:     integer;
+  CurLyricsTime: real;
+  VideoFrameTime: Extended;
+  Line: TLyricLine;
+  LastWord: TLyricWord;
+begin
+  Background.Draw;
+
+  // draw background picture (if any, and if no visualizations)
+  // when we don't check for visualizations the visualizations would
+  // be overdrawn by the picture when {UNDEFINED UseTexture} in UVisualizer
+  if (not fShowVisualization) then
+    SingDrawBackground;
+
+  // set player names (for 2 screens and only singstar skin)
+  if ScreenAct = 1 then
+  begin
+    Text[TextP1].Text     := 'P1';
+    Text[TextP1TwoP].Text := 'P1';
+    Text[TextP1ThreeP].Text := 'P1';
+    Text[TextP2R].Text    := 'P2';
+    Text[TextP2M].Text    := 'P2';
+    Text[TextP3R].Text    := 'P3';
+  end;
+
+  if ScreenAct = 2 then
+  begin
+    case PlayersPlay of
+      4:
+      begin
+        Text[TextP1TwoP].Text := 'P3';
+        Text[TextP2R].Text    := 'P4';
+      end;
+      6:
+      begin
+        Text[TextP1ThreeP].Text := 'P4';
+        Text[TextP2M].Text      := 'P5';
+        Text[TextP3R].Text      := 'P6';
+      end;
+    end; // case
+  end; // if
+
+  // retrieve current lyrics time, we have to store the value to avoid
+  // that min- and sec-values do not match
+  CurLyricsTime := LyricsState.GetCurrentTime();
+
+  // retrieve time for timebar text
+  case (fTimebarMode) of
+    tbmRemaining: begin
+      DisplayTime := LyricsState.TotalTime - CurLyricsTime;
+      DisplayPrefix := '-';
+    end;
+    tbmTotal: begin
+      DisplayTime := LyricsState.TotalTime;
+      DisplayPrefix := '#';
+    end;
+    else begin
+      DisplayTime := CurLyricsTime;
+      DisplayPrefix := '';
+    end;
+  end;
+  DisplayMin := Round(DisplayTime) div 60;
+  DisplaySec := Round(DisplayTime) mod 60;
+
+  // update static menu with time ...
+  Text[TextTimeText].Text := Format('%s%.2d:%.2d',
+      [DisplayPrefix, DisplayMin, DisplaySec]);
+
+  //the song was sung to the end?
+  Line := Lyrics.GetUpperLine();
+  if Line.LastLine then
+  begin
+    LastWord := Line.Words[Length(Line.Words)-1];
+    if CurLyricsTime >= GetTimeFromBeat(LastWord.Start+LastWord.Length) then
+      SungToEnd := true;
+  end;
+
+  // update and draw movie
+  if Assigned(fCurrentVideo) then
+  begin
+    // Just call this once
+    // when Screens = 2
+    if (ScreenAct = 1) then
+    begin
+      if (ShowFinish) then
+      begin
+        // everything is setup, determine the current position 
+        VideoFrameTime := CurrentSong.VideoGAP + LyricsState.GetCurrentTime();
+      end
+      else
+      begin
+        // Important: do not yet start the triggered timer by a call to
+        // LyricsState.GetCurrentTime()
+        VideoFrameTime := CurrentSong.VideoGAP;
+      end;
+      fCurrentVideo.GetFrame(VideoFrameTime);
+    end;
+
+    fCurrentVideo.SetScreen(ScreenAct);
+    fCurrentVideo.Draw;
+  end;
+
+  // draw static menu (FG)
+  DrawFG;
+
+  // check for music finish
+  //Log.LogError('Check for music finish: ' + BoolToStr(Music.Finished) + ' ' + FloatToStr(LyricsState.CurrentTime*1000) + ' ' + IntToStr(CurrentSong.Finish));
+  if ShowFinish then
+  begin
+    if (not AudioPlayback.Finished) and
+       ((CurrentSong.Finish = 0) or
+        (LyricsState.GetCurrentTime() * 1000 <= CurrentSong.Finish)) and
+       (not Settings.Finish) then
+    begin
+      // analyze song if not paused
+      if (not Paused) then
+      begin
+        Sing(Self);
+        Party.CallOnSing;
+      end;
+    end
+    else
+    begin
+      if (not FadeOut) and (Screens=1) or (ScreenAct=2) then
+      begin
+        Finish;
+        FadeOut := true;
+      end;
+    end;
+  end;
+
+  // always draw custom items
+  SingDraw;
+
+  // goldennotestarstwinkle
+  GoldenRec.SpawnRec;
+
+  // draw scores
+  Scores.Draw;
+
+  // draw pausepopup
+  // FIXME: this is a workaround that the static is drawn over the lyrics, lines, scores and effects
+  // maybe someone could find a better solution
+  if Paused then
+  begin
+    Statics[StaticPausePopup].Visible := true;
+    Statics[StaticPausePopup].Draw;
+    Statics[StaticPausePopup].Visible := false;
+  end;
+
+  Result := true;
+end;
+
+procedure TScreenSing.Finish;
+begin
+  AudioInput.CaptureStop;
+  AudioPlayback.Stop;
+  AudioPlayback.SetSyncSource(nil);
+
+  LyricsState.Stop();
+  LyricsState.SetSyncSource(nil);
+
+  // close video files
+  fVideoClip := nil;
+  fCurrentVideo := nil;
+
+  // kill all stars and effects
+  GoldenRec.KillAll;
+
+  if (Ini.SavePlayback = 1) then
+  begin
+    Log.BenchmarkStart(0);
+    Log.LogVoice(0);
+    Log.LogVoice(1);
+    Log.LogVoice(2);
+    Log.BenchmarkEnd(0);
+    Log.LogBenchmark('Creating files', 0);
+  end;
+
+  SetFontItalic(false);
+
+  if not FadeOut then
+    Party.CallAfterSing;
+end;
+
+procedure TScreenSing.OnSentenceEnd(SentenceIndex: cardinal);
+var
+  PlayerIndex: byte;
+  CurrentPlayer: PPLayer;
+  CurrentScore: real;
+  Line:      PLine;
+  LinePerfection: real;  // perfection of singing performance on the current line
+  Rating:    integer;
+  LineScore: real;
+  LineBonus: real;
+  MaxSongScore: integer; // max. points for the song (without line bonus)
+  MaxLineScore: real;    // max. points for the current line
+const
+  // TODO: move this to a better place
+  MAX_LINE_RATING = 8;        // max. rating for singing performance
+begin
+  Line := @Lines[0].Line[SentenceIndex];
+
+  // check for empty sentence
+  if (Line.TotalNotes <= 0) then
+    Exit;
+
+  // set max song score
+  if (Ini.LineBonus = 0) then
+    MaxSongScore := MAX_SONG_SCORE
+  else
+    MaxSongScore := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS;
+
+  // Note: ScoreValue is the sum of all note values of the song
+  MaxLineScore := MaxSongScore * (Line.TotalNotes / Lines[0].ScoreValue);
+
+  for PlayerIndex := 0 to High(Player) do
+  begin
+    CurrentPlayer := @Player[PlayerIndex];
+    CurrentScore  := CurrentPlayer.Score + CurrentPlayer.ScoreGolden;
+
+    // line bonus
+
+    // points for this line
+    LineScore := CurrentScore - CurrentPlayer.ScoreLast;
+
+    // check for lines with low points
+    if (MaxLineScore <= 2) then
+      LinePerfection := 1
+    else
+      // determine LinePerfection
+      // Note: the "+2" extra points are a little bonus so the player does not
+      // have to be that perfect to reach the bonus steps.
+      LinePerfection := LineScore / (MaxLineScore - 2);
+
+    // clamp LinePerfection to range [0..1]
+    if (LinePerfection < 0) then
+      LinePerfection := 0
+    else if (LinePerfection > 1) then
+      LinePerfection := 1;
+
+    // add line-bonus if enabled
+    if (Ini.LineBonus > 0) then
+    begin
+      // line-bonus points (same for each line, no matter how long the line is)
+      LineBonus := MAX_SONG_LINE_BONUS / (Length(Lines[0].Line) -
+        NumEmptySentences);
+      // apply line-bonus
+      CurrentPlayer.ScoreLine :=
+        CurrentPlayer.ScoreLine + LineBonus * LinePerfection;
+      CurrentPlayer.ScoreLineInt := Floor(CurrentPlayer.ScoreLine / 10) * 10;
+      // update total score
+      CurrentPlayer.ScoreTotalInt :=
+        CurrentPlayer.ScoreInt +
+        CurrentPlayer.ScoreGoldenInt
+        + CurrentPlayer.ScoreLineInt;
+
+      // spawn rating pop-up
+      Rating := Round(LinePerfection * MAX_LINE_RATING);
+      Scores.SpawnPopUp(PlayerIndex, Rating, CurrentPlayer.ScoreTotalInt);
+    end
+    else
+      Scores.RaiseScore(PlayerIndex, CurrentPlayer.ScoreTotalInt);
+
+    // PerfectLineTwinkle (effect), part 1
+    if (Ini.EffectSing = 1) then
+      CurrentPlayer.LastSentencePerfect := (LinePerfection >= 1);
+
+    // refresh last score
+    CurrentPlayer.ScoreLast := CurrentScore;
+  end;
+
+  // PerfectLineTwinkle (effect), part 2
+  if (Ini.EffectSing = 1) then
+    GoldenRec.SpawnPerfectLineTwinkle;
+end;
+
+ // Called on sentence change
+ // SentenceIndex: index of the new active sentence
+procedure TScreenSing.OnSentenceChange(SentenceIndex: cardinal);
+begin
+  // goldenstarstwinkle
+  GoldenRec.SentenceChange;
+
+  // fill lyrics queue and set upper line to the current sentence
+  while (Lyrics.GetUpperLineIndex() < SentenceIndex) or
+    (not Lyrics.IsQueueFull) do
+  begin
+    // add the next line to the queue or a dummy if no more lines are available
+    if (Lyrics.LineCounter <= High(Lines[0].Line)) then
+      Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter])
+    else
+      Lyrics.AddLine(nil);
+  end;
+end;
+
+function TLyricsSyncSource.GetClock(): real;
+begin
+  Result := LyricsState.GetCurrentTime();
+end;
+
+function TMusicSyncSource.GetClock(): real;
+begin
+  Result := AudioPlayback.Position;
+end;
+
+end.
+
diff --git a/songmanagement/src/screens/UScreenSong.pas b/songmanagement/src/screens/UScreenSong.pas
new file mode 100644
index 00000000..6fe8d204
--- /dev/null
+++ b/songmanagement/src/screens/UScreenSong.pas
@@ -0,0 +1,2156 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenSong;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  SDL,
+  UCommon,
+  UDisplay,
+  UPath,
+  UFiles,
+  UIni,
+  ULanguage,
+  ULog,
+  UMenu,
+  UMenuEqualizer,
+  UMusic,
+  USong,
+  USongs,
+  UTexture,
+  UThemes,
+  UTime;
+
+type
+  TScreenSong = class(TMenu)
+    private
+      Equalizer: Tms_Equalizer;
+
+      PreviewOpened: Integer; // interaction of the Song that is loaded for preview music
+                              // -1 if nothing is opened
+
+      isScrolling: boolean;   // true if song flow is about to move
+
+      fCurrentVideo: IVideo;
+
+      procedure StartMusicPreview();
+      procedure StopMusicPreview();
+      procedure StartVideoPreview();
+      procedure StopVideoPreview();
+    public
+      TextArtist:   integer;
+      TextTitle:    integer;
+      TextNumber:   integer;
+
+      //Video Icon Mod
+      VideoIcon: cardinal;
+
+      TextCat:   integer;
+      StaticCat: integer;
+
+      SongCurrent:  real;
+      SongTarget:   real;
+
+      HighSpeed:    boolean;
+      CoverFull:    boolean;
+      CoverTime:    real;
+
+      CoverX:       integer;
+      CoverY:       integer;
+      CoverW:       integer;
+      is_jump:      boolean; // Jump to Song Mod
+      is_jump_title:boolean; //Jump to SOng MOd-YTrue if search for Title
+
+      //Party Mod
+      Mode: TSingMode;
+
+      //party Statics (Joker)
+      StaticTeam1Joker1: cardinal;
+      StaticTeam1Joker2: cardinal;
+      StaticTeam1Joker3: cardinal;
+      StaticTeam1Joker4: cardinal;
+      StaticTeam1Joker5: cardinal;
+
+      StaticTeam2Joker1: cardinal;
+      StaticTeam2Joker2: cardinal;
+      StaticTeam2Joker3: cardinal;
+      StaticTeam2Joker4: cardinal;
+      StaticTeam2Joker5: cardinal;
+
+      StaticTeam3Joker1: cardinal;
+      StaticTeam3Joker2: cardinal;
+      StaticTeam3Joker3: cardinal;
+      StaticTeam3Joker4: cardinal;
+      StaticTeam3Joker5: cardinal;
+
+      StaticParty:    array of cardinal;
+      TextParty:      array of cardinal;
+      StaticNonParty: array of cardinal;
+      TextNonParty:   array of cardinal;
+
+      constructor Create; override;
+      procedure SetScroll;
+      //procedure SetScroll1;
+      //procedure SetScroll2;
+      procedure SetScroll3;
+      procedure SetScroll4;
+      procedure SetScroll5;
+      procedure SetScroll6;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      function ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; override;
+      function Draw: boolean; override;
+      procedure GenerateThumbnails();
+      procedure OnShow; override;
+      procedure OnShowFinish; override;
+      procedure OnHide; override;
+      procedure SelectNext;
+      procedure SelectPrev;
+      procedure SkipTo(Target: cardinal);
+      procedure FixSelected; //Show Wrong Song when Tabs on Fix
+      procedure FixSelected2; //Show Wrong Song when Tabs on Fix
+      procedure ShowCatTL(Cat: integer);// Show Cat in Top left
+      procedure ShowCatTLCustom(Caption: UTF8String);// Show Custom Text in Top left
+      procedure HideCatTL;// Show Cat in Tob left
+      procedure Refresh; //Refresh Song Sorting
+      procedure ChangeMusic;
+      //Party Mode
+      procedure SelectRandomSong;
+      procedure SetJoker;
+      procedure SetStatics;
+      //procedures for Menu
+      procedure StartSong;
+      procedure OpenEditor;
+      procedure DoJoker(Team: integer);
+      procedure SelectPlayers;
+
+      procedure OnSongSelect;   // called when song flows movement stops at a song
+      procedure OnSongDeSelect; // called before current song is deselected
+
+      procedure UnloadDetailedCover;
+
+      //Extensions
+      procedure DrawExtensions;
+  end;
+
+implementation
+
+uses
+  Math,
+  gl,
+  UCovers,
+  UGraphic,
+  UMain,
+  UMenuButton,
+  UNote,
+  UParty,
+  UPlaylist,
+  UScreenSongMenu,
+  USkins,
+  UUnicodeUtils;
+
+// ***** Public methods ****** //
+
+//Show Wrong Song when Tabs on Fix
+procedure TScreenSong.FixSelected;
+var
+  I, I2: integer;
+begin
+  if CatSongs.VisibleSongs > 0 then
+  begin
+    I2:= 0;
+    for I := Low(CatSongs.Song) to High(Catsongs.Song) do
+    begin
+      if CatSongs.Song[I].Visible then
+        inc(I2);
+
+      if I = Interaction - 1 then
+        break;
+    end;
+
+    SongCurrent := I2;
+    SongTarget  := I2;
+  end;
+end;
+
+procedure TScreenSong.FixSelected2;
+var
+  I, I2: integer;
+begin
+  if CatSongs.VisibleSongs > 0 then
+  begin
+    I2:= 0;
+    for I := Low(CatSongs.Song) to High(Catsongs.Song) do
+    begin
+      if CatSongs.Song[I].Visible then
+        inc(I2);
+
+      if I = Interaction - 1 then
+        break;
+    end;
+
+    SongTarget  := I2;
+  end;
+end;
+//Show Wrong Song when Tabs on Fix End
+
+procedure TScreenSong.ShowCatTLCustom(Caption: UTF8String);// Show Custom Text in Top left
+begin
+  Text[TextCat].Text := Caption;
+  Text[TextCat].Visible := true;
+  Statics[StaticCat].Visible := false;
+end;
+
+//Show Cat in Top Left Mod
+procedure TScreenSong.ShowCatTL(Cat: integer);
+begin
+  //Change
+  Text[TextCat].Text := CatSongs.Song[Cat].Artist;
+  //Statics[StaticCat].Texture := Texture.GetTexture(Button[Cat].Texture.Name, TEXTURE_TYPE_PLAIN, true);
+
+  //Show
+  Text[TextCat].Visible := true;
+  Statics[StaticCat].Visible := true;
+end;
+
+procedure TScreenSong.HideCatTL;
+begin
+  //Hide
+  //Text[TextCat].Visible := false;
+  Statics[StaticCat].Visible := false;
+  //New -> Show Text specified in Theme
+  Text[TextCat].Visible := true;
+  Text[TextCat].Text := Theme.Song.TextCat.Text;
+end;
+//Show Cat in Top Left Mod End
+
+// Method for input parsing. If false is returned, GetNextWindow
+// should be checked to know the next window to load;
+function TScreenSong.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+  I:      integer;
+  I2:     integer;
+  SDL_ModState:  word;
+  UpperLetter: UCS4Char;
+  TempStr: UTF8String;
+begin
+  Result := true;
+
+  //Song Screen Extensions (Jumpto + Menu)
+  if (ScreenSongMenu.Visible) then
+  begin
+    Result := ScreenSongMenu.ParseInput(PressedKey, CharCode, PressedDown);
+    Exit;
+  end
+  else if (ScreenSongJumpto.Visible) then
+  begin
+    Result := ScreenSongJumpto.ParseInput(PressedKey, CharCode, PressedDown);
+    Exit;
+  end;
+
+  if (PressedDown) then
+  begin // Key Down
+
+    SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT
+    + KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT  + KMOD_RALT);
+
+    //Jump to Artist/Titel
+    if ((SDL_ModState and KMOD_LALT <> 0) and (Mode = smNormal)) then
+    begin
+      UpperLetter := UCS4UpperCase(CharCode);
+
+      if (UpperLetter in ([Ord('A')..Ord('Z'), Ord('0') .. Ord('9')]) ) then
+      begin
+        I2 := Length(CatSongs.Song);
+
+        //Jump To Titel
+        if (SDL_ModState = (KMOD_LALT or KMOD_LSHIFT)) then
+        begin
+          for I := 1 to High(CatSongs.Song) do
+          begin
+            if (CatSongs.Song[(I + Interaction) mod I2].Visible) then
+            begin
+              TempStr := CatSongs.Song[(I + Interaction) mod I2].Title;
+              if (Length(TempStr) > 0) and
+                 (UCS4UpperCase(UTF8ToUCS4String(TempStr)[0]) = UpperLetter) then
+              begin
+                SkipTo(CatSongs.VisibleIndex((I + Interaction) mod I2));
+
+                AudioPlayback.PlaySound(SoundLib.Change);
+
+                SetScroll4;
+                //Break and Exit
+                Exit;
+              end;
+            end;
+          end;
+        end
+        //Jump to Artist
+        else if (SDL_ModState = KMOD_LALT) then
+        begin
+          for I := 1 to High(CatSongs.Song) do
+          begin
+            if (CatSongs.Song[(I + Interaction) mod I2].Visible) then
+            begin
+              TempStr := CatSongs.Song[(I + Interaction) mod I2].Artist;
+              if (Length(TempStr) > 0) and
+                 (UCS4UpperCase(UTF8ToUCS4String(TempStr)[0]) = UpperLetter) then
+              begin
+                SkipTo(CatSongs.VisibleIndex((I + Interaction) mod I2));
+
+                AudioPlayback.PlaySound(SoundLib.Change);
+
+                SetScroll4;
+
+                //Break and Exit
+                Exit;
+              end;
+            end;
+          end;
+        end;
+      end;
+
+      Exit;
+    end;
+
+    // **********************
+    // * workaround for LCTRL+R: it should be changed when we have a solution for the
+    // * CTRL+'A'..'Z' problem
+    if (SDL_ModState = KMOD_LCTRL) and (PressedKey = SDLK_R) then
+      CharCode := UCS4Char('R');
+    // **********************
+
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+
+      Ord('M'): //Show SongMenu
+        begin
+          if (Songs.SongList.Count > 0) then
+          begin
+            if (Mode = smNormal) then
+            begin
+              if (not CatSongs.Song[Interaction].Main) then // clicked on Song
+              begin 
+                if CatSongs.CatNumShow = -3 then
+                begin
+                  ScreenSongMenu.OnShow;
+                  ScreenSongMenu.MenuShow(SM_Playlist);
+                end
+                else
+                begin
+                  ScreenSongMenu.OnShow;
+                  ScreenSongMenu.MenuShow(SM_Main);
+                end;
+              end
+              else
+              begin
+                ScreenSongMenu.OnShow;
+                ScreenSongMenu.MenuShow(SM_Playlist_Load);
+              end;
+            end //Party Mode -> Show Party Menu
+            else
+            begin
+              ScreenSongMenu.OnShow;
+              ScreenSongMenu.MenuShow(SM_Party_Main);
+            end;
+          end;
+          Exit;
+        end;
+
+      Ord('P'): //Show Playlist Menu
+        begin
+          if (Songs.SongList.Count > 0) and (Mode = smNormal) then
+          begin
+            ScreenSongMenu.OnShow;
+            ScreenSongMenu.MenuShow(SM_Playlist_Load);
+          end;
+          Exit;
+        end;
+
+      Ord('J'): //Show Jumpto Menu
+        begin
+          if (Songs.SongList.Count > 0) and (Mode = smNormal) then
+          begin
+            ScreenSongJumpto.Visible := true;
+          end;
+          Exit;
+        end;
+
+      Ord('E'):
+        begin
+          OpenEditor;
+          Exit;
+        end;
+
+      Ord('R'):
+        begin
+          if (Songs.SongList.Count > 0) and
+             (Mode = smNormal) then
+          begin
+            if (SDL_ModState = KMOD_LSHIFT) and (Ini.TabsAtStartup = 1) then // random category
+            begin
+              I2 := 0; // count cats
+              for I := 0 to High(CatSongs.Song) do
+              begin
+                if CatSongs.Song[I].Main then
+                  Inc(I2);
+              end;
+
+              I2 := Random(I2 + 1); // random and include I2
+
+              // find cat:
+              for I := 0 to High(CatSongs.Song) do
+                begin
+                if CatSongs.Song[I].Main then
+                  Dec(I2);
+                if (I2 <= 0) then
+                begin
+                  // show cat in top left mod
+                  ShowCatTL (I);
+
+                  Interaction := I;
+
+                  CatSongs.ShowCategoryList;
+                  CatSongs.ClickCategoryButton(I);
+                  SelectNext;
+                  FixSelected;
+                  break;
+                end;
+              end;
+            end
+            else if (SDL_ModState = KMOD_LCTRL) and (Ini.TabsAtStartup = 1) then // random in all categories
+            begin
+              repeat
+                I2 := Random(High(CatSongs.Song) + 1);
+              until (not CatSongs.Song[I2].Main);
+
+              // search cat
+              for I := I2 downto 0 do
+              begin
+              if CatSongs.Song[I].Main then
+                break;
+              end;
+              
+              // in I is now the categorie in I2 the song
+
+              // choose cat
+              CatSongs.ShowCategoryList;
+
+              // show cat in top left mod
+              ShowCatTL (I);
+
+              CatSongs.ClickCategoryButton(I);
+              SelectNext;
+
+              // Fix: not existing song selected:
+              //if (I + 1 = I2) then
+                Inc(I2);
+
+              // choose song
+              SkipTo(I2 - I);
+            end
+            else // random in one category
+            begin
+              SkipTo(Random(CatSongs.VisibleSongs));
+            end;
+            AudioPlayback.PlaySound(SoundLib.Change);
+
+            SetScroll4;
+          end;
+          Exit;
+        end;
+    end; // normal keys
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          if (Mode = smNormal) then
+          begin
+            //On Escape goto Cat-List Hack
+            if (Ini.TabsAtStartup = 1) and (CatSongs.CatNumShow <> -1) then
+              begin
+              //Find Category
+              I := Interaction;
+              while (not CatSongs.Song[I].Main) do
+              begin
+                Dec(I);
+                if (I < 0) then
+                  break;
+              end;
+              if (I <= 1) then
+                Interaction := High(CatSongs.Song)
+              else
+                Interaction := I - 1;
+
+              //Stop Music
+              StopMusicPreview();
+
+              CatSongs.ShowCategoryList;
+
+              //Show Cat in Top Left Mod
+              HideCatTL;
+
+              //Show Wrong Song when Tabs on Fix
+              SelectNext;
+              FixSelected;
+              //SelectPrev(true);
+              //CatSongs.Song[0].Visible := false;
+              end
+            else
+            begin
+            //On Escape goto Cat-List Hack End
+              //Tabs off and in Search or Playlist -> Go back to Song view
+              if (CatSongs.CatNumShow < -1) then
+              begin
+                //Atm: Set Empty Filter
+                CatSongs.SetFilter('', fltAll);
+
+                //Show Cat in Top Left Mod
+                HideCatTL;
+                Interaction := 0;
+
+                //Show Wrong Song when Tabs on Fix
+                SelectNext;
+                FixSelected;
+              end
+              else
+              begin
+                StopMusicPreview();
+                AudioPlayback.PlaySound(SoundLib.Back);
+
+                FadeTo(@ScreenMain);
+              end;
+
+            end;
+          end
+          //When in party Mode then Ask before Close
+          else if (Mode = smPartyMode) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Back);
+            CheckFadeTo(@ScreenMain,'MSG_END_PARTY');
+          end;
+        end;
+      SDLK_RETURN:
+        begin
+          if (Songs.SongList.Count > 0) then
+          begin
+            if CatSongs.Song[Interaction].Main then
+            begin // clicked on Category Button
+              //Show Cat in Top Left Mod
+              ShowCatTL (Interaction);
+
+              //I := CatSongs.VisibleIndex(Interaction);
+              CatSongs.ClickCategoryButton(Interaction);
+              {I2 := CatSongs.VisibleIndex(Interaction);
+              SongCurrent := SongCurrent - I + I2;
+              SongTarget := SongTarget - I + I2; }
+
+              //  SetScroll4;
+
+              //Show Wrong Song when Tabs on Fix
+              SelectNext;
+              FixSelected;
+            end
+            else
+            begin // clicked on song
+              if (Mode = smNormal) then //Normal Mode -> Start Song
+              begin
+                //Do the Action that is specified in Ini
+                case Ini.OnSongClick of
+                  0: StartSong;
+                  1: SelectPlayers;
+                  2:begin
+                      if (CatSongs.CatNumShow = -3) then
+                        ScreenSongMenu.MenuShow(SM_Playlist)
+                      else
+                        ScreenSongMenu.MenuShow(SM_Main);
+                    end;
+                end;
+              end
+              else if (Mode = smPartyMode) then //PartyMode -> Show Menu
+              begin
+                if (Ini.PartyPopup = 1) then
+                  ScreenSongMenu.MenuShow(SM_Party_Main)
+                else
+                  Party.CallAfterSongSelect;
+              end;
+            end;
+          end;
+        end;
+
+      SDLK_DOWN:
+        begin
+          if (Mode = smNormal) then
+          begin
+            //Only Change Cat when not in Playlist or Search Mode
+            if (CatSongs.CatNumShow > -2) then
+            begin
+              //Cat Change Hack
+              if Ini.TabsAtStartup = 1 then
+              begin
+                I := Interaction;
+                if I <= 0 then
+                  I := 1;
+
+                while not catsongs.Song[I].Main do
+                begin
+                  Inc (I);
+                  if (I > High(catsongs.Song)) then
+                    I := Low(catsongs.Song);
+                end;
+
+                Interaction := I;
+
+                //Show Cat in Top Left Mod
+                ShowCatTL (Interaction);
+
+                CatSongs.ClickCategoryButton(Interaction);
+                SelectNext;
+                FixSelected;
+
+                //Play Music:
+                AudioPlayback.PlaySound(SoundLib.Change);
+              end;
+
+            //
+            //Cat Change Hack End}
+            end;
+          end;
+        end;
+      SDLK_UP:
+        begin
+          if (Mode = smNormal) then
+          begin
+            //Only Change Cat when not in Playlist or Search Mode
+            if (CatSongs.CatNumShow > -2) then
+            begin
+              //Cat Change Hack
+              if Ini.TabsAtStartup = 1 then
+              begin
+                I := Interaction;
+                I2 := 0;
+                if I <= 0 then
+                  I := 1;
+
+                while not catsongs.Song[I].Main or (I2 = 0) do
+                begin
+                  if catsongs.Song[I].Main then
+                    Inc(I2);
+                  Dec (I);
+                  if (I < Low(catsongs.Song)) then
+                    I := High(catsongs.Song);
+                end;
+
+                Interaction := I;
+
+                //Show Cat in Top Left Mod
+                ShowCatTL (I);
+
+                CatSongs.ClickCategoryButton(I);
+                SelectNext;
+                FixSelected;
+
+                //Play Music:
+                AudioPlayback.PlaySound(SoundLib.Change);
+              end;
+            end;
+            //Cat Change Hack End}
+          end;
+        end;
+
+      SDLK_RIGHT:
+        begin
+          if (Songs.SongList.Count > 0) and (Mode = smNormal) then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Change);
+            SelectNext;
+            SetScroll4;
+          end;
+        end;
+
+      SDLK_LEFT:
+        begin
+          if (Songs.SongList.Count > 0)and (Mode = smNormal)  then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Change);
+            SelectPrev;
+            SetScroll4;
+          end;
+        end;
+
+      SDLK_1:
+        begin //Joker
+          DoJoker(0);
+        end;
+
+      SDLK_2:
+        begin //Joker
+          DoJoker(1);
+        end;
+
+      SDLK_3:
+        begin //Joker
+          DoJoker(2);
+        end;
+    end;
+  end; // if (PressedDown)
+end;
+
+function TScreenSong.ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean;
+  var
+    I, J: Integer;
+    Btn: Integer;
+begin
+  Result := true;
+
+  if (ScreenSongMenu.Visible) then
+  begin
+    Result := ScreenSongMenu.ParseMouse(MouseButton, BtnDown, X, Y);
+    exit;
+  end
+  else if (ScreenSongJumpTo.Visible) then
+  begin
+    Result := ScreenSongJumpTo.ParseMouse(MouseButton, BtnDown, X, Y);
+    exit;
+  end
+  else // no extension visible
+  begin
+    if (BtnDown) then
+    begin
+      //if RightMbESC is set, send ESC keypress
+      if RightMbESC and (MouseButton = SDL_BUTTON_RIGHT) then
+        Result:=ParseInput(SDLK_ESCAPE, 0, true)
+
+     //song scrolling with mousewheel
+      else if (MouseButton = SDL_BUTTON_WHEELDOWN) then
+        ParseInput(SDLK_RIGHT, 0, true)
+
+      else if (MouseButton = SDL_BUTTON_WHEELUP) then
+        ParseInput(SDLK_LEFT, 0, true)
+
+      //LMB anywhere starts
+      else if (MouseButton = SDL_BUTTON_LEFT) then
+      begin
+        if (CatSongs.VisibleSongs > 4) then
+        begin
+          // select the second visible button left from selected
+          I := 0;
+          Btn := Interaction;
+          while (I < 2) do
+          begin
+            Dec(Btn);
+            if (Btn < 0) then
+              Btn := High(CatSongs.Song);
+
+            if (CatSongs.Song[Btn].Visible) then
+              Inc(I);
+          end;
+
+          // test the 5 front buttons for click
+          for I := 0 to 4 do
+          begin
+            if InRegion(X, Y, Button[Btn].GetMouseOverArea) then
+            begin
+              // song cover clicked
+              if (I = 2) then
+              begin // Selected Song clicked -> start singing
+                ParseInput(SDLK_RETURN, 0, true);
+              end
+              else
+              begin // one of the other 4 covers in the front clicked -> select it
+                J := I - 2;
+                while (J < 0) do
+                begin
+                  ParseInput(SDLK_LEFT, 0, true);
+                  Inc(J);
+                end;
+
+                while (J > 0) do
+                begin
+                  ParseInput(SDLK_RIGHT, 0, true);
+                  Dec(J);
+                end;
+              end;
+              Break;
+            end;
+
+            Btn := CatSongs.FindNextVisible(Btn);
+            if (Btn = -1) then
+              Break;
+          end;
+        end
+        else
+          ParseInput(SDLK_RETURN, 0, true);
+      end;
+    end;
+  end;
+end;
+
+constructor TScreenSong.Create;
+var
+  i: integer;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.Song);
+
+  TextArtist := AddText(Theme.Song.TextArtist);
+  TextTitle :=  AddText(Theme.Song.TextTitle);
+  TextNumber := AddText(Theme.Song.TextNumber);
+
+  //Show Cat in Top Left mod
+  TextCat := AddText(Theme.Song.TextCat);
+  StaticCat :=  AddStatic(Theme.Song.StaticCat);
+
+  //Show Video Icon Mod
+  VideoIcon := AddStatic(Theme.Song.VideoIcon);
+
+  //Party Mode
+  StaticTeam1Joker1 := AddStatic(Theme.Song.StaticTeam1Joker1);
+  StaticTeam1Joker2 := AddStatic(Theme.Song.StaticTeam1Joker2);
+  StaticTeam1Joker3 := AddStatic(Theme.Song.StaticTeam1Joker3);
+  StaticTeam1Joker4 := AddStatic(Theme.Song.StaticTeam1Joker4);
+  StaticTeam1Joker5 := AddStatic(Theme.Song.StaticTeam1Joker5);
+
+  StaticTeam2Joker1 := AddStatic(Theme.Song.StaticTeam2Joker1);
+  StaticTeam2Joker2 := AddStatic(Theme.Song.StaticTeam2Joker2);
+  StaticTeam2Joker3 := AddStatic(Theme.Song.StaticTeam2Joker3);
+  StaticTeam2Joker4 := AddStatic(Theme.Song.StaticTeam2Joker4);
+  StaticTeam2Joker5 := AddStatic(Theme.Song.StaticTeam2Joker5);
+
+  StaticTeam3Joker1 := AddStatic(Theme.Song.StaticTeam3Joker1);
+  StaticTeam3Joker2 := AddStatic(Theme.Song.StaticTeam3Joker2);
+  StaticTeam3Joker3 := AddStatic(Theme.Song.StaticTeam3Joker3);
+  StaticTeam3Joker4 := AddStatic(Theme.Song.StaticTeam3Joker4);
+  StaticTeam3Joker5 := AddStatic(Theme.Song.StaticTeam3Joker5);
+
+  //Load Party or NonParty specific Statics and Texts
+  SetLength(StaticParty, Length(Theme.Song.StaticParty));
+  for i := 0 to High(Theme.Song.StaticParty) do
+    StaticParty[i] := AddStatic(Theme.Song.StaticParty[i]);
+
+  SetLength(TextParty, Length(Theme.Song.TextParty));
+  for i := 0 to High(Theme.Song.TextParty) do
+    TextParty[i] := AddText(Theme.Song.TextParty[i]);
+
+  SetLength(StaticNonParty, Length(Theme.Song.StaticNonParty));
+  for i := 0 to High(Theme.Song.StaticNonParty) do
+    StaticNonParty[i] := AddStatic(Theme.Song.StaticNonParty[i]);
+
+  SetLength(TextNonParty, Length(Theme.Song.TextNonParty));
+  for i := 0 to High(Theme.Song.TextNonParty) do
+    TextNonParty[i] := AddText(Theme.Song.TextNonParty[i]);
+
+  // Song List
+  //Songs.LoadSongList; // moved to the UltraStar unit
+  CatSongs.Refresh;
+
+  GenerateThumbnails();
+
+  // Randomize Patch
+  Randomize;
+
+  Equalizer := Tms_Equalizer.Create(AudioPlayback, Theme.Song.Equalizer);
+
+  PreviewOpened := -1;
+  isScrolling := false;
+
+  fCurrentVideo := nil;
+end;
+
+procedure TScreenSong.GenerateThumbnails();
+var
+  I: integer;
+  CoverButtonIndex: integer;
+  CoverButton: TButton;
+  CoverTexture: TTexture;
+  Cover: TCover;
+  CoverFile: IPath;
+  Song: TSong;
+begin
+  if (Length(CatSongs.Song) <= 0) then
+    Exit;
+
+  // set length of button array once instead for every song
+  SetButtonLength(Length(CatSongs.Song));
+
+  // create all buttons
+  for I := 0 to High(CatSongs.Song) do
+  begin
+    CoverButton := nil;
+
+    // create a clickable cover
+    CoverButtonIndex := AddButton(300 + I*250, 140, 200, 200, PATH_NONE, TEXTURE_TYPE_PLAIN, Theme.Song.Cover.Reflections);
+    if (CoverButtonIndex > -1) then
+      CoverButton := Button[CoverButtonIndex];
+    if (CoverButton = nil) then
+      Continue;
+
+    Song := CatSongs.Song[I];
+
+    CoverFile := Song.Path.Append(Song.Cover);
+    if (not CoverFile.IsFile()) then
+      Song.Cover := PATH_NONE;
+
+    if (Song.Cover.IsUnset) then
+      CoverFile := Skin.GetTextureFileName('SongCover');
+
+    // load cover and cache its texture
+    Cover := Covers.FindCover(CoverFile);
+    if (Cover = nil) then
+      Cover := Covers.AddCover(CoverFile);
+
+    // use the cached texture
+    // TODO: this is a workaround until the new song-loading works.
+    // The TCover object should be added to the song-object. The thumbnails
+    // should be loaded each time the song-screen is shown (it is real fast).
+    // This way, we will not waste that much memory and have a link between
+    // song and cover.
+    if (Cover <> nil) then
+    begin
+      CoverTexture := Cover.GetPreviewTexture();
+      Texture.AddTexture(CoverTexture, TEXTURE_TYPE_PLAIN, true);
+      CoverButton.Texture := CoverTexture;
+
+      // set selected to false -> the right texture will be displayed
+      CoverButton.Selected := False;
+    end;
+
+    Cover.Free;
+  end;
+
+  // reset selection
+  if (Length(CatSongs.Song) > 0) then
+    Interaction := 0;
+end;
+
+{ called when song flows movement stops at a song }
+procedure TScreenSong.OnSongSelect;
+begin
+  if (Ini.PreviewVolume <> 0) then
+  begin
+    StartMusicPreview;
+    StartVideoPreview;
+  end;
+
+  // fade in detailed cover
+  CoverTime := 0;
+end;
+
+{ called before current song is deselected }
+procedure TScreenSong.OnSongDeSelect;
+begin
+  CoverTime := 10;
+  UnLoadDetailedCover;
+
+  StopMusicPreview();
+  StopVideoPreview();
+  PreviewOpened := -1;
+end;
+
+procedure TScreenSong.SetScroll;
+var
+  VS, B: integer;
+begin
+  VS := CatSongs.VisibleSongs;
+  if VS > 0 then
+  begin
+    // Set Positions
+    case Theme.Song.Cover.Style of
+      3: SetScroll3;
+      5: SetScroll5;
+      6: SetScroll6;
+      else SetScroll4;
+    end;
+
+    // Set visibility of video icon
+    Statics[VideoIcon].Visible := CatSongs.Song[Interaction].Video.IsSet;
+
+    // Set texts
+    Text[TextArtist].Text := CatSongs.Song[Interaction].Artist;
+    Text[TextTitle].Text  :=  CatSongs.Song[Interaction].Title;
+    if (Ini.TabsAtStartup = 1) and (CatSongs.CatNumShow = -1) then
+    begin
+      Text[TextNumber].Text := IntToStr(CatSongs.Song[Interaction].OrderNum) + '/' + IntToStr(CatSongs.CatCount);
+      Text[TextTitle].Text  := '(' + IntToStr(CatSongs.Song[Interaction].CatNumber) + ' ' + Language.Translate('SING_SONGS_IN_CAT') + ')';
+    end
+    else if (CatSongs.CatNumShow = -2) then
+      Text[TextNumber].Text := IntToStr(CatSongs.VisibleIndex(Interaction)+1) + '/' + IntToStr(VS)
+    else if (CatSongs.CatNumShow = -3) then
+      Text[TextNumber].Text := IntToStr(CatSongs.VisibleIndex(Interaction)+1) + '/' + IntToStr(VS)
+    else if (Ini.TabsAtStartup = 1) then
+      Text[TextNumber].Text := IntToStr(CatSongs.Song[Interaction].CatNumber) + '/' + IntToStr(CatSongs.Song[Interaction - CatSongs.Song[Interaction].CatNumber].CatNumber)
+    else
+      Text[TextNumber].Text := IntToStr(Interaction+1) + '/' + IntToStr(Length(CatSongs.Song));
+  end
+  else
+  begin
+    Text[TextNumber].Text := '0/0';
+    Text[TextArtist].Text := '';
+    Text[TextTitle].Text  := '';
+    for B := 0 to High(Button) do
+      Button[B].Visible := false;
+
+  end;
+end;
+
+(*
+procedure TScreenSong.SetScroll1;
+var
+  B:      integer;    // button
+  Src:    integer;
+  //Dst:    integer;
+  Count:  integer;    // Dst is not used. Count is used.
+  Ready:  boolean;
+
+  VisCount: integer;  // count of visible (or selectable) buttons
+  VisInt:   integer;  // visible position of interacted button
+  Typ:      integer;  // 0 when all songs fits the screen
+  Placed:   integer;  // number of placed visible buttons
+begin
+  //Src := 0;
+  //Dst := -1;
+  Count := 1;
+  Typ := 0;
+  Ready := false;
+  Placed := 0;
+
+  VisCount := 0;
+  for B := 0 to High(Button) do
+    if CatSongs.Song[B].Visible then
+      Inc(VisCount);
+
+  VisInt := 0;
+  for B := 0 to Interaction-1 do
+    if CatSongs.Song[B].Visible then
+      Inc(VisInt);
+
+  if VisCount <= 6 then
+  begin
+    Typ := 0;
+  end
+  else
+  begin
+    if VisInt <= 3 then
+    begin
+      Typ := 1;
+      Count := 7;
+      Ready := true;
+    end;
+
+    if (VisCount - VisInt) <= 3 then
+    begin
+      Typ := 2;
+      Count := 7;
+      Ready := true;
+    end;
+
+    if not Ready then
+    begin
+      Typ := 3;
+      Src := Interaction;
+    end;
+  end;
+
+
+  // hide all buttons
+  for B := 0 to High(Button) do
+  begin
+    Button[B].Visible := false;
+    Button[B].Selectable := CatSongs.Song[B].Visible;
+  end;
+
+  {
+  for B := Src to Dst do
+  begin
+    //Button[B].Visible := true;
+    Button[B].Visible := CatSongs.Song[B].Visible;
+    Button[B].Selectable := Button[B].Visible;
+    Button[B].Y := 140 + (B-Src) * 60;
+  end;
+  }
+
+  if Typ = 0 then
+  begin
+    for B := 0 to High(Button) do
+    begin
+      if CatSongs.Song[B].Visible then
+      begin
+        Button[B].Visible := true;
+        Button[B].Y := 140 + (Placed) * 60;
+        Inc(Placed);
+      end;
+    end;
+  end;
+
+  if Typ = 1 then
+  begin
+    B := 0;
+    while (Count > 0) do
+    begin
+      if CatSongs.Song[B].Visible then
+      begin
+        Button[B].Visible := true;
+        Button[B].Y := 140 + (Placed) * 60;
+        Inc(Placed);
+        Dec(Count);
+      end;
+      Inc(B);
+    end;
+  end;
+
+  if Typ = 2 then
+  begin
+    B := High(Button);
+    while (Count > 0) do
+    begin
+      if CatSongs.Song[B].Visible then
+      begin
+        Button[B].Visible := true;
+        Button[B].Y := 140 + (6-Placed) * 60;
+        Inc(Placed);
+        Dec(Count);
+      end;
+      Dec(B);
+    end;
+  end;
+
+  if Typ = 3 then
+  begin
+    B := Src;
+    Count := 4;
+    while (Count > 0) do
+    begin
+      if CatSongs.Song[B].Visible then
+      begin
+        Button[B].Visible := true;
+        Button[B].Y := 140 + (3+Placed) * 60;
+        Inc(Placed);
+        Dec(Count);
+      end;
+      Inc(B);
+    end;
+
+    B := Src-1;
+    Placed := 0;
+    Count := 3;
+    while (Count > 0) do
+    begin
+      if CatSongs.Song[B].Visible then
+      begin
+        Button[B].Visible := true;
+        Button[B].Y := 140 + (2-Placed) * 60;
+        Inc(Placed);
+        Dec(Count);
+      end;
+      Dec(B);
+    end;
+
+  end;
+
+  if Length(Button) > 0 then
+    Statics[1].Texture.Y := Button[Interaction].Y - 5; // selection texture
+end;
+
+procedure TScreenSong.SetScroll2;
+var
+  B:      integer;
+  //Factor:    integer; // factor of position relative to center of screen
+  //Factor2:   real;
+begin
+  // line
+  for B := 0 to High(Button) do
+    Button[B].X := 300 + (B - Interaction) * 260;
+
+  if Length(Button) >= 3 then
+  begin
+    if Interaction = 0 then
+      Button[High(Button)].X := 300 - 260;
+
+    if Interaction = High(Button) then
+      Button[0].X := 300 + 260;
+  end;
+
+  // circle
+  {
+  for B := 0 to High(Button) do
+  begin
+    Factor := (B - Interaction); // 0 to center, -1: to left, +1 to right
+    Factor2 := Factor / Length(Button);
+    Button[B].X := 300 + 10000 * sin(2*pi*Factor2);
+    //Button[B].Y := 140 + 50 * ;
+  end;
+  }
+end;
+*)
+
+procedure TScreenSong.SetScroll3; // with slide
+var
+  B:      integer;
+  //Factor:    integer; // factor of position relative to center of screen
+  //Factor2:   real;
+begin
+  SongTarget := Interaction;
+
+  // line
+  for B := 0 to High(Button) do
+  begin
+    Button[B].X := 300 + (B - SongCurrent) * 260;
+    if (Button[B].X < -Button[B].W) or (Button[B].X > 800) then
+      Button[B].Visible := false
+    else
+      Button[B].Visible := true;
+  end;
+
+  {
+  if Length(Button) >= 3 then
+  begin
+    if Interaction = 0 then
+      Button[High(Button)].X := 300 - 260;
+
+    if Interaction = High(Button) then
+      Button[0].X := 300 + 260;
+  end;
+  }
+
+  // circle
+  {
+  for B := 0 to High(Button) do
+  begin
+    Factor := (B - Interaction); // 0 to center, -1: to left, +1 to right
+    Factor2 := Factor / Length(Button);
+    Button[B].X := 300 + 10000 * sin(2*pi*Factor2);
+    //Button[B].Y := 140 + 50 * ;
+  end;
+  }
+end;
+
+(**
+ * Rotation
+ *)
+procedure TScreenSong.SetScroll4;
+var
+  B:      integer;
+  Angle:  real;
+  Z, Z2:  real;
+  VS:     integer;
+begin
+  VS := CatSongs.VisibleSongs();
+
+  for B := 0 to High(Button) do
+  begin
+    Button[B].Visible := CatSongs.Song[B].Visible;
+    if Button[B].Visible then
+    begin
+      // angle between the cover and selected song-cover in radians
+      Angle := 2*Pi * (CatSongs.VisibleIndex(B) - SongCurrent) /  VS;
+
+      // calc z-position from angle
+      Z := (1 + cos(Angle)) / 2;  // scaled to range [0..1]
+      Z2 := (1 + 2*Z) / 3;        // scaled to range [1/3..1]
+
+      // adjust cover's width and height according its z-position
+      // Note: Theme.Song.Cover.W is not used as width and height are equal
+      //   and Theme.Song.Cover.W is used as circle radius in Scroll5.
+      Button[B].W := Theme.Song.Cover.H * Z2;
+      Button[B].H := Button[B].W;
+
+      // set cover position
+      Button[B].X := Theme.Song.Cover.X +
+                     (0.185 * Theme.Song.Cover.H * VS * sin(Angle)) * Z2 -
+                     ((Button[B].H - Theme.Song.Cover.H)/2);
+      Button[B].Y := Theme.Song.Cover.Y  +
+                     (Theme.Song.Cover.H - Abs(Button[B].H)) * 0.7;
+      Button[B].Z := Z / 2 + 0.3;
+    end;
+  end;
+end;
+
+(**
+ * rotate
+ *)
+procedure TScreenSong.SetScroll5;
+var
+  B:      integer;
+  Angle:    real;
+  Pos:    real;
+  VS:     integer;
+  Padding:     real;
+  X:        real;
+  {
+  Theme.Song.CoverW: circle radius
+  Theme.Song.CoverX: x-pos. of the left edge of the selected cover
+  Theme.Song.CoverY: y-pos. of the upper edge of the selected cover
+  Theme.Song.CoverH: cover height
+  }
+begin
+  VS := CatSongs.VisibleSongs();
+
+  // Update positions of all buttons
+  for B := 0 to High(Button) do
+  begin
+    Button[B].Visible := CatSongs.Song[B].Visible; // adjust visibility
+    if Button[B].Visible then // Only change pos for visible buttons
+    begin
+      // Pos is the distance to the centered cover in the range [-VS/2..+VS/2]
+      Pos := (CatSongs.VisibleIndex(B) - SongCurrent);
+      if (Pos < -VS/2) then
+        Pos := Pos + VS
+      else if (Pos > VS/2) then
+        Pos := Pos - VS;
+
+      // Avoid overlapping of the front covers.
+      // Use an alternate position for the five front covers. 
+      if (Abs(Pos) < 2.5) then
+      begin
+        Angle := Pi * (Pos / Min(VS, 5)); // Range: (-1/4*Pi .. +1/4*Pi)
+
+        Button[B].H := Abs(Theme.Song.Cover.H * cos(Angle*0.8));
+        Button[B].W := Button[B].H;
+
+        //Button[B].Reflectionspacing := 15 * Button[B].H/Theme.Song.Cover.H;
+        Button[B].DeSelectReflectionspacing := 15 * Button[B].H/Theme.Song.Cover.H;
+
+        Padding := (Button[B].H - Theme.Song.Cover.H)/2;
+        X := Sin(Angle*1.3) * 0.9;
+
+        Button[B].X := Theme.Song.Cover.X + Theme.Song.Cover.W * X - Padding;
+        Button[B].Y := (Theme.Song.Cover.Y  + (Theme.Song.Cover.H - Abs(Theme.Song.Cover.H * cos(Angle))) * 0.5);
+        Button[B].Z := 0.95 - Abs(Pos) * 0.01;
+
+        if VS < 5 then
+          Button[B].Texture.Alpha := 1 - Abs(Pos) / VS  * 2
+        else
+          Button[B].Texture.Alpha := 1;    
+      end
+      { only draw 3 visible covers in the background
+        (the 3 that are on the opposite of the front covers}
+      else if (VS > 7) and (Abs(Pos) > floor(VS/2) - 1.5) then
+      begin
+        // Transform Pos to range [-1..-3/4, +3/4..+1]
+        { the 3 covers at the back will show up in the gap between the
+          front cover and its neighbors
+          one cover will be hiddenbehind the front cover,
+          but this will not be a lack of performance ;) }
+        if Pos < 0 then
+          Pos := (Pos - 2 + ceil(VS/2))/8 - 0.75
+        else
+          Pos := (Pos + 2 - floor(VS/2))/8 + 0.75;
+
+        // angle in radians [-2Pi..-Pi, +Pi..+2Pi]
+        Angle := 2*Pi * Pos;
+
+        Button[B].H := 0.6*(Theme.Song.Cover.H-Abs(Theme.Song.Cover.H * cos(Angle/2)*0.8));
+        Button[B].W := Button[B].H;
+
+        Padding := (Button[B].H - Theme.Song.Cover.H)/2;
+
+        Button[B].X :=  Theme.Song.Cover.X+Theme.Song.Cover.H/2-Button[b].H/2+Theme.Song.Cover.W/320*((Theme.Song.Cover.H)*sin(Angle/2)*1.52);
+        Button[B].Y := Theme.Song.Cover.Y  - (Button[B].H - Theme.Song.Cover.H)*0.75;
+        Button[B].Z := (0.4 - Abs(Pos/4)) -0.00001; //z < 0.49999 is behind the cover 1 is in front of the covers
+
+        Button[B].Texture.Alpha := 1;
+
+        //Button[B].Reflectionspacing := 15 * Button[B].H/Theme.Song.Cover.H;
+        Button[B].DeSelectReflectionspacing := 15 * Button[B].H/Theme.Song.Cover.H;
+      end
+      { all other covers are not visible }
+      else
+      Button[B].Visible := false;
+    end;
+  end;
+end;
+
+procedure TScreenSong.SetScroll6; // rotate (slotmachine style)
+var
+  B:      integer;
+  Angle:  real;
+  Pos:    real;
+  VS:     integer;
+  diff:   real;
+  X:      real;
+  Factor: real;
+  Z, Z2:  real;
+begin
+  VS := CatSongs.VisibleSongs;
+  if VS <= 5 then
+  begin
+    // circle
+    for B := 0 to High(Button) do
+    begin
+      Button[B].Visible := CatSongs.Song[B].Visible;
+      if Button[B].Visible then // optimization for 1000 songs - updates only visible songs, hiding in tabs becomes useful for maintaing good speed
+      begin
+  
+        Factor := 2 * pi * (CatSongs.VisibleIndex(B) - SongCurrent) /  VS {CatSongs.VisibleSongs};// 0.5.0 (II): takes another 16ms
+
+        Z := (1 + cos(Factor)) / 2;
+        Z2 := (1 + 2*Z) / 3;
+
+        Button[B].Y := Theme.Song.Cover.Y + (0.185 * Theme.Song.Cover.H * VS * sin(Factor)) * Z2 - ((Button[B].H - Theme.Song.Cover.H)/2); // 0.5.0 (I): 2 times faster by not calling CatSongs.VisibleSongs
+        Button[B].Z := Z / 2 + 0.3;
+
+        Button[B].W := Theme.Song.Cover.H * Z2;
+
+        //Button[B].Y := {50 +} 140 + 50 - 50 * Z2;
+        Button[B].X := Theme.Song.Cover.X  + (Theme.Song.Cover.H - Abs(Button[B].H)) * 0.7 ;
+        Button[B].H := Button[B].W;
+      end;
+    end;
+  end
+  else
+  begin
+    //Change Pos of all Buttons
+    for B := Low(Button) to High(Button) do
+    begin
+      Button[B].Visible := CatSongs.Song[B].Visible; //Adjust Visibility
+      if Button[B].Visible then //Only Change Pos for Visible Buttons
+      begin
+        Pos := (CatSongs.VisibleIndex(B) - SongCurrent);
+        if (Pos < -VS/2) then
+          Pos := Pos + VS
+        else if (Pos > VS/2) then
+          Pos := Pos - VS;
+
+        if (Abs(Pos) < 2.5) then {fixed Positions}
+        begin
+          Angle := Pi * (Pos / 5);
+          //Button[B].Visible := false;
+
+          Button[B].H := Abs(Theme.Song.Cover.H * cos(Angle*0.8));//Power(Z2, 3);
+
+          Button[B].DeSelectReflectionspacing := 15 * Button[B].H/Theme.Song.Cover.H;
+
+          Button[B].Z := 0.95 - Abs(Pos) * 0.01;
+
+          Button[B].X := (Theme.Song.Cover.X  + (Theme.Song.Cover.H - Abs(Theme.Song.Cover.H * cos(Angle))) * 0.5);
+
+          Button[B].W := Button[B].H;
+
+          Diff := (Button[B].H - Theme.Song.Cover.H)/2;
+
+          X := Sin(Angle*1.3)*0.9;
+
+          Button[B].Y := Theme.Song.Cover.Y + Theme.Song.Cover.W * X - Diff;
+        end
+        else
+        begin {Behind the Front Covers}
+
+          // limit-bg-covers hack
+          if (abs(VS/2-abs(Pos))>10) then
+            Button[B].Visible := false;
+          if VS > 25 then
+            VS:=25;
+          // end of limit-bg-covers hack
+
+          if Pos < 0 then
+            Pos := (Pos - VS/2)/VS
+          else
+            Pos := (Pos + VS/2)/VS;
+
+          Angle := Pi * Pos*2;
+
+          Button[B].Z := (0.4 - Abs(Pos/4)) -0.00001; //z < 0.49999 is behind the cover 1 is in front of the covers
+
+          Button[B].H :=0.6*(Theme.Song.Cover.H-Abs(Theme.Song.Cover.H * cos(Angle/2)*0.8));//Power(Z2, 3);
+
+          Button[B].W := Button[B].H;
+
+          Button[B].X := Theme.Song.Cover.X  - (Button[B].H - Theme.Song.Cover.H)*0.5;
+
+          Button[B].DeSelectReflectionspacing := 15 * Button[B].H/Theme.Song.Cover.H;
+
+          Button[B].Y := Theme.Song.Cover.Y+Theme.Song.Cover.H/2-Button[b].H/2+Theme.Song.Cover.W/320*(Theme.Song.Cover.H*sin(Angle/2)*1.52);
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TScreenSong.OnShow;
+begin
+  inherited;
+{**
+ * Pause background music, so we can play it again on scorescreen
+ *}
+  SoundLib.PauseBgMusic;
+
+  AudioPlayback.Stop;
+  PreviewOpened := -1;
+
+  // reset video playback engine
+  fCurrentVideo := nil;
+
+  if Ini.Players <= 3 then PlayersPlay := Ini.Players + 1;
+  if Ini.Players  = 4 then PlayersPlay := 6;
+
+  //Cat Mod etc
+  if (Ini.TabsAtStartup = 1) and (CatSongs.CatNumShow = -1) then
+  begin
+    CatSongs.ShowCategoryList;
+    FixSelected;
+    //Show Cat in Top Left Mod
+    HideCatTL;
+  end;
+
+  if Length(CatSongs.Song) > 0 then
+  begin
+    SetScroll;
+  end;
+
+  //Playlist Mode
+  if (Mode = smNormal) then
+  begin
+    //If Playlist Shown -> Select Next automatically
+    if (CatSongs.CatNumShow = -3) then
+    begin
+      SelectNext;
+    end;
+  end
+  //Party Mode
+  else if (Mode = smPartyMode) then
+  begin
+    SelectRandomSong;
+    //Show Menu directly in PartyMode
+    //But only if selected in Options
+    if (Ini.PartyPopup = 1) then
+    begin
+      ScreenSongMenu.MenuShow(SM_Party_Main);
+    end;
+  end;
+
+  isScrolling := false;
+  SetJoker;
+  SetStatics;
+end;
+
+procedure TScreenSong.OnShowFinish;
+begin
+  isScrolling := true;
+  CoverTime := 10;
+end;
+
+procedure TScreenSong.OnHide;
+begin
+  // turn music volume to 100%
+  AudioPlayback.SetVolume(1.0);
+
+  // stop preview
+  StopMusicPreview();
+  StopVideoPreview();
+end;
+
+procedure TScreenSong.DrawExtensions;
+begin
+  //Draw Song Menu
+  if (ScreenSongMenu.Visible) then
+  begin
+    ScreenSongMenu.Draw;
+  end
+  else if (ScreenSongJumpto.Visible) then
+  begin
+    ScreenSongJumpto.Draw;
+  end
+end;
+
+function TScreenSong.Draw: boolean;
+var
+  dx:         real;
+  dt:         real;
+  I:          integer;
+  VideoAlpha: real;
+begin
+  if isScrolling then
+  begin
+    dx := SongTarget-SongCurrent;
+    dt := TimeSkip * 7;
+
+    if dt > 1 then
+      dt := 1;
+
+    SongCurrent := SongCurrent + dx*dt;
+
+    if SameValue(SongCurrent, SongTarget, 0.002) and (CatSongs.VisibleSongs > 0) then
+    begin
+      isScrolling := false;
+      SongCurrent := SongTarget;
+      OnSongSelect;
+    end;
+  end;
+
+  {
+  if SongCurrent > Catsongs.VisibleSongs then
+  begin
+    SongCurrent := SongCurrent - Catsongs.VisibleSongs;
+    SongTarget := SongTarget - Catsongs.VisibleSongs;
+  end;
+  }
+
+  //Log.BenchmarkStart(5);
+
+  SetScroll;
+
+  //Log.BenchmarkEnd(5);
+  //Log.LogBenchmark('SetScroll4', 5);
+
+  //Fading Functions, Only if Covertime is under 5 Seconds
+  if (CoverTime < 9) then
+  begin
+    // cover fade
+    if (CoverTime < 1) and (CoverTime + TimeSkip >= 1) then
+    begin
+      // load new texture
+      Texture.GetTexture(Button[Interaction].Texture.Name, TEXTURE_TYPE_PLAIN, false);
+      Button[Interaction].Texture.Alpha := 1;
+      Button[Interaction].Texture2 := Texture.GetTexture(Button[Interaction].Texture.Name, TEXTURE_TYPE_PLAIN, false);
+      Button[Interaction].Texture2.Alpha := 1;
+    end;
+
+    //Update Fading Time
+    CoverTime := CoverTime + TimeSkip;
+
+    //Update Fading Texture
+    Button[Interaction].Texture2.Alpha := (CoverTime - 1) * 1.5;
+    if Button[Interaction].Texture2.Alpha > 1 then
+      Button[Interaction].Texture2.Alpha := 1;
+
+  end;
+
+  //inherited Draw;
+  //heres a little Hack, that causes the Statics
+  //are Drawn after the Buttons because of some Blending Problems.
+  //This should cause no Problems because all Buttons on this screen
+  //Has Z Position.
+  //Draw BG
+  DrawBG;
+
+  VideoAlpha := Button[interaction].Texture.Alpha*(CoverTime-1);
+  //Instead of Draw FG Procedure:
+  //We draw Buttons for our own
+  for I := 0 to Length(Button) - 1 do
+  begin
+    if (I<>Interaction) or not Assigned(fCurrentVideo) or (VideoAlpha<1) or AudioPlayback.Finished then
+      Button[I].Draw;
+  end;
+
+  if AudioPlayback.Finished then
+    StopVideoPreview;
+
+  if Assigned(fCurrentVideo) then
+  begin
+    // Just call this once
+    // when Screens = 2
+    if (ScreenAct = 1) then
+      fCurrentVideo.GetFrame(CatSongs.Song[Interaction].VideoGAP + AudioPlayback.Position);
+
+    fCurrentVideo.SetScreen(ScreenAct);
+    fCurrentVideo.Alpha := VideoAlpha;
+
+    //set up window
+    with Button[interaction] do
+    begin
+      fCurrentVideo.SetScreenPosition(X, Y, Z);
+      fCurrentVideo.Width := W;
+      fCurrentVideo.Height := H;
+      fCurrentVideo.ReflectionSpacing := Reflectionspacing;
+    end;
+    fCurrentVideo.AspectCorrection := acoCrop;
+
+    fCurrentVideo.Draw;
+
+    if Button[interaction].Reflection then
+      fCurrentVideo.DrawReflection;
+  end;
+
+  // Statics
+  for I := 0 to Length(Statics) - 1 do
+    Statics[I].Draw;
+
+  // and texts
+  for I := 0 to Length(Text) - 1 do
+    Text[I].Draw;
+
+  Equalizer.Draw;
+
+  DrawExtensions;
+
+  Result := true;
+end;
+
+procedure TScreenSong.SelectNext;
+var
+  Skip: integer;
+  VS:   integer;
+begin
+  VS := CatSongs.VisibleSongs;
+
+  if VS > 0 then
+  begin
+    if (not isScrolling) and (VS > 0) then
+    begin
+      isScrolling := true;
+      OnSongDeselect;
+    end;
+
+    Skip := 1;
+
+    // this 1 could be changed by CatSongs.FindNextVisible
+    while (not CatSongs.Song[(Interaction + Skip) mod Length(Interactions)].Visible) do
+      Inc(Skip);
+
+    SongTarget := SongTarget + 1;//Skip;
+
+    Interaction := (Interaction + Skip) mod Length(Interactions);
+
+    // try to keep all at the beginning
+    if SongTarget > VS-1 then
+    begin
+      SongTarget := SongTarget - VS;
+      SongCurrent := SongCurrent - VS;
+    end;
+
+  end;
+
+  // Interaction -> Button, load cover
+  // show uncached texture
+  //Button[Interaction].Texture := Texture.GetTexture(Button[Interaction].Texture.Name, TEXTURE_TYPE_PLAIN, false);
+end;
+
+procedure TScreenSong.SelectPrev;
+var
+  Skip: integer;
+  VS:   integer;
+begin
+  VS := CatSongs.VisibleSongs;
+
+  if VS > 0 then
+  begin
+    if (not isScrolling) and (VS > 0) then
+    begin
+      isScrolling := true;
+      OnSongDeselect;
+    end;
+
+    Skip := 1;
+
+    while (not CatSongs.Song[(Interaction - Skip + Length(Interactions)) mod Length(Interactions)].Visible) do
+      Inc(Skip);
+    SongTarget := SongTarget - 1;//Skip;
+
+    Interaction := (Interaction - Skip + Length(Interactions)) mod Length(Interactions);
+
+    // try to keep all at the beginning
+    if SongTarget < 0 then
+    begin
+      SongTarget := SongTarget + CatSongs.VisibleSongs;
+      SongCurrent := SongCurrent + CatSongs.VisibleSongs;
+    end;
+
+    // show uncached texture
+    //Button[Interaction].Texture := Texture.GetTexture(Button[Interaction].Texture.Name, TEXTURE_TYPE_PLAIN, false);
+  end;
+end;
+
+procedure TScreenSong.StartMusicPreview();
+var
+  Song: TSong;
+  PreviewPos: real;
+begin
+  AudioPlayback.Close();
+
+  if CatSongs.VisibleSongs = 0 then
+    Exit;
+
+  Song := CatSongs.Song[Interaction];
+  if not assigned(Song) then
+    Exit;
+
+  //fix: if main cat than there is nothing to play
+  if Song.main then
+    Exit;
+
+  if AudioPlayback.Open(Song.Path.Append(Song.Mp3)) then
+  begin
+    PreviewOpened := Interaction;
+
+    PreviewPos := AudioPlayback.Length / 4;
+    // fix for invalid music file lengths
+    if (PreviewPos > 60.0) then
+      PreviewPos := 60.0;
+    AudioPlayback.Position := PreviewPos;
+
+    // set preview volume
+    if (Ini.PreviewFading = 0) then
+    begin
+      // music fade disabled: start with full volume
+      AudioPlayback.SetVolume(IPreviewVolumeVals[Ini.PreviewVolume]);
+      AudioPlayback.Play()
+    end
+    else
+    begin
+      // music fade enabled: start muted and fade-in
+      AudioPlayback.SetVolume(0);
+      AudioPlayback.FadeIn(Ini.PreviewFading, IPreviewVolumeVals[Ini.PreviewVolume]);
+    end;
+  end;
+end;
+
+procedure TScreenSong.StopMusicPreview();
+begin
+  // Stop preview of previous song
+  AudioPlayback.Stop;
+end;
+
+procedure TScreenSong.StartVideoPreview();
+var
+  VideoFile:  IPath;
+  Song:       TSong;
+
+begin
+  if (Ini.VideoPreview=0)  then
+    Exit;
+
+  if Assigned(fCurrentVideo) then
+  begin
+    fCurrentVideo.Stop();
+    fCurrentVideo := nil;
+  end;
+
+  //if no audio open => exit
+  if (PreviewOpened = -1) then
+    Exit;
+
+  if CatSongs.VisibleSongs = 0 then
+    Exit;
+
+  Song := CatSongs.Song[Interaction];
+  if not assigned(Song) then
+    Exit;
+
+  //fix: if main cat than there is nothing to play
+  if Song.main then
+    Exit;
+
+  VideoFile := Song.Path.Append(Song.Video);
+  if (Song.Video.IsSet) and VideoFile.IsFile then
+  begin
+    fCurrentVideo := VideoPlayback.Open(VideoFile);
+    if (fCurrentVideo <> nil) then
+    begin
+      fCurrentVideo.Position := Song.VideoGAP + AudioPlayback.Position;
+      fCurrentVideo.Play;
+    end;
+  end;
+end;
+
+procedure TScreenSong.StopVideoPreview();
+begin
+  // Stop video preview of previous song
+  if Assigned(fCurrentVideo) then
+  begin
+    fCurrentVideo.Stop();
+    fCurrentVideo := nil;
+  end;
+end;
+
+// Changes previewed song
+procedure TScreenSong.ChangeMusic;
+begin
+  StopMusicPreview();
+  StopVideoPreview();
+  PreviewOpened := -1;
+  StartMusicPreview();
+  StartVideoPreview();
+end;
+
+procedure TScreenSong.SkipTo(Target: cardinal);
+var
+  i: integer;
+begin
+  Interaction := High(CatSongs.Song);
+  SongTarget  := 0;
+
+  for i := 1 to Target+1 do
+    SelectNext;
+
+  FixSelected2;
+end;
+
+procedure TScreenSong.SelectRandomSong;
+var
+  I, I2: integer;
+begin
+  case PlaylistMan.Mode of
+      smNormal:  // all songs just select random song
+        begin
+          // when tabs are activated then use tab method
+          if (Ini.TabsAtStartup = 1) then
+          begin
+            repeat
+              I2 := Low(CatSongs.Song) + Random(High(CatSongs.Song) + 1 - Low(CatSongs.Song));
+            until CatSongs.Song[I2].Main = false;
+
+            // search cat
+            for I := I2 downto Low(CatSongs.Song) do
+            begin
+              if CatSongs.Song[I].Main then
+                break;
+            end;
+            // I is the cat number, I2 is the no of the song within this cat
+
+            // choose cat
+            CatSongs.ShowCategoryList;
+
+            // show cat in top left mod
+            ShowCatTL(I);
+
+            CatSongs.ClickCategoryButton(I);
+            SelectNext;
+
+            // choose song
+            SkipTo(I2 - I);
+          end
+          // when tabs are deactivated use easy method
+          else
+            SkipTo(Random(CatSongs.VisibleSongs));
+        end;
+      smPartyMode:  // one category select category and select random song
+        begin
+          CatSongs.ShowCategoryList;
+          CatSongs.ClickCategoryButton(PlaylistMan.CurPlayList);
+          ShowCatTL(PlaylistMan.CurPlayList);
+
+          SelectNext;
+          FixSelected2;
+
+          SkipTo(Random(CatSongs.VisibleSongs));
+        end;
+      smPlaylistRandom:  // playlist: select playlist and select random song
+        begin
+          PlaylistMan.SetPlayList(PlaylistMan.CurPlayList);
+
+          SkipTo(Random(CatSongs.VisibleSongs));
+          FixSelected2;
+        end;
+  end;
+
+  AudioPlayback.PlaySound(SoundLib.Change);
+  SetScroll;
+end;
+
+procedure TScreenSong.SetJoker;
+begin
+  // If Party Mode
+  if Mode = smPartyMode then //Show Joker that are available
+  begin
+    if (Length(Party.Teams) >= 1) then
+    begin
+      Statics[StaticTeam1Joker1].Visible := (Party.Teams[0].JokersLeft >= 1);
+      Statics[StaticTeam1Joker2].Visible := (Party.Teams[0].JokersLeft >= 2);
+      Statics[StaticTeam1Joker3].Visible := (Party.Teams[0].JokersLeft >= 3);
+      Statics[StaticTeam1Joker4].Visible := (Party.Teams[0].JokersLeft >= 4);
+      Statics[StaticTeam1Joker5].Visible := (Party.Teams[0].JokersLeft >= 5);
+    end
+    else
+    begin
+      Statics[StaticTeam1Joker1].Visible := false;
+      Statics[StaticTeam1Joker2].Visible := false;
+      Statics[StaticTeam1Joker3].Visible := false;
+      Statics[StaticTeam1Joker4].Visible := false;
+      Statics[StaticTeam1Joker5].Visible := false;
+    end;
+
+    if (Length(Party.Teams) >= 2) then
+    begin
+      Statics[StaticTeam2Joker1].Visible := (Party.Teams[1].JokersLeft >= 1);
+      Statics[StaticTeam2Joker2].Visible := (Party.Teams[1].JokersLeft >= 2);
+      Statics[StaticTeam2Joker3].Visible := (Party.Teams[1].JokersLeft >= 3);
+      Statics[StaticTeam2Joker4].Visible := (Party.Teams[1].JokersLeft >= 4);
+      Statics[StaticTeam2Joker5].Visible := (Party.Teams[1].JokersLeft >= 5);
+    end
+    else
+    begin
+      Statics[StaticTeam2Joker1].Visible := false;
+      Statics[StaticTeam2Joker2].Visible := false;
+      Statics[StaticTeam2Joker3].Visible := false;
+      Statics[StaticTeam2Joker4].Visible := false;
+      Statics[StaticTeam2Joker5].Visible := false;
+    end;
+
+    if (Length(Party.Teams) >= 3) then
+    begin
+      Statics[StaticTeam3Joker1].Visible := (Party.Teams[2].JokersLeft >= 1);
+      Statics[StaticTeam3Joker2].Visible := (Party.Teams[2].JokersLeft >= 2);
+      Statics[StaticTeam3Joker3].Visible := (Party.Teams[2].JokersLeft >= 3);
+      Statics[StaticTeam3Joker4].Visible := (Party.Teams[2].JokersLeft >= 4);
+      Statics[StaticTeam3Joker5].Visible := (Party.Teams[2].JokersLeft >= 5);
+    end
+    else
+    begin
+      Statics[StaticTeam3Joker1].Visible := false;
+      Statics[StaticTeam3Joker2].Visible := false;
+      Statics[StaticTeam3Joker3].Visible := false;
+      Statics[StaticTeam3Joker4].Visible := false;
+      Statics[StaticTeam3Joker5].Visible := false;
+    end;
+  end
+  else
+  begin //Hide all
+    Statics[StaticTeam1Joker1].Visible := false;
+    Statics[StaticTeam1Joker2].Visible := false;
+    Statics[StaticTeam1Joker3].Visible := false;
+    Statics[StaticTeam1Joker4].Visible := false;
+    Statics[StaticTeam1Joker5].Visible := false;
+
+    Statics[StaticTeam2Joker1].Visible := false;
+    Statics[StaticTeam2Joker2].Visible := false;
+    Statics[StaticTeam2Joker3].Visible := false;
+    Statics[StaticTeam2Joker4].Visible := false;
+    Statics[StaticTeam2Joker5].Visible := false;
+
+    Statics[StaticTeam3Joker1].Visible := false;
+    Statics[StaticTeam3Joker2].Visible := false;
+    Statics[StaticTeam3Joker3].Visible := false;
+    Statics[StaticTeam3Joker4].Visible := false;
+    Statics[StaticTeam3Joker5].Visible := false;
+  end;
+end;
+
+procedure TScreenSong.SetStatics;
+var
+  I:       integer;
+  Visible: boolean;
+begin
+  //Set Visibility of Party Statics and Text
+  Visible := (Mode = smPartyMode);
+
+  for I := 0 to High(StaticParty) do
+    Statics[StaticParty[I]].Visible := Visible;
+
+  for I := 0 to High(TextParty) do
+    Text[TextParty[I]].Visible := Visible;
+
+  //Set Visibility of Non Party Statics and Text
+  Visible := not Visible;
+
+  for I := 0 to High(StaticNonParty) do
+    Statics[StaticNonParty[I]].Visible := Visible;
+
+  for I := 0 to High(TextNonParty) do
+    Text[TextNonParty[I]].Visible := Visible;
+end;
+
+//Procedures for Menu
+
+procedure TScreenSong.StartSong;
+begin
+  CatSongs.Selected := Interaction;
+  StopMusicPreview();
+
+  //Party Mode
+  if (Mode = smPartyMode) then
+  begin
+    FadeTo(@ScreenSing);
+  end
+  else
+  begin
+    FadeTo(@ScreenSing);
+  end;
+end;
+
+procedure TScreenSong.SelectPlayers;
+begin
+  CatSongs.Selected := Interaction;
+  StopMusicPreview();
+
+  ScreenName.Goto_SingScreen := true;
+  FadeTo(@ScreenName);
+end;
+
+procedure TScreenSong.OpenEditor;
+begin
+  if (Songs.SongList.Count > 0) and
+     (not CatSongs.Song[Interaction].Main) and
+     (Mode = smNormal) then
+  begin
+    StopMusicPreview();
+    AudioPlayback.PlaySound(SoundLib.Start);
+    CurrentSong := CatSongs.Song[Interaction];
+    FadeTo(@ScreenEditSub);
+  end;
+end;
+
+//Team No of Team (0-5)
+procedure TScreenSong.DoJoker (Team: integer);
+begin
+  if (Mode = smPartyMode) and
+     (High(Party.Teams) >= Team) and
+     (Party.Teams[Team].JokersLeft > 0) then
+  begin
+    //Use Joker
+    Dec(Party.Teams[Team].JokersLeft);
+    SelectRandomSong;
+    SetJoker;
+  end;
+end;
+
+//Detailed Cover Unloading. Unloads the Detailed, uncached Cover of the cur. Song
+procedure TScreenSong.UnloadDetailedCover;
+begin
+  // show cached texture
+  Button[Interaction].Texture := Texture.GetTexture(Button[Interaction].Texture.Name, TEXTURE_TYPE_PLAIN, true);
+  Button[Interaction].Texture2.Alpha := 0;
+
+  if Button[Interaction].Texture.Name <> Skin.GetTextureFileName('SongCover') then
+    Texture.UnloadTexture(Button[Interaction].Texture.Name, TEXTURE_TYPE_PLAIN, false);
+end;
+
+procedure TScreenSong.Refresh;
+begin
+  {
+  CatSongs.Refresh;
+  CatSongs.ShowCategoryList;
+  Interaction := 0;
+  SelectNext(true);
+  FixSelected;
+  }
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenSongJumpto.pas b/songmanagement/src/screens/UScreenSongJumpto.pas
new file mode 100644
index 00000000..b3d48679
--- /dev/null
+++ b/songmanagement/src/screens/UScreenSongJumpto.pas
@@ -0,0 +1,247 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenSongJumpto;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SDL,
+  SysUtils,
+  UMenu,
+  UDisplay,
+  UMusic,
+  UFiles,
+  USongs,
+  UThemes;
+
+type
+  TScreenSongJumpto = class(TMenu)
+    private
+      //For ChangeMusic
+      fLastPlayed: integer;
+      fVisible: boolean;
+      fSelectType: TSongFilter;
+      fVisSongs: integer;
+
+      procedure SetTextFound(Count: Cardinal);
+
+      //Visible //Whether the Menu should be Drawn
+      //Whether the Menu should be Drawn
+      procedure SetVisible(Value: boolean);
+    public
+      constructor Create; override;
+
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      function Draw: boolean; override;
+
+      property Visible: boolean read fVisible write SetVisible;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UIni,
+  UTexture,
+  ULanguage,
+  UParty,
+  UScreenSong,
+  ULog,
+  UUnicodeUtils;
+
+function TScreenSongJumpto.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    if (IsAlphaNumericChar(CharCode) or
+        IsPunctuationChar(CharCode)) then
+    begin
+      if (Interaction = 0) then
+      begin
+        Button[0].Text[0].Text := Button[0].Text[0].Text + UCS4ToUTF8String(CharCode);
+        SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, fSelectType));
+      end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_BACKSPACE:
+        begin
+          if (Interaction = 0) and (Length(Button[0].Text[0].Text) > 0) then
+          begin
+            Button[0].Text[0].DeleteLastLetter();
+            SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, fSelectType));
+          end;
+        end;
+
+      SDLK_RETURN,
+      SDLK_ESCAPE:
+        begin
+          Visible := false;
+          AudioPlayback.PlaySound(SoundLib.Back);
+          if (fVisSongs = 0) and (Length(Button[0].Text[0].Text) > 0) then
+          begin
+            ScreenSong.UnLoadDetailedCover;
+            Button[0].Text[0].Text := '';
+            CatSongs.SetFilter('', fltAll);
+            SetTextFound(0);
+          end;
+        end;
+
+      SDLK_DOWN:
+        begin
+          {SelectNext;
+          Button[0].Text[0].Selected := (Interaction = 0);}
+        end;
+
+      SDLK_UP:
+        begin
+          {SelectPrev;
+          Button[0].Text[0].Selected := (Interaction = 0); }
+        end;
+
+      SDLK_RIGHT:
+        begin
+          Interaction := 1;
+          InteractInc;
+          if (Length(Button[0].Text[0].Text) > 0) then
+            SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, fSelectType));
+          Interaction := 0;
+        end;
+      SDLK_LEFT:
+        begin
+          Interaction := 1;
+          InteractDec;
+          if (Length(Button[0].Text[0].Text) > 0) then
+            SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, fSelectType));
+          Interaction := 0;
+        end;
+    end;
+  end;
+end;
+
+constructor TScreenSongJumpto.Create;
+begin
+  inherited Create;
+
+  AddText(Theme.SongJumpto.TextFound);
+
+  LoadFromTheme(Theme.SongJumpto);
+
+  AddButton(Theme.SongJumpto.ButtonSearchText);
+  if (Length(Button[0].Text) = 0) then
+    AddButtonText(14, 20, '');
+
+  fSelectType := fltAll;
+  AddSelectSlide(Theme.SongJumpto.SelectSlideType, PInteger(@fSelectType)^, Theme.SongJumpto.IType);
+
+  Interaction := 0;
+  fLastPlayed  := 0;
+end;
+
+procedure TScreenSongJumpto.SetVisible(Value: boolean);
+begin
+//If change from invisible to Visible then OnShow
+  if (fVisible = false) and (Value = true) then
+    OnShow;
+
+  fVisible := Value;
+end;
+
+procedure TScreenSongJumpto.OnShow;
+begin
+  inherited;
+
+  //Reset Screen if no Old Search is Displayed
+  if (CatSongs.CatNumShow <> -2) then
+  begin
+    SelectsS[0].SetSelectOpt(0);
+
+    Button[0].Text[0].Text := '';
+    Text[0].Text := Theme.SongJumpto.NoSongsFound;
+  end;
+
+  //Select Input
+  Interaction := 0;
+  Button[0].Text[0].Selected := true;
+
+  fLastPlayed := ScreenSong.Interaction;
+end;
+
+function TScreenSongJumpto.Draw: boolean;
+begin
+  Result := inherited Draw;
+end;
+
+procedure TScreenSongJumpto.SetTextFound(Count: cardinal);
+begin
+  if (Count = 0) then
+  begin
+    Text[0].Text := Theme.SongJumpto.NoSongsFound;
+    if (Length(Button[0].Text[0].Text) = 0) then
+      ScreenSong.HideCatTL
+    else
+      ScreenSong.ShowCatTLCustom(Format(Theme.SongJumpto.CatText, [Button[0].Text[0].Text]));
+  end
+  else
+  begin
+    Text[0].Text := Format(Theme.SongJumpto.SongsFound, [Count]);
+
+    //Set CatTopLeftText
+    ScreenSong.ShowCatTLCustom(Format(Theme.SongJumpto.CatText, [Button[0].Text[0].Text]));
+  end;
+
+  //Set visSongs
+  fVisSongs := Count;
+
+  //Fix SongSelection
+  ScreenSong.Interaction := high(CatSongs.Song);
+  ScreenSong.SelectNext;
+  ScreenSong.FixSelected;
+
+  //Play Correct Music
+  if (ScreenSong.Interaction <> fLastPlayed) or (CatSongs.VisibleSongs = 0) then
+  begin
+    if (CatSongs.VisibleSongs > 0) then
+      fLastPlayed := ScreenSong.Interaction
+    else
+      fLastPlayed := -1;
+
+    ScreenSong.ChangeMusic;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenSongMenu.pas b/songmanagement/src/screens/UScreenSongMenu.pas
new file mode 100644
index 00000000..173ac2c8
--- /dev/null
+++ b/songmanagement/src/screens/UScreenSongMenu.pas
@@ -0,0 +1,664 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenSongMenu;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  UDisplay,
+  UMusic,
+  UFiles,
+  SysUtils,
+  UThemes;
+
+type
+  TScreenSongMenu = class(TMenu)
+    private
+      CurMenu: byte; // num of the cur. shown menu
+    public
+      Visible: boolean; // whether the menu should be drawn
+
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      function Draw: boolean; override;
+      procedure MenuShow(sMenu: byte);
+      procedure HandleReturn;
+  end;
+
+const
+  SM_Main = 1;
+
+  SM_PlayList         = 64 or 1;
+  SM_Playlist_Add     = 64 or 2;
+  SM_Playlist_New     = 64 or 3;
+
+  SM_Playlist_DelItem = 64 or 5;
+
+  SM_Playlist_Load    = 64 or 8 or 1;
+  SM_Playlist_Del     = 64 or 8 or 5;
+
+  SM_Party_Main       = 128 or 1;
+  SM_Party_Joker      = 128 or 2;
+
+var
+  ISelections: array of UTF8String;
+  SelectValue: integer;
+
+implementation
+
+uses
+  UGraphic,
+  UMain,
+  UIni,
+  UTexture,
+  ULanguage,
+  UParty,
+  UPlaylist,
+  USongs,
+  UUnicodeUtils;
+
+function TScreenSongMenu.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // key down
+    if (CurMenu = SM_Playlist_New) and (Interaction=0) then
+    begin
+      // check normal keys
+      if IsAlphaNumericChar(CharCode) or
+         (CharCode in [Ord(' '), Ord('-'), Ord('_'), Ord('!'),
+                       Ord(','), Ord('<'), Ord('/'), Ord('*'),
+                       Ord('?'), Ord(''''), Ord('"')]) then
+      begin
+        Button[Interaction].Text[0].Text := Button[Interaction].Text[0].Text +
+                                            UCS4ToUTF8String(CharCode);
+        exit;
+      end;
+
+      // check special keys
+      case PressedKey of
+        SDLK_BACKSPACE:
+          begin
+            Button[Interaction].Text[0].DeleteLastLetter;
+            exit;
+          end;
+      end;
+    end;
+
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE:
+        begin
+          AudioPlayback.PlaySound(SoundLib.Back);
+          Visible := false;
+        end;
+
+      SDLK_RETURN:
+        begin
+          HandleReturn;
+        end;
+
+      SDLK_DOWN: InteractNext;
+      SDLK_UP:   InteractPrev;
+
+      SDLK_RIGHT:
+        begin
+          if (Interaction=3) then
+            InteractInc;
+        end;
+      SDLK_LEFT:
+        begin
+          if (Interaction=3) then
+            InteractDec;
+        end;
+
+      SDLK_1:
+        begin // jocker
+            // use joker
+          case CurMenu of
+            SM_Party_Main:
+            begin
+              ScreenSong.DoJoker(0)
+            end;
+          end;
+        end;
+      SDLK_2:
+        begin // jocker
+            // use joker
+          case CurMenu of
+            SM_Party_Main:
+            begin
+              ScreenSong.DoJoker(1)
+            end;
+          end;
+        end;
+      SDLK_3:
+        begin // jocker
+            // use joker
+          case CurMenu of
+            SM_Party_Main:
+            begin
+              ScreenSong.DoJoker(2)
+            end;
+          end;
+        end;
+    end; // case
+  end; // if
+end;
+
+constructor TScreenSongMenu.Create;
+begin
+  inherited Create;
+
+  // create dummy selectslide entrys
+  SetLength(ISelections, 1);
+  ISelections[0] := 'Dummy';
+
+  AddText(Theme.SongMenu.TextMenu);
+
+  LoadFromTheme(Theme.SongMenu);
+
+  AddButton(Theme.SongMenu.Button1);
+  if (Length(Button[0].Text) = 0) then
+    AddButtonText(14, 20, 'Button 1');
+
+  AddButton(Theme.SongMenu.Button2);
+  if (Length(Button[1].Text) = 0) then
+    AddButtonText(14, 20, 'Button 2');
+
+  AddButton(Theme.SongMenu.Button3);
+  if (Length(Button[2].Text) = 0) then
+    AddButtonText(14, 20, 'Button 3');
+
+  AddSelectSlide(Theme.SongMenu.SelectSlide3, SelectValue, ISelections);
+
+  AddButton(Theme.SongMenu.Button4);
+  if (Length(Button[3].Text) = 0) then
+    AddButtonText(14, 20, 'Button 4');
+
+  Interaction := 0;
+end;
+
+function TScreenSongMenu.Draw: boolean;
+begin
+  Result := inherited Draw;
+end;
+
+procedure TScreenSongMenu.OnShow;
+begin
+  inherited;
+end;
+
+procedure TScreenSongMenu.MenuShow(sMenu: byte);
+begin
+  Interaction := 0; // reset interaction
+  Visible := true;  // set visible
+  case sMenu of
+    SM_Main:
+      begin
+        CurMenu := sMenu;
+        Text[0].Text := Language.Translate('SONG_MENU_NAME_MAIN');
+
+        Button[0].Visible := true;
+        Button[1].Visible := true;
+        Button[2].Visible := true;
+        Button[3].Visible := true;
+        SelectsS[0].Visible := false;
+
+        Button[0].Text[0].Text := Language.Translate('SONG_MENU_PLAY');
+        Button[1].Text[0].Text := Language.Translate('SONG_MENU_CHANGEPLAYERS');
+        Button[2].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_ADD');
+        Button[3].Text[0].Text := Language.Translate('SONG_MENU_EDIT');
+      end;
+
+    SM_PlayList:
+      begin
+        CurMenu := sMenu;
+        Text[0].Text := Language.Translate('SONG_MENU_NAME_PLAYLIST');
+
+        Button[0].Visible := true;
+        Button[1].Visible := true;
+        Button[2].Visible := true;
+        Button[3].Visible := true;
+        SelectsS[0].Visible := false;
+
+        Button[0].Text[0].Text := Language.Translate('SONG_MENU_PLAY');
+        Button[1].Text[0].Text := Language.Translate('SONG_MENU_CHANGEPLAYERS');
+        Button[2].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_DEL');
+        Button[3].Text[0].Text := Language.Translate('SONG_MENU_EDIT');
+      end;
+
+    SM_Playlist_Add:
+      begin
+        CurMenu := sMenu;
+        Text[0].Text := Language.Translate('SONG_MENU_NAME_PLAYLIST_ADD');
+
+        Button[0].Visible := true;
+        Button[1].Visible := false;
+        Button[2].Visible := false;
+        Button[3].Visible := true;
+        SelectsS[0].Visible := true;
+
+        Button[0].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_ADD_NEW');
+        Button[3].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_ADD_EXISTING');
+
+        SetLength(ISelections, Length(PlaylistMan.Playlists));
+        PlaylistMan.GetNames(ISelections);
+
+        if (Length(ISelections)>=1) then
+        begin
+          UpdateSelectSlideOptions(Theme.SongMenu.SelectSlide3, 0, ISelections, SelectValue);
+        end
+        else
+        begin
+          Button[3].Visible := false;
+          SelectsS[0].Visible := false;
+          Button[2].Visible := true;
+          Button[2].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_NOEXISTING');
+        end;
+      end;
+
+    SM_Playlist_New:
+      begin
+        CurMenu := sMenu;
+        Text[0].Text := Language.Translate('SONG_MENU_NAME_PLAYLIST_NEW');
+
+        Button[0].Visible := true;
+        Button[1].Visible := false;
+        Button[2].Visible := true;
+        Button[3].Visible := true;
+        SelectsS[0].Visible := false;
+
+        Button[0].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_NEW_UNNAMED');
+        Button[2].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_NEW_CREATE');
+        Button[3].Text[0].Text := Language.Translate('SONG_MENU_CANCEL');
+      end;
+
+    SM_Playlist_DelItem:
+      begin
+        CurMenu := sMenu;
+        Text[0].Text := Language.Translate('SONG_MENU_NAME_PLAYLIST_DELITEM');
+
+        Button[0].Visible := true;
+        Button[1].Visible := false;
+        Button[2].Visible := false;
+        Button[3].Visible := true;
+        SelectsS[0].Visible := false;
+
+        Button[0].Text[0].Text := Language.Translate('SONG_MENU_YES');
+        Button[3].Text[0].Text := Language.Translate('SONG_MENU_CANCEL');
+      end;
+
+    SM_Playlist_Load:
+      begin
+        CurMenu := sMenu;
+        Text[0].Text := Language.Translate('SONG_MENU_NAME_PLAYLIST_LOAD');
+
+        // show delete curent playlist button when playlist is opened
+        Button[0].Visible := (CatSongs.CatNumShow = -3);
+
+        Button[1].Visible := false;
+        Button[2].Visible := false;
+        Button[3].Visible := true;
+        SelectsS[0].Visible := true;
+
+        Button[0].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_DELCURRENT');
+        Button[3].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_LOAD');
+
+        SetLength(ISelections, Length(PlaylistMan.Playlists));
+        PlaylistMan.GetNames(ISelections);
+
+        if (Length(ISelections)>=1) then
+        begin
+          UpdateSelectSlideOptions(Theme.SongMenu.SelectSlide3, 0, ISelections, SelectValue);
+          Interaction := 3;
+        end
+        else
+        begin
+          Button[3].Visible := false;
+          SelectsS[0].Visible := false;
+          Button[2].Visible := true;
+          Button[2].Text[0].Text := Language.Translate('SONG_MENU_PLAYLIST_NOEXISTING');
+          Interaction := 2;
+        end;
+      end;
+
+    SM_Playlist_Del:
+      begin
+        CurMenu := sMenu;
+        Text[0].Text := Language.Translate('SONG_MENU_NAME_PLAYLIST_DEL');
+
+        Button[0].Visible := true;
+        Button[1].Visible := false;
+        Button[2].Visible := false;
+        Button[3].Visible := true;
+        SelectsS[0].Visible := false;
+
+        Button[0].Text[0].Text := Language.Translate('SONG_MENU_YES');
+        Button[3].Text[0].Text := Language.Translate('SONG_MENU_CANCEL');
+      end;
+
+    SM_Party_Main:
+      begin
+        CurMenu := sMenu;
+        Text[0].Text := Language.Translate('SONG_MENU_NAME_PARTY_MAIN');
+
+        Button[0].Visible := true;
+        Button[1].Visible := false;
+        Button[2].Visible := false;
+        Button[3].Visible := true;
+        SelectsS[0].Visible := false;
+
+        Button[0].Text[0].Text := Language.Translate('SONG_MENU_PLAY');
+        //Button[1].Text[0].Text := Language.Translate('SONG_MENU_JOKER');
+        //Button[2].Text[0].Text := Language.Translate('SONG_MENU_PLAYMODI');
+        Button[3].Text[0].Text := Language.Translate('SONG_MENU_JOKER');
+      end;
+
+    SM_Party_Joker:
+      begin
+        CurMenu := sMenu;
+        Text[0].Text := Language.Translate('SONG_MENU_NAME_PARTY_JOKER');
+        // to-do : Party
+        Button[0].Visible := (Length(Party.Teams) >= 1) AND (Party.Teams[0].JokersLeft > 0);
+        Button[1].Visible := (Length(Party.Teams) >= 2) AND (Party.Teams[1].JokersLeft > 0);
+        Button[2].Visible := (Length(Party.Teams) >= 3) AND (Party.Teams[2].JokersLeft > 0);
+        Button[3].Visible := True;
+        SelectsS[0].Visible := False;
+
+        if (Button[0].Visible) then
+          Button[0].Text[0].Text := UTF8String(Party.Teams[0].Name);
+        if (Button[1].Visible) then
+          Button[1].Text[0].Text := UTF8String(Party.Teams[1].Name);
+        if (Button[2].Visible) then
+          Button[2].Text[0].Text := UTF8String(Party.Teams[2].Name);
+        Button[3].Text[0].Text := Language.Translate('SONG_MENU_CANCEL');
+
+        // set right interaction
+        if (not Button[0].Visible) then
+        begin
+          if (not Button[1].Visible) then
+          begin
+            if (not Button[2].Visible) then
+              Interaction := 4
+            else
+              Interaction := 2;
+          end
+          else
+            Interaction := 1;
+        end;
+
+      end;
+  end;
+end;
+
+procedure TScreenSongMenu.HandleReturn;
+begin
+  case CurMenu of
+    SM_Main:
+      begin
+        case Interaction of
+          0: // button 1
+            begin
+              ScreenSong.StartSong;
+              Visible := false;
+            end;
+
+          1: // button 2
+            begin
+              // select new players then sing:
+              ScreenSong.SelectPlayers;
+              Visible := false;
+            end;
+
+          2: // button 3
+            begin
+              // show add to playlist menu
+              MenuShow(SM_Playlist_Add);
+            end;
+
+          3: // selectslide 3
+            begin
+              //Dummy
+            end;
+
+          4: // button 4
+            begin
+              ScreenSong.OpenEditor;
+              Visible := false;
+            end;
+        end;
+      end;
+
+    SM_PlayList:
+      begin
+        Visible := false;
+        case Interaction of
+          0: // button 1
+            begin
+              ScreenSong.StartSong;
+              Visible := false;
+            end;
+
+          1: // button 2
+            begin
+              // select new players then sing:
+              ScreenSong.SelectPlayers;
+              Visible := false;
+            end;
+
+          2: // button 3
+            begin
+              // show add to playlist menu
+              MenuShow(SM_Playlist_DelItem);
+            end;
+
+          3: // selectslide 3
+            begin
+              // dummy
+            end;
+
+          4: // button 4
+            begin
+              ScreenSong.OpenEditor;
+              Visible := false;
+            end;
+        end;
+      end;
+
+    SM_Playlist_Add:
+      begin
+        case Interaction of
+          0: // button 1
+            begin
+              MenuShow(SM_Playlist_New);
+            end;
+
+          3: // selectslide 3
+            begin
+              // dummy
+            end;
+
+          4: // button 4
+            begin
+              PlaylistMan.AddItem(ScreenSong.Interaction, SelectValue);
+              Visible := false;
+            end;
+        end;
+      end;
+
+      SM_Playlist_New:
+      begin
+        case Interaction of
+          0: // button 1
+            begin
+              // nothing, button for entering name
+            end;
+
+          2: // button 3
+            begin
+              // create playlist and add song
+              PlaylistMan.AddItem(
+              ScreenSong.Interaction,
+              PlaylistMan.AddPlaylist(Button[0].Text[0].Text));
+              Visible := false;
+            end;
+
+          3: // selectslide 3
+            begin
+              // cancel -> go back to add screen
+              MenuShow(SM_Playlist_Add);
+            end;
+
+          4: // button 4
+            begin
+              Visible := false;
+            end;
+        end;
+      end;
+
+    SM_Playlist_DelItem:
+      begin
+        Visible := false;
+        case Interaction of
+          0: // button 1
+            begin
+              // delete
+              PlayListMan.DelItem(PlayListMan.GetIndexbySongID(ScreenSong.Interaction));
+              Visible := false;
+            end;
+
+          4: // button 4
+            begin
+              MenuShow(SM_Playlist);
+            end;
+        end;
+      end;
+
+    SM_Playlist_Load:
+      begin
+        case Interaction of
+          0: // button 1 (Delete playlist)
+            begin
+              MenuShow(SM_Playlist_Del);
+            end;
+          4: // button 4
+            begin
+              // load playlist
+              PlaylistMan.SetPlayList(SelectValue);
+              Visible := false;
+            end;
+        end;
+      end;
+
+    SM_Playlist_Del:
+      begin
+        Visible := false;
+        case Interaction of
+          0: // button 1
+            begin
+              // delete
+              PlayListMan.DelPlaylist(PlaylistMan.CurPlayList);
+              Visible := false;
+            end;
+
+          4: // button 4
+            begin
+              MenuShow(SM_Playlist_Load);
+            end;
+        end;
+      end;
+
+    SM_Party_Main:
+      begin
+        case Interaction of
+          0: // button 1
+            begin
+              // start singing
+              Party.CallAfterSongSelect;
+              Visible := false;
+            end;
+
+          4: // button 4
+            begin
+              // joker
+              MenuShow(SM_Party_Joker);
+            end;
+        end;
+      end;
+
+    SM_Party_Joker:
+      begin
+        Visible := false;
+        case Interaction of
+          0: // button 1
+            begin
+              // joker team 1
+              ScreenSong.DoJoker(0);
+            end;
+
+          1: // button 2
+            begin
+              // joker team 2
+              ScreenSong.DoJoker(1);
+            end;
+
+          2: // button 3
+            begin
+              // joker team 3
+              ScreenSong.DoJoker(2);
+            end;
+
+          4: // button 4
+            begin
+              // cancel... (go back to old menu)
+              MenuShow(SM_Party_Main);
+            end;
+        end;
+      end;
+  end;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenStatDetail.pas b/songmanagement/src/screens/UScreenStatDetail.pas
new file mode 100644
index 00000000..1638cd85
--- /dev/null
+++ b/songmanagement/src/screens/UScreenStatDetail.pas
@@ -0,0 +1,303 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenStatDetail;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  SysUtils,
+  UDisplay,
+  UMusic,
+  UIni,
+  UDataBase,
+  UThemes;
+
+type
+  TScreenStatDetail = class(TMenu)
+    public
+      Typ:  TStatType;
+      Page: cardinal;
+      Count: byte;
+      Reversed: boolean;
+
+      TotEntrys: cardinal;
+      TotPages:  cardinal;
+
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+
+      procedure SetTitle;
+      Procedure SetPage(NewPage: cardinal);
+  end;
+
+implementation
+
+uses
+  Math,
+  Classes,
+  UGraphic,
+  ULanguage,
+  ULog,
+  UUnicodeUtils;
+
+function TScreenStatDetail.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenStatMain);
+        end;
+      SDLK_RETURN:
+        begin
+          if Interaction = 0 then
+          begin
+            //Next Page
+            SetPage(Page+1);
+          end;
+
+          if Interaction = 1 then
+          begin
+            //Previous Page
+            if (Page > 0) then
+              SetPage(Page-1);
+          end;
+
+          if Interaction = 2 then
+          begin
+            //Reverse Order
+            Reversed := not Reversed;
+            SetPage(Page);
+          end;
+
+          if Interaction = 3 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Back);
+            FadeTo(@ScreenStatMain);
+          end;
+        end;
+      SDLK_LEFT:
+      begin
+          InteractPrev;
+      end;
+      SDLK_RIGHT:
+      begin
+          InteractNext;
+      end;
+      SDLK_UP:
+      begin
+          InteractPrev;
+      end;
+      SDLK_DOWN:
+      begin
+          InteractNext;
+      end;
+    end;
+  end;
+end;
+
+constructor TScreenStatDetail.Create;
+var
+  I:    integer;
+begin
+  inherited Create;
+
+  for I := 0 to High(Theme.StatDetail.TextList) do
+    AddText(Theme.StatDetail.TextList[I]);
+
+  Count := Length(Theme.StatDetail.TextList);
+
+  AddText(Theme.StatDetail.TextDescription);
+  AddText(Theme.StatDetail.TextPage);
+
+  LoadFromTheme(Theme.StatDetail);
+
+  AddButton(Theme.StatDetail.ButtonNext);
+  if (Length(Button[0].Text)=0) then
+    AddButtonText(14, 20, Language.Translate('STAT_NEXT'));
+
+  AddButton(Theme.StatDetail.ButtonPrev);
+  if (Length(Button[1].Text)=0) then
+    AddButtonText(14, 20, Language.Translate('STAT_PREV'));
+
+  AddButton(Theme.StatDetail.ButtonReverse);
+  if (Length(Button[2].Text)=0) then
+    AddButtonText(14, 20, Language.Translate('STAT_REVERSE'));
+
+  AddButton(Theme.StatDetail.ButtonExit);
+  if (Length(Button[3].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[7]);
+
+  Interaction := 0;
+  Typ := TStatType(0);
+end;
+
+procedure TScreenStatDetail.OnShow;
+begin
+  inherited;
+
+  //Set Tot Entrys and PAges
+  TotEntrys := DataBase.GetTotalEntrys(Typ);
+  TotPages := Ceil(TotEntrys / Count);
+
+  //Show correct Title
+  SetTitle;
+
+  //Show First Page
+  Reversed := false;
+  SetPage(0);
+end;
+
+procedure TScreenStatDetail.SetTitle;
+begin
+  if Reversed then
+    Text[Count].Text := Theme.StatDetail.DescriptionR[Ord(Typ)]
+  else
+    Text[Count].Text := Theme.StatDetail.Description[Ord(Typ)];
+end;
+
+procedure TScreenStatDetail.SetPage(NewPage: cardinal);
+var
+  StatList: TList;
+  I: integer;
+  FormatStr: string;
+  PerPage: byte;
+begin
+  // fetch statistics
+  StatList := Database.GetStats(Typ, Count, NewPage, Reversed);
+  if ((StatList <> nil) and (StatList.Count > 0)) then
+  begin
+    Page := NewPage;
+
+    // reset texts
+    for I := 0 to Count-1 do
+      Text[I].Text := '';
+
+    FormatStr := Theme.StatDetail.FormatStr[Ord(Typ)];
+
+    //refresh Texts
+    for I := 0 to StatList.Count-1 do
+    begin
+      try
+        case Typ of
+          stBestScores: begin //Best Scores
+            with TStatResultBestScores(StatList[I]) do
+            begin
+              //Set Texts
+              if (Score > 0) then
+              begin
+                Text[I].Text := Format(FormatStr,
+                  [Singer, Score, Theme.ILevel[Difficulty], SongArtist, SongTitle, Date]);
+              end;
+            end;
+          end;
+
+          stBestSingers: begin //Best Singers
+            with TStatResultBestSingers(StatList[I]) do
+            begin
+              //Set Texts
+              if (AverageScore > 0) then
+                Text[I].Text := Format(FormatStr, [Player, AverageScore]);
+            end;
+          end;
+
+          stMostSungSong: begin //Popular Songs
+            with TStatResultMostSungSong(StatList[I]) do
+            begin
+              //Set Texts
+              if (Artist <> '') then
+                Text[I].Text := Format(FormatStr, [Artist, Title, TimesSung]);
+            end;
+          end;
+
+          stMostPopBand: begin //Popular Bands
+            with TStatResultMostPopBand(StatList[I]) do
+            begin
+              //Set Texts
+              if (ArtistName <> '') then
+                Text[I].Text := Format(FormatStr, [ArtistName, TimesSungtot]);
+            end;
+          end;
+        end;
+      except
+        on E: EConvertError do
+          Log.LogError('Error Parsing FormatString in UScreenStatDetail: ' + E.Message);
+      end;
+    end;
+
+    if (Page + 1 = TotPages) and (TotEntrys mod Count <> 0) then
+      PerPage := (TotEntrys mod Count)
+    else
+      PerPage := Count;
+
+    try      
+      Text[Count+1].Text := Format(Theme.StatDetail.PageStr,
+          [Page + 1, TotPages, PerPage, TotEntrys]);
+    except
+      on E: EConvertError do
+        Log.LogError('Error Parsing FormatString in UScreenStatDetail: ' + E.Message);
+    end;
+
+    //Show correct Title
+    SetTitle;
+  end;
+
+  Database.FreeStats(StatList);
+end;
+
+procedure TScreenStatDetail.SetAnimationProgress(Progress: real);
+var
+  I: integer;
+begin
+  for I := 0 to High(Button) do
+    Button[I].Texture.ScaleW := Progress;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenStatMain.pas b/songmanagement/src/screens/UScreenStatMain.pas
new file mode 100644
index 00000000..204f40cd
--- /dev/null
+++ b/songmanagement/src/screens/UScreenStatMain.pas
@@ -0,0 +1,323 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenStatMain;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  UMenu,
+  SDL,
+  SysUtils,
+  UDisplay,
+  UMusic,
+  UIni,
+  UThemes;
+
+type
+  TScreenStatMain = class(TMenu)
+    private
+      //Some Stat Value that don't need to be calculated 2 times
+      SongsWithVid: cardinal;
+      function FormatOverviewIntro(FormatStr: UTF8String): UTF8String;
+      function FormatSongOverview(FormatStr: UTF8String): UTF8String;
+      function FormatPlayerOverview(FormatStr: UTF8String): UTF8String;
+    public
+      TextOverview:    integer;
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      procedure OnShow; override;
+      procedure SetAnimationProgress(Progress: real); override;
+
+      procedure SetOverview;
+  end;
+
+implementation
+
+uses
+  UGraphic,
+  UDataBase,
+  USongs,
+  USong,
+  ULanguage,
+  UCommon,
+  Classes,
+  ULog,
+  UUnicodeUtils;
+
+function TScreenStatMain.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if (PressedDown) then
+  begin // Key Down
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+    
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE :
+        begin
+          Ini.Save;
+          AudioPlayback.PlaySound(SoundLib.Back);
+          FadeTo(@ScreenMain);
+        end;
+      SDLK_RETURN:
+        begin
+          //Exit Button Pressed
+          if Interaction = 4 then
+          begin
+            AudioPlayback.PlaySound(SoundLib.Back);
+            FadeTo(@ScreenMain);
+          end
+          else //One of the Stats Buttons Pressed
+          begin
+            AudioPlayback.PlaySound(SoundLib.Back);
+            ScreenStatDetail.Typ := TStatType(Interaction);
+            FadeTo(@ScreenStatDetail);
+          end;
+        end;
+      SDLK_LEFT:
+      begin
+          InteractPrev;
+      end;
+      SDLK_RIGHT:
+      begin
+          InteractNext;
+      end;
+      SDLK_UP:
+      begin
+          InteractPrev;
+      end;
+      SDLK_DOWN:
+      begin
+          InteractNext;
+      end;
+    end;
+  end;
+end;
+
+constructor TScreenStatMain.Create;
+var
+  I:    integer;
+begin
+  inherited Create;
+
+  TextOverview := AddText(Theme.StatMain.TextOverview);
+
+  LoadFromTheme(Theme.StatMain);
+
+  AddButton(Theme.StatMain.ButtonScores);
+  if (Length(Button[0].Text)=0) then
+    AddButtonText(14, 20, Theme.StatDetail.Description[0]);
+
+  AddButton(Theme.StatMain.ButtonSingers);
+  if (Length(Button[1].Text)=0) then
+    AddButtonText(14, 20, Theme.StatDetail.Description[1]);
+
+  AddButton(Theme.StatMain.ButtonSongs);
+  if (Length(Button[2].Text)=0) then
+    AddButtonText(14, 20, Theme.StatDetail.Description[2]);
+
+  AddButton(Theme.StatMain.ButtonBands);
+  if (Length(Button[3].Text)=0) then
+    AddButtonText(14, 20, Theme.StatDetail.Description[3]);
+
+  AddButton(Theme.StatMain.ButtonExit);
+  if (Length(Button[4].Text)=0) then
+    AddButtonText(14, 20, Theme.Options.Description[4]);
+
+  Interaction := 0;
+
+  //Set Songs with Vid
+  SongsWithVid := 0;
+  for I := 0 to Songs.SongList.Count -1 do
+    if (TSong(Songs.SongList[I]).Video.IsSet) then
+      Inc(SongsWithVid);
+end;
+
+procedure TScreenStatMain.OnShow;
+begin
+  inherited;
+
+  //Set Overview Text:
+  SetOverview;
+end;
+
+function TScreenStatMain.FormatOverviewIntro(FormatStr: UTF8String): UTF8String;
+var
+  Year, Month, Day: word;
+begin
+  {Format:
+    %0:d Ultrastar Version
+    %1:d Day of Reset
+    %2:d Month of Reset
+    %3:d Year of Reset}
+
+  Result := '';
+
+  try
+    DecodeDate(Database.GetStatReset(), Year, Month, Day);
+    Result := Format(FormatStr, [Language.Translate('US_VERSION'), Day, Month, Year]);
+  except
+    on E: EConvertError do
+      Log.LogError('Error Parsing FormatString "STAT_OVERVIEW_INTRO": ' + E.Message);
+  end;
+end;
+
+function TScreenStatMain.FormatSongOverview(FormatStr: UTF8String): UTF8String;
+var
+  CntSongs, CntSungSongs, CntVidSongs: integer;
+  MostPopSongArtist, MostPopSongTitle: UTF8String;
+  StatList: TList;
+  MostSungSong: TStatResultMostSungSong;
+begin
+  {Format:
+    %0:d Count Songs
+    %1:d Count of Sung Songs
+    %2:d Count of UnSung Songs
+    %3:d Count of Songs with Video
+    %4:s Name of the most popular Song}
+
+  CntSongs := Songs.SongList.Count;
+  CntSungSongs := Database.GetTotalEntrys(stMostSungSong);
+  CntVidSongs := SongsWithVid;
+
+  StatList := Database.GetStats(stMostSungSong, 1, 0, false);
+  if ((StatList <> nil) and (StatList.Count > 0)) then
+  begin
+    MostSungSong := StatList[0];
+    MostPopSongArtist := MostSungSong.Artist;
+    MostPopSongTitle := MostSungSong.Title;
+  end
+  else
+  begin
+    MostPopSongArtist := '-';
+    MostPopSongTitle := '-';
+  end;
+  Database.FreeStats(StatList);
+
+  Result := '';
+  
+  try
+    Result := Format(FormatStr, [
+        CntSongs, CntSungSongs, CntSongs-CntSungSongs, CntVidSongs,
+        MostPopSongArtist, MostPopSongTitle]);
+  except
+    on E: EConvertError do
+      Log.LogError('Error Parsing FormatString "STAT_OVERVIEW_SONG": ' + E.Message);
+  end;
+end;
+
+function TScreenStatMain.FormatPlayerOverview(FormatStr: UTF8String): UTF8String;
+var
+  CntPlayers: integer;
+  BestScoreStat:    TStatResultBestScores;
+  BestSingerStat:   TStatResultBestSingers;
+  BestPlayer, BestScorePlayer: UTF8String;
+  BestPlayerScore, BestScore: integer;
+  SingerStats, ScoreStats: TList;
+begin
+  {Format:
+    %0:d Count Players
+    %1:s Best Player
+    %2:d Best Players Score
+    %3:s Best Score Player
+    %4:d Best Score}
+
+  CntPlayers := Database.GetTotalEntrys(stBestSingers);
+
+  SingerStats := Database.GetStats(stBestSingers, 1, 0, false);
+  if ((SingerStats <> nil) and (SingerStats.Count > 0)) then
+  begin
+    BestSingerStat := SingerStats[0];
+    BestPlayer := BestSingerStat.Player;
+    BestPlayerScore := BestSingerStat.AverageScore;
+  end
+  else
+  begin
+    BestPlayer := '-';
+    BestPlayerScore := 0;
+  end;
+  Database.FreeStats(SingerStats);
+
+  ScoreStats  := Database.GetStats(stBestScores, 1, 0, false);
+  if ((ScoreStats <> nil) and (ScoreStats.Count > 0)) then
+  begin
+    BestScoreStat := ScoreStats[0];
+    BestScorePlayer := BestScoreStat.Singer;
+    BestScore := BestScoreStat.Score;
+  end
+  else
+  begin
+    BestScorePlayer := '-';
+    BestScore := 0;
+  end;
+  Database.FreeStats(ScoreStats);
+
+  Result := '';
+
+  try
+    Result := Format(Formatstr, [
+        CntPlayers, BestPlayer, BestPlayerScore,
+        BestScorePlayer, BestScore]);
+  except
+    on E: EConvertError do
+      Log.LogError('Error Parsing FormatString "STAT_OVERVIEW_PLAYER": ' + E.Message);
+  end;
+end;
+
+procedure TScreenStatMain.SetOverview;
+var
+  Overview: UTF8String;
+begin
+  // Format overview
+  Overview := FormatOverviewIntro(Language.Translate('STAT_OVERVIEW_INTRO')) + '\n \n' + 
+              FormatSongOverview(Language.Translate('STAT_OVERVIEW_SONG')) + '\n \n' + 
+              FormatPlayerOverview(Language.Translate('STAT_OVERVIEW_PLAYER'));
+  Text[0].Text := Overview;
+end;
+
+procedure TScreenStatMain.SetAnimationProgress(Progress: real);
+var
+  I: integer;
+begin
+  for I := 0 to high(Button) do
+    Button[I].Texture.ScaleW := Progress;
+end;
+
+end.
diff --git a/songmanagement/src/screens/UScreenTop5.pas b/songmanagement/src/screens/UScreenTop5.pas
new file mode 100644
index 00000000..75b9f160
--- /dev/null
+++ b/songmanagement/src/screens/UScreenTop5.pas
@@ -0,0 +1,307 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenTop5;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+  SysUtils,
+  SDL,
+  UDisplay,
+  UMenu,
+  UMusic,
+  USongs,
+  UThemes;
+
+type
+  TScreenTop5 = class(TMenu)
+    public
+      TextLevel:       integer;
+      TextArtistTitle: integer;
+      DifficultyShow:  integer;
+
+      StaticNumber:    array[1..5] of integer;
+      TextNumber:      array[1..5] of integer;
+      TextName:        array[1..5] of integer;
+      TextScore:       array[1..5] of integer;
+      TextDate:        array[1..5] of integer;
+
+      Fadeout:         boolean;
+
+      constructor Create; override;
+      function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+      function ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; override;
+      procedure OnShow; override;
+      procedure DrawScores(difficulty: integer);
+      function Draw: boolean; override;
+  end;
+
+implementation
+
+uses
+  UDataBase,
+  UGraphic,
+  UMain,
+  UIni,
+  UNote,
+  UUnicodeUtils;
+
+function TScreenTop5.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+begin
+  Result := true;
+  if PressedDown then
+  begin
+    // check normal keys
+    case UCS4UpperCase(CharCode) of
+      Ord('Q'):
+        begin
+          Result := false;
+          Exit;
+        end;
+    end;
+
+    // check special keys
+    case PressedKey of
+      SDLK_ESCAPE,
+      SDLK_BACKSPACE,
+      SDLK_RETURN:
+        begin
+          if (not Fadeout) then
+          begin
+            FadeTo(@ScreenSong);
+            Fadeout := true;
+          end;
+        end;
+      SDLK_RIGHT:
+        begin
+          inc(DifficultyShow);
+          if (DifficultyShow>2) then
+            DifficultyShow:=0;
+          DrawScores(DifficultyShow);
+        end;
+      SDLK_LEFT:
+        begin
+          dec(DifficultyShow);
+          if (DifficultyShow<0) then
+            DifficultyShow:=2;
+          DrawScores(DifficultyShow);
+        end;
+      SDLK_UP:
+        begin
+          inc(DifficultyShow);
+          if (DifficultyShow>2) then
+            DifficultyShow:=0;
+          DrawScores(DifficultyShow);
+        end;
+      SDLK_DOWN:
+        begin
+          dec(DifficultyShow);
+          if (DifficultyShow<0) then
+            DifficultyShow:=2;
+          DrawScores(DifficultyShow);
+        end;
+      SDLK_SYSREQ:
+        begin
+          Display.SaveScreenShot;
+        end;
+    end;
+  end;
+end;
+
+function TScreenTop5.ParseMouse(MouseButton: integer;
+                                BtnDown: boolean;
+				X, Y: integer): boolean;
+begin
+  Result := true;
+  if (MouseButton = SDL_BUTTON_LEFT) and BtnDown then
+    //left-click anywhere sends return
+    ParseInput(SDLK_RETURN, 0, true);
+end;
+
+constructor TScreenTop5.Create;
+var
+  I: integer;
+begin
+  inherited Create;
+
+  LoadFromTheme(Theme.Top5);
+
+  TextLevel       := AddText(Theme.Top5.TextLevel);
+  TextArtistTitle := AddText(Theme.Top5.TextArtistTitle);
+
+  for I := 0 to 4 do
+  begin
+    StaticNumber[I+1] := AddStatic(Theme.Top5.StaticNumber[I]);
+    TextNumber[I+1]   := AddText  (Theme.Top5.TextNumber[I]);
+    TextName[I+1]     := AddText  (Theme.Top5.TextName[I]);
+    TextScore[I+1]    := AddText  (Theme.Top5.TextScore[I]);
+    TextDate[I+1]     := AddText  (Theme.Top5.TextDate[I]);
+  end;
+
+end;
+
+procedure TScreenTop5.OnShow;
+var
+  I:    integer;
+  PMax: integer;
+  sung: boolean; //score added? otherwise in wasn't sung!
+begin
+  inherited;
+
+  sung := false;
+  Fadeout := false;
+  DifficultyShow := Ini.Difficulty;
+
+  //ReadScore(CurrentSong);
+
+  PMax := Ini.Players;
+  if PMax = 4 then
+    PMax := 5;
+  for I := 0 to PMax do
+  begin
+    if (Round(Player[I].ScoreTotalInt) > 0) and (ScreenSing.SungToEnd) then
+    begin
+      DataBase.AddScore(CurrentSong, Ini.Difficulty, Ini.Name[I], Round(Player[I].ScoreTotalInt));
+      sung:=true;
+    end;
+  end;
+
+  if sung then
+    DataBase.WriteScore(CurrentSong);
+  DataBase.ReadScore(CurrentSong);
+
+  Text[TextArtistTitle].Text := CurrentSong.Artist + ' - ' + CurrentSong.Title;
+
+  for I := 1 to Length(CurrentSong.Score[Ini.Difficulty]) do
+  begin
+    Statics[StaticNumber[I]].Visible := true;
+    Text[TextNumber[I]].Visible := true;
+    Text[TextName[I]].Visible := true;
+    Text[TextScore[I]].Visible := true;
+    Text[TextDate[I]].Visible := true;
+
+    Text[TextName[I]].Text := CurrentSong.Score[Ini.Difficulty, I-1].Name;
+    Text[TextScore[I]].Text := IntToStr(CurrentSong.Score[Ini.Difficulty, I-1].Score);
+    Text[TextDate[I]].Text := CurrentSong.Score[Ini.Difficulty, I-1].Date;
+  end;
+
+  for I := Length(CurrentSong.Score[Ini.Difficulty]) + 1 to 5 do
+  begin
+    Statics[StaticNumber[I]].Visible := false;
+    Text[TextNumber[I]].Visible := false;
+    Text[TextName[I]].Visible := false;
+    Text[TextScore[I]].Visible := false;
+    Text[TextDate[I]].Visible := false;
+  end;
+
+  Text[TextLevel].Text := IDifficultyTranslated[Ini.Difficulty];
+end;
+
+procedure TScreenTop5.DrawScores(difficulty: integer);
+var
+  I:    integer;
+begin
+  for I := 1 to Length(CurrentSong.Score[difficulty]) do
+  begin
+    Statics[StaticNumber[I]].Visible := true;
+    Text[TextNumber[I]].Visible := true;
+    Text[TextName[I]].Visible := true;
+    Text[TextScore[I]].Visible := true;
+    Text[TextDate[I]].Visible := true;
+
+    Text[TextName[I]].Text := CurrentSong.Score[difficulty, I-1].Name;
+    Text[TextScore[I]].Text := IntToStr(CurrentSong.Score[difficulty, I-1].Score);
+    Text[TextDate[I]].Text := CurrentSong.Score[difficulty, I-1].Date;
+  end;
+
+  for I := Length(CurrentSong.Score[difficulty]) + 1 to 5 do
+  begin
+    Statics[StaticNumber[I]].Visible := false;
+    Text[TextNumber[I]].Visible := false;
+    Text[TextName[I]].Visible := false;
+    Text[TextScore[I]].Visible := false;
+    Text[TextDate[I]].Visible := false;
+  end;
+
+  Text[TextLevel].Text := IDifficulty[difficulty];
+end;
+
+function TScreenTop5.Draw: boolean;
+//var
+{
+  Min:     real;
+  Max:     real;
+  Factor:  real;
+  Factor2: real;
+
+  Item:    integer;
+  P:       integer;
+  C:       integer;
+}
+begin
+  // Singstar - let it be...... with 6 statics
+(*
+  if PlayersPlay = 6 then
+  begin
+    for Item := 4 to 6 do
+    begin
+      if ScreenAct = 1 then P := Item-4;
+      if ScreenAct = 2 then P := Item-1;
+
+      FillPlayer(Item, P);
+{
+      if ScreenAct = 1 then
+      begin
+        LoadColor(
+          Statics[StaticBoxLightest[Item]].Texture.ColR,
+          Statics[StaticBoxLightest[Item]].Texture.ColG,
+          Statics[StaticBoxLightest[Item]].Texture.ColB,
+          'P1Dark');
+      end;
+
+      if ScreenAct = 2 then
+      begin
+        LoadColor(
+          Statics[StaticBoxLightest[Item]].Texture.ColR,
+          Statics[StaticBoxLightest[Item]].Texture.ColG,
+          Statics[StaticBoxLightest[Item]].Texture.ColB,
+          'P4Dark');
+      end;
+}
+    end;
+  end;
+*)
+
+  Result := inherited Draw;
+end;
+
+end.
diff --git a/songmanagement/src/switches.inc b/songmanagement/src/switches.inc
new file mode 100644
index 00000000..64ebb5c2
--- /dev/null
+++ b/songmanagement/src/switches.inc
@@ -0,0 +1,129 @@
+// prevent pasdoc from parsing this file
+{$IFNDEF PASDOC}
+
+// compiler/IDE dependent config
+{$IFDEF FPC}
+  {$H+} // use AnsiString instead of ShortString as String-type (default in Delphi)
+
+  // if -dDEBUG is specified on the command-line, FPC uses some default
+  // compiler-flags specified in fpc.cfg -> use -dDEBUG_MODE instead
+  {$IFDEF DEBUG_MODE}
+    {$DEFINE DEBUG}
+  {$ENDIF}
+
+  {$DEFINE HasInline}
+{$ELSE}
+  {$DEFINE Delphi}
+
+  // Delphi version numbers (ignore Delphi < 7 and Delphi 8 (VER160))
+
+  {$IF Defined(VER180)} // Delphi 2006 (=10)
+    {$DEFINE DELPHI_10}
+    {$DEFINE DELPHI_7_UP}
+    {$DEFINE DELPHI_9_UP}
+    {$DEFINE DELPHI_10_UP}
+  {$ELSEIF Defined(VER170)} // Delphi 2005 (=9)
+    {$DEFINE DELPHI_9}
+    {$DEFINE DELPHI_7_UP}
+    {$DEFINE DELPHI_9_UP}    
+  {$ELSEIF Defined(VER150)}
+    {$DEFINE DELPHI_7}
+    {$DEFINE DELPHI_7_UP}
+  {$ELSE} // unsupported
+    {$WARN ERROR 'Unsupported compiler version'}
+  {$IFEND}
+
+  // inline directive introduced with Delphi 2005
+  {$IFDEF DELPHI_9_UP}
+    {$DEFINE HasInline}
+  {$ENDIF}
+{$ENDIF}
+
+
+// platform dependent config
+{$IF Defined(MSWINDOWS)}
+  // include defines but no constants
+  {$I config-win.inc}
+
+  // enable debug-mode. For development only!
+  {.$DEFINE DEBUG}
+  {$IFDEF DEBUG}
+    // windows apps are either GUI- or console-apps. Console-apps will open
+    // an additional console-window for output. For development only!
+    {$DEFINE CONSOLE}
+  {$ENDIF}
+
+  {$DEFINE HaveBASS}
+  {$DEFINE UseMIDIPort}
+{$ELSEIF Defined(DARWIN)}
+  // include defines but no constants
+  {$I config-darwin.inc}
+
+  // enable debug-mode. For development only!
+  {.$DEFINE DEBUG}
+  {$DEFINE CONSOLE}
+  {.$DEFINE HaveBASS}
+  {$DEFINE UTF8_FILENAMES}
+{$ELSEIF Defined(UNIX)}
+  // include defines but no constants
+  {$IF Defined(FREEBSD)}
+    {$I config-freebsd.inc}
+  {$ELSEIF Defined(Linux)}
+    {$I config-linux.inc}
+  {$IFEND}
+
+  // use "configure --enable-debug", "make debug" or
+  // the command-line parameter "-debug" instead of defining DEBUG directly
+  {.$DEFINE DEBUG}
+  // linux apps are always console-apps so leave this defined.
+  {$DEFINE CONSOLE}
+{$IFEND}
+
+// audio config
+{$IF Defined(HaveBASS)}
+  {$DEFINE UseBASSPlayback}
+  {$DEFINE UseBASSDecoder}
+  {$DEFINE UseBASSInput}
+{$ELSEIF Defined(HavePortaudio)}
+  {$DEFINE UseSDLPlayback}
+  {.$DEFINE UsePortaudioPlayback}
+  {$DEFINE UsePortaudioInput}
+  {$IFDEF HavePortmixer}
+    {$DEFINE UsePortmixer}
+  {$ENDIF}
+{$IFEND}
+
+// ffmpeg config
+{$IFDEF HaveFFmpeg}
+  {$DEFINE UseFFmpegDecoder}
+  {$DEFINE UseFFmpegResample}
+  {$DEFINE UseFFmpegVideo}
+  {$IFDEF HaveSWScale}
+    {$DEFINE UseSWScale}
+  {$ENDIF}
+{$ENDIF}
+
+{$IFDEF HaveLibsamplerate}
+  {$DEFINE UseSRCResample}
+{$ENDIF}
+
+// projectM config
+{$IF Defined(HaveProjectM)}
+  {$DEFINE UseProjectM}
+{$IFEND}
+
+// specify some useful defines
+
+{$IF Defined(UseFFmpegVideo) or Defined(UseFFmpegDecoder)}
+  {$DEFINE UseFFmpeg}
+{$IFEND}
+
+{$IF Defined(UseBASSInput) or Defined(UseBASSPlayback) or Defined(UseBASSDecoder)}
+  {$DEFINE UseBASS}
+{$IFEND}
+
+{$IF Defined(UsePortaudioInput) or Defined(UsePortaudioPlayback)}
+  {$DEFINE UsePortaudio}
+{$IFEND}
+
+{$ENDIF PASDOC}
\ No newline at end of file
diff --git a/songmanagement/src/ultrastardx.dpr b/songmanagement/src/ultrastardx.dpr
new file mode 100644
index 00000000..f6c9558c
--- /dev/null
+++ b/songmanagement/src/ultrastardx.dpr
@@ -0,0 +1,345 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+program ultrastardx;
+
+{$IFDEF MSWINDOWS}
+  {$R '..\res\ultrastardx.res' '..\res\ultrastardx.rc'}
+{$ENDIF}
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+{$IFDEF MSWINDOWS}
+  // Set global application-type (GUI/CONSOLE) switch for Windows.
+  // CONSOLE is the default for FPC, GUI for Delphi, so we have
+  // to specify one of the two in any case.
+  {$IFDEF CONSOLE}
+    {$APPTYPE CONSOLE}
+  {$ELSE}
+    {$APPTYPE GUI}
+  {$ENDIF}
+{$ENDIF}
+
+uses
+  {$IFDEF Unix}
+  cthreads,            // THIS MUST be the first used unit in FPC if Threads are used!!
+                       // (see http://wiki.lazarus.freepascal.org/Multithreaded_Application_Tutorial)
+  cwstring,            // Enable Unicode support
+  {$ENDIF}
+
+  {$IFNDEF FPC}
+  ctypes                 in 'lib\ctypes\ctypes.pas', // FPC compatibility types for C libs
+  {$ENDIF}
+
+  //------------------------------
+  //Includes - 3rd Party Libraries
+  //------------------------------
+  moduleloader           in 'lib\JEDI-SDL\SDL\Pas\moduleloader.pas',
+  gl                     in 'lib\JEDI-SDL\OpenGL\Pas\gl.pas',
+  glu                    in 'lib\JEDI-SDL\OpenGL\Pas\glu.pas',
+  glext                  in 'lib\JEDI-SDL\OpenGL\Pas\glext.pas',
+  sdl                    in 'lib\JEDI-SDL\SDL\Pas\sdl.pas',
+  sdl_image              in 'lib\JEDI-SDL\SDL_Image\Pas\sdl_image.pas',
+  sdlutils               in 'lib\JEDI-SDL\SDL\Pas\sdlutils.pas',
+  sdlstreams             in 'lib\JEDI-SDL\SDL\Pas\sdlstreams.pas',
+  UMediaCore_SDL         in 'media\UMediaCore_SDL.pas',
+
+  zlib                   in 'lib\zlib\zlib.pas',
+  png                    in 'lib\libpng\png.pas',
+  freetype               in 'lib\freetype\freetype.pas',
+
+  {$IFDEF UseBass}
+  bass                   in 'lib\bass\delphi\bass.pas',
+  UAudioCore_Bass        in 'media\UAudioCore_Bass.pas',
+  {$ENDIF}
+  {$IFDEF UsePortaudio}
+  portaudio              in 'lib\portaudio\portaudio.pas',
+  UAudioCore_Portaudio   in 'media\UAudioCore_Portaudio.pas',
+  {$ENDIF}
+  {$IFDEF UsePortmixer}
+  portmixer              in 'lib\portmixer\portmixer.pas',
+  {$ENDIF}
+
+  {$IFDEF UseFFmpeg}
+  avcodec                in 'lib\ffmpeg\avcodec.pas',
+  avformat               in 'lib\ffmpeg\avformat.pas',
+  avutil                 in 'lib\ffmpeg\avutil.pas',
+  rational               in 'lib\ffmpeg\rational.pas',
+  opt                    in 'lib\ffmpeg\opt.pas',
+  avio                   in 'lib\ffmpeg\avio.pas',
+  mathematics            in 'lib\ffmpeg\mathematics.pas',
+  UMediaCore_FFmpeg      in 'media\UMediaCore_FFmpeg.pas',
+  {$IFDEF UseSWScale}
+  swscale                in 'lib\ffmpeg\swscale.pas',
+  {$ENDIF}
+  {$ENDIF}
+
+  {$IFDEF UseSRCResample}
+  samplerate             in 'lib\samplerate\samplerate.pas',
+  {$ENDIF}
+
+  {$IFDEF UseProjectM}
+  projectM      in 'lib\projectM\projectM.pas',
+  {$ENDIF}
+
+  {$IFDEF MSWINDOWS}
+  {$IFDEF FPC}
+  // FPC compatibility file for Allocate/DeallocateHWnd
+  WinAllocation in 'lib\other\WinAllocation.pas',
+  {$ENDIF}
+
+  midiout       in 'lib\midi\midiout.pas',
+  CIRCBUF       in 'lib\midi\CIRCBUF.PAS',
+  MidiType      in 'lib\midi\MidiType.PAS',
+  MidiDefs      in 'lib\midi\MidiDefs.PAS',
+  MidiCons      in 'lib\midi\MidiCons.PAS',
+  MidiFile      in 'lib\midi\MidiFile.PAS',
+  Delphmcb      in 'lib\midi\Delphmcb.PAS',
+
+  DirWatch      in 'lib\other\DirWatch.pas',
+  {$ENDIF}
+
+  {$IFDEF DARWIN}
+  PseudoThread  in 'macosx\PseudoThread.pas',
+  {$ENDIF}
+
+  SQLiteTable3  in 'lib\SQLite\SQLiteTable3.pas',
+  SQLite3       in 'lib\SQLite\SQLite3.pas',
+
+  pcre          in 'lib\pcre\pcre.pas',
+
+  {$IFDEF MSWINDOWS}
+  // TntUnicodeControls
+  TntSystem         in 'lib\TntUnicodeControls\TntSystem.pas',
+  TntSysUtils       in 'lib\TntUnicodeControls\TntSysUtils.pas',
+  TntWindows        in 'lib\TntUnicodeControls\TntWindows.pas',
+  TntWideStrUtils   in 'lib\TntUnicodeControls\TntWideStrUtils.pas',
+  TntClasses        in 'lib\TntUnicodeControls\TntClasses.pas',
+  TntFormatStrUtils in 'lib\TntUnicodeControls\TntFormatStrUtils.pas',
+  {$IFNDEF DELPHI_10_UP} // WideStrings for FPC and Delphi < 2006
+  TntWideStrings   in 'lib\TntUnicodeControls\TntWideStrings.pas',
+  {$ENDIF}
+  {$ENDIF}
+
+  //------------------------------
+  //Includes - Lua Support
+  //------------------------------
+  ULua           in 'lib\Lua\ULua.pas',
+  ULuaUtils      in 'lua\ULuaUtils.pas',
+  ULuaGl         in 'lua\ULuaGl.pas',
+  ULuaLog        in 'lua\ULuaLog.pas',
+  ULuaTextGL     in 'lua\ULuaTextGL.pas',
+  ULuaTexture    in 'lua\ULuaTexture.pas',
+  UHookableEvent in 'lua\UHookableEvent.pas',
+  ULuaCore       in 'lua\ULuaCore.pas',
+  ULuaUsdx       in 'lua\ULuaUsdx.pas',
+  ULuaParty      in 'lua\ULuaParty.pas',
+  ULuaScreenSing in 'lua\ULuaScreenSing.pas',
+
+  //------------------------------
+  //Includes - Menu System
+  //------------------------------
+  UDisplay               in 'menu\UDisplay.pas',
+  UMenu                  in 'menu\UMenu.pas',
+  UMenuStatic            in 'menu\UMenuStatic.pas',
+  UMenuText              in 'menu\UMenuText.pas',
+  UMenuButton            in 'menu\UMenuButton.pas',
+  UMenuInteract          in 'menu\UMenuInteract.pas',
+  UMenuSelectSlide       in 'menu\UMenuSelectSlide.pas',
+  UMenuEqualizer         in 'menu\UMenuEqualizer.pas',
+  UDrawTexture           in 'menu\UDrawTexture.pas',
+  UMenuButtonCollection  in 'menu\UMenuButtonCollection.pas',
+
+  UMenuBackground        in 'menu\UMenuBackground.pas',
+  UMenuBackgroundNone    in 'menu\UMenuBackgroundNone.pas',
+  UMenuBackgroundColor   in 'menu\UMenuBackgroundColor.pas',
+  UMenuBackgroundTexture in 'menu\UMenuBackgroundTexture.pas',
+  UMenuBackgroundVideo   in 'menu\UMenuBackgroundVideo.pas',
+  UMenuBackgroundFade    in 'menu\UMenuBackgroundFade.pas',
+
+  //------------------------------
+  //Includes - base
+  //------------------------------
+  UConfig           in 'base\UConfig.pas',
+  
+  UCommon           in 'base\UCommon.pas',
+  UGraphic          in 'base\UGraphic.pas',
+  UTexture          in 'base\UTexture.pas',
+  ULanguage         in 'base\ULanguage.pas',
+  UMain             in 'base\UMain.pas',
+  UDraw             in 'base\UDraw.pas',
+  URecord           in 'base\URecord.pas',
+  UTime             in 'base\UTime.pas',
+  USong             in 'base\USong.pas',
+  UXMLSong          in 'base\UXMLSong.pas',
+  USongs            in 'base\USongs.pas',
+  UIni              in 'base\UIni.pas',
+  UImage            in 'base\UImage.pas',
+  ULyrics           in 'base\ULyrics.pas',
+  UEditorLyrics     in 'base\UEditorLyrics.pas',
+  USkins            in 'base\USkins.pas',
+  UThemes           in 'base\UThemes.pas',
+  ULog              in 'base\ULog.pas',
+  UJoystick         in 'base\UJoystick.pas',
+  UDataBase         in 'base\UDataBase.pas',
+  UCovers           in 'base\UCovers.pas',
+  UCatCovers        in 'base\UCatCovers.pas',
+  UFiles            in 'base\UFiles.pas',
+  UGraphicClasses   in 'base\UGraphicClasses.pas',
+  UPlaylist         in 'base\UPlaylist.pas',
+  UCommandLine      in 'base\UCommandLine.pas',
+  URingBuffer       in 'base\URingBuffer.pas',
+  USingScores       in 'base\USingScores.pas',
+  USingNotes        in 'base\USingNotes.pas',
+  UPathUtils        in 'base\UPathUtils.pas',
+  UNote             in 'base\UNote.pas',
+  UBeatTimer        in 'base\UBeatTimer.pas',
+
+  TextGL            in 'base\TextGL.pas',
+  UUnicodeUtils     in 'base\UUnicodeUtils.pas',
+  UFont             in 'base\UFont.pas',
+  UTextEncoding     in 'base\UTextEncoding.pas',
+
+  UPath             in 'base\UPath.pas',
+  UFilesystem       in 'base\UFilesystem.pas',
+
+  //------------------------------
+  //Includes - Plugin Support
+  //------------------------------
+  UParty            in 'base\UParty.pas',            // TODO: rewrite Party Manager as Module, reomplent ability to offer party Mody by Plugin
+
+  //------------------------------
+  //Includes - Platform
+  //------------------------------
+  
+  UPlatform         in 'base\UPlatform.pas',
+{$IF Defined(MSWINDOWS)}
+  UPlatformWindows  in 'base\UPlatformWindows.pas',
+{$ELSEIF Defined(DARWIN)}
+  UPlatformMacOSX   in 'base/UPlatformMacOSX.pas',
+{$ELSEIF Defined(UNIX)}
+  UPlatformLinux    in 'base\UPlatformLinux.pas',
+{$IFEND}
+
+  //------------------------------
+  //Includes - Media
+  //------------------------------
+
+  UMusic                    in 'base\UMusic.pas',
+  UAudioPlaybackBase        in 'media\UAudioPlaybackBase.pas',
+{$IF Defined(UsePortaudioPlayback) or Defined(UseSDLPlayback)}
+  UFFT                      in 'lib\fft\UFFT.pas',
+  UAudioPlayback_SoftMixer  in 'media\UAudioPlayback_SoftMixer.pas',
+{$IFEND}
+  UAudioConverter           in 'media\UAudioConverter.pas',
+
+  //******************************
+  //Pluggable media modules
+  // The modules are prioritized as in the include list below.
+  // This means the first entry has highest priority, the last lowest.
+  //******************************
+
+{$IFDEF UseFFmpegVideo}
+  UVideo                    in 'media\UVideo.pas',
+{$ENDIF}
+{$IFDEF UseProjectM}
+  // must be after UVideo, so it will not be the default video module
+  UVisualizer               in 'media\UVisualizer.pas',
+{$ENDIF}
+{$IFDEF UseBASSInput}
+  UAudioInput_Bass          in 'media\UAudioInput_Bass.pas',
+{$ENDIF}
+{$IFDEF UseBASSDecoder}
+  // prefer Bass to FFmpeg if possible
+  UAudioDecoder_Bass        in 'media\UAudioDecoder_Bass.pas',
+{$ENDIF}
+{$IFDEF UseBASSPlayback}
+  UAudioPlayback_Bass       in 'media\UAudioPlayback_Bass.pas',
+{$ENDIF}
+{$IFDEF UseSDLPlayback}
+  UAudioPlayback_SDL        in 'media\UAudioPlayback_SDL.pas',
+{$ENDIF}
+{$IFDEF UsePortaudioInput}
+  UAudioInput_Portaudio     in 'media\UAudioInput_Portaudio.pas',
+{$ENDIF}
+{$IFDEF UsePortaudioPlayback}
+  UAudioPlayback_Portaudio  in 'media\UAudioPlayback_Portaudio.pas',
+{$ENDIF}
+{$IFDEF UseFFmpegDecoder}
+  UAudioDecoder_FFmpeg      in 'media\UAudioDecoder_FFmpeg.pas',
+{$ENDIF}
+  // fallback dummy, must be last
+  UMedia_dummy              in 'media\UMedia_dummy.pas',
+
+
+  //------------------------------
+  //Includes - Screens
+  //------------------------------  
+  UScreenLoading          in 'screens\UScreenLoading.pas',
+  UScreenMain             in 'screens\UScreenMain.pas',
+  UScreenName             in 'screens\UScreenName.pas',
+  UScreenLevel            in 'screens\UScreenLevel.pas',
+  UScreenSong             in 'screens\UScreenSong.pas',
+  UScreenSing             in 'screens\UScreenSing.pas',
+  UScreenScore            in 'screens\UScreenScore.pas',
+  UScreenOptions          in 'screens\UScreenOptions.pas',
+  UScreenOptionsGame      in 'screens\UScreenOptionsGame.pas',
+  UScreenOptionsGraphics  in 'screens\UScreenOptionsGraphics.pas',
+  UScreenOptionsSound     in 'screens\UScreenOptionsSound.pas',
+  UScreenOptionsLyrics    in 'screens\UScreenOptionsLyrics.pas',
+  UScreenOptionsThemes    in 'screens\UScreenOptionsThemes.pas',
+  UScreenOptionsRecord    in 'screens\UScreenOptionsRecord.pas',
+  UScreenOptionsAdvanced  in 'screens\UScreenOptionsAdvanced.pas',
+  UScreenEditSub          in 'screens\UScreenEditSub.pas',
+  UScreenEdit             in 'screens\UScreenEdit.pas',
+  UScreenEditConvert      in 'screens\UScreenEditConvert.pas',
+  UScreenEditHeader       in 'screens\UScreenEditHeader.pas',
+  UScreenOpen             in 'screens\UScreenOpen.pas',
+  UScreenTop5             in 'screens\UScreenTop5.pas',
+  UScreenSongMenu         in 'screens\UScreenSongMenu.pas',
+  UScreenSongJumpto       in 'screens\UScreenSongJumpto.pas',
+  UScreenStatMain         in 'screens\UScreenStatMain.pas',
+  UScreenStatDetail       in 'screens\UScreenStatDetail.pas',
+  UScreenCredits          in 'screens\UScreenCredits.pas',
+  UScreenPopup            in 'screens\UScreenPopup.pas',
+
+  //Includes - Screens PartyMode
+  UScreenPartyNewRound    in 'screens\UScreenPartyNewRound.pas',
+  UScreenPartyScore       in 'screens\UScreenPartyScore.pas',
+  UScreenPartyPlayer      in 'screens\UScreenPartyPlayer.pas',
+  UScreenPartyOptions     in 'screens\UScreenPartyOptions.pas',
+  UScreenPartyRounds      in 'screens\UScreenPartyRounds.pas',
+  UScreenPartyWin         in 'screens\UScreenPartyWin.pas',
+
+  SysUtils;
+
+begin
+  Main;
+end.
+
diff --git a/songmanagement/test/TestPortAudioDevice.pas b/songmanagement/test/TestPortAudioDevice.pas
new file mode 100644
index 00000000..ba394383
--- /dev/null
+++ b/songmanagement/test/TestPortAudioDevice.pas
@@ -0,0 +1,528 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+program TestPortAudioDevice;
+
+{* TestPortAudioDevice does some basic tests of the portaudio libs.
+ * If all works, it lists all audio input and output devices and their
+ * characteristics. Compile and run with simple commands.
+ *}
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
+uses
+  SysUtils,
+  ctypes,
+  crt,
+  math,
+  PortAudio in '../src/lib/portaudio/portaudio.pas';
+
+const
+  paDefaultApi = -1;
+
+  ApiPreferenceOrder:
+{$IF Defined(MSWINDOWS)}
+    // Note1: Portmixer has no mixer support for paASIO and paWASAPI at the moment
+    // Note2: Windows Default-API is MME, but DirectSound is faster
+    array[0..0] of TPaHostApiTypeId = ( paDirectSound );
+{$ELSEIF Defined(DARWIN)}
+    array[0..0] of TPaHostApiTypeId = ( paDefaultApi ); // paCoreAudio
+{$ELSEIF Defined(UNIX)}
+    // Note: Portmixer has no mixer support for JACK at the moment
+    array[0..2] of TPaHostApiTypeId = ( paALSA, paJACK, paOSS );
+{$ELSE}
+    array[0..0] of TPaHostApiTypeId = ( paDefaultApi );
+{$IFEND}
+
+  standardSampleRates: array[1..13] of cdouble =
+    ( 8000.0,  9600.0,  11025.0,  12000.0,  16000.0,
+     22050.0, 24000.0,  32000.0,  44100.0,  48000.0,
+     88200.0, 96000.0, 192000.0
+    );
+
+  SampleFormat: array[1..8] of culong =
+    (paFloat32,      paInt32,          paInt24, paInt16, paInt8, paUInt8,
+     paCustomFormat, paNonInterleaved
+    );
+  SampleFormatName: array[1..8] of string =
+    ('paFloat32',      'paInt32',          'paInt24', 'paInt16', 'paInt8', 'paUInt8',
+     'paCustomFormat', 'paNonInterleaved'
+    );
+
+var
+  i, j:        integer;
+  PaError:     TPaError;
+  paApiIndex:  TPaHostApiIndex;
+  paApiInfo:   PPaHostApiInfo;
+  deviceIndex: TPaDeviceIndex;
+  deviceInfo:  PPaDeviceInfo;
+  inputParameters:  PPaStreamParameters;
+  outputParameters: PPaStreamParameters;
+  sampleRate:       cdouble;
+  stream:           PPaStream;
+  framesPerBuffer:  culong;
+  streamFlags:      TPaStreamFlags;
+  streamCallback:   PPaStreamCallback;
+  callbackStartTime: TDateTime;
+  callbackWorks:    boolean;
+  userData:         Pointer;
+
+
+function GetPreferredApiIndex(): TPaHostApiIndex;
+var
+  i:        integer;
+  apiIndex: TPaHostApiIndex;
+  apiInfo:  PPaHostApiInfo;
+begin
+  result := -1;
+
+  // select preferred sound-API
+  for i:= 0 to High(ApiPreferenceOrder) do
+  begin
+    if (ApiPreferenceOrder[i] <> paDefaultApi) then
+    begin
+      // check if API is available
+      apiIndex := Pa_HostApiTypeIdToHostApiIndex(ApiPreferenceOrder[i]);
+      if (apiIndex >= 0) then
+      begin
+        // we found an API but we must check if it works
+        // (on linux portaudio might detect OSS but does not provide
+        // any devices if ALSA is enabled)
+        apiInfo := Pa_GetHostApiInfo(apiIndex);
+        if (apiInfo^.deviceCount > 0) then
+        begin
+          Result := apiIndex;
+          break;
+        end;
+      end;
+    end;
+  end;
+
+  // None of the preferred APIs is available -> use default
+  if (result < 0) then
+  begin
+    result := Pa_GetDefaultHostApi();
+  end;
+end;
+
+{
+type
+  TAudioSampleFormat = (
+    asfU8, asfS8,         // unsigned/signed  8 bits
+    asfU16LSB, asfS16LSB, // unsigned/signed 16 bits (endianness: LSB)
+    asfU16MSB, asfS16MSB, // unsigned/signed 16 bits (endianness: MSB)
+    asfU16, asfS16,       // unsigned/signed 16 bits (endianness: System)
+    asfS32,               // signed 32 bits (endianness: System)
+    asfFloat,             // float
+    asfDouble             // double
+  );
+  TAudioFormatInfo = ;
+  TAudioInputDevice = record
+      AudioFormat:     TAudioFormatInfo; // capture format info (e.g. 44.1kHz SInt16 stereo)
+      CaptureChannel:  array of TCaptureBuffer; // sound-buffer references used for mono or stereo channel's capture data
+  end;
+
+procedure HandleMicrophoneData(Buffer: PByteArray; Size: integer; InputDevice: TAudioInputDevice);
+var
+  MultiChannelBuffer:      PByteArray;  // buffer handled as array of bytes (offset relative to channel)
+  SingleChannelBuffer:     PByteArray;  // temporary buffer for new samples per channel
+  SingleChannelBufferSize: integer;
+  ChannelIndex:            integer;
+  CaptureChannel:          TCaptureBuffer;
+  AudioFormat:             TAudioFormatInfo;
+  SampleSize:              integer;
+  SamplesPerChannel:       integer;
+  i:                       integer;
+begin
+  AudioFormat := InputDevice.AudioFormat;
+  SampleSize := AudioSampleSize[AudioFormat.Format];
+  SamplesPerChannel := Size div AudioFormat.FrameSize;
+
+  SingleChannelBufferSize := SamplesPerChannel * SampleSize;
+  GetMem(SingleChannelBuffer, SingleChannelBufferSize);
+
+  // process channels
+  for ChannelIndex := 0 to High(InputDevice.CaptureChannel) do
+  begin
+    CaptureChannel := InputDevice.CaptureChannel[ChannelIndex];
+    // check if a capture buffer was assigned, otherwise there is nothing to do
+    if (CaptureChannel <> nil) then
+    begin
+      // set offset according to channel index
+      MultiChannelBuffer := @Buffer[ChannelIndex * SampleSize];
+      // separate channel-data from interleaved multi-channel (e.g. stereo) data
+      for i := 0 to SamplesPerChannel-1 do
+      begin
+        Move(MultiChannelBuffer[i*AudioFormat.FrameSize],
+             SingleChannelBuffer[i*SampleSize],
+             SampleSize);
+      end;
+      CaptureChannel.ProcessNewBuffer(SingleChannelBuffer, SingleChannelBufferSize);
+    end;
+  end;
+
+  FreeMem(SingleChannelBuffer);
+end;
+}
+
+procedure TestInitTerminate();
+begin
+  writeln ('*** Test of Pa_Initialize and Pa_Terminate ***');
+  PaError := Pa_Initialize;
+  if PaError = paNoError then
+    writeln ('Pa_Initialize: No error')
+  else
+    writeln ('Pa_Initialize: Error No ', PaError);
+
+  PaError := Pa_Terminate; 
+  if PaError = paNoError then
+    writeln ('Pa_Terminate:  No error')
+  else
+    writeln ('Pa_Terminate:  Error No: ', PaError);
+  writeln;
+end;
+
+procedure TestErrorText();
+begin
+  writeln ('*** Test of Pa_GetErrorText ***');
+  PaError := Pa_Initialize;
+  writeln ('paNoError (0): ', Pa_GetErrorText(PaError));
+  writeln;
+  writeln ('Code   Text');
+  writeln ('------------------------------------');
+  i := paNotInitialized;
+  repeat
+    writeln (i:6, ' ', Pa_GetErrorText(i));
+    i := succ(i);
+  until SameText(Pa_GetErrorText(i), 'Invalid error code') or (i = paNotInitialized + 100);
+  writeln (i:6, ' ', Pa_GetErrorText(i));
+  PaError := Pa_Terminate; 
+  writeln;
+end;
+
+procedure TestVersion();
+begin
+  writeln ('*** Test of Pa_GetVersion and Pa_GetVersionText ***');
+  PaError := Pa_Initialize;
+  writeln ('Pa_GetVersion:     ', Pa_GetVersion);
+  writeln ('Pa_GetVersionText: ', Pa_GetVersionText);
+  PaError := Pa_Terminate; 
+  writeln;
+end;
+
+procedure TestApiInfo();
+begin
+  writeln ('*** Test of GetPreferredApiIndex ***');
+  PaError    := Pa_Initialize;
+  paApiIndex := GetPreferredApiIndex();
+  if (paApiIndex = -1) then
+    writeln ('GetPreferredApiIndex: No working Audio-API found.')
+  else
+    writeln ('GetPreferredApiIndex: working Audio-API found. No: ', paApiIndex);
+  PaError := Pa_Terminate; 
+  writeln;
+
+  writeln ('*** Test of Pa_GetHostApiInfo ***');
+  PaError    := Pa_Initialize;
+  paApiIndex := GetPreferredApiIndex();
+  paApiInfo  := Pa_GetHostApiInfo(paApiIndex);
+  writeln ('Pa_GetHostApiInfo:');
+  writeln ('paApiInfo.structVersion:       ', paApiInfo.structVersion);
+  writeln ('paApiInfo._type:               ', paApiInfo._type);
+  writeln ('paApiInfo.name:                ', paApiInfo.name);
+  writeln ('paApiInfo.deviceCount:         ', paApiInfo.deviceCount);
+  writeln ('paApiInfo.defaultInputDevice:  ', paApiInfo.defaultInputDevice);
+  writeln ('paApiInfo.defaultOutputDevice: ', paApiInfo.defaultOutputDevice);
+  PaError := Pa_Terminate; 
+  writeln;
+
+  writeln ('*** Test of Pa_HostApiDeviceIndexToDeviceIndex ***');
+  PaError    := Pa_Initialize;
+  paApiIndex := GetPreferredApiIndex();
+  paApiInfo  := Pa_GetHostApiInfo(paApiIndex);
+  for i:= 0 to paApiInfo^.deviceCount-1 do
+  begin
+    deviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(paApiIndex, i);
+    writeln ('deviceIndex[', i, ']: ', deviceIndex);
+  end;
+  PaError := Pa_Terminate; 
+  writeln;
+end;
+
+procedure TestDeviceInfo();
+begin
+  writeln ('*** Test of Pa_GetDeviceCount ***');
+  PaError := Pa_Initialize;
+  writeln ('Pa_GetDeviceCount: ', Pa_GetDeviceCount);
+  PaError := Pa_Terminate; 
+  writeln;
+
+  writeln ('*** Test of Pa_GetDefaultInputDevice ***');
+  PaError := Pa_Initialize;
+  writeln ('Pa_GetDefaultInputDevice: ', Pa_GetDefaultInputDevice);
+  PaError := Pa_Terminate; 
+  writeln;
+
+  writeln ('*** Test of Pa_GetDefaultOutputDevice ***');
+  PaError := Pa_Initialize;
+  writeln ('Pa_GetDefaultOutputDevice: ', Pa_GetDefaultOutputDevice);
+  PaError := Pa_Terminate; 
+  writeln;
+
+  writeln ('*** Test of Pa_GetDeviceInfo ***');
+// Note: the fields of deviceInfo can also be used without the '^'.
+// deviceInfo.name works as well as deviceInfo^.name
+  PaError    := Pa_Initialize;
+  paApiIndex := GetPreferredApiIndex();
+  paApiInfo  := Pa_GetHostApiInfo(paApiIndex);
+  for i:= 0 to paApiInfo^.deviceCount - 1 do
+  begin
+    deviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(paApiIndex, i);
+    deviceInfo  := Pa_GetDeviceInfo(deviceIndex);
+    writeln ('deviceInfo[', i, '].name:                     ', deviceInfo^.name);
+    writeln ('deviceInfo[', i, '].structVersion:            ', deviceInfo^.structVersion, ' (should be 2)');
+    writeln ('deviceInfo[', i, '].hostApi:                  ', deviceInfo^.hostApi);
+    writeln ('deviceInfo[', i, '].maxInputChannels:         ', deviceInfo^.maxInputChannels);
+    writeln ('deviceInfo[', i, '].maxOutputChannels:        ', deviceInfo^.maxOutputChannels);
+    writeln ('deviceInfo[', i, '].defaultLowInputLatency:   ', deviceInfo^.defaultLowInputLatency:6:4);
+    writeln ('deviceInfo[', i, '].defaultLowOutputLatency:  ', deviceInfo^.defaultLowOutputLatency:6:4);
+    writeln ('deviceInfo[', i, '].defaultHighInputLatency:  ', deviceInfo^.defaultHighInputLatency:6:4);
+    writeln ('deviceInfo[', i, '].defaultHighOutputLatency: ', deviceInfo^.defaultHighOutputLatency:6:4);
+    writeln ('deviceInfo[', i, '].defaultSampleRate:        ', deviceInfo^.defaultSampleRate:5:0);
+    writeln;
+  end;
+  PaError := Pa_Terminate; 
+end;
+
+procedure TestFormatInfo();
+begin
+  writeln ('*** Test of Pa_IsFormatSupported ***');
+  PaError    := Pa_Initialize;
+  paApiIndex := GetPreferredApiIndex();
+  paApiInfo  := Pa_GetHostApiInfo(paApiIndex);
+  for i:= 0 to paApiInfo^.deviceCount - 1 do
+  begin
+    deviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(paApiIndex, i);
+    deviceInfo  := Pa_GetDeviceInfo(deviceIndex);
+    writeln ('Device[', i, '] ', deviceInfo^.name, ':');
+    New(inputParameters);
+    New(outputParameters);
+
+    if deviceInfo^.maxInputChannels > 0 then
+    begin
+      inputParameters^.device                    := deviceIndex;
+      inputParameters^.channelCount              := deviceInfo^.maxInputChannels;
+      inputParameters^.sampleFormat              := paInt16;
+      inputParameters^.suggestedLatency          := 0;
+      inputParameters^.hostApiSpecificStreamInfo := nil;
+      outputParameters := nil;
+    end
+    else
+    begin
+      inputParameters := nil;
+      outputParameters^.device                    := deviceIndex;
+      outputParameters^.channelCount              := deviceInfo^.maxOutputChannels;
+      outputParameters^.sampleFormat              := paInt16;
+      outputParameters^.suggestedLatency          := 0;
+      outputParameters^.hostApiSpecificStreamInfo := nil;
+    end;
+
+    sampleRate := deviceInfo^.defaultSampleRate;
+    PaError    := Pa_IsFormatSupported(inputParameters, outputParameters, sampleRate);
+    if PaError = paFormatIsSupported then
+      writeln ('Sample rate: ', sampleRate:5:0, ' : supported')
+    else
+      writeln ('Sample rate: ', sampleRate:5:0, ' : Error: ', Pa_GetErrorText(PaError));
+
+    for j := low(standardSampleRates) to high(standardSampleRates) do
+    begin 
+      sampleRate := standardSampleRates[j];
+      PaError    := Pa_IsFormatSupported(inputParameters, outputParameters, sampleRate);
+      if PaError = paFormatIsSupported then
+	writeln ('Sample rate: ', sampleRate:5:0, ' : supported')
+      else
+	writeln ('Sample rate: ', sampleRate:5:0, ' : Error: ', PaError);
+    end;
+
+    writeln;
+    for j := low(SampleFormat) to high(SampleFormat) do
+    begin 
+      if inputParameters <> nil then
+        inputParameters^.sampleFormat := SampleFormat[j]
+      else
+	outputParameters^.sampleFormat := SampleFormat[j];
+      PaError := Pa_IsFormatSupported(inputParameters, outputParameters, sampleRate);
+      if PaError = paFormatIsSupported then
+        writeln ('Sample Format ', SampleFormatName[j], ': supported')
+      else
+        writeln ('Sample Format ', SampleFormatName[j], ': ', Pa_GetErrorText(PaError));
+    end;
+
+    Dispose(inputParameters);
+    Dispose(outputParameters);
+    writeln;
+  end;
+  PaError := Pa_Terminate; 
+end;
+
+function AudioCallback(input: pointer; output: pointer; frameCount: culong;
+      timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
+      inputDevice: pointer): cint; cdecl;
+var
+  duration: real;
+begin
+  duration := (Now() - callbackStartTime) * 24 * 3600;
+  if (duration < 2.0) then
+    result := paContinue
+  else
+  begin
+    callbackWorks := true;
+    result := paComplete;
+  end;
+end;
+
+procedure TestStreams();
+begin
+  writeln ('*** Test of Pa_OpenStream and Pa_CloseStream ***');
+  PaError    := Pa_Initialize;
+  paApiIndex := GetPreferredApiIndex();
+  paApiInfo  := Pa_GetHostApiInfo(paApiIndex);
+  for i:= 0 to paApiInfo^.deviceCount - 1 do
+  begin
+    deviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(paApiIndex, i);
+    deviceInfo  := Pa_GetDeviceInfo(deviceIndex);
+    writeln ('Device[', i, '] ', deviceInfo^.name, ':');
+    New(inputParameters);
+    New(outputParameters);
+    if deviceInfo^.maxInputChannels > 0 then
+    begin
+      inputParameters^.device                    := deviceIndex;
+      inputParameters^.channelCount              := deviceInfo^.maxInputChannels;
+      inputParameters^.sampleFormat              := paInt16;
+      inputParameters^.suggestedLatency          := deviceInfo.defaultHighInputLatency;
+      inputParameters^.hostApiSpecificStreamInfo := nil;
+      outputParameters := nil;
+    end
+    else
+    begin
+      inputParameters := nil;
+      outputParameters^.device                    := deviceIndex;
+      outputParameters^.channelCount              := deviceInfo^.maxOutputChannels;
+      outputParameters^.sampleFormat              := paInt16;
+      outputParameters^.suggestedLatency          := deviceInfo.defaultLowOutputLatency;
+      outputParameters^.hostApiSpecificStreamInfo := nil;
+    end;
+      
+    sampleRate      := deviceInfo^.defaultSampleRate;
+    framesPerBuffer := paFramesPerBufferUnspecified;
+    streamFlags     := paNoFlag;
+    streamCallback  := @AudioCallback;
+    userData        := nil;
+
+    PaError := Pa_OpenStream(
+                     stream,
+                     inputParameters,
+                     outputParameters,
+		     sampleRate,
+                     framesPerBuffer,
+                     streamFlags,
+                     streamCallback,
+                     userData 
+		     );
+    if (PaError = paNoError) and (stream <> nil) then
+      writeln ('Pa_OpenStream: success')
+    else
+      writeln ('Pa_OpenStream: ', Pa_GetErrorText(PaError));
+
+    if (PaError = paNoError) and (stream <> nil) then
+    begin
+      callbackStartTime := Now();
+
+      PaError := Pa_StartStream(stream);
+      if (PaError = paNoError) then
+	writeln ('Pa_StartStream: success')
+      else
+	writeln ('Pa_StartStream: ', Pa_GetErrorText(PaError));
+
+      callbackWorks := false;
+
+      // wait twice the time a successful callback would need for termination
+      writeln('Wait for callback');
+      delay(4000);
+
+      if (callbackWorks and (Pa_IsStreamStopped(stream) = 0)) then
+      begin
+	writeln ('Success: Device works');
+	PaError := Pa_StopStream(stream);
+	if (PaError = paNoError) then
+	  writeln ('Pa_StopStream: success')
+	else
+	  writeln ('Pa_StopStream: ', Pa_GetErrorText(PaError));
+      end
+      else
+      begin
+	writeln ('Error: Non working device');
+        PaError := Pa_AbortStream(stream);
+        if (PaError = paNoError) then
+          writeln ('Pa_AbortStream: success')
+        else
+          writeln ('Pa_AbortStream: ', Pa_GetErrorText(PaError));
+
+      end;
+    end;
+
+    PaError := Pa_CloseStream(stream);
+    if PaError = paNoError then
+      writeln ('Pa_CloseStream: success')
+    else
+      writeln ('Pa_CloseStream: ', Pa_GetErrorText(PaError));
+
+    Dispose(inputParameters);
+    Dispose(outputParameters);
+    
+    writeln;    
+  end;
+  PaError := Pa_Terminate; 
+end;
+
+begin
+  // floating point exceptions are raised. Therefore, set the exception mask.
+  SetExceptionMask([exZeroDivide, exPrecision]);
+
+  writeln ('Start: Test of Portaudio libs');
+  writeln;
+
+  //TestInitTerminate();
+  //TestErrorText(); 
+  //TestVersion();
+  //TestApiInfo();
+  //TestDeviceInfo();
+  //TestFormatInfo();
+  TestStreams();
+  
+  writeln ('End: Test of Portaudio libs');
+end.
\ No newline at end of file
diff --git a/songmanagement/test/TestSignAlgorithm.pas b/songmanagement/test/TestSignAlgorithm.pas
new file mode 100644
index 00000000..915e5681
--- /dev/null
+++ b/songmanagement/test/TestSignAlgorithm.pas
@@ -0,0 +1,58 @@
+program TestSignAlgorithm;
+
+uses
+  sysutils;
+
+const
+  a1 = 2;
+  a2 = 1;
+  a3 = 0;
+  a4 = -1;
+  a5 = -2;
+
+var
+  index, number: longint;
+
+begin
+  writeln;
+  writeln ('This tests the arithmetic procedure used in libavutil and libavcodec.');
+  writeln ('positive numbers should give 1, negative numbers -1.');
+  writeln ('-17: ', not((-17 shr 30) and $00000002) + 2);
+  writeln ('-16: ', not((-16 shr 30) and $00000002) + 2);
+  writeln ('-15: ', not((-15 shr 30) and $00000002) + 2);
+  writeln (' -3: ', not(( -3 shr 30) and $00000002) + 2);
+  writeln (' -2: ', not(( -2 shr 30) and $00000002) + 2);
+  writeln (' -1: ', not(( -1 shr 30) and $00000002) + 2);
+  writeln ('  0: ', not((  0 shr 30) and $00000002) + 2);
+  writeln ('  1: ', not((  1 shr 30) and $00000002) + 2);
+  writeln ('  2: ', not((  2 shr 30) and $00000002) + 2);
+  writeln ('  3: ', not((  3 shr 30) and $00000002) + 2);
+  writeln ('  8: ', not((  8 shr 30) and $00000002) + 2);
+  writeln ('MaxInt:     ', MaxInt:12, ' ', IntToHex(MaxInt,8), ' ', not((MaxInt shr 30) and $00000002) + 2);
+  writeln ('MaxLongint: ', MaxLongint:12, ' ', IntToHex(MaxLongint,8), ' ', not((MaxLongint shr 30) and $00000002) + 2);
+  writeln ('MinInt:     ', -MaxInt - 1:12, ' ', IntToHex(-MaxInt - 1,8), ' ', not(((-MaxInt - 1) shr 30) and $00000002) + 2);
+  writeln ('MinLongInt: ', -MaxLongint - 1:12, ' ', IntToHex(-MaxLongint - 1,8), ' ', not(((-MaxLongint - 1) shr 30) and $00000002) + 2);
+  writeln (a1, ' ', IntToHex(a1,8) , ' ', not((a1 shr 30) and $00000002) + 2);
+  writeln (a2, ' ', IntToHex(a2,8) , ' ', not((a2 shr 30) and $00000002) + 2);
+  writeln (a3, ' ', IntToHex(a3,8) , ' ', not((a3 shr 30) and $00000002) + 2);
+  writeln (a4, ' ', IntToHex(a4,8) , ' ', not((a4 shr 30) and $00000002) + 2);
+  writeln (a5, ' ', IntToHex(a5,8) , ' ', not((a5 shr 30) and $00000002) + 2);
+  writeln;
+  writeln ('Hit RETURN for more positive numbers. The last one overflows and becomes negative.');
+  readln;
+  number := 1;
+  for index := 1 to 32 do
+  begin
+    writeln (index:2, ': ', number:11, ' ', IntToHex(number shr 30 ,8):10, ' ', not((number shr 30) and $00000002) + 2);
+    number := number * 2;
+  end;
+  writeln;
+  writeln ('Hit RETURN for more positive numbers.');
+  readln;
+  number := -1;
+  for index := 1 to 32 do
+  begin
+    writeln (index:2, ': ', number:11, ' ', IntToHex(number shr 30 ,8):10, ' ', not((number shr 30) and $00000002) + 2);
+    number := number * 2;
+  end;
+end.
\ No newline at end of file
diff --git a/songmanagement/test/switches.inc b/songmanagement/test/switches.inc
new file mode 100644
index 00000000..e69de29b
diff --git a/songmanagement/test/test001.pas b/songmanagement/test/test001.pas
new file mode 100644
index 00000000..c9ba266f
--- /dev/null
+++ b/songmanagement/test/test001.pas
@@ -0,0 +1,86 @@
+program test001;
+
+{
+This program tests the function glext_ExtensionSupported from unit glext.
+}
+
+uses
+  SysUtils,
+  SDL          in '../src/lib/JEDI-SDL/SDL/Pas/sdl.pas',
+  moduleloader in '../src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas',
+  gl           in '../src/lib/JEDI-SDL/OpenGL/Pas/gl.pas',
+  glext        in '../src/lib/JEDI-SDL/OpenGL/Pas/glext.pas';
+
+const
+  s1:  pchar = '';
+  s2:  pchar = 'ext';
+  s3:  pchar = ' ext';
+  s4:  pchar = ' ext ';
+  s5:  pchar = 'kkshf kjsfh ext';
+  s6:  pchar = 'fakh sajhf ext jskdhf';
+  s7:  pchar = 'ext jshf';
+  s8:  pchar = 'sdkjfh ksjhext sjdha';
+  s9:  pchar = 'sdkjfh ksjh extsjdha';
+  s10: pchar = 'sdkjfh ksjhextsjdha';
+  s11: pchar = 'sd kjf jdha';
+
+  e1: pchar = '';
+  e2: pchar = 'ext';
+  e3: pchar = 'GL_ARB_window_pos';
+
+  SCREEN_WIDTH  = 640;
+  SCREEN_HEIGHT = 480;
+  SCREEN_BPP    =  16;
+
+var
+  surface:    PSDL_Surface;
+  videoFlags: integer;
+  testFailed: boolean;
+  
+procedure treatTestFailure(testNumber: integer, var testFailed: boolean);
+begin
+  writeln;
+  write ('test001, ', testNumber, ': failed');
+  testFailed := true;
+end;
+
+begin
+  write ('test001: Start ... ');
+  testFailed := false;
+
+// initialize SDL and OpenGL for the use of glGetString(GL_EXTENSIONS)
+// within glext_ExtensionSupported.
+
+  SDL_Init( SDL_INIT_VIDEO);
+
+// the flags to pass to SDL_SetVideoMode
+  videoFlags := SDL_OPENGL;
+
+// get a SDL surface
+  surface := SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags);
+
+// Initialization finished
+
+  if     glext_ExtensionSupported(e1, s1)  then treatTestFailure( 1, testFailed);
+  if     glext_ExtensionSupported(e1, s2)  then treatTestFailure( 2, testFailed);
+  if     glext_ExtensionSupported(e2, s1)  then treatTestFailure( 3, testFailed);
+  if not glext_ExtensionSupported(e2, s2)  then treatTestFailure( 4, testFailed);
+  if not glext_ExtensionSupported(e2, s3)  then treatTestFailure( 5, testFailed);
+  if not glext_ExtensionSupported(e2, s4)  then treatTestFailure( 6, testFailed);
+  if not glext_ExtensionSupported(e2, s5)  then treatTestFailure( 7, testFailed);
+  if not glext_ExtensionSupported(e2, s6)  then treatTestFailure( 8, testFailed);
+  if not glext_ExtensionSupported(e2, s7)  then treatTestFailure( 9, testFailed);
+  if     glext_ExtensionSupported(e2, s8)  then treatTestFailure(10, testFailed);
+  if     glext_ExtensionSupported(e2, s9)  then treatTestFailure(11, testFailed);
+  if     glext_ExtensionSupported(e2, s10) then treatTestFailure(12, testFailed);
+  if     glext_ExtensionSupported(e2, s11) then treatTestFailure(13, testFailed);
+  if not glext_ExtensionSupported(e3, s1)  then treatTestFailure(14, testFailed);
+
+  if testFailed then
+  begin
+    writeln;
+    writeln ('test001: End');
+  end
+  else
+    writeln ('End');
+end.
\ No newline at end of file
diff --git a/songmanagement/test/test_libraries.lpi b/songmanagement/test/test_libraries.lpi
new file mode 100644
index 00000000..cc3a6ddf
--- /dev/null
+++ b/songmanagement/test/test_libraries.lpi
@@ -0,0 +1,299 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="/"/>
+    <Version Value="6"/>
+    <General>
+      <MainUnit Value="0"/>
+      <TargetFileExt Value=""/>
+      <ActiveEditorIndexAtStart Value="0"/>
+    </General>
+    <VersionInfo>
+      <ProjectVersion Value=""/>
+      <Language Value=""/>
+      <CharSet Value=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="FPCUnitConsoleRunner"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="test_libraries.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="Test_Libraries"/>
+        <CursorPos X="77" Y="17"/>
+        <TopLine Value="1"/>
+        <EditorIndex Value="1"/>
+        <UsageCount Value="20"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="testsqllite.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="TestSQLLite"/>
+        <CursorPos X="23" Y="57"/>
+        <TopLine Value="39"/>
+        <EditorIndex Value="0"/>
+        <UsageCount Value="20"/>
+        <Loaded Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="../lib/SQLite/SQLiteTable3.pas"/>
+        <UnitName Value="SQLiteTable3"/>
+        <CursorPos X="37" Y="29"/>
+        <TopLine Value="11"/>
+        <EditorIndex Value="2"/>
+        <UsageCount Value="10"/>
+        <Loaded Value="True"/>
+      </Unit2>
+    </Units>
+    <JumpHistory Count="11" HistoryIndex="10">
+      <Position1>
+        <Filename Value="testsqllite.pas"/>
+        <Caret Line="8" Column="68" TopLine="1"/>
+      </Position1>
+      <Position2>
+        <Filename Value="../lib/SQLite/SQLiteTable3.pas"/>
+        <Caret Line="1" Column="1" TopLine="1"/>
+      </Position2>
+      <Position3>
+        <Filename Value="../lib/SQLite/SQLiteTable3.pas"/>
+        <Caret Line="37" Column="64" TopLine="14"/>
+      </Position3>
+      <Position4>
+        <Filename Value="testsqllite.pas"/>
+        <Caret Line="26" Column="34" TopLine="1"/>
+      </Position4>
+      <Position5>
+        <Filename Value="testsqllite.pas"/>
+        <Caret Line="13" Column="10" TopLine="1"/>
+      </Position5>
+      <Position6>
+        <Filename Value="testsqllite.pas"/>
+        <Caret Line="20" Column="29" TopLine="4"/>
+      </Position6>
+      <Position7>
+        <Filename Value="testsqllite.pas"/>
+        <Caret Line="28" Column="22" TopLine="5"/>
+      </Position7>
+      <Position8>
+        <Filename Value="testsqllite.pas"/>
+        <Caret Line="33" Column="42" TopLine="5"/>
+      </Position8>
+      <Position9>
+        <Filename Value="testsqllite.pas"/>
+        <Caret Line="21" Column="15" TopLine="5"/>
+      </Position9>
+      <Position10>
+        <Filename Value="testsqllite.pas"/>
+        <Caret Line="20" Column="38" TopLine="5"/>
+      </Position10>
+      <Position11>
+        <Filename Value="testsqllite.pas"/>
+        <Caret Line="61" Column="47" TopLine="39"/>
+      </Position11>
+    </JumpHistory>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="5"/>
+    <CodeGeneration>
+      <Generate Value="Faster"/>
+    </CodeGeneration>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <BreakPoints Count="37">
+      <Item1>
+        <Source Value="../../../../../project_mutliloader/fmmultiloaderform.pas"/>
+        <Line Value="370"/>
+      </Item1>
+      <Item2>
+        <Source Value="../../../../../project_mutliloader/uploader_infomine.pas"/>
+        <Line Value="1"/>
+      </Item2>
+      <Item3>
+        <Source Value="../../../../../project_mutliloader/uploader_seek_publicweb.pas"/>
+        <Line Value="515"/>
+      </Item3>
+      <Item4>
+        <Source Value="../../../../../project_mutliloader/fmmultiloaderform.pas"/>
+        <Line Value="803"/>
+      </Item4>
+      <Item5>
+        <Source Value="../../../../../project_mutliloader/fmmultiloaderform.pas"/>
+        <Line Value="822"/>
+      </Item5>
+      <Item6>
+        <Source Value="../../../../../project_mutliloader/fmmultiloaderform.pas"/>
+        <Line Value="824"/>
+      </Item6>
+      <Item7>
+        <Source Value="../../../../../project_mutliloader/fmmultiloaderform.pas"/>
+        <Line Value="1492"/>
+      </Item7>
+      <Item8>
+        <Source Value="../../../../../project_mutliloader/fmmultiloaderform.pas"/>
+        <Line Value="1536"/>
+      </Item8>
+      <Item9>
+        <Source Value="../../../../../Common/aSpell/spellcheck_controlls.pas"/>
+        <Line Value="425"/>
+      </Item9>
+      <Item10>
+        <Source Value="../../../../../Common/aSpell/spellcheck_controlls.pas"/>
+        <Line Value="455"/>
+      </Item10>
+      <Item11>
+        <Source Value="../../../../../Common/aSpell/spellcheck_controlls.pas"/>
+        <Line Value="574"/>
+      </Item11>
+      <Item12>
+        <Source Value="../../../../../Common/aSpell/spellcheck_controlls.pas"/>
+        <Line Value="602"/>
+      </Item12>
+      <Item13>
+        <Source Value="../../../../../project_mutliloader/fmmultiloaderform.pas"/>
+        <Line Value="1621"/>
+      </Item13>
+      <Item15>
+        <Source Value="../../../../../project_SkyeDB/fmclient.pas"/>
+        <Line Value="986"/>
+      </Item15>
+      <Item16>
+        <Source Value="../../../../../project_SkyeDB/fmclient.pas"/>
+        <Line Value="2065"/>
+      </Item16>
+      <Item17>
+        <Source Value="../../../../../project_SkyeDB/fmclient.pas"/>
+        <Line Value="1541"/>
+      </Item17>
+      <Item18>
+        <Source Value="../../../../../project_SkyeDB/fmcandidate.pas"/>
+        <Line Value="741"/>
+      </Item18>
+      <Item19>
+        <Source Value="../../../../../project_SkyeDB/fmcandidate.pas"/>
+        <Line Value="1633"/>
+      </Item19>
+      <Item20>
+        <Source Value="../../../../../project_SkyeDB/fmclient.pas"/>
+        <Line Value="3554"/>
+      </Item20>
+      <Item21>
+        <Source Value="../../../../../project_SkyeDB/fmcandidate.pas"/>
+        <Line Value="5037"/>
+      </Item21>
+      <Item22>
+        <Source Value="../../../../../project_SkyeDB/fmcandidate.pas"/>
+        <Line Value="2994"/>
+      </Item22>
+      <Item23>
+        <Source Value="../../../../../common/asterisk/comManagerMessage.pas"/>
+        <Line Value="564"/>
+      </Item23>
+      <Item24>
+        <Source Value="../../../../../common/asterisk/comManagerMessage.pas"/>
+        <Line Value="549"/>
+      </Item24>
+      <Item25>
+        <Source Value="../../../../../common/asterisk/comManagerMessage.pas"/>
+        <Line Value="438"/>
+      </Item25>
+      <Item26>
+        <Source Value="../../../../../common/asterisk/comManagerMessage.pas"/>
+        <Line Value="436"/>
+      </Item26>
+      <Item27>
+        <Source Value="../../../../../project_SkyeDB/fmcandidate.pas"/>
+        <Line Value="5648"/>
+      </Item27>
+      <Item28>
+        <Source Value="../../../../../project_SkyeDB/fmcandidate.pas"/>
+        <Line Value="636"/>
+      </Item28>
+      <Item29>
+        <Source Value="../../../../../common/common/ConvertUnicode.pas"/>
+        <Line Value="83"/>
+      </Item29>
+      <Item30>
+        <Source Value="/usr/share/lazarus/components/uniqueinstance/uniqueinstance.pas"/>
+        <Line Value="124"/>
+      </Item30>
+      <Item31>
+        <Source Value="/usr/share/lazarus/components/uniqueinstance/uniqueinstance.pas"/>
+        <Line Value="112"/>
+      </Item31>
+      <Item32>
+        <Source Value="/usr/share/lazarus/components/uniqueinstance/uniqueinstance.pas"/>
+        <Line Value="174"/>
+      </Item32>
+      <Item33>
+        <Source Value="/usr/share/lazarus/components/uniqueinstance/uniqueinstance.pas"/>
+        <Line Value="199"/>
+      </Item33>
+      <Item34>
+        <Source Value="../../../../../common/asterisk/comManagerMessage.pas"/>
+        <Line Value="800"/>
+      </Item34>
+      <Item35>
+        <Source Value="../../../../../common/asterisk/comManagerMessage.pas"/>
+        <Line Value="798"/>
+      </Item35>
+      <Item36>
+        <Source Value="../../../../../common/asterisk/comManagerMessage.pas"/>
+        <Line Value="778"/>
+      </Item36>
+      <Item37>
+        <Source Value="../../../../../common/asterisk/comManagerMessage.pas"/>
+        <Line Value="522"/>
+      </Item37>
+    </BreakPoints>
+    <Watches Count="6">
+      <Item1>
+        <Expression Value="edSearchSummry.text"/>
+      </Item1>
+      <Item2>
+        <Expression Value=" trim(edSearhSummary.text) "/>
+      </Item2>
+      <Item3>
+        <Expression Value="lData"/>
+      </Item3>
+      <Item4>
+        <Expression Value="ord(a)"/>
+      </Item4>
+      <Item5>
+        <Expression Value="lHTTP.headers.text"/>
+      </Item5>
+      <Item6>
+        <Expression Value="lSummaryContactName"/>
+      </Item6>
+    </Watches>
+    <Exceptions Count="2">
+      <Item1>
+        <Name Value="ECodetoolError"/>
+      </Item1>
+      <Item2>
+        <Name Value="EFOpenError"/>
+      </Item2>
+    </Exceptions>
+  </Debugging>
+</CONFIG>
diff --git a/songmanagement/test/test_libraries.lpr b/songmanagement/test/test_libraries.lpr
new file mode 100644
index 00000000..3e3ae380
--- /dev/null
+++ b/songmanagement/test/test_libraries.lpr
@@ -0,0 +1,31 @@
+program Test_Libraries;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes,
+  consoletestrunner,
+  TestSQLLite,
+  SQLite3 in '../lib/SQLite/SQLite3.pas',
+
+  SQLiteTable3 in '../lib/SQLite/SQLiteTable3.pas';
+
+type
+
+  { TLazTestRunner }
+
+  TMyTestRunner = class(TTestRunner)
+  protected
+  // override the protected methods of TTestRunner to customize its behavior
+  end;
+
+var
+  Application: TMyTestRunner;
+
+begin
+  Application := TMyTestRunner.Create(nil);
+  Application.Initialize;
+  Application.Title := 'FPCUnit Console test runner';
+  Application.Run;
+  Application.Free;
+end.
diff --git a/songmanagement/test/testsqllite.pas b/songmanagement/test/testsqllite.pas
new file mode 100644
index 00000000..b1b682d2
--- /dev/null
+++ b/songmanagement/test/testsqllite.pas
@@ -0,0 +1,84 @@
+unit TestSQLLite;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry, SQLiteTable3, unix;
+
+type
+
+  TTest_SqlLite= class(TTestCase)
+  private
+    fSQLLite  : TSQLiteDatabase;
+    fFileName : string;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override; 
+  published
+    procedure Test_Random_TableExists;
+    procedure Test_Delete_NonExistant_Table;
+    procedure Test_TableExists_On_0Length_File;
+  end; 
+
+implementation
+
+procedure TTest_SqlLite.Test_Random_TableExists;
+begin
+  deletefile( fFileName );
+  fSQLLite  := TSQLiteDatabase.Create( fFileName );
+
+  // Test if some random table exists
+  check( not fSQLLite.TableExists( 'testTable'+floattostr(now()) ) , 'Randomly Named Table Should NOT Exists (In an empty database file)' );
+end; 
+
+procedure TTest_SqlLite.Test_Delete_NonExistant_Table;
+var
+  lSQL : String;
+begin
+  deletefile( fFileName );
+  fSQLLite  := TSQLiteDatabase.Create( fFileName );
+  try
+    lSQL := 'DROP TABLE testtable';
+    fSQLLite.execsql( lSQL );
+  except
+    exit;
+  end;
+
+  Fail('SQLLite did not except when trying to delete a non existant table' );
+end;
+
+procedure TTest_SqlLite.Test_TableExists_On_0Length_File;
+var
+  lSQL : String;
+begin
+  deletefile( fFileName );
+  shell('cat /dev/null > '+fFileName);
+  
+  if not fileexists( fFileName ) then
+    Fail('0 Length file was not created... oops' );
+    
+  fSQLLite  := TSQLiteDatabase.Create( fFileName );
+
+  check( not fSQLLite.TableExists( 'testTable' ) , 'Randomly Named Table Should NOT Exists' );
+end;
+
+
+procedure TTest_SqlLite.SetUp; 
+begin
+  fFileName := 'test.db';
+//  fSQLLite  := TSQLiteDatabase.Create( fFileName );
+end; 
+
+
+procedure TTest_SqlLite.TearDown; 
+begin
+  freeandnil( fSQLLite );
+end; 
+
+initialization
+
+  RegisterTest(TTest_SqlLite); 
+end.
+
diff --git a/songmanagement/tools/ScoreConverter/ScoreConverter.dpr b/songmanagement/tools/ScoreConverter/ScoreConverter.dpr
new file mode 100644
index 00000000..2774cde4
--- /dev/null
+++ b/songmanagement/tools/ScoreConverter/ScoreConverter.dpr
@@ -0,0 +1,17 @@
+program ScoreConverter;
+
+uses
+  Forms,
+  Umainform in 'Umainform.pas' {mainform},
+  UScores in 'UScores.pas',
+  UDataBase in '..\Game\Code\Classes\UDataBase.pas',
+  USongs in 'USongs.pas';
+
+{$R *.res}
+
+begin
+  Application.Initialize;
+  Application.Title := 'Score Converter';
+  Application.CreateForm(Tmainform, mainform);
+  Application.Run;
+end.
diff --git a/songmanagement/tools/ScoreConverter/ScoreConverter.ico b/songmanagement/tools/ScoreConverter/ScoreConverter.ico
new file mode 100644
index 00000000..80319014
Binary files /dev/null and b/songmanagement/tools/ScoreConverter/ScoreConverter.ico differ
diff --git a/songmanagement/tools/ScoreConverter/ScoreConverter.res b/songmanagement/tools/ScoreConverter/ScoreConverter.res
new file mode 100644
index 00000000..2d3bea87
Binary files /dev/null and b/songmanagement/tools/ScoreConverter/ScoreConverter.res differ
diff --git a/songmanagement/tools/ScoreConverter/UScores.pas b/songmanagement/tools/ScoreConverter/UScores.pas
new file mode 100644
index 00000000..801d796e
--- /dev/null
+++ b/songmanagement/tools/ScoreConverter/UScores.pas
@@ -0,0 +1,102 @@
+unit UScores;
+
+interface
+
+uses USongs;
+
+procedure ReadScore(var Song: TSong);
+procedure WriteScore(var Song: TSong);
+procedure AddScore(var Song: TSong; Level: integer; Name: string; Score: integer);
+
+implementation
+
+uses IniFiles, SysUtils;
+
+procedure ReadScore(var Song: TSong);
+var
+  F:    TIniFile;
+  S:    string;
+  P:    integer;
+  Lev:  integer;
+  LevS: string;
+begin
+  F := TIniFile.Create(Song.Path + ChangeFileExt(Song.FileName, '.sco'));
+
+  for Lev := 0 to 2 do begin
+    case Lev of
+      0:  LevS := 'Easy';
+      1:  LevS := 'Normal';
+      2:  LevS := 'Hard';
+    end;
+
+    P := 1;
+    S := F.ReadString(LevS + IntToStr(P), 'Name', '');
+    while (S <> '') and (P<=5) do begin
+      SetLength(Song.Score[Lev], P);
+      Song.Score[Lev, P-1].Name := S;
+      Song.Score[Lev, P-1].Score := F.ReadInteger(LevS + IntToStr(P), 'Score', 0);
+
+      Inc(P);
+      S := F.ReadString(LevS + IntToStr(P), 'Name', '');
+    end;
+  end;
+end;
+
+procedure AddScore(var Song: TSong; Level: integer; Name: string; Score: integer);
+var
+  S:    integer;
+  S2:   integer;
+begin
+  S := 0;
+  while (S <= High(Song.Score[Level])) and (Score <= Song.Score[Level, S].Score) do
+    Inc(S);
+  // S has the number for new score
+
+
+  // we create new score
+  SetLength(Song.Score[Level], Length(Song.Score[Level]) + 1);
+
+  // we move down old scores
+  for S2 := High(Song.Score[Level])-1 downto S do
+    Song.Score[Level, S2+1] := Song.Score[Level, S2];
+
+  // we fill new score
+  Song.Score[Level, S].Name := Name;
+  Song.Score[Level, S].Score := Score;
+
+  if Length(Song.Score[Level]) > 5 then begin
+    SetLength(Song.Score[Level], 5);
+  end;
+end;
+
+procedure WriteScore(var Song: TSong);
+var
+  F:    TIniFile;
+  S:    integer;
+  Lev:      integer;
+  LevS:     string;
+  FileName: string;
+begin
+  FileName := Song.Path + ChangeFileExt(Song.FileName, '.sco');
+  if (not FileExists(FileName)) or (FileExists(FileName) and  DeleteFile(FileName)) then begin
+    // file has been deleted -> creating new file
+    F := TIniFile.Create(FileName);
+
+    for Lev := 0 to 2 do begin
+      case Lev of
+        0:  LevS := 'Easy';
+        1:  LevS := 'Normal';
+        2:  LevS := 'Hard';
+      end;
+
+      for S := 0 to high(Song.Score[Lev]) do begin
+        F.WriteString(LevS + IntToStr(S+1), 'Name', Song.Score[Lev, S].Name);
+        F.WriteInteger(LevS + IntToStr(S+1), 'Score', Song.Score[Lev, S].Score);
+
+      end; // for S
+    end; // for Lev
+    F.Free;
+  end; // if
+end;
+
+end.
diff --git a/songmanagement/tools/ScoreConverter/USongs.pas b/songmanagement/tools/ScoreConverter/USongs.pas
new file mode 100644
index 00000000..8f20f44f
--- /dev/null
+++ b/songmanagement/tools/ScoreConverter/USongs.pas
@@ -0,0 +1,160 @@
+unit USongs;
+
+interface
+
+type
+  TScore = record
+    Name:       string;
+    Score:      integer;
+    Length:     string;
+  end;
+  
+  TSong = record
+    Path:       string;
+    FileName:   string;
+
+    Title:      string;
+    Artist:     string;
+
+    Score:      array[0..2] of array of TScore;
+  end;
+
+  TSongs = class
+    LastCount: Integer;
+    Song:       array of TSong; // array of songs
+
+    function  ReadHeader(var rSong: TSong): boolean;
+    procedure BrowseDir(Dir: string); // Browse a dir + subdirs for songfiles
+  end;
+
+  var Songs: TSongs;
+
+implementation
+uses Sysutils, UMainForm, Dialogs;
+
+function TSongs.ReadHeader(var rSong: TSong): boolean;
+var
+  Line, Identifier, Value: String;
+  Temp: word;
+  Done: byte;
+  SongFile: Textfile;
+begin
+  Result := False;
+
+
+  //Open File and set File Pointer to the beginning
+  AssignFile(SongFile, rSong.Path + rSong.FileName);
+  Reset(SongFile);
+
+  //Read Header
+  Result := true;
+
+  //Read first Line
+  ReadLn (SongFile, Line);
+
+  if (Length(Line)<=0) then
+  begin
+    Result := False;
+    Exit;
+  end;
+  Done := 0;
+  //Read Lines while Line starts with #
+  While (Line[1] = '#') do
+  begin
+    Temp := Pos(':', Line);
+
+    //Line has a Seperator-> Headerline
+    if (Temp <> 0) then
+    begin
+      //Read Identifier and Value
+      Identifier  := Uppercase(Trim(Copy(Line, 2, Temp - 2))); //Uppercase is for Case Insensitive Checks
+      Value       := Trim(Copy(Line, Temp + 1,Length(Line) - Temp));
+
+      //Check the Identifier (If Value is given)
+      if (Length(Value) <> 0) then
+      begin
+
+        //-----------
+        //Required Attributes
+        //-----------
+
+        //Title
+        if (Identifier = 'TITLE') then
+        begin
+          rSong.Title := Value;
+
+          //Add Title Flag to Done
+          Done := Done or 1;
+        end
+
+        //Artist
+        else if (Identifier = 'ARTIST') then
+        begin
+          rSong.Artist := Value;
+
+          //Add Artist Flag to Done
+          Done := Done or 2;
+        end;
+
+      end;
+    end;
+
+    if not EOf(SongFile) then
+      ReadLn (SongFile, Line)
+    else
+    begin
+      Result := False;
+      break;
+    end;
+
+    //End on first empty Line
+    if (Length(Line) = 0) then
+      break;
+  end;
+
+  //Check if all Required Values are given
+  if (Done <> 3) then
+  begin
+    Result := False;
+  end;
+
+  //And Close File
+  CloseFile(SongFile);
+end;
+
+procedure TSongs.BrowseDir(Dir: string);
+var
+  SR:     TSearchRec;   // for parsing Songs Directory
+  SLen:   integer;
+begin
+  if FindFirst(Dir + '*', faDirectory, SR) = 0 then begin
+    repeat
+      if (SR.Name <> '.') and (SR.Name <> '..') then
+        BrowseDir(Dir + Sr.Name + '\');
+    until FindNext(SR) <> 0;
+  end;
+  FindClose(SR);
+
+ if FindFirst(Dir + '*.txt', 0, SR) = 0 then begin
+    repeat
+      SLen := Length(Song);
+      SetLength(Song, SLen + 1);
+
+      Song[SLen].Path := Dir;
+      Song[SLen].FileName := SR.Name;
+
+      if (ReadHeader(Song[SLen]) = false) then SetLength(Song, SLen);
+
+      //update Songs Label
+      if LastCount <> SLen div 30 then
+      begin
+        LastCount := SLen div 30;
+        MainForm.UpdateLoadedSongs(Dir, SLen);
+      end;
+
+    until FindNext(SR) <> 0;
+    end; // if FindFirst
+  FindClose(SR);
+end;
+
+end.
diff --git a/songmanagement/tools/ScoreConverter/Umainform.dfm b/songmanagement/tools/ScoreConverter/Umainform.dfm
new file mode 100644
index 00000000..a4291e7b
--- /dev/null
+++ b/songmanagement/tools/ScoreConverter/Umainform.dfm
@@ -0,0 +1,123 @@
+object mainform: Tmainform
+  Left = 328
+  Top = 228
+  HorzScrollBar.Visible = False
+  VertScrollBar.Visible = False
+  BorderIcons = [biSystemMenu, biMinimize]
+  BorderStyle = bsSingle
+  Caption = 'Ultrastar Deluxe Score Converter'
+  ClientHeight = 159
+  ClientWidth = 449
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'MS Sans Serif'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poDesktopCenter
+  OnCreate = FormCreate
+  PixelsPerInch = 96
+  TextHeight = 13
+  object Label1: TLabel
+    Left = 8
+    Top = 8
+    Width = 60
+    Height = 13
+    Caption = 'SongFolder: '
+  end
+  object lFolder: TLabel
+    Left = 8
+    Top = 24
+    Width = 29
+    Height = 13
+    Caption = 'Folder'
+  end
+  object Label2: TLabel
+    Left = 8
+    Top = 48
+    Width = 49
+    Height = 13
+    Caption = 'Database:'
+  end
+  object lDatabase: TLabel
+    Left = 8
+    Top = 64
+    Width = 46
+    Height = 13
+    Caption = 'Database'
+  end
+  object lDatabase2: TLabel
+    Left = 72
+    Top = 48
+    Width = 54
+    Height = 13
+    Caption = 'lDatabase2'
+  end
+  object lFolder2: TLabel
+    Left = 72
+    Top = 8
+    Width = 37
+    Height = 13
+    Caption = 'lFolder2'
+  end
+  object lStatus: TLabel
+    Left = 0
+    Top = 96
+    Width = 449
+    Height = 13
+    Alignment = taCenter
+    AutoSize = False
+    Caption = 'lStatus'
+  end
+  object bFLoad: TButton
+    Left = 176
+    Top = 8
+    Width = 57
+    Height = 17
+    Caption = 'Load'
+    TabOrder = 0
+    OnClick = bFLoadClick
+  end
+  object bDLoad: TButton
+    Left = 176
+    Top = 48
+    Width = 57
+    Height = 17
+    Caption = 'Load'
+    TabOrder = 1
+    OnClick = bDLoadClick
+  end
+  object bToDB: TButton
+    Left = 16
+    Top = 112
+    Width = 153
+    Height = 17
+    Caption = 'Convert *.SCO to Database'
+    Enabled = False
+    TabOrder = 2
+    OnClick = bToDBClick
+  end
+  object bFromDB: TButton
+    Left = 288
+    Top = 112
+    Width = 145
+    Height = 17
+    Caption = 'Convert Database to *.SCO'
+    Enabled = False
+    TabOrder = 3
+    OnClick = bFromDBClick
+  end
+  object pProgress: TProgressBar
+    Left = 8
+    Top = 136
+    Width = 433
+    Height = 17
+    TabOrder = 4
+  end
+  object oDatabase: TOpenDialog
+    Filter = 'Ultrastar Deluxe Database|ultrastar.db'
+    Left = 136
+    Top = 48
+  end
+end
diff --git a/songmanagement/tools/ScoreConverter/Umainform.pas b/songmanagement/tools/ScoreConverter/Umainform.pas
new file mode 100644
index 00000000..647cf3a4
--- /dev/null
+++ b/songmanagement/tools/ScoreConverter/Umainform.pas
@@ -0,0 +1,230 @@
+unit Umainform;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, ComCtrls, UDataBase, ShellAPI, ShlObj, USongs;
+
+type
+  Tmainform = class(TForm)
+    Label1: TLabel;
+    lFolder: TLabel;
+    bFLoad: TButton;
+    Label2: TLabel;
+    lDatabase: TLabel;
+    bDLoad: TButton;
+    lDatabase2: TLabel;
+    lFolder2: TLabel;
+    bToDB: TButton;
+    bFromDB: TButton;
+    pProgress: TProgressBar;
+    oDatabase: TOpenDialog;
+    lStatus: TLabel;
+    procedure FormCreate(Sender: TObject);
+    procedure bDLoadClick(Sender: TObject);
+    function BrowseDialog (const Title: string; const Flag: integer): string;
+    procedure bFLoadClick(Sender: TObject);
+    procedure UpdateLoadedSongs(Path: String; Count: integer);
+    procedure bToDBClick(Sender: TObject);
+    procedure bFromDBClick(Sender: TObject);
+  private
+    { Private-Deklarationen }
+  public
+    { Public-Deklarationen }
+  end;
+
+var
+  mainform: Tmainform;
+  DBLoaded: Boolean;
+  SFLoaded: Boolean;
+
+
+implementation
+
+uses UScores;
+
+{$R *.dfm}
+
+function Tmainform.BrowseDialog
+ (const Title: string; const Flag: integer): string;
+var
+  lpItemID : PItemIDList;
+  BrowseInfo : TBrowseInfo;
+  DisplayName : array[0..MAX_PATH] of char;
+  TempPath : array[0..MAX_PATH] of char;
+begin
+  Result:='';
+  FillChar(BrowseInfo, sizeof(TBrowseInfo), #0);
+  with BrowseInfo do begin
+    hwndOwner := Application.Handle;
+    pszDisplayName := @DisplayName;
+    lpszTitle := PChar(Title);
+    ulFlags := Flag;
+  end;
+  lpItemID := SHBrowseForFolder(BrowseInfo);
+  if lpItemId <> nil then begin
+    SHGetPathFromIDList(lpItemID, TempPath);
+    Result := TempPath;
+    GlobalFreePtr(lpItemID);
+  end;
+end;
+
+procedure Tmainform.FormCreate(Sender: TObject);
+begin
+  Database := TDataBaseSystem.Create;
+  Songs := TSongs.Create;
+  lStatus.Caption := 'Welcome to USD Score Converter';
+  lFolder2.Caption := 'No Songs loaded';
+  lFolder.Caption := '';
+  lDataBase2.Caption := 'No Database loaded';
+  lDataBase.Caption := '';
+end;
+
+procedure Tmainform.bDLoadClick(Sender: TObject);
+begin
+  if oDatabase.Execute then
+  begin
+    try
+      Database.Init(oDataBase.FileName);
+      lDataBase2.Caption := 'Database loaded';
+      lDataBase.Caption := oDataBase.FileName;
+      DBLoaded := True;
+    except
+      lDataBase2.Caption := 'No Database loaded';
+      lDataBase.Caption := '';
+      DBLoaded := False;
+    end;
+  end;
+  bToDB.Enabled := DBLoaded and SFLoaded;
+  bFromDB.Enabled := bToDB.Enabled;
+end;
+
+procedure Tmainform.bFLoadClick(Sender: TObject);
+var
+  Path: String;
+begin
+  Path := BrowseDialog('Select UltraStar SongFolder', BIF_RETURNONLYFSDIRS);
+
+  if Path <> '' then
+  begin
+    SetLength(Songs.Song, 0);
+    try
+      Songs.BrowseDir(Path + '\');
+      lFolder2.Caption := Inttostr(Length(Songs.Song)) + ' Songs loaded';
+      lFolder.Caption := Path;
+      SFLoaded := True;
+    except
+      lFolder2.Caption := 'No Songs loaded';
+      lFolder.Caption := '';
+      SFLoaded := False;
+    end;
+  end;
+
+  bToDB.Enabled := DBLoaded and SFLoaded;
+  bFromDB.Enabled := bToDB.Enabled;
+end;
+
+procedure Tmainform.UpdateLoadedSongs(Path: String; Count: integer);
+begin
+  lFolder2.Caption := Inttostr(Count) + ' Songs loaded';
+  lFolder.Caption := Path;
+  Application.ProcessMessages;
+end;
+
+procedure Tmainform.bToDBClick(Sender: TObject);
+var
+  I, J, K: Integer;
+  LastI: integer;
+begin
+  if (Messagebox(0, PChar('If the same directory is added more than one time the Score-File will be useless. Cont�nue ?'), PChar(Mainform.Caption), MB_ICONWARNING or MB_YESNO) = IDYes) then
+  begin
+    pProgress.Max := high(Songs.Song);
+    pProgress.Position := 0;
+    // Go through all Songs
+    For I := 0 to high(Songs.Song) do
+    begin
+      try
+        //Read Scores from .SCO File
+        ReadScore (Songs.Song[I]);
+
+        //Go from Easy to Difficult
+        For J := 0 to 2 do
+        begin
+          //Go through all Score Entrys with Difficulty J
+          For K := 0 to high(Songs.Song[I].Score[J]) do
+          begin
+            //Add to DataBase
+            DataBase.AddScore(Songs.Song[I], J, Songs.Song[I].Score[J][K].Name, Songs.Song[I].Score[J][K].Score);
+          end;
+        end;
+
+      except
+        showmessage ('Error Converting Score From Song: ' + Songs.Song[I].Path  + Songs.Song[I].FileName);
+      end;
+
+      //Update ProgressBar
+      J := I div 30;
+      if (LastI <> J) then
+      begin
+        LastI := J;
+        pProgress.Position := I;
+        lStatus.Caption := 'Adding Songscore: ' + Songs.Song[I].Artist + ' - ' + Songs.Song[I].Title;
+        Application.ProcessMessages;
+      end;
+    end;
+
+    pProgress.Position := pProgress.Max;
+    lStatus.Caption := 'Finished';
+  end;
+end;
+
+procedure Tmainform.bFromDBClick(Sender: TObject);
+var
+  I, J: Integer;
+  LastI: integer;
+  anyScoreinthere: boolean;
+begin
+  if (Messagebox(0, PChar('All Score Entrys in the Song Directory having an equivalent will be Overwritten. Cont�nue ?'), PChar(Mainform.Caption), MB_ICONWARNING or MB_YESNO) = IDYes) then
+  begin
+    pProgress.Max := high(Songs.Song);
+    pProgress.Position := 0;
+    // Go through all Songs
+    For I := 0 to high(Songs.Song) do
+    begin
+      try
+        //Not Write ScoreFile when there are no Scores for this File
+        anyScoreinthere := false;
+        //Read Scores from DB File
+        Database.ReadScore (Songs.Song[I]);
+
+        //Go from Easy to Difficult
+        For J := 0 to 2 do
+        begin
+          anyScoreinthere := anyScoreinthere or (Length(Songs.Song[I].Score[J]) > 0);
+        end;
+
+        if AnyScoreinThere then
+          WriteScore(Songs.Song[I]);
+
+      except
+        showmessage ('Error Converting Score From Song: ' + Songs.Song[I].Path  + Songs.Song[I].FileName);
+      end;
+
+      //Update ProgressBar
+      J := I div 30;
+      if (LastI <> J) then
+      begin
+        LastI := J;
+        pProgress.Position := I;
+        lStatus.Caption := 'Writing ScoreFile: ' + Songs.Song[I].Artist + ' - ' + Songs.Song[I].Title;
+        Application.ProcessMessages;
+      end;
+    end;
+    
+    pProgress.Position := pProgress.Max;
+    lStatus.Caption := 'Finished';
+  end;
+end;
+
+end.
-- 
cgit v1.2.3